def get_intelix_auth(sophos_auth, intelix_final_path):
    # load and read the sophos config file
    intelix_conf = cp.ConfigParser(allow_no_value=True)
    intelix_conf.read(intelix_final_path)

    if sophos_auth == "static":
        # Auth is static so the creds are pulled from the config
        logging.info("Static API credentials parameter, has been passed. Getting value from config")
        client_id = intelix_conf.get('static', 'client_id')
        client_secret = intelix_conf.get('static', 'client_secret')
        if int(len(client_secret)) == 0 or int(len(client_id)) == 0:
            # verifies that there is something in the variable
            logging.error("Please verify the static credentials are valid in config.ini")
            exit(1)
        else:
            logging.info("Values have been applied to the credential variables")
            return intelix_client_id, intelix_client_secret
    elif sophos_auth == "aws":
        # Creds are held in AWS, gather the config information
        logging.info("Attempting to get Sophos Intelix API credentials from AWS Secrets Manager")
        client_id_key = intelix_conf.get('intelix', 'client_id_key')
        client_secret_key = intelix_conf.get('intelix', 'client_secret_key')
        secret_name = intelix_conf.get('intelix', 'secret_name')
        region_name = intelix_conf.get('intelix', 'region_name')
        try:
            # Pull the credentials from AWS Secret Manager and pass to initialise Sophos Central API
            aws_secret = awssec.get_secret(secret_name, region_name)
            intelix_client_id = aws_secret[client_id_key]
            intelix_client_secret = aws_secret[client_secret_key]
            logging.info("Values have been applied to the Intelix credential variables")
            return intelix_client_id, intelix_client_secret
        except Exception as aws_exception:
            # Return the exception raised from the aws secrets script
            raise aws_exception
def get_sophos_creds(sophos_auth, sophos_final_path):
    # load and read the sophos config file
    sophos_conf = cp.ConfigParser(allow_no_value=True)
    sophos_conf.read(sophos_final_path)

    if sophos_auth == "static":
        # Auth is static so the creds are pulled from the config
        logging.info(
            "Static API credentials parameter, has been passed. Getting value from config"
        )
        client_id = sophos_conf.get('static', 'client_id')
        client_secret = sophos_conf.get('static', 'client_secret')
        if int(len(client_secret)) == 0 or int(len(client_id)) == 0:
            # verifies that there is something in the variable
            logging.error(
                "Please verify the static credentials are valid in config.ini")
            exit(1)
        else:
            logging.info(
                "Values have been applied to the credential variables")
            return client_id, client_secret
    elif sophos_auth == "aws":
        # Creds are held in AWS, gather the config information
        logging.info(
            "Attempting to get Sophos Central API credentials from AWS Secrets Manager"
        )
        client_id_key = sophos_conf.get('aws', 'client_id_key')
        client_secret_key = sophos_conf.get('aws', 'client_secret_key')
        secret_name = sophos_conf.get('aws', 'secret_name')
        region_name = sophos_conf.get('aws', 'region_name')
        try:
            # Pull the credentials from AWS Secret Manager and pass to initialise Sophos Central API
            aws_secret = awssec.get_secret(secret_name, region_name)
            client_id = aws_secret[client_id_key]
            client_secret = aws_secret[client_secret_key]
            logging.info(
                "Values have been applied to the credential variables, attempt to initialize Sophos Central API"
            )
            return client_id, client_secret
        except Exception as aws_exception:
            # Return the exception raised from the aws secrets script
            raise aws_exception
    else:
        # Invalid auth parameter has been passed
        logging.error(
            "No authentication or an incorrect authentication method has been specified.\nPlease run --help for "
            "further information")
