# YARA API — Manage YARA Rulesets on Spectra Analyze

> Manage YARA rulesets on Spectra Analyze: list, create, update, and delete rulesets. GET/POST/DELETE /api/yara/v2/rulesets/ endpoints.

## Retrieve a list of YARA rulesets on the appliance

```
GET /api/yara/v2/rulesets/
```

Retrieve a list of YARA rulesets that are on the Spectra Analyze appliance. The list can be filtered by several criteria (ruleset status, source, and owner) using optional parameters.

For every ruleset in the list, the output includes additional information such as: ruleset name, total number of matches, last matched date, and more.

If the optional `type` parameter is not provided in the request, the response includes only the default ruleset type (“my”, meaning the rulesets owned by the user sending the request). By default, Spectra Core rulesets are not included in the response.

### Request Format

**Request Parameters**

| NAME      | REQUIRED | DESCRIPTION                                                  | TYPE          |
| :-------- | :------- | :----------------------------------------------------------- | :------------ |
| type      | Optional | Filter YARA rulesets on the appliance by their owner. When this parameter is provided in the request, only the rulesets matching the specified type are returned in the response. Supported values: `my` (default - currently authenticated user), `user`, `system`, `all` | query, string |
| status    | Optional | Filter YARA rulesets on the appliance by their status. When this parameter is provided in the request, only the rulesets matching the specified status are returned in the response. Supported values: `all` (default), `error`, `active`, `disabled`, `pending`, `invalid`, `capped` | query, string |
| source    | Optional | Filter YARA rulesets on the appliance by their source. When this parameter is provided in the request, only the rulesets matching the specified source are returned in the response. Supported values: `all` (default), `local`, `cloud` | query, string |
| page      | Optional | Optional parameter used for pagination. When this parameter is omitted from the request, all available results are returned at once. **This parameter cannot be used without** `page_size`. Use `page_size` to set how many results should be on each page, and then specify which page to return with `page` in the same request. The `count` value in the response indicates the total number of results. Use this number as guidance for pagination. The values of `page size` and `page` multiplied must not exceed the `count` value. For example, if `count` is 80 and `page_size` is set to 10, it is not possible to request `page=9`. | query, string |
| page_size | Optional | Optional parameter that controls how many results to return per page in the response. **This parameter cannot be used without** `page`. When this parameter is omitted from the request, all available results are returned at once. | query, string |

**Request Examples**

**cURL**

```bash
# Add --insecure before the URL if you are using a self-signed SSL certificate
curl -X GET 'https://appliance.example.com/api/yara/v2/rulesets/' \
  --header 'Authorization: Token exampletoken'
```

**cURL with pagination**

```bash
# Add --insecure before the URL if you are using a self-signed SSL certificate
curl -X GET 'https://a1000.example.com/api/yara/v2/rulesets/?page_size=10&page=2' \
  --header 'Authorization: Token exampletoken'
```

**Python**

```python

# Change the values of token and hash_value
token = "exampletoken"
hash_value = "examplehash"
# Change the host name in the URL and the fields to be included in the response
url = f"https://appliance.example.com/api/yara/v2/rulesets/"

headers = {
    "Authorization": f"Token {token}"
}

# Add verify=False in the request if you are using a self-signed SSL certificate
response = requests.get(url, headers=headers)
print(response.text)
```

### Response Format

**Response Examples**

```json
{
  "count": <total result count number>,
  "next": "http://192.168.1.101/api/yara/rulesets/?type=<type>&status=<status>&source=<source>&page=<next page number>&page_size=<page size number>",
  "results": [{
      "status": "active",
      "suspicious_match_count": 10,
      "goodware_match_count": 1,
      "cloud_synced": False,
      "malicious_match_count": 100,
      "name": 'ruleset name",
      "owner": "user name",
      "last_matched": "2017-03-14T11:19:31.978544Z",
      "system_ruleset": False,
      "unknown_match_count": 0
  },
  ...
  ]
}
```

**Response Status Codes**

| CODE | DESCRIPTION                     |
| :--- | :------------------------------ |
| 200  | OK                              |
| 400  | Parameter not in expected range |
| 401  | Unauthorized                    |

## Retrieve the contents of a YARA ruleset

```
GET /api/yara/ruleset/content/?name={ruleset_name}
```

Retrieve the full contents of the requested ruleset in raw text/plain format. All rulesets can be retrieved, regardless of their current status on the appliance (enabled, disabled…).

### Request Format

**Request Parameters**

