> ## Documentation Index
> Fetch the complete documentation index at: https://cloudanix.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Security group changes alarm remediation

### Triage and Remediation

<Tabs>
  <Tab title="Remediation">
    ### Remediation

    <AccordionGroup>
      <Accordion title="Using Console" defaultOpen="true">
        Below are console-based steps to set up a CloudWatch alarm for Security Group changes using CloudTrail logs.

        ***

        ## 1. Ensure CloudTrail Is Enabled and Sending Logs to CloudWatch Logs

        1. In the AWS Management Console, go to **CloudTrail**.
        2. In the left pane, choose **Trails**.
        3. Either:
           * **Use existing trail** that already:
             * Logs **Management events** (Read/Write or at least **Write-only**).
             * Delivers logs to a **CloudWatch Logs log group**,
           * Or create/configure one:
             1. Click **Create trail** (or select a trail → **Edit**).
             2. Under **Management events**, ensure **Write** is enabled.
             3. Under **CloudWatch Logs**, choose **Enabled**.
             4. Select or create:
                * A **CloudWatch log group**, and
                * An **IAM role** for CloudTrail to put logs in CloudWatch Logs.
             5. Save the trail.

        ***

        ## 2. Create a Metric Filter for Security Group Changes

        1. Go to **CloudWatch** in the console.

        2. In the left pane, select **Logs → Log groups**.

        3. Click the log group that CloudTrail is configured to use (e.g., `/aws/cloudtrail/logs`).

        4. Select the **Metric filters** tab.

        5. Click **Create metric filter**.

        6. Under **Filter pattern**, paste:

           ```text theme={null}
           {($.eventName = AuthorizeSecurityGroupIngress) ||
            ($.eventName = AuthorizeSecurityGroupEgress)  ||
            ($.eventName = RevokeSecurityGroupIngress)    ||
            ($.eventName = RevokeSecurityGroupEgress)     ||
            ($.eventName = CreateSecurityGroup)           ||
            ($.eventName = DeleteSecurityGroup)           ||
            ($.eventName = UpdateSecurityGroupRuleDescriptionsIngress) ||
            ($.eventName = UpdateSecurityGroupRuleDescriptionsEgress)}
           ```

        7. Click **Next**.

        8. For **Metric name**, enter something like: `SecurityGroupChangeCount`.

        9. For **Metric namespace**, use something like: `CIS/SecurityGroup`.

        10. For **Metric value**, enter: `1`.

        11. Leave **Default value** empty or `0` (optional).

        12. Click **Next**, then **Create metric filter**.

        ***

        ## 3. Create a CloudWatch Alarm for the Metric

        1. Still in **CloudWatch**, go to **Alarms → All alarms**.
        2. Click **Create alarm**.
        3. Click **Select metric**.
        4. Navigate to the namespace you created: **CIS → SecurityGroup → Metrics with no dimensions** (or whatever you named it).
        5. Select the metric **SecurityGroupChangeCount** and click **Next**.

        ***

        ## 4. Configure Alarm Threshold

        1. Under **Conditions**:
           * **Statistic**: `Sum`.
           * **Period**: e.g., `5 minutes`.
           * **Threshold type**: `Static`.
           * **Whenever SecurityGroupChangeCount is**: `>= 1`.
        2. Click **Next**.

        ***

        ## 5. Set Notification (SNS) for the Alarm

        1. Under **Notification**:
           * **Alarm state trigger**: `In alarm`.
           * **Select an SNS topic** (e.g., `security-alerts`), or click **Create new topic**:
             * Give it a name, e.g., `security-group-changes-topic`.
             * Add your email address (or other endpoints) as a subscription.
        2. Click **Next**.

        ***

        ## 6. Name and Create the Alarm

        1. Give the alarm a name like: `SecurityGroupChangesAlarm`.
        2. (Optional) Add a description, e.g., “Alarm on any Security Group change events from CloudTrail”.
        3. Review settings and click **Create alarm**.

        ***

        ## 7. Confirm SNS Subscription

        1. Check your email (or other endpoint) for the **SNS subscription confirmation** message.
        2. Confirm the subscription so you receive alerts.

        This will trigger a CloudWatch alarm any time CloudTrail logs a Security Group change and send a notification via SNS.
      </Accordion>

      <Accordion title="Using CLI">
        Below is one straightforward way to do this entirely via AWS CLI using a CloudWatch Logs metric filter on CloudTrail logs, plus a CloudWatch alarm.

        Assumptions (adjust as needed):

        * You already have a **CloudTrail trail** that logs to a **CloudWatch Logs log group**.
        * Log group name: `CloudTrail/DefaultLogGroup`
        * Region: `us-east-1`
        * SNS topic for notifications: `arn:aws:sns:us-east-1:123456789012:SecurityNotifications`

        ***

        ### 1. Verify your CloudTrail is sending logs to CloudWatch Logs

        ```bash theme={null}
        aws cloudtrail describe-trails \
          --query "trailList[].{Name:Name,LogGroupArn:CloudWatchLogsLogGroupArn}" \
          --region us-east-1
        ```

        If `CloudWatchLogsLogGroupArn` is empty, you must configure CloudTrail to send to a log group first (either via console or `update-trail` + `put-event-selectors`). Once CloudTrail is delivering events to a log group, use that log group name in the steps below.

        ***

        ### 2. Create the CloudWatch Logs metric filter

        Replace the log group name as needed.

        ```bash theme={null}
        LOG_GROUP_NAME="CloudTrail/DefaultLogGroup"
        METRIC_NAME="SecurityGroupChanges"
        METRIC_NAMESPACE="CloudTrailMetrics"

        aws logs put-metric-filter \
          --log-group-name "$LOG_GROUP_NAME" \
          --filter-name "SecurityGroupChanges" \
          --filter-pattern '{ ($.eventName = AuthorizeSecurityGroupIngress) || 
                              ($.eventName = AuthorizeSecurityGroupEgress)  || 
                              ($.eventName = RevokeSecurityGroupIngress)    || 
                              ($.eventName = RevokeSecurityGroupEgress)     || 
                              ($.eventName = CreateSecurityGroup)           || 
                              ($.eventName = DeleteSecurityGroup) }' \
          --metric-transformations \
              metricName="$METRIC_NAME",metricNamespace="$METRIC_NAMESPACE",metricValue=1
        ```

        This creates a metric that increments whenever a security group is created, deleted, or its rules are changed.

        ***

        ### 3. Create the CloudWatch alarm on that metric

        ```bash theme={null}
        SNS_TOPIC_ARN="arn:aws:sns:us-east-1:123456789012:SecurityNotifications"
        ALARM_NAME="SecurityGroupChangesAlarm"
        REGION="us-east-1"

        aws cloudwatch put-metric-alarm \
          --alarm-name "$ALARM_NAME" \
          --alarm-description "Alarm when security group configurations change." \
          --metric-name "$METRIC_NAME" \
          --namespace "$METRIC_NAMESPACE" \
          --statistic Sum \
          --period 300 \
          --evaluation-periods 1 \
          --threshold 1 \
          --comparison-operator GreaterThanOrEqualToThreshold \
          --treat-missing-data notBreaching \
          --alarm-actions "$SNS_TOPIC_ARN" \
          --region "$REGION"
        ```

        This alarm will go into ALARM state (and notify via SNS) if at least one security group change event is logged in the last 5 minutes.

        ***

        ### 4. (Optional) Test the setup

        Perform an action like adding a rule to a security group:

        ```bash theme={null}
        aws ec2 authorize-security-group-ingress \
          --group-id sg-xxxxxxxx \
          --protocol tcp \
          --port 443 \
          --cidr 1.2.3.4/32 \
          --region us-east-1
        ```

        Within a few minutes, the metric should increment and the alarm should trigger.
      </Accordion>

      <Accordion title="Using Python">
        Below are the steps and sample Python (boto3) code to enable an alarm on Security Group changes using CloudWatch in AWS.

        ## Overview

        To alarm on Security Group changes, you typically:

        1. Ensure CloudTrail is logging management events for EC2 (Security Groups) and sending logs to CloudWatch Logs.
        2. Create a CloudWatch Logs metric filter on those CloudTrail events.
        3. Create a CloudWatch alarm on that metric.

        ***

        ## 1. Prerequisites

        * `boto3` installed:
          ```bash theme={null}
          pip install boto3
          ```
        * AWS credentials configured (via environment vars, `~/.aws/credentials`, or IAM role).
        * An existing CloudTrail that:
          * Logs **management events**.
          * Delivers to a **CloudWatch Logs log group** (you need that log group name).

        Let’s assume:

        * Region: `us-east-1`
        * CloudWatch Logs group: `/aws/cloudtrail/security`
        * Metric namespace: `SecurityGroupMonitoring`
        * Metric name: `SecurityGroupChanges`
        * Alarm name: `SecurityGroupChangesAlarm`
        * Notification via SNS topic ARN: `arn:aws:sns:us-east-1:123456789012:secgroup-alerts`

        ***

        ## 2. Ensure CloudTrail is Sending to CloudWatch Logs (Python)

        If you already have this set up, you can skip this step.

        ```python theme={null}
        import boto3

        region = "us-east-1"
        logs_group_name = "/aws/cloudtrail/security"
        trail_name = "org-or-account-cloudtrail"  # change as needed

        logs = boto3.client("logs", region_name=region)
        ct = boto3.client("cloudtrail", region_name=region)

        # 1) Create CloudWatch Logs group if it doesn't exist
        try:
            logs.create_log_group(logGroupName=logs_group_name)
        except logs.exceptions.ResourceAlreadyExistsException:
            pass

        # 2) Configure / update CloudTrail to send logs to CloudWatch Logs
        ct.update_trail(
            Name=trail_name,
            CloudWatchLogsLogGroupArn=f"arn:aws:logs:{region}:123456789012:log-group:{logs_group_name}",
            CloudWatchLogsRoleArn="arn:aws:iam::123456789012:role/CloudTrail_CloudWatchLogs_Role",
        )
        ```

        You must have an IAM role (`CloudTrail_CloudWatchLogs_Role`) with the appropriate trust policy for CloudTrail and permissions to write to the log group.

        ***

        ## 3. Create CloudWatch Logs Metric Filter for Security Group Changes

        Target CloudTrail events for Security Groups, e.g.:

        * `AuthorizeSecurityGroupIngress`
        * `AuthorizeSecurityGroupEgress`
        * `RevokeSecurityGroupIngress`
        * `RevokeSecurityGroupEgress`
        * `CreateSecurityGroup`
        * `DeleteSecurityGroup`
        * `UpdateSecurityGroupRuleDescriptionsIngress`
        * `UpdateSecurityGroupRuleDescriptionsEgress`

        Filter pattern example:

        ```text theme={null}
        { ($.eventName = "AuthorizeSecurityGroupIngress") ||
          ($.eventName = "AuthorizeSecurityGroupEgress") ||
          ($.eventName = "RevokeSecurityGroupIngress") ||
          ($.eventName = "RevokeSecurityGroupEgress") ||
          ($.eventName = "CreateSecurityGroup") ||
          ($.eventName = "DeleteSecurityGroup") ||
          ($.eventName = "UpdateSecurityGroupRuleDescriptionsIngress") ||
          ($.eventName = "UpdateSecurityGroupRuleDescriptionsEgress") }
        ```

        Python to create the metric filter:

        ```python theme={null}
        import boto3

        region = "us-east-1"
        logs_group_name = "/aws/cloudtrail/security"
        metric_namespace = "SecurityGroupMonitoring"
        metric_name = "SecurityGroupChanges"
        metric_filter_name = "SecurityGroupChangesFilter"

        logs = boto3.client("logs", region_name=region)

        filter_pattern = (
            '{ ($.eventName = "AuthorizeSecurityGroupIngress") || '
            '($.eventName = "AuthorizeSecurityGroupEgress") || '
            '($.eventName = "RevokeSecurityGroupIngress") || '
            '($.eventName = "RevokeSecurityGroupEgress") || '
            '($.eventName = "CreateSecurityGroup") || '
            '($.eventName = "DeleteSecurityGroup") || '
            '($.eventName = "UpdateSecurityGroupRuleDescriptionsIngress") || '
            '($.eventName = "UpdateSecurityGroupRuleDescriptionsEgress") }'
        )

        logs.put_metric_filter(
            logGroupName=logs_group_name,
            filterName=metric_filter_name,
            filterPattern=filter_pattern,
            metricTransformations=[
                {
                    "metricName": metric_name,
                    "metricNamespace": metric_namespace,
                    "metricValue": "1"
                }
            ]
        )
        ```

        This will emit a metric value of `1` every time a matching event occurs.

        ***

        ## 4. Create a CloudWatch Alarm on That Metric

        For example, trigger an alarm if **≥ 1** change occurs in a 5‑minute period.

        ```python theme={null}
        import boto3

        region = "us-east-1"
        metric_namespace = "SecurityGroupMonitoring"
        metric_name = "SecurityGroupChanges"
        alarm_name = "SecurityGroupChangesAlarm"
        sns_topic_arn = "arn:aws:sns:us-east-1:123456789012:secgroup-alerts"

        cw = boto3.client("cloudwatch", region_name=region)

        cw.put_metric_alarm(
            AlarmName=alarm_name,
            AlarmDescription="Alarm when Security Group changes occur",
            Namespace=metric_namespace,
            MetricName=metric_name,
            Statistic="Sum",
            Period=300,  # 5 minutes
            EvaluationPeriods=1,
            Threshold=1,
            ComparisonOperator="GreaterThanOrEqualToThreshold",
            TreatMissingData="notBreaching",
            AlarmActions=[sns_topic_arn],      # actions when ALARM
            OKActions=[sns_topic_arn],         # optional: notify when OK
            Dimensions=[],                     # none; metric is global in namespace
        )
        ```

        ***

        ## 5. Validation

        1. Make a small SG change (e.g., add/remove a rule).
        2. Wait a few minutes.
        3. In CloudWatch console:
           * Check the custom metric `SecurityGroupMonitoring / SecurityGroupChanges`.
           * Confirm it registers data points.
           * Confirm `SecurityGroupChangesAlarm` changes state to `ALARM` and SNS is triggered.

        ***

        If you share your exact account/region/log group names and whether CloudTrail → CloudWatch Logs is already configured, I can adapt the code snippets precisely to your environment.
      </Accordion>

      <Accordion title="Using Terraform">
        ```hcl theme={null}
        # CloudTrail log group that already receives CloudTrail events
        # Replace EXISTING_CLOUDTRAIL_LOG_GROUP_NAME with your log group name
        data "aws_cloudwatch_log_group" "cloudtrail" {
          name = "EXISTING_CLOUDTRAIL_LOG_GROUP_NAME"
        }

        # Metric filter equivalent to `aws logs put-metric-filter ...`
        resource "aws_cloudwatch_log_metric_filter" "security_group_changes" {
          name           = "SecurityGroupChangesFilter"
          log_group_name = data.aws_cloudwatch_log_group.cloudtrail.name

          pattern = "{ ($.eventName = AuthorizeSecurityGroupIngress) || ($.eventName = AuthorizeSecurityGroupEgress) || ($.eventName = RevokeSecurityGroupIngress) || ($.eventName = RevokeSecurityGroupEgress) || ($.eventName = CreateSecurityGroup) || ($.eventName = DeleteSecurityGroup) }"

          metric_transformation {
            name      = "SecurityGroupChangesMetric"
            namespace = "CloudTrailMetrics"
            value     = "1"
          }
        }

        # SNS topic equivalent to `aws sns create-topic ...`
        resource "aws_sns_topic" "security_group_changes" {
          name = "SecurityGroupChangesTopic"
        }

        # SNS email subscription equivalent to `aws sns subscribe ...`
        # Replace ALERT_EMAIL_ADDRESS with a valid email you can confirm
        resource "aws_sns_topic_subscription" "security_group_changes_email" {
          topic_arn = aws_sns_topic.security_group_changes.arn
          protocol  = "email"
          endpoint  = "ALERT_EMAIL_ADDRESS"
        }

        # CloudWatch alarm equivalent to `aws cloudwatch put-metric-alarm ...`
        resource "aws_cloudwatch_metric_alarm" "security_group_changes" {
          alarm_name        = "SecurityGroupChangesAlarm"
          alarm_description = "Monitors for AWS Security Group changes"

          namespace  = "CloudTrailMetrics"
          metric_name = "SecurityGroupChangesMetric"
          statistic   = "Sum"
          period      = 300

          threshold          = 1
          comparison_operator = "GreaterThanOrEqualToThreshold"
          evaluation_periods  = 1
          datapoints_to_alarm = 1

          alarm_actions = [
            aws_sns_topic.security_group_changes.arn,
          ]

          treat_missing_data = "notBreaching"
        }

        ```

        This adds new resources and does not force replacement of existing ones, but if a metric filter, SNS topic, or alarm with the same name already exists and is not managed by Terraform, you must either import it or change the names to avoid conflicts.

        To verify, `terraform plan` should show 4 resources to add: `aws_cloudwatch_log_metric_filter.security_group_changes`, `aws_sns_topic.security_group_changes`, `aws_sns_topic_subscription.security_group_changes_email`, and `aws_cloudwatch_metric_alarm.security_group_changes`, with no changes to other resources.
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>
