2020
2121
2222CLASSIFICATIONS = ("MALICIOUS" , "SUSPICIOUS" , "GOODWARE" , "UNKNOWN" )
23- AVAILABLE_PLATFORMS = ("windows7" , "windows10" , "macos_11" , "windows11" , "linux" )
23+ AVAILABLE_PLATFORMS = ("windows7" , "windows10" , "macos_11" , "windows11" , "linux" , "android12" )
2424
2525
2626class A1000 (object ):
@@ -64,6 +64,12 @@ class A1000(object):
6464 __GET_OR_SET_YARA_RULESET_SYNCHRONIZATION_TIME_ENDPOINT = "/api/yara/ticloud/time/"
6565 __YARA_LOCAL_RETROSCAN_ENDPOINT = "/api/uploads/local-retro-hunt/"
6666 __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/"
6773 __ADVANCED_SEARCH_ENDPOINT_V2 = "/api/samples/v2/search/"
6874 __ADVANCED_SEARCH_ENDPOINT_V3 = "/api/samples/v3/search/"
6975 __LIST_CONTAINERS_ENDPOINT = "/api/samples/containers/"
@@ -2019,6 +2025,275 @@ def get_yara_cloud_retro_scan_status(self, ruleset_name):
20192025
20202026 return response
20212027
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+
20222297 def advanced_search_v2 (self , query_string , ticloud = False , page_number = 1 , records_per_page = 20 , sorting_criteria = None ,
20232298 sorting_order = "desc" ):
20242299 """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
28523127
28533128 return response
28543129
2855- def __delete_request (self , url , post_json = None ):
3130+ def __delete_request (self , url , post_json = None , params = None ):
28563131 """A generic DELETE request method for all A1000 methods.
28573132 :param url: request URL
28583133 :type url: str
@@ -2865,6 +3140,22 @@ def __delete_request(self, url, post_json=None):
28653140 response = requests .delete (
28663141 url = url ,
28673142 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 ,
28683159 verify = self ._verify ,
28693160 proxies = self ._proxies ,
28703161 headers = self ._headers
0 commit comments