Skip to content

Commit

Permalink
Merge branch 'master' into PRWLR-4452-ensure-aws-waf-classic-regional…
Browse files Browse the repository at this point in the history
…-rule-groups-have-at-least-one-rule
  • Loading branch information
sergargar authored Oct 16, 2024
2 parents 13a138c + 9d97b1a commit 97fac7a
Show file tree
Hide file tree
Showing 64 changed files with 4,064 additions and 101 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/find-secrets.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jobs:
with:
fetch-depth: 0
- name: TruffleHog OSS
uses: trufflesecurity/[email protected].8
uses: trufflesecurity/[email protected].9
with:
path: ./
base: ${{ github.event.repository.default_branch }}
Expand Down
1 change: 1 addition & 0 deletions permissions/create_role_to_assume_cfn.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ Resources:
- 'cloudtrail:GetInsightSelectors'
- 'codeartifact:List*'
- 'codebuild:BatchGet*'
- 'codebuild:ListReportGroups'
- 'cognito-idp:GetUserPoolMfaConfig'
- 'dlm:Get*'
- 'drs:Describe*'
Expand Down
1 change: 1 addition & 0 deletions permissions/prowler-additions-policy.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"cloudtrail:GetInsightSelectors",
"codeartifact:List*",
"codebuild:BatchGet*",
"codebuild:ListReportGroups",
"cognito-idp:GetUserPoolMfaConfig",
"dlm:Get*",
"drs:Describe*",
Expand Down
5 changes: 3 additions & 2 deletions prowler/providers/aws/aws_provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ def __init__(
profile: str = None,
regions: set = set(),
organizations_role_arn: str = None,
scan_unused_services: bool = None,
scan_unused_services: bool = False,
resource_tags: list[str] = [],
resource_arn: list[str] = [],
audit_config: dict = {},
Expand All @@ -106,7 +106,7 @@ def __init__(
- profile: The name of the AWS CLI profile to use.
- regions: A set of regions to audit.
- organizations_role_arn: The ARN of the AWS Organizations IAM role to assume.
- scan_unused_services: A boolean indicating whether to scan unused services.
- scan_unused_services: A boolean indicating whether to scan unused services. False by default.
- resource_tags: A list of tags to filter the resources to audit.
- resource_arn: A list of ARNs of the resources to audit.
- audit_config: The audit configuration.
Expand All @@ -122,6 +122,7 @@ def __init__(
- ArgumentTypeError: If the input role session name is invalid.
"""

logger.info("Initializing AWS provider ...")

######## AWS Session
Expand Down
24 changes: 24 additions & 0 deletions prowler/providers/aws/aws_regions_by_service.json
Original file line number Diff line number Diff line change
Expand Up @@ -10146,6 +10146,30 @@
"aws-us-gov": []
}
},
"ssm-quicksetup": {
"regions": {
"aws": [
"ap-northeast-1",
"ap-northeast-2",
"ap-south-1",
"ap-southeast-1",
"ap-southeast-2",
"ca-central-1",
"eu-central-1",
"eu-north-1",
"eu-west-1",
"eu-west-2",
"eu-west-3",
"sa-east-1",
"us-east-1",
"us-east-2",
"us-west-1",
"us-west-2"
],
"aws-cn": [],
"aws-us-gov": []
}
},
"ssm-sap": {
"regions": {
"aws": [
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"Provider": "aws",
"CheckID": "autoscaling_group_multiple_instance_types",
"CheckTitle": "EC2 Auto Scaling Group should use multiple instance types in multiple Availability Zones.",
"CheckType": [
"Software and Configuration Checks/AWS Security Best Practices"
],
"ServiceName": "autoscaling",
"SubServiceName": "",
"ResourceIdTemplate": "arn:partition:autoscaling:region:account-id:autoScalingGroupName/resource-name",
"Severity": "medium",
"ResourceType": "AwsAutoScalingAutoScalingGroup",
"Description": "This control checks whether an Amazon EC2 Auto Scaling group uses multiple instance types in all the Availability Zones, meaning that there should be multiple Availability Zones with multiple instances on each one. The control fails if the Auto Scaling group has only one instance type defined.",
"Risk": "Using only one instance type in an Auto Scaling group reduces the flexibility to launch new instances when there is insufficient capacity for that specific type, potentially affecting the availability of the application.",
"RelatedUrl": "https://docs.aws.amazon.com/autoscaling/ec2/userguide/ec2-auto-scaling-mixed-instances-groups.html",
"Remediation": {
"Code": {
"CLI": "aws autoscaling create-auto-scaling-group --mixed-instances-policy ...",
"NativeIaC": "",
"Other": "https://docs.aws.amazon.com/securityhub/latest/userguide/autoscaling-controls.html#autoscaling-6",
"Terraform": ""
},
"Recommendation": {
"Text": "Configure your EC2 Auto Scaling group to use multiple instance types across multiple Availability Zones.",
"Url": "https://www.trendmicro.com/cloudoneconformity/knowledge-base/aws/AutoScaling/asg-multiple-instance-type-az.html"
}
},
"Categories": [],
"DependsOn": [],
"RelatedTo": [],
"Notes": ""
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
from prowler.lib.check.models import Check, Check_Report_AWS
from prowler.providers.aws.services.autoscaling.autoscaling_client import (
autoscaling_client,
)


class autoscaling_group_multiple_instance_types(Check):
def execute(self):
findings = []
for group in autoscaling_client.groups:
report = Check_Report_AWS(self.metadata())
report.region = group.region
report.resource_id = group.name
report.resource_arn = group.arn
report.resource_tags = group.tags
report.status = "FAIL"
report.status_extended = f"Autoscaling group {group.name} does not have multiple instance types in multiple Availability Zones."

failing_azs = []

for az, types in group.az_instance_types.items():
if len(types) < 2:
failing_azs.append(az)

if not failing_azs and len(group.az_instance_types) > 1:
report.status = "PASS"
report.status_extended = f"Autoscaling group {group.name} has multiple instance types in each of its Availability Zones."
elif failing_azs:
azs_str = ", ".join(failing_azs)
report.status_extended = f"Autoscaling group {group.name} has only one or no instance types in Availability Zone(s): {azs_str}."

findings.append(report)

return findings
14 changes: 14 additions & 0 deletions prowler/providers/aws/services/autoscaling/autoscaling_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,13 +66,25 @@ def _describe_auto_scaling_groups(self, regional_client):
self.audit_resources,
)
):
instance_types = []
az_instance_types = {}
for instance in group.get("Instances", []):
az = instance["AvailabilityZone"]
instance_type = instance["InstanceType"]
instance_types.append(instance_type)
if az not in az_instance_types:
az_instance_types[az] = set()
az_instance_types[az].add(instance_type)

self.groups.append(
Group(
arn=group.get("AutoScalingGroupARN"),
name=group.get("AutoScalingGroupName"),
region=regional_client.region,
availability_zones=group.get("AvailabilityZones"),
tags=group.get("Tags"),
instance_types=instance_types,
az_instance_types=az_instance_types,
launch_template=group.get("LaunchTemplate", {}),
mixed_instances_policy_launch_template=group.get(
"MixedInstancesPolicy", {}
Expand Down Expand Up @@ -154,6 +166,8 @@ class Group(BaseModel):
region: str
availability_zones: list
tags: list = []
instance_types: list = []
az_instance_types: dict = {}
launch_template: dict = {}
mixed_instances_policy_launch_template: dict = {}
health_check_type: str
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"Provider": "aws",
"CheckID": "cloudwatch_alarm_actions_alarm_state_configured",
"CheckTitle": "Check if CloudWatch alarms have specified actions configured for the ALARM state.",
"CheckType": [
"Software and Configuration Checks/AWS Security Best Practices"
],
"ServiceName": "cloudwatch",
"SubServiceName": "",
"ResourceIdTemplate": "arn:aws:cloudwatch:region:account-id:alarm/alarm-name",
"Severity": "high",
"ResourceType": "AwsCloudWatchAlarm",
"Description": "This control checks whether an Amazon CloudWatch alarm has at least one action configured for the ALARM state. The control fails if the alarm doesn't have an action configured for the ALARM state.",
"Risk": "Without an action configured for the ALARM state, the CloudWatch alarm will not notify you or take any predefined action when a monitored metric goes beyond the defined threshold, potentially delaying responses to critical events.",
"RelatedUrl": "https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/AlarmThatSendsEmail.html#alarms-and-actions",
"Remediation": {
"Code": {
"CLI": "aws cloudwatch put-metric-alarm --alarm-name <alarm-name> --alarm-actions <action-arn>",
"NativeIaC": "",
"Other": "https://docs.aws.amazon.com/securityhub/latest/userguide/cloudwatch-controls.html#cloudwatch-15",
"Terraform": ""
},
"Recommendation": {
"Text": "Configure your CloudWatch alarms to trigger actions, such as sending notifications via Amazon SNS, when the alarm state changes to ALARM.",
"Url": "https://www.trendmicro.com/cloudoneconformity/knowledge-base/aws/CloudWatch/cloudwatch-alarm-action.html"
}
},
"Categories": [],
"DependsOn": [],
"RelatedTo": [],
"Notes": ""
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
from prowler.lib.check.models import Check, Check_Report_AWS
from prowler.providers.aws.services.cloudwatch.cloudwatch_client import (
cloudwatch_client,
)


class cloudwatch_alarm_actions_alarm_state_configured(Check):
def execute(self):
findings = []
for metric_alarm in cloudwatch_client.metric_alarms:
report = Check_Report_AWS(self.metadata())
report.region = metric_alarm.region
report.resource_id = metric_alarm.name
report.resource_arn = metric_alarm.arn
report.resource_tags = metric_alarm.tags
report.status = "PASS"
report.status_extended = f"CloudWatch metric alarm {metric_alarm.name} has actions configured for the ALARM state."
if not metric_alarm.alarm_actions:
report.status = "FAIL"
report.status_extended = f"CloudWatch metric alarm {metric_alarm.name} does not have actions configured for the ALARM state."
findings.append(report)
return findings
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"Provider": "aws",
"CheckID": "cloudwatch_alarm_actions_enabled",
"CheckTitle": "Check if CloudWatch alarms have actions enabled",
"CheckType": [
"Software and Configuration Checks/AWS Security Best Practices"
],
"ServiceName": "cloudwatch",
"SubServiceName": "",
"ResourceIdTemplate": "arn:aws:cloudwatch:region:account-id:alarm/alarm-name",
"Severity": "high",
"ResourceType": "AwsCloudWatchAlarm",
"Description": "Alarm actions automatically alert you when a monitored metric is outside the defined threshold. If the alarm action is deactivated, no actions are run when the alarm changes state, and you won't be alerted to changes in monitored metrics. We recommend activating CloudWatch alarm actions to help you quickly respond to security and operational issues.",
"Risk": "Without active alarm actions, you may not be alerted to security or operational issues, potentially leading to delayed responses and increased risk.",
"RelatedUrl": "https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/AlarmThatSendsEmail.html#alarms-and-actions",
"Remediation": {
"Code": {
"CLI": "aws cloudwatch enable-alarm-actions --alarm-names <alarm-name>",
"NativeIaC": "",
"Other": "https://docs.aws.amazon.com/securityhub/latest/userguide/cloudwatch-controls.html#cloudwatch-17",
"Terraform": ""
},
"Recommendation": {
"Text": "Ensure that all CloudWatch alarms have at least one action configured. This can include sending notifications to SNS topics, invoking Lambda functions, or triggering other AWS services.",
"Url": "https://www.trendmicro.com/cloudoneconformity/knowledge-base/aws/CloudWatch/cloudwatch-alarm-action-activated.html"
}
},
"Categories": [],
"DependsOn": [],
"RelatedTo": [],
"Notes": ""
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
from prowler.lib.check.models import Check, Check_Report_AWS
from prowler.providers.aws.services.cloudwatch.cloudwatch_client import (
cloudwatch_client,
)


class cloudwatch_alarm_actions_enabled(Check):
def execute(self):
findings = []
for metric_alarm in cloudwatch_client.metric_alarms:
report = Check_Report_AWS(self.metadata())
report.region = metric_alarm.region
report.resource_id = metric_alarm.name
report.resource_arn = metric_alarm.arn
report.resource_tags = metric_alarm.tags
report.status = "PASS"
report.status_extended = (
f"CloudWatch metric alarm {metric_alarm.name} has actions enabled."
)
if not metric_alarm.actions_enabled:
report.status = "FAIL"
report.status_extended = f"CloudWatch metric alarm {metric_alarm.name} does not have actions enabled."
findings.append(report)
return findings
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
from prowler.providers.aws.lib.service.service import AWSService


################## CloudWatch
class CloudWatch(AWSService):
def __init__(self, provider):
# Call AWSService's __init__
Expand Down Expand Up @@ -43,6 +42,8 @@ def _describe_alarms(self, regional_client):
metric=metric_name,
name_space=namespace,
region=regional_client.region,
alarm_actions=alarm.get("AlarmActions", []),
actions_enabled=alarm.get("ActionsEnabled", False),
)
)
except ClientError as error:
Expand Down Expand Up @@ -76,7 +77,6 @@ def _list_tags_for_resource(self):
)


################## CloudWatch Logs
class Logs(AWSService):
def __init__(self, provider):
# Call AWSService's __init__
Expand Down Expand Up @@ -247,6 +247,8 @@ class MetricAlarm(BaseModel):
name_space: Optional[str]
region: str
tags: Optional[list] = []
alarm_actions: list
actions_enabled: bool


class LogGroup(BaseModel):
Expand Down
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"Provider": "aws",
"CheckID": "codebuild_project_logging_enabled",
"CheckTitle": "Ensure that CodeBuild projects have S3 or CloudWatch logging enabled",
"CheckType": [],
"ServiceName": "codebuild",
"SubServiceName": "",
"ResourceIdTemplate": "arn:partition:service:region:account-id:resource-id",
"Severity": "medium",
"ResourceType": "AwsCodeBuildProject",
"Description": "Ensure that CodeBuild projects have S3 or CloudWatch logging enabled.",
"Risk": "Without logging, tracking and investigating security incidents in CodeBuild projects becomes challenging, reducing confidence in threat detections.",
"RelatedUrl": "https://docs.aws.amazon.com/codebuild/latest/userguide/change-project.html#change-project-console-logs",
"Remediation": {
"Code": {
"CLI": "aws codebuild update-project --name <project-name> --logs-config \"cloudWatchLogs={status=ENABLED},s3Logs={status=ENABLED\"}",
"NativeIaC": "",
"Other": "https://docs.aws.amazon.com/securityhub/latest/userguide/codebuild-controls.html#codebuild-4",
"Terraform": ""
},
"Recommendation": {
"Text": "Enable logging for CodeBuild projects to capture build events and logs for future analysis and incident response.",
"Url": "https://docs.aws.amazon.com/codebuild/latest/userguide/change-project.html#change-project-console-logs"
}
},
"Categories": [
"logging"
],
"DependsOn": [],
"RelatedTo": [],
"Notes": ""
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
from prowler.lib.check.models import Check, Check_Report_AWS
from prowler.providers.aws.services.codebuild.codebuild_client import codebuild_client


class codebuild_project_logging_enabled(Check):
def execute(self):
findings = []
for project in codebuild_client.projects.values():
report = Check_Report_AWS(self.metadata())
report.resource_id = project.name
report.resource_arn = project.arn
report.region = project.region
report.resource_tags = project.tags
report.status = "PASS"

if project.cloudwatch_logs.enabled and project.s3_logs.enabled:
report.status_extended = f"CodeBuild project {project.name} has enabled CloudWartch logs in log group {project.cloudwatch_logs.group_name} and S3 logs in bucket {project.s3_logs.bucket_location}."
elif project.cloudwatch_logs.enabled:
report.status_extended = f"CodeBuild project {project.name} has CloudWatch logging enabled in log group {project.cloudwatch_logs.group_name}."
elif project.s3_logs.enabled:
report.status_extended = f"CodeBuild project {project.name} has S3 logging enabled in bucket {project.s3_logs.bucket_location}."
else:
report.status = "FAIL"
report.status_extended = (
f"CodeBuild project {project.name} does not have logging enabled."
)

findings.append(report)

return findings
Loading

0 comments on commit 97fac7a

Please sign in to comment.