| NAME | REQUIRED | DESCRIPTION                                                  | TYPE          |
| :--- | :------- | :----------------------------------------------------------- | :------------ |
| name | Required | Name of the YARA ruleset to retrieve. Ruleset names are case-sensitive. | query, string |

**Request Examples**

**cURL**

```bash
# Add --insecure before the URL if you are using a self-signed SSL certificate
curl -X GET 'https://appliance.example.com/api/yara/ruleset/content/?name=example_ruleset' \
  --header 'Authorization: Token exampletoken'
```

**Python**

```python

# Change the values of token and hash_value
token = "exampletoken"
hash_value = "examplehash"
# Change the host name in the URL and the fields to be included in the response
url = f"https://appliance.example.com/api/yara/ruleset/content/?name=example_ruleset"

headers = {
    "Authorization": f"Token {token}"
}

# Add verify=False in the request if you are using a self-signed SSL certificate
response = requests.get(url, headers=headers)
print(response.text)
```

### Response Format

**Response Example**

```
{
  "code": 200,
  "detail":{
      "name":"ruleset_name"
      "content":"import \"pe\"\n\nrule TestYaraRule : malicious\n{\n    ... \n        \n}",
  }
}
```

**Response Status Codes**

| CODE | DESCRIPTION                               |
| :--- | :---------------------------------------- |
| 200  | OK                                        |
| 400  | Missing or invalid ruleset name parameter |
| 404  | Ruleset not found                         |

## Retrieve YARA matches for specified rulesets

```
GET /api/yara/v2/ruleset/matches/?name={ruleset_name}
```

Retrieve the list of YARA matches (both local and cloud) for requested rulesets. If multiple rulesets are provided in the request, only the samples that match all requested rulesets are listed in the response.

The *cloud* field in the response indicates whether the match happened locally (returns “false”) or in the Spectra Intelligence cloud (returns “true”). The same sample can return different values for the *cloud* field, if that sample is found on the Spectra Analyze instance and in the cloud. **Known issue**: if the sample is not found locally but only in the cloud, the `extracted_file_count` and `sha256` fields contain `null`.

If the requested rulesets don’t have any matches, an empty response is returned.

### Request Format

**Request Parameters**

| NAME      | REQUIRED | DESCRIPTION                                                  | TYPE          |
| :-------- | :------- | :----------------------------------------------------------- | :------------ |
| name      | Required | Name of the YARA ruleset for which to retrieve matches. At least one value must be provided in the request. Ruleset names are case-sensitive. If multiple ruleset names are provided in the request, only the samples that match all requested rulesets are listed in the response. When providing multiple ruleset names, they should be serialized as form-style query expansion (example: `/?name=ruleset1&name=ruleset2&name=...`). | query, string |
| page      | Optional | Optional parameter used for pagination. When this parameter is omitted from the request, all available results are returned at once. **This parameter cannot be used without** `page_size`. Use `page_size` to set how many results should be on each page, and then specify which page to return with `page` in the same request. The `count` value in the response indicates the total number of results. Use this number as guidance for pagination. The values of `page size` and `page` multiplied must not exceed the `count` value. For example, if `count` is 80 and `page_size` is set to 10, it is not possible to request `page=9`. | query, string |
| page_size | Optional | Optional parameter that controls how many results to return per page in the response. **This parameter cannot be used without** `page`. When this parameter is omitted from the request, all available results are returned at once. | query, string |

**Request Examples**

**cURL**

```bash
# Add --insecure before the URL if you are using a self-signed SSL certificate
curl -X GET 'https://appliance.example.com/api/yara/v2/ruleset/matches/?name=example_ruleset' \
  --header 'Authorization: Token exampletoken'
```

**Python**

```python

# Change the values of token and hash_value
token = "exampletoken"
hash_value = "examplehash"
# Change the host name in the URL and the fields to be included in the response
url = f"https://appliance.example.com/api/yara/v2/ruleset/matches/?name=example_ruleset"

headers = {
    "Authorization": f"Token {token}"
}

# Add verify=False in the request if you are using a self-signed SSL certificate
response = requests.get(url, headers=headers)
print(response.text)
```

### Response Format

**Response Examples**

