def _fn_bigfix_assets_function(self, event, *args, **kwargs): """Function: Resilient Function : Bigfix assets - Get properties in BigFix for an endpoint.""" try: # Get the function parameters: bigfix_asset_name = kwargs.get("bigfix_asset_name") # text bigfix_asset_id = kwargs.get("bigfix_asset_id") # number bigfix_incident_id = kwargs.get("bigfix_incident_id") # number log = logging.getLogger(__name__) log.info("bigfix_asset_name: %s", bigfix_asset_name) log.info("bigfix_asset_id: %s", bigfix_asset_id) log.info("bigfix_incident_id: %s", bigfix_incident_id) params = { "asset_name": bigfix_asset_name, "asset_id": bigfix_asset_id, "incident_id": bigfix_incident_id } validate_params(params, "fn_bigfix_assets") yield StatusMessage( u"Running BigFix Query for Endpoint id {0}, with name {1} ...". format(params["asset_id"], params["asset_name"])) bigfix_client = BigFixClient(self.options) try: # Perform the BigFix Query response = bigfix_client.get_bf_computer_properties( params["asset_id"]) except Exception as e: log.exception("Failed to query a BigFix asset.") yield StatusMessage( "Failed with exception '{}' while trying to query a BigFix asset" .format(type(e).__name__)) raise Exception( "Failed with exception '{}' while trying to query a BigFix asset" .format(type(e).__name__)) if not response: yield StatusMessage( "No properties retrieved for the asset id '{}'".format( params["asset_id"])) results = {} else: # Create a Resilient attachment file_name = "bigfix-properties-" + params["asset_name"] + "-" + \ datetime.datetime.today().strftime('%Y%m%d') + ".xml" att_report = create_attachment(self.rest_client(), file_name, response, params) results = {"status": "OK", "att_name": att_report["name"]} yield StatusMessage("done...") log.debug(results) # Produce a FunctionResult with the results yield FunctionResult(results) except Exception: yield FunctionError()
def selftest_function(opts): """ Simple test to verify Bigfix connectivity. """ options = opts.get("fn_bigfix", {}) try: bigfix_client = BigFixClient(options) r = bigfix_client.test_connectivity() if r.status_code == 200: return {"state": "success", "status_code": r.status_code } else: return {"state": "failure", "status_code": r.status_code } except Exception as e: return {"state": "failure", "status_code": str(e)}
def _fn_bigfix_artifact_function(self, event, *args, **kwargs): """Function: Resilient Function : Bigfix artifact - Get hits in BigFix for artifact.""" try: # Get the function parameters: bigfix_artifact_id = kwargs.get("bigfix_artifact_id") # number bigfix_artifact_value = kwargs.get("bigfix_artifact_value") # text bigfix_artifact_type = kwargs.get("bigfix_artifact_type") # text bigfix_artifact_properties_name = kwargs.get( "bigfix_artifact_properties_name") # text bigfix_artifact_properties_value = kwargs.get( "bigfix_artifact_properties_value") # text bigfix_incident_id = kwargs.get("bigfix_incident_id") # number bigfix_incident_plan_status = kwargs.get( "bigfix_incident_plan_status") # text log = logging.getLogger(__name__) log.info("bigfix_artifact_id: %s", bigfix_artifact_id) log.info("bigfix_artifact_value: %s", bigfix_artifact_value) log.info("bigfix_artifact_type: %s", bigfix_artifact_type) log.info("bigfix_artifact_properties_name: %s", bigfix_artifact_properties_name) log.info("bigfix_artifact_properties_value: %s", bigfix_artifact_properties_value) log.info("bigfix_incident_id: %s", bigfix_incident_id) log.info("bigfix_incident_plan_status: %s", bigfix_incident_plan_status) params = { "artifact_id": bigfix_artifact_id, "artifact_value": bigfix_artifact_value, "artifact_properties_name": bigfix_artifact_properties_name, "artifact_properties_value": bigfix_artifact_properties_value, "artifact_type": bigfix_artifact_type, "incident_id": bigfix_incident_id, "incident_plan_status": bigfix_incident_plan_status } validate_params(params, "fn_bigfix_artifact") yield StatusMessage( "Running BigFix Query for Artifact id {0}, with value {1} ...". format(params["artifact_id"], params["artifact_value"])) bigfix_client = BigFixClient(self.options) try: artifact_data = None if params["incident_plan_status"] != 'C': # If incident isn't closed if params["artifact_type"] == "IP Address": artifact_data = bigfix_client.get_bf_computer_by_ip( bigfix_artifact_value) elif params["artifact_type"] == "File Path": artifact_data = bigfix_client.get_bf_computer_by_file_path( bigfix_artifact_value) elif params["artifact_type"] == "Process Name": artifact_data = bigfix_client.get_bf_computer_by_process_name( bigfix_artifact_value) elif params["artifact_type"] == "Service": artifact_data = bigfix_client.get_bf_computer_by_service_name( bigfix_artifact_value) elif params["artifact_type"] == "Registry Key": artifact_data = bigfix_client.get_bf_computer_by_registry_key_name_value( bigfix_artifact_value, params["artifact_properties_name"], params["artifact_properties_value"]) else: raise ValueError( "Unsupported artifact type {}.".format( bigfix_artifact_type)) except Exception as e: log.exception("Failed to query BigFix.") yield StatusMessage( "Failed with exception '{}' while trying to query BigFix.". format(type(e).__name__)) raise Exception( "Failed with exception '{}' while trying to query BigFix.". format(type(e).__name__)) if bigfix_incident_plan_status == 'C': yield StatusMessage( "Ignoring action, incident {} is closed".format( params["incident_id"])) results = {} elif not artifact_data: yield StatusMessage( "Could not find data about the artifact {}".format( params["artifact_value"])) results = {} else: hits = get_hits(artifact_data, params) if len(hits) == 0: yield StatusMessage( "No hits detected for artifact id '{0}' with value '{1}' and of type '{2}'." .format(params["artifact_id"], params["artifact_value"], params["artifact_type"])) results = {} elif len(hits) > int( self.options.get("hunt_results_limit", "200")): yield StatusMessage( "Adding artifact data as an incident attachment") # Define file name and content to add as an attachment file_name = "query_for_artifact_{0}_{1}_{2}.txt" \ .format(params["artifact_id"], params["artifact_type"], datetime.datetime.today().strftime('%Y%m%d')) file_content = "" for data in hits: file_content += "Resource ID: {0}. Resource Name: {1}. Artifact value: {2}. Artifact Type: {3} \n" \ .format(data["computer_id"], data["computer_name"], params["artifact_value"], params["artifact_type"]) # Create an attachment att_report = create_attachment(self.rest_client(), file_name, file_content, params) results = { "hits_over_limit": True, "att_name": att_report["name"], "hits_count": len(hits) } else: query_execution_date = datetime.datetime.now().strftime( '%m-%d-%Y %H:%M:%S') results = { "endpoint_hits": json.loads(json.dumps(hits)), "hits_count": len(hits), "query_execution_date": query_execution_date } yield StatusMessage("done...") log.debug(results) # Produce a FunctionResult with the results yield FunctionResult(results) except Exception: log.exception( "Exception in Resilient Function for BigFix integration.") yield FunctionError()
def _fn_bigfix_remediation_function(self, event, *args, **kwargs): """Function: Resilient Function : Bigfix remediation - Remediate hit for endpoint in BigFix.""" try: # Get the function parameters: bigfix_asset_id = kwargs.get("bigfix_asset_id") # text bigfix_artifact_value = kwargs.get("bigfix_artifact_value") # text bigfix_artifact_type = kwargs.get("bigfix_artifact_type") # text bigfix_incident_id = kwargs.get("bigfix_incident_id") # number log = logging.getLogger(__name__) log.info("bigfix_asset_id: %s", bigfix_asset_id) log.info("bigfix_artifact_value: %s", bigfix_artifact_value) log.info("bigfix_artifact_type: %s", bigfix_artifact_type) log.info("bigfix_incident_id: %s", bigfix_incident_id) params = { "asset_id": bigfix_asset_id, "artifact_value": bigfix_artifact_value, "artifact_type": bigfix_artifact_type, "incident_id": bigfix_incident_id } validate_params(params, "fn_bigfix_remediation") yield StatusMessage( u"Running BigFix remediation for Artifact '{0}' on endpoint '{1}' ..." .format(params["artifact_value"], params["asset_id"])) bigfix_client = BigFixClient(self.options) yield StatusMessage("Running BigFix remediation ...") # Send a remediation message to BigFix try: if params["artifact_type"] == "Process Name": response = bigfix_client.send_kill_process_remediation_message( bigfix_artifact_value, bigfix_asset_id) elif params["artifact_type"] == "Service": response = bigfix_client.send_stop_service_remediation_message( bigfix_artifact_value, bigfix_asset_id) elif params["artifact_type"] == "Registry Key": if len(bigfix_artifact_value.split('\\')) <= 2: log.exception( "Delete not allowed for root level key %s.", bigfix_artifact_value) yield StatusMessage( "Warning: Delete not allowed for root level key {}." .format(bigfix_artifact_value)) response = None else: # Test if registry key has 1 or more subkeys response = None result = bigfix_client.check_exists_subkey( bigfix_artifact_value, bigfix_asset_id) # Query should return array with single result. if not result or not result[0]: log.exception( "Delete not allowed for key '%s'. BigFix subkey query did not return a valid result.", bigfix_artifact_value) yield StatusMessage( "Warning: Delete not allowed for key '{}'. BigFix subkey query did not return a valid result." .format(bigfix_artifact_value)) elif (result[0]["failure"] == 0 or result[0]["failure"] == "False") and result[0]["result"] == "True": log.exception( "Delete not allowed, key '%s' has 1 or more subkeys.", bigfix_artifact_value) yield StatusMessage( "Warning: Delete not allowed, key '{}' has 1 or more subkeys." .format(bigfix_artifact_value)) else: response = bigfix_client.send_delete_registry_key_remediation_message( bigfix_artifact_value, bigfix_asset_id) elif params["artifact_type"] == "File Path": # Test if file path is a folder, if so disallow remediate. response = None result = bigfix_client.check_is_folder( bigfix_artifact_value, bigfix_asset_id) # Query should return array with single result. if not result or not result[0]: log.exception( "Delete not allowed' for artifact %s'. BigFix subkey query did not return a valid result.", bigfix_artifact_value) yield StatusMessage( "Warning: Delete not allowed for artifact '{}'. BigFix subkey query did not " "return a valid result".format( bigfix_artifact_value)) elif (result[0]["failure"] == 0 or result[0]["failure"] == "False") and result[0]["result"] == "True": log.exception( "Delete not allowed, '%s' is a folder artifact.", bigfix_artifact_value) yield StatusMessage( "Warning: Delete not allowed for folder artifact '{}'." .format(bigfix_artifact_value)) else: response = bigfix_client.send_delete_file_remediation_message( bigfix_artifact_value, bigfix_asset_id) else: log.error("Unsupported artifact type '%s'.", params["artifact_type"]) raise ValueError("Unsupported artifact type '{}'.".format( params["artifact_type"])) except Exception as e: log.exception("Failed to run a BigFix remediation.") yield StatusMessage( "Failed with exception '{}' while trying to run a BigFix remediation." .format(type(e).__name__)) raise Exception( "Failed with exception '{}' while trying to run a BigFix remediation." .format(type(e).__name__)) if response is None: log.debug("Could not create BigFix Action.") raise FunctionError("Could not create BigFix Action") else: status_message = "BigFix action created successfully." action_id = response remediation_date = datetime.datetime.today().strftime( '%m-%d-%Y %H:%M:%S') results = { "status": "OK", "status_message": status_message, "remediation_date": remediation_date, "action_id": action_id } yield StatusMessage("done...") log.debug(results) # Produce a FunctionResult with the results yield FunctionResult(results) except Exception: log.exception( "Exception in Resilient Function for BigFix integration.") yield FunctionError()
def _fn_bigfix_action_status_function(self, event, *args, **kwargs): """Function: Resilient Function : Bigfix action status - Get status for Bigfix action id.""" try: # Get the function parameters: bigfix_action_id = kwargs.get("bigfix_action_id") # number log = logging.getLogger(__name__) log.info("bigfix_action_id: %s", bigfix_action_id) if is_none(bigfix_action_id): raise ValueError( "Required parameter 'bigfix_action_id' not set.") yield StatusMessage( "Running Query BigFix for BigFix action id '{}' ...".format( bigfix_action_id)) bigfix_client = BigFixClient(self.options) retry_interval = int(self.options.get("bigfix_polling_interval")) retry_timeout = int(self.options.get("bigfix_polling_timeout")) # Check status every 'retry_interval' secs up to 'retry_timeout' secs try: status = None (status, status_message) = poll_action_status( bigfix_client, bigfix_action_id, retry_interval, retry_timeout) except Exception as e: log.exception("Failed to poll BigFix action status.") yield StatusMessage( "Failed with exception '{}' while trying to poll BigFix action status." .format(type(e).__name__)) raise Exception( "Failed with exception '{}' while trying to poll BigFix action status." .format(type(e).__name__)) if not status: raise FunctionError( "Function 'poll_action_status' returned bad status {}.". format(status)) elif status == "OK": yield StatusMessage( "Received successful status message '{0}' for BigFix action {1}." .format(re.sub('\.$', '', status_message), bigfix_action_id)) results = {"status": "OK", "status_message": status_message} elif status == "Failed": yield StatusMessage( "Received error status {0} for BigFix action {1}.".format( status_message, bigfix_action_id)) results = { "status": "Failed", "status_message": status_message } elif status == "Unsupported": yield StatusMessage( "Received unexpected status {0} while retrieving status for BigFix action {1}." .format(status_message, bigfix_action_id)) results = {} elif status == "Timedout": yield StatusMessage( "Timed out getting action status for BigFix action {}". format(bigfix_action_id)) results = {} yield StatusMessage("done...") log.debug(results) # Produce a FunctionResult with the results yield FunctionResult(results) except Exception: log.exception( "Exception in Resilient Function for BigFix integration.") yield FunctionError()