diff --git a/prowler/__main__.py b/prowler/__main__.py index f6c0a87dec..fd006dd1c4 100644 --- a/prowler/__main__.py +++ b/prowler/__main__.py @@ -59,11 +59,11 @@ def prowler(): # Save Arguments provider = args.provider - checks = args.checks - excluded_checks = args.excluded_checks - excluded_services = args.excluded_services - services = args.services - categories = args.categories + checks = args.check + excluded_checks = args.excluded_check + excluded_services = args.excluded_service + services = args.service + categories = args.category checks_file = args.checks_file checks_folder = args.checks_folder severities = args.severity @@ -75,10 +75,10 @@ def prowler(): # We treat the compliance framework as another output format if compliance_framework: - args.output_modes.extend(compliance_framework) + args.output_formats.extend(compliance_framework) # If no input compliance framework, set all else: - args.output_modes.extend(get_available_compliance_frameworks(provider)) + args.output_formats.extend(get_available_compliance_frameworks(provider)) # Set Logger configuration set_logging_config(args.log_level, args.log_file, args.only_logs) @@ -229,8 +229,8 @@ def prowler(): ) sys.exit(1) - if args.output_modes: - for mode in args.output_modes: + if args.output_formats: + for mode in args.output_formats: # Close json file if exists if "json" in mode: close_json( @@ -282,14 +282,14 @@ def prowler(): # Prepare the findings to be sent to Security Hub security_hub_findings_per_region = prepare_security_hub_findings( findings, - provider, + global_provider, global_provider.output_options, aws_security_enabled_regions, ) # Send the findings to Security Hub findings_sent_to_security_hub = batch_send_to_security_hub( - security_hub_findings_per_region, provider.session.current_session + security_hub_findings_per_region, global_provider.session.current_session ) print( @@ -303,7 +303,7 @@ def prowler(): ) findings_archived_in_security_hub = resolve_security_hub_previous_findings( security_hub_findings_per_region, - provider, + global_provider, ) print( f"{Style.BRIGHT}{Fore.GREEN}\n{findings_archived_in_security_hub} findings archived in AWS Security Hub!{Style.RESET_ALL}" diff --git a/prowler/lib/cli/parser.py b/prowler/lib/cli/parser.py index a0118e597b..a0ab46432a 100644 --- a/prowler/lib/cli/parser.py +++ b/prowler/lib/cli/parser.py @@ -25,24 +25,29 @@ def __init__(self): prog="prowler", formatter_class=RawTextHelpFormatter, epilog=""" -To see the different available options on a specific provider, run: - prowler {provider} -h|--help -Detailed documentation at https://docs.prowler.cloud +Available components: + dashboard Prowler local dashboard + + +To see the different available options on a specific component, run: + prowler {provider|dashboard} -h|--help + +Detailed documentation at https://docs.prowler.com """, ) # Default self.parser.add_argument( - "-v", "--version", + "-v", action="store_true", - help="show Prowler version", + help="Show Prowler version", ) # Common arguments parser self.common_providers_parser = argparse.ArgumentParser(add_help=False) # Providers Parser self.subparsers = self.parser.add_subparsers( - title="Prowler Available Cloud Providers", + title="Available cloud providers", dest="provider", ) @@ -126,22 +131,23 @@ def __init_outputs_parser__(self): choices=finding_statuses, ) common_outputs_parser.add_argument( - "-M", + "--output-formats", "--output-modes", + "-M", nargs="+", - help="Output modes, by default csv and json", + help="Output modes, by default csv and json-oscf are saved. When using AWS Security Hub integration, json-asff output is also saved.", default=["csv", "json-ocsf"], choices=["csv", "json-asff", "json-ocsf"], ) common_outputs_parser.add_argument( - "-F", "--output-filename", + "-F", nargs="?", help="Custom output report name without the file extension, if not specified will use default output/prowler-output-ACCOUNT_NUM-OUTPUT_DATE.format", ) common_outputs_parser.add_argument( - "-o", "--output-directory", + "-o", nargs="?", help="Custom output directory, by default the folder where Prowler is stored", default=default_output_directory, @@ -149,21 +155,16 @@ def __init_outputs_parser__(self): common_outputs_parser.add_argument( "--verbose", action="store_true", - help="Display detailed information about findings", + help="Runs showing all checks executed and results", ) common_outputs_parser.add_argument( - "-z", "--ignore-exit-code-3", + "-z", action="store_true", help="Failed checks do not trigger exit code 3", ) common_outputs_parser.add_argument( - "-b", "--no-banner", action="store_true", help="Hide Prowler banner" - ) - common_outputs_parser.add_argument( - "--slack", - action="store_true", - help="Send a summary of the execution with a Slack APP in your channel. Environment variables SLACK_API_TOKEN and SLACK_CHANNEL_ID are required (see more in https://docs.prowler.cloud/en/latest/tutorials/integrations/#slack).", + "--no-banner", "-b", action="store_true", help="Hide Prowler banner" ) common_outputs_parser.add_argument( "--unix-timestamp", @@ -201,10 +202,17 @@ def __init_exclude_checks_parser__(self): "Exclude checks/services to run" ) exclude_checks_parser.add_argument( - "-e", "--excluded-checks", nargs="+", help="Checks to exclude" + "--excluded-check", + "--excluded-checks", + "-e", + nargs="+", + help="Checks to exclude", ) exclude_checks_parser.add_argument( - "--excluded-services", nargs="+", help="Services to exclude" + "--excluded-service", + "--excluded-services", + nargs="+", + help="Services to exclude", ) def __init_checks_parser__(self): @@ -215,21 +223,29 @@ def __init_checks_parser__(self): # The following arguments needs to be set exclusivelly group = common_checks_parser.add_mutually_exclusive_group() group.add_argument( - "-c", "--checks", nargs="+", help="List of checks to be executed." + "--check", + "--checks", + "-c", + nargs="+", + help="List of checks to be executed.", ) group.add_argument( - "-C", "--checks-file", + "-C", nargs="?", help="JSON file containing the checks to be executed. See config/checklist_example.json", ) group.add_argument( - "-s", "--services", nargs="+", help="List of services to be executed." + "--service", + "--services", + "-s", + nargs="+", + help="List of services to be executed.", ) common_checks_parser.add_argument( "--severity", nargs="+", - help=f"List of severities to be executed {valid_severities}", + help=f"Severities to be executed {valid_severities}", choices=valid_severities, ) group.add_argument( @@ -239,15 +255,16 @@ def __init_checks_parser__(self): choices=available_compliance_frameworks, ) group.add_argument( + "--category", "--categories", nargs="+", help="List of categories to be executed.", default=[], - # Pending validate choices + # TODO: Pending validate choices ) common_checks_parser.add_argument( - "-x", "--checks-folder", + "-x", nargs="?", help="Specify external directory with custom checks (each check must have a folder with the required files, see more in https://docs.prowler.cloud/en/latest/tutorials/misc/#custom-checks).", ) @@ -259,23 +276,27 @@ def __init_list_checks_parser__(self): ) list_group = list_checks_parser.add_mutually_exclusive_group() list_group.add_argument( - "-l", "--list-checks", action="store_true", help="List checks" + "--list-checks", "-l", action="store_true", help="List checks" ) list_group.add_argument( "--list-checks-json", action="store_true", - help="Output a list of checks in json for use with --checks-file", + help="Output a list of checks in json format to use with --checks-file option", ) list_group.add_argument( - "--list-services", action="store_true", help="List services" + "--list-services", + action="store_true", + help="List covered services by given provider", ) list_group.add_argument( - "--list-compliance", action="store_true", help="List compliance frameworks" + "--list-compliance", + action="store_true", + help="List all available compliance frameworks", ) list_group.add_argument( "--list-compliance-requirements", nargs="+", - help="List compliance requirements for a given compliance framework", + help="List requirements and checks per compliance framework", choices=available_compliance_frameworks, ) list_group.add_argument( @@ -290,8 +311,8 @@ def __init_mutelist_parser__(self): ) provider = sys.argv[1] if len(sys.argv) > 1 else "aws" mutelist_subparser.add_argument( - "-w", "--mutelist-file", + "-w", nargs="?", default=get_default_mute_file_path(provider), help="Path for mutelist yaml file. See example prowler/config/_mutelist.yaml for reference and format. For AWS provider, it also accepts AWS DynamoDB Table, Lambda ARNs or S3 URIs, see more in https://docs.prowler.cloud/en/latest/tutorials/mutelist/", @@ -323,10 +344,15 @@ def __init_third_party_integrations_parser__(self): "3rd Party Integrations" ) third_party_subparser.add_argument( - "-N", "--shodan", + "-N", nargs="?", default=None, metavar="SHODAN_API_KEY", - help="Shodan API key.", + help="Check if any public IPs in your Cloud environments are exposed in Shodan.", + ) + third_party_subparser.add_argument( + "--slack", + action="store_true", + help="Send a summary of the execution with a Slack APP in your channel. Environment variables SLACK_API_TOKEN and SLACK_CHANNEL_ID are required (see more in https://docs.prowler.cloud/en/latest/tutorials/integrations/#slack).", ) diff --git a/prowler/providers/aws/lib/arguments/arguments.py b/prowler/providers/aws/lib/arguments/arguments.py index f8158687f2..b28202d357 100644 --- a/prowler/providers/aws/lib/arguments/arguments.py +++ b/prowler/providers/aws/lib/arguments/arguments.py @@ -14,19 +14,19 @@ def init_parser(self): # Authentication Methods aws_auth_subparser = aws_parser.add_argument_group("Authentication Modes") aws_auth_subparser.add_argument( - "-p", "--profile", + "-p", nargs="?", default=None, help="AWS profile to launch prowler with", ) aws_auth_subparser.add_argument( - "-R", "--role", + "-R", nargs="?", default=None, help="ARN of the role to be assumed", - # Pending ARN validation + # TODO: Pending ARN validation ) aws_auth_subparser.add_argument( "--role-session-name", @@ -41,17 +41,17 @@ def init_parser(self): help="IAM entity enforces MFA so you need to input the MFA ARN and the TOTP", ) aws_auth_subparser.add_argument( - "-T", "--session-duration", + "-T", nargs="?", default=3600, type=validate_session_duration, help="Assumed role session duration in seconds, must be between 900 and 43200. Default: 3600", - # Pending session duration validation + # TODO: Pending session duration validation ) aws_auth_subparser.add_argument( - "-I", "--external-id", + "-I", nargs="?", default=None, help="External ID to be passed when assuming role", @@ -59,9 +59,9 @@ def init_parser(self): # AWS Regions aws_regions_subparser = aws_parser.add_argument_group("AWS Regions") aws_regions_subparser.add_argument( - "-f", "--region", "--filter-region", + "-f", nargs="+", help="AWS region names to run Prowler against", choices=get_aws_available_regions(), @@ -69,18 +69,18 @@ def init_parser(self): # AWS Organizations aws_orgs_subparser = aws_parser.add_argument_group("AWS Organizations") aws_orgs_subparser.add_argument( - "-O", "--organizations-role", + "-O", nargs="?", help="Specify AWS Organizations management role ARN to be assumed, to get Organization metadata", ) # AWS Security Hub aws_security_hub_subparser = aws_parser.add_argument_group("AWS Security Hub") aws_security_hub_subparser.add_argument( - "-S", "--security-hub", + "-S", action="store_true", - help="Send check output to AWS Security Hub", + help="Send check output to AWS Security Hub and save json-asff outuput.", ) aws_security_hub_subparser.add_argument( "--skip-sh-update", @@ -95,8 +95,8 @@ def init_parser(self): # AWS Quick Inventory aws_quick_inventory_subparser = aws_parser.add_argument_group("Quick Inventory") aws_quick_inventory_subparser.add_argument( - "-i", "--quick-inventory", + "-i", action="store_true", help="Run Prowler Quick Inventory. The inventory will be stored in an output csv by default", ) @@ -104,16 +104,16 @@ def init_parser(self): aws_outputs_subparser = aws_parser.add_argument_group("AWS Outputs to S3") aws_outputs_bucket_parser = aws_outputs_subparser.add_mutually_exclusive_group() aws_outputs_bucket_parser.add_argument( - "-B", "--output-bucket", + "-B", nargs="?", type=validate_bucket, default=None, help="Custom output bucket, requires -M and it can work also with -o flag.", ) aws_outputs_bucket_parser.add_argument( - "-D", "--output-bucket-no-assume", + "-D", nargs="?", type=validate_bucket, default=None, @@ -124,6 +124,7 @@ def init_parser(self): aws_based_scans_subparser = aws_parser.add_argument_group("AWS Based Scans") aws_based_scans_parser = aws_based_scans_subparser.add_mutually_exclusive_group() aws_based_scans_parser.add_argument( + "--resource-tag", "--resource-tags", nargs="+", default=None, @@ -131,6 +132,7 @@ def init_parser(self): ) aws_based_scans_parser.add_argument( "--resource-arn", + "--resource-arns", nargs="+", type=arn_type, default=None, diff --git a/prowler/providers/aws/lib/security_hub/security_hub.py b/prowler/providers/aws/lib/security_hub/security_hub.py index f1ab8ea7fc..7202987d9c 100644 --- a/prowler/providers/aws/lib/security_hub/security_hub.py +++ b/prowler/providers/aws/lib/security_hub/security_hub.py @@ -196,6 +196,7 @@ def __send_findings_to_security_hub__( for findings in list_chunked: batch_import = security_hub_client.batch_import_findings(Findings=findings) if batch_import["FailedCount"] > 0: + print(batch_import["FailedCount"]) failed_import = batch_import["FailedFindings"][0] logger.error( f"Failed to send findings to AWS Security Hub -- {failed_import['ErrorCode']} -- {failed_import['ErrorMessage']}" diff --git a/prowler/providers/azure/azure_provider.py b/prowler/providers/azure/azure_provider.py index e39beefbda..c9aefea985 100644 --- a/prowler/providers/azure/azure_provider.py +++ b/prowler/providers/azure/azure_provider.py @@ -36,7 +36,7 @@ class AzureProvider(Provider): def __init__(self, arguments): logger.info("Setting Azure provider ...") - subscription_ids = arguments.subscription_ids + subscription_ids = arguments.subscription_id logger.info("Checking if any credentials mode is set ...") az_cli_auth = arguments.az_cli_auth diff --git a/prowler/providers/azure/lib/arguments/arguments.py b/prowler/providers/azure/lib/arguments/arguments.py index 30cf7a33d7..736b7b5cea 100644 --- a/prowler/providers/azure/lib/arguments/arguments.py +++ b/prowler/providers/azure/lib/arguments/arguments.py @@ -32,6 +32,7 @@ def init_parser(self): # Subscriptions azure_subscriptions_subparser = azure_parser.add_argument_group("Subscriptions") azure_subscriptions_subparser.add_argument( + "--subscription-id", "--subscription-ids", nargs="+", default=[], diff --git a/prowler/providers/common/models.py b/prowler/providers/common/models.py index 4f42d0960a..c4d6c62fea 100644 --- a/prowler/providers/common/models.py +++ b/prowler/providers/common/models.py @@ -28,7 +28,7 @@ class ProviderOutputOptions: def __init__(self, arguments, bulk_checks_metadata): self.status = arguments.status - self.output_modes = arguments.output_modes + self.output_modes = arguments.output_formats self.output_directory = arguments.output_directory self.verbose = arguments.verbose self.bulk_checks_metadata = bulk_checks_metadata @@ -43,8 +43,8 @@ def __init__(self, arguments, bulk_checks_metadata): # Check output directory, if it is not created -> create it if arguments.output_directory: if not isdir(arguments.output_directory): - if arguments.output_modes: + if arguments.output_formats: makedirs(arguments.output_directory, exist_ok=True) if not isdir(arguments.output_directory + "/compliance"): - if arguments.output_modes: + if arguments.output_formats: makedirs(arguments.output_directory + "/compliance", exist_ok=True) diff --git a/prowler/providers/gcp/gcp_provider.py b/prowler/providers/gcp/gcp_provider.py index d819a6f256..4cd718501f 100644 --- a/prowler/providers/gcp/gcp_provider.py +++ b/prowler/providers/gcp/gcp_provider.py @@ -34,7 +34,7 @@ class GcpProvider(Provider): def __init__(self, arguments): logger.info("Instantiating GCP Provider ...") - input_project_ids = arguments.project_ids + input_project_ids = arguments.project_id credentials_file = arguments.credentials_file self._session = self.setup_session(credentials_file) diff --git a/prowler/providers/gcp/lib/arguments/arguments.py b/prowler/providers/gcp/lib/arguments/arguments.py index e7892105e0..e7f797b09e 100644 --- a/prowler/providers/gcp/lib/arguments/arguments.py +++ b/prowler/providers/gcp/lib/arguments/arguments.py @@ -15,6 +15,7 @@ def init_parser(self): # Subscriptions gcp_subscriptions_subparser = gcp_parser.add_argument_group("Projects") gcp_subscriptions_subparser.add_argument( + "--project-id", "--project-ids", nargs="+", default=[], diff --git a/prowler/providers/kubernetes/kubernetes_provider.py b/prowler/providers/kubernetes/kubernetes_provider.py index edd9b28640..2e2b062df0 100644 --- a/prowler/providers/kubernetes/kubernetes_provider.py +++ b/prowler/providers/kubernetes/kubernetes_provider.py @@ -37,11 +37,11 @@ def __init__(self, arguments: Namespace): """ logger.info("Instantiating Kubernetes Provider ...") self._session = self.setup_session(arguments.kubeconfig_file, arguments.context) - if not arguments.namespaces: + if not arguments.namespace: logger.info("Retrieving all namespaces ...") self._namespaces = self.get_all_namespaces() else: - self._namespaces = arguments.namespaces + self._namespaces = arguments.namespace if not self._session.api_client: logger.critical("Failed to set up a Kubernetes session.") diff --git a/prowler/providers/kubernetes/lib/arguments/arguments.py b/prowler/providers/kubernetes/lib/arguments/arguments.py index dad68041fb..27be298baa 100644 --- a/prowler/providers/kubernetes/lib/arguments/arguments.py +++ b/prowler/providers/kubernetes/lib/arguments/arguments.py @@ -20,6 +20,7 @@ def init_parser(self): help="The name of the kubeconfig context to use. By default, current_context from config file will be used.", ) k8s_auth_subparser.add_argument( + "--namespace", "--namespaces", nargs="+", metavar="NAMESPACES", diff --git a/tests/lib/cli/parser_test.py b/tests/lib/cli/parser_test.py index b30e92547f..9a0c405603 100644 --- a/tests/lib/cli/parser_test.py +++ b/tests/lib/cli/parser_test.py @@ -16,7 +16,9 @@ # capsys # https://docs.pytest.org/en/7.1.x/how-to/capture-stdout-stderr.html -prowler_default_usage_error = "usage: prowler [-h] [-v] {aws,azure,gcp,kubernetes} ..." +prowler_default_usage_error = ( + "usage: prowler [-h] [--version] {aws,azure,gcp,kubernetes} ..." +) def mock_get_available_providers(): @@ -42,9 +44,9 @@ def test_default_parser_no_arguments_aws(self): parsed = self.parser.parse(command) assert parsed.provider == provider assert not parsed.status - assert len(parsed.output_modes) == 2 - assert "csv" in parsed.output_modes - assert "json-ocsf" in parsed.output_modes + assert len(parsed.output_formats) == 2 + assert "csv" in parsed.output_formats + assert "json-ocsf" in parsed.output_formats assert not parsed.output_filename assert "output" in parsed.output_directory assert not parsed.verbose @@ -54,15 +56,15 @@ def test_default_parser_no_arguments_aws(self): assert parsed.log_level == "CRITICAL" assert not parsed.log_file assert not parsed.only_logs - assert not parsed.checks + assert not parsed.check assert not parsed.checks_file assert not parsed.checks_folder - assert not parsed.services + assert not parsed.service assert not parsed.severity assert not parsed.compliance - assert len(parsed.categories) == 0 - assert not parsed.excluded_checks - assert not parsed.excluded_services + assert len(parsed.category) == 0 + assert not parsed.excluded_check + assert not parsed.excluded_service assert not parsed.list_checks assert not parsed.list_services assert not parsed.list_compliance @@ -79,7 +81,7 @@ def test_default_parser_no_arguments_aws(self): assert not parsed.output_bucket assert not parsed.output_bucket_no_assume assert not parsed.shodan - assert not parsed.resource_tags + assert not parsed.resource_tag assert not parsed.scan_unused_services def test_default_parser_no_arguments_azure(self): @@ -88,9 +90,9 @@ def test_default_parser_no_arguments_azure(self): parsed = self.parser.parse(command) assert parsed.provider == provider assert not parsed.status - assert len(parsed.output_modes) == 2 - assert "csv" in parsed.output_modes - assert "json-ocsf" in parsed.output_modes + assert len(parsed.output_formats) == 2 + assert "csv" in parsed.output_formats + assert "json-ocsf" in parsed.output_formats assert not parsed.output_filename assert "output" in parsed.output_directory assert not parsed.verbose @@ -100,21 +102,21 @@ def test_default_parser_no_arguments_azure(self): assert parsed.log_level == "CRITICAL" assert not parsed.log_file assert not parsed.only_logs - assert not parsed.checks + assert not parsed.check assert not parsed.checks_file assert not parsed.checks_folder - assert not parsed.services + assert not parsed.service assert not parsed.severity assert not parsed.compliance - assert len(parsed.categories) == 0 - assert not parsed.excluded_checks - assert not parsed.excluded_services + assert len(parsed.category) == 0 + assert not parsed.excluded_check + assert not parsed.excluded_service assert not parsed.list_checks assert not parsed.list_services assert not parsed.list_compliance assert not parsed.list_compliance_requirements assert not parsed.list_categories - assert len(parsed.subscription_ids) == 0 + assert len(parsed.subscription_id) == 0 assert not parsed.az_cli_auth assert not parsed.sp_env_auth assert not parsed.browser_auth @@ -127,9 +129,9 @@ def test_default_parser_no_arguments_gcp(self): parsed = self.parser.parse(command) assert parsed.provider == provider assert not parsed.status - assert len(parsed.output_modes) == 2 - assert "csv" in parsed.output_modes - assert "json-ocsf" in parsed.output_modes + assert len(parsed.output_formats) == 2 + assert "csv" in parsed.output_formats + assert "json-ocsf" in parsed.output_formats assert not parsed.output_filename assert "output" in parsed.output_directory assert not parsed.verbose @@ -139,15 +141,15 @@ def test_default_parser_no_arguments_gcp(self): assert parsed.log_level == "CRITICAL" assert not parsed.log_file assert not parsed.only_logs - assert not parsed.checks + assert not parsed.check assert not parsed.checks_file assert not parsed.checks_folder - assert not parsed.services + assert not parsed.service assert not parsed.severity assert not parsed.compliance - assert len(parsed.categories) == 0 - assert not parsed.excluded_checks - assert not parsed.excluded_services + assert len(parsed.category) == 0 + assert not parsed.excluded_check + assert not parsed.excluded_service assert not parsed.list_checks assert not parsed.list_services assert not parsed.list_compliance @@ -161,9 +163,9 @@ def test_default_parser_no_arguments_kubernetes(self): parsed = self.parser.parse(command) assert parsed.provider == provider assert not parsed.severity - assert len(parsed.output_modes) == 2 - assert "csv" in parsed.output_modes - assert "json-ocsf" in parsed.output_modes + assert len(parsed.output_formats) == 2 + assert "csv" in parsed.output_formats + assert "json-ocsf" in parsed.output_formats assert not parsed.output_filename assert "output" in parsed.output_directory assert not parsed.verbose @@ -173,15 +175,15 @@ def test_default_parser_no_arguments_kubernetes(self): assert parsed.log_level == "CRITICAL" assert not parsed.log_file assert not parsed.only_logs - assert not parsed.checks + assert not parsed.check assert not parsed.checks_file assert not parsed.checks_folder - assert not parsed.services + assert not parsed.service assert not parsed.severity assert not parsed.compliance - assert len(parsed.categories) == 0 - assert not parsed.excluded_checks - assert not parsed.excluded_services + assert len(parsed.category) == 0 + assert not parsed.excluded_check + assert not parsed.excluded_service assert not parsed.list_checks assert not parsed.list_services assert not parsed.list_compliance @@ -189,7 +191,7 @@ def test_default_parser_no_arguments_kubernetes(self): assert not parsed.list_categories assert not parsed.kubeconfig_file assert not parsed.context - assert not parsed.namespaces + assert not parsed.namespace def test_root_parser_version_short(self): command = [prowler_command, "-v"] @@ -259,36 +261,36 @@ def test_root_parser_exit_code_3_long(self): parsed = self.parser.parse(command) assert parsed.ignore_exit_code_3 - def test_root_parser_default_output_modes(self): + def test_root_parser_default_output_formats(self): command = [prowler_command] parsed = self.parser.parse(command) - assert len(parsed.output_modes) == 2 - assert "csv" in parsed.output_modes - assert "json-ocsf" in parsed.output_modes + assert len(parsed.output_formats) == 2 + assert "csv" in parsed.output_formats + assert "json-ocsf" in parsed.output_formats - def test_root_parser_output_modes_short(self): + def test_root_parser_output_formats_short(self): command = [prowler_command, "-M", "csv"] parsed = self.parser.parse(command) - assert len(parsed.output_modes) == 1 - assert "csv" in parsed.output_modes + assert len(parsed.output_formats) == 1 + assert "csv" in parsed.output_formats - def test_root_parser_output_modes_long(self): + def test_root_parser_output_formats_long(self): command = [prowler_command, "--output-modes", "csv"] parsed = self.parser.parse(command) - assert len(parsed.output_modes) == 1 - assert "csv" in parsed.output_modes + assert len(parsed.output_formats) == 1 + assert "csv" in parsed.output_formats - def test_root_parser_output_modes_short_json_ocsf(self): + def test_root_parser_output_formats_short_json_ocsf(self): command = [prowler_command, "-M", "json-ocsf"] parsed = self.parser.parse(command) - assert len(parsed.output_modes) == 1 - assert "json-ocsf" in parsed.output_modes + assert len(parsed.output_formats) == 1 + assert "json-ocsf" in parsed.output_formats - def test_root_parser_output_modes_long_json_ocsf(self): + def test_root_parser_output_formats_long_json_ocsf(self): command = [prowler_command, "--output-modes", "json-ocsf"] parsed = self.parser.parse(command) - assert len(parsed.output_modes) == 1 - assert "json-ocsf" in parsed.output_modes + assert len(parsed.output_formats) == 1 + assert "json-ocsf" in parsed.output_formats def test_root_parser_output_filename_short(self): filename = "test_output.txt" @@ -402,22 +404,22 @@ def test_exclude_checks_parser_excluded_checks_short(self): excluded_checks = "check_test" command = [prowler_command, "-e", excluded_checks] parsed = self.parser.parse(command) - assert excluded_checks in parsed.excluded_checks + assert excluded_checks in parsed.excluded_check def test_exclude_checks_parser_excluded_checks_short_two(self): excluded_checks_1 = "check_test_1" excluded_checks_2 = "check_test_2" command = [prowler_command, "-e", excluded_checks_1, excluded_checks_2] parsed = self.parser.parse(command) - assert len(parsed.excluded_checks) == 2 - assert excluded_checks_1 in parsed.excluded_checks - assert excluded_checks_2 in parsed.excluded_checks + assert len(parsed.excluded_check) == 2 + assert excluded_checks_1 in parsed.excluded_check + assert excluded_checks_2 in parsed.excluded_check def test_exclude_checks_parser_excluded_checks_long(self): excluded_check = "check_test" command = [prowler_command, "--excluded-checks", excluded_check] parsed = self.parser.parse(command) - assert excluded_check in parsed.excluded_checks + assert excluded_check in parsed.excluded_check def test_exclude_checks_parser_excluded_checks_long_two(self): excluded_checks_1 = "check_test_1" @@ -429,15 +431,15 @@ def test_exclude_checks_parser_excluded_checks_long_two(self): excluded_checks_2, ] parsed = self.parser.parse(command) - assert len(parsed.excluded_checks) == 2 - assert excluded_checks_1 in parsed.excluded_checks - assert excluded_checks_2 in parsed.excluded_checks + assert len(parsed.excluded_check) == 2 + assert excluded_checks_1 in parsed.excluded_check + assert excluded_checks_2 in parsed.excluded_check def test_exclude_checks_parser_excluded_services_long(self): excluded_service = "accessanalyzer" command = [prowler_command, "--excluded-services", excluded_service] parsed = self.parser.parse(command) - assert excluded_service in parsed.excluded_services + assert excluded_service in parsed.excluded_service def test_exclude_checks_parser_excluded_services_long_two(self): excluded_service_1 = "accessanalyzer" @@ -449,17 +451,17 @@ def test_exclude_checks_parser_excluded_services_long_two(self): excluded_service_2, ] parsed = self.parser.parse(command) - assert len(parsed.excluded_services) == 2 - assert excluded_service_1 in parsed.excluded_services - assert excluded_service_2 in parsed.excluded_services + assert len(parsed.excluded_service) == 2 + assert excluded_service_1 in parsed.excluded_service + assert excluded_service_2 in parsed.excluded_service def test_checks_parser_checks_short(self): check = "check_test_1" argument = "-c" command = [prowler_command, argument, check] parsed = self.parser.parse(command) - assert len(parsed.checks) == 1 - assert check in parsed.checks + assert len(parsed.check) == 1 + assert check in parsed.check def test_checks_parser_checks_short_two(self): check_1 = "check_test_1" @@ -467,17 +469,17 @@ def test_checks_parser_checks_short_two(self): argument = "-c" command = [prowler_command, argument, check_1, check_2] parsed = self.parser.parse(command) - assert len(parsed.checks) == 2 - assert check_1 in parsed.checks - assert check_2 in parsed.checks + assert len(parsed.check) == 2 + assert check_1 in parsed.check + assert check_2 in parsed.check def test_checks_parser_checks_long(self): check = "check_test_1" argument = "--checks" command = [prowler_command, argument, check] parsed = self.parser.parse(command) - assert len(parsed.checks) == 1 - assert check in parsed.checks + assert len(parsed.check) == 1 + assert check in parsed.check def test_checks_parser_checks_long_two(self): check_1 = "check_test_1" @@ -485,9 +487,9 @@ def test_checks_parser_checks_long_two(self): argument = "--checks" command = [prowler_command, argument, check_1, check_2] parsed = self.parser.parse(command) - assert len(parsed.checks) == 2 - assert check_1 in parsed.checks - assert check_2 in parsed.checks + assert len(parsed.check) == 2 + assert check_1 in parsed.check + assert check_2 in parsed.check def test_checks_parser_checks_file_short(self): argument = "-C" @@ -522,7 +524,7 @@ def test_checks_parser_services_short(self): service_1 = "iam" command = [prowler_command, argument, service_1] parsed = self.parser.parse(command) - assert service_1 in parsed.services + assert service_1 in parsed.service def test_checks_parser_services_short_two(self): argument = "-s" @@ -530,16 +532,16 @@ def test_checks_parser_services_short_two(self): service_2 = "s3" command = [prowler_command, argument, service_1, service_2] parsed = self.parser.parse(command) - assert len(parsed.services) == 2 - assert service_1 in parsed.services - assert service_2 in parsed.services + assert len(parsed.service) == 2 + assert service_1 in parsed.service + assert service_2 in parsed.service def test_checks_parser_services_long(self): argument = "--services" service_1 = "iam" command = [prowler_command, argument, service_1] parsed = self.parser.parse(command) - assert service_1 in parsed.services + assert service_1 in parsed.service def test_checks_parser_services_long_two(self): argument = "--services" @@ -547,9 +549,9 @@ def test_checks_parser_services_long_two(self): service_2 = "s3" command = [prowler_command, argument, service_1, service_2] parsed = self.parser.parse(command) - assert len(parsed.services) == 2 - assert service_1 in parsed.services - assert service_2 in parsed.services + assert len(parsed.service) == 2 + assert service_1 in parsed.service + assert service_2 in parsed.service def test_checks_parser_services_with_severity(self): argument1 = "--services" @@ -558,8 +560,8 @@ def test_checks_parser_services_with_severity(self): severity = "low" command = [prowler_command, argument1, service_1, argument2, severity] parsed = self.parser.parse(command) - assert len(parsed.services) == 1 - assert service_1 in parsed.services + assert len(parsed.service) == 1 + assert service_1 in parsed.service assert len(parsed.severity) == 1 assert severity in parsed.severity @@ -654,8 +656,8 @@ def test_checks_parser_categories(self): category = "secrets" command = [prowler_command, argument, category] parsed = self.parser.parse(command) - assert len(parsed.categories) == 1 - assert category in parsed.categories + assert len(parsed.category) == 1 + assert category in parsed.category def test_checks_parser_categories_two(self): argument = "--categories" @@ -663,9 +665,9 @@ def test_checks_parser_categories_two(self): category_2 = "forensics" command = [prowler_command, argument, category_1, category_2] parsed = self.parser.parse(command) - assert len(parsed.categories) == 2 - assert category_1 in parsed.categories - assert category_2 in parsed.categories + assert len(parsed.category) == 2 + assert category_1 in parsed.category + assert category_2 in parsed.category def test_list_checks_parser_list_checks_short(self): argument = "-l" @@ -1011,9 +1013,9 @@ def test_aws_parser_resource_tags(self): scan_tag2 = "Key2=Value2" command = [prowler_command, argument, scan_tag1, scan_tag2] parsed = self.parser.parse(command) - assert len(parsed.resource_tags) == 2 - assert scan_tag1 in parsed.resource_tags - assert scan_tag2 in parsed.resource_tags + assert len(parsed.resource_tag) == 2 + assert scan_tag1 in parsed.resource_tag + assert scan_tag2 in parsed.resource_tag def test_aws_parser_resource_arn(self): argument = "--resource-arn" @@ -1118,16 +1120,16 @@ def test_parser_azure_auth_managed_identity(self): assert parsed.provider == "azure" assert parsed.managed_identity_auth - def test_parser_azure_subscription_ids(self): + def test_parser_azure_subscription_id(self): argument = "--subscription-ids" subscription_1 = "test_subscription_1" subscription_2 = "test_subscription_2" command = [prowler_command, "azure", argument, subscription_1, subscription_2] parsed = self.parser.parse(command) assert parsed.provider == "azure" - assert len(parsed.subscription_ids) == 2 - assert parsed.subscription_ids[0] == subscription_1 - assert parsed.subscription_ids[1] == subscription_2 + assert len(parsed.subscription_id) == 2 + assert parsed.subscription_id[0] == subscription_1 + assert parsed.subscription_id[1] == subscription_2 def test_parser_azure_region(self): argument = "--azure-region" @@ -1169,16 +1171,16 @@ def test_parser_gcp_auth_credentials_file(self): assert parsed.provider == "gcp" assert parsed.credentials_file == file - def test_parser_gcp_project_ids(self): - argument = "--project-ids" + def test_parser_gcp_project_id(self): + argument = "--project-id" project_1 = "test_project_1" project_2 = "test_project_2" command = [prowler_command, "gcp", argument, project_1, project_2] parsed = self.parser.parse(command) assert parsed.provider == "gcp" - assert len(parsed.project_ids) == 2 - assert parsed.project_ids[0] == project_1 - assert parsed.project_ids[1] == project_2 + assert len(parsed.project_id) == 2 + assert parsed.project_id[0] == project_1 + assert parsed.project_id[1] == project_2 def test_parser_kubernetes_auth_kubeconfig_file(self): argument = "--kubeconfig-file" @@ -1197,13 +1199,13 @@ def test_parser_kubernetes_auth_context(self): assert parsed.context == context def test_parser_kubernetes_auth_namespace(self): - argument = "--namespaces" + argument = "--namespace" namespace_1 = "default" namespace_2 = "kube-system" command = [prowler_command, "kubernetes", argument, namespace_1, namespace_2] parsed = self.parser.parse(command) assert parsed.provider == "kubernetes" - assert parsed.namespaces == [namespace_1, namespace_2] + assert parsed.namespace == [namespace_1, namespace_2] def test_validate_azure_region_valid_regions(self): expected_regions = [ diff --git a/tests/providers/aws/aws_provider_test.py b/tests/providers/aws/aws_provider_test.py index d66613f77e..1a5a9a62de 100644 --- a/tests/providers/aws/aws_provider_test.py +++ b/tests/providers/aws/aws_provider_test.py @@ -809,7 +809,7 @@ def test_aws_provider_resource_tags(self): def test_set_provider_output_options_aws_no_output_filename(self): arguments = Namespace() arguments.status = ["FAIL"] - arguments.output_modes = ["csv"] + arguments.output_formats = ["csv"] arguments.output_directory = "output_test_directory" arguments.verbose = True arguments.security_hub = True @@ -851,7 +851,7 @@ def test_set_provider_output_options_aws_no_output_filename(self): def test_set_provider_output_options_aws(self): arguments = Namespace() arguments.status = [] - arguments.output_modes = ["csv"] + arguments.output_formats = ["csv"] arguments.output_directory = "output_test_directory" arguments.verbose = True arguments.output_filename = "output_test_filename" diff --git a/tests/providers/aws/utils.py b/tests/providers/aws/utils.py index 68a55fa61a..13a3d67a72 100644 --- a/tests/providers/aws/utils.py +++ b/tests/providers/aws/utils.py @@ -116,7 +116,7 @@ def set_mocked_aws_provider( def set_default_provider_arguments(arguments: Namespace) -> Namespace: arguments.status = [] - arguments.output_modes = [] + arguments.output_formats = [] arguments.output_directory = "" arguments.verbose = False arguments.only_logs = False diff --git a/tests/providers/azure/azure_provider_test.py b/tests/providers/azure/azure_provider_test.py index a4c3c85936..c41ede196a 100644 --- a/tests/providers/azure/azure_provider_test.py +++ b/tests/providers/azure/azure_provider_test.py @@ -19,7 +19,7 @@ class TestAzureProvider: def test_azure_provider(self): arguments = Namespace() - arguments.subscription_ids = None + arguments.subscription_id = None arguments.tenant_id = None # We need to set exactly one auth method arguments.az_cli_auth = True @@ -63,7 +63,7 @@ def test_azure_provider(self): def test_azure_provider_not_auth_methods(self): arguments = Namespace() - arguments.subscription_ids = None + arguments.subscription_id = None arguments.tenant_id = None # We need to set exactly one auth method arguments.az_cli_auth = None @@ -92,7 +92,7 @@ def test_azure_provider_not_auth_methods(self): def test_azure_provider_browser_auth_but_not_tenant_id(self): arguments = Namespace() - arguments.subscription_ids = None + arguments.subscription_id = None arguments.tenant_id = None # We need to set exactly one auth method arguments.az_cli_auth = None @@ -121,7 +121,7 @@ def test_azure_provider_browser_auth_but_not_tenant_id(self): def test_azure_provider_not_browser_auth_but_tenant_id(self): arguments = Namespace() - arguments.subscription_ids = None + arguments.subscription_id = None arguments.tenant_id = "test-tenant-id" # We need to set exactly one auth method arguments.az_cli_auth = None @@ -151,7 +151,7 @@ def test_azure_provider_not_browser_auth_but_tenant_id(self): @freeze_time(datetime.today()) def test_azure_provider_output_options_with_domain(self): arguments = Namespace() - arguments.subscription_ids = None + arguments.subscription_id = None arguments.tenant_id = None # We need to set exactly one auth method @@ -164,7 +164,7 @@ def test_azure_provider_output_options_with_domain(self): arguments.azure_region = "AzureCloud" # Output Options - arguments.output_modes = ["csv"] + arguments.output_formats = ["csv"] arguments.output_directory = "output_test_directory" arguments.status = [] arguments.verbose = True diff --git a/tests/providers/gcp/gcp_provider_test.py b/tests/providers/gcp/gcp_provider_test.py index 7148c74835..1f8cc242a5 100644 --- a/tests/providers/gcp/gcp_provider_test.py +++ b/tests/providers/gcp/gcp_provider_test.py @@ -13,7 +13,7 @@ class TestGCPProvider: def test_gcp_provider(self): arguments = Namespace() - arguments.project_ids = [] + arguments.project_id = [] arguments.credentials_file = "" arguments.config_file = default_config_file_path @@ -46,13 +46,13 @@ def test_gcp_provider(self): @freeze_time(datetime.today()) def test_gcp_provider_output_options(self): arguments = Namespace() - arguments.project_ids = [] + arguments.project_id = [] arguments.credentials_file = "" arguments.config_file = default_config_file_path # Output options arguments.status = [] - arguments.output_modes = ["csv"] + arguments.output_formats = ["csv"] arguments.output_directory = "output_test_directory" arguments.verbose = True arguments.only_logs = False diff --git a/tests/providers/kubernetes/kubernetes_provider_test.py b/tests/providers/kubernetes/kubernetes_provider_test.py index 15484a883b..21b86e38b1 100644 --- a/tests/providers/kubernetes/kubernetes_provider_test.py +++ b/tests/providers/kubernetes/kubernetes_provider_test.py @@ -47,7 +47,7 @@ def test_kubernetes_provider_no_namespaces( arguments.kubeconfig_file = "dummy_path" arguments.context = None arguments.only_logs = False - arguments.namespaces = None + arguments.namespace = None arguments.config_file = default_config_file_path # Instantiate the KubernetesProvider with mocked arguments @@ -72,10 +72,10 @@ def test_set_provider_output_options_kubernetes(self): arguments.kubeconfig_file = "dummy_path" arguments.context = None arguments.only_logs = False - arguments.namespaces = None + arguments.namespace = None arguments.config_file = default_config_file_path arguments.status = [] - arguments.output_modes = ["csv"] + arguments.output_formats = ["csv"] arguments.output_directory = "output_test_directory" arguments.verbose = True arguments.output_filename = "output_test_filename"