20
20
21
21
22
22
CLASSIFICATIONS = ("MALICIOUS" , "SUSPICIOUS" , "GOODWARE" , "UNKNOWN" )
23
- AVAILABLE_PLATFORMS = ("windows7" , "windows10" , "macos_11" , "windows11" , "linux" )
23
+ AVAILABLE_PLATFORMS = ("windows7" , "windows10" , "macos_11" , "windows11" , "linux" , "android12" )
24
24
25
25
26
26
class A1000 (object ):
@@ -64,6 +64,12 @@ class A1000(object):
64
64
__GET_OR_SET_YARA_RULESET_SYNCHRONIZATION_TIME_ENDPOINT = "/api/yara/ticloud/time/"
65
65
__YARA_LOCAL_RETROSCAN_ENDPOINT = "/api/uploads/local-retro-hunt/"
66
66
__YARA_CLOUD_RETROSCANS_ENDPOINT = "/api/yara/ruleset/{ruleset_name}/cloud-retro-hunt/"
67
+ __YARA_REPOSITORIES_ENDPOINT = "/api/yara/repositories/"
68
+ __YARA_PUBLISH_ALL_ENDPOINT = "/api/yara/publish/all/"
69
+ __YARA_PUBLISH_RULESET_ENDPOINT = "/api/yara/publish/ruleset/{ruleset_name}/"
70
+ __YARA_SET_UPDATE_ENDPOINT = "/api/yara/update/set-interval/{value_seconds}/"
71
+ __YARA_RESET_UPDATE_ENDPOINT = "/api/yara/update/reset-interval/"
72
+ __YARA_RUN_UPDATE_ENDPOINT = "/api/yara/update/run/"
67
73
__ADVANCED_SEARCH_ENDPOINT_V2 = "/api/samples/v2/search/"
68
74
__ADVANCED_SEARCH_ENDPOINT_V3 = "/api/samples/v3/search/"
69
75
__LIST_CONTAINERS_ENDPOINT = "/api/samples/containers/"
@@ -2019,6 +2025,275 @@ def get_yara_cloud_retro_scan_status(self, ruleset_name):
2019
2025
2020
2026
return response
2021
2027
2028
+ def publish_all_yara_rulesets (self ):
2029
+ """Triggers publishing process for all non-core YARA rulesets in the system.
2030
+ :return: response
2031
+ :rtype: requests.Response
2032
+ """
2033
+ url = self ._url .format (endpoint = self .__YARA_PUBLISH_ALL_ENDPOINT )
2034
+
2035
+ response = self .__post_request (url = url )
2036
+
2037
+ self .__raise_on_error (response )
2038
+
2039
+ return response
2040
+
2041
+ def publish_single_yara_ruleset (self , ruleset_name ):
2042
+ """Triggers publishing process for a single YARA ruleset in the system.
2043
+ Only non-core rulesets can be published.
2044
+ :param ruleset_name: Name of the ruleset
2045
+ :type ruleset_name: str
2046
+ :return: response
2047
+ :rtype: requests.Response
2048
+ """
2049
+ endpoint = self ._url .format (endpoint = self .__YARA_PUBLISH_RULESET_ENDPOINT )
2050
+
2051
+ url = endpoint .format (ruleset_name = ruleset_name )
2052
+
2053
+ response = self .__post_request (url = url )
2054
+
2055
+ self .__raise_on_error (response )
2056
+
2057
+ return response
2058
+
2059
+ def get_yara_repositories (self , active_filter = None , page_size = None , page_number = None ):
2060
+ """Returns a list of all Yara Online Sources repositories
2061
+ with optional filtering by custom or system repositories.
2062
+ :param active_filter: Filter repositories by type. Possible values: 'all', 'user' and 'system'
2063
+ :type active_filter: str
2064
+ :param page_size: Number of results per page
2065
+ :type page_size: int
2066
+ :param page_number: Page number
2067
+ :type page_number: int
2068
+ :return: response
2069
+ :rtype: requests.Response
2070
+ """
2071
+ url = self ._url .format (endpoint = self .__YARA_REPOSITORIES_ENDPOINT )
2072
+
2073
+ params = {
2074
+ "active_filter" : active_filter ,
2075
+ "page_size" : page_size ,
2076
+ "page" : page_number
2077
+ }
2078
+
2079
+ response = self .__get_request (url = url , params = params )
2080
+
2081
+ self .__raise_on_error (response )
2082
+
2083
+ return response
2084
+
2085
+ def get_yara_repositories_aggregated (self , active_filter = None , page_size = 100 , max_results = None ):
2086
+ """Returns a list of all Yara Online Sources repositories
2087
+ with optional filtering by custom or system repositories.
2088
+ This method performs automated paging with defining the maximum number of returned results being optional.
2089
+ :param active_filter: Filter repositories by type. Possible values: 'all', 'user' and 'system'
2090
+ :type active_filter: str
2091
+ :param page_size: Number of results per page
2092
+ :type page_size: int
2093
+ :param max_results: Maximum number of results to return; Leave as None to get all results
2094
+ :type max_results: int or None
2095
+ :return: list of results
2096
+ :rtype: List
2097
+ """
2098
+ results_list = []
2099
+
2100
+ response = self .get_yara_repositories (
2101
+ active_filter = active_filter ,
2102
+ page_size = page_size ,
2103
+ page_number = 1
2104
+ )
2105
+
2106
+ results = response .json ().get ("results" , [])
2107
+ results_list .append (results )
2108
+
2109
+ if max_results and len (results_list ) >= max_results :
2110
+ return results_list [:max_results ]
2111
+
2112
+ next_page_url = response .json ().get ("next" )
2113
+
2114
+ while next_page_url :
2115
+ response = self .__get_request (url = next_page_url )
2116
+
2117
+ results = response .json ().get ("results" , [])
2118
+ results_list .append (results )
2119
+
2120
+ next_page_url = response .json ().get ("next" )
2121
+
2122
+ if not max_results :
2123
+ if not next_page_url :
2124
+ break
2125
+
2126
+ else :
2127
+ if not next_page_url or len (results_list ) >= max_results :
2128
+ return results_list [:max_results ]
2129
+
2130
+ return results_list
2131
+
2132
+ def create_yara_repository (self , repository_url , name , source_branch , api_token , import_update_preferences ):
2133
+ """Creates a new Yara Online Source repository for fetching and managing YARA rules.
2134
+ The system will verify connectivity to the provided GitHub repository before creation.
2135
+ :param repository_url: URL pointing to the remote ruleset repository.
2136
+ :type repository_url: str
2137
+ :param name: Display name for the repository
2138
+ :type name: str
2139
+ :param source_branch: Git branch to pull rulesets from; Defaults to main or master if omitted
2140
+ :type source_branch: str
2141
+ :param api_token: Token used to authenticate to private remote repositories
2142
+ :type api_token: str
2143
+ :param import_update_preferences: Integer enum representing importing update preferences;
2144
+ Supported values: 0 - Manual, 1 - Auto-Update, 2 - Auto-Update and Auto-Import.
2145
+ :type import_update_preferences: int
2146
+ :return: response
2147
+ :rtype: requests.Response
2148
+ """
2149
+ args = {
2150
+ "repository_url" : repository_url ,
2151
+ "name" : name ,
2152
+ "source_branch" : source_branch ,
2153
+ "api_token" : api_token ,
2154
+ }
2155
+
2156
+ for arg , value in args .items ():
2157
+ if not isinstance (value , str ):
2158
+ raise WrongInputError (f"{ arg } needs to be a string" )
2159
+
2160
+ if not isinstance (import_update_preferences , int ):
2161
+ raise WrongInputError (f"import_update_preferences needs to be an integer" )
2162
+
2163
+ url = self ._url .format (endpoint = self .__YARA_REPOSITORIES_ENDPOINT )
2164
+
2165
+ post_json = {"url" : repository_url , "name" : name , "source_branch" : source_branch , "api_token" : api_token ,
2166
+ "import_update_preferences" : import_update_preferences }
2167
+
2168
+ response = self .__post_request (url = url , post_json = post_json )
2169
+
2170
+ self .__raise_on_error (response )
2171
+
2172
+ return response
2173
+
2174
+ def update_yara_repository (self , repository_id , repository_url , name , source_branch , api_token ,
2175
+ import_update_preferences ):
2176
+ """Updates a Yara Online Source repository.
2177
+ The system will verify connectivity to the provided GitHub repository before updating.
2178
+ :param repository_id: Repository ID
2179
+ :type repository_id: int
2180
+ :param repository_url: URL pointing to the remote ruleset repository.
2181
+ :type repository_url: str
2182
+ :param name: Display name for the repository
2183
+ :type name: str
2184
+ :param source_branch: Git branch to pull rulesets from; Defaults to main or master if omitted
2185
+ :type source_branch: str
2186
+ :param api_token: Token used to authenticate to private remote repositories
2187
+ :type api_token: str
2188
+ :param import_update_preferences: Integer enum representing importing update preferences;
2189
+ Supported values: 0 - Manual, 1 - Auto-Update, 2 - Auto-Update and Auto-Import.
2190
+ :type import_update_preferences: int
2191
+ :return: response
2192
+ :rtype: requests.Response
2193
+ """
2194
+ args = {
2195
+ "repository_url" : repository_url ,
2196
+ "name" : name ,
2197
+ "source_branch" : source_branch ,
2198
+ "api_token" : api_token ,
2199
+ }
2200
+
2201
+ for arg , value in args .items ():
2202
+ if not isinstance (value , str ):
2203
+ raise WrongInputError (f"{ arg } needs to be a string" )
2204
+
2205
+ if not isinstance (import_update_preferences , int ):
2206
+ raise WrongInputError (f"import_update_preferences needs to be an integer" )
2207
+
2208
+ if not isinstance (repository_id , int ):
2209
+ raise WrongInputError ("repository_id needs to be an integer" )
2210
+
2211
+ endpoint = f"{ self .__YARA_REPOSITORIES_ENDPOINT } /{ repository_id } /"
2212
+
2213
+ url = self ._url .format (endpoint = endpoint )
2214
+
2215
+ put_json = {"url" : repository_url , "name" : name , "source_branch" : source_branch , "api_token" : api_token ,
2216
+ "import_update_preferences" : import_update_preferences }
2217
+
2218
+ response = self .__put_request (url = url , put_json = put_json )
2219
+
2220
+ self .__raise_on_error (response )
2221
+
2222
+ return response
2223
+
2224
+ def delete_yara_repository (self , repository_id , remove_rulesets = False ):
2225
+ """Deletes a Yara Online Source repository. Only custom repositories can be deleted,
2226
+ and only by their owner or a superuser. Associated rulesets can optionally be removed as well.
2227
+ :param repository_id: Repository ID
2228
+ :type repository_id: int
2229
+ :param remove_rulesets: Whether to also remove all rulesets associated with this repository;
2230
+ Default is False
2231
+ :type remove_rulesets: bool
2232
+ :return: response
2233
+ :rtype: requests.Response
2234
+ """
2235
+ if not isinstance (remove_rulesets , bool ):
2236
+ raise WrongInputError ("remove_rulesets needs to be boolean" )
2237
+
2238
+ endpoint = f"{ self .__YARA_REPOSITORIES_ENDPOINT } /{ repository_id } /"
2239
+
2240
+ url = self ._url .format (endpoint = endpoint )
2241
+
2242
+ params = {"shouldRemoveRulesets" : remove_rulesets }
2243
+
2244
+ response = self .__delete_request (url = url , params = params )
2245
+
2246
+ self .__raise_on_error (response )
2247
+
2248
+ return response
2249
+
2250
+ def set_yara_update_interval (self , seconds ):
2251
+ """Configure the interval at which the YARA update job runs automatically.
2252
+ :param seconds: Interval in seconds;
2253
+ Setting to '0' will disable auto-update job (This will introduce a short maintenance downtime)
2254
+ :type seconds: int
2255
+ :return: response
2256
+ :rtype: requests.Response
2257
+ """
2258
+ if not isinstance (seconds , int ):
2259
+ raise WrongInputError ("seconds should be an integer" )
2260
+
2261
+ endpoint = self .__YARA_SET_UPDATE_ENDPOINT .format (value_seconds = seconds )
2262
+
2263
+ url = self ._url .format (endpoint = endpoint )
2264
+
2265
+ response = self .__post_request (url = url )
2266
+
2267
+ self .__raise_on_error (response )
2268
+
2269
+ return response
2270
+
2271
+ def reset_yara_update_interval (self ):
2272
+ """Reset the YARA update job cadence to its default value.
2273
+ :return: response
2274
+ :rtype: requests.Response
2275
+ """
2276
+ url = self ._url .format (endpoint = self .__YARA_RESET_UPDATE_ENDPOINT )
2277
+
2278
+ response = self .__post_request (url = url )
2279
+
2280
+ self .__raise_on_error (response )
2281
+
2282
+ return response
2283
+
2284
+ def run_yara_update (self ):
2285
+ """Manually trigger YARA update job execution.
2286
+ :return: response
2287
+ :rtype: requests.Response
2288
+ """
2289
+ url = self ._url .format (endpoint = self .__YARA_RUN_UPDATE_ENDPOINT )
2290
+
2291
+ response = self .__post_request (url = url )
2292
+
2293
+ self .__raise_on_error (response )
2294
+
2295
+ return response
2296
+
2022
2297
def advanced_search_v2 (self , query_string , ticloud = False , page_number = 1 , records_per_page = 20 , sorting_criteria = None ,
2023
2298
sorting_order = "desc" ):
2024
2299
"""THIS METHOD IS DEPRECATED. Use advanced_search_v3 instead.
@@ -2852,7 +3127,7 @@ def __post_request(self, url, post_json=None, files=None, data=None, params=None
2852
3127
2853
3128
return response
2854
3129
2855
- def __delete_request (self , url , post_json = None ):
3130
+ def __delete_request (self , url , post_json = None , params = None ):
2856
3131
"""A generic DELETE request method for all A1000 methods.
2857
3132
:param url: request URL
2858
3133
:type url: str
@@ -2865,6 +3140,22 @@ def __delete_request(self, url, post_json=None):
2865
3140
response = requests .delete (
2866
3141
url = url ,
2867
3142
json = post_json ,
3143
+ params = params ,
3144
+ verify = self ._verify ,
3145
+ proxies = self ._proxies ,
3146
+ headers = self ._headers
3147
+ )
3148
+
3149
+ return response
3150
+
3151
+ def __put_request (self , url , data = None , put_json = None ):
3152
+ self ._headers ["User-Agent" ] = (f"{ self ._user_agent } ; "
3153
+ f"{ self .__class__ .__name__ } { inspect .currentframe ().f_back .f_code .co_name } " )
3154
+
3155
+ response = requests .put (
3156
+ url = url ,
3157
+ data = data ,
3158
+ json = put_json ,
2868
3159
verify = self ._verify ,
2869
3160
proxies = self ._proxies ,
2870
3161
headers = self ._headers
0 commit comments