def validate_params(self): if not self.get_global_setting("canary_domain"): self.log_error( 'canary_domain is a mandatory setup parameter, but its value is None.' ) return False splunk_session_key = self.session_key splunkService = client.connect(token=splunk_session_key) api_key = get_api_key(splunkService) if not api_key: self.log_error( 'api_key is a mandatory setup parameter, but its value is None.' ) return False return True
def collect_events(helper, ew): domain = helper.get_global_setting('canary_domain') api_key = get_api_key(helper.service) incident_limit = 20 #Admin can use XXXXXXX.canary.tools or simply XXXXXXX if not domain.endswith('.canary.tools'): domain += '.canary.tools' #Check to see if proxy setting is configured proxy = helper.get_proxy() if proxy: use_proxy = True else: use_proxy = False #Set a custom useragent header for Splunk API so Canary.tools can measure the use of the product #Include the TA-canary version number try: ta_version = [ i for i in helper.service.apps.list() if i.name == helper.app ][0].content['version'] except: ta_version = 'N/A' try: splunk_version = helper.service.info['version'] except KeyError: splunk_version = 'Unknown_version' # the call above worked correctly on 7.3 -> 8.0.5 so another version is likely headers = { 'User-Agent': 'Splunk API Call TA-Canary ({ta_version}) Splunk ({splunk_version}) '. format(ta_version=ta_version, splunk_version=splunk_version), 'X-Canary-Auth-Token': api_key } #Pass the domain and the api key to the url. url = "https://{}/api/v1/ping".format(domain) #Set the method of Get to the console method = "GET" #Try the first connection to see if it works. response = helper.send_http_request(url, method, headers=headers, verify=True, timeout=60, use_proxy=use_proxy) try: response except Exception as e: helper.log_error( "Error occured with canary.tools API call. Error Message: {}". format(e)) sys.exit() if response.status_code == 200: #Successfull Connection helper.log_info("Successfully connected to Canary.tools API") #Get current time for testing purposes. current_time = time.time() #Collect All incidents from Canary Tools url_allIncidents = "https://{}/api/v1/incidents/all?tz=UTC&limit={}".format( domain, incident_limit) if helper.get_check_point('last_updated_id'): url_allIncidents += '&incidents_since={}'.format( helper.get_check_point('last_updated_id')) # helper.log_info("last_updated_id URL is {}".format(url_allIncidents)) #Collect All Registered Devices from Canary Tools url_regDevices = "https://{}/api/v1/devices/all?tz=UTC".format(domain) #Collect All Canary Tokens from Canary Tools url_canarytokens_fetch = "https://{}/api/v1/canarytokens/fetch".format( domain) #Issue a new response to the Registered DevicesAPI response_regDevices = helper.send_http_request(url_regDevices, method, headers=headers, verify=True, timeout=60, use_proxy=use_proxy) #Issue a new response to the Canary Tokens API response_canarytokens_fetch = helper.send_http_request( url_canarytokens_fetch, method, headers=headers, verify=True, timeout=60, use_proxy=use_proxy) #Try to connect to the url for registered devices try: response_regDevices #Throw an exception if it fails except Exception as e: helper.log_error( "Error occured with canary.tools API call to retrieve all registered devices. Error Message: {}" .format(e)) sys.exit() #Try to connect to the url for canary tokens try: response_canarytokens_fetch #Throw an exception if it fails except Exception as e: helper.log_error( "Error occured with canary.tools API call to retrieve all canary tokens. Error Message: {}" .format(e)) sys.exit() #Issue a new response to the All Incidents API response_allIncidents = helper.send_http_request(url_allIncidents, method, headers=headers, verify=True, timeout=60, use_proxy=use_proxy) #Try to connect to the url for All Incidents try: response_allIncidents #Throw an exception if it fails except Exception as e: helper.log_error( "Error occured with canary.tools API call to retrieve all Incidents. Error Message: {}" .format(e)) sys.exit() #Set the most recent updated_id to the last seen incident updated_id, or the epoch last_updated_id = helper.get_check_point('last_updated_id') if not last_updated_id: last_updated_id = 0 while response_allIncidents.status_code == 200: #If we receive a 200 response from the all incidents API #Output the results to json data = response_allIncidents.json() try: if last_updated_id < data['max_updated_id']: last_updated_id = data['max_updated_id'] except: #max_updated_id is only present on queries with incidents pass if len(data['incidents']) > 0: for a in data['incidents']: #Add current time of server to timestamp a['_time'] = current_time #Convert data to a string data_dump = json.dumps(a) #Write the event to the destination index event = helper.new_event( data_dump, source=helper.get_input_type(), index=helper.get_output_index(), sourcetype="canarytools:incidents") ew.write_event(event) else: #If no incidents have been logged #Add current time of server to timestamp helper.log_info( "No incidents have been logged. Successful connection to canaryapi" ) if not data['cursor']['next_link'] or not data['cursor'][ 'next_link'].startswith('https://'): break response_allIncidents = helper.send_http_request( data['cursor']['next_link'], method, headers=headers, verify=True, timeout=60, use_proxy=use_proxy) #If the resposne code from querying the Incidents is not 200 else: helper.log_error( "Error occured with canary.tools API call. Error Message: {}". format(response_allIncidents.json())) if last_updated_id: helper.save_check_point('last_updated_id', last_updated_id) helper.log_debug("Setting last_updated_id checkpoint to {}".format( last_updated_id)) #If we receive a 200 response from the registered devices API if response_regDevices.status_code == 200: #Output the results to json data = response_regDevices.json() if len(data['devices']) > 0: for a in data['devices']: #Only create a device event for new or changed devices check_point_key = 'device:' + a['id'] saved_data = helper.get_check_point(check_point_key) if not saved_data: saved_data = {} monitor_fields = [ 'name', 'description', 'ip_address', 'live', 'version' ] fields_changed = False for field in monitor_fields: if a.get(field, None) != saved_data.get(field, None): fields_changed = True break if not fields_changed: continue helper.save_check_point(check_point_key, a) #Add current time of server to timestamp a['_time'] = current_time #Convert data to a string data_dump = json.dumps(a) #Write the event to the destination index event = helper.new_event(data_dump, source=helper.get_input_type(), index=helper.get_output_index(), sourcetype="canarytools:devices") ew.write_event(event) else: #If no devices have been registered #Add current time of server to timestamp helper.log_info( "No devices have been registered. Successful connection to canaryapi" ) #If the resposne code from querying the Registered devices is not 200 else: helper.log_error( "Error occured with canary.tools API call. Error Message: {}". format(response_regDevices.json())) #If we receive a 200 response from the canary tokens API if response_canarytokens_fetch.status_code == 200: #Output the results to json data = response_canarytokens_fetch.json() if len(data['tokens']) > 0: for a in data['tokens']: #Only create a token event for new or changed tokens check_point_key = 'token:' + a['node_id'] saved_data = helper.get_check_point(check_point_key) if not saved_data: saved_data = {} monitor_fields = ['memo', 'enabled'] fields_changed = False for field in monitor_fields: if a.get(field, None) != saved_data.get(field, None): fields_changed = True break if not fields_changed: continue helper.save_check_point(check_point_key, a) #Add current time of server to timestamp a['_time'] = current_time #Convert data to a string data_dump = json.dumps(a) #Write the event to the destination index event = helper.new_event(data_dump, source=helper.get_input_type(), index=helper.get_output_index(), sourcetype="canarytools:tokens") ew.write_event(event) else: #If no tokens have been registered #Add current time of server to timestamp helper.log_info( "No tokens have been regiestered. Successful connection to canaryapi" ) else: helper.log_error( "Error occured with canary.tools API call. Error Message: {}". format(response_canarytokens_fetch.json())) else: helper.log_error( "Error occured with canary.tools API call. Error Message: {}". format(response.json()))
def process_event(helper, *args, **kwargs): """ # IMPORTANT # Do not remove the anchor macro:start and macro:end lines. # These lines are used to generate sample code. If they are # removed, the sample code will not be updated when configurations # are updated. [sample_code_macro:start] # The following example gets and sets the log level helper.set_log_level(helper.log_level) # The following example gets the setup parameters and prints them to the log canary_domain = helper.get_global_setting("canary_domain") #Admin can use XXXXXXX.canary.tools or simply XXXXXXX if not canary_domain.endswith('.canary.tools'): canary_domain += '.canary.tools' helper.log_info("canary_domain={}".format(canary_domain)) splunk_session_key = helper.session_key splunkService = client.connect(token=splunk_session_key) api_key = get_api_key(splunkService) # The following example sends rest requests to some endpoint # response is a response object in python requests library response = helper.send_http_request("http://www.splunk.com", "GET", parameters=None, payload=None, headers=None, cookies=None, verify=True, cert=None, timeout=None, use_proxy=True) # get the response headers r_headers = response.headers # get the response body as text r_text = response.text # get response body as json. If the body text is not a json string, raise a ValueError r_json = response.json() # get response cookies r_cookies = response.cookies # get redirect history historical_responses = response.history # get response status code r_status = response.status_code # check the response status, if the status is not sucessful, raise requests.HTTPError response.raise_for_status() # The following example gets the alert action parameters and prints them to the log incident_id = helper.get_param("incident_id") helper.log_info("incident_id={}".format(incident_id)) index_name = helper.get_param("index_name") helper.log_info("index_name={}".format(index_name)) # The following example adds two sample events ("hello", "world") # and writes them to Splunk # NOTE: Call helper.writeevents() only once after all events # have been added helper.addevent("hello", sourcetype="sample_sourcetype") helper.addevent("world", sourcetype="sample_sourcetype") helper.writeevents(index="summary", host="localhost", source="localhost") # The following example gets the events that trigger the alert events = helper.get_events() for event in events: helper.log_info("event={}".format(event)) # helper.settings is a dict that includes environment configuration # Example usage: helper.settings["server_uri"] helper.log_info("server_uri={}".format(helper.settings["server_uri"])) [sample_code_macro:end] """ import json import time import splunklib.client as client sys.path.insert(0, '../') from api_key_retrieval import get_api_key helper.log_info("Alert action canary_delete_an_incident started.") domain = helper.get_global_setting('canary_domain') #Admin can use XXXXXXX.canary.tools or simply XXXXXXX if not domain.endswith('.canary.tools'): domain += '.canary.tools' helper.log_info("canary_domain={}".format(domain)) splunk_session_key = helper.session_key splunkService = client.connect(token=splunk_session_key) api_key = get_api_key(splunkService) #Check to see if proxy setting is configured proxy = helper.get_proxy() if proxy: use_proxy = True else: use_proxy = False #Set a custom useragent header for Splunk API so Canary.tools can see the use of the product #Include the TA-canary version number try: version = [ i for i in helper.service.apps.list() if i.name == helper.app ][0].content['version'] except: version = 'N/A' headers = { 'User-Agent': 'Splunk API Call ({})'.format(version), 'X-Canary-Auth-Token': api_key } #Get ID of Incident incident_id = helper.get_param("incident_id") #Get Index Name index_name = helper.get_param("index_name") #Get current time for testing purposes. current_time = time.time() #Pass the domain and the api key to the url. url = "https://{}/api/v1/incident/delete?incident={}".format( domain, incident_id) #Set the method of Get to the console method = "DELETE" #Try the first connection to see if it works. response = helper.send_http_request(url, method, parameters=None, payload=canary_data, headers=headers, cookies=None, verify=True, cert=None, timeout=None, use_proxy=use_proxy) try: response except Exception as e: helper.log_error( "Error occured with canary.tools Acknowledging an incident. Error Message: {}" .format(e)) sys.exit() if response.status_code == 200: #Successfull Connection helper.log_info("Successfully deleted incident") data = response.json() data['api_call'] = 'Incident Acknowledged' data['_time'] = current_time json_data = json.dumps(data) helper.addevent(json_data, sourcetype="canarytools:ar") helper.writeevents(source="canary_toolsapi", index=index_name, host="adaptive_response") else: data = response.json() data['api_call'] = 'Incident Deleted' data['_time'] = current_time json_data = json.dumps(data) helper.addevent(json_data, sourcetype="canarytools:ar") helper.writeevents(source="canary_toolsapi", index=index_name, host="adaptive_response") helper.log_error("Error with deleting incident.") # TODO: Implement your alert action logic here return 0
def collect_events(helper, ew): domain = helper.get_global_setting('canary_domain') #Admin can use XXXXXXX.canary.tools or simply XXXXXXX if not domain.endswith('.canary.tools'): domain += '.canary.tools' api_key = get_api_key(helper.service) # api_key = helper.get_global_setting("api_key") incident_limit = 20 #Check to see if proxy setting is configured proxy = helper.get_proxy() if proxy: use_proxy = True else: use_proxy = False #Set a custom useragent header for Splunk API so Canary.tools can measure the use of the product #Include the TA-canary version number try: version = [ i for i in helper.service.apps.list() if i.name == helper.app ][0].content['version'] except: version = 'N/A' headers = { 'User-Agent': 'Splunk API Call ({})'.format(version), 'X-Canary-Auth-Token': api_key } #Pass the domain and the api key to the url. url = "https://{}/api/v1/ping".format(domain) #Set the method of Get to the console method = "GET" #Try the first connection to see if it works. response = helper.send_http_request(url, method, headers=headers, verify=True, timeout=60, use_proxy=use_proxy) try: response except Exception as e: helper.log_error( "Error occured with canary.tools Device poll API call. Error Message: {}" .format(e)) sys.exit() if response.status_code == 200: #Successfull Connection helper.log_info("Successfully connected to Canary.tools API") #Get current time for testing purposes. current_time = time.time() #Collect All unacknowledged incidents from Canary Tools url_unacknowledgedIncidents = "https://{}/api/v1/incidents/unacknowledged?tz=UTC&limit={}".format( domain, incident_limit) url_cursorIncidents = "https://{}/api/v1/incidents/unacknowledged?tz=UTC&cursor=".format( domain) #Collect All Registered Devices from Canary Tools url_regDevices = "https://{}/api/v1/devices/all?tz=UTC".format(domain) #Collect All Canary Tokens from Canary Tools url_canarytokens_fetch = "https://{}/api/v1/canarytokens/fetch".format( domain) #Issue a new response to the Registered DevicesAPI response_regDevices = helper.send_http_request(url_regDevices, method, headers=headers, verify=True, timeout=60, use_proxy=use_proxy) #Issue a new response to the Canary Tokens API response_canarytokens_fetch = helper.send_http_request( url_canarytokens_fetch, method, headers=headers, verify=True, timeout=60, use_proxy=use_proxy) #Issue a new response to the All Incidents API response_unacknowledgedIncidents = helper.send_http_request( url_unacknowledgedIncidents, method, headers=headers, verify=True, timeout=60, use_proxy=use_proxy) #Try to connect to the url for All Incidents try: response_unacknowledgedIncidents #Throw an exception if it fails except Exception as e: helper.log_error( "Error occured with canary.tools API call to retrieve all unacknowledged Incidents. Error Message: {}" .format(e)) sys.exit() #Set the most recent timestamp to the current time. most_recent_timestamp = current_time #Try to connect to the url for registered devices try: response_regDevices #Throw an exception if it fails except Exception as e: helper.log_error( "Error occured with canary.tools API call to retrieve all registered devices. Error Message: {}" .format(e)) sys.exit() #Try to connect to the url for canary tokens try: response_canarytokens_fetch #Throw an exception if it fails except Exception as e: helper.log_error( "Error occured with canary.tools API call to retrieve all canary tokens. Error Message: {}" .format(e)) sys.exit() #If we receive a 200 response from the registered devices API if response_regDevices.status_code == 200: #Output the results to json data = response_regDevices.json() if len(data['devices']) > 0: for a in data['devices']: #Add current time of server to timestamp a['_time'] = current_time #Convert data to a string data_dump = json.dumps(a) #Write the event to the destination index event = helper.new_event(data_dump, source=helper.get_input_type(), index=helper.get_output_index(), sourcetype="canarytools:devices") ew.write_event(event) else: #If no devices have been registered helper.log_info( "No devices have been registered. Successful connection to canaryapi" ) #If the resposne code from querying the Registered devices is not 200 else: helper.log_error( "Error occured with canary.tools API call. Error Message: {}". format(response_regDevices.json())) #If we receive a 200 response from the canary tokens API if response_canarytokens_fetch.status_code == 200: #Output the results to json data = response_canarytokens_fetch.json() if len(data['tokens']) > 0: for a in data['tokens']: #Add current time of server to timestamp a['_time'] = current_time #Convert data to a string data_dump = json.dumps(a) #Write the event to the destination index event = helper.new_event(data_dump, source=helper.get_input_type(), index=helper.get_output_index(), sourcetype="canarytools:tokens") ew.write_event(event) else: #If no tokens have been registered helper.log_info( "No tokens have been regiestered. Successful connection to canaryapi" ) else: helper.log_error( "Error occured with canary.tools API call. Error Message: {}". format(response_canarytokens_fetch.json())) while response_unacknowledgedIncidents.status_code == 200: #If we receive a 200 response from the all incidents API #Output the results to json data = response_unacknowledgedIncidents.json() if len(data['incidents']) > 0: for a in data['incidents']: #Add current time of server to timestamp a['_time'] = current_time #Convert data to a string data_dump = json.dumps(a) #Write the event to the destination index event = helper.new_event( data_dump, source=helper.get_input_type(), index=helper.get_output_index(), sourcetype="canarytools:incidents") ew.write_event(event) try: created_timestamp = int(a['description']['created']) if created_timestamp > most_recent_timestamp: most_recent_timestamp = created_timestamp except (KeyError, ValueError) as e: helper.log_error( "Error updating timestamp {}".format(e)) else: #If no incidents have been logged helper.log_info( "No incidents have been logged. Successful connection to canaryapi" ) if not data['cursor']['next_link'] or not data['cursor'][ 'next_link'].startswith('https://'): break response_unacknowledgedIncidents = helper.send_http_request( data['cursor']['next_link'], method, headers=headers, verify=True, timeout=60, use_proxy=use_proxy) #If the resposne code from querying the Incidents is not 200 else: helper.log_error( "Error occured with canary.tools API call. Error Message: {}". format(response_unacknowledgedIncidents.json())) else: helper.log_error( "Error occured with canary.tools device API call. Error Message: {}" .format(response.json()))