def main(): # For the purpose of this sample, the reading in of credentials, the setup # of HTTP request headers, and the construction and sending of a request # object has been abstracted to the 'RestApiClient' class. # For more information on how these operations are done see the sample # '01_Authentication.py'. client = RestApiClient() # Many API endpoints accept parameters. # One type of parameter is a query parameter. # If an endpoint accepts query parameters they are passed after a '?' as # part of the URL. Each parameter has a name and a value separated by a '='. # Several parameters can be passed separated by '&' characters. SampleUtilities.pretty_print_request(client, 'reference_data/sets?name=rest_api_samples_testset&element_type=ALN', 'POST') response = client.call_api('reference_data/sets?name=rest_api_samples_testset&element_type=ALN', 'POST') # The response code for successfully creating a set is 201. if (response.code == 201): SampleUtilities.pretty_print_response(response) # The error code that occurs when attempting to create a set that already # exists is 409. elif (response.code == 409): print("Reference set already exists") response = client.call_api('reference_data/sets/rest_api_samples_testset', 'GET') SampleUtilities.pretty_print_response(response) elif (response.code >= 500): print("An internal server error occurred. You should check your system.") SampleUtilities.pretty_print_response(response) else: print("Some other error has occurred:") SampleUtilities.pretty_print_response(response)
def main(): # Create our client. client = RestApiClient(version='3.0') # Using the /asset_model/assets endpoint with a GET request. SampleUtilities.pretty_print_request(client, 'asset_model/assets', 'GET') response = client.call_api('asset_model/assets', 'GET') # Verify that the call to the API was successful. if (response.code != 200): print('Failed to retrieve asset list.') SampleUtilities.pretty_print_response(response) sys.exit(1) # Display the number of assets retrieved. response_body = json.loads(response.read().decode('utf-8')) number_of_assets_retrieved = len(response_body) # Display number of assets, and the IDs of the assets retrieved. print(str(number_of_assets_retrieved) + ' assets were retrieved.') if (number_of_assets_retrieved > 0): print("Asset IDs: ", end="") for asset in response_body: print(str(asset['id']) + ' ', end="") print()
def setup_data(client): SampleUtilities.data_setup(client, 'reference_data/sets?name=rest_api_samples_suspect_ips&element_type=IP', 'POST') SampleUtilities.data_setup(client, 'reference_data/sets/rest_api_samples_suspect_ips?value=8.7.6.5', 'POST') SampleUtilities.data_setup(client, 'reference_data/sets/rest_api_samples_suspect_ips?value=10.7.6.5', 'POST') SampleUtilities.data_setup(client, 'reference_data/sets/rest_api_samples_suspect_ips?value=13.7.6.5', 'POST') SampleUtilities.data_setup(client, 'reference_data/sets?name=rest_api_samples_blocked_ips&element_type=IP', 'POST')
def main(): # Create our client. client = RestApiClient() # Using the /asset_model/assets endpoint with a GET request. SampleUtilities.pretty_print_request(client, 'asset_model/assets', 'GET') response = client.call_api('asset_model/assets', 'GET') # Verify that the call to the API was successful. if (response.code != 200): print('Failed to retrieve asset list.') SampleUtilities.pretty_print_response(response) sys.exit(1) # Display the number of assets retrieved. response_body = json.loads(response.read().decode('utf-8')) number_of_assets_retrieved = len(response_body) # Display number of assets, and the IDs of the assets retrieved. print(str(number_of_assets_retrieved) + ' assets were retrieved.') if (number_of_assets_retrieved > 0): print("Asset IDs: ", end="") for asset in response_body: print(str(asset['id']) + ' ', end="") print()
def main(): # Create our client and set up some sample data. client = RestApiClient(version='3.0') setup_data(client) # Some endpoints accept path parameters. # These parameters are inserted into the path portion of the URL at # specific locations. In this example we are retrieving the contents of a # reference set named 'rest_api_samples_testset'. SampleUtilities.pretty_print_request( client, 'reference_data/sets/rest_api_samples_testset', 'GET') response = client.call_api('reference_data/sets/rest_api_samples_testset', 'GET') SampleUtilities.pretty_print_response(response) # Query parameters and path parameters can be combined in a single request. # Here we are adding a value to the reference set we just looked at. SampleUtilities.pretty_print_request( client, 'reference_data/sets/rest_api_samples_testset?value=' + 'rest_api_sample_value', 'POST') response = client.call_api( 'reference_data/sets/rest_api_samples_testset?value=' + 'rest_api_sample_value', 'POST') # Along with GET requests, POST and DELETE requests often return # information that can be used to confirm the results of the request. SampleUtilities.pretty_print_response(response) # Now we can look at the contents of the reference set again to see the # value we added. response = client.call_api('reference_data/sets/rest_api_samples_testset', 'GET') SampleUtilities.pretty_print_response(response)
def main(): # Create our client and set up some sample data. client = RestApiClient() setup_data(client) # Some endpoints accept path parameters. # These parameters are inserted into the path portion of the URL at specific # locations. In this example we are retrieving the contents of a reference # set named 'rest_api_samples_testset'. SampleUtilities.pretty_print_request(client, 'referencedata/sets/rest_api_samples_testset', 'GET') response = client.call_api('referencedata/sets/rest_api_samples_testset', 'GET') SampleUtilities.pretty_print_response(response) # Query parameters and path parameters can be combined in a single request. # Here we are adding a value to the reference set we just looked at. SampleUtilities.pretty_print_request(client, 'referencedata/sets/rest_api_samples_testset?value=rest_api_sample_value', 'POST') response = client.call_api('referencedata/sets/rest_api_samples_testset?value=rest_api_sample_value', 'POST') # Along with GET requests, POST and DELETE requests often return information # that can be used to confirm the results of the request. SampleUtilities.pretty_print_response(response) # Now we can look at the contents of the reference set again to see the # value we added. response = client.call_api('referencedata/sets/rest_api_samples_testset', 'GET') SampleUtilities.pretty_print_response(response)
def main(): # Create our client. client = RestApiClient(version='3.0') # Using the /asset_model/properties endpoint with a GET request. SampleUtilities.pretty_print_request(client, 'asset_model/properties', 'GET') response = client.call_api('asset_model/properties', 'GET') # Verify that the call to the API was successful. if (response.code != 200): print('Failed to retrieve propertiy list.') SampleUtilities.pretty_print_response(response) sys.exit(1) # Display the number of properties retrieved. response_body = json.loads(response.read().decode('utf-8')) number_of_properties_retrieved = len(response_body) # Display number of properties, and the names of the properties retrieved. print(str(number_of_properties_retrieved) + ' properties were retrieved.') if (number_of_properties_retrieved > 0): print("Property Names: ", end="") for property in response_body: print(str(property['name']) + ', ', end="") print()
def main(): # Create our client and set up some sample data. client = RestApiClient() setup_data(client) # Here we have a look at the data in this map of sets. response = client.call_api('referencedata/mapOfSets/rest_api_samples_login_events', 'GET') SampleUtilities.pretty_print_response(response) # Retrieve the map of sets and load it into a JSON object. response = client.call_api('referencedata/mapOfSets/rest_api_samples_login_events', 'GET') response_body = json.loads(response.read().decode('utf-8')) # Capture the data portion of the map of sets. data = response_body['data'] # Also get the current time so that the CIO's dashboard can plot the results # over time. current_time = time.strftime('%Y-%m-%d %H:%M:%S') # We now empty the reference map of sets so that new data can start to # accumulate. We empty it now so that we don't miss new events if we have a # lot of data to process. Note that by using the purgeOnly parameter we are # only emptying the collection, not deleting it. print("Purging the collection so that new data can be collected.") response = client.call_api('referencedata/mapOfSets/rest_api_samples_login_events?purgeOnly=true', 'DELETE') SampleUtilities.pretty_print_response(response) # Go through the data, find the information we are interested in, and send # it to the CIO's dashboard. for key in data.keys(): number_of_elements = len(data[key]) send_data_to_dashboard(current_time, key, number_of_elements)
def main(): # Create our client. client = RestApiClient() # Using the /asset_model/properties endpoint with a GET request. SampleUtilities.pretty_print_request(client, 'asset_model/properties', 'GET') response = client.call_api('asset_model/properties', 'GET') # Verify that the call to the API was successful. if (response.code != 200): print('Failed to retrieve propertiy list.') SampleUtilities.pretty_print_response(response) sys.exit(1) # Display the number of properties retrieved. response_body = json.loads(response.read().decode('utf-8')) number_of_properties_retrieved = len(response_body) # Display number of properties, and the names of the properties retrieved. print(str(number_of_properties_retrieved) + ' properties were retrieved.') if (number_of_properties_retrieved > 0): print("Property Names: ", end="") for property in response_body: print(str(property['name']) + ', ', end="") print()
def main(): # Create our client. client = RestApiClient(version="3.0") # Using the /asset_model/assets endpoint with a GET request. SampleUtilities.pretty_print_request(client, "asset_model/assets", "GET") response = client.call_api("asset_model/assets", "GET") # Verify that the call to the API was successful. if response.code != 200: print("Failed to retrieve asset list.") SampleUtilities.pretty_print_response(response) sys.exit(1) # Display the number of assets retrieved. response_body = json.loads(response.read().decode("utf-8")) number_of_assets_retrieved = len(response_body) # Display number of assets, and the IDs of the assets retrieved. print(str(number_of_assets_retrieved) + " assets were retrieved.") if number_of_assets_retrieved > 0: print("Asset IDs: ", end="") for asset in response_body: print(str(asset["id"]) + " ", end="") print()
def main(): # Create our client and set up some sample data. client = RestApiClient(version='3.0') setup_data(client) # Using the '/sets/{name} endpoint with a GET request we can retrieve the # contents of our set of suspect addresses. SampleUtilities.pretty_print_request( client, 'reference_data/sets/rest_api_samples_suspect_ips', 'GET') response = client.call_api( 'reference_data/sets/rest_api_samples_suspect_ips', 'GET') # Based on our business rules, this set should always exist. If it does not # exist it could be an indication that our security has been breached and # that an attack is in progress. We should raise an alarm. if (response.code == 404): print('Something is wrong, a system administrator should investigate.') sys.exit(1) # Extract the reference set from the response body. response_body = json.loads(response.read().decode('utf-8')) data = response_body['data'] for element in data: # For each suspect ip address, pass it to our legacy system to # validate. If it is a real threat, move it to the blocked list so that # the configured rules can generate offenses if it is active on our # network. ip_address = element['value'] if (legacy_system_logic(ip_address)): SampleUtilities.pretty_print_request( client, 'reference_data/sets/rest_api_samples_blocked_ips?value=' + ip_address, 'POST') response = client.call_api( 'reference_data/sets/rest_api_samples_blocked_ips?value=' + ip_address, 'POST') SampleUtilities.pretty_print_request( client, 'reference_data/sets/rest_api_samples_suspect_ips/' + ip_address, 'DELETE') response = client.call_api( 'reference_data/sets/rest_api_samples_suspect_ips/' + ip_address, 'DELETE') # The result of this processing is that there are some ip addresses now in # the blocked list. response = client.call_api( 'reference_data/sets/rest_api_samples_suspect_ips', 'GET') SampleUtilities.pretty_print_response(response) # The ip addresses that were not blocked are sill in the suspect list for # us to watch. response = client.call_api( 'reference_data/sets/rest_api_samples_blocked_ips', 'GET') SampleUtilities.pretty_print_response(response)
def main(): # Create our client. client = RestApiClient() # While using the REST API an error may occur. Information about # the error is returned to you in the HTTP response that you receive. # The HTTP code in the response can tell you a little bit about the error. # A code in the 400 range indicates that there was a problem with the # request. # A code in the 500 range indicates that there was a problem with the # server. # In addition to the response code, the response body contains information # about the error that occurred. # In this example we are trying to access the contents of a reference data # set that does not exist. try: SampleUtilities.pretty_print_request(client, 'referencedata/sets/rest_api_samples_does_not_exist', 'GET') response = client.call_api('referencedata/sets/rest_api_samples_does_not_exist', 'GET') except urllib.error.HTTPError as e: response = e SampleUtilities.pretty_print_response(response) # In this example we are passing a query parameter using the wrong name. try: SampleUtilities.pretty_print_request(client, 'referencedata/sets?wrong_name=fake', 'POST') response = client.call_api('referencedata/sets?wrong_name=fake', 'POST') except urllib.error.HTTPError as e: response = e SampleUtilities.pretty_print_response(response)
def main(): # Create our client and set up some sample data. client = RestApiClient() setup_data(client) current_time = int(time.time() *1000) # First lets have a look at the data in the system. response = client.call_api('referencedata/tables/rest_api_samples_server_access', 'GET') SampleUtilities.pretty_print_response(response) response = client.call_api('referencedata/tables/rest_api_samples_server_access', 'GET') response_body = json.loads(response.read().decode('utf-8')) data = response_body['data'] # Note that tables are stored sparsely, that is to say if a particular # cell is empty it does not exist in the table. However, our external # reporting tool can put appropriate defaults for these cells into the # report. print_custom_report(data) # Now our external system calculates which users should have their secure # access revoked. threshold = get_old_data_threshold(data) # check to see which users should have their secure access expired. for user in data: if ('Last_Secure_Login' in data[user]): if (data[user]['Last_Secure_Login']['lastSeen'] < threshold): print ("User '" + user + "' has not logged in to the secure server recently. Revoking their access.") outer_key = user if ('Authorization_Server_IP_Secure' in data[user]): inner_key = 'Authorization_Server_IP_Secure' value = data[user]['Authorization_Server_IP_Secure']['value'] response = client.call_api('referencedata/tables/rest_api_samples_server_access/' + outer_key + '/' + inner_key + '?value=' + value, 'DELETE') if ('Authorization_Server_PORT_Secure' in data[user]): inner_key = 'Authorization_Server_PORT_Secure' value = data[user]['Authorization_Server_PORT_Secure']['value'] response = client.call_api('referencedata/tables/rest_api_samples_server_access/' + outer_key + '/' + inner_key + '?value=' + value, 'DELETE') # now lets have a look at the data after we updated the table. response = client.call_api('referencedata/tables/rest_api_samples_server_access', 'GET') SampleUtilities.pretty_print_response(response) response = client.call_api('referencedata/tables/rest_api_samples_server_access', 'GET') response_body = json.loads(response.read().decode('utf-8')) data = response_body['data'] print_custom_report(data)
def main(): # Create our client and set up some sample data. client = RestApiClient(version="3.0") setup_data(client) # Using the '/sets/{name} endpoint with a GET request we can retrieve the # contents of our set of suspect addresses. SampleUtilities.pretty_print_request(client, "reference_data/sets/rest_api_samples_suspect_ips", "GET") response = client.call_api("reference_data/sets/rest_api_samples_suspect_ips", "GET") # Based on our business rules, this set should always exist. If it does not # exist it could be an indication that our security has been breached and # that an attack is in progress. We should raise an alarm. if response.code == 404: print("Something is wrong, a system administrator should investigate.") sys.exit(1) # Extract the reference set from the response body. response_body = json.loads(response.read().decode("utf-8")) data = response_body["data"] for element in data: # For each suspect ip address, pass it to our legacy system to # validate. If it is a real threat, move it to the blocked list so that # the configured rules can generate offenses if it is active on our # network. ip_address = element["value"] if legacy_system_logic(ip_address): SampleUtilities.pretty_print_request( client, "reference_data/sets/rest_api_samples_blocked_ips?value=" + ip_address, "POST" ) response = client.call_api("reference_data/sets/rest_api_samples_blocked_ips?value=" + ip_address, "POST") SampleUtilities.pretty_print_request( client, "reference_data/sets/rest_api_samples_suspect_ips/" + ip_address, "DELETE" ) response = client.call_api("reference_data/sets/rest_api_samples_suspect_ips/" + ip_address, "DELETE") # The result of this processing is that there are some ip addresses now in # the blocked list. response = client.call_api("reference_data/sets/rest_api_samples_suspect_ips", "GET") SampleUtilities.pretty_print_response(response) # The ip addresses that were not blocked are sill in the suspect list for # us to watch. response = client.call_api("reference_data/sets/rest_api_samples_blocked_ips", "GET") SampleUtilities.pretty_print_response(response)
def call_api(self, endpoint, method, headers=None, params=[], data=None, print_request=False): path = self.parse_path(endpoint, params) # If the caller specified customer headers merge them with the default # headers. actual_headers = self.headers.copy() if headers is not None: for header_key in headers: actual_headers[header_key] = headers[header_key] # Send the request and receive the response request = Request( 'https://' + self.server_ip + self.base_uri + path, headers=actual_headers) request.get_method = lambda: method # Print the request if print_request is True. if print_request: SampleUtilities.pretty_print_request(self, path, method, headers=actual_headers) try: response = urlopen(request, data) response_info = response.info() if 'Deprecated' in response_info: # This version of the API is Deprecated. Print a warning to # stderr. print("WARNING: " + response_info['Deprecated'], file=sys.stderr) # returns response object for opening url. return response except HTTPError as e: # an object which contains information similar to a request object return e except URLError as e: if (isinstance(e.reason, ssl.SSLError) and e.reason.reason == "CERTIFICATE_VERIFY_FAILED"): print("Certificate verification failed.") sys.exit(3) else: raise e
def setup_data(client): SampleUtilities.data_setup( client, 'reference_data/sets?name=rest_api_samples_suspect_ips&' + 'element_type=IP', 'POST') SampleUtilities.data_setup( client, 'reference_data/sets/rest_api_samples_suspect_ips?value=8.7.6.5', 'POST') SampleUtilities.data_setup( client, 'reference_data/sets/rest_api_samples_suspect_ips?value=10.7.6.5', 'POST') SampleUtilities.data_setup( client, 'reference_data/sets/rest_api_samples_suspect_ips?value=13.7.6.5', 'POST') SampleUtilities.data_setup( client, 'reference_data/sets?name=rest_api_samples_blocked_ips&' + 'element_type=IP', 'POST')
def main(): # First we have to create our client client = RestApiClient(version='3.0') # This example gives a demonstration of how to create a new closing reason # for your offenses. # First, check what closing reasons are already available to avoid # creating duplicates. Send in the GET request. SampleUtilities.pretty_print_request( client, 'siem/offense_closing_reasons', 'GET') response = client.call_api('siem/offense_closing_reasons', 'GET') # and output the response SampleUtilities.pretty_print_response(response) if (response.code != 200): print('Call Failed') sys.exit(1) # Double check that the user wants to create a new closing reason while True: confirmation = input('Are you sure you want to create a new ' + 'closing reason? (YES/no) ') if (confirmation == 'YES'): break elif (confirmation == 'no'): print('Not creating a new closing reason') exit(0) else: print(confirmation + 'is not a valid answer.') # Have the user input the text. quote it to retain special characters like # spaces. text = urllib.parse.quote( input('Please enter the text you want to put in the closing reason.\n') ) # Put through the request to add a closing reason with the text the user # entered as the reason SampleUtilities.pretty_print_request( client, 'siem/offense_closing_reasons?reason=' + text, 'POST') response = client.call_api('siem/offense_closing_reasons?reason=' + text, 'POST') SampleUtilities.pretty_print_response(response) if (response.code != 201): print('Call Failed') sys.exit(1) print('Closing reason added')
def main(): # Create our client. client = RestApiClient(version='3.0') # Using the /asset_model/properties endpoint with a GET request. SampleUtilities.pretty_print_request(client, 'asset_model/saved_searches', 'GET') response = client.call_api('asset_model/saved_searches', 'GET') # Verify that the call to the API was successful. if (response.code != 200): print('Failed to retrieve saved searches list.') SampleUtilities.pretty_print_response(response) sys.exit(1) # Find the number of saved searches retrieved. response_body = json.loads(response.read().decode('utf-8')) number_of_searches_retrieved = len(response_body) # Display number of searches, and the names of the searches retrieved. print(str(number_of_searches_retrieved) + ' searches were retrieved.\n') if (number_of_searches_retrieved > 0): print("Searching Assets...\n\n") for search in response_body: # Retrieve the saved search unique identifier. saved_search_id = str(search['id']) saved_search_name = str(search['name']) print('Running saved search : ' + saved_search_name) # Using the /asset_model/saved_searches/{saved_search_id}/results # endpoint with a GET request. search_endpoint_url = ('asset_model/saved_searches/' + saved_search_id + '/results') SampleUtilities.pretty_print_request(client, search_endpoint_url, 'GET') search_response = client.call_api(search_endpoint_url, 'GET') if(response.code != 200): print("Failed to search assets.") SampleUtilities.pretty_print_response(response) sys.exit(1) # Find the number of assets found search_response_body = json.loads(search_response.read(). decode('utf-8')) number_of_assets_found = len(search_response_body) # Display the number of assets retrieved. print(str(number_of_assets_found) + ' assets were retrieved.\n') print()
def setup_data(client): SampleUtilities.data_setup( client, 'reference_data/maps?name=rest_api_samples_current_admin_shift&' + 'element_type=ALN', 'POST') SampleUtilities.data_setup( client, 'reference_data/maps/rest_api_samples_current_admin_shift?' + 'key=7.34.87.23&value=sven', 'POST') SampleUtilities.data_setup( client, 'reference_data/maps/rest_api_samples_current_admin_shift?' + 'key=7.34.85.10&value=sven', 'POST') SampleUtilities.data_setup( client, 'reference_data/maps/rest_api_samples_current_admin_shift?' + 'key=7.34.123.8&value=jill', 'POST') SampleUtilities.data_setup( client, 'reference_data/maps/rest_api_samples_current_admin_shift?' + 'key=7.34.10.5&value=alice', 'POST')
def main(): # Create our client and set up some sample data. client = RestApiClient() setup_data(client) # Some endpoints accept body parameters. An example of this is the # /referencedata/sets/bulkLoad endpoint. # Body parameters may appear with path parameters, as in this case, but will # never appear with query parameters. # You must make sure that you set the content type correctly to a type # accepted by the endpoint. headers = client.get_headers().copy() headers['Content-type'] = 'application/json' body = b'["abc", "def", "123"]' # Send the request. SampleUtilities.pretty_print_request(client, 'referencedata/sets/bulkLoad/rest_api_samples_testset', 'POST', headers=headers) response = client.call_api('referencedata/sets/bulkLoad/rest_api_samples_testset', 'POST', headers=headers, data=body) SampleUtilities.pretty_print_response(response) # The response from the previous command only shows information about the # set, not the contents of the set. We can view the contents of the set with # this command: response = client.call_api('referencedata/sets/rest_api_samples_testset', 'GET') SampleUtilities.pretty_print_response(response)
def main(): # For the purpose of this sample, the reading in of credentials, the setup # of HTTP request headers, and the construction and sending of a request # object has been abstracted to the 'RestApiClient' class. # For more information on how these operations are done see the sample # '01_Authentication.py'. client = RestApiClient(version='3.0') # Many API endpoints accept parameters. # One type of parameter is a query parameter. # If an endpoint accepts query parameters they are passed after a '?' as # part of the URL. Each parameter has a name and a value separated by a # '='. Several parameters can be passed separated by '&' characters. SampleUtilities.pretty_print_request( client, 'reference_data/sets?name=rest_api_samples_testset&' + 'element_type=ALN', 'POST') response = client.call_api( 'reference_data/sets?name=rest_api_samples_testset&element_type=ALN', 'POST') # The response code for successfully creating a set is 201. if (response.code == 201): SampleUtilities.pretty_print_response(response) # The error code that occurs when attempting to create a set that already # exists is 409. elif (response.code == 409): print("Reference set already exists") response = client.call_api( 'reference_data/sets/rest_api_samples_testset', 'GET') SampleUtilities.pretty_print_response(response) elif (response.code >= 500): print( "An internal server error occurred. You should check your system.") SampleUtilities.pretty_print_response(response) else: print("Some other error has occurred:") SampleUtilities.pretty_print_response(response)
def main(): # Create our client and set up some sample data. client = RestApiClient(version='3.0') setup_data(client) # Here we have a look at the data in this map of sets. response = client.call_api( 'reference_data/map_of_sets/rest_api_samples_login_events', 'GET') SampleUtilities.pretty_print_response(response) # Retrieve the map of sets and load it into a JSON object. response = client.call_api( 'reference_data/map_of_sets/rest_api_samples_login_events', 'GET') response_body = json.loads(response.read().decode('utf-8')) # Capture the data portion of the map of sets. data = response_body['data'] # Also get the current time so that the CIO's dashboard can plot the # results over time. current_time = time.strftime('%Y-%m-%d %H:%M:%S') # We now empty the reference map of sets so that new data can start to # accumulate. We empty it now so that we don't miss new events if we have a # lot of data to process. Note that by using the purgeOnly parameter we are # only emptying the collection, not deleting it. print("Purging the collection so that new data can be collected.") response = client.call_api( 'reference_data/map_of_sets/rest_api_samples_login_events?' + 'purge_only=true', 'DELETE') SampleUtilities.pretty_print_response(response) # Go through the data, find the information we are interested in, and send # it to the CIO's dashboard. for key in data.keys(): number_of_elements = len(data[key]) send_data_to_dashboard(current_time, key, number_of_elements)
def main(): # First we have to create our client client = RestApiClient() # This example gives a demonstration of how to create a new closing reason for your # offenses. # First, check what closing reasons are already available to avoid creating duplicates # Send in the GET request SampleUtilities.pretty_print_request(client, 'siem/offense_closing_reasons', 'GET') response = client.call_api('siem/offense_closing_reasons', 'GET') # and output the response SampleUtilities.pretty_print_response(response) if (response.code != 200): print('Call Failed') sys.exit(1) # Double check that the user wants to create a new closing reason while True: confirmation = input('Are you sure you want to create a new closing reason? (YES/no) ') if (confirmation == 'YES'): break elif (confirmation == 'no'): print('Not creating a new closing reason') exit(0) else: print(confirmation + 'is not a valid answer.') # Have the user input the text. quote it to retain special characters like spaces. text = urllib.parse.quote(input('Please enter the text you want to put in the closing reason.\n')) # Put through the request to add a closing reason with the text the user entered as the reason SampleUtilities.pretty_print_request(client, 'siem/offense_closing_reasons?reason=' + text, 'POST') response = client.call_api('siem/offense_closing_reasons?reason=' + text, 'POST') SampleUtilities.pretty_print_response(response) if (response.code != 201): print('Call Failed') sys.exit(1) print('Closing reason added')
def main(): # Create our client. client = RestApiClient(version='3.0') # While using the REST API an error may occur. Information about # the error is returned to you in the HTTP response that you receive. # The HTTP code in the response can tell you a little bit about the error. # A code in the 400 range indicates that there was a problem with the # request. # A code in the 500 range indicates that there was a problem with the # server. # In addition to the response code, the response body contains information # about the error that occurred. # In this example we are trying to access the contents of a reference data # set that does not exist. try: SampleUtilities.pretty_print_request( client, 'reference_data/sets/rest_api_samples_does_not_exist', 'GET') response = client.call_api( 'reference_data/sets/rest_api_samples_does_not_exist', 'GET') except urllib.error.HTTPError as e: response = e SampleUtilities.pretty_print_response(response) # In this example we are passing a query parameter using the wrong name. try: SampleUtilities.pretty_print_request( client, 'reference_data/sets?wrong_name=fake', 'POST') response = client.call_api('reference_data/sets?wrong_name=fake', 'POST') except urllib.error.HTTPError as e: response = e SampleUtilities.pretty_print_response(response)
def main(): # First we have to create our client client = RestApiClient(version="3.0") # This example gives a demonstration of how to create a new closing reason # for your offenses. # First, check what closing reasons are already available to avoid # creating duplicates. Send in the GET request. SampleUtilities.pretty_print_request(client, "siem/offense_closing_reasons", "GET") response = client.call_api("siem/offense_closing_reasons", "GET") # and output the response SampleUtilities.pretty_print_response(response) if response.code != 200: print("Call Failed") sys.exit(1) # Double check that the user wants to create a new closing reason while True: confirmation = input("Are you sure you want to create a new " + "closing reason? (YES/no) ") if confirmation == "YES": break elif confirmation == "no": print("Not creating a new closing reason") exit(0) else: print(confirmation + "is not a valid answer.") # Have the user input the text. text = input("Please enter the text you want to put in the closing reason.\n") # Put through the request to add a closing reason with the text the user # entered as the reason params = {"reason": text} response = client.call_api("siem/offense_closing_reasons", "POST", params=params, print_request=True) SampleUtilities.pretty_print_response(response) if response.code != 201: print("Call Failed") sys.exit(1) print("Closing reason added")
def main(): # Create our client and set up some sample data. client = RestApiClient(version='3.0') setup_data(client) # First lets see who is on duty now. print("These administrators are on duty during the first shift:") response = client.call_api( 'reference_data/maps/rest_api_samples_current_admin_shift', 'GET') SampleUtilities.pretty_print_response(response) # # Change to the second shift as scheduled by our HR system. # Get the current shift. response = client.call_api( 'reference_data/maps/rest_api_samples_current_admin_shift', 'GET') response_body = json.loads(response.read().decode('utf-8')) data = response_body['data'] # Change to the second shift. print("Changing to the second shift:") update_reference_map(get_second_shift_schedule_from_hr(), data, client) # Show that the change has happened. response = client.call_api( 'reference_data/maps/rest_api_samples_current_admin_shift', 'GET') SampleUtilities.pretty_print_response(response) # # Change to the third shift as scheduled by our HR system. # Get the current shift. response = client.call_api( 'reference_data/maps/rest_api_samples_current_admin_shift', 'GET') response_body = json.loads(response.read().decode('utf-8')) data = response_body['data'] # Change to the third shift. print("Changing to the third shift:") update_reference_map(get_third_shift_schedule_from_hr(), data, client) # Show that the change has happened. response = client.call_api( 'reference_data/maps/rest_api_samples_current_admin_shift', 'GET') SampleUtilities.pretty_print_response(response)
def main(): # Create our client and set up some sample data. client = RestApiClient(version='3.0') setup_data(client) # Some endpoints accept body parameters. An example of this is the # /reference_data/sets/bulk_load endpoint. # Body parameters may appear with path parameters, as in this case, but # will never appear with query parameters. # You must make sure that you set the content type correctly to a type # accepted by the endpoint. headers = client.get_headers().copy() headers['Content-type'] = 'application/json' body = b'["abc", "def", "123"]' # Send the request. SampleUtilities.pretty_print_request( client, 'reference_data/sets/bulk_load/rest_api_samples_testset', 'POST', headers=headers) response = client.call_api( 'reference_data/sets/bulk_load/rest_api_samples_testset', 'POST', headers=headers, data=body) SampleUtilities.pretty_print_response(response) # The response from the previous command only shows information about the # set, not the contents of the set. We can view the contents of the set # with this command: response = client.call_api('reference_data/sets/rest_api_samples_testset', 'GET') SampleUtilities.pretty_print_response(response)
def setup_data(client): SampleUtilities.data_setup( client, 'reference_data/sets?name=rest_api_samples_testset&' + 'element_type=ALN', 'POST')
def main(): # First we have to create our client client = RestApiClient(version='3.0') # Send in the request to GET all the OPEN offenses, but only showing some # of the fields, enough to distinguish the offenses. SampleUtilities.pretty_print_request( client, 'siem/offenses?fields=id,description,status,offense_type,' + 'offense_source&filter=status=OPEN', 'GET') response = client.call_api( 'siem/offenses?fields=id,description,status,offense_type,' + 'offense_source&filter=status=OPEN', 'GET') # Print out the result SampleUtilities.pretty_print_response(response) if (response.code != 200): print('Call Failed') sys.exit(1) # Prompt the user for an ID offense_ID = input( 'Select an offense to hide. Please type its ID or quit. ') # Error checking because we want to make sure the user has selected an OPEN # offense. while True: if (offense_ID == 'quit'): exit(0) # Make the request to 'GET' the offense chosen by the user SampleUtilities.pretty_print_request( client, 'siem/offenses/' + str(offense_ID), 'GET') response = client.call_api('siem/offenses/' + str(offense_ID), 'GET') # Save a copy of the data, decoding it into a string so that # we can read it response_text = response.read().decode('utf-8') # Check response code to see if the offense exists if (response.code == 200): # Reformat the data string into a dictionary so that we # easily access the information. response_body = json.loads(response_text) # Ensure the offense is OPEN if (response_body['status'] != 'OPEN'): offense_ID = input('The offense you selected is not OPEN. ' + 'Please try again or type quit. ') else: # Only breaks when the ID exists and is OPEN break else: offense_ID = input('An offense by that ID does not exist. ' + 'Please try again or type quit. ') # Prints the response, which has already been decoded. # **Only works on responses that have been decoded** print(json.dumps(response_body, indent=4)) while True: # As this sample uses data on your system, ensure that the user wants # to hide the offense. confirmation = input( 'Are you sure you want to hide this offense? ' + 'This will affect the status of the offense. (YES/no)\n') if (confirmation == 'YES'): # Sends in the POST request to update the offense. Also using # fields to trim down the data received by POST. SampleUtilities.pretty_print_request( client, 'siem/offenses/' + offense_ID + '?status=HIDDEN&fields=id,description,status,' + 'offense_type,offense_source', 'POST') response = client.call_api( 'siem/offenses/' + offense_ID + '?status=HIDDEN' + '&fields=id,description,status,offense_type,offense_source', 'POST') # Prints the data received by POST SampleUtilities.pretty_print_response(response) if (response.code != 200): print('Call Failed') SampleUtilities.pretty_print_response(response) sys.exit(1) print('Offense ' + offense_ID + ' hidden') break elif (confirmation == 'no'): print('You have decided not to hide offense ' + offense_ID + '. This sample will now end.') break else: print(confirmation + ' is not a valid response.')
def setup_data(client): SampleUtilities.data_setup(client, 'reference_data/sets?name=rest_api_samples_authorized_users&element_type=ALN', 'POST') SampleUtilities.data_setup(client, 'reference_data/sets/rest_api_samples_authorized_users?value=dave', 'POST') SampleUtilities.data_setup(client, 'reference_data/sets?name=rest_api_samples_authorized_ips&element_type=IP', 'POST') SampleUtilities.data_setup(client, 'reference_data/sets?name=rest_api_samples_keywords&element_type=ALNIC', 'POST') SampleUtilities.data_setup(client, 'reference_data/sets/rest_api_samples_keywords?value=sample', 'POST') SampleUtilities.data_setup(client, 'reference_data/sets?name=rest_api_samples_authorized_ports&element_type=PORT', 'POST') SampleUtilities.data_setup(client, 'reference_data/sets?name=rest_api_samples_recent_access&element_type=DATE', 'POST')
def main(): # First we have to create our client client = RestApiClient() # Request the API call only taking a few fields SampleUtilities.pretty_print_request(client, 'siem/offenses?fields=id,description,' + 'status,offense_type,offense_source', 'GET') response = client.call_api('siem/offenses?fields=id,description,status,offense_type,offense_source', 'GET') # Print out the result for the user to see SampleUtilities.pretty_print_response(response) # Prompt the user for an ID offense_ID = input('Select an offense to post a note to. Please type its ID or quit. ') # Error checking because we want to make sure the user has selected an offense that exists. while True: if (offense_ID == 'quit'): exit(0) # Make the request to 'GET' the offense chosen by the user SampleUtilities.pretty_print_request(client, 'siem/offenses/' + str(offense_ID), 'GET') response = client.call_api('siem/offenses/' + str(offense_ID), 'GET') # Check response code to see if the offense exists if (response.code == 200): break else: offense_ID = input('An offense by that ID does not exist. Please try again or type quit. ') # Print out the offense the user chose SampleUtilities.pretty_print_response(response) # Send in the API Call request for the offense's notes SampleUtilities.pretty_print_request(client, 'siem/offenses/' + str(offense_ID) + '/notes', 'GET') response = client.call_api('siem/offenses/' + str(offense_ID) + '/notes', 'GET') # Display all the notes on the offense SampleUtilities.pretty_print_response(response) # Confirm that the user wants to make a new note for the offense. We have to check this since it will # permanently add that note to the offense. confirmation = input('Would you like to make a new note for offense ' + str(offense_ID) + '? (YES/no)\n') if (confirmation != 'YES'): print('You have chosen not to post a new note. Exiting sample.') exit(0) # Take in the text for the note. Since the note could be multiple words, and the API calls through a # url, we are using urllib.parse.quote to preserve the spaces and special characters in the note. text = urllib.parse.quote(input('Please enter the content of the note.\n')) # Send in the request for the new note to be put on the offense. SampleUtilities.pretty_print_request(client, 'siem/offenses/' + offense_ID + '/notes?note_text=' + text, 'POST') response = client.call_api('siem/offenses/' + offense_ID + '/notes?note_text=' + text, 'POST') #Display to the user the new note to confirm that it has been created properly. SampleUtilities.pretty_print_response(response)
def setup_data(client): SampleUtilities.data_setup(client, 'referencedata/sets?name=rest_api_samples_testset&elementType=ALN', 'POST')
def setup_data(client): current_time = int(time.time() * 1000) key_name_types = urllib.parse.quote( "[{\"element_type\": \"IP\", " + "\"key_name\": \"Authorization_Server_IP_Secure\"}, " + "{\"element_type\": \"PORT\", " + "\"key_name\": \"Authorization_Server_PORT_Secure\"}, " + "{\"element_type\": \"DATE\", \"key_name\": \"Last_Secure_Login\"}, " + "{\"element_type\": \"IP\", " + "\"key_name\": \"Authorization_Server_IP_General\"}]") SampleUtilities.data_setup( client, 'reference_data/tables?name=rest_api_samples_server_access&' + 'element_type=ALN&key_name_types=' + key_name_types, 'POST') SampleUtilities.data_setup( client, 'reference_data/tables/rest_api_samples_server_access?' + 'outer_key=calvin&inner_key=Authorization_Server_IP_Secure&' + 'value=6.3.9.12', 'POST') SampleUtilities.data_setup( client, 'reference_data/tables/rest_api_samples_server_access?' + 'outer_key=calvin&inner_key=Authorization_Server_PORT_Secure&' + 'value=443', 'POST') SampleUtilities.data_setup( client, 'reference_data/tables/rest_api_samples_server_access?' + 'outer_key=calvin&inner_key=Authorization_Server_IP_General&' + 'value=7.12.15.12', 'POST') SampleUtilities.data_setup( client, 'reference_data/tables/rest_api_samples_server_access?' + 'outer_key=calvin&inner_key=Last_Secure_Login&value=' + str(current_time), 'POST') SampleUtilities.data_setup( client, 'reference_data/tables/rest_api_samples_server_access?' + 'outer_key=socrates&inner_key=Authorization_Server_IP_General&' + 'value=7.12.14.85', 'POST') time.sleep(1) SampleUtilities.data_setup( client, 'reference_data/tables/rest_api_samples_server_access?' + 'outer_key=mill&inner_key=Authorization_Server_IP_Secure&' + 'value=6.3.9.12', 'POST') SampleUtilities.data_setup( client, 'reference_data/tables/rest_api_samples_server_access?' + 'outer_key=mill&inner_key=Authorization_Server_PORT_Secure&value=443', 'POST') SampleUtilities.data_setup( client, 'reference_data/tables/rest_api_samples_server_access?' + 'outer_key=mill&inner_key=Last_Secure_Login&value=' + str(current_time), 'POST') SampleUtilities.data_setup( client, 'reference_data/tables/rest_api_samples_server_access?' + 'outer_key=mill&inner_key=Authorization_Server_IP_General&' + 'value=7.13.22.85', 'POST') SampleUtilities.data_setup( client, 'reference_data/tables/rest_api_samples_server_access?' + 'outer_key=hobbes&inner_key=Authorization_Server_IP_Secure&' + 'value=6.3.9.12', 'POST') SampleUtilities.data_setup( client, 'reference_data/tables/rest_api_samples_server_access?' + 'outer_key=hobbes&inner_key=Authorization_Server_PORT_Secure&value=22', 'POST') SampleUtilities.data_setup( client, 'reference_data/tables/rest_api_samples_server_access?' + 'outer_key=hobbes&inner_key=Last_Secure_Login&value=' + str(current_time), 'POST') SampleUtilities.data_setup( client, 'reference_data/tables/rest_api_samples_server_access?' + 'outer_key=hobbes&inner_key=Authorization_Server_IP_General&' + 'value=7.12.19.125', 'POST') SampleUtilities.data_setup( client, 'reference_data/tables/rest_api_samples_server_access?' + 'outer_key=aquinas&inner_key=Last_Secure_Login&value=' + str(current_time - 1000000), 'POST') SampleUtilities.data_setup( client, 'reference_data/tables/rest_api_samples_server_access?' + 'outer_key=aquinas&inner_key=Authorization_Server_IP_General&' + 'value=7.12.15.12', 'POST')
def main(): # Create our client and set up some sample data. client = RestApiClient(version='3.0') setup_data(client) # First lets have a look at the data in the system. response = client.call_api( 'reference_data/tables/rest_api_samples_server_access', 'GET') SampleUtilities.pretty_print_response(response) response = client.call_api( 'reference_data/tables/rest_api_samples_server_access', 'GET') response_body = json.loads(response.read().decode('utf-8')) data = response_body['data'] # Note that tables are stored sparsely, that is to say if a particular # cell is empty it does not exist in the table. However, our external # reporting tool can put appropriate defaults for these cells into the # report. print_custom_report(data) # Now our external system calculates which users should have their secure # access revoked. threshold = get_old_data_threshold(data) # check to see which users should have their secure access expired. for user in data: if ('Last_Secure_Login' in data[user]): if (data[user]['Last_Secure_Login']['last_seen'] < threshold): print("User '" + user + "' has not logged in to the secure server recently. " + "Revoking their access.") outer_key = user if ('Authorization_Server_IP_Secure' in data[user]): inner_key = 'Authorization_Server_IP_Secure' value = ( data[user]['Authorization_Server_IP_Secure']['value']) response = client.call_api( 'reference_data/tables/rest_api_samples_server_' + 'access/' + outer_key + '/' + inner_key + '?value=' + value, 'DELETE') if ('Authorization_Server_PORT_Secure' in data[user]): inner_key = 'Authorization_Server_PORT_Secure' value = (data[user]['Authorization_Server_PORT_Secure'] ['value']) response = client.call_api( 'reference_data/tables/rest_api_samples_server_' + 'access/' + outer_key + '/' + inner_key + '?value=' + value, 'DELETE') # now lets have a look at the data after we updated the table. response = client.call_api( 'reference_data/tables/rest_api_samples_server_access', 'GET') SampleUtilities.pretty_print_response(response) response = client.call_api( 'reference_data/tables/rest_api_samples_server_access', 'GET') response_body = json.loads(response.read().decode('utf-8')) data = response_body['data'] print_custom_report(data)
def setup_data(client): SampleUtilities.data_setup( client, 'reference_data/map_of_sets?name=rest_api_samples_login_events&' + 'element_type=ALN', 'POST') SampleUtilities.data_setup( client, 'reference_data/map_of_sets/rest_api_samples_login_events?' + 'key=3.4.5.6&value=bob', 'POST') SampleUtilities.data_setup( client, 'reference_data/map_of_sets/rest_api_samples_login_events?' + 'key=3.4.5.6&value=frank', 'POST') SampleUtilities.data_setup( client, 'reference_data/map_of_sets/rest_api_samples_login_events?' + 'key=3.4.5.6&value=jane', 'POST') SampleUtilities.data_setup( client, 'reference_data/map_of_sets/rest_api_samples_login_events?' + 'key=2.12.42.7&value=kim', 'POST') SampleUtilities.data_setup( client, 'reference_data/map_of_sets/rest_api_samples_login_events?' + 'key=2.12.42.7&value=serge', 'POST') SampleUtilities.data_setup( client, 'reference_data/map_of_sets/rest_api_samples_login_events?' + 'key=2.12.42.7&value=sue', 'POST') SampleUtilities.data_setup( client, 'reference_data/map_of_sets/rest_api_samples_login_events?' + 'key=2.12.42.7&value=rick', 'POST')
def main(): # First we have to create our client client = RestApiClient() # Send in the request to GET all the OPEN offenses, but only showing some of # the fields, enough to distinguish the offenses. SampleUtilities.pretty_print_request(client, 'siem/offenses?fields=id,description,' + 'status,offense_type,offense_source&filter=status=OPEN', 'GET') response = client.call_api('siem/offenses?fields=id,description,status,offense_type,offense_source' + '&filter=status=OPEN', 'GET') # Print out the result SampleUtilities.pretty_print_response(response) # Prompt the user for an ID offense_ID = input('Select an offense to hide. Please type its ID or quit. ') # Error checking because we want to make sure the user has selected an OPEN offense. while True: if (offense_ID == 'quit'): exit(0) # Make the request to 'GET' the offense chosen by the user SampleUtilities.pretty_print_request(client, 'siem/offenses/' + str(offense_ID), 'GET') response = client.call_api('siem/offenses/' + str(offense_ID), 'GET') # Save a copy of the data, decoding it into a string so that # we can read it response_text = response.read().decode('utf-8') # Check response code to see if the offense exists if (response.code == 200): # Reformat the data string into a dictionary so that we # easily access the information. response_body = json.loads(response_text) # Ensure the offense is OPEN if (response_body['status'] != 'OPEN'): offense_ID = input('The offense you selected is not OPEN. Please try again or type quit. ') else: # Only breaks when the ID exists and is OPEN break else: offense_ID = input('An offense by that ID does not exist. Please try again or type quit. ') # Prints the response, which has already been decoded. #**Only works on responses that have been decoded** print(json.dumps(response_body, indent=4)) # As this sample uses data on your system, ensure that the user wants to hide the offense. confirmation = input('Are you sure you want to hide this offense? ' + 'This will affect the status of the offense. (YES/no)\n') if (confirmation == 'YES'): #Sends in the request to update the offense SampleUtilities.pretty_print_request(client, 'siem/offenses/' + offense_ID + '?status=HIDDEN', 'POST') response = client.call_api('siem/offenses/' + offense_ID + '?status=HIDDEN', 'POST') print('Offense ' + offense_ID + ' hidden') else: print('You have decided not to hide offense ' + offense_ID +'. This sample will now end.')
def setup_data(client): SampleUtilities.data_setup( client, 'reference_data/sets?name=rest_api_samples_authorized_users&' + 'element_type=ALN', 'POST') SampleUtilities.data_setup( client, 'reference_data/sets/rest_api_samples_authorized_users?value=dave', 'POST') SampleUtilities.data_setup( client, 'reference_data/sets?name=rest_api_samples_authorized_ips&' + 'element_type=IP', 'POST') SampleUtilities.data_setup( client, 'reference_data/sets?name=rest_api_samples_keywords&' + 'element_type=ALNIC', 'POST') SampleUtilities.data_setup( client, 'reference_data/sets/rest_api_samples_keywords?value=sample', 'POST') SampleUtilities.data_setup( client, 'reference_data/sets?name=rest_api_samples_authorized_ports&' + 'element_type=PORT', 'POST') SampleUtilities.data_setup( client, 'reference_data/sets?name=rest_api_samples_recent_access&' + 'element_type=DATE', 'POST')
def main(): # Create our client and set up some sample data. client = RestApiClient(version='3.0') setup_data(client) # First lets have a look at the data in this reference set SampleUtilities.pretty_print_request(client, 'reference_data/sets', 'GET') response = client.call_api('reference_data/sets', 'GET') SampleUtilities.pretty_print_response(response) # Suppose we are only interested in the names and the size of each set. We # can restrict the data we get back with a 'fields' parameter. fields = 'fields=' + urllib.parse.quote('name,number_of_elements') SampleUtilities.pretty_print_request(client, 'reference_data/sets?' + fields, 'GET') response = client.call_api('reference_data/sets?' + fields, 'GET') SampleUtilities.pretty_print_response(response) # If this set contained a large amount of data, we might want to process it # a little bit at a time. To get back only part of the data we can use a # 'Range' header. # Note that the range header is indexed form zero, so here we are asking # for the first 5 items. range_header = {'Range': 'items=0-4'} SampleUtilities.pretty_print_request(client, 'reference_data/sets', 'GET', headers=range_header) response = client.call_api('reference_data/sets', 'GET', headers=range_header) response_headers = response.info() SampleUtilities.pretty_print_response(response) # Note that there is a header in the response that contains information # about the portion of the data that you requested. # the 'Content-Range' header tells you which items you got back and how # many items are in the whole list. print('Content-Range header value: ' + response_headers['Content-Range']) parsed_range_header = response_headers['Content-Range'].split('/') print('This tells us which items we got back: ' + parsed_range_header[0]) print('This tells us how many items there are in total: ' + parsed_range_header[1]) # We can use this information to get back the data one page at a time current_position = 5 while (current_position < int(parsed_range_header[1])): range_string = ('items=' + str(current_position) + '-' + str(current_position + 4)) range_header = {'Range': range_string} SampleUtilities.pretty_print_request(client, 'reference_data/sets', 'GET', headers=range_header) response = client.call_api('reference_data/sets', 'GET', headers=range_header) print((response.info())['Content-Range']) SampleUtilities.pretty_print_response(response) current_position = current_position + 5 # Now suppose that we want to find a specific set that contains data we are # interested in. We can use the filter parameter to do this. # Some sets were added during the setup of this sample script. Lets find # them. filter_string = 'filter=' + urllib.parse.quote( 'name between rest_api_samples and rest_api_samplet') SampleUtilities.pretty_print_request( client, 'reference_data/sets?' + filter_string, 'GET') response = client.call_api('reference_data/sets?' + filter_string, 'GET') SampleUtilities.pretty_print_response(response) # Only some of these sets contain data. filter_string = 'filter=' + urllib.parse.quote( 'name between rest_api_samples and rest_api_samplet and ' + 'number_of_elements>0') SampleUtilities.pretty_print_request( client, 'reference_data/sets?' + filter_string, 'GET') response = client.call_api('reference_data/sets?' + filter_string, 'GET') SampleUtilities.pretty_print_response(response) response = client.call_api('reference_data/sets?' + filter_string, 'GET') parsed_response = json.loads(response.read().decode('utf-8')) for ref_data_set in parsed_response: print('The sample reference set ' + ref_data_set['name'] + ' contains data') # the filter parameter supports: # and, or, and not logical operators as well as brackets to specify # precedence. # =, >, <, >=, <=, !=, in, between, is null comparisons. # Refer to your product documentation for more information about using # filters. # You can combine fields, filters, and the range parameter to have precise # control over the data you get back from the API. filter_string = 'filter=' + urllib.parse.quote( 'name between rest_api_samples and rest_api_samplet') range_header = {'Range': 'items=0-1'} fields = 'fields=' + urllib.parse.quote('name') # Here we are asking for only the names of the top two reference sets that # were added by this sample script. SampleUtilities.pretty_print_request(client, 'reference_data/sets?' + filter_string + '&' + fields, 'GET', headers=range_header) response = client.call_api('reference_data/sets?' + filter_string + '&' + fields, 'GET', headers=range_header) SampleUtilities.pretty_print_response(response)
def main(): # First we have to create our client client = RestApiClient(version='3.0') # In this half of the sample, we will show one way to use a csv file and # turn it into a dictionary. Then using that dictionary, and information on # the offenses, assign each unclosed offense to the correct person. # Read your raw string file_name = 'assignment_data.csv' file_in = open(file_name, 'r') # Break it into a list of lines file_data = file_in.read().splitlines() # This is the array of dictionaries we're going to be using to store the # data assignment_data = [] # Iterate through each line, and taking each word separately organize them # in a dictionary for later use and put the dictionary into a list of # similar dictionaries. for data in file_data: data = data.split(',') tmp_dict = {} # Assign the offense to 'name' tmp_dict['name'] = data[0] # Given the 'destination_network' tmp_dict['destination_network'] = data[1] # And it should be resolved by 'days_to_resolve' days later tmp_dict['days_to_resolve'] = data[2] assignment_data.append(tmp_dict) # Display the new list of dictionaries print(json.dumps(assignment_data, indent=4)) # Now that we have our rules set out for how to deal with offenses, we need # to GET the offenses. The only offenses we need to assign to people are # those that aren't CLOSED and aren't already assigned to someone. params = {'filter': 'status != CLOSED', 'fields': 'id,description,magnitude,destination_networks,' 'assigned_to'} response = client.call_api('siem/offenses', 'GET', params=params, print_request=True) # Ensure the call didn't fail for some reason. if (response.code != 200): print( 'An error occured trying to get a list of offenses on the system.') SampleUtilities.pretty_print_response(response) exit(1) # Decode the offenses we just received from the API call and print them # out for the user to see. offense_list = json.loads(response.read().decode('utf-8')) print(json.dumps(offense_list, indent=4)) # Check if the user really wants to proceed, as changes will be made to the # offenses while True: confirmation = input( 'This sample is about to assign offenses to users as specified' ' by assignment_data.csv. Are you sure you want to proceed?' ' (YES/no) ') if (confirmation == 'YES'): break elif (confirmation == 'no'): print('You have chosen not to proceed with assigning offenses.') exit(0) else: print(confirmation + ' is not a valid answer.') # If there aren't any offenses, don't assign anything. if (len(offense_list) == 0): print('No offenses to assign') # If there ARE offenses... else: # Create a list of just the destination networks for quick access. It's # important that the new list is in the same order as the original assignment_networks = list(map(lambda assignment: assignment['destination_network'], assignment_data)) # Now go through all the offenses for offense in offense_list: # A flag variable to show if the current offense has been assigned # to anybody yet. assigned = False # Now we take a look at all the destination_networks for target_ip in offense['destination_networks']: if target_ip in assignment_networks: # Once we match a destination_network to one of the # networks specified by our assignment rules, we need to # find which rule, or line in the csv file, made a match # with this current offense's destination_network index = assignment_networks.index(target_ip) # Once we know which rule matched with the # destination_network, we can send in a POST call to update # the offense's assigned_to variable, and by doing that # assign the offense to the correct user. params = {'assigned_to': assignment_data[index]['name']} response = client.call_api( 'siem/offenses/' + str(offense['id']), 'POST', params=params) # Check the response code if (response.code == 200): print('Offense ' + str(offense['id']) + ' (destination network: ' + target_ip + ') has been assigned to ' + assignment_data[index]['name'] + '.') # If the offense was assigned properly, flip the flag assigned = True else: print('There was an error when assigning offense ' + str(offense['id'])) SampleUtilities.pretty_print_response(response) break # If the offense didn't make any matches in the # assignment_networks, or there was a problem calling the API, # display a special message. if (not assigned): print('Offense ' + str(offense['id']) + ' could not ' 'be assigned because there is no valid user associated ' 'with destination networks ' + str(offense['destination_networks']) + '.') # Now that offenses have been assigned, we want to go through all of the # offenses that aren't closed and ARE assigned to people. Since we want # offenses to be closed within a certain time, we're going to be checking # that. # Send in the GET request params = {'filter': 'status != CLOSED and assigned_to is not null', 'fields': 'id,description,start_time,destination_networks,' 'assigned_to'} response = client.call_api('siem/offenses', 'GET', params=params, print_request=True) # Check the response code for errors if (response.code != 200): print( 'An error occured trying to get a list of offenses on the system.') SampleUtilities.pretty_print_response(response) exit(1) # Decode the response offense_list = json.loads(response.read().decode('utf-8')) # This loop is structurally similar to the one above if (len(offense_list) == 0): print('No offenses assigned') else: # Create two new maps of assignment_data, one with the # destination_networks and one with the names for quick access, since # both of these are necessary assignment_networks = list(map(lambda assignment: assignment['destination_network'], assignment_data)) assignment_names = list( map(lambda name: name['name'], assignment_data)) for offense in offense_list: # A flag variable to check if the offense has already existed # longer than the days_to_resolve late = False # A flag variable to check if the offense was assigned to a user in # assignment_data.csv match = False for target_ip in offense['destination_networks']: # Check the target_ip and the name of the user the offense was # assigned to. if ((target_ip in assignment_networks) and (offense['assigned_to'] == assignment_names[ assignment_networks.index(target_ip)])): # Trigger the flag to say this offense has been matched to # a user-network pair in the assignment data match = True index = assignment_networks.index(target_ip) # Get the current datetime and calculate the datetime for # when the offense was created. We use these datetimes to # calculate how long it's been since the offense was # created. Divide start_time by 1000 since start_time is in # milliseconds. current_date = datetime.datetime.utcnow() assignment_date = datetime.datetime.utcfromtimestamp( offense['start_time']/1000) elapsed_time = (current_date - assignment_date).days # If the offense has existed longer than days_to_resolve, # display an urgent message. Instead of displaying an # urgent message, any number of things could be done. For # example, if you include an email in the data file, then # in this situation you could email the user responsible # for the offense directly. if elapsed_time > int( assignment_data[index]['days_to_resolve']): print('Notify ' + assignment_names[index] + ', ' + 'offense ' + str(offense['id']) + ' must be closed immediately.') # Trigger the flag to say this offense is late late = True break # If it wasn't already late, and it was matched with an destination # network and user in assignment_data.csv display a message just to # indicate how long the offense has before it's late. if (not late and match): print('Please close offense ' + str(offense['id']) + ' within ' + str(int(assignment_data[index] ['days_to_resolve']) - elapsed_time) + ' days!')
def main(): # First we have to create our client client = RestApiClient(version='3.0') # In this half of the sample, we will show one way to use a csv file and # turn it into a dictionary. Then using that dictionary, and information on # the offenses, assign each unclosed offense to the correct person. # Read your raw string file_name = 'assignment_data.csv' file_in = open(file_name, 'r') # Break it into a list of lines file_data = file_in.read().splitlines() # This is the array of dictionaries we're going to be using to store the # data assignment_data = [] # Iterate through each line, and taking each word separately organize them # in a dictionary for later use and put the dictionary into a list of # similar dictionaries. for data in file_data: data = data.split(',') tmp_dict = {} # Assign the offense to 'name' tmp_dict['name'] = data[0] # Given the 'destination_network' tmp_dict['destination_network'] = data[1] # And it should be resolved by 'days_to_resolve' days later tmp_dict['days_to_resolve'] = data[2] assignment_data.append(tmp_dict) # Display the new list of dictionaries print(json.dumps(assignment_data, indent=4)) # Now that we have our rules set out for how to deal with offenses, we need # to GET the offenses. The only offenses we need to assign to people are # those that aren't CLOSED and aren't already assigned to someone. search = urllib.parse.quote('siem/offenses?filter=status!=CLOSED' '&fields=id,description,' 'magnitude,destination_networks,assigned_to') # Call the API to GET the offenses SampleUtilities.pretty_print_request(client, search, 'GET') response = client.call_api(search, 'GET') # Ensure the call didn't fail for some reason. if (response.code != 200): print( 'An error occured trying to get a list of offenses on the system.') SampleUtilities.pretty_print_response(response) exit(1) # Decode the offenses we just received from the API call and print them # out for the user to see. offense_list = json.loads(response.read().decode('utf-8')) print(json.dumps(offense_list, indent=4)) # Check if the user really wants to proceed, as changes will be made to the # offenses while True: confirmation = input( 'This sample is about to assign offenses to users as specified' ' by assignment_data.csv. Are you sure you want to proceed?' ' (YES/no) ') if (confirmation == 'YES'): break elif (confirmation == 'no'): print('You have chosen not to proceed with assigning offenses.') exit(0) else: print(confirmation + ' is not a valid answer.') # If there aren't any offenses, don't assign anything. if (len(offense_list) == 0): print('No offenses to assign') # If there ARE offenses... else: # Create a list of just the destination networks for quick access. It's # important that the new list is in the same order as the original assignment_networks = list( map(lambda assignment: assignment['destination_network'], assignment_data)) # Now go through all the offenses for offense in offense_list: # A flag variable to show if the current offense has been assigned # to anybody yet. assigned = False # Now we take a look at all the destination_networks for target_ip in offense['destination_networks']: if target_ip in assignment_networks: # Once we match a destination_network to one of the # networks specified by our assignment rules, we need to # find which rule, or line in the csv file, made a match # with this current offense's destination_network index = assignment_networks.index(target_ip) # Once we know which rule matched with the # destination_network, we can send in a POST call to update # the offense's assigned_to variable, and by doing that # assign the offense to the correct user. update_request = urllib.parse.quote( 'siem/offenses/' + str(offense['id']) + '?assigned_to=' + assignment_data[index]['name']) response = client.call_api(update_request, 'POST') # Check the response code if (response.code == 200): print('Offense ' + str(offense['id']) + ' (destination network: ' + target_ip + ') has been assigned to ' + assignment_data[index]['name'] + '.') # If the offense was assigned properly, flip the flag assigned = True else: print('There was an error when assigning offense ' + str(offense['id'])) SampleUtilities.pretty_print_response(response) break # If the offense didn't make any matches in the # assignment_networks, or there was a problem calling the API, # display a special message. if (not assigned): print('Offense ' + str(offense['id']) + ' could not ' 'be assigned because there is no valid user associated ' 'with destination networks ' + str(offense['destination_networks']) + '.') # Now that offenses have been assigned, we want to go through all of the # offenses that aren't closed and ARE assigned to people. Since we want # offenses to be closed within a certain time, we're going to be checking # that. # Send in the GET request search = urllib.parse.quote( 'siem/offenses?filter=status!=CLOSED and assigned_to is not null&' 'fields=id,description,start_time,destination_networks,assigned_to') SampleUtilities.pretty_print_request(client, search, 'GET') response = client.call_api(search, 'GET') # Check the response code for errors if (response.code != 200): print( 'An error occured trying to get a list of offenses on the system.') SampleUtilities.pretty_print_response(response) exit(1) # Decode the response offense_list = json.loads(response.read().decode('utf-8')) # This loop is structurally similar to the one above if (len(offense_list) == 0): print('No offenses assigned') else: # Create two new maps of assignment_data, one with the # destination_networks and one with the names for quick access, since # both of these are necessary assignment_networks = list( map(lambda assignment: assignment['destination_network'], assignment_data)) assignment_names = list(map(lambda name: name['name'], assignment_data)) for offense in offense_list: # A flag variable to check if the offense has already existed # longer than the days_to_resolve late = False # A flag variable to check if the offense was assigned to a user in # assignment_data.csv match = False for target_ip in offense['destination_networks']: # Check the target_ip and the name of the user the offense was # assigned to. if ((target_ip in assignment_networks) and (offense['assigned_to'] == assignment_names[ assignment_networks.index(target_ip)])): # Trigger the flag to say this offense has been matched to # a user-network pair in the assignment data match = True index = assignment_networks.index(target_ip) # Get the current datetime and calculate the datetime for # when the offense was created. We use these datetimes to # calculate how long it's been since the offense was # created. Divide start_time by 1000 since start_time is in # milliseconds. current_date = datetime.datetime.utcnow() assignment_date = datetime.datetime.utcfromtimestamp( offense['start_time'] / 1000) elapsed_time = (current_date - assignment_date).days # If the offense has existed longer than days_to_resolve, # display an urgent message. Instead of displaying an # urgent message, any number of things could be done. For # example, if you include an email in the data file, then # in this situation you could email the user responsible # for the offense directly. if elapsed_time > int( assignment_data[index]['days_to_resolve']): print('Notify ' + assignment_names[index] + ', ' + ' offense ' + str(offense['id']) + ' must be closed immediately.') # Trigger the flag to say this offense is late late = True break # If it wasn't already late, and it was matched with an destination # network and user in assignment_data.csv display a message just to # indicate how long the offense has before it's late. if (not late and match): print('Please close offense ' + str(offense['id']) + ' within ' + str( int(assignment_data[index]['days_to_resolve']) - elapsed_time) + ' days!')
def main(): # First we have to create our client client = RestApiClient() #----------------------------------------------------------------------------# #Basic 'GET' # In this example we'll be using the GET endpoint of siem/offenses without # any parameters. This will print absolutely everything it can find, every # parameter of every offense. # Send in the request SampleUtilities.pretty_print_request(client, 'siem/offenses', 'GET') response = client.call_api('siem/offenses', 'GET') # Check if the success code was returned to ensure the call to the API was # successful. if (response.code != 200): print('Failed to retrieve the list of offenses') SampleUtilities.pretty_print_response(response) sys.exit(1) # Since the previous call had no parameters and response has a lot of text, # we'll just print out the number of offenses response_body = json.loads(response.read().decode('utf-8')) print('Number of offenses retrived: ' + str(len(response_body))) #----------------------------------------------------------------------------# #Using the fields parameter with 'GET' # If you just print out the result of a call to the siem/offenses GET endpoint # there will be a lot of fields displayed which you have no interest in. # Here, the fields parameter will make sure the only the fields you want # are displayed for each offense. # Setting a variable for all the fields that are to be displayed fields = '''id,status,description,offense_type,offense_source,magnitude,\ source_network,destination_networks,assigned_to''' # Send in the request SampleUtilities.pretty_print_request(client, 'siem/offenses?fields=' + fields, 'GET') response = client.call_api('siem/offenses?fields=' + fields, 'GET') # Once again, check the response code if (response.code != 200): print('Failed to retrieve list of offenses') SampleUtilities.pretty_print_response(response) sys.exit(1) # This time we will print out the data itself SampleUtilities.pretty_print_response(response) #----------------------------------------------------------------------------# #Using the filter parameter with 'GET' # Sometimes you'll want to narrow down your search to just a few offenses. # You can use the filter parameter to carefully select what is returned # after the call by the value of the fields. # Here we're only looking for OPEN offenses, as shown by the value of 'status' # being 'OPEN' # Send in the request SampleUtilities.pretty_print_request(client, 'siem/offenses?fields=' + fields + '&filter=status=OPEN', 'GET') response = client.call_api('siem/offenses?fields=' + fields + '&filter=status=OPEN', 'GET') # Always check the response code if (response.code != 200): print('Failed to retrieve list of offenses') SampleUtilities.pretty_print_response(response) sys.exit(1) # And output the data SampleUtilities.pretty_print_response(response) #----------------------------------------------------------------------------# #Paging the 'GET' data using 'Range' # If you have a lot of offenses, then you may want to browse through them # just a few at a time. In that case, you can use the Range header to # limit the number of offenses shown in a single call. # In this example only OPEN offenses will be used. # Call the endpoint so that we can find how many OPEN offenses there are. response = client.call_api('siem/offenses?filter=status=OPEN', 'GET') num_of_open_offenses = len(json.loads(response.read().decode('utf-8'))) # Copy the headers into our own variable range_header = client.get_headers().copy() # Set the starting point (indexing starts at 0) page_position = 0 # and choose how many offenses you want to display at a time. offenses_per_page = 5 # Looping here in order to repeatedly show 5 offenses at a time until we've # seen all of the OPEN offenses while True: # Change the value for Range in the header in the format item=x-y range_header['Range'] = 'items=' + str(page_position) + '-' + str(page_position + offenses_per_page - 1) # Send in the request SampleUtilities.pretty_print_request(client,'siem/offenses?fields=' + fields + '&filter=status=OPEN', 'GET', headers=range_header) response = client.call_api('siem/offenses?fields=' + fields + '&filter=status=OPEN', 'GET', headers=range_header) # As usual, check the response code if (response.code != 200): print('Failed to retrieve list of offenses') SampleUtilities.pretty_print_response(response) sys.exit(1) # Output the data SampleUtilities.pretty_print_response(response) # Check to see if all the offenses have been displayed if (page_position + offenses_per_page >= num_of_open_offenses): break else: # Wait for the user to display the next set input('Push any enter to bring up the next ' + str(offenses_per_page) + ' offenses.') page_position += offenses_per_page print('All offenses have been printed to the screen.')
def main(): # First we have to create our client client = RestApiClient(version='3.0') # Request the API call only taking a few fields SampleUtilities.pretty_print_request( client, 'siem/offenses?fields=id,description,' + 'status,offense_type,offense_source', 'GET') response = client.call_api( 'siem/offenses?fields=id,description,status,offense_type,' + 'offense_source', 'GET') # Print out the result for the user to see SampleUtilities.pretty_print_response(response) if (response.code != 200): print('Call Failed') sys.exit(1) # Prompt the user for an ID offense_ID = input('Select an offense to post a note to. ' + 'Please type its ID or quit. ') # Error checking because we want to make sure the user has selected an # offense that exists. while True: if (offense_ID == 'quit'): exit(0) # Make the request to 'GET' the offense chosen by the user SampleUtilities.pretty_print_request(client, 'siem/offenses/' + str(offense_ID), 'GET') response = client.call_api('siem/offenses/' + str(offense_ID), 'GET') # Check response code to see if the offense exists if (response.code == 200): break else: offense_ID = input('An offense by that ID does not exist. ' + 'Please try again or type quit. ') # Print out the offense the user chose SampleUtilities.pretty_print_response(response) # Send in the API Call request for the offense's notes SampleUtilities.pretty_print_request( client, 'siem/offenses/' + str(offense_ID) + '/notes', 'GET') response = client.call_api('siem/offenses/' + str(offense_ID) + '/notes', 'GET') # Display all the notes on the offense SampleUtilities.pretty_print_response(response) if (response.code != 200): print('Call Failed') sys.exit(1) # Confirm that the user wants to make a new note for the offense. We have # to check this since it will permanently add that note to the offense. while True: confirmation = input( 'Would you like to make a new note for offense ' + str(offense_ID) + '? You will NOT be able to delete this note ' + 'later. (YES/no)\n') if (confirmation == 'no'): print('You have chosen not to post a new note. Exiting sample.') exit(0) elif (confirmation == 'YES'): break else: print(confirmation + ' is not a valid answer.') # Take in the text for the note. text = input('Please enter the content of the note.\n') # Send in the request for the new note to be put on the offense. params = {'note_text': text} response = client.call_api('siem/offenses/' + offense_ID + '/notes', 'POST', params=params, print_request=True) # Display to the user the new note received from POST to confirm that it # has been created properly. SampleUtilities.pretty_print_response(response) if (response.code != 201): print('Call Failed') sys.exit(1) print('Note added')
def main(): # First we have to create our client client = RestApiClient(version='3.0') # Send in the request to show all offenses. Here we're using the fields # parameter so that we only see the important information about the # offenses, and using the filter parameter so that we only get offenses # that aren't already closed. SampleUtilities.pretty_print_request( client, 'siem/offenses?fields=id,description,status,offense_type,' + 'offense_source&filter=status!=CLOSED', 'GET') response = client.call_api( 'siem/offenses?fields=id,description,status,offense_type,' + 'offense_source&filter=status!=CLOSED', 'GET') # Print out the result SampleUtilities.pretty_print_response(response) # Don't forget to check the response code if (response.code != 200): print('Call Failed') sys.exit(1) # Prompt the user for an offense ID offense_ID = input( 'Select an offense to close. Please type its ID or quit. ') # Error checking because we want to make sure the user has selected an # OPEN or HIDDEN offense. while True: if (offense_ID == 'quit'): exit(0) # Make the request to 'GET' the offense chosen by the user SampleUtilities.pretty_print_request(client, 'siem/offenses/' + str(offense_ID), 'GET') response = client.call_api('siem/offenses/' + str(offense_ID), 'GET') # Save a copy of the data, decoding it into a string so that # we can read it response_text = response.read().decode('utf-8') # Check response code to see if the offense exists if (response.code == 200): # Reformat the data string into a dictionary so that we # easily access the information. response_body = json.loads(response_text) # Ensure the offense is OPEN or HIDDEN if (response_body['status'] == 'CLOSED'): offense_ID = input( 'The offense you selected is already CLOSED. ' + 'Please try again or type quit. ') else: # Only breaks when the ID exists and not CLOSED break else: offense_ID = input( 'An offense by that ID does not exist. ' + 'Please try again or type quit. ') # Print out the info about the offense the user wants to close # **Only works on things already decoded** print(json.dumps(response_body, indent=4)) # Now since we're closing an offense, we need a closing reason to justify # closing the offense. While both the status parameter and the # closing_reason_id parameters are optional, they're dependent on one # another, so if you close an offense you NEED to give a reason, and vice # versa. # Here we're showing the user what options they have when selecting a # closing_reason so send in the request. SampleUtilities.pretty_print_request(client, 'siem/offense_closing_reasons', 'GET') response = client.call_api('siem/offense_closing_reasons', 'GET') # And print out the response SampleUtilities.pretty_print_response(response) # Always check the response code if (response.code != 200): print('Call Failed') sys.exit(1) # Now that the user has seen which closing_reasons there are to choose # from, have them select one. closing_reason_ID = input('Please select a closing reason or type quit. ') while True: if (closing_reason_ID == 'quit'): exit(0) # Call the API to see if we can GET it, seeing if it exists SampleUtilities.pretty_print_request( client, 'siem/offense_closing_reasons/' + closing_reason_ID, 'GET') response = client.call_api('siem/offense_closing_reasons/' + closing_reason_ID, 'GET') if (response.code == 200): # Breaks the loop once the closing reason exists. break closing_reason_ID = input( 'There has been an error. Please try again or type quit. ') # Now that we've selected which offense and which closing_reason we want to # close, we need have the option of leaving a note. This is to reflect the # UI. In the UI when you decide to close an offense, you have option to # leave a note usually giving further information than the closing_id make_note = input( 'Do you want to create a note for this offense? (YES/no) ') if (make_note == 'YES'): # Quote some text for the not to contain note_text = input('Please enter a note to close the offense with:\n') while True: if note_text != '': confirmation = input( 'Are you sure you want to enter the note "' + note_text + '"? (YES/no) ') if (confirmation == 'YES'): break note_text = input( 'Please enter a note to close the offense with:\n') # Ensure that the user really wants to close the offense while True: confirm = input( 'Are you sure you want to close offense ' + offense_ID + ' with closing reason ' + closing_reason_ID + '? (YES/no)\n') if (confirm == 'YES'): break elif (confirm == 'no'): print('Not closing offense ' + offense_ID) exit(0) else: print(confirm + ' is not a valid response.') # Once the user has confirmed they want to close the offense, we can start # updating the offense # First let's create the note (if the user wants to) if (make_note == 'YES'): params = {'note_text': note_text} response = client.call_api('siem/offenses/' + offense_ID + '/notes', 'POST', params=params, print_request=True) SampleUtilities.pretty_print_response(response) if (response.code != 201): print('Call Failed Creating Note') exit(1) # Then we change the status to CLOSED and add a closing reason. Also using # fields to trim down the data received by POST. SampleUtilities.pretty_print_request( client, 'siem/offenses/' + offense_ID + '?status=CLOSED&closing_reason_id=' + closing_reason_ID + '&fields=id,description,status,offense_type,offense_source', 'POST') response = client.call_api( 'siem/offenses/' + offense_ID + '?status=CLOSED&closing_reason_id=' + closing_reason_ID + '&fields=id,description,status,offense_type,offense_source', 'POST') # Display it at the end to make sure nothing messed up SampleUtilities.pretty_print_response(response) if response.code != 200: print('Call Failed Closing Item') print('Offense closed')
def main(): # First we have to create our client client = RestApiClient(version='3.0') # ------------------------------------------------------------------------- # Basic 'GET' # In this example we'll be using the GET endpoint of siem/offenses without # any parameters. This will print absolutely everything it can find, every # parameter of every offense. # Send in the request SampleUtilities.pretty_print_request(client, 'siem/offenses', 'GET') response = client.call_api('siem/offenses', 'GET') # Check if the success code was returned to ensure the call to the API was # successful. if (response.code != 200): print('Failed to retrieve the list of offenses') SampleUtilities.pretty_print_response(response) sys.exit(1) # Since the previous call had no parameters and response has a lot of text, # we'll just print out the number of offenses response_body = json.loads(response.read().decode('utf-8')) print('Number of offenses retrived: ' + str(len(response_body))) # ------------------------------------------------------------------------- # Using the fields parameter with 'GET' # If you just print out the result of a call to the siem/offenses GET # endpoint there will be a lot of fields displayed which you have no # interest in. Here, the fields parameter will make sure the only the # fields you want are displayed for each offense. # Setting a variable for all the fields that are to be displayed fields = '''id,status,description,offense_type,offense_source,magnitude,\ source_network,destination_networks,assigned_to''' # Send in the request SampleUtilities.pretty_print_request(client, 'siem/offenses?fields=' + fields, 'GET') response = client.call_api('siem/offenses?fields=' + fields, 'GET') # Once again, check the response code if (response.code != 200): print('Failed to retrieve list of offenses') SampleUtilities.pretty_print_response(response) sys.exit(1) # This time we will print out the data itself SampleUtilities.pretty_print_response(response) # ------------------------------------------------------------------------- # Using the filter parameter with 'GET' # Sometimes you'll want to narrow down your search to just a few offenses. # You can use the filter parameter to carefully select what is returned # after the call by the value of the fields. # Here we're only looking for OPEN offenses, as shown by the value of # 'status' being 'OPEN' # Send in the request SampleUtilities.pretty_print_request( client, 'siem/offenses?fields=' + fields + '&filter=status=OPEN', 'GET') response = client.call_api( 'siem/offenses?fields=' + fields + '&filter=status=OPEN', 'GET') # Always check the response code if (response.code != 200): print('Failed to retrieve list of offenses') SampleUtilities.pretty_print_response(response) sys.exit(1) # And output the data SampleUtilities.pretty_print_response(response) # ------------------------------------------------------------------------- # Paging the 'GET' data using 'Range' # If you have a lot of offenses, then you may want to browse through them # just a few at a time. In that case, you can use the Range header to # limit the number of offenses shown in a single call. # In this example only OPEN offenses will be used. # Call the endpoint so that we can find how many OPEN offenses there are. response = client.call_api('siem/offenses?filter=status=OPEN', 'GET') num_of_open_offenses = len(json.loads(response.read().decode('utf-8'))) # Copy the headers into our own variable range_header = client.get_headers().copy() # Set the starting point (indexing starts at 0) page_position = 0 # and choose how many offenses you want to display at a time. offenses_per_page = 5 # Looping here in order to repeatedly show 5 offenses at a time until we've # seen all of the OPEN offenses or exit character q is pressed input_string = "" while True: # Change the value for Range in the header in the format item=x-y range_header['Range'] = ('items=' + str(page_position) + '-' + str(page_position + offenses_per_page - 1)) # Send in the request SampleUtilities.pretty_print_request(client, 'siem/offenses?fields=' + fields + '&filter=status=OPEN', 'GET', headers=range_header) response = client.call_api('siem/offenses?fields=' + fields + '&filter=status=OPEN', 'GET', headers=range_header) # As usual, check the response code if (response.code != 200): print('Failed to retrieve list of offenses') SampleUtilities.pretty_print_response(response) sys.exit(1) # Output the data SampleUtilities.pretty_print_response(response) # Check to see if all the offenses have been displayed if (page_position + offenses_per_page >= num_of_open_offenses): print('All offenses have been printed to the screen.') break else: # Wait for the user to display the next set or quit input_string = input('Push enter to bring up the next ' + str(offenses_per_page) + ' offenses, or q to quit. ') # If the user entered the character 'q', quit. if (input_string == 'q'): break page_position += offenses_per_page
def main(): # First we have to create our client client = RestApiClient(version='3.0') # Request the API call only taking a few fields SampleUtilities.pretty_print_request( client, 'siem/offenses?fields=id,description,' + 'status,offense_type,offense_source', 'GET') response = client.call_api( 'siem/offenses?fields=id,description,status,offense_type,' + 'offense_source', 'GET') # Print out the result for the user to see SampleUtilities.pretty_print_response(response) if (response.code != 200): print('Call Failed') sys.exit(1) # Prompt the user for an ID offense_ID = input('Select an offense to post a note to. ' + 'Please type its ID or quit. ') # Error checking because we want to make sure the user has selected an # offense that exists. while True: if (offense_ID == 'quit'): exit(0) # Make the request to 'GET' the offense chosen by the user SampleUtilities.pretty_print_request(client, 'siem/offenses/' + str(offense_ID), 'GET') response = client.call_api('siem/offenses/' + str(offense_ID), 'GET') # Check response code to see if the offense exists if (response.code == 200): break else: offense_ID = input('An offense by that ID does not exist. ' + 'Please try again or type quit. ') # Print out the offense the user chose SampleUtilities.pretty_print_response(response) # Send in the API Call request for the offense's notes SampleUtilities.pretty_print_request( client, 'siem/offenses/' + str(offense_ID) + '/notes', 'GET') response = client.call_api('siem/offenses/' + str(offense_ID) + '/notes', 'GET') # Display all the notes on the offense SampleUtilities.pretty_print_response(response) if (response.code != 200): print('Call Failed') sys.exit(1) # Confirm that the user wants to make a new note for the offense. We have # to check this since it will permanently add that note to the offense. while True: confirmation = input( 'Would you like to make a new note for offense ' + str(offense_ID) + '? You will NOT be able to delete this note ' + 'later. (YES/no)\n') if (confirmation == 'no'): print('You have chosen not to post a new note. Exiting sample.') exit(0) elif (confirmation == 'YES'): break else: print(confirmation + ' is not a valid answer.') # Take in the text for the note. Since the note could be multiple words, # and the API calls through a url, we are using urllib.parse.quote to # preserve the spaces and special characters in the note. text = urllib.parse.quote(input('Please enter the content of the note.\n')) # Send in the request for the new note to be put on the offense. SampleUtilities.pretty_print_request( client, 'siem/offenses/' + offense_ID + '/notes?note_text=' + text, 'POST') response = client.call_api('siem/offenses/' + offense_ID + '/notes?note_text=' + text, 'POST') # Display to the user the new note received from POST to confirm that it # has been created properly. SampleUtilities.pretty_print_response(response) if (response.code != 201): print('Call Failed') sys.exit(1) print('Note added')
def main(): # Create our client and set up some sample data. client = RestApiClient() setup_data(client) # First lets have a look at the data in this reference set SampleUtilities.pretty_print_request(client, 'reference_data/sets', 'GET') response = client.call_api('reference_data/sets', 'GET') SampleUtilities.pretty_print_response(response) # Suppose we are only interested in the names and the size of each set. We # can restrict the data we get back with a 'fields' parameter. fields = 'fields=' + urllib.parse.quote('name,number_of_elements') SampleUtilities.pretty_print_request(client, 'reference_data/sets?' + fields, 'GET') response = client.call_api('reference_data/sets?' + fields, 'GET') SampleUtilities.pretty_print_response(response) # If this set contained a large amount of data, we might want to process it # a little bit at a time. To get back only part of the data we can use a # 'Range' header. # Note that the range header is indexed form zero, so here we are asking # for the first 5 items. range_header = {'Range': 'items=0-4'} SampleUtilities.pretty_print_request(client, 'reference_data/sets', 'GET', headers=range_header) response = client.call_api('reference_data/sets', 'GET', headers=range_header) response_headers = response.info() SampleUtilities.pretty_print_response(response) # Note that there is a header in the response that contains information # about the portion of the data that you requested. # the 'Content-Range' header tells you which items you got back and how many # items are in the whole list. print ('Content-Range header value: ' + response_headers['Content-Range']) parsed_range_header = response_headers['Content-Range'].split('/') print('This tells us which items we got back: ' + parsed_range_header[0]) print('This tells us how many items there are in total: ' + parsed_range_header[1]) # We can use this information to get back the data one page at a time current_position = 5 while(current_position < int(parsed_range_header[1])): range_string = 'items=' + str(current_position) + '-' + str(current_position + 4) range_header = {'Range': range_string} SampleUtilities.pretty_print_request(client, 'reference_data/sets', 'GET', headers=range_header) response = client.call_api('reference_data/sets', 'GET', headers=range_header) print((response.info())['Content-Range']) SampleUtilities.pretty_print_response(response) current_position = current_position + 5 # Now suppose that we want to find a specific set that contains data we are # interested in. We can use the filter parameter to do this. # Some sets were added during the setup of this sample script. Lets find them. filter_string = 'filter=' + urllib.parse.quote('name between rest_api_samples and rest_api_samplet') SampleUtilities.pretty_print_request(client, 'reference_data/sets?' + filter_string, 'GET') response = client.call_api('reference_data/sets?' + filter_string, 'GET') SampleUtilities.pretty_print_response(response) # Only some of these sets contain data. filter_string = 'filter=' + urllib.parse.quote('name between rest_api_samples and rest_api_samplet and number_of_elements>0') SampleUtilities.pretty_print_request(client, 'reference_data/sets?' + filter_string, 'GET') response = client.call_api('reference_data/sets?' + filter_string, 'GET') SampleUtilities.pretty_print_response(response) response = client.call_api('reference_data/sets?' + filter_string, 'GET') parsed_response = json.loads(response.read().decode('utf-8')) for ref_data_set in parsed_response: print('The sample reference set ' + ref_data_set['name'] + ' contains data') # the filter parameter supports: # and, or, and not logical operators as well as brackets to specify # precedence. # =, >, <, >=, <=, !=, in, between, is null comparisons. # Refer to your product documentation for more information about using # filters. # You can combine fields, filters, and the range parameter to have precise # control over the data you get back from the API. filter_string = 'filter=' + urllib.parse.quote('name between rest_api_samples and rest_api_samplet') range_header = {'Range': 'items=0-1'} fields = 'fields=' + urllib.parse.quote('name') # Here we are asking for only the names of the top two reference sets that # were added by this sample script. SampleUtilities.pretty_print_request(client, 'reference_data/sets?' + filter_string + '&' + fields, 'GET', headers=range_header) response = client.call_api('reference_data/sets?' + filter_string + '&' + fields, 'GET', headers=range_header) SampleUtilities.pretty_print_response(response)
def main(): # First we have to create our client client = RestApiClient(version='3.0') # Send in the request to show all offenses. Here we're using the fields # parameter so that we only see the important information about the # offenses, and using the filter parameter so that we only get offenses # that aren't already closed. SampleUtilities.pretty_print_request( client, 'siem/offenses?fields=id,description,status,offense_type,' + 'offense_source&filter=status!=CLOSED', 'GET') response = client.call_api( 'siem/offenses?fields=id,description,status,offense_type,' + 'offense_source&filter=status!=CLOSED', 'GET') # Print out the result SampleUtilities.pretty_print_response(response) # Don't forget to check the response code if (response.code != 200): print('Call Failed') sys.exit(1) # Prompt the user for an offense ID offense_ID = input( 'Select an offense to close. Please type its ID or quit. ') # Error checking because we want to make sure the user has selected an # OPEN or HIDDEN offense. while True: if (offense_ID == 'quit'): exit(0) # Make the request to 'GET' the offense chosen by the user SampleUtilities.pretty_print_request( client, 'siem/offenses/' + str(offense_ID), 'GET') response = client.call_api('siem/offenses/' + str(offense_ID), 'GET') # Save a copy of the data, decoding it into a string so that # we can read it response_text = response.read().decode('utf-8') # Check response code to see if the offense exists if (response.code == 200): # Reformat the data string into a dictionary so that we # easily access the information. response_body = json.loads(response_text) # Ensure the offense is OPEN or HIDDEN if (response_body['status'] == 'CLOSED'): offense_ID = input( 'The offense you selected is already CLOSED. ' + 'Please try again or type quit. ') else: # Only breaks when the ID exists and not CLOSED break else: offense_ID = input('An offense by that ID does not exist. ' + 'Please try again or type quit. ') # Print out the info about the offense the user wants to close # **Only works on things already decoded** print(json.dumps(response_body, indent=4)) # Now since we're closing an offense, we need a closing reason to justify # closing the offense. While both the status parameter and the # closing_reason_id parameters are optional, they're dependent on one # another, so if you close an offense you NEED to give a reason, and vice # versa. # Here we're showing the user what options they have when selecting a # closing_reason so send in the request. SampleUtilities.pretty_print_request(client, 'siem/offense_closing_reasons', 'GET') response = client.call_api('siem/offense_closing_reasons', 'GET') # And print out the response SampleUtilities.pretty_print_response(response) # Always check the response code if (response.code != 200): print('Call Failed') sys.exit(1) # Now that the user has seen which closing_reasons there are to choose # from, have them select one. closing_reason_ID = input('Please select a closing reason or type quit. ') while True: if (closing_reason_ID == 'quit'): exit(0) # Call the API to see if we can GET it, seeing if it exists SampleUtilities.pretty_print_request( client, 'siem/offense_closing_reasons/' + closing_reason_ID, 'GET') response = client.call_api( 'siem/offense_closing_reasons/' + closing_reason_ID, 'GET') if (response.code == 200): # Breaks the loop once the closing reason exists. break closing_reason_ID = input( 'There has been an error. Please try again or type quit. ') # Now that we've selected which offense and which closing_reason we want to # close, we need have the option of leaving a note. This is to reflect the # UI. In the UI when you decide to close an offense, you have option to # leave a note usually giving further information than the closing_id make_note = input( 'Do you want to create a note for this offense? (YES/no) ') if (make_note == 'YES'): # Quote some text for the not to contain note_text = input('Please enter a note to close the offense with:\n') while True: if note_text != '': confirmation = input( 'Are you sure you want to enter the note "' + note_text + '"? (YES/no) ') if (confirmation == 'YES'): break note_text = input( 'Please enter a note to close the offense with:\n') note_text = urllib.parse.quote(note_text) # Ensure that the user really wants to close the offense while True: confirm = input('Are you sure you want to close offense ' + offense_ID + ' with closing reason ' + closing_reason_ID + '? (YES/no)\n') if (confirm == 'YES'): break elif (confirm == 'no'): print('Not closing offense ' + offense_ID) exit(0) else: print(confirm + ' is not a valid response.') # Once the user has confirmed they want to close the offense, we can start # updating the offense # First let's create the note (if the user wants to) if (make_note == 'YES'): SampleUtilities.pretty_print_request( client, 'siem/offenses/' + offense_ID + '/notes?note_text=' + note_text, 'POST') response = client.call_api( 'siem/offenses/' + offense_ID + '/notes?note_text=' + note_text, 'POST') SampleUtilities.pretty_print_response(response) if (response.code != 201): print('Call Failed Creating Note') exit(1) # Then we change the status to CLOSED and add a closing reason. Also using # fields to trim down the data received by POST. SampleUtilities.pretty_print_request( client, 'siem/offenses/' + offense_ID + '?status=CLOSED&closing_reason_id=' + closing_reason_ID + '&fields=id,description,status,offense_type,offense_source', 'POST') response = client.call_api( 'siem/offenses/' + offense_ID + '?status=CLOSED&closing_reason_id=' + closing_reason_ID + '&fields=id,description,status,offense_type,offense_source', 'POST') # Display it at the end to make sure nothing messed up SampleUtilities.pretty_print_response(response) if response.code != 200: print('Call Failed Closing Item') print('Offense closed')
def setup_data(client): current_time = int(time.time() * 1000) key_name_types = urllib.parse.quote("[{\"element_type\": \"IP\", \"key_name\": \"Authorization_Server_IP_Secure\"}, {\"element_type\": \"PORT\", \"key_name\": \"Authorization_Server_PORT_Secure\"}, {\"element_type\": \"DATE\", \"key_name\": \"Last_Secure_Login\"}, {\"element_type\": \"IP\", \"key_name\": \"Authorization_Server_IP_General\"}]") SampleUtilities.data_setup(client, 'reference_data/tables?name=rest_api_samples_server_access&element_type=ALN&key_name_types=' + key_name_types, 'POST') SampleUtilities.data_setup(client, 'reference_data/tables/rest_api_samples_server_access?outer_key=calvin&inner_key=Authorization_Server_IP_Secure&value=6.3.9.12', 'POST') SampleUtilities.data_setup(client, 'reference_data/tables/rest_api_samples_server_access?outer_key=calvin&inner_key=Authorization_Server_PORT_Secure&value=443', 'POST') SampleUtilities.data_setup(client, 'reference_data/tables/rest_api_samples_server_access?outer_key=calvin&inner_key=Authorization_Server_IP_General&value=7.12.15.12', 'POST') SampleUtilities.data_setup(client, 'reference_data/tables/rest_api_samples_server_access?outer_key=calvin&inner_key=Last_Secure_Login&value=' + str(current_time), 'POST') SampleUtilities.data_setup(client, 'reference_data/tables/rest_api_samples_server_access?outer_key=socrates&inner_key=Authorization_Server_IP_General&value=7.12.14.85', 'POST') time.sleep(1) SampleUtilities.data_setup(client, 'reference_data/tables/rest_api_samples_server_access?outer_key=mill&inner_key=Authorization_Server_IP_Secure&value=6.3.9.12', 'POST') SampleUtilities.data_setup(client, 'reference_data/tables/rest_api_samples_server_access?outer_key=mill&inner_key=Authorization_Server_PORT_Secure&value=443', 'POST') SampleUtilities.data_setup(client, 'reference_data/tables/rest_api_samples_server_access?outer_key=mill&inner_key=Last_Secure_Login&value=' + str(current_time), 'POST') SampleUtilities.data_setup(client, 'reference_data/tables/rest_api_samples_server_access?outer_key=mill&inner_key=Authorization_Server_IP_General&value=7.13.22.85', 'POST') SampleUtilities.data_setup(client, 'reference_data/tables/rest_api_samples_server_access?outer_key=hobbes&inner_key=Authorization_Server_IP_Secure&value=6.3.9.12', 'POST') SampleUtilities.data_setup(client, 'reference_data/tables/rest_api_samples_server_access?outer_key=hobbes&inner_key=Authorization_Server_PORT_Secure&value=22', 'POST') SampleUtilities.data_setup(client, 'reference_data/tables/rest_api_samples_server_access?outer_key=hobbes&inner_key=Last_Secure_Login&value=' + str(current_time), 'POST') SampleUtilities.data_setup(client, 'reference_data/tables/rest_api_samples_server_access?outer_key=hobbes&inner_key=Authorization_Server_IP_General&value=7.12.19.125', 'POST') SampleUtilities.data_setup(client, 'reference_data/tables/rest_api_samples_server_access?outer_key=aquinas&inner_key=Last_Secure_Login&value=' + str(current_time - 1000000), 'POST') SampleUtilities.data_setup(client, 'reference_data/tables/rest_api_samples_server_access?outer_key=aquinas&inner_key=Authorization_Server_IP_General&value=7.12.15.12', 'POST')