```json
{
  "count": <total result count number>,
  "next": "http://192.168.1.101/api/yara/ruleset/matches/?name=<ruleset name>&page=<next page number>&page_size=<page size number>",
  "results": [{
      "classification": 3,
      "sha1": "4e43fa0f1c715ea704102a9a4f59bfe0520419b8",
      "sha256": "250c3b6198639bead80aee27825cd9aadf774f747a392e7c30984cf78277c422",
      "created": "2017-03-14T11:19:31.978544Z",
      "file_type": "PE/Exe",
      "extracted_file_count": 60,
      "rule": "test",
      "filename": "4e43fa0f1c715ea704102a9a4f59bfe0520419b8",
      "classification_result": "Win32.Trojan.Injector",
      "downloadable": true,
      "file_size": 608768,
      "riskscore": 10,
      "cloud": false,
      "md5": "6867a9aaa3666c511163ee4fe513f038"
  },
  ...
  ]
}
```

**Response Status Codes**

| CODE | DESCRIPTION                               |
| :--- | :---------------------------------------- |
| 200  | OK                                        |
| 400  | Missing or invalid ruleset name parameter |
| 404  | Ruleset not found                         |

## Create or update a YARA ruleset

```
POST /api/yara/ruleset/
```

Creates a new YARA ruleset if it doesn’t exist. If a ruleset with the specified name already exists, a new revision (update) of the ruleset is created. Spectra Core rulesets cannot be modified with this API.

Pass the entire ruleset as **form data** under `content`. The content type is `application/x-www-form-urlencoded`.

**Restrictions**

1. YARA ruleset names on Spectra Analyze are case-sensitive and character-limited. When naming rulesets, keep the name between 3 and 48 characters. Generally, the underscore ( _ ) should be used instead of spaces, and any other special characters should be avoided. It is recommended to only use numbers (0-9) and a-z/A-Z letters in YARA ruleset names.
2. Rulesets larger than 1 MB (1048576 bytes) can be created and used on the appliance, but they cannot be saved and executed in the Spectra Intelligence cloud.
3. YARA rulesets on Spectra Analyze are not applied to files larger than 700 MB.

### Request Format

**Request Parameters**

| FIELD   | REQUIRED | DATA TYPE | DESCRIPTION                                                  | PARAMETER TYPE |
| :------ | :------- | :-------- | :----------------------------------------------------------- | :------------- |
| name    | required | string    | Name of the ruleset to create or update.                     | form           |
| content | required | string    | Content of the YARA ruleset to create or update.             | form           |
| publish | optional | string    | Determines whether the ruleset should be synchronized to other appliances in the same [Spectra Detect](/SpectraDetect/) Manager cluster. Usable only with administrator tokens if the Spectra Analyze is configured to allow only users with the appropriate user roles to synchronize YARA actions. Requires YARA synchronization to be enabled on the Spectra Analyze appliance. | form           |
| ticloud | optional | bool      | Determines whether the ruleset should be synchronized with Spectra Intelligence or not. The value can be true or false; default is false. This parameter is equivalent to the *Run ruleset continuously in Spectra Intelligence* option in the graphical Spectra Analyze YARA editor. | form           |

**Request Examples**

**cURL**

```bash
# Add --insecure before the URL if you are using a self-signed SSL certificate
curl -X POST 'https://appliance.example.com/api/yara/ruleset/' \
--header 'Authorization: Token exampletoken' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'name=example_ruleset' \
--data-urlencode 'content=rule example_rule {condition:false}'
```

**Python**

```python

# Change the token
token = "exampletoken"
# Change the host name in the URL
url = "https://appliance.example.com/api/yara/ruleset/"

payload='name=example_ruleset&content=rule example_rule {condition: false}'
headers = {
  'Authorization': f'Token {token}',
  'Content-Type': 'application/x-www-form-urlencoded'
}

# Add verify=False in the request if you are using a self-signed SSL certificate
response = requests.post(url, headers=headers, data=payload)

print(response.text)
```

### Response Format

**Response Example**

```json
{
  "code": 200,
  "message": "Ruleset updated/created successfully."
  "detail": {
      "name": "ruleset_name"
  }
}
```

**Response Status Codes**

| CODE | DESCRIPTION                                                  |
| :--- | :----------------------------------------------------------- |
| 200  | OK                                                           |
| 400  | Parameter not in expected range                              |
| 401  | “Core ruleset cannot be updated” for Spectra Core rulesets.  |
| 403  | This response is returned when the request isn’t authenticated. Possible cause is that the publish parameter was provided, but the token doesn’t have permission. |
| 409  | Rulesets cannot be updated while their Spectra Intelligence validation is pending, or while a Cloud Retro hunt is running. |
| 500  | Error while creating or updating ruleset. Ruleset saved successfully, but due to errors the system cannot run it. |

