def build_scan_object(self):
     session = cloudpassage.HaloSession(key_id, secret_key,
                                        api_host=api_hostname,
                                        api_port=api_port,
                                        integration_string="SDK-Smoke")
     return_obj = cloudpassage.Scan(session)
     return(return_obj)
Exemplo n.º 2
0
 def scan_all_modules(self, agent_id):
     scan_types = ["csm", "svm"]
     command_ids = []
     unfinished_statuses = ['queued', 'pending']
     server_module = cloudpassage.Server(self.halo_session)
     scan_module = cloudpassage.Scan(self.halo_session)
     raw_scan_results = []
     # Initiate scans
     print "Initiating scans for agent %s" % agent_id
     for scan_type in scan_types:
         command_id = scan_module.initiate_scan(agent_id, scan_type)["id"]
         command_ids.append(command_id)
         print command_id
     # Wait until all are complete
     print "Waiting for all scan jobs to be run"
     while len(command_ids) > 0:
         time.sleep(30)
         for command_id in command_ids:
             print "Checking status of command %s" % command_id
             status = server_module.command_details(agent_id, command_id)
             if status not in unfinished_statuses:
                 command_ids.remove(command_id)
     # Get results
     print "Getting scan results"
     for scan_type in scan_types:
         try:
             results = scan_module.last_scan_results(agent_id, scan_type)
         except CloudPassageValidation as e:
             message = "Error encountered: %s" % str(e)
             result = {"result": message}
         raw_scan_results.append(results)
     # Process and print scan results
     pretty = self.print_pretty_scans(raw_scan_results)
     return
Exemplo n.º 3
0
    def test_verify_and_build_status_params(self):
        bad_list = ["cats"]
        bad_string = "cats"
        good_list = ["running"]
        good_string = "running"
        bad_statuses = [bad_list, bad_string]
        good_statuses = [good_list, good_string]
        scanner = cloudpassage.Scan(None)
        for status in bad_statuses:
            try:
                accepted = scanner.verify_and_build_status_params(status)
            except cloudpassage.CloudPassageValidation:
                accepted = False
            assert accepted is False
        for status in good_statuses:
            accepted = scanner.verify_and_build_status_params(status)
            assert accepted == status

        def test_verify_and_build_module_params(self):
            bad_list = ["cats"]
            bad_string = "cats"
            good_list = ["sam"]
            good_string = "sam"
            bad_modules = [bad_list, bad_string]
            good_modules = [good_list, good_string]
            scanner = cloudpassage.Scan(None)
            for status in bad_modules:
                try:
                    accepted = scanner.verify_and_build_module_params(status)
                except cloudpassage.CloudPassageValidation:
                    accepted = False
                assert accepted is False
            for status in good_modules:
                accepted = scanner.verify_and_build_module_params(status)
                assert accepted == status
Exemplo n.º 4
0
    def hold_for_completion(self, scan_body):
        """Wait for completion and return completed scan.

        This function checks the status from scan_body and if the status is
        queued, pending, or running, we wait and re-query until the status
        indicates completion.

        We don't wait more than 6 minutes for a scan to complete, though.

        Args:
            scan_body(dict): Body of scan from API.

        """
        wait_time = 10
        scan = cloudpassage.Scan(self.halo_session)
        # time_waited = 0
        while scan_body["status"] in ["queued", "pending", "running"]:
            # if time_waited >= self.scan_timeout:
            t_delta = Utility.iso_8601_delta(Utility.iso8601_now(),
                                             scan_body["created_at"])
            if abs(t_delta.seconds) > self.scan_timeout:
                print("Not waiting on scan with ID %s anymore...(%s seconds)" %
                      (scan_body["id"], abs(t_delta.seconds)))
                break
            time.sleep(wait_time)
            # time_waited += wait_time
            scan_body = scan.scan_details(scan_body["id"])
        return scan_body
