mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-07-23 12:31:54 +00:00
docs: migrate to Mintlify (#8894)
This commit is contained in:
@@ -0,0 +1,25 @@
|
||||
---
|
||||
title: "Check Aliases"
|
||||
---
|
||||
|
||||
Prowler allows you to use aliases for the checks. You only have to add the `CheckAliases` key to the check's metadata with a list of the aliases:
|
||||
|
||||
```json title="check.metadata.json"
|
||||
"Provider": "<provider>",
|
||||
"CheckID": "<check_id>",
|
||||
"CheckTitle": "<check_title>",
|
||||
"CheckAliases": [
|
||||
"<check_alias_1>"
|
||||
"<check_alias_2>",
|
||||
...
|
||||
],
|
||||
...
|
||||
```
|
||||
|
||||
Then you can execute the check either with its check ID or with one of the previous aliases:
|
||||
|
||||
```shell
|
||||
prowler <provider> -c/--checks <check_alias_1>
|
||||
|
||||
Using alias <check_alias_1> for check <check_id>...
|
||||
```
|
||||
@@ -0,0 +1,80 @@
|
||||
---
|
||||
title: 'Compliance'
|
||||
---
|
||||
|
||||
Prowler allows you to execute checks based on requirements defined in compliance frameworks. By default, it will execute and give you an overview of the status of each compliance framework:
|
||||
|
||||
<img src="/images/cli/compliance/compliance.png" />
|
||||
|
||||
You can find CSVs containing detailed compliance results in the compliance folder within Prowler's output folder.
|
||||
|
||||
## Execute Prowler based on Compliance Frameworks
|
||||
|
||||
Prowler can analyze your environment based on a specific compliance framework and get more details, to do it, you can use option `--compliance`:
|
||||
|
||||
```sh
|
||||
prowler <provider> --compliance <compliance_framework>
|
||||
```
|
||||
|
||||
Standard results will be shown and additionally the framework information as the sample below for CIS AWS 2.0. For details a CSV file has been generated as well.
|
||||
|
||||
<img src="/images/cli/compliance/compliance-cis-sample1.png" />
|
||||
|
||||
<Note>
|
||||
**If Prowler can't find a resource related with a check from a compliance requirement, this requirement won't appear on the output**
|
||||
</Note>
|
||||
|
||||
## List Available Compliance Frameworks
|
||||
|
||||
To see which compliance frameworks are covered by Prowler, use the `--list-compliance` option:
|
||||
|
||||
```sh
|
||||
prowler <provider> --list-compliance
|
||||
```
|
||||
|
||||
Or you can visit [Prowler Hub](https://hub.prowler.com/compliance).
|
||||
|
||||
## List Requirements of Compliance Frameworks
|
||||
To list requirements for a compliance framework, use the `--list-compliance-requirements` option:
|
||||
|
||||
```sh
|
||||
prowler <provider> --list-compliance-requirements <compliance_framework(s)>
|
||||
```
|
||||
|
||||
Example for the first requirements of CIS 1.5 for AWS:
|
||||
|
||||
```
|
||||
Listing CIS 1.5 AWS Compliance Requirements:
|
||||
|
||||
Requirement Id: 1.1
|
||||
- Description: Maintain current contact details
|
||||
- Checks:
|
||||
account_maintain_current_contact_details
|
||||
|
||||
Requirement Id: 1.2
|
||||
- Description: Ensure security contact information is registered
|
||||
- Checks:
|
||||
account_security_contact_information_is_registered
|
||||
|
||||
Requirement Id: 1.3
|
||||
- Description: Ensure security questions are registered in the AWS account
|
||||
- Checks:
|
||||
account_security_questions_are_registered_in_the_aws_account
|
||||
|
||||
Requirement Id: 1.4
|
||||
- Description: Ensure no 'root' user account access key exists
|
||||
- Checks:
|
||||
iam_no_root_access_key
|
||||
|
||||
Requirement Id: 1.5
|
||||
- Description: Ensure MFA is enabled for the 'root' user account
|
||||
- Checks:
|
||||
iam_root_mfa_enabled
|
||||
|
||||
[redacted]
|
||||
|
||||
```
|
||||
|
||||
## Create and contribute adding other Security Frameworks
|
||||
|
||||
This information is part of the Developer Guide and can be found [here](/developer-guide/security-compliance-framework).
|
||||
@@ -0,0 +1,607 @@
|
||||
---
|
||||
title: "Configuration File"
|
||||
---
|
||||
|
||||
Several Prowler's checks have user configurable variables that can be modified in a common **configuration file**. This file can be found in the following [path](https://github.com/prowler-cloud/prowler/blob/master/prowler/config/config.yaml):
|
||||
|
||||
```
|
||||
prowler/config/config.yaml
|
||||
```
|
||||
|
||||
Additionally, you can input a custom configuration file using the `--config-file` argument.
|
||||
|
||||
## AWS
|
||||
|
||||
### Configurable Checks
|
||||
The following list includes all the AWS checks with configurable variables that can be changed in the configuration yaml file:
|
||||
|
||||
| Check Name | Value | Type |
|
||||
|---------------------------------------------------------------|--------------------------------------------------|-----------------|
|
||||
| `acm_certificates_expiration_check` | `days_to_expire_threshold` | Integer |
|
||||
| `appstream_fleet_maximum_session_duration` | `max_session_duration_seconds` | Integer |
|
||||
| `appstream_fleet_session_disconnect_timeout` | `max_disconnect_timeout_in_seconds` | Integer |
|
||||
| `appstream_fleet_session_idle_disconnect_timeout` | `max_idle_disconnect_timeout_in_seconds` | Integer |
|
||||
| `autoscaling_find_secrets_ec2_launch_configuration` | `secrets_ignore_patterns` | List of Strings |
|
||||
| `awslambda_function_no_secrets_in_code` | `secrets_ignore_patterns` | List of Strings |
|
||||
| `awslambda_function_no_secrets_in_variables` | `secrets_ignore_patterns` | List of Strings |
|
||||
| `awslambda_function_using_supported_runtimes` | `obsolete_lambda_runtimes` | Integer |
|
||||
| `awslambda_function_vpc_is_in_multi_azs` | `lambda_min_azs` | Integer |
|
||||
| `cloudformation_stack_outputs_find_secrets` | `secrets_ignore_patterns` | List of Strings |
|
||||
| `cloudtrail_threat_detection_enumeration` | `threat_detection_enumeration_actions` | List of Strings |
|
||||
| `cloudtrail_threat_detection_enumeration` | `threat_detection_enumeration_entropy` | Integer |
|
||||
| `cloudtrail_threat_detection_enumeration` | `threat_detection_enumeration_minutes` | Integer |
|
||||
| `cloudtrail_threat_detection_privilege_escalation` | `threat_detection_privilege_escalation_actions` | List of Strings |
|
||||
| `cloudtrail_threat_detection_privilege_escalation` | `threat_detection_privilege_escalation_entropy` | Integer |
|
||||
| `cloudtrail_threat_detection_privilege_escalation` | `threat_detection_privilege_escalation_minutes` | Integer |
|
||||
| `cloudwatch_log_group_no_secrets_in_logs` | `secrets_ignore_patterns` | List of Strings |
|
||||
| `cloudwatch_log_group_retention_policy_specific_days_enabled` | `log_group_retention_days` | Integer |
|
||||
| `codebuild_github_allowed_organizations` | `github_allowed_organizations` | List of Strings |
|
||||
| `codebuild_project_no_secrets_in_variables` | `excluded_sensitive_environment_variables` | List of Strings |
|
||||
| `codebuild_project_no_secrets_in_variables` | `secrets_ignore_patterns` | List of Strings |
|
||||
| `config_recorder_all_regions_enabled` | `mute_non_default_regions` | Boolean |
|
||||
| `drs_job_exist` | `mute_non_default_regions` | Boolean |
|
||||
| `ec2_elastic_ip_shodan` | `shodan_api_key` | String |
|
||||
| `ec2_instance_older_than_specific_days` | `max_ec2_instance_age_in_days` | Integer |
|
||||
| `ec2_instance_secrets_user_data` | `secrets_ignore_patterns` | List of Strings |
|
||||
| `ec2_launch_template_no_secrets` | `secrets_ignore_patterns` | List of Strings |
|
||||
| `ec2_securitygroup_allow_ingress_from_internet_to_any_port` | `ec2_allowed_instance_owners` | List of Strings |
|
||||
| `ec2_securitygroup_allow_ingress_from_internet_to_any_port` | `ec2_allowed_interface_types` | List of Strings |
|
||||
| `ec2_securitygroup_allow_ingress_from_internet_to_high_risk_tcp_ports`| `ec2_high_risk_ports` | List of Integer |
|
||||
| `ec2_securitygroup_with_many_ingress_egress_rules` | `max_security_group_rules` | Integer |
|
||||
| `ecs_task_definitions_no_environment_secrets` | `secrets_ignore_patterns` | List of Strings |
|
||||
| `ecr_repositories_scan_vulnerabilities_in_latest_image` | `ecr_repository_vulnerability_minimum_severity` | String |
|
||||
| `eks_cluster_uses_a_supported_version` | `eks_cluster_oldest_version_supported` | String |
|
||||
| `eks_control_plane_logging_all_types_enabled` | `eks_required_log_types` | List of Strings |
|
||||
| `elasticache_redis_cluster_backup_enabled` | `minimum_snapshot_retention_period` | Integer |
|
||||
| `elb_is_in_multiple_az` | `elb_min_azs` | Integer |
|
||||
| `elbv2_is_in_multiple_az` | `elbv2_min_azs` | Integer |
|
||||
| `guardduty_is_enabled` | `mute_non_default_regions` | Boolean |
|
||||
| `iam_user_accesskey_unused` | `max_unused_access_keys_days` | Integer |
|
||||
| `iam_user_console_access_unused` | `max_console_access_days` | Integer |
|
||||
| `organizations_delegated_administrators` | `organizations_trusted_delegated_administrators` | List of Strings |
|
||||
| `organizations_scp_check_deny_regions` | `organizations_enabled_regions` | List of Strings |
|
||||
| `rds_instance_backup_enabled` | `check_rds_instance_replicas` | Boolean |
|
||||
| `securityhub_enabled` | `mute_non_default_regions` | Boolean |
|
||||
| `secretsmanager_secret_unused` | `max_days_secret_unused` | Integer |
|
||||
| `secretsmanager_secret_rotated_periodically` | `max_days_secret_unrotated` | Integer |
|
||||
| `ssm_document_secrets` | `secrets_ignore_patterns` | List of Strings |
|
||||
| `trustedadvisor_premium_support_plan_subscribed` | `verify_premium_support_plans` | Boolean |
|
||||
| `vpc_endpoint_connections_trust_boundaries` | `trusted_account_ids` | List of Strings |
|
||||
| `vpc_endpoint_services_allowed_principals_trust_boundaries` | `trusted_account_ids` | List of Strings |
|
||||
|
||||
|
||||
## Azure
|
||||
|
||||
### Configurable Checks
|
||||
The following list includes all the Azure checks with configurable variables that can be changed in the configuration yaml file:
|
||||
|
||||
| Check Name | Value | Type |
|
||||
|---------------------------------------------------------------|--------------------------------------------------|-----------------|
|
||||
| `network_public_ip_shodan` | `shodan_api_key` | String |
|
||||
| `app_ensure_php_version_is_latest` | `php_latest_version` | String |
|
||||
| `app_ensure_python_version_is_latest` | `python_latest_version` | String |
|
||||
| `app_ensure_java_version_is_latest` | `java_latest_version` | String |
|
||||
| `sqlserver_recommended_minimal_tls_version` | `recommended_minimal_tls_versions` | List of Strings |
|
||||
| `vm_sufficient_daily_backup_retention_period` | `vm_backup_min_daily_retention_days` | Integer |
|
||||
| `vm_desired_sku_size` | `desired_vm_sku_sizes` | List of Strings |
|
||||
| `defender_attack_path_notifications_properly_configured` | `defender_attack_path_minimal_risk_level` | String |
|
||||
| `apim_threat_detection_llm_jacking` | `apim_threat_detection_llm_jacking_threshold` | Float |
|
||||
| `apim_threat_detection_llm_jacking` | `apim_threat_detection_llm_jacking_minutes` | Integer |
|
||||
| `apim_threat_detection_llm_jacking` | `apim_threat_detection_llm_jacking_actions` | List of Strings |
|
||||
|
||||
|
||||
## GCP
|
||||
|
||||
### Configurable Checks
|
||||
|
||||
## Kubernetes
|
||||
|
||||
### Configurable Checks
|
||||
The following list includes all the Kubernetes checks with configurable variables that can be changed in the configuration yaml file:
|
||||
|
||||
| Check Name | Value | Type |
|
||||
|---------------------------------------------------------------|--------------------------------------------------|-----------------|
|
||||
| `audit_log_maxbackup` | `audit_log_maxbackup` | String |
|
||||
| `audit_log_maxsize` | `audit_log_maxsize` | String |
|
||||
| `audit_log_maxage` | `audit_log_maxage` | String |
|
||||
| `apiserver_strong_ciphers` | `apiserver_strong_ciphers` | String |
|
||||
| `kubelet_strong_ciphers_only` | `kubelet_strong_ciphers` | String |
|
||||
|
||||
|
||||
## M365
|
||||
|
||||
### Configurable Checks
|
||||
The following list includes all the Microsoft 365 checks with configurable variables that can be changed in the configuration yaml file:
|
||||
|
||||
| Check Name | Value | Type |
|
||||
|---------------------------------------------------------------|--------------------------------------------------|-----------------|
|
||||
| `entra_admin_users_sign_in_frequency_enabled` | `sign_in_frequency` | Integer |
|
||||
| `teams_external_file_sharing_restricted` | `allowed_cloud_storage_services` | List of Strings |
|
||||
| `exchange_organization_mailtips_enabled` | `recommended_mailtips_large_audience_threshold` | Integer |
|
||||
|
||||
|
||||
## GitHub
|
||||
|
||||
### Configurable Checks
|
||||
The following list includes all the GitHub checks with configurable variables that can be changed in the configuration yaml file:
|
||||
|
||||
| Check Name | Value | Type |
|
||||
|--------------------------------------------|---------------------------------------------|---------|
|
||||
| `repository_inactive_not_archived` | `inactive_not_archived_days_threshold` | Integer |
|
||||
|
||||
## Config YAML File Structure
|
||||
|
||||
<Note>
|
||||
This is the new Prowler configuration file format. The old one without provider keys is still compatible just for the AWS provider.
|
||||
|
||||
</Note>
|
||||
```yaml title="config.yaml"
|
||||
# AWS Configuration
|
||||
aws:
|
||||
# AWS Global Configuration
|
||||
# aws.mute_non_default_regions --> Set to True to muted failed findings in non-default regions for AccessAnalyzer, GuardDuty, SecurityHub, DRS and Config
|
||||
mute_non_default_regions: False
|
||||
# If you want to mute failed findings only in specific regions, create a file with the following syntax and run it with `prowler aws -w mutelist.yaml`:
|
||||
# Mutelist:
|
||||
# Accounts:
|
||||
# "*":
|
||||
# Checks:
|
||||
# "*":
|
||||
# Regions:
|
||||
# - "ap-southeast-1"
|
||||
# - "ap-southeast-2"
|
||||
# Resources:
|
||||
# - "*"
|
||||
|
||||
# AWS IAM Configuration
|
||||
# aws.iam_user_accesskey_unused --> CIS recommends 45 days
|
||||
max_unused_access_keys_days: 45
|
||||
# aws.iam_user_console_access_unused --> CIS recommends 45 days
|
||||
max_console_access_days: 45
|
||||
|
||||
# AWS EC2 Configuration
|
||||
# aws.ec2_elastic_ip_shodan
|
||||
# TODO: create common config
|
||||
shodan_api_key: null
|
||||
# aws.ec2_securitygroup_with_many_ingress_egress_rules --> by default is 50 rules
|
||||
max_security_group_rules: 50
|
||||
# aws.ec2_instance_older_than_specific_days --> by default is 6 months (180 days)
|
||||
max_ec2_instance_age_in_days: 180
|
||||
# aws.ec2_securitygroup_allow_ingress_from_internet_to_any_port
|
||||
# allowed network interface types for security groups open to the Internet
|
||||
ec2_allowed_interface_types:
|
||||
[
|
||||
"api_gateway_managed",
|
||||
"vpc_endpoint",
|
||||
]
|
||||
# allowed network interface owners for security groups open to the Internet
|
||||
ec2_allowed_instance_owners:
|
||||
[
|
||||
"amazon-elb"
|
||||
]
|
||||
# aws.ec2_securitygroup_allow_ingress_from_internet_to_high_risk_tcp_ports
|
||||
ec2_high_risk_ports:
|
||||
[
|
||||
25,
|
||||
110,
|
||||
135,
|
||||
143,
|
||||
445,
|
||||
3000,
|
||||
4333,
|
||||
5000,
|
||||
5500,
|
||||
8080,
|
||||
8088,
|
||||
]
|
||||
|
||||
# AWS VPC Configuration (vpc_endpoint_connections_trust_boundaries, vpc_endpoint_services_allowed_principals_trust_boundaries)
|
||||
# AWS SSM Configuration (aws.ssm_documents_set_as_public)
|
||||
# Single account environment: No action required. The AWS account number will be automatically added by the checks.
|
||||
# Multi account environment: Any additional trusted account number should be added as a space separated list, e.g.
|
||||
# trusted_account_ids : ["123456789012", "098765432109", "678901234567"]
|
||||
trusted_account_ids: []
|
||||
|
||||
# AWS Cloudwatch Configuration
|
||||
# aws.cloudwatch_log_group_retention_policy_specific_days_enabled --> by default is 365 days
|
||||
log_group_retention_days: 365
|
||||
|
||||
# AWS AppStream Session Configuration
|
||||
# aws.appstream_fleet_session_idle_disconnect_timeout
|
||||
max_idle_disconnect_timeout_in_seconds: 600 # 10 Minutes
|
||||
# aws.appstream_fleet_session_disconnect_timeout
|
||||
max_disconnect_timeout_in_seconds: 300 # 5 Minutes
|
||||
# aws.appstream_fleet_maximum_session_duration
|
||||
max_session_duration_seconds: 36000 # 10 Hours
|
||||
|
||||
# AWS Lambda Configuration
|
||||
# aws.awslambda_function_using_supported_runtimes
|
||||
obsolete_lambda_runtimes:
|
||||
[
|
||||
"java8",
|
||||
"go1.x",
|
||||
"provided",
|
||||
"python3.6",
|
||||
"python2.7",
|
||||
"python3.7",
|
||||
"nodejs4.3",
|
||||
"nodejs4.3-edge",
|
||||
"nodejs6.10",
|
||||
"nodejs",
|
||||
"nodejs8.10",
|
||||
"nodejs10.x",
|
||||
"nodejs12.x",
|
||||
"nodejs14.x",
|
||||
"dotnet5.0",
|
||||
"dotnetcore1.0",
|
||||
"dotnetcore2.0",
|
||||
"dotnetcore2.1",
|
||||
"dotnetcore3.1",
|
||||
"ruby2.5",
|
||||
"ruby2.7",
|
||||
]
|
||||
|
||||
# AWS Organizations
|
||||
# aws.organizations_scp_check_deny_regions
|
||||
# aws.organizations_enabled_regions: [
|
||||
# "eu-central-1",
|
||||
# "eu-west-1",
|
||||
# "us-east-1"
|
||||
# ]
|
||||
organizations_enabled_regions: []
|
||||
organizations_trusted_delegated_administrators: []
|
||||
|
||||
# AWS ECR
|
||||
# aws.ecr_repositories_scan_vulnerabilities_in_latest_image
|
||||
# CRITICAL
|
||||
# HIGH
|
||||
# MEDIUM
|
||||
ecr_repository_vulnerability_minimum_severity: "MEDIUM"
|
||||
|
||||
# AWS Trusted Advisor
|
||||
# aws.trustedadvisor_premium_support_plan_subscribed
|
||||
verify_premium_support_plans: True
|
||||
|
||||
# AWS CloudTrail Configuration
|
||||
# aws.cloudtrail_threat_detection_privilege_escalation
|
||||
threat_detection_privilege_escalation_threshold: 0.2 # Percentage of actions found to decide if it is an privilege_escalation attack event, by default is 0.2 (20%)
|
||||
threat_detection_privilege_escalation_minutes: 1440 # Past minutes to search from now for privilege_escalation attacks, by default is 1440 minutes (24 hours)
|
||||
threat_detection_privilege_escalation_actions:
|
||||
[
|
||||
"AddPermission",
|
||||
"AddRoleToInstanceProfile",
|
||||
"AddUserToGroup",
|
||||
"AssociateAccessPolicy",
|
||||
"AssumeRole",
|
||||
"AttachGroupPolicy",
|
||||
"AttachRolePolicy",
|
||||
"AttachUserPolicy",
|
||||
"ChangePassword",
|
||||
"CreateAccessEntry",
|
||||
"CreateAccessKey",
|
||||
"CreateDevEndpoint",
|
||||
"CreateEventSourceMapping",
|
||||
"CreateFunction",
|
||||
"CreateGroup",
|
||||
"CreateJob",
|
||||
"CreateKeyPair",
|
||||
"CreateLoginProfile",
|
||||
"CreatePipeline",
|
||||
"CreatePolicyVersion",
|
||||
"CreateRole",
|
||||
"CreateStack",
|
||||
"DeleteRolePermissionsBoundary",
|
||||
"DeleteRolePolicy",
|
||||
"DeleteUserPermissionsBoundary",
|
||||
"DeleteUserPolicy",
|
||||
"DetachRolePolicy",
|
||||
"DetachUserPolicy",
|
||||
"GetCredentialsForIdentity",
|
||||
"GetId",
|
||||
"GetPolicyVersion",
|
||||
"GetUserPolicy",
|
||||
"Invoke",
|
||||
"ModifyInstanceAttribute",
|
||||
"PassRole",
|
||||
"PutGroupPolicy",
|
||||
"PutPipelineDefinition",
|
||||
"PutRolePermissionsBoundary",
|
||||
"PutRolePolicy",
|
||||
"PutUserPermissionsBoundary",
|
||||
"PutUserPolicy",
|
||||
"ReplaceIamInstanceProfileAssociation",
|
||||
"RunInstances",
|
||||
"SetDefaultPolicyVersion",
|
||||
"UpdateAccessKey",
|
||||
"UpdateAssumeRolePolicy",
|
||||
"UpdateDevEndpoint",
|
||||
"UpdateEventSourceMapping",
|
||||
"UpdateFunctionCode",
|
||||
"UpdateJob",
|
||||
"UpdateLoginProfile",
|
||||
]
|
||||
# aws.cloudtrail_threat_detection_enumeration
|
||||
threat_detection_enumeration_threshold: 0.3 # Percentage of actions found to decide if it is an enumeration attack event, by default is 0.3 (30%)
|
||||
threat_detection_enumeration_minutes: 1440 # Past minutes to search from now for enumeration attacks, by default is 1440 minutes (24 hours)
|
||||
threat_detection_enumeration_actions:
|
||||
[
|
||||
"DescribeAccessEntry",
|
||||
"DescribeAccountAttributes",
|
||||
"DescribeAvailabilityZones",
|
||||
"DescribeBundleTasks",
|
||||
"DescribeCarrierGateways",
|
||||
"DescribeClientVpnRoutes",
|
||||
"DescribeCluster",
|
||||
"DescribeDhcpOptions",
|
||||
"DescribeFlowLogs",
|
||||
"DescribeImages",
|
||||
"DescribeInstanceAttribute",
|
||||
"DescribeInstanceInformation",
|
||||
"DescribeInstanceTypes",
|
||||
"DescribeInstances",
|
||||
"DescribeInstances",
|
||||
"DescribeKeyPairs",
|
||||
"DescribeLogGroups",
|
||||
"DescribeLogStreams",
|
||||
"DescribeOrganization",
|
||||
"DescribeRegions",
|
||||
"DescribeSecurityGroups",
|
||||
"DescribeSnapshotAttribute",
|
||||
"DescribeSnapshotTierStatus",
|
||||
"DescribeSubscriptionFilters",
|
||||
"DescribeTransitGatewayMulticastDomains",
|
||||
"DescribeVolumes",
|
||||
"DescribeVolumesModifications",
|
||||
"DescribeVpcEndpointConnectionNotifications",
|
||||
"DescribeVpcs",
|
||||
"GetAccount",
|
||||
"GetAccountAuthorizationDetails",
|
||||
"GetAccountSendingEnabled",
|
||||
"GetBucketAcl",
|
||||
"GetBucketLogging",
|
||||
"GetBucketPolicy",
|
||||
"GetBucketReplication",
|
||||
"GetBucketVersioning",
|
||||
"GetCallerIdentity",
|
||||
"GetCertificate",
|
||||
"GetConsoleScreenshot",
|
||||
"GetCostAndUsage",
|
||||
"GetDetector",
|
||||
"GetEbsDefaultKmsKeyId",
|
||||
"GetEbsEncryptionByDefault",
|
||||
"GetFindings",
|
||||
"GetFlowLogsIntegrationTemplate",
|
||||
"GetIdentityVerificationAttributes",
|
||||
"GetInstances",
|
||||
"GetIntrospectionSchema",
|
||||
"GetLaunchTemplateData",
|
||||
"GetLaunchTemplateData",
|
||||
"GetLogRecord",
|
||||
"GetParameters",
|
||||
"GetPolicyVersion",
|
||||
"GetPublicAccessBlock",
|
||||
"GetQueryResults",
|
||||
"GetRegions",
|
||||
"GetSMSAttributes",
|
||||
"GetSMSSandboxAccountStatus",
|
||||
"GetSendQuota",
|
||||
"GetTransitGatewayRouteTableAssociations",
|
||||
"GetUserPolicy",
|
||||
"HeadObject",
|
||||
"ListAccessKeys",
|
||||
"ListAccounts",
|
||||
"ListAllMyBuckets",
|
||||
"ListAssociatedAccessPolicies",
|
||||
"ListAttachedUserPolicies",
|
||||
"ListClusters",
|
||||
"ListDetectors",
|
||||
"ListDomains",
|
||||
"ListFindings",
|
||||
"ListHostedZones",
|
||||
"ListIPSets",
|
||||
"ListIdentities",
|
||||
"ListInstanceProfiles",
|
||||
"ListObjects",
|
||||
"ListOrganizationalUnitsForParent",
|
||||
"ListOriginationNumbers",
|
||||
"ListPolicyVersions",
|
||||
"ListRoles",
|
||||
"ListRoles",
|
||||
"ListRules",
|
||||
"ListServiceQuotas",
|
||||
"ListSubscriptions",
|
||||
"ListTargetsByRule",
|
||||
"ListTopics",
|
||||
"ListUsers",
|
||||
"LookupEvents",
|
||||
"Search",
|
||||
]
|
||||
# aws.cloudtrail_threat_detection_llm_jacking
|
||||
threat_detection_llm_jacking_threshold: 0.4 # Percentage of actions found to decide if it is an LLM Jacking attack event, by default is 0.4 (40%)
|
||||
threat_detection_llm_jacking_minutes: 1440 # Past minutes to search from now for LLM Jacking attacks, by default is 1440 minutes (24 hours)
|
||||
threat_detection_llm_jacking_actions:
|
||||
[
|
||||
"PutUseCaseForModelAccess", # Submits a use case for model access, providing justification (Write).
|
||||
"PutFoundationModelEntitlement", # Grants entitlement for accessing a foundation model (Write).
|
||||
"PutModelInvocationLoggingConfiguration", # Configures logging for model invocations (Write).
|
||||
"CreateFoundationModelAgreement", # Creates a new agreement to use a foundation model (Write).
|
||||
"InvokeModel", # Invokes a specified Bedrock model for inference using provided prompt and parameters (Read).
|
||||
"InvokeModelWithResponseStream", # Invokes a Bedrock model for inference with real-time token streaming (Read).
|
||||
"GetUseCaseForModelAccess", # Retrieves an existing use case for model access (Read).
|
||||
"GetModelInvocationLoggingConfiguration", # Fetches the logging configuration for model invocations (Read).
|
||||
"GetFoundationModelAvailability", # Checks the availability of a foundation model for use (Read).
|
||||
"ListFoundationModelAgreementOffers", # Lists available agreement offers for accessing foundation models (List).
|
||||
"ListFoundationModels", # Lists the available foundation models in Bedrock (List).
|
||||
"ListProvisionedModelThroughputs", # Lists the provisioned throughput for previously created models (List).
|
||||
]
|
||||
|
||||
# AWS RDS Configuration
|
||||
# aws.rds_instance_backup_enabled
|
||||
# Whether to check RDS instance replicas or not
|
||||
check_rds_instance_replicas: False
|
||||
|
||||
# AWS ACM Configuration
|
||||
# aws.acm_certificates_expiration_check
|
||||
days_to_expire_threshold: 7
|
||||
|
||||
# AWS EKS Configuration
|
||||
# aws.eks_control_plane_logging_all_types_enabled
|
||||
# EKS control plane logging types that must be enabled
|
||||
eks_required_log_types:
|
||||
[
|
||||
"api",
|
||||
"audit",
|
||||
"authenticator",
|
||||
"controllerManager",
|
||||
"scheduler",
|
||||
]
|
||||
|
||||
# aws.eks_cluster_uses_a_supported_version
|
||||
# EKS clusters must be version 1.28 or higher
|
||||
eks_cluster_oldest_version_supported: "1.28"
|
||||
|
||||
# AWS CodeBuild Configuration
|
||||
# aws.codebuild_project_no_secrets_in_variables
|
||||
# CodeBuild sensitive variables that are excluded from the check
|
||||
excluded_sensitive_environment_variables:
|
||||
[
|
||||
|
||||
]
|
||||
|
||||
# Azure Configuration
|
||||
azure:
|
||||
# Azure Network Configuration
|
||||
# azure.network_public_ip_shodan
|
||||
# TODO: create common config
|
||||
shodan_api_key: null
|
||||
|
||||
# Azure App Service
|
||||
# azure.app_ensure_php_version_is_latest
|
||||
php_latest_version: "8.2"
|
||||
# azure.app_ensure_python_version_is_latest
|
||||
python_latest_version: "3.12"
|
||||
# azure.app_ensure_java_version_is_latest
|
||||
java_latest_version: "17"
|
||||
|
||||
# Azure SQL Server
|
||||
# azure.sqlserver_minimal_tls_version
|
||||
recommended_minimal_tls_versions:
|
||||
[
|
||||
"1.2",
|
||||
"1.3"
|
||||
]
|
||||
|
||||
# Azure Virtual Machines
|
||||
# azure.vm_desired_sku_size
|
||||
# List of desired VM SKU sizes that are allowed in the organization
|
||||
desired_vm_sku_sizes:
|
||||
[
|
||||
"Standard_A8_v2",
|
||||
"Standard_DS3_v2",
|
||||
"Standard_D4s_v3",
|
||||
]
|
||||
# Azure VM Backup Configuration
|
||||
# azure.vm_sufficient_daily_backup_retention_period
|
||||
vm_backup_min_daily_retention_days: 7
|
||||
|
||||
# Azure API Management Threat Detection Configuration
|
||||
# azure.apim_threat_detection_llm_jacking
|
||||
apim_threat_detection_llm_jacking_threshold: 0.1
|
||||
apim_threat_detection_llm_jacking_minutes: 1440
|
||||
apim_threat_detection_llm_jacking_actions:
|
||||
[
|
||||
# OpenAI API endpoints
|
||||
"ImageGenerations_Create",
|
||||
"ChatCompletions_Create",
|
||||
"Completions_Create",
|
||||
"Embeddings_Create",
|
||||
"FineTuning_Jobs_Create",
|
||||
"Models_List",
|
||||
|
||||
# Azure OpenAI endpoints
|
||||
"Deployments_List",
|
||||
"Deployments_Get",
|
||||
"Deployments_Create",
|
||||
"Deployments_Delete",
|
||||
|
||||
# Anthropic endpoints
|
||||
"Messages_Create",
|
||||
"Claude_Create",
|
||||
|
||||
# Google AI endpoints
|
||||
"GenerateContent",
|
||||
"GenerateText",
|
||||
"GenerateImage",
|
||||
|
||||
# Meta AI endpoints
|
||||
"Llama_Create",
|
||||
"CodeLlama_Create",
|
||||
|
||||
# Other LLM endpoints
|
||||
"Gemini_Generate",
|
||||
"Claude_Generate",
|
||||
"Llama_Generate"
|
||||
]
|
||||
|
||||
# GCP Configuration
|
||||
gcp:
|
||||
# GCP Compute Configuration
|
||||
# gcp.compute_public_address_shodan
|
||||
shodan_api_key: null
|
||||
|
||||
# Kubernetes Configuration
|
||||
kubernetes:
|
||||
# Kubernetes API Server
|
||||
# kubernetes.apiserver_audit_log_maxbackup_set
|
||||
audit_log_maxbackup: 10
|
||||
# kubernetes.apiserver_audit_log_maxsize_set
|
||||
audit_log_maxsize: 100
|
||||
# kubernetes.apiserver_audit_log_maxage_set
|
||||
audit_log_maxage: 30
|
||||
# kubernetes.apiserver_strong_ciphers_only
|
||||
apiserver_strong_ciphers:
|
||||
[
|
||||
"TLS_AES_128_GCM_SHA256",
|
||||
"TLS_AES_256_GCM_SHA384",
|
||||
"TLS_CHACHA20_POLY1305_SHA256",
|
||||
]
|
||||
# Kubelet
|
||||
# kubernetes.kubelet_strong_ciphers_only
|
||||
kubelet_strong_ciphers:
|
||||
[
|
||||
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
|
||||
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
|
||||
"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305",
|
||||
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
|
||||
"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305",
|
||||
"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
|
||||
"TLS_RSA_WITH_AES_256_GCM_SHA384",
|
||||
"TLS_RSA_WITH_AES_128_GCM_SHA256",
|
||||
]
|
||||
|
||||
# M365 Configuration
|
||||
m365:
|
||||
# Entra Conditional Access Policy
|
||||
# m365.entra_admin_users_sign_in_frequency_enabled
|
||||
sign_in_frequency: 4 # 4 hours
|
||||
# Teams Settings
|
||||
# m365.teams_external_file_sharing_restricted
|
||||
allowed_cloud_storage_services:
|
||||
[
|
||||
#"allow_box",
|
||||
#"allow_drop_box",
|
||||
#"allow_egnyte",
|
||||
#"allow_google_drive",
|
||||
#"allow_share_file",
|
||||
]
|
||||
# Exchange Organization Settings
|
||||
# m365.exchange_organization_mailtips_enabled
|
||||
recommended_mailtips_large_audience_threshold: 25 # maximum number of recipients
|
||||
|
||||
# GitHub Configuration
|
||||
github:
|
||||
# github.repository_inactive_not_archived
|
||||
inactive_not_archived_days_threshold: 180
|
||||
|
||||
|
||||
```
|
||||
@@ -0,0 +1,129 @@
|
||||
---
|
||||
title: "Custom Checks Metadata"
|
||||
---
|
||||
|
||||
In certain organizations, the severity of specific checks might differ from the default values defined in the check's metadata. For instance, while `s3_bucket_level_public_access_block` could be deemed `critical` for some organizations, others might assign a different severity level to it.
|
||||
|
||||
The custom metadata option offers a means to override default metadata set by Prowler
|
||||
|
||||
You can utilize `--custom-checks-metadata-file` followed by the path to your custom checks metadata YAML file.
|
||||
|
||||
## Available Fields
|
||||
|
||||
The list of supported check's metadata fields that can be override are listed as follows:
|
||||
|
||||
- Severity
|
||||
- CheckTitle
|
||||
- Risk
|
||||
- RelatedUrl
|
||||
- Remediation
|
||||
- Code
|
||||
- CLI
|
||||
- NativeIaC
|
||||
- Other
|
||||
- Terraform
|
||||
- Recommendation
|
||||
- Text
|
||||
- Url
|
||||
|
||||
|
||||
## File Syntax
|
||||
|
||||
This feature is available for all the providers supported in Prowler since the metadata format is common between all the providers. The YAML format for the custom checks metadata file is as follows:
|
||||
|
||||
```yaml title="custom_checks_metadata.yaml"
|
||||
CustomChecksMetadata:
|
||||
aws:
|
||||
Checks:
|
||||
s3_bucket_level_public_access_block:
|
||||
Severity: high
|
||||
CheckTitle: S3 Bucket Level Public Access Block
|
||||
Description: This check ensures that the S3 bucket level public access block is enabled.
|
||||
Risk: This check is important because it ensures that the S3 bucket level public access block is enabled.
|
||||
RelatedUrl: https://docs.aws.amazon.com/AmazonS3/latest/dev/access-control-block-public-access.html
|
||||
Remediation:
|
||||
Code:
|
||||
CLI: aws s3api put-public-access-block --bucket <bucket-name> --public-access-block-configuration BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true
|
||||
NativeIaC: https://aws.amazon.com/es/s3/features/block-public-access/
|
||||
Other: https://docs.aws.amazon.com/AmazonS3/latest/userguide/access-control-block-public-access.html
|
||||
Terraform: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block
|
||||
Recommendation:
|
||||
Text: Enable the S3 bucket level public access block.
|
||||
Url: https://docs.aws.amazon.com/AmazonS3/latest/dev/access-control-block-public-access.html
|
||||
s3_bucket_no_mfa_delete:
|
||||
Severity: high
|
||||
CheckTitle: S3 Bucket No MFA Delete
|
||||
Description: This check ensures that the S3 bucket does not allow delete operations without MFA.
|
||||
Risk: This check is important because it ensures that the S3 bucket does not allow delete operations without MFA.
|
||||
RelatedUrl: https://docs.aws.amazon.com/AmazonS3/latest/dev/Versioning.html
|
||||
Remediation:
|
||||
Code:
|
||||
CLI: aws s3api put-bucket-versioning --bucket <bucket-name> --versioning-configuration Status=Enabled,MFADelete=Enabled
|
||||
NativeIaC: https://aws.amazon.com/es/s3/features/versioning/
|
||||
Other: https://docs.aws.amazon.com/AmazonS3/latest/dev/Versioning.html
|
||||
Terraform: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_versioning
|
||||
Recommendation:
|
||||
Text: Enable versioning on the S3 bucket.
|
||||
Url: https://docs.aws.amazon.com/AmazonS3/latest/dev/Versioning.html
|
||||
azure:
|
||||
Checks:
|
||||
storage_infrastructure_encryption_is_enabled:
|
||||
Severity: medium
|
||||
CheckTitle: Storage Infrastructure Encryption Is Enabled
|
||||
Description: This check ensures that storage infrastructure encryption is enabled.
|
||||
Risk: This check is important because it ensures that storage infrastructure encryption is enabled.
|
||||
RelatedUrl: https://docs.microsoft.com/en-us/azure/storage/common/storage-service-encryption
|
||||
Remediation:
|
||||
Code:
|
||||
CLI: az storage account update --name <storage-account-name> --resource-group <resource-group-name> --set properties.encryption.services.blob.enabled=true properties.encryption.services.file.enabled=true properties.encryption.services.queue.enabled=true properties.encryption.services.table.enabled=true
|
||||
NativeIaC: https://docs.microsoft.com/en-us/azure/templates/microsoft.storage/storageaccounts
|
||||
Other: https://docs.microsoft.com/en-us/azure/storage/common/storage-service-encryption
|
||||
Terraform: https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/storage_account
|
||||
Recommendation:
|
||||
Text: Enable storage infrastructure encryption.
|
||||
Url: https://docs.microsoft.com/en-us/azure/storage/common/storage-service-encryption
|
||||
gcp:
|
||||
Checks:
|
||||
compute_instance_public_ip:
|
||||
Severity: critical
|
||||
CheckTitle: Compute Instance Public IP
|
||||
Description: This check ensures that the compute instance does not have a public IP.
|
||||
Risk: This check is important because it ensures that the compute instance does not have a public IP.
|
||||
RelatedUrl: https://cloud.google.com/compute/docs/ip-addresses/reserve-static-external-ip-address
|
||||
Remediation:
|
||||
Code:
|
||||
CLI: https://docs.prowler.com/checks/gcp/google-cloud-public-policies/bc_gcp_public_2#cli-command
|
||||
NativeIaC: https://cloud.google.com/compute/docs/reference/rest/v1/instances
|
||||
Other: https://cloud.google.com/compute/docs/ip-addresses/reserve-static-external-ip-address
|
||||
Terraform: https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/compute_instance
|
||||
Recommendation:
|
||||
Text: Remove the public IP from the compute instance.
|
||||
Url: https://cloud.google.com/compute/docs/ip-addresses/reserve-static-external-ip-address
|
||||
kubernetes:
|
||||
Checks:
|
||||
apiserver_anonymous_requests:
|
||||
Severity: low
|
||||
CheckTitle: APIServer Anonymous Requests
|
||||
Description: This check ensures that anonymous requests to the APIServer are disabled.
|
||||
Risk: This check is important because it ensures that anonymous requests to the APIServer are disabled.
|
||||
RelatedUrl: https://kubernetes.io/docs/reference/access-authn-authz/authentication/
|
||||
Remediation:
|
||||
Code:
|
||||
CLI: --anonymous-auth=false
|
||||
NativeIaC: https://docs.prowler.com/checks/kubernetes/kubernetes-policy-index/ensure-that-the-anonymous-auth-argument-is-set-to-false-1#kubernetes
|
||||
Other: https://kubernetes.io/docs/reference/access-authn-authz/authentication/
|
||||
Terraform: https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/cluster_role_binding
|
||||
Recommendation:
|
||||
Text: Disable anonymous requests to the APIServer.
|
||||
Url: https://kubernetes.io/docs/reference/access-authn-authz/authentication/
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
Executing the following command will assess all checks and generate a report while overriding the metadata for those checks:
|
||||
|
||||
```sh
|
||||
prowler <provider> --custom-checks-metadata-file <path/to/custom/metadata>
|
||||
```
|
||||
|
||||
This customization feature enables organizations to tailor the severity of specific checks based on their unique requirements, providing greater flexibility in security assessment and reporting.
|
||||
@@ -0,0 +1,126 @@
|
||||
---
|
||||
title: 'Dashboard'
|
||||
---
|
||||
|
||||
Prowler allows you to run your own local dashboards using the csv outputs provided by Prowler
|
||||
|
||||
```sh
|
||||
prowler dashboard
|
||||
```
|
||||
|
||||
<Note>
|
||||
You can expose the `dashboard` server in another address using the `HOST` environment variable.
|
||||
|
||||
</Note>
|
||||
To run Prowler local dashboard with Docker, use:
|
||||
|
||||
```sh
|
||||
docker run -v /your/local/dir/prowler-output:/home/prowler/output --env HOST=0.0.0.0 --publish 127.0.0.1:11666:11666 toniblyx/prowler:latest dashboard
|
||||
```
|
||||
|
||||
Make sure you update the `/your/local/dir/prowler-output` to match the path that contains your prowler output.
|
||||
|
||||
<Note>
|
||||
**Remember that the `dashboard` server is not authenticated. If you expose it to the Internet, do it at your own risk.**
|
||||
|
||||
</Note>
|
||||
The banner and additional info about the dashboard will be shown on your console: <img src="/images/cli/dashboard/dashboard-banner.png" />
|
||||
|
||||
## Overview Page
|
||||
|
||||
The overview page provides a full impression of your findings obtained from Prowler:
|
||||
|
||||
<img src="/images/cli/dashboard/dashboard-overview.png" />
|
||||
|
||||
This page allows for multiple functions:
|
||||
|
||||
* Apply filters:
|
||||
|
||||
* Assesment Date
|
||||
* Account
|
||||
* Region
|
||||
* Severity
|
||||
* Service
|
||||
* Status
|
||||
|
||||
* See which files has been scanned to generate the dashboard by placing your mouse on the `?` icon:
|
||||
|
||||
<img src="/images/cli/dashboard/dashboard-files-scanned.png" />
|
||||
|
||||
* Download the `Top Findings by Severity` table using the button `DOWNLOAD THIS TABLE AS CSV` or `DOWNLOAD THIS TABLE AS XLSX`
|
||||
|
||||
* Click the provider cards to filter by provider.
|
||||
|
||||
* On the dropdowns under `Top Findings by Severity` you can apply multiple sorts to see the information, also you will get a detailed view of each finding using the dropdowns:
|
||||
|
||||
<img src="/images/cli/dashboard/dropdown.png" />
|
||||
|
||||
## Compliance Page
|
||||
|
||||
This page shows all the info related to the compliance selected. Multiple filters can be selected as per your preferences.
|
||||
|
||||
<img src="/images/cli/dashboard/dashboard-compliance.png" />
|
||||
|
||||
To add your own compliance to compliance page, add a file with the compliance name (using `_` instead of `.`) to the path `/dashboard/compliance`.
|
||||
|
||||
In this file use the format present in the others compliance files to create the table. Example for CIS 2.0:
|
||||
|
||||
```python
|
||||
import warnings
|
||||
|
||||
from dashboard.common_methods import get_section_containers_cis
|
||||
|
||||
warnings.filterwarnings("ignore")
|
||||
|
||||
|
||||
def get_table(data):
|
||||
aux = data[
|
||||
[
|
||||
"REQUIREMENTS_ID",
|
||||
"REQUIREMENTS_DESCRIPTION",
|
||||
"REQUIREMENTS_ATTRIBUTES_SECTION",
|
||||
"CHECKID",
|
||||
"STATUS",
|
||||
"REGION",
|
||||
"ACCOUNTID",
|
||||
"RESOURCEID",
|
||||
]
|
||||
].copy()
|
||||
|
||||
return get_section_containers_cis(
|
||||
aux, "REQUIREMENTS_ID", "REQUIREMENTS_ATTRIBUTES_SECTION"
|
||||
)
|
||||
|
||||
```
|
||||
|
||||
## S3 Integration
|
||||
|
||||
If you are using Prowler SaaS with the S3 integration or that integration from Prowler Open Source and you want to use your data from your S3 bucket, you can run the following command in order to load the dashboard with the new files:
|
||||
|
||||
```sh
|
||||
aws s3 cp s3://<your-bucket>/output/csv ./output --recursive
|
||||
```
|
||||
|
||||
## Output Path
|
||||
|
||||
Prowler will use the outputs from the folder `/output` (for common prowler outputs) and `/output/compliance` (for prowler compliance outputs) to generate the dashboard.
|
||||
|
||||
To change the path, modify the values `folder_path_overview` or `folder_path_compliance` from `/dashboard/config.py`
|
||||
|
||||
<Note>
|
||||
If you have any issue related with dashboards, check that the output path where the dashboard is getting the outputs is correct.
|
||||
|
||||
|
||||
</Note>
|
||||
## Output Support
|
||||
|
||||
Prowler dashboard supports the detailed outputs:
|
||||
|
||||
| Provider| V3| V4| COMPLIANCE-V3| COMPLIANCE-V4
|
||||
|----------|----------|----------|----------|----------
|
||||
| AWS| ✅| ✅| ✅| ✅
|
||||
| Azure| ❌| ✅| ❌| ✅
|
||||
| Kubernetes| ❌| ✅| ❌| ✅
|
||||
| GCP| ❌| ✅| ❌| ✅
|
||||
| M365| ❌| ✅| ❌| ✅
|
||||
| GitHub| ❌| ✅| ❌| ✅
|
||||
@@ -0,0 +1,164 @@
|
||||
---
|
||||
title: 'Prowler Fixers (Remediations)'
|
||||
---
|
||||
|
||||
Prowler allows you to fix some of the failed findings it identifies. You can use the `--fixer` flag to run the fixes that are available for the checks that failed.
|
||||
|
||||
```sh
|
||||
prowler <provider> -c <check_to_fix_1> <check_to_fix_2> ... --fixer
|
||||
```
|
||||
|
||||
<img src="/images/cli/fixer.png" />
|
||||
|
||||
<Note>
|
||||
You can see all the available fixes for each provider with the `--list-remediations` or `--list-fixers` flag.
|
||||
|
||||
```sh
|
||||
prowler <provider> --list-fixers
|
||||
```
|
||||
|
||||
</Note>
|
||||
It's important to note that using the fixers for `Access Analyzer`, `GuardDuty`, and `SecurityHub` may incur additional costs. These AWS services might trigger actions or deploy resources that can lead to charges on your AWS account.
|
||||
|
||||
## Writing a Fixer
|
||||
|
||||
To write a fixer, you need to create a file called `<check_id>_fixer.py` inside the check folder, with a function called `fixer` that receives either the region or the resource to be fixed as a parameter, and returns a boolean value indicating if the fix was successful or not.
|
||||
|
||||
For example, the regional fixer for the `ec2_ebs_default_encryption` check, which enables EBS encryption by default in a region, would look like this:
|
||||
|
||||
```python
|
||||
from prowler.lib.logger import logger
|
||||
from prowler.providers.aws.services.ec2.ec2_client import ec2_client
|
||||
|
||||
|
||||
def fixer(region):
|
||||
"""
|
||||
Enable EBS encryption by default in a region. Note: Custom KMS keys for EBS Default Encryption may be overwritten. Requires the ec2:EnableEbsEncryptionByDefault permission.
|
||||
It can be set as follows:
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Action": "ec2:EnableEbsEncryptionByDefault",
|
||||
"Resource": "*"
|
||||
}
|
||||
]
|
||||
}
|
||||
Args:
|
||||
region (str): AWS region
|
||||
Returns:
|
||||
bool: True if EBS encryption by default is enabled, False otherwise
|
||||
"""
|
||||
try:
|
||||
regional_client = ec2_client.regional_clients[region]
|
||||
return regional_client.enable_ebs_encryption_by_default()[
|
||||
"EbsEncryptionByDefault"
|
||||
]
|
||||
except Exception as error:
|
||||
logger.error(
|
||||
f"{region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||
)
|
||||
return False
|
||||
```
|
||||
|
||||
On the other hand, the fixer for the `s3_account_level_public_access_blocks` check, which enables the account-level public access blocks for S3, would look like this:
|
||||
|
||||
```python
|
||||
from prowler.lib.logger import logger
|
||||
from prowler.providers.aws.services.s3.s3control_client import s3control_client
|
||||
|
||||
|
||||
def fixer(resource_id: str) -> bool:
|
||||
"""
|
||||
Enable S3 Block Public Access for the account. Note: Custom KMS keys for EBS Default Encryption may be overwritten. By blocking all S3 public access you may break public S3 buckets.
|
||||
Requires the s3:PutAccountPublicAccessBlock permission:
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Action": "s3:PutAccountPublicAccessBlock",
|
||||
"Resource": "*"
|
||||
}
|
||||
]
|
||||
}
|
||||
Returns:
|
||||
bool: True if S3 Block Public Access is enabled, False otherwise
|
||||
"""
|
||||
try:
|
||||
s3control_client.client.put_public_access_block(
|
||||
AccountId=resource_id,
|
||||
PublicAccessBlockConfiguration={
|
||||
"BlockPublicAcls": True,
|
||||
"IgnorePublicAcls": True,
|
||||
"BlockPublicPolicy": True,
|
||||
"RestrictPublicBuckets": True,
|
||||
},
|
||||
)
|
||||
except Exception as error:
|
||||
logger.error(
|
||||
f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||
)
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
```
|
||||
|
||||
## Fixer Config file
|
||||
|
||||
For some fixers, you can have configurable parameters depending on your use case. You can either use the default config file in `prowler/config/fixer_config.yaml` or create a custom config file and pass it to the fixer with the `--fixer-config` flag. The config file should be a YAML file with the following structure:
|
||||
|
||||
```yaml
|
||||
# Fixer configuration file
|
||||
aws:
|
||||
# ec2_ebs_default_encryption
|
||||
# No configuration needed for this check
|
||||
|
||||
# s3_account_level_public_access_blocks
|
||||
# No configuration needed for this check
|
||||
|
||||
# iam_password_policy_* checks:
|
||||
iam_password_policy:
|
||||
MinimumPasswordLength: 14
|
||||
RequireSymbols: True
|
||||
RequireNumbers: True
|
||||
RequireUppercaseCharacters: True
|
||||
RequireLowercaseCharacters: True
|
||||
AllowUsersToChangePassword: True
|
||||
MaxPasswordAge: 90
|
||||
PasswordReusePrevention: 24
|
||||
HardExpiry: False
|
||||
|
||||
# accessanalyzer_enabled
|
||||
accessanalyzer_enabled:
|
||||
AnalyzerName: "DefaultAnalyzer"
|
||||
AnalyzerType: "ACCOUNT_UNUSED_ACCESS"
|
||||
|
||||
# guardduty_is_enabled
|
||||
# No configuration needed for this check
|
||||
|
||||
# securityhub_enabled
|
||||
securityhub_enabled:
|
||||
EnableDefaultStandards: True
|
||||
|
||||
# cloudtrail_multi_region_enabled
|
||||
cloudtrail_multi_region_enabled:
|
||||
TrailName: "DefaultTrail"
|
||||
S3BucketName: "my-cloudtrail-bucket"
|
||||
IsMultiRegionTrail: True
|
||||
EnableLogFileValidation: True
|
||||
# CloudWatchLogsLogGroupArn: "arn:aws:logs:us-east-1:123456789012:log-group:my-cloudtrail-log-group"
|
||||
# CloudWatchLogsRoleArn: "arn:aws:iam::123456789012:role/my-cloudtrail-role"
|
||||
# KmsKeyId: "arn:aws:kms:us-east-1:123456789012:key/1234abcd-12ab-34cd-56ef-1234567890ab"
|
||||
|
||||
# kms_cmk_rotation_enabled
|
||||
# No configuration needed for this check
|
||||
|
||||
# ec2_ebs_snapshot_account_block_public_access
|
||||
ec2_ebs_snapshot_account_block_public_access:
|
||||
State: "block-all-sharing"
|
||||
|
||||
# ec2_instance_account_imdsv2_enabled
|
||||
# No configuration needed for this check
|
||||
```
|
||||
@@ -0,0 +1,41 @@
|
||||
---
|
||||
title: 'Integrations'
|
||||
---
|
||||
|
||||
## Integration with Slack
|
||||
|
||||
Prowler can be integrated with [Slack](https://slack.com/) to send a summary of the execution having configured a Slack APP in your channel with the following command:
|
||||
|
||||
```sh
|
||||
prowler <provider> --slack
|
||||
```
|
||||
|
||||

|
||||
|
||||
<Note>
|
||||
Slack integration needs `SLACK_API_TOKEN` and `SLACK_CHANNEL_NAME` environment variables.
|
||||
|
||||
</Note>
|
||||
### Configuration of the Integration with Slack
|
||||
|
||||
To configure the Slack Integration, follow the next steps:
|
||||
|
||||
1. Create a Slack Application:
|
||||
- Go to [Slack API page](https://api.slack.com/tutorials/tracks/getting-a-token), scroll down to the *Create app* button and select your workspace:
|
||||

|
||||
|
||||
- Install the application in your selected workspaces:
|
||||

|
||||
|
||||
- Get the *Slack App OAuth Token* that Prowler needs to send the message:
|
||||

|
||||
|
||||
2. Optionally, create a Slack Channel (you can use an existing one)
|
||||
|
||||
3. Integrate the created Slack App to your Slack channel:
|
||||
- Click on the channel, go to the Integrations tab, and Add an App.
|
||||

|
||||
|
||||
4. Set the following environment variables that Prowler will read:
|
||||
- `SLACK_API_TOKEN`: the *Slack App OAuth Token* that was previously get.
|
||||
- `SLACK_CHANNEL_NAME`: the name of your Slack Channel where Prowler will send the message.
|
||||
@@ -0,0 +1,57 @@
|
||||
---
|
||||
title: 'Logging'
|
||||
---
|
||||
|
||||
Prowler has a logging feature to be as transparent as possible, so that you can see every action that is being performed whilst the tool is being executing.
|
||||
|
||||
## Set Log Level
|
||||
|
||||
There are different log levels depending on the logging information that is desired to be displayed:
|
||||
|
||||
- **DEBUG**: It will show low-level logs from Python.
|
||||
- **INFO**: It will show all the API calls that are being invoked by the provider.
|
||||
- **WARNING**: It will show all resources that are being **muted**.
|
||||
- **ERROR**: It will show any errors, e.g., not authorized actions.
|
||||
- **CRITICAL**: The default log level. If a critical log appears, it will **exit** Prowler’s execution.
|
||||
|
||||
You can establish the log level of Prowler with `--log-level` option:
|
||||
|
||||
```console
|
||||
prowler <provider> --log-level {DEBUG,INFO,WARNING,ERROR,CRITICAL}
|
||||
```
|
||||
|
||||
<Note>
|
||||
By default, Prowler will run with the `CRITICAL` log level, since critical errors will abort the execution.
|
||||
|
||||
</Note>
|
||||
## Export Logs to File
|
||||
|
||||
Prowler allows you to export the logs in json format with the `--log-file` option:
|
||||
|
||||
```console
|
||||
prowler <provider> --log-level {DEBUG,INFO,WARNING,ERROR,CRITICAL} --log-file <file_name>.json
|
||||
```
|
||||
|
||||
An example of a log file will be the following:
|
||||
|
||||
```json
|
||||
{
|
||||
"timestamp": "2022-12-01 16:45:56,399",
|
||||
"filename": "ec2_service.py:114",
|
||||
"level": "ERROR",
|
||||
"module": "ec2_service",
|
||||
"message": "eu-west-2 -- ClientError[102]: An error occurred (UnauthorizedOperation) when calling the DescribeSecurityGroups operation: You are not authorized to perform this operation."
|
||||
}
|
||||
{
|
||||
"timestamp": "2022-12-01 16:45:56,438",
|
||||
"filename": "ec2_service.py:134",
|
||||
"level": "ERROR",
|
||||
"module": "ec2_service",
|
||||
"message": "eu-west-2 -- ClientError[124]: An error occurred (UnauthorizedOperation) when calling the DescribeNetworkAcls operation: You are not authorized to perform this operation."
|
||||
}
|
||||
```
|
||||
|
||||
<Note>
|
||||
Each finding is represented as a `json` object.
|
||||
|
||||
</Note>
|
||||
@@ -0,0 +1,181 @@
|
||||
---
|
||||
title: 'Miscellaneous'
|
||||
---
|
||||
|
||||
## Prowler Version
|
||||
|
||||
### Showing the Prowler version:
|
||||
|
||||
```console
|
||||
prowler <provider> -V/-v/--version
|
||||
```
|
||||
|
||||
## Prowler Execution Options
|
||||
|
||||
Prowler provides various execution settings.
|
||||
|
||||
### Verbose Execution
|
||||
|
||||
To enable verbose mode in Prowler, similar to Version 2, use:
|
||||
|
||||
```console
|
||||
prowler <provider> --verbose
|
||||
```
|
||||
|
||||
### Filter findings by status
|
||||
|
||||
Prowler allows filtering findings based on their status, ensuring reports and CLI display only relevant findings:
|
||||
|
||||
```console
|
||||
prowler <provider> --status [PASS, FAIL, MANUAL]
|
||||
```
|
||||
|
||||
### Disable Exit Code 3
|
||||
|
||||
By default, Prowler triggers exit code 3 for failed checks. To disable this behavior:
|
||||
|
||||
```console
|
||||
prowler <provider> -z/--ignore-exit-code-3
|
||||
```
|
||||
|
||||
### Hide Prowler Banner
|
||||
|
||||
To run Prowler without displaying the banner:
|
||||
|
||||
```console
|
||||
prowler <provider> -b/--no-banner
|
||||
```
|
||||
|
||||
### Disable Colors in Output
|
||||
|
||||
To run Prowler without color formatting:
|
||||
|
||||
```console
|
||||
prowler <provider> --no-color
|
||||
```
|
||||
|
||||
### Checks in Prowler
|
||||
|
||||
Prowler provides various security checks per cloud provider. Use the following options to list, execute, or exclude specific checks:
|
||||
|
||||
- **List Available Checks**: To display all available checks for the chosen provider:
|
||||
|
||||
```console
|
||||
prowler <provider> --list-checks
|
||||
```
|
||||
|
||||
- **Execute Specific Checks**: Run one or more specific security checks using:
|
||||
|
||||
```console
|
||||
prowler <provider> -c/--checks s3_bucket_public_access
|
||||
```
|
||||
|
||||
- **Exclude Specific Checks**: Exclude checks from execution with:
|
||||
|
||||
```console
|
||||
prowler <provider> -e/--excluded-checks ec2 rds
|
||||
```
|
||||
|
||||
- **Execute Checks from a JSON File**: To run checks defined in a JSON file, structure the file as follows:
|
||||
|
||||
```json
|
||||
<checks_list>.json
|
||||
|
||||
{
|
||||
"<provider>": [
|
||||
"<check_name_1",
|
||||
"<check_name_2",
|
||||
"<check_name_3",
|
||||
...
|
||||
],
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
```console
|
||||
prowler <provider> -C/--checks-file <checks_list>.json
|
||||
```
|
||||
|
||||
## Custom Checks in Prowler
|
||||
|
||||
Prowler supports custom security checks, allowing users to define their own logic.
|
||||
|
||||
```console
|
||||
prowler <provider> -x/--checks-folder <custom_checks_folder>
|
||||
```
|
||||
|
||||
<Note>
|
||||
S3 URIs are also supported for custom check folders (e.g., `s3://bucket/prefix/checks_folder/`). Ensure the credentials used have `s3:GetObject` permissions in the specified S3 path.
|
||||
|
||||
</Note>
|
||||
**Folder Structure for Custom Checks**
|
||||
|
||||
Each check must reside in a dedicated subfolder, following this structure:
|
||||
|
||||
- `__init__.py` (empty file) – Ensures Python treats the check folder as a package.
|
||||
- `check_name.py` (name file) – Defines the check’s logic for contextual information.
|
||||
- `check_name.metadata.json` (metadata file) – Defines the check’s metadata for contextual information.
|
||||
|
||||
<Note>
|
||||
The check name must start with the service name followed by an underscore (e.g., ec2\_instance\_public\_ip).
|
||||
|
||||
</Note>
|
||||
To see more information about how to write checks, refer to the [Developer Guide](/developer-guide/checks#creating-a-check).
|
||||
|
||||
<Note>
|
||||
If you want to run ONLY your custom check(s), import it with -x (--checks-folder) and then run it with -c (--checks), e.g.: `console prowler aws -x s3://bucket/prowler/providers/aws/services/s3/s3_bucket_policy/ -c s3_bucket_policy`
|
||||
|
||||
</Note>
|
||||
## Severities
|
||||
|
||||
Each of Prowler's checks has a severity, which can be one of the following:
|
||||
|
||||
- informational
|
||||
- low
|
||||
- medium
|
||||
- high
|
||||
- critical
|
||||
|
||||
To execute specific severity(s):
|
||||
|
||||
```console
|
||||
prowler <provider> --severity critical high
|
||||
```
|
||||
|
||||
## Service
|
||||
|
||||
Prowler has services per provider, there are options related with them:
|
||||
|
||||
- List the available services in the provider:
|
||||
|
||||
```console
|
||||
prowler <provider> --list-services
|
||||
```
|
||||
|
||||
- Execute specific service(s):
|
||||
|
||||
```console
|
||||
prowler <provider> -s/--services s3 iam
|
||||
```
|
||||
|
||||
- Exclude specific service(s):
|
||||
|
||||
```console
|
||||
prowler <provider> --excluded-services ec2 rds
|
||||
```
|
||||
|
||||
## Categories
|
||||
|
||||
Prowler groups checks in different categories. There are options related with said categories:
|
||||
|
||||
- List the available categories in the provider:
|
||||
|
||||
```console
|
||||
prowler <provider> --list-categories
|
||||
```
|
||||
|
||||
- Execute specific category(s):
|
||||
|
||||
```console
|
||||
prowler <provider> --categories secrets
|
||||
```
|
||||
@@ -0,0 +1,277 @@
|
||||
---
|
||||
title: 'Mutelisting'
|
||||
---
|
||||
|
||||
**Muting Findings for Intentional Configurations**
|
||||
|
||||
In some cases, certain AWS resources may be intentionally configured in a way that deviates from security best practices but serves a valid use case. Examples include:
|
||||
|
||||
An AWS S3 bucket open to the Internet, used for hosting a public website.
|
||||
|
||||
An AWS security group with an open port necessary for a specific application.
|
||||
|
||||
**Mutelist Option Behavior**
|
||||
|
||||
The Mutelist option works in combination with other filtering mechanisms and modifies the output in the following way when a finding is muted:
|
||||
|
||||
- JSON-OCSF: `status_id` is `Suppressed`.
|
||||
- CSV: `muted` is `True`. The field `status` will keep the original status, `MANUAL`, `PASS` or `FAIL`, of the finding.
|
||||
|
||||
## How the Mutelist Works
|
||||
|
||||
The **Mutelist** uses both "AND" and "OR" logic to determine which resources, checks, regions, and tags should be muted. For each check, the Mutelist evaluates whether the account, region, and resource match the specified criteria using "AND" logic. If tags are specified, the Mutelist can apply either "AND" or "OR" logic.
|
||||
|
||||
If any of the criteria do not match, the check is not muted.
|
||||
|
||||
<Note>
|
||||
Remember that mutelist can be used with regular expressions.
|
||||
|
||||
</Note>
|
||||
## Mutelist Specification
|
||||
|
||||
<Note>
|
||||
- For Azure provider, the Account ID is the Subscription Name and the Region is the Location.
|
||||
- For GCP provider, the Account ID is the Project ID and the Region is the Zone.
|
||||
- For Kubernetes provider, the Account ID is the Cluster Name and the Region is the Namespace.
|
||||
|
||||
</Note>
|
||||
The Mutelist file uses the [YAML](https://en.wikipedia.org/wiki/YAML) format with the following syntax:
|
||||
|
||||
```yaml
|
||||
### Account, Check and/or Region can be * to apply for all the cases.
|
||||
### Resources and tags are lists that can have either Regex or Keywords.
|
||||
### Tags is an optional list that matches on tuples of 'key=value' and are "ANDed" together.
|
||||
### Use an alternation Regex to match one of multiple tags with "ORed" logic.
|
||||
### For each check you can except Accounts, Regions, Resources and/or Tags.
|
||||
########################### MUTELIST EXAMPLE ###########################
|
||||
Mutelist:
|
||||
Accounts:
|
||||
"123456789012":
|
||||
Checks:
|
||||
"iam_user_hardware_mfa_enabled":
|
||||
Regions:
|
||||
- "us-east-1"
|
||||
Resources:
|
||||
- "user-1" # Will mute user-1 in check iam_user_hardware_mfa_enabled
|
||||
- "user-2" # Will mute user-2 in check iam_user_hardware_mfa_enabled
|
||||
Description: "Findings related with the check iam_user_hardware_mfa_enabled will be muted for us-east-1 region and user-1, user-2 resources"
|
||||
"ec2_*":
|
||||
Regions:
|
||||
- "*"
|
||||
Resources:
|
||||
- "*" # Will mute every EC2 check in every account and region
|
||||
"*":
|
||||
Regions:
|
||||
- "*"
|
||||
Resources:
|
||||
- "test"
|
||||
Tags:
|
||||
- "test=test" # Will mute every resource containing the string "test" and the tags 'test=test' and
|
||||
- "project=test|project=stage" # either of ('project=test' OR project=stage) in account 123456789012 and every region
|
||||
"*":
|
||||
Regions:
|
||||
- "*"
|
||||
Resources:
|
||||
- "test"
|
||||
Tags:
|
||||
- "test=test"
|
||||
- "project=test" # This will mute every resource containing the string "test" and BOTH tags at the same time.
|
||||
"*":
|
||||
Regions:
|
||||
- "*"
|
||||
Resources:
|
||||
- "test"
|
||||
Tags: # This will mute every resource containing the string "test" and the ones that contain EITHER the `test=test` OR `project=test` OR `project=dev`
|
||||
- "test=test|project=(test|dev)"
|
||||
"*":
|
||||
Regions:
|
||||
- "*"
|
||||
Resources:
|
||||
- "test"
|
||||
Tags:
|
||||
- "test=test" # This will mute every resource containing the string "test" and the tags `test=test` and either `project=test` OR `project=stage` in every account and region.
|
||||
- "project=test|project=stage"
|
||||
|
||||
"*":
|
||||
Checks:
|
||||
"s3_bucket_object_versioning":
|
||||
Regions:
|
||||
- "eu-west-1"
|
||||
- "us-east-1"
|
||||
Resources:
|
||||
- "ci-logs" # Will mute bucket "ci-logs" AND ALSO bucket "ci-logs-replica" in specified check and regions
|
||||
- "logs" # Will mute EVERY BUCKET containing the string "logs" in specified check and regions
|
||||
- ".+-logs" # Will mute all buckets containing the terms ci-logs, qa-logs, etc. in specified check and regions
|
||||
"ecs_task_definitions_no_environment_secrets":
|
||||
Regions:
|
||||
- "*"
|
||||
Resources:
|
||||
- "*"
|
||||
Exceptions:
|
||||
Accounts:
|
||||
- "0123456789012"
|
||||
Regions:
|
||||
- "eu-west-1"
|
||||
- "eu-south-2" # Will mute every resource in check ecs_task_definitions_no_environment_secrets except the ones in account 0123456789012 located in eu-south-2 or eu-west-1
|
||||
"*":
|
||||
Regions:
|
||||
- "*"
|
||||
Resources:
|
||||
- "*"
|
||||
Tags:
|
||||
- "environment=dev" # Will mute every resource containing the tag 'environment=dev' in every account and region
|
||||
|
||||
"123456789012":
|
||||
Checks:
|
||||
"*":
|
||||
Regions:
|
||||
- "*"
|
||||
Resources:
|
||||
- "*"
|
||||
Exceptions:
|
||||
Resources:
|
||||
- "test"
|
||||
Tags:
|
||||
- "environment=prod" # Will mute every resource except in account 123456789012 except the ones containing the string "test" and tag environment=prod
|
||||
|
||||
"*":
|
||||
Checks:
|
||||
"ec2_*":
|
||||
Regions:
|
||||
- "*"
|
||||
Resources:
|
||||
- "test-resource" # Will mute the resource "test-resource" in all accounts and regions for whatever check from the EC2 service
|
||||
```
|
||||
|
||||
|
||||
### Account, Check, Region, Resource, and Tag
|
||||
|
||||
| Field| Description| Logic
|
||||
|----------|----------|----------
|
||||
| `account_id`| Use `*` to apply the mutelist to all accounts.| `ANDed`
|
||||
| `check_name`| The name of the Prowler check. Use `*` to apply the mutelist to all checks, or `service_*` to apply it to all service's checks.| `ANDed`
|
||||
| `region`| The region identifier. Use `*` to apply the mutelist to all regions.| `ANDed`
|
||||
| `resource`| The resource identifier. Use `*` to apply the mutelist to all resources.| `ANDed`
|
||||
| `tag`| The tag value.| `ORed`
|
||||
|
||||
### Description
|
||||
|
||||
This field can be used to add information or some hints for the Mutelist rule.
|
||||
|
||||
## How to Use the Mutelist
|
||||
|
||||
To use the Mutelist, you need to specify the path to the Mutelist YAML file using the `-w` or `--mutelist-file` option when running Prowler:
|
||||
|
||||
```
|
||||
prowler <provider> -w mutelist.yaml
|
||||
```
|
||||
|
||||
Replace `<provider>` with the appropriate provider name.
|
||||
|
||||
## Considerations
|
||||
|
||||
- The Mutelist can be used in combination with other Prowler options, such as the `--service` or `--checks` option, to further customize the scanning process.
|
||||
- Make sure to review and update the Mutelist regularly to ensure it reflects the desired exclusions and remains up to date with your infrastructure.
|
||||
|
||||
## AWS Mutelist
|
||||
|
||||
### Muting specific AWS regions
|
||||
|
||||
If you want to mute failed findings only in specific regions, create a file with the following syntax and run it with `prowler aws -w mutelist.yaml`:
|
||||
|
||||
Mutelist:
|
||||
Accounts:
|
||||
"*":
|
||||
Checks:
|
||||
"*":
|
||||
Regions:
|
||||
- "ap-southeast-1"
|
||||
- "ap-southeast-2"
|
||||
Resources:
|
||||
- "*"
|
||||
Description: "Description related with the muted findings for the check"
|
||||
|
||||
### Default Mutelist
|
||||
|
||||
For the AWS Provider, Prowler is executed with a default AWS Mutelist with the AWS Resources that should be muted such as all resources created by AWS Control Tower when setting up a landing zone that can be found in [AWS Documentation](https://docs.aws.amazon.com/controltower/latest/userguide/shared-account-resources.html). You can see this Mutelist file in [`prowler/config/aws_mutelist.yaml`](https://github.com/prowler-cloud/prowler/blob/master/prowler/config/aws_mutelist.yaml).
|
||||
|
||||
### Supported Mutelist Locations
|
||||
|
||||
The mutelisting flag supports the following AWS locations when using the AWS Provider:
|
||||
|
||||
#### AWS S3 URI
|
||||
|
||||
You will need to pass the S3 URI where your Mutelist YAML file was uploaded to your bucket:
|
||||
|
||||
```
|
||||
prowler aws -w s3://<bucket>/<prefix>/mutelist.yaml
|
||||
```
|
||||
|
||||
<Note>
|
||||
Make sure that the used AWS credentials have `s3:GetObject` permissions in the S3 path where the mutelist file is located.
|
||||
|
||||
</Note>
|
||||
#### AWS DynamoDB Table ARN
|
||||
|
||||
You will need to pass the DynamoDB Mutelist Table ARN:
|
||||
|
||||
```
|
||||
prowler aws -w arn:aws:dynamodb:<region_name>:<account_id>:table/<table_name>
|
||||
```
|
||||
|
||||
The DynamoDB Table must have the following String keys:
|
||||
|
||||
<img src="/images/cli/mutelist-keys.png" />
|
||||
|
||||
The Mutelist Table must have the following columns:
|
||||
|
||||
- Accounts (String): This field can contain either an Account ID or an `*` (which applies to all the accounts that use this table as an mutelist).
|
||||
|
||||
- Checks (String): This field can contain either a Prowler Check Name or an `*` (which applies to all the scanned checks).
|
||||
|
||||
- Regions (List): This field contains a list of regions where this mutelist rule is applied (it can also contains an `*` to apply all scanned regions).
|
||||
|
||||
- Resources (List): This field contains a list of regular expressions (regex) that applies to the resources that are wanted to be muted.
|
||||
|
||||
- Tags (List): -Optional- This field contains a list of tuples in the form of 'key=value' that applies to the resources tags that are wanted to be muted.
|
||||
|
||||
- Exceptions (Map): -Optional- This field contains a map of lists of accounts/regions/resources/tags that are wanted to be excepted in the mutelist.
|
||||
|
||||
The following example will mute all resources in all accounts for the EC2 checks in the regions `eu-west-1` and `us-east-1` with the tags `environment=dev` and `environment=prod`, except the resources containing the string `test` in the account `012345678912` and region `eu-west-1` with the tag `environment=prod`:
|
||||
|
||||
<img src="/images/cli/mutelist-row.png" />
|
||||
|
||||
<Note>
|
||||
Make sure that the used AWS credentials have `dynamodb:PartiQLSelect` permissions in the table.
|
||||
|
||||
</Note>
|
||||
#### AWS Lambda ARN
|
||||
|
||||
You will need to pass the AWS Lambda Function ARN:
|
||||
|
||||
```
|
||||
prowler aws -w arn:aws:lambda:REGION:ACCOUNT_ID:function:FUNCTION_NAME
|
||||
```
|
||||
|
||||
Make sure that the credentials that Prowler uses can invoke the Lambda Function:
|
||||
|
||||
```
|
||||
- PolicyName: GetMuteList
|
||||
PolicyDocument:
|
||||
Version: '2012-10-17'
|
||||
Statement:
|
||||
- Action: 'lambda:InvokeFunction'
|
||||
Effect: Allow
|
||||
Resource: arn:aws:lambda:REGION:ACCOUNT_ID:function:FUNCTION_NAME
|
||||
```
|
||||
|
||||
The Lambda Function can then generate an Mutelist dynamically. Here is the code an example Python Lambda Function that generates an Mutelist:
|
||||
|
||||
```
|
||||
def handler(event, context):
|
||||
checks = {}
|
||||
checks["vpc_flow_logs_enabled"] = { "Regions": [ "*" ], "Resources": [ "" ], Optional("Tags"): [ "key:value" ] }
|
||||
|
||||
al = { "Mutelist": { "Accounts": { "*": { "Checks": checks } } } }
|
||||
return al
|
||||
```
|
||||
@@ -0,0 +1,191 @@
|
||||
---
|
||||
title: 'Parallel Execution'
|
||||
---
|
||||
|
||||
The strategy used here will be to execute Prowler once per service. You can modify this approach as per your requirements.
|
||||
|
||||
This can help for really large accounts, but please be aware of AWS API rate limits:
|
||||
|
||||
1. **Service-Specific Limits**: Each AWS service has its own rate limits. For instance, Amazon EC2 might have different rate limits for launching instances versus making API calls to describe instances.
|
||||
2. **API Rate Limits**: Most of the rate limits in AWS are applied at the API level. Each API call to an AWS service counts towards the rate limit for that service.
|
||||
3. **Throttling Responses**: When you exceed the rate limit for a service, AWS responds with a throttling error. In AWS SDKs, these are typically represented as `ThrottlingException` or `RateLimitExceeded` errors.
|
||||
|
||||
For information on Prowler's retrier configuration please refer to this [page](https://docs.prowler.cloud/en/latest/tutorials/aws/boto3-configuration/).
|
||||
|
||||
<Note>
|
||||
You might need to increase the `--aws-retries-max-attempts` parameter from the default value of 3. The retrier follows an exponential backoff strategy.
|
||||
|
||||
</Note>
|
||||
## Linux
|
||||
|
||||
Generate a list of services that Prowler supports, and populate this info into a file:
|
||||
|
||||
```bash
|
||||
prowler aws --list-services | awk -F"- " '{print $2}' | sed '/^$/d' > services
|
||||
```
|
||||
|
||||
Make any modifications for services you would like to skip scanning by modifying this file.
|
||||
|
||||
Then create a new PowerShell script file `parallel-prowler.sh` and add the following contents. Update the `$profile` variable to the AWS CLI profile you want to run Prowler with.
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
|
||||
# Change these variables as needed
|
||||
profile="your_profile"
|
||||
account_id=$(aws sts get-caller-identity --profile "${profile}" --query 'Account' --output text)
|
||||
|
||||
echo "Executing in account: ${account_id}"
|
||||
|
||||
# Maximum number of concurrent processes
|
||||
MAX_PROCESSES=5
|
||||
|
||||
# Loop through the services
|
||||
while read service; do
|
||||
echo "$(date '+%Y-%m-%d %H:%M:%S'): Starting job for service: ${service}"
|
||||
|
||||
# Run the command in the background
|
||||
(prowler -p "$profile" -s "$service" -F "${account_id}-${service}" --only-logs; echo "$(date '+%Y-%m-%d %H:%M:%S') - ${service} has completed") &
|
||||
|
||||
# Check if we have reached the maximum number of processes
|
||||
while [ $(jobs -r | wc -l) -ge ${MAX_PROCESSES} ]; do
|
||||
# Wait for a second before checking again
|
||||
sleep 1
|
||||
done
|
||||
done < ./services
|
||||
|
||||
# Wait for all background processes to finish
|
||||
wait
|
||||
echo "All jobs completed"
|
||||
```
|
||||
|
||||
Output will be stored in the `output/` folder that is in the same directory from which you executed the script.
|
||||
|
||||
## Windows
|
||||
|
||||
Generate a list of services that Prowler supports, and populate this info into a file:
|
||||
|
||||
```powershell
|
||||
prowler aws --list-services | ForEach-Object {
|
||||
# Capture lines that are likely service names
|
||||
if ($_ -match '^\- \w+$') {
|
||||
$_.Trim().Substring(2)
|
||||
}
|
||||
} | Where-Object {
|
||||
# Filter out empty or null lines
|
||||
$_ -ne $null -and $_ -ne ''
|
||||
} | Set-Content -Path "services"
|
||||
```
|
||||
|
||||
Make any modifications for services you would like to skip scanning by modifying this file.
|
||||
|
||||
Then create a new PowerShell script file `parallel-prowler.ps1` and add the following contents. Update the `$profile` variable to the AWS CLI profile you want to run Prowler with.
|
||||
|
||||
Change any parameters you would like when calling Prowler in the `Start-Job -ScriptBlock` section. Note that you need to keep the `--only-logs` parameter, else some encoding issue occurs when trying to render the progress-bar and Prowler won't successfully execute.
|
||||
|
||||
```powershell
|
||||
$profile = "your_profile"
|
||||
$account_id = Invoke-Expression -Command "aws sts get-caller-identity --profile $profile --query 'Account' --output text"
|
||||
|
||||
Write-Host "Executing Prowler in $account_id"
|
||||
|
||||
# Maximum number of concurrent jobs
|
||||
$MAX_PROCESSES = 5
|
||||
|
||||
# Read services from a file
|
||||
$services = Get-Content -Path "services"
|
||||
|
||||
# Array to keep track of started jobs
|
||||
$jobs = @()
|
||||
|
||||
foreach ($service in $services) {
|
||||
# Start the command as a job
|
||||
$job = Start-Job -ScriptBlock {
|
||||
prowler -p ${using:profile} -s ${using:service} -F "${using:account_id}-${using:service}" --only-logs
|
||||
$endTimestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
|
||||
Write-Output "${endTimestamp} - $using:service has completed"
|
||||
}
|
||||
$jobs += $job
|
||||
Write-Host "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') - Starting job for service: $service"
|
||||
|
||||
# Check if we have reached the maximum number of jobs
|
||||
while (($jobs | Where-Object { $_.State -eq 'Running' }).Count -ge $MAX_PROCESSES) {
|
||||
Start-Sleep -Seconds 1
|
||||
# Check for any completed jobs and receive their output
|
||||
$completedJobs = $jobs | Where-Object { $_.State -eq 'Completed' }
|
||||
foreach ($completedJob in $completedJobs) {
|
||||
Receive-Job -Job $completedJob -Keep | ForEach-Object { Write-Host $_ }
|
||||
$jobs = $jobs | Where-Object { $_.Id -ne $completedJob.Id }
|
||||
Remove-Job -Job $completedJob
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Check for any remaining completed jobs
|
||||
$remainingCompletedJobs = $jobs | Where-Object { $_.State -eq 'Completed' }
|
||||
foreach ($remainingJob in $remainingCompletedJobs) {
|
||||
Receive-Job -Job $remainingJob -Keep | ForEach-Object { Write-Host $_ }
|
||||
Remove-Job -Job $remainingJob
|
||||
}
|
||||
|
||||
Write-Host "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') - All jobs completed"
|
||||
```
|
||||
|
||||
Output will be stored in `C:\Users\YOUR-USER\Documents\output\`
|
||||
|
||||
## Combining the output files
|
||||
|
||||
Guidance is provided for the CSV file format. From the ouput directory, execute either the following Bash or PowerShell script. The script will collect the output from the CSV files, only include the header from the first file, and then output the result as CombinedCSV.csv in the current working directory.
|
||||
|
||||
There is no logic implemented in terms of which CSV files it will combine. If you have additional CSV files from other actions, such as running a quick inventory, you will need to move that out of the current (or any nested) directory, or move the output you want to combine into its own folder and run the script from there.
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
|
||||
# Initialize a variable to indicate the first file
|
||||
firstFile=true
|
||||
|
||||
# Find all CSV files and loop through them
|
||||
find . -name "*.csv" -print0 | while IFS= read -r -d '' file; do
|
||||
if [ "$firstFile" = true ]; then
|
||||
# For the first file, keep the header
|
||||
cat "$file" > CombinedCSV.csv
|
||||
firstFile=false
|
||||
else
|
||||
# For subsequent files, skip the header
|
||||
tail -n +2 "$file" >> CombinedCSV.csv
|
||||
fi
|
||||
done
|
||||
```
|
||||
|
||||
```powershell
|
||||
# Get all CSV files from current directory and its subdirectories
|
||||
$csvFiles = Get-ChildItem -Recurse -Filter "*.csv"
|
||||
|
||||
# Initialize a variable to track if it's the first file
|
||||
$firstFile = $true
|
||||
|
||||
# Loop through each CSV file
|
||||
foreach ($file in $csvFiles) {
|
||||
if ($firstFile) {
|
||||
# For the first file, keep the header and change the flag
|
||||
$combinedCsv = Import-Csv -Path $file.FullName
|
||||
$firstFile = $false
|
||||
} else {
|
||||
# For subsequent files, skip the header
|
||||
$tempCsv = Import-Csv -Path $file.FullName
|
||||
$combinedCsv += $tempCsv | Select-Object * -Skip 1
|
||||
}
|
||||
}
|
||||
|
||||
# Export the combined data to a new CSV file
|
||||
$combinedCsv | Export-Csv -Path "CombinedCSV.csv" -NoTypeInformation
|
||||
```
|
||||
|
||||
## TODO: Additional Improvements
|
||||
|
||||
Some services need to instantiate another service to perform a check. For instance, `cloudwatch` will instantiate Prowler's `iam` service to perform the `cloudwatch_cross_account_sharing_disabled` check. When the `iam` service is instantiated, it will perform the `__init__` function, and pull all the information required for that service. This provides an opportunity for an improvement in the above script to group related services together so that the `iam` services (or any other cross-service references) isn't repeatedily instantiated by grouping dependant services together. A complete mapping between these services still needs to be further investigated, but these are the cross-references that have been noted:
|
||||
|
||||
* inspector2 needs lambda and ec2
|
||||
* cloudwatch needs iam
|
||||
* dlm needs ec2
|
||||
@@ -0,0 +1,87 @@
|
||||
---
|
||||
title: 'Pentesting'
|
||||
---
|
||||
|
||||
Prowler has some checks that analyse pentesting risks (Secrets, Internet Exposed, AuthN, AuthZ, and more).
|
||||
|
||||
## Detect Secrets
|
||||
|
||||
Prowler uses `detect-secrets` library to search for any secrets that are stores in plaintext within your environment.
|
||||
|
||||
The actual checks that have this functionality are the following:
|
||||
|
||||
- autoscaling\_find\_secrets\_ec2\_launch\_configuration
|
||||
- awslambda\_function\_no\_secrets\_in\_code
|
||||
- awslambda\_function\_no\_secrets\_in\_variables
|
||||
- cloudformation\_stack\_outputs\_find\_secrets
|
||||
- ec2\_instance\_secrets\_user\_data
|
||||
- ec2\_launch\_template\_no\_secrets
|
||||
- ecs\_task\_definitions\_no\_environment\_secrets
|
||||
- ssm\_document\_secrets
|
||||
|
||||
To execute detect-secrets related checks, you can run the following command:
|
||||
|
||||
```console
|
||||
prowler <provider> --categories secrets
|
||||
```
|
||||
|
||||
## Internet Exposed Resources
|
||||
|
||||
Several checks analyse resources that are exposed to the Internet, these are:
|
||||
|
||||
1. apigateway\_restapi\_public
|
||||
|
||||
- appstream\_fleet\_default\_internet\_access\_disabled
|
||||
- awslambda\_function\_not\_publicly\_accessible
|
||||
- ec2\_ami\_public
|
||||
- ec2\_ebs\_public\_snapshot
|
||||
- ec2\_instance\_internet\_facing\_with\_instance\_profile
|
||||
- ec2\_instance\_port\_X\_exposed\_to\_internet (where X is the port number)
|
||||
- ec2\_instance\_public\_ip
|
||||
- ec2\_networkacl\_allow\_ingress\_any\_port
|
||||
- ec2\_securitygroup\_allow\_wide\_open\_public\_ipv4
|
||||
- ec2\_securitygroup\_allow\_ingress\_from\_internet\_to\_any\_port
|
||||
- ecr\_repositories\_not\_publicly\_accessible
|
||||
- eks\_control\_plane\_endpoint\_access\_restricted
|
||||
- eks\_endpoints\_not\_publicly\_accessible
|
||||
- eks\_control\_plane\_endpoint\_access\_restricted
|
||||
- eks\_endpoints\_not\_publicly\_accessible
|
||||
- elbv2\_internet\_facing
|
||||
- kms\_key\_not\_publicly\_accessible
|
||||
- opensearch\_service\_domains\_not\_publicly\_accessible
|
||||
- rds\_instance\_no\_public\_access
|
||||
- rds\_snapshots\_public\_access
|
||||
- s3\_bucket\_policy\_public\_write\_access
|
||||
- s3\_bucket\_public\_access
|
||||
- sagemaker\_notebook\_instance\_without\_direct\_internet\_access\_configured
|
||||
- sns\_topics\_not\_publicly\_accessible
|
||||
- sqs\_queues\_not\_publicly\_accessible
|
||||
- network\_public\_ip\_shodan
|
||||
|
||||
To execute Internet-exposed related checks, you can run the following command:
|
||||
|
||||
```console
|
||||
prowler <provider> --categories internet-exposed
|
||||
```
|
||||
|
||||
### Shodan
|
||||
|
||||
Prowler allows you check if any public IPs in your Cloud environments are exposed in Shodan with the `-N`/`--shodan <shodan_api_key>` option:
|
||||
|
||||
For example, you can check if any of your AWS Elastic Compute Cloud (EC2) instances has an elastic IP exposed in Shodan:
|
||||
|
||||
```console
|
||||
prowler aws -N/--shodan <shodan_api_key> -c ec2_elastic_ip_shodan
|
||||
```
|
||||
|
||||
Also, you can check if any of your Azure Subscription has an public IP exposed in Shodan:
|
||||
|
||||
```console
|
||||
prowler azure -N/--shodan <shodan_api_key> -c network_public_ip_shodan
|
||||
```
|
||||
|
||||
And finally, you can check if any of your GCP projects has an public IP address exposed in Shodan:
|
||||
|
||||
```console
|
||||
prowler gcp -N/--shodan <shodan_api_key> -c compute_public_address_shodan
|
||||
```
|
||||
@@ -0,0 +1,47 @@
|
||||
---
|
||||
title: 'Prowler Check Kreator'
|
||||
---
|
||||
|
||||
<Note>
|
||||
Currently, this tool is only available for creating checks for the AWS provider.
|
||||
|
||||
</Note>
|
||||
<Note>
|
||||
If you are looking for a way to create new checks for all the supported providers, you can use [Prowler Studio](https://github.com/prowler-cloud/prowler-studio), it is an AI-powered toolkit for generating and managing security checks for Prowler (better version of the Check Kreator).
|
||||
|
||||
</Note>
|
||||
## Introduction
|
||||
|
||||
**Prowler Check Kreator** is a utility designed to streamline the creation of new checks for Prowler. This tool generates all necessary files required to add a new check to the Prowler repository. Specifically, it creates:
|
||||
|
||||
- A dedicated folder for the check.
|
||||
- The main check script.
|
||||
- A metadata file with essential details.
|
||||
- A folder and file structure for testing the check.
|
||||
|
||||
## Usage
|
||||
|
||||
To use the tool, execute the main script with the following command:
|
||||
|
||||
```bash
|
||||
python util/prowler_check_kreator/prowler_check_kreator.py <prowler_provider> <check_name>
|
||||
```
|
||||
|
||||
Parameters:
|
||||
|
||||
- `<prowler_provider>`: Currently only AWS is supported.
|
||||
- `<check_name>`: The name you wish to assign to the new check.
|
||||
|
||||
## AI integration
|
||||
|
||||
This tool optionally integrates AI to assist in generating the check code and metadata file content. When AI assistance is chosen, the tool uses [Gemini](https://gemini.google.com/) to produce preliminary code and metadata.
|
||||
|
||||
<Note>
|
||||
For this feature to work, you must have the library `google-generativeai` installed in your Python environment.
|
||||
|
||||
</Note>
|
||||
<Warning>
|
||||
AI-generated code and metadata might contain errors or require adjustments to align with specific Prowler requirements. Carefully review all AI-generated content before committing.
|
||||
|
||||
</Warning>
|
||||
To enable AI assistance, simply confirm when prompted by the tool. Additionally, ensure that the `GEMINI_API_KEY` environment variable is set with a valid Gemini API key. For instructions on obtaining your API key, refer to the [Gemini documentation](https://ai.google.dev/gemini-api/docs/api-key).
|
||||
@@ -0,0 +1,29 @@
|
||||
---
|
||||
title: 'Quick Inventory'
|
||||
---
|
||||
|
||||
Prowler allows you to execute a quick inventory to extract the number of resources in your provider.
|
||||
|
||||
<Note>
|
||||
Currently, it is only available for AWS provider.
|
||||
|
||||
</Note>
|
||||
- You can use option `-i`/`--quick-inventory` to execute it:
|
||||
|
||||
```sh
|
||||
prowler <provider> -i
|
||||
```
|
||||
|
||||
<Note>
|
||||
By default, it extracts resources from all the regions, you could use `-f`/`--filter-region` to specify the regions to execute the analysis.
|
||||
|
||||
</Note>
|
||||
- This feature specify both the number of resources for each service and for each resource type.
|
||||
|
||||
- Also, it creates by default a CSV and JSON to see detailed information about the resources extracted.
|
||||
|
||||

|
||||
|
||||
## Objections
|
||||
|
||||
The inventorying process is carried out with `resourcegroupstaggingapi` calls, which means that only resources they have or have had tags will appear (except for the IAM and S3 resources which are done with Boto3 API calls).
|
||||
@@ -0,0 +1,440 @@
|
||||
---
|
||||
title: 'Reporting in Prowler'
|
||||
---
|
||||
|
||||
Prowler generates security assessment reports in multiple formats, ensuring compatibility with various analysis tools and AWS integrations.
|
||||
|
||||
## Default Report Generation
|
||||
|
||||
By default, Prowler outputs reports in CSV and JSON-[OCSF](https://schema.ocsf.io/) formats:
|
||||
|
||||
```console
|
||||
prowler <provider> -M csv json-ocsf json-asff html
|
||||
```
|
||||
|
||||
If you require reports in JSON-ASFF (used by AWS Security Hub), set it using the `-M/--output-modes/--output-formats` flag, as in the following example:
|
||||
|
||||
```console
|
||||
prowler <provider> --output-formats json-asff
|
||||
```
|
||||
|
||||
## Compliance Reports
|
||||
|
||||
All compliance-related reports are automatically generated when Prowler is executed. These outputs are stored in the `/output/compliance` directory.
|
||||
|
||||
## Custom Output Flags
|
||||
|
||||
By default, Prowler creates a file inside the `output` directory named: `prowler-output-ACCOUNT_NUM-OUTPUT_DATE.format`.
|
||||
|
||||
However, both the output file name and directory can be personalised:
|
||||
|
||||
- Custom output report name:
|
||||
|
||||
You can use the flag `-F`/`--output-filename`
|
||||
|
||||
```console
|
||||
prowler <provider> -M csv json-ocsf json-asff -F <custom_report_name>
|
||||
```
|
||||
|
||||
|
||||
- Custom output directory:
|
||||
|
||||
You can use the flag `-o`/`--output-directory`
|
||||
|
||||
```console
|
||||
prowler <provider> -M csv json-ocsf json-asff -o <custom_report_directory>
|
||||
```
|
||||
|
||||
<Note>
|
||||
Both flags can be used simultaneously to provide a custom directory and filename. `console prowler <provider> -M csv json-ocsf json-asff \ -F <custom_report_name> -o <custom_report_directory>`
|
||||
|
||||
</Note>
|
||||
## Output timestamp format
|
||||
|
||||
By default, the timestamp format of the output files is ISO 8601. This can be changed with the flag `--unix-timestamp` generating the timestamp fields in pure unix timestamp format.
|
||||
|
||||
## Supported Output Formats
|
||||
|
||||
Prowler natively supports the following reporting output formats:
|
||||
|
||||
- CSV
|
||||
- JSON-OCSF
|
||||
- JSON-ASFF
|
||||
- HTML
|
||||
|
||||
Hereunder is the structure for each of the supported report formats by Prowler:
|
||||
|
||||
### CSV
|
||||
|
||||
The CSV format follows a standardized structure across all providers. The following are the available columns:
|
||||
|
||||
- AUTH\_METHOD
|
||||
- TIMESTAMP
|
||||
- ACCOUNT\_UID
|
||||
- ACCOUNT\_NAME
|
||||
- ACCOUNT\_EMAIL
|
||||
- ACCOUNT\_ORGANIZATION\_UID
|
||||
- ACCOUNT\_ORGANIZATION\_NAME
|
||||
- ACCOUNT\_TAGS
|
||||
- FINDING\_UID
|
||||
- PROVIDER
|
||||
- CHECK\_ID
|
||||
- CHECK\_TITLE
|
||||
- CHECK\_TYPE
|
||||
- STATUS
|
||||
- STATUS\_EXTENDED
|
||||
- MUTED
|
||||
- SERVICE\_NAME
|
||||
- SUBSERVICE\_NAME
|
||||
- SEVERITY
|
||||
- RESOURCE\_TYPE
|
||||
- RESOURCE\_UID
|
||||
- RESOURCE\_NAME
|
||||
- RESOURCE\_DETAILS
|
||||
- RESOURCE\_TAGS
|
||||
- PARTITION
|
||||
- REGION
|
||||
- DESCRIPTION
|
||||
- RISK
|
||||
- RELATED\_URL
|
||||
- REMEDIATION\_RECOMMENDATION\_TEXT
|
||||
- REMEDIATION\_RECOMMENDATION\_URL
|
||||
- REMEDIATION\_CODE\_NATIVEIAC
|
||||
- REMEDIATION\_CODE\_TERRAFORM
|
||||
- REMEDIATION\_CODE\_CLI
|
||||
- REMEDIATION\_CODE\_OTHER
|
||||
- COMPLIANCE
|
||||
- CATEGORIES
|
||||
- DEPENDS\_ON
|
||||
- RELATED\_TO
|
||||
- NOTES
|
||||
- PROWLER\_VERSION
|
||||
- ADDITIONAL\_URLS
|
||||
|
||||
#### CSV Headers Mapping
|
||||
|
||||
The following table shows the mapping between the CSV headers and the the providers fields:
|
||||
|
||||
| Open Source Consolidated| AWS| GCP| AZURE| KUBERNETES
|
||||
|----------|----------|----------|----------|----------
|
||||
| auth\_method| profile| principal| identity\_type : identity\_id| in-cluster/kube-config
|
||||
| provider| provider| provider| provider| provider
|
||||
| account\_uid| account\_id / account\_arn| project\_id| subscription\_id| cluster
|
||||
| account\_name| account\_name| project\_name| subscription\_name| context:context
|
||||
| account\_email| account\_email| N/A| N/A| N/A
|
||||
| account\_organization\_uid| account\_organizations\_arn| project\_organization\_id| tenant\_id| N/A
|
||||
| account\_organization\_name| account\_org| project\_organization\_display\_name| tenant\_domain| N/A
|
||||
| account\_tags| account\_tags| project\_labels| subscription\_tags| N/A
|
||||
| partition| partition| N/A| region\_config.name| N/A
|
||||
| region| region| location| location| namespace:namespace
|
||||
| resource\_name| resource\_id| resource\_name| resource\_name| resource\_name
|
||||
| resource\_uid| resource\_arn| resource\_id| resource\_id| resource\_id
|
||||
| finding\_uid| finding\_unique\_id| finding\_unique\_id| finding\_unique\_id| finding\_unique\_id
|
||||
|
||||
### JSON-OCSF
|
||||
|
||||
The JSON-OCSF output format implements the [Detection Finding](https://schema.ocsf.io/classes/detection_finding) from the [OCSF](https://schema.ocsf.io)
|
||||
|
||||
```json
|
||||
[{
|
||||
"message": "Potential secrets found in ECS task definition manufacturer-api with revision 7: Secrets in container manufacturer-api -> Secret Keyword on the environment variable DB_PASSWORD.",
|
||||
"metadata": {
|
||||
"event_code": "ecs_task_definitions_no_environment_secrets",
|
||||
"product": {
|
||||
"name": "Prowler",
|
||||
"uid": "prowler",
|
||||
"vendor_name": "Prowler",
|
||||
"version": "5.3.0"
|
||||
},
|
||||
"profiles": [
|
||||
"cloud",
|
||||
"datetime"
|
||||
],
|
||||
"tenant_uid": "",
|
||||
"version": "1.3.0"
|
||||
},
|
||||
"severity_id": 5,
|
||||
"severity": "Critical",
|
||||
"status": "New",
|
||||
"status_code": "FAIL",
|
||||
"status_detail": "Potential secrets found in ECS task definition manufacturer-api with revision 7: Secrets in container manufacturer-api -> Secret Keyword on the environment variable DB_PASSWORD.",
|
||||
"status_id": 1,
|
||||
"unmapped": {
|
||||
"related_url": "",
|
||||
"categories": [
|
||||
"secrets"
|
||||
],
|
||||
"depends_on": [],
|
||||
"related_to": [],
|
||||
"notes": "",
|
||||
"additional_urls": [],
|
||||
"compliance": {
|
||||
"MITRE-ATTACK": [
|
||||
"T1552"
|
||||
],
|
||||
"AWS-Foundational-Security-Best-Practices": [
|
||||
"ecs"
|
||||
],
|
||||
"KISA-ISMS-P-2023": [
|
||||
"2.7.1",
|
||||
"2.11.2"
|
||||
],
|
||||
"KISA-ISMS-P-2023-korean": [
|
||||
"2.7.1",
|
||||
"2.11.2"
|
||||
],
|
||||
"AWS-Well-Architected-Framework-Security-Pillar": [
|
||||
"SEC02-BP03"
|
||||
]
|
||||
}
|
||||
},
|
||||
"activity_name": "Create",
|
||||
"activity_id": 1,
|
||||
"finding_info": {
|
||||
"created_time": 1737995806,
|
||||
"created_time_dt": "2025-01-27T17:36:46.855898",
|
||||
"desc": "Check if secrets exists in ECS task definitions environment variables.",
|
||||
"product_uid": "prowler",
|
||||
"title": "Check if secrets exists in ECS task definitions environment variables",
|
||||
"types": [
|
||||
"Protect",
|
||||
"Secure development",
|
||||
"Credentials not hard-coded"
|
||||
],
|
||||
"uid": "prowler-aws-ecs_task_definitions_no_environment_secrets-123456789012-eu-central-1-manufacturer-api:7"
|
||||
},
|
||||
"resources": [
|
||||
{
|
||||
"cloud_partition": "aws",
|
||||
"region": "eu-central-1",
|
||||
"data": {
|
||||
"details": "",
|
||||
"metadata": {
|
||||
"name": "manufacturer-api",
|
||||
"arn": "arn:aws:ecs:eu-central-1:123456789012:task-definition/manufacturer-api:7",
|
||||
"revision": "7",
|
||||
"region": "eu-central-1",
|
||||
"container_definitions": [
|
||||
{
|
||||
"name": "manufacturer-api",
|
||||
"privileged": false,
|
||||
"readonly_rootfilesystem": false,
|
||||
"user": "",
|
||||
"environment": [
|
||||
{
|
||||
"name": "DB_HOST",
|
||||
"value": "some.cluster.eu-central-1.rds.amazonaws.com"
|
||||
},
|
||||
{
|
||||
"name": "DB_PASSWORD",
|
||||
"value": "somePassword"
|
||||
}
|
||||
],
|
||||
"log_driver": "",
|
||||
"log_option": ""
|
||||
}
|
||||
],
|
||||
"pid_mode": "",
|
||||
"tags": [],
|
||||
"network_mode": "awsvpc"
|
||||
}
|
||||
},
|
||||
"group": {
|
||||
"name": "ecs"
|
||||
},
|
||||
"labels": [],
|
||||
"name": "manufacturer-api:7",
|
||||
"type": "AwsEcsTaskDefinition",
|
||||
"uid": "arn:aws:ecs:eu-central-1:123456789012:task-definition/manufacturer-api:7"
|
||||
}
|
||||
],
|
||||
"category_name": "Findings",
|
||||
"category_uid": 2,
|
||||
"class_name": "Detection Finding",
|
||||
"class_uid": 2004,
|
||||
"cloud": {
|
||||
"account": {
|
||||
"name": "",
|
||||
"type": "AWS Account",
|
||||
"type_id": 10,
|
||||
"uid": "123456789012",
|
||||
"labels": []
|
||||
},
|
||||
"org": {
|
||||
"name": "",
|
||||
"uid": ""
|
||||
},
|
||||
"provider": "aws",
|
||||
"region": "eu-central-1"
|
||||
},
|
||||
"remediation": {
|
||||
"desc": "Use Secrets Manager or Parameter Store to securely provide credentials to containers without hardcoding the secrets in code or passing them through environment variables. It is currently not possible to delete task definition revisions which contain plaintext secrets. AWS is looking into implementing this feature in 2023, and it is therefore recommended that all plaintext secrets are rotated at the same time as moving the secrets to Secrets Manager or Parameter Store.",
|
||||
"references": [
|
||||
"https://docs.aws.amazon.com/AmazonECS/latest/developerguide/specifying-sensitive-data.html"
|
||||
]
|
||||
},
|
||||
"risk_details": "The use of a hard-coded password increases the possibility of password guessing. If hard-coded passwords are used, it is possible that malicious users gain access through the account in question.",
|
||||
"time": 1737995806,
|
||||
"time_dt": "2025-01-27T17:36:46.855898",
|
||||
"type_uid": 200401,
|
||||
"type_name": "Detection Finding: Create"
|
||||
}]
|
||||
```
|
||||
|
||||
<Note>
|
||||
Each finding is a `json` object within a list.
|
||||
|
||||
</Note>
|
||||
### JSON-ASFF
|
||||
|
||||
<Note>
|
||||
Only available when using `--security-hub` or `--output-formats json-asff`
|
||||
|
||||
</Note>
|
||||
The following code is an example output of the [JSON-ASFF](https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-findings-format-syntax.html) format:
|
||||
|
||||
```json
|
||||
[{
|
||||
"SchemaVersion": "2018-10-08",
|
||||
"Id": "prowler-rds_instance_minor_version_upgrade_enabled-ACCOUNT_ID-eu-west-1-b1ade474a",
|
||||
"ProductArn": "arn:aws:securityhub:eu-west-1::product/prowler/prowler",
|
||||
"RecordState": "ACTIVE",
|
||||
"ProductFields": {
|
||||
"ProviderName": "Prowler",
|
||||
"ProviderVersion": "3.0-beta-21Nov2022",
|
||||
"ProwlerResourceName": "rds-instance-id"
|
||||
},
|
||||
"GeneratorId": "prowler-rds_instance_minor_version_upgrade_enabled",
|
||||
"AwsAccountId": "ACCOUNT_ID",
|
||||
"Types": [],
|
||||
"FirstObservedAt": "2022-12-01T13:16:57Z",
|
||||
"UpdatedAt": "2022-12-01T13:16:57Z",
|
||||
"CreatedAt": "2022-12-01T13:16:57Z",
|
||||
"Severity": {
|
||||
"Label": "LOW"
|
||||
},
|
||||
"Title": "Ensure RDS instances have minor version upgrade enabled.",
|
||||
"Description": "Ensure RDS instances have minor version upgrade enabled.",
|
||||
"Resources": [
|
||||
{
|
||||
"Type": "AwsRdsDbInstance",
|
||||
"Id": "rds-instance-id",
|
||||
"Partition": "aws",
|
||||
"Region": "eu-west-1"
|
||||
}
|
||||
],
|
||||
"Compliance": {
|
||||
"Status": "PASSED",
|
||||
"RelatedRequirements": [
|
||||
"CISA your-systems-2 booting-up-thing-to-do-first-3",
|
||||
"CIS-1.5 2.3.2",
|
||||
"AWS-Foundational-Security-Best-Practices rds",
|
||||
"RBI-Cyber-Security-Framework annex_i_6",
|
||||
"FFIEC d3-cc-pm-b-1 d3-cc-pm-b-3"
|
||||
],
|
||||
"AssociatedStandards": [
|
||||
{
|
||||
"StandardsId": "CISA"
|
||||
},
|
||||
{
|
||||
"StandardsId": "CIS-1.5"
|
||||
},
|
||||
{
|
||||
"StandardsId": "AWS-Foundational-Security-Best-Practices"
|
||||
},
|
||||
{
|
||||
"StandardsId": "RBI-Cyber-Security-Framework"
|
||||
},
|
||||
{
|
||||
"StandardsId": "FFIEC"
|
||||
}
|
||||
]
|
||||
},
|
||||
"Remediation": {
|
||||
"Recommendation": {
|
||||
"Text": "Enable auto minor version upgrade for all databases and environments.",
|
||||
"Url": "https://aws.amazon.com/blogs/database/best-practices-for-upgrading-amazon-rds-to-major-and-minor-versions-of-postgresql/"
|
||||
}
|
||||
}
|
||||
}]
|
||||
```
|
||||
|
||||
<Note>
|
||||
Each finding is a `json` object within a list.
|
||||
|
||||
</Note>
|
||||
### HTML
|
||||
|
||||
The following image is an example of the HTML output:
|
||||
|
||||
<img src="/images/cli/reporting/html-output.png" />
|
||||
## V4 Deprecations
|
||||
|
||||
Some deprecations have been made to unify formats and improve outputs.
|
||||
|
||||
### JSON
|
||||
|
||||
Native JSON format has been deprecated in favor of JSON [OCSF](https://schema.ocsf.io/) `v1.1.0`.
|
||||
|
||||
The following is the mapping between the native JSON and the Detection Finding from the JSON-OCSF:
|
||||
|
||||
| Native JSON Prowler v3| JSON-OCSF v.1.1.0
|
||||
|----------|----------
|
||||
| AssessmentStartTime| time\_dt
|
||||
| FindingUniqueId| finding\_info.uid
|
||||
| Provider| cloud.provider
|
||||
| CheckID| metadata.event\_code
|
||||
| CheckTitle| finding\_info.title
|
||||
| CheckType| finding\_info.types
|
||||
| ServiceName| resources.group.name
|
||||
| SubServiceName| _Not mapped yet_
|
||||
| Status| status\_code
|
||||
| StatusExtended| status\_detail
|
||||
| Severity| severity
|
||||
| ResourceType| resources.type
|
||||
| ResourceDetails| resources.data.details
|
||||
| Description| finding\_info.desc
|
||||
| Risk| risk\_details
|
||||
| RelatedUrl| unmapped.related\_url
|
||||
| Remediation.Recommendation.Text| remediation.desc
|
||||
| Remediation.Recommendation.Url| remediation.references
|
||||
| Remediation.Code.NativeIaC| remediation.references
|
||||
| Remediation.Code.Terraform| remediation.references
|
||||
| Remediation.Code.CLI| remediation.references
|
||||
| Remediation.Code.Other| remediation.references
|
||||
| Compliance| unmapped.compliance
|
||||
| Categories| unmapped.categories
|
||||
| DependsOn| unmapped.depends\_on
|
||||
| RelatedTo| unmapped.related\_to
|
||||
| AdditionalURLs| unmapped.additional\_urls
|
||||
| Notes| unmapped.notes
|
||||
| Profile| _Not mapped yet_
|
||||
| AccountId| cloud.account.uid
|
||||
| OrganizationsInfo.account\_name| cloud.account.name
|
||||
| OrganizationsInfo.account\_email| _Not mapped yet_
|
||||
| OrganizationsInfo.account\_arn| _Not mapped yet_
|
||||
| OrganizationsInfo.account\_org| cloud.org.name
|
||||
| OrganizationsInfo.account\_tags| cloud.account.labels
|
||||
| Region| resources.region
|
||||
| ResourceId| resources.name
|
||||
| ResourceArn| resources.uid
|
||||
| ResourceTags| resources.labels
|
||||
|
||||
### CSV Columns
|
||||
|
||||
In Prowler v3 each provider had some specific columns, different from the rest. These are the cases that have changed in Prowler v4:
|
||||
|
||||
| Provider| v3| v4
|
||||
|----------|----------|----------
|
||||
| AWS| PROFILE| AUTH\_METHOD
|
||||
| AWS| ACCOUNT\_ID| ACCOUNT\_UID
|
||||
| AWS| ACCOUNT\_ORGANIZATION\_ARN| ACCOUNT\_ORGANIZATION\_UID
|
||||
| AWS| ACCOUNT\_ORG| ACCOUNT\_ORGANIZATION\_NAME
|
||||
| AWS| FINDING\_UNIQUE\_ID| FINDING\_UID
|
||||
| AWS| ASSESSMENT\_START\_TIME| TIMESTAMP
|
||||
| AZURE| TENANT\_DOMAIN| ACCOUNT\_ORGANIZATION\_NAME
|
||||
| AZURE| SUBSCRIPTION| ACCOUNT\_UID
|
||||
| GCP| PROJECT\_ID| ACCOUNT\_UID
|
||||
| GCP| LOCATION| REGION
|
||||
| AWS / AZURE / GCP| RESOURCE\_ID| RESOURCE\_NAME
|
||||
| AWS / AZURE / GCP| RESOURCE\_ARN| RESOURCE\_UID
|
||||
@@ -0,0 +1,112 @@
|
||||
---
|
||||
title: 'Scanning Unused Services'
|
||||
---
|
||||
|
||||
<Note>
|
||||
This feature is currently available only for the AWS provider.
|
||||
|
||||
</Note>
|
||||
By default, Prowler scans only actively used cloud services (services with resources deployed). This reduces unnecessary findings in reports. To include unused services in the scan, use the following command:
|
||||
|
||||
```console
|
||||
prowler <provider> --scan-unused-services
|
||||
```
|
||||
|
||||
## Services Ignored
|
||||
|
||||
### AWS
|
||||
|
||||
#### ACM (AWS Certificate Manager)
|
||||
|
||||
Certificates stored in ACM without active usage in AWS resources are excluded. By default, Prowler only scans actively used certificates. Unused certificates will not be checked if they are expired, if their expiring date is near or if they are good.
|
||||
|
||||
- `acm_certificates_expiration_check`
|
||||
|
||||
#### Athena
|
||||
|
||||
Upon AWS account creation, Athena provisions a default primary workgroup for the user. Prowler verifies if this workgroup is enabled and used by checking for queries within the last 45 days. If Athena is unused, findings related to its checks will not appear.
|
||||
|
||||
- `athena_workgroup_encryption`
|
||||
- `athena_workgroup_enforce_configuration`
|
||||
|
||||
#### AWS CloudTrail
|
||||
|
||||
AWS CloudTrail should have at least one trail with a data event to record all S3 object-level API operations. Before flagging this issue, Prowler verifies if S3 buckets exist in the account.
|
||||
|
||||
- `cloudtrail_s3_dataevents_read_enabled`
|
||||
- `cloudtrail_s3_dataevents_write_enabled`
|
||||
|
||||
#### AWS Elastic Compute Cloud (EC2)
|
||||
|
||||
If Amazon Elastic Block Store (EBS) default encyption is not enabled, sensitive data at rest will remain unprotected in EC2. However, Prowler will only generate a finding if EBS volumes exist where default encryption could be enforced.
|
||||
|
||||
- `ec2_ebs_default_encryption`
|
||||
|
||||
**Security Groups**: Misconfigured security groups increase the attack surface.
|
||||
|
||||
Prowler scans only attached security groups to report vulnerabilities in actively used configurations. Applies to:
|
||||
|
||||
- 15 security group-related checks, including open ports and ingress/egress traffic rules.
|
||||
|
||||
- `ec2_securitygroup_allow_ingress_from_internet_to_port_X`
|
||||
- `ec2_securitygroup_default_restrict_traffic`
|
||||
- `ec2_securitygroup_allow_wide_open_public_ipv4`
|
||||
|
||||
- 3 network ACL-related checks, ensuring only active ACLs with open ports are flagged.
|
||||
|
||||
- `ec2_networkacl_allow_ingress_X_port`
|
||||
|
||||
#### AWS Glue
|
||||
|
||||
AWS Glue best practices recommend encrypting metadata and connection passwords in Data Catalogs.
|
||||
|
||||
Prowler verifies service usage by checking for existing Data Catalog tables before applying findings.
|
||||
|
||||
- `glue_data_catalogs_connection_passwords_encryption_enabled`
|
||||
- `glue_data_catalogs_metadata_encryption_enabled`
|
||||
|
||||
#### Amazon Inspector
|
||||
|
||||
Amazon Inspector is a vulnerability discovery service that automates continuous security scans for Amazon EC2, Amazon ECR, and AWS Lambda environments. Prowler recommends enabling Amazon Inspector and addressing all findings. By default, Prowler only triggers alerts if there are Lambda functions, EC2 instances, or ECR repositories in the region where Amazon Inspector should be enabled.
|
||||
|
||||
- `inspector2_is_enabled`
|
||||
|
||||
#### Amazon Macie
|
||||
|
||||
Amazon Macie leverages machine learning to automatically discover, classify, and protect sensitive data in S3 buckets. Prowler only generates findings if Macie is disabled and there are S3 buckets in the AWS account.
|
||||
|
||||
- `macie_is_enabled`
|
||||
|
||||
#### Network Firewall
|
||||
|
||||
A network firewall is essential for monitoring and controlling traffic within a Virtual Private Cloud (VPC). Prowler only alerts for VPCs in use, specifically those containing ENIs (Elastic Network Interfaces).
|
||||
|
||||
- `networkfirewall_in_all_vpc`
|
||||
|
||||
#### Amazon S3
|
||||
|
||||
To prevent unintended data exposure:
|
||||
|
||||
Public Access Block should be enabled at the account level. Prowler only checks this setting if S3 buckets exist in the account.
|
||||
|
||||
- `s3_account_level_public_access_blocks`
|
||||
|
||||
#### Virtual Private Cloud (VPC)
|
||||
|
||||
VPC settings directly impact network security and availability.
|
||||
|
||||
- VPC Flow Logs: Provide visibility into network traffic for security monitoring. Prowler only checks if Flow Logs are enabled for VPCs in use, i.e., those with active ENIs.
|
||||
|
||||
- `vpc_flow_logs_enabled`
|
||||
|
||||
- VPC Subnet Public IP Restrictions: Prevent unintended exposure of resources to the internet. Prowler only checks this configuration for VPCs in use, i.e., those with active ENIs.
|
||||
|
||||
- `vpc_subnet_no_public_ip_by_default`
|
||||
|
||||
- Separate Private and Public Subnets: Best practice to avoid exposure risks. Prowler only checks this configuration for VPCs in use, i.e., those with active ENIs.
|
||||
|
||||
- `vpc_subnet_separate_private_public`
|
||||
|
||||
- Multi-AZ Subnet Distribution: VPCs should have subnets in different availability zones to prevent a single point of failure. Prowler only checks this configuration for VPCs in use, i.e., those with active ENIs.
|
||||
|
||||
- `vpc_subnet_different_az`
|
||||
Reference in New Issue
Block a user