Guided Walkthroughs

Configuration Packages

AI CloudAdvisor (Beta)

By Implementation

Service Control PoliciesConfig RulesAuto Remediation RulesConformance PacksAmazon GuardDutyAmazon InspectorAWS Security HubAWS Network FirewallRoute53 Resolver SecurityAmazon MacieS3 Bucket PoliciesCloudWatch Alarms and Event RulesAWS WAFAWS Secrets ManagerAWS Systems ManagerSecurity Groups & NACLsAWS KMSAWS SSOIAM PoliciesVPC Endpoint PoliciesCloudFormation Guard RulesLoad BalancersRDS Event SubscriptionsAWS Resource Access Manager (RAM)

By Service Protected

Reference Guides

Other

Configuration Packages

VPC Events and Compliance Rules

A configuration package to monitor VPC related API activity as well as configuration compliance rules to ensure the security of VPC configuration. The package includes:

A premium subscription is required for this content
You can browse templates for individual Config Rules, Event Rules, SNS notifications and more in our repository for free! Go to Library

Items
25
Size
19.4 KB
AWSTemplateFormatVersion: "2010-09-09"
Description: ""
Resources:
  BucketPolicy:
    Type: "AWS::S3::BucketPolicy"
    Properties:
      Bucket:
        Ref: "S3SharedBucket"
      PolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Principal:
              Service:
                - "cloudtrail.amazonaws.com"
                - "config.amazonaws.com"
            Action:
              - "s3:GetBucketAcl"
            Resource:
              - Fn::GetAtt:
                  - "S3SharedBucket"
                  - "Arn"
            Effect: "Allow"
            Condition: {}
          - Principal:
              Service:
                - "cloudtrail.amazonaws.com"
                - "config.amazonaws.com"
            Action:
              - "s3:PutObject"
            Resource:
              - Fn::Join:
                  - ""
                  -
                    - ""
                    - Fn::GetAtt:
                        - "S3SharedBucket"
                        - "Arn"
                    - "/*"
            Effect: "Allow"
            Condition:
              StringEquals:
                s3:x-amz-acl: "bucket-owner-full-control"
    DependsOn: "S3SharedBucket"
  CloudTrail:
    Type: "AWS::CloudTrail::Trail"
    Properties:
      TrailName: "ManagementEventsTrail"
      IsLogging: true
      EnableLogFileValidation: true
      EventSelectors:
        - IncludeManagementEvents: true
          ReadWriteType: "All"
      IsMultiRegionTrail: true
      IncludeGlobalServiceEvents: true
      S3BucketName:
        Ref: "S3SharedBucket"
      CloudWatchLogsLogGroupArn:
        Fn::GetAtt:
          - "CWLogGroupForCloudTrail"
          - "Arn"
      CloudWatchLogsRoleArn:
        Fn::GetAtt:
          - "IamRoleForCwLogsCloudTrail"
          - "Arn"
    DependsOn:
      - "BucketPolicy"
  IamRoleForCwLogsCloudTrail:
    Type: "AWS::IAM::Role"
    Properties:
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Sid: ""
            Effect: "Allow"
            Principal:
              Service: "cloudtrail.amazonaws.com"
            Action: "sts:AssumeRole"
      Policies:
        - PolicyName: "allow-access-to-cw-logs"
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: "Allow"
                Action:
                  - "logs:CreateLogStream"
                  - "logs:PutLogEvents"
                Resource: "*"
  CWLogGroupForCloudTrail:
    Type: "AWS::Logs::LogGroup"
    Properties:
      LogGroupName: "CloudTrailLogs"
      RetentionInDays: 90
  ConfigurationRecorder:
    Type: "AWS::Config::ConfigurationRecorder"
    Properties:
      RoleARN:
        Fn::GetAtt:
          - "IamRoleForAwsConfig"
          - "Arn"
      RecordingGroup:
        AllSupported: true
        IncludeGlobalResourceTypes: true
  DeliveryChannel:
    Type: "AWS::Config::DeliveryChannel"
    Properties:
      S3BucketName:
        Ref: "S3SharedBucket"
  IamRoleForAwsConfig:
    Type: "AWS::IAM::Role"
    Properties:
      ManagedPolicyArns:
        - "arn:aws:iam::aws:policy/service-role/AWS_ConfigRole"
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Sid: ""
            Effect: "Allow"
            Principal:
              Service: "config.amazonaws.com"
            Action: "sts:AssumeRole"
      Policies:
        - PolicyName: "allow-access-to-config-s3-bucket"
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: "Allow"
                Action:
                  - "s3:PutObject"
                Resource:
                  - Fn::Join:
                      - ""
                      -
                        - Fn::GetAtt:
                            - "S3SharedBucket"
                            - "Arn"
                        - "/*"
                Condition:
                  StringLike:
                    s3:x-amz-acl: "bucket-owner-full-control"
              - Effect: "Allow"
                Action:
                  - "s3:GetBucketAcl"
                Resource:
                  Fn::GetAtt:
                    - "S3SharedBucket"
                    - "Arn"
      RoleName: "iamRoleForAWSConfig"
  S3SharedBucket:
    Type: "AWS::S3::Bucket"
    Properties:
      LoggingConfiguration: {}
      BucketEncryption:
        ServerSideEncryptionConfiguration:
          - ServerSideEncryptionByDefault:
              SSEAlgorithm: "AES256"
      VersioningConfiguration:
        Status: "Suspended"
      AccessControl: "LogDeliveryWrite"
      PublicAccessBlockConfiguration:
        BlockPublicAcls: true
        BlockPublicPolicy: true
        IgnorePublicAcls: true
        RestrictPublicBuckets: true
  SnsTopic1:
    Type: "AWS::SNS::Topic"
    Properties:
      Subscription:
        - Endpoint: "email@example.com"
          Protocol: "email"
      TopicName: "sns-topic"
  ConfigRule1:
    Type: "AWS::Config::ConfigRule"
    Properties:
      ConfigRuleName: "restricted-ssh"
      Scope:
        ComplianceResourceTypes:
          - "AWS::EC2::SecurityGroup"
      Description: "A Config rule that checks whether security groups in use do not allow restricted incoming SSH traffic. This rule applies only to IPv4."
      Source:
        Owner: "AWS"
        SourceIdentifier: "INCOMING_SSH_DISABLED"
    DependsOn:
      - "ConfigurationRecorder"
  ConfigRule2:
    Type: "AWS::Config::ConfigRule"
    Properties:
      ConfigRuleName: "restricted-common-ports"
      Scope:
        ComplianceResourceTypes:
          - "AWS::EC2::SecurityGroup"
      Description: "A Config rule that checks whether security groups in use do not allow restricted incoming TCP traffic to the specified ports. This rule applies only to IPv4."
      InputParameters:
        blockedPort1: "20"
        blockedPort2: "21"
        blockedPort3: "3389"
        blockedPort4: "3306"
        blockedPort5: "4333"
      Source:
        Owner: "AWS"
        SourceIdentifier: "RESTRICTED_INCOMING_TRAFFIC"
    DependsOn:
      - "ConfigurationRecorder"
  ConfigRule3:
    Type: "AWS::Config::ConfigRule"
    Properties:
      ConfigRuleName: "ec2_vpc_public_subnet"
      Scope:
        ComplianceResourceTypes:
          - "AWS::EC2::Instance"
      Description: "A Config rule that checks that no EC2 Instances are in Public Subnet."
      Source:
        Owner: "CUSTOM_LAMBDA"
        SourceIdentifier:
          Fn::GetAtt:
            - "LambdaFunctionForConfigRule3"
            - "Arn"
        SourceDetails:
          - EventSource: "aws.config"
            MessageType: "ConfigurationItemChangeNotification"
          - EventSource: "aws.config"
            MessageType: "OversizedConfigurationItemChangeNotification"
    DependsOn:
      - "ConfigurationRecorder"
  LambdaInvokePermissionsConfigRule3:
    Type: "AWS::Lambda::Permission"
    Properties:
      FunctionName:
        Fn::GetAtt:
          - "LambdaFunctionForConfigRule3"
          - "Arn"
      Action: "lambda:InvokeFunction"
      Principal: "config.amazonaws.com"
  LambdaFunctionForConfigRule3:
    Type: "AWS::Lambda::Function"
    Properties:
      FunctionName: "LambdaForec2_vpc_public_subnet"
      Handler: "index.lambda_handler"
      Role:
        Fn::GetAtt:
          - "LambdaIamRoleConfigRule3"
          - "Arn"
      Runtime: "python3.9"
      Code:
        ZipFile:
          Fn::Join:
            - "\n"
            -
              - ""
              - "#"
              - "# This file made available under CC0 1.0 Universal (https://creativecommons.org/publicdomain/zero/1.0/legalcode)"
              - "#"
              - "# Description: Check that no EC2 Instances are in Public Subnet"
              - "#"
              - "# Trigger Type: Change Triggered"
              - "# Scope of Changes: EC2:Instance"
              - "# Accepted Parameters: None"
              - "# Your Lambda function execution role will need to have a policy that provides the appropriate"
              - "# permissions.  Here is a policy that you can consider.  You should validate this for your own"
              - "# environment"
              - "#{"
              - "#    \"Version\": \"2012-10-17\","
              - "#    \"Statement\": ["
              - "#        {"
              - "#            \"Effect\": \"Allow\","
              - "#            \"Action\": ["
              - "#                \"logs:CreateLogGroup\","
              - "#                \"logs:CreateLogStream\","
              - "#                \"logs:PutLogEvents\""
              - "#            ],"
              - "#            \"Resource\": \"arn:aws:logs:*:*:*\""
              - "#        },"
              - "#        {"
              - "#            \"Effect\": \"Allow\","
              - "#            \"Action\": ["
              - "#                \"config:PutEvaluations\","
              - "#                \"ec2:DescribeRouteTables\""
              - "#            ],"
              - "#            \"Resource\": \"*\""
              - "#        }"
              - "#    ]"
              - "#}"
              - "#"
              - ""
              - "import boto3"
              - "import botocore"
              - "import json"
              - "import logging"
              - ""
              - "log = logging.getLogger()"
              - "log.setLevel(logging.INFO)"
              - ""
              - "def evaluate_compliance(configuration_item):"
              - "    subnet_id   = configuration_item[\"configuration\"][\"subnetId\"]"
              - "    vpc_id      = configuration_item[\"configuration\"][\"vpcId\"]"
              - "    client      = boto3.client(\"ec2\");"
              - ""
              - "    response    = client.describe_route_tables()"
              - ""
              - "    # If the subnet is explicitly associated to a route table, check if there"
              - "    # is a public route. If no explicit association exists, check if the main"
              - "    # route table has a public route."
              - ""
              - "    private = True"
              - "    mainTableIsPublic = False"
              - "    noExplicitAssociationFound = True"
              - "    explicitAssocationIsPublic = False"
              - ""
              - "    for i in response['RouteTables']:"
              - "        if i['VpcId'] == vpc_id:"
              - "            for j in i['Associations']:"
              - "                if j['Main'] == True:"
              - "                    for k in i['Routes']:"
              - "                        if k['DestinationCidrBlock'] == '0.0.0.0/0' or k['GatewayId'].startswith('igw-'):"
              - "                            mainTableIsPublic = True"
              - "                else:"
              - "                    if j['SubnetId'] == subnet_id:"
              - "                        noExplicitAssociationFound = False"
              - "                        for k in i['Routes']:"
              - "                            if k['DestinationCidrBlock'] == '0.0.0.0/0' or k['GatewayId'].startswith('igw-'):"
              - "                                explicitAssocationIsPublic = True"
              - ""
              - "    if (mainTableIsPublic and noExplicitAssociationFound) or explicitAssocationIsPublic:"
              - "        private = False"
              - ""
              - "    if private:"
              - "        return {"
              - "            \"compliance_type\": \"COMPLIANT\","
              - "            \"annotation\": 'Its in private subnet'"
              - "        }"
              - "    else:"
              - "        return {"
              - "            \"compliance_type\" : \"NON_COMPLIANT\","
              - "            \"annotation\" : 'Not in private subnet'"
              - "        }"
              - ""
              - "def lambda_handler(event, context):"
              - "    log.debug('Event %s', event)"
              - "    invoking_event      = json.loads(event['invokingEvent'])"
              - "    configuration_item  = invoking_event[\"configurationItem\"]"
              - "    evaluation          = evaluate_compliance(configuration_item)"
              - "    config              = boto3.client('config')"
              - ""
              - "    response = config.put_evaluations("
              - "       Evaluations=["
              - "           {"
              - "               'ComplianceResourceType':    invoking_event['configurationItem']['resourceType'],"
              - "               'ComplianceResourceId':      invoking_event['configurationItem']['resourceId'],"
              - "               'ComplianceType':            evaluation[\"compliance_type\"],"
              - "               \"Annotation\":                evaluation[\"annotation\"],"
              - "               'OrderingTimestamp':         invoking_event['configurationItem']['configurationItemCaptureTime']"
              - "           },"
              - "       ],"
              - "       ResultToken=event['resultToken'])"
              - ""
      Timeout: 300
    DependsOn: "LambdaIamRoleConfigRule3"
  LambdaIamRoleConfigRule3:
    Type: "AWS::IAM::Role"
    Properties:
      RoleName: "IAMRoleForec2_vpc_public_subnetXhu"
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: "Allow"
            Principal:
              Service:
                - "lambda.amazonaws.com"
            Action:
              - "sts:AssumeRole"
      ManagedPolicyArns:
        - "arn:aws:iam::aws:policy/AmazonEC2ReadOnlyAccess"
        - "arn:aws:iam::aws:policy/service-role/AWSConfigRulesExecutionRole"
        - "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
  CwEvent1:
    Type: "AWS::Events::Rule"
    Properties:
      Name: "detect-config-rule-compliance-changes"
      Description: "A CloudWatch Event Rule that detects changes to AWS Config Rule compliance status and publishes change events to an SNS topic for notification."
      State: "ENABLED"
      Targets:
        - Arn:
            Ref: "SnsTopic1"
          Id: "target-id1"
      EventPattern:
        detail-type:
          - "Config Rules Compliance Change"
        source:
          - "aws.config"
  SnsTopicPolicyCwEvent1:
    Type: "AWS::SNS::TopicPolicy"
    Properties:
      PolicyDocument:
        Statement:
          - Sid: "__default_statement_ID"
            Effect: "Allow"
            Principal:
              AWS: "*"
            Action:
              - "SNS:GetTopicAttributes"
              - "SNS:SetTopicAttributes"
              - "SNS:AddPermission"
              - "SNS:RemovePermission"
              - "SNS:DeleteTopic"
              - "SNS:Subscribe"
              - "SNS:ListSubscriptionsByTopic"
              - "SNS:Publish"
              - "SNS:Receive"
            Resource:
              Ref: "SnsTopic1"
            Condition:
              StringEquals:
                AWS:SourceOwner:
                  Ref: "AWS::AccountId"
          - Sid: "TrustCWEToPublishEventsToMyTopic"
            Effect: "Allow"
            Principal:
              Service: "events.amazonaws.com"
            Action: "sns:Publish"
            Resource:
              Ref: "SnsTopic1"
      Topics:
        - Ref: "SnsTopic1"
  CwAlarm1:
    Type: "AWS::CloudWatch::Alarm"
    Properties:
      AlarmName: "igw_changes"
      AlarmDescription: "A CloudWatch Alarm that triggers when changes are made to an Internet Gateway in a VPC."
      MetricName: "GatewayEventCount"
      Namespace: "CloudTrailMetrics"
      Statistic: "Sum"
      Period: "300"
      EvaluationPeriods: "1"
      Threshold: "1"
      ComparisonOperator: "GreaterThanOrEqualToThreshold"
      AlarmActions:
        - Ref: "SnsTopic1"
      TreatMissingData: "notBreaching"
  MetricFilter1:
    Type: "AWS::Logs::MetricFilter"
    Properties:
      LogGroupName:
        Ref: "CWLogGroupForCloudTrail"
      FilterPattern: "{ ($.eventName = CreateCustomerGateway) || ($.eventName = DeleteCustomerGateway) || ($.eventName = AttachInternetGateway) || ($.eventName = CreateInternetGateway) || ($.eventName = DeleteInternetGateway) || ($.eventName = DetachInternetGateway) }"
      MetricTransformations:
        - MetricValue: "1"
          MetricNamespace: "CloudTrailMetrics"
          MetricName: "GatewayEventCount"
  CwAlarm2:
    Type: "AWS::CloudWatch::Alarm"
    Properties:
      AlarmName: "vpc_changes"
      AlarmDescription: "A CloudWatch Alarm that triggers when changes are made to a VPC."
      MetricName: "VpcEventCount"
      Namespace: "CloudTrailMetrics"
      Statistic: "Sum"
      Period: "300"
      EvaluationPeriods: "1"
      Threshold: "1"
      ComparisonOperator: "GreaterThanOrEqualToThreshold"
      AlarmActions:
        - Ref: "SnsTopic1"
      TreatMissingData: "notBreaching"
  MetricFilter2:
    Type: "AWS::Logs::MetricFilter"
    Properties:
      LogGroupName:
        Ref: "CWLogGroupForCloudTrail"
      FilterPattern: "{ ($.eventName = CreateVpc) || ($.eventName = DeleteVpc) || ($.eventName = ModifyVpcAttribute) || ($.eventName = AcceptVpcPeeringConnection) || ($.eventName = CreateVpcPeeringConnection) || ($.eventName = DeleteVpcPeeringConnection) || ($.eventName = RejectVpcPeeringConnection) || ($.eventName = AttachClassicLinkVpc) || ($.eventName = DetachClassicLinkVpc) || ($.eventName = DisableVpcClassicLink) || ($.eventName = EnableVpcClassicLink) }"
      MetricTransformations:
        - MetricValue: "1"
          MetricNamespace: "CloudTrailMetrics"
          MetricName: "VpcEventCount"
  CwAlarm3:
    Type: "AWS::CloudWatch::Alarm"
    Properties:
      AlarmName: "securitygroup_changes"
      AlarmDescription: "A CloudWatch Alarm that triggers when changes are made to Security Groups."
      MetricName: "SecurityGroupEventCount"
      Namespace: "CloudTrailMetrics"
      Statistic: "Sum"
      Period: "300"
      EvaluationPeriods: "1"
      Threshold: "1"
      ComparisonOperator: "GreaterThanOrEqualToThreshold"
      AlarmActions:
        - Ref: "SnsTopic1"
      TreatMissingData: "notBreaching"
  MetricFilter3:
    Type: "AWS::Logs::MetricFilter"
    Properties:
      LogGroupName:
        Ref: "CWLogGroupForCloudTrail"
      FilterPattern: "{ ($.eventName = AuthorizeSecurityGroupIngress) || ($.eventName = AuthorizeSecurityGroupEgress) || ($.eventName = RevokeSecurityGroupIngress) || ($.eventName = RevokeSecurityGroupEgress) || ($.eventName = CreateSecurityGroup) || ($.eventName = DeleteSecurityGroup) }"
      MetricTransformations:
        - MetricValue: "1"
          MetricNamespace: "CloudTrailMetrics"
          MetricName: "SecurityGroupEventCount"
  CwAlarm4:
    Type: "AWS::CloudWatch::Alarm"
    Properties:
      AlarmName: "nacl_changes"
      AlarmDescription: "A CloudWatch Alarm that triggers when changes are made to Network ACLs."
      MetricName: "NetworkAclEventCount"
      Namespace: "CloudTrailMetrics"
      Statistic: "Sum"
      Period: "300"
      EvaluationPeriods: "1"
      Threshold: "1"
      ComparisonOperator: "GreaterThanOrEqualToThreshold"
      AlarmActions:
        - Ref: "SnsTopic1"
      TreatMissingData: "notBreaching"
  MetricFilter4:
    Type: "AWS::Logs::MetricFilter"
    Properties:
      LogGroupName:
        Ref: "CWLogGroupForCloudTrail"
      FilterPattern: "{ ($.eventName = CreateNetworkAcl) || ($.eventName = CreateNetworkAclEntry) || ($.eventName = DeleteNetworkAcl) || ($.eventName = DeleteNetworkAclEntry) || ($.eventName = ReplaceNetworkAclEntry) || ($.eventName = ReplaceNetworkAclAssociation) }"
      MetricTransformations:
        - MetricValue: "1"
          MetricNamespace: "CloudTrailMetrics"
          MetricName: "NetworkAclEventCount"
Parameters: {}
Metadata: {}
Conditions: {}

Actions



Customize Template

Configuration Presets

Resource Settings

EDIT
EDIT
EDIT
EDIT
EDIT
EDIT
EDIT
EDIT
EDIT
EDIT
EDIT
EDIT
EDIT
EDIT
EDIT
EDIT
EDIT