Exemplo n.º 5
0
 def test_scan_type_valid(self):
     valid_types = ["svm", "sva", "csm", "sca", "fim", "sam", "sv"]
     invalid_types = ["death_stare", "lids"]
     scanner = cloudpassage.Scan(None)
     for v in valid_types:
         assert scanner.scan_type_supported(v)
     for i in invalid_types:
         assert not scanner.scan_type_supported(i)
def main():
    # Set up config and Halo objects.
    config = cloudpassage.ApiKeyManager()
    server_id = os.getenv("SERVER_ID")
    crit_threshold = int(os.getenv("CRITICAL_THRESHOLD"))
    non_crit_threshold = int(os.getenv("NON_CRITICAL_THRESHOLD"))
    halo_session = cloudpassage.HaloSession(config.key_id,
                                            config.secret_key,
                                            api_host=config.api_hostname)
    server_obj = cloudpassage.Server(halo_session)
    scan_obj = cloudpassage.Scan(halo_session)
    # Initiate a scan of the target server
    print("Initiating scan...")
    job_id = scan_obj.initiate_scan(server_id, 'sca')["id"]
    incomplete_statuses = ["queued", "pending", "running"]
    scan_status = "queued"
    while scan_status in incomplete_statuses:
        time.sleep(20)
        print("Waiting for scan %s on server %s to finish (status %s)" %
              (job_id, server_id, scan_status))  # NOQA
        scan_status = server_obj.command_details(server_id, job_id)["status"]
    scan_results = scan_obj.last_scan_results(server_id, 'sca')["scan"]
    over_threshold = False
    threshold_msg = ""
    crit_findings = scan_results["critical_findings_count"]
    non_crit_findings = scan_results["non_critical_findings_count"]
    # Test criticality against threshold
    if crit_findings > crit_threshold:
        threshold_msg += "Critical findings: %s Threshold: %s\n" % (
            crit_findings, crit_threshold)  # NOQA
        if crit_threshold != -1:
            over_threshold = True
        else:
            threshold_msg += "Critical threshold set to -1, not failing.\n"
    if non_crit_findings > non_crit_threshold:
        threshold_msg += "Non-critical findings: %s Threshold: %s\n" % (
            non_crit_findings, non_crit_threshold)  # NOQA
        if non_crit_threshold != -1:
            over_threshold = True
        else:
            threshold_msg += "Non-critical threshold set to -1, not failing.\n"
    # Build findings text
    failed_items = ""
    bad_findings = [
        f for f in scan_results["findings"] if f["status"] == 'bad'
    ]  # NOQA
    for finding in bad_findings:
        msg = "Critical: %s  Rule: %s\n" % (str(
            finding["critical"]), finding["rule_name"])
        failed_items += msg
    output_msg = "\n---\n".join([failed_items, threshold_msg])
    print(output_msg)
    # Exit with 1 if we are over threshold.
    if over_threshold:
        print("Threshold exceeded, this job will be marked Failed")
        sys.exit(1)
    else:
        print("Nothing exceeds thresholds; this job will be marked Passed.")
Exemplo n.º 7
0
 def __init__(self):
     self.key = os.getenv("HALO_API_KEY")
     self.secret = os.getenv("HALO_API_SECRET_KEY")
     self.session = cloudpassage.HaloSession(self.key, self.secret)
     # We go ahead and grab an auth token for all abstractions to use.
     self.session.authenticate_client()
     self.servers = cloudpassage.Server(self.session)
     self.scans = cloudpassage.Scan(self.session)
     return