def get_splunk_creds(splunk_final_path):
    # Initially set the Splunk flag and Splunk creds to None.
    splunk_aws_flag = None
    splunk_creds = None

    # load and read the splunk config
    logging.info("Reading Splunk configuration information")
    splunk_conf = cp.ConfigParser(allow_no_value=True)
    splunk_conf.read(splunk_final_path)
    splunk_use_aws = splunk_conf.get('splunk_aws', 'splunk_aws')
    splunk_ack_enabled = splunk_conf.get('splunk_hec', 'splunk_ack_enabled')
    splunk_verify_ack = splunk_conf.get('splunk_hec', 'verify_ack_result')

    # check authentication method
    logging.info("Splunk output has been set")
    if splunk_use_aws == "1":
        logging.info(
            "Config setting set to use Splunk creds from AWS Secrets Manager")
        # Confirm that the check indexer acknowledgement has not been set without the config for ack_enabled being 0
        if splunk_verify_ack == "1" and splunk_ack_enabled == "0":
            logging.error(
                "To verify Splunk Index Acknowledgements, you must set the config 'splunk_ack_enabled' to '1'"
            )
            exit(1)
        else:
            # Apply the splunk aws settings to variables in order to get aws secret information
            logging.info(
                "Flag set to pull HEC token from AWS Secrets Manager. Getting config settings"
            )
            token_key = splunk_conf.get('splunk_aws', 'token_key')
            secret_name = splunk_conf.get('splunk_aws', 'secret_name')
            region_name = splunk_conf.get('splunk_aws', 'region_name')
            # verify that the config is valid
            try:
                # Pull the credentials from AWS Secret Manager and add to splunk_creds variable
                logging.info("Attempting to get Splunk HEC token from AWS")
                aws_secret = awssec.get_secret(secret_name, region_name)
                splunk_token = aws_secret[token_key]
                # Verify that the token matches expected format
                aws_token_match = match(r"{0}".format(api_conf.uuid_regex),
                                        splunk_token)
                if aws_token_match is None:
                    # An exception will be raised if the token does not match the correct format
                    logging.error(
                        "Please ensure you have a valid HEC token in your AWS Secrets Manager"
                    )
                    exit(1)
                else:
                    logging.info("HEC token is in a valid format")
                    #splunk_creds = {'tok': '{0}'.format(splunk_token)}
                    splunk_creds = splunk_token
                    return splunk_creds
            except Exception("AWSException") as aws_exception:
                raise aws_exception
    elif splunk_use_aws == "0":
        logging.info(
            "Config setting set to use static Splunk HEC token from config")
        logging.info("Getting static credentials for Splunk HEC from config")
        splunk_static_tok = splunk_conf.get('splunk_static', 'token')
        logging.info("Verying token passed is in the correct format")
        token_match = match(r"{0}".format(api_conf.uuid_regex),
                            splunk_static_tok)
        # verify that the value in the static Splunk HEC token is valid
        if token_match is None:
            logging.error(
                "Please ensure you have a valid HEC token in the splunk_config.ini"
            )
            exit(1)
        else:
            logging.info("Token is in the correct format")
            splunk_creds = {'tok': '{0}'.format(splunk_static_tok)}
            return splunk_creds
def ten_auth():
    sophos_conf_path = api_conf.sophos_conf_path
    sophos_final_path = api_utils.get_file_location(sophos_conf_path)

    sophos_conf = cp.ConfigParser(allow_no_value=True)
    sophos_conf.read(sophos_final_path)
    secret_name = sophos_conf.get('aws', 'secret_name')
    region_name = sophos_conf.get('aws', 'region_name')

    if secret_name and region_name:
        try:
            # Pull the credentials from AWS Secret Manager and pass to initialise Sophos Central API
            aws_secret = awssecret.get_secret(secret_name, region_name)
            client_id = aws_secret['client_id']
            client_secret = aws_secret['client_secret']
            logging.info(
                "Values have been applied to the credential variables, attempt to initialize Sophos Central API"
            )
        except Exception as aws_exception:
            # Return the exception raised from the aws secrets script
            raise aws_exception
    else:
        logging.info(
            "No AWS creds set in config. Requesting client_id and client_secret"
        )
        client_id = getpass.getpass(
            prompt="Provide Sophos Central API Client ID: ", stream=None)
        if client_id:
            client_secret = getpass.getpass(
                prompt="Provide Sophos Central API Client Secret: ",
                stream=None)
        else:
            logging.critical("No Client ID provided. Exiting")
            exit(1)

    # Set authorisation and whoami URLs
    auth_url = api_conf.auth_uri
    whoami_url = api_conf.whoami_uri
    partner_url = api_conf.tenants_ptr_uri
    organization_url = api_conf.tenants_org_uri

    # Get Sophos Central API Bearer Token for authorisation
    sophos_access_token = get_bearer_tok(client_id, client_secret, auth_url)

    # Construct id_headers
    headers = validate_id_headers(sophos_access_token)

    # Lookup up the unique ID assigned to the business entity for Sophos Central API
    whoami_id, whoami_type, whoami_data = get_whoami_data(headers, whoami_url)

    # Obtain correct whoami uri/header based on the whoami type
    header_type, tenant_url = validate_whoami_type(whoami_type, whoami_data,
                                                   partner_url,
                                                   organization_url)

    # Construct tenant headers
    tenant_headers = api_tenant.gen_tenant_headers(headers, whoami_id,
                                                   whoami_type, header_type)

    # Check and gather tenant information
    if whoami_type == "tenant":
        tenant_info = api_tenant.type_tenant(tenant_headers, whoami_id,
                                             tenant_url, sophos_access_token)
    else:
        tenant_info = api_tenant.get_tenant_info(headers, tenant_url,
                                                 sophos_access_token)

    return tenant_info