## Delete a YARA ruleset and its matches from the appliance

``DELETE /api/yara/ruleset/``

Delete the specified YARA ruleset and its matches from the appliance. Spectra Core rulesets cannot be deleted.

Only users with the appropriate user roles can delete rulesets created by other users.

### Request Format

**Request Parameters**

|         | REQUIRED | DATA TYPE | DESCRIPTION                                                  | PARAMETER TYPE |
| :------ | :------- | :-------- | :----------------------------------------------------------- | :------------- |
| name    | required | string    | Name of the ruleset to delete. Ruleset names are case-sensitive. | form           |
| publish | optional | string    | Determines whether the ruleset deletion should be synchronized to other appliances in the same Spectra Detect Manager cluster, if the appliance is configured to allow only users with the appropriate user roles to synchronize YARA actions. Requires YARA synchronization to be enabled on the appliance, as well as on the connected Spectra Detect Manager. Usable only with administrator tokens. | form           |

**Request Examples**

**cURL**

```bash
# Add --insecure before the URL if you're using a self-signed SSL certificate
curl -X DELETE 'https://appliance.example.com/api/yara/ruleset/' \
--header 'Authorization: Token exampletoken' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'name=example_ruleset'
```

**Python**

```python

# Change the token
token = "exampletoken"
# Change the host name in the URL
url = "https://appliance.example.com/api/yara/ruleset/"

payload='name=example_ruleset'
headers = {
  'Authorization': f'Token {token}',
  'Content-Type': 'application/x-www-form-urlencoded'
}

# Add verify=False in the request if you are using a self-signed SSL certificate
response = requests.delete(url, headers=headers, data=payload)

print(response.text)
```

### Response Format

**Response Example**

```json
{
    "core": 200
    "message": "Ruleset deleted successfully.",
    "detail":{
        "name": "example_ruleset"
    }
}
```

**Response Status Codes**

| CODE | DESCRIPTION                                                  |
| :--- | :----------------------------------------------------------- |
| 200  | OK                                                           |
| 400  | Missing or invalid ruleset name parameter                    |
| 401  | Unauthorized action; ruleset is a Spectra Core ruleset or was created by another user |
| 403  | This response is returned when the request isn’t authenticated. Possible cause is that the publish parameter was provided, but the token doesn’t have permission. |
| 404  | Ruleset not found                                            |
| 500  | Error occurred while deleting ruleset                        |

## Enable/Disable a YARA ruleset

```
POST /api/yara/ruleset/{enable | disable}/
```

Enables a previously disabled YARA ruleset, or disables a currently enabled YARA ruleset.

Administrators can enable/disable any ruleset on the appliance via this endpoint. Regular Spectra Analyze users can only enable/disable their own rulesets.

### Request Format

**Request Parameters**

| FIELD          | REQUIRED | DATA TYPE | DESCRIPTION                                                  | PARAMETER TYPE |
| :------------- | :------- | :-------- | :----------------------------------------------------------- | :------------- |
| enable/disable | required | string    | Whether to enable or disable the specified ruleset.          | path           |
| name           | required | string    | Name of the ruleset to enable/disable. Ruleset names are case-sensitive. | form           |
| publish        | optional | string    | Determines whether the ruleset action should be synchronized to other appliances in the same Spectra Detect Manager cluster. Usable only with administrator tokens if the appliance is configured to allow only users with the appropriate user roles to synchronize YARA actions. Requires YARA synchronization to be enabled on the appliance, as well as on the connected Spectra Detect Manager. | form           |

The URL must end with a forward slash (`/`).

**Request Examples**

**cURL**

```bash
# Add --insecure before the URL if you're using a self-signed SSL certificate
curl -X POST 'https://appliance.example.com/api/yara/ruleset/disable/' \
--header 'Authorization: Token exampletoken' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'name=example_ruleset'
```

**Python**

```python

# Change the token
token = "exampletoken"
# Change the host name in the URL
url = "https://appliance.example.com/api/yara/ruleset/disable/"

payload = 'name=example_ruleset'
headers = {
  'Authorization': f'Token {token}',
  'Content-Type': 'application/x-www-form-urlencoded'
}

# Add verify=False in the request if you are using a self-signed SSL certificate
response = requests.post(url, headers=headers, data=payload)

print(response.text)
```

### Response Format

**Response Examples**

```
{
  "code": 200,
  "message": "Ruleset enabled successfully."
  "detail": {
      "name: "ruleset name"
  }
}

{
  "code": 200,
  "message": "Ruleset disabled successfully."
  "detail": {
      "name": "ruleset name"
  }
}
```