Exemplo n.º 8
0
 def get(self, scan_id):
     """This wraps other functions that get specific scan details"""
     scan = cloudpassage.Scan(self.halo_session)
     details = scan.scan_details(scan_id)
     details = self.hold_for_completion(details)
     if details["module"] == "fim":
         new_deets = self.enrich_fim(details)
         details["findings"] = None
         details["findings"] = new_deets
     return details
 def test_bad_server_id(self):
     session = cloudpassage.HaloSession(key_id, secret_key,
                                        api_host=api_hostname,
                                        api_port=api_port)
     scanner = cloudpassage.Scan(session)
     scan_type = "svm"
     server_id = "ABC123"
     with pytest.raises(cloudpassage.CloudPassageResourceExistence) as e:
         scanner.initiate_scan(server_id, scan_type)
     assert server_id in str(e)
 def test_bad_scan_type(self):
     session = cloudpassage.HaloSession(key_id, secret_key,
                                        api_host=api_hostname,
                                        api_port=api_port)
     scanner = cloudpassage.Scan(session)
     s_group = cloudpassage.ServerGroup(session)
     scan_type = "barfola"
     server_id = s_group.list_all()[0]["id"]
     with pytest.raises(cloudpassage.CloudPassageValidation) as e:
         scanner.initiate_scan(server_id, scan_type)
     assert 'Unsupported scan type: barfola' in str(e)
 def test_scan_type_valid(self):
     valid_types = ["svm", "sva", "csm", "sca", "fim", "sam", "sv"]
     invalid_types = ["death_stare", "lids"]
     session = cloudpassage.HaloSession(key_id, secret_key,
                                        api_host=api_hostname,
                                        api_port=api_port)
     scanner = cloudpassage.Scan(session)
     for v in valid_types:
         assert scanner.scan_type_supported(v)
     for i in invalid_types:
         assert not scanner.scan_type_supported(i)
Exemplo n.º 12
0
def main():
    global FAIL_EXIT_CODE
    FAIL_EXIT_CODE = int(os.getenv("FAIL_EXIT_CODE", 2))
    start_time = datetime.datetime.now()
    copy_tree("static", "reports/html/static")
    Path("reports/html/cve").mkdir(parents=True, exist_ok=True)

    key = os.getenv("HALO_API_KEY")
    secret = os.getenv("HALO_API_SECRET_KEY")
    module_str = os.getenv("SCAN_MODULE")
    modules = module_str.split(",")
    instance_id = os.getenv("INSTANCE_ID")
    timeout = os.getenv("TIMEOUT")
    max_cvss_threshold = float(os.getenv("MAX_CVSS", 7))

    modules = [module.lower() for module in modules]
    modules = list(set(modules))

    session = cloudpassage.HaloSession(key, secret)
    validate_input(session, modules, instance_id, max_cvss_threshold)

    server = cloudpassage.Server(session)
    scan = cloudpassage.Scan(session)
    group = cloudpassage.ServerGroup(session)

    scanned_server = get_server(server, instance_id, start_time, timeout)

    server_id = scanned_server["id"]
    print(f"Server ID: {server_id}")

    modules = validate_csm(modules, scanned_server, group)

    scans = {}
    for module in modules:
        while True:
            try:
                scan_output = scan.last_scan_results(server_id, module)
            except cloudpassage.CloudPassageResourceExistence:
                check_timeout(start_time, timeout)
                print("Waiting on {} scan to complete...".format(module))
                time.sleep(30)
            if scan_output and "scan" in scan_output:
                scans[module] = scan_output["scan"]
                break
            check_timeout(start_time, timeout)
            print("Waiting on {} scan to complete...".format(module))
            time.sleep(30)

    build_success = process_scan(scans, scanned_server, session)

    if not build_success:
        print("Security scan results did not meet pass criteria")
        sys.exit(FAIL_EXIT_CODE)
 def test_sam_historical_is_unsupported(self):
     rejected = False
     session = cloudpassage.HaloSession(key_id, secret_key,
                                        api_host=api_hostname,
                                        api_port=api_port)
     scanner = cloudpassage.Scan(session)
     server = cloudpassage.Server(session)
     scan_type = "sam"
     server_id = server.list_all()[0]["id"]
     try:
         scanner.last_scan_results(server_id, scan_type)
     except cloudpassage.CloudPassageValidation:
         rejected = True
     assert rejected
