mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-07-24 21:11:53 +00:00
feat(cloudwatch): add new check cloudwatch_alarm_actions_enabled (#5416)
Co-authored-by: Sergio <sergio@prowler.com>
This commit is contained in:
committed by
GitHub
parent
a491e39a18
commit
23c3884ab7
+32
@@ -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": ""
|
||||
}
|
||||
+24
@@ -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
|
||||
@@ -43,6 +43,7 @@ class CloudWatch(AWSService):
|
||||
metric=metric_name,
|
||||
name_space=namespace,
|
||||
region=regional_client.region,
|
||||
actions_enabled=alarm["ActionsEnabled"],
|
||||
)
|
||||
)
|
||||
except ClientError as error:
|
||||
@@ -247,6 +248,7 @@ class MetricAlarm(BaseModel):
|
||||
name_space: Optional[str]
|
||||
region: str
|
||||
tags: Optional[list] = []
|
||||
actions_enabled: bool = False
|
||||
|
||||
|
||||
class LogGroup(BaseModel):
|
||||
|
||||
+130
@@ -0,0 +1,130 @@
|
||||
from unittest import mock
|
||||
|
||||
from boto3 import client
|
||||
from moto import mock_aws
|
||||
|
||||
from tests.providers.aws.utils import AWS_REGION_US_EAST_1, set_mocked_aws_provider
|
||||
|
||||
|
||||
class Test_cloudwatch_alarm_actions_enabled:
|
||||
@mock_aws
|
||||
def test_no_cloudwatch_alarms(self):
|
||||
cloudwatch_client = client("cloudwatch", region_name=AWS_REGION_US_EAST_1)
|
||||
cloudwatch_client.metric_alarms = []
|
||||
|
||||
from prowler.providers.aws.services.cloudwatch.cloudwatch_service import (
|
||||
CloudWatch,
|
||||
)
|
||||
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_US_EAST_1])
|
||||
|
||||
with mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=aws_provider,
|
||||
), mock.patch(
|
||||
"prowler.providers.aws.services.cloudwatch.cloudwatch_alarm_actions_enabled.cloudwatch_alarm_actions_enabled.cloudwatch_client",
|
||||
new=CloudWatch(aws_provider),
|
||||
):
|
||||
|
||||
from prowler.providers.aws.services.cloudwatch.cloudwatch_alarm_actions_enabled.cloudwatch_alarm_actions_enabled import (
|
||||
cloudwatch_alarm_actions_enabled,
|
||||
)
|
||||
|
||||
check = cloudwatch_alarm_actions_enabled()
|
||||
result = check.execute()
|
||||
|
||||
assert len(result) == 0
|
||||
|
||||
@mock_aws
|
||||
def test_cloudwatch_alarms_actions_enabled(self):
|
||||
cloudwatch_client = client("cloudwatch", region_name=AWS_REGION_US_EAST_1)
|
||||
cloudwatch_client.put_metric_alarm(
|
||||
AlarmName="test_alarm",
|
||||
AlarmDescription="Test alarm",
|
||||
ActionsEnabled=True,
|
||||
AlarmActions=["arn:aws:sns:us-east-1:123456789012:my-sns-topic"],
|
||||
EvaluationPeriods=1,
|
||||
ComparisonOperator="GreaterThanThreshold",
|
||||
)
|
||||
|
||||
from prowler.providers.aws.services.cloudwatch.cloudwatch_service import (
|
||||
CloudWatch,
|
||||
)
|
||||
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_US_EAST_1])
|
||||
|
||||
with mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=aws_provider,
|
||||
), mock.patch(
|
||||
"prowler.providers.aws.services.cloudwatch.cloudwatch_alarm_actions_enabled.cloudwatch_alarm_actions_enabled.cloudwatch_client",
|
||||
new=CloudWatch(aws_provider),
|
||||
):
|
||||
|
||||
from prowler.providers.aws.services.cloudwatch.cloudwatch_alarm_actions_enabled.cloudwatch_alarm_actions_enabled import (
|
||||
cloudwatch_alarm_actions_enabled,
|
||||
)
|
||||
|
||||
check = cloudwatch_alarm_actions_enabled()
|
||||
result = check.execute()
|
||||
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "PASS"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== "CloudWatch metric alarm test_alarm has actions enabled."
|
||||
)
|
||||
assert result[0].resource_id == "test_alarm"
|
||||
assert (
|
||||
result[0].resource_arn
|
||||
== "arn:aws:cloudwatch:us-east-1:123456789012:alarm:test_alarm"
|
||||
)
|
||||
assert result[0].region == AWS_REGION_US_EAST_1
|
||||
assert result[0].resource_tags == []
|
||||
|
||||
@mock_aws
|
||||
def test_cloudwatch_alarms_actions_disabled(self):
|
||||
cloudwatch_client = client("cloudwatch", region_name=AWS_REGION_US_EAST_1)
|
||||
cloudwatch_client.put_metric_alarm(
|
||||
AlarmName="test_alarm",
|
||||
AlarmDescription="Test alarm",
|
||||
ActionsEnabled=False,
|
||||
AlarmActions=["arn:aws:sns:us-east-1:123456789012:my-sns-topic"],
|
||||
EvaluationPeriods=1,
|
||||
ComparisonOperator="GreaterThanThreshold",
|
||||
)
|
||||
|
||||
from prowler.providers.aws.services.cloudwatch.cloudwatch_service import (
|
||||
CloudWatch,
|
||||
)
|
||||
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_US_EAST_1])
|
||||
|
||||
with mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=aws_provider,
|
||||
), mock.patch(
|
||||
"prowler.providers.aws.services.cloudwatch.cloudwatch_alarm_actions_enabled.cloudwatch_alarm_actions_enabled.cloudwatch_client",
|
||||
new=CloudWatch(aws_provider),
|
||||
):
|
||||
|
||||
from prowler.providers.aws.services.cloudwatch.cloudwatch_alarm_actions_enabled.cloudwatch_alarm_actions_enabled import (
|
||||
cloudwatch_alarm_actions_enabled,
|
||||
)
|
||||
|
||||
check = cloudwatch_alarm_actions_enabled()
|
||||
result = check.execute()
|
||||
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== "CloudWatch metric alarm test_alarm does not have actions enabled."
|
||||
)
|
||||
assert result[0].resource_id == "test_alarm"
|
||||
assert (
|
||||
result[0].resource_arn
|
||||
== "arn:aws:cloudwatch:us-east-1:123456789012:alarm:test_alarm"
|
||||
)
|
||||
assert result[0].region == AWS_REGION_US_EAST_1
|
||||
assert result[0].resource_tags == []
|
||||
@@ -116,6 +116,7 @@ class Test_CloudWatch_Service:
|
||||
Threshold=2,
|
||||
Unit="Seconds",
|
||||
Tags=[{"Key": "key-1", "Value": "value-1"}],
|
||||
ActionsEnabled=True,
|
||||
)
|
||||
aws_provider = set_mocked_aws_provider(
|
||||
expected_checks=["cloudwatch_log_group_no_secrets_in_logs"]
|
||||
@@ -133,6 +134,7 @@ class Test_CloudWatch_Service:
|
||||
assert cloudwatch.metric_alarms[0].tags == [
|
||||
{"Key": "key-1", "Value": "value-1"}
|
||||
]
|
||||
assert cloudwatch.metric_alarms[0].actions_enabled
|
||||
|
||||
# Test Logs Filters
|
||||
@mock_aws
|
||||
|
||||
Reference in New Issue
Block a user