**Response Status Codes**

| CODE             | DESCRIPTION                                                  |
| :--------------- | :----------------------------------------------------------- |
| 200              | In case the user also provides the publish parameter, but doesn’t have permissions due to appliance configuration, this response will contain the “Publish requests with non-admin token - not published” error message. |
| 400              | Missing or malformed name parameter                          |
| 401 Unauthorized | “Ruleset cannot be enabled/disabled. It is created by another user.” or “Core ruleset cannot be enabled/disabled” for Spectra Core rulesets. The first reason does not apply to administrators. |
| 404              | Ruleset with that name does not exist                        |
| 500              | Error occurred while enabling/disabling ruleset              |

## Get YARA ruleset synchronization time

```
GET /api/yara/ticloud/time/
```

Provides information about the current synchronization status for Spectra Intelligence-enabled rulesets. There are no required parameters for this endpoint.

The URL must end with a forward slash (`/`).

**Request Examples**

**cURL**

```bash
# Add --insecure before the URL if you're using a self-signed SSL certificate
curl -X GET 'https://appliance.example.com/api/yara/ticloud/time/' \
--header 'Authorization: Token exampletoken'
```

**Python**

```python

# Change the token
token = "exampletoken"
# Change the host name in the URL
url = "https://appliance.example.com/api/yara/ticloud/time/"

headers = {
  'Authorization': f'Token {token}',
}

# Add verify=False in the request if you are using a self-signed SSL certificate
response = requests.get(url, headers=headers)

print(response.text)
```

**Response Example**

```json
{
  "code": 200,
  "message": "TiCloud matches are syncing from 2017-03-14T11:19:31.978544Z"
  "detail": {
      "time": "2017-03-14T11:19:31.978544Z"
  }
}
```

**Response Status Codes**

| CODE | DESCRIPTION                                                  |
| :--- | :----------------------------------------------------------- |
| 200  | OK                                                           |
| 403  | This response is returned when the request isn’t authenticated. |
| 405  | YARA Spectra Intelligence synchronization is currently not enabled. |

## Set YARA ruleset synchronization time

```
POST /api/yara/ticloud/time/
```

Allows modifying the Spectra Intelligence synchronization time for Spectra Intelligence-enabled YARA rulesets.

The **time** parameter can be supplied either as a query string or in the JSON request payload. The time format should be UTC (YYYY-MM-DD hh:mm:ss) or Unix epoch time as the number of seconds since 1970-01-01.

The URL must end with a forward slash (`/`).

### Request Format

**Request Parameters**

| FIELD | REQUIRED | DATA TYPE | DESCRIPTION                                                  | PARAMETER TYPE |
| :---- | :------- | :-------- | :----------------------------------------------------------- | :------------- |
| time  | required | string    | Sets the date and time for YARA Spectra Intelligence synchronization. Format should be UTC (YYYY-MM-DD hh:mm:ss) or Unix epoch time as the number of seconds since 1970-01-01 | form           |

The `time` parameter should be passed in the body of the request, and its content type is `application/x-www-form-urlencoded`.

**Request Examples**

**cURL**

```bash
# Add --insecure before the URL if you're using a self-signed SSL certificate
curl -X POST 'https://appliance.example.com/api/yara/ticloud/time/' \
--header 'Authorization: Token exampletoken'
--header 'Content-Type: application/x-www-form-urlencoded' --data-urlencode 'time=999999999'
```

**Python**

```python

# Change the token
token = "exampletoken"
# Change the host name in the URL
url = "https://appliance.example.com/api/yara/ticloud/time/"

payload = 'time=2020-04-20 04:20'
headers = {
  'Authorization': f'Token {token}',
  'Content-Type': 'application/x-www-form-urlencoded'
}

# Add verify=False in the request if you are using a self-signed SSL certificate
response = requests.get(url, headers=headers, data=payload)

print(response.text)
```

### Response Format

**Response Example**

```
{
  "code": 200,
  "message": "TiCloud matches are syncing from 2017-03-14T11:19:31.978544Z"
  "detail": {
      "time": "2017-08-10 11:53:24+00:00"
  }
}
```

**Response Status Codes**

| CODE | DESCRIPTION                                                  |
| :--- | :----------------------------------------------------------- |
| 200  | OK                                                           |
| 404  | Malformed time parameter                                     |
| 405  | YARA Spectra Intelligence synchronization is currently not enabled. |