Exemplo n.º 14
0
def process_csm(csm_scan, server, session, tests):
    scan = cloudpassage.Scan(session)
    policy = cloudpassage.ConfigurationPolicy(session)
    scan_details = scan.scan_details(csm_scan["id"])
    csm_policy_list = scan_details["policies"]
    csm_policies = [policy.describe(item["id"]) for item in csm_policy_list]
    rules_dict = {}
    for csm_policy in csm_policies:
        for rule in csm_policy["rules"]:
            rules_dict[rule["name"]] = rule

    tests["max_criticals"]["actual"] = csm_scan["critical_findings_count"]
    tests["max_non_criticals"]["actual"] = csm_scan["non_critical_findings_count"]

    if tests["max_criticals"]["actual"] > tests["max_criticals"]["threshold"]:
        tests["max_criticals"]["result"] = False
    if tests["max_non_criticals"]["actual"] > tests["max_non_criticals"]["threshold"]:
        tests["max_non_criticals"]["result"] = False

    bad_findings = [finding for finding in csm_scan["findings"] if finding['status'] == ('bad' or 'indeterminate')]
    scan_time = csm_scan["completed_at"]
    generate_csm_report(tests, bad_findings, server, scan_time, rules_dict, csm_policies)

    return all(v["result"] for v in tests.values())
 def test_instantiation(self):
     session = cloudpassage.HaloSession(key_id, secret_key,
                                        api_host=api_hostname,
                                        api_port=api_port)
     assert cloudpassage.Scan(session)
Exemplo n.º 16
0
def get_scan_data(session):
    mode = "w"
    report_directory = "reports/"
    report_name = "CSM_report_all_events_"
    report_extension = ".csv"

    if not os.path.exists(report_directory):
        os.makedirs(report_directory)

    out_file = "%s%s" % (report_directory, report_name) \
               + time.strftime("%Y%m%d-%H%M%S") + report_extension
    ofile = open(out_file, mode)

    halo_server_list = get_halo_servers_id(session)

    ofile.write('AWS Account ID, Halo Server ID, AWS Instance ID,'
                'CSM Rule Name, '
                'Rule Description, Expected Target Value for Check, Actual '
                'Value\n')

    server_count = 1
    increment = 1
    scan_type = "sca"

    total_servers = len(halo_server_list)

    for server in halo_server_list:
        print "Processing {0} of {1} servers".format(server_count,
                                                     total_servers)
        server_count += increment

        # get the last csm scan
        cp_scan_ob = cloudpassage.Scan(session)
        data = cp_scan_ob.last_scan_results(server['halo_server_id'],
                                            scan_type)

        if 'scan' in data:
            current_findings = data['scan']['findings']

            for finding in current_findings:
                if finding['status'] == 'bad':
                    # and finding['critical'] is True:

                    finding_details = finding['details']

                    for details in finding_details:

                        if details['status'] == 'bad':
                            expected_value = details['expected']

                            # strip commas if var is a str
                            if not isinstance(expected_value, bool):
                                expected_value = str(expected_value)
                                expected_value = \
                                    expected_value.replace(",", " ")

                            # set to space if they key does not exist
                            if 'rule_description' not in finding:
                                rule_description = " "
                            else:
                                # if the key does exist then strip the returns
                                # and newlines and commas
                                rule_description = \
                                    finding['rule_description']
                                rule_description = \
                                    rule_description.replace(",", " ")
                                rule_description = \
                                    rule_description.replace("\r", "")
                                rule_description = \
                                    rule_description.replace("\n", "")

                            row = "'{0}',{1},{2},{3},{4},{5},{6}\n" \
                                  "".format(server['aws_account_id'],
                                            server['halo_server_id'],
                                            server['aws_instance_id'],
                                            finding['rule_name'],
                                            rule_description,
                                            expected_value,
                                            details['actual'])
                            row = str(row)
                            ofile.write(row)

    ofile.close()
Exemplo n.º 17
0
 def test_instantiation(self):
     assert cloudpassage.Scan(None)
