CloudWatch alarms should have action enabled
A CloudWatch alarm with disabled actions is functionally decorative. It will change state internally but never notify an SNS topic, trigger an Auto Scaling policy, or stop a runaway EC2 instance. Teams often disable actions during maintenance windows and forget to re-enable them, creating blind spots that persist for weeks or months.
The failure mode is insidious because dashboards may still show alarm states correctly, giving operators a false sense of coverage. Actual incident response depends on actions firing, not on the alarm existing.
Retrofit consideration
Implementation
Choose the approach that matches how you manage Terraform.
Use the compliance.tf module to enforce this control by default. See get started with compliance.tf.
This control is enforced automatically with Compliance.tf modules. Start free trial
If you use terraform-aws-modules/cloudwatch/aws//modules/metric-alarm, set the right module inputs for this control. You can later migrate to the compliance.tf module with minimal changes because it is compatible by design.
module "cloudwatch" {
source = "terraform-aws-modules/cloudwatch/aws//modules/metric-alarm"
version = ">=5.0.0"
alarm_actions = ["arn:aws:sns:us-east-1:123456789012:example-topic"]
alarm_name = "pofix-abc123"
comparison_operator = "GreaterThanThreshold"
evaluation_periods = 1
metric_name = "CPUUtilization"
namespace = "AWS/EC2"
period = 300
statistic = "Average"
threshold = 80
actions_enabled = true
}Use AWS provider resources directly. See docs for the resources involved: aws_cloudwatch_metric_alarm.
resource "aws_cloudwatch_metric_alarm" "this" {
alarm_actions = ["arn:aws:sns:us-east-1:123456789012:example-topic"]
alarm_name = "pofix-abc123"
comparison_operator = "GreaterThanOrEqualToThreshold"
evaluation_periods = 1
metric_name = "CPUUtilization"
namespace = "AWS/EC2"
period = 300
statistic = "Average"
threshold = 80
actions_enabled = true
}What this control checks
The aws_cloudwatch_metric_alarm resource controls this via the actions_enabled argument. Set to true (or omitted, since true is the provider default), the alarm executes its configured alarm_actions, ok_actions, and insufficient_data_actions on state transitions. Setting actions_enabled = false fails the control. To pass, either set it explicitly or rely on the default. Note that the alarm also needs at least one ARN in alarm_actions for the flag to be meaningful, but this control only checks the flag itself.
Common pitfalls
Default is true but explicit false persists after import
Import an alarm that had actions disabled via the console or aws cloudwatch disable-alarm-actions, and the imported state may show actions_enabled = false until you apply configuration. If actions_enabled is omitted from the resource block, Terraform uses the provider default (true) and a plan will show an update to re-enable actions. Make the value explicit rather than relying on the default.
Actions enabled but action list is empty
This control passes when actions_enabled = true, but an alarm with no ARNs in alarm_actions, ok_actions, or insufficient_data_actions still does nothing on state change. Passing this check alone does not guarantee operational alerting.
Temporary disable during deployments not reverted
Teams sometimes call aws cloudwatch disable-alarm-actions during blue/green deployments to suppress noise. If the re-enable step is skipped because a CI/CD pipeline fails or a runbook step gets missed, alarms stay silenced. Terraform will not correct this unless the alarm is fully managed in state with actions_enabled = true declared.
Composite alarms have separate actions_enabled
The aws_cloudwatch_composite_alarm resource also has an actions_enabled argument. If you use composite alarms to aggregate metric alarms, both layers need actions enabled. This control evaluates metric alarms, but composite alarms with disabled actions create the same blind spot.
Audit evidence
Config rule evaluation results for CLOUDWATCH_ALARM_ACTION_CHECK showing all alarms as compliant is the primary artifact. Supporting evidence includes aws cloudwatch describe-alarms output filtered to show ActionsEnabled: true for every alarm, or console screenshots of the alarm list with the "Actions enabled" column visible.
For ongoing assurance, CloudTrail logs showing DisableAlarmActions and EnableAlarmActions API calls help auditors verify that any temporary disabling was reversed promptly.
Framework-specific interpretation
SOC 2: CC7.2 covers monitoring for anomalies; CC7.3 covers evaluation and response to identified issues. Disabled alarm actions sever the connection between those two requirements: the system detects, but never acts on what it finds. Type II examiners evaluate operating effectiveness, and an alarm that never pages anyone or triggers automation does not demonstrate effective monitoring controls.
NIST Cybersecurity Framework v2.0: DE.CM and DE.AE require that monitoring signals actually reach someone or trigger a response. An alarm that transitions state but never fires its actions satisfies neither. Detection capability that exists only in configuration is not detection capability in practice.
Related controls
Tool mappings
Use these identifiers to cross-reference this control across tools, reports, and evidence.
- Compliance.tf Control:
cloudwatch_alarm_action_enabled_check - AWS Config Managed Rule:
CLOUDWATCH_ALARM_ACTION_ENABLED_CHECK - Checkov Check:
CKV_AWS_319 - Powerpipe Control:
aws_compliance.control.cloudwatch_alarm_action_enabled_check - Prowler Check:
cloudwatch_alarm_actions_enabled - AWS Security Hub Control:
CloudWatch.17
Last reviewed: 2026-03-09