Ejemplo n.º 5
0
def main(params):
    # set params to variables
    log_level = params.log_level
    tenant = params.tenant
    search_filter = params.filter
    search_variables = params.variables
    search_type = params.search_type
    search_val = params.search_input
    misp_attr = params.misp
    api = params.api
    output = params.output

    if log_level is None:
        logging.disable(True)
    else:
        logging.disable(False)
        log_name = log_level
        level = getattr(logging, log_name)
        log_fmt = '%(asctime)s: [%(levelname)s]: %(message)s'
        logging.basicConfig(level=level, format=log_fmt, datefmt='%d/%m/%Y %I:%M:%S %p')

    logging.info("Start of Logging")

    if api == "ld":
        api = "live-discover"
    elif api == "xdr":
        api = "xdr-datalake"
    else:
        logging.error("No api passed, exiting")
        exit(1)

    if misp_attr:
        misp_conf_path = api_conf.misp_conf_path
        misp_final_path = api_utils.get_file_location(misp_conf_path)

        misp_conf = cp.ConfigParser(allow_no_value=True)
        misp_conf.read(misp_final_path)
        secret_name = misp_conf.get('aws', 'secret_name')
        region_name = misp_conf.get('aws', 'region_name')
        misp_tok = misp_conf.get('aws', 'api_key')
        misp_url = misp_conf.get('url', 'misp_instance')

        # Get attributes for iocs to search
        misp_type = params.misp_type
        misp_val = params.misp_val

        if not misp_type or not misp_val:
            logging.error("You must specify a MISP type and value")
            exit(1)
        else:
            pass

        if misp_tok:
            try:
                # Pull the credentials from AWS Secret Manager and pass to initialise misp
                misp_secret = awssecret.get_secret(secret_name, region_name)
                misp_tok = misp_secret['{0}'.format(misp_tok)]
                logging.info("MISP auth token applied")
            except Exception as aws_exception:
                # Return the exception raised from the aws secrets script
                raise aws_exception
            finally:
                attributes = sld.get_misp_attributes(misp_url, misp_type, misp_val, misp_tok, wildcard=True)
        else:
            logging.info("No AWS creds set in config. Requesting MISP API token")
            misp_tok = getpass.getpass(prompt="Provide MISP token: ", stream=None)
            if misp_tok:
                attributes = sld.get_misp_attributes(misp_url, misp_type, misp_val, misp_tok, wildcard=True)
            else:
                logging.error("No MISP token provided. Exiting")
                exit(1)

        if not attributes:
            logging.critical("No attributes found, exiting")
            exit(1)
        else:
            logging.info("MISP attributes obtained")

            pass
    else:
        pass

    # format the filter variable to remove escape characters and pass as json
    if search_filter:
        try:
            search_filter = json.loads(re.sub('[\\?]', '', search_filter))
        except ValueError as err:
            logging.error("JSON malformed: {0}".format(search_filter))
            raise err
        else:
            pass
    elif search_type == "list":
        pass
    elif api == "xdr-datalake":
        pass
    else:
        logging.critical("No filter passed, A filter must be provided")
        exit(1)

    if (search_variables and misp_attr) or (misp_attr and api == "xdr-datalake"):
        if api == "live-discover":
            # Format the search date
            date_frmt = "{0}.000Z".format(search_variables[2])
        else:
            pass

        # estimated size of variables
        ioc_size = getsizeof(attributes)
        if ioc_size < 1 or ioc_size > 5000:
            logging.critical(
                "Size of IOC JSON must be in the range of 1 - 5000. Current estimated size is: {0}".format(ioc_size))
            exit(1)
        else:
            pass

        # Build JSON
        if api == "live-discover":
            variables_json = [
                {
                    "name": "Number of Hours of activity to search",
                    "dataType": "text",
                    "value": "{0}".format(search_variables[0])
                },
                {
                    "name": "IOC JSON",
                    "dataType": "text",
                    "value": attributes
                },
                {
                    "name": "Start Search From",
                    "dataType": "dateTime",
                    "value": "{0}".format(date_frmt)
                }
            ]
        elif api == "xdr-datalake":
            variables_json = [
                {
                    "name": "IOC_JSON",
                    "dataType": "text",
                    "value": attributes
                }
            ]
    elif search_variables:
        if api == "live-discover":
            # Format the search date
            date_frmt = "{0}.000Z".format(search_variables[2])
        else:
            pass

        # esitmated size of variables
        ioc_size = getsizeof(search_variables)
        if ioc_size < 1 or ioc_size > 5000:
            logging.critical(
                "Size of IOC JSON must be in the range of 1 - 5000. Current estimated size is: {0}".format(ioc_size))
            exit(1)
        else:
            pass

        # Build JSON
        if api == "live-discover":
            variables_json = [
                {
                    "name": "Number of Hours of activity to search",
                    "dataType": "text",
                    "value": "{0}".format(search_variables[0])
                },
                {
                    "name": "IOC JSON",
                    "dataType": "text",
                    "value": search_variables[1]
                },
                {
                    "name": "Start Search From",
                    "dataType": "dateTime",
                    "value": "{0}".format(date_frmt)
                }
            ]
        elif api == "xdr-datalake":
            variables_json = [
                {
                    "name": "IOC_JSON",
                    "dataType": "text",
                    "value": search_variables[0]
                }
            ]
    else:
        logging.info("No variables passed")
        variables_json = None

    # Auth and get tenant information
    tenant_info = api_auth.ten_auth()

    # Generate tenant url data
    tenant_url_data = api_utils.generate_tenant_urls(tenant_info, page_size, api, from_str=None, to_str=None)

    for key, value in tenant_url_data.items():
        # If a tenant has been passed in the CLI arguments it checks whether it exists in the tenants obtained
        if tenant == key:
            # The tenant passed has been found
            logging.info("Tenant ID passed: '{0}'".format(key))
            tenant_url_data = {key: value}
        else:
            pass

    # kick off live discover search
    if search_type == "list":
        query_data = sld.live_discover(tenant_url_data, search_type, search_val, search_filter, variables_json, api)
        if output == 'json':
            api_output.process_output_json(query_data, "{0}_query_list.json".format(api), api)
        else:
            for key, value in query_data.items():
                print(json.dumps(value, indent=2))
    else:
        ld_data, ep_data, res_data = sld.live_discover(tenant_url_data, search_type, search_val, search_filter,
                                                       variables_json, api)
        # output results to temp

        # get datetime for files
        filetime = datetime.datetime.utcnow()
        filetimestamp = filetime.timestamp()

        if ep_data:
            api_output.process_output_json(ep_data, "{0}_endpoint_data_{1}.json".format(api, filetimestamp), api)
        else:
            logging.info("No EP data to output")

        api_output.process_output_json(ld_data, "{0}_search_data_{1}.json".format(api, filetimestamp), api)
        api_output.process_output_json(res_data, "{0}_result_data_{1}.json".format(api, filetimestamp), api)

    logging.info("Script complete")
    exit(0)