Exemplo n.º 18
0
def main():
    # Suspect package names
    suspect_packages = "kubectl,kubeadm,kubelet"

    # Suspect processes URL
    procs_url = "/v2/servers?process_name=kubelet,kubeadm,kubectl,kube-proxy"

    # Minimum versions safe from API auth bug
    kube_min_ver = {
        "1.10": "1.10.11",
        "1.11": "1.11.5",
        "1.12": "1.12.3",
        "1.13": "1.13.0-rc.1"
    }

    # Get Halo auth info
    key = os.getenv("HALO_API_KEY")
    secret = os.getenv("HALO_API_SECRET_KEY")

    # Set up CloudPassage API abstractions
    session = cloudpassage.HaloSession(key, secret)
    servers = cloudpassage.Server(session)
    scans = cloudpassage.Scan(session)
    helper = cloudpassage.HttpHelper(session)

    # Get servers with suspect packages installed
    servers_installed_kube = [
        x for x in servers.list_all(package_name=suspect_packages)
    ]

    # Get servers with suspect processes
    servers_running_kube = [
        x for x in helper.get_paginated(procs_url, "servers", 99)
    ]

    # Print preliminary metrics
    print("Installation match: %s" % len(servers_installed_kube))
    print("Running process match: %s" % len(servers_running_kube))

    # Get a list of all servers with K8s-related procs or packages
    kube_servers = merge_server_lists(servers_installed_kube,
                                      servers_running_kube)
    # Create a dictionary of packages, processes, and metadata for each server.
    inventory = {
        x["id"]: {
            "packages":
            get_package_listing_from_scan(
                scans.last_scan_results(x["id"], "svm")),  # NOQA
            "processes":
            servers.list_processes(x["id"]),
            "server_metadata":
            x
        }
        for x in kube_servers
    }

    # Print a report to stdout
    print("{}{}{}{}{}{}{}".format(
        "Halo ID".ljust(40), "CSP account".ljust(40), "CSP Instance".ljust(40),
        "kubectl version".ljust(20), "kubeadm version".ljust(20),
        "kubelet version".ljust(20), "kubectl vulnerable".ljust(25),
        "kubeadm vulnerable".ljust(25), "kubelet vulnerable".ljust(25),
        "k8s processes(below)"))
    for x in inventory.items():
        server_id = x[0]
        server_csp_id = x[1]["server_metadata"][
            "csp_account_id"] if "csp_account_id" in x[1][
                "server_metadata"] else ""  # NOQA
        server_instance_id = x[1]["server_metadata"][
            "csp_instance_id"] if "csp_instance_id" in x[1][
                "server_metadata"] else ""  # NOQA
        kubectl_version = get_package_version(x[1]["packages"], "kubectl")
        kubeadm_version = get_package_version(x[1]["packages"], "kubeadm")
        kubelet_version = get_package_version(x[1]["packages"], "kubelet")
        kube_procs = get_kube_procs(x[1]["processes"])
        kubectl_vulnerable = is_kube_vulnerable(kube_min_ver, kubectl_version)
        kubeadm_vulnerable = is_kube_vulnerable(kube_min_ver, kubeadm_version)
        kubelet_vulnerable = is_kube_vulnerable(kube_min_ver, kubelet_version)
        print("{}{}{}{}{}{}{}{}{}\n{}\n\n".format(server_id.ljust(40),
                                                  server_csp_id.ljust(40),
                                                  server_instance_id.ljust(40),
                                                  kubectl_version.ljust(16),
                                                  kubeadm_version.ljust(16),
                                                  kubelet_version.ljust(16),
                                                  kubectl_vulnerable.ljust(20),
                                                  kubeadm_vulnerable.ljust(20),
                                                  kubelet_vulnerable.ljust(20),
                                                  kube_procs))
    dump_to_csv(inventory, kube_min_ver)
    dump_to_json(inventory)
Exemplo n.º 19
0
 def __init__(self, config):
     session = cloudpassage.HaloSession(config.halo_key,
                                        config.halo_secret,
                                        api_host=config.halo_url)
     self.scan = cloudpassage.Scan(session)