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 KMSIAM PoliciesAmazon ECRRDS Event Subscriptions

By Service Protected

Configuration Packages

Strategy Guides

Other

Config Rules

No EC2 Instances in Public Subnets Check

A Config rule that checks that no EC2 Instances are in Public Subnet.

Items
4
Size
7.7 KB
AWSTemplateFormatVersion: "2010-09-09"
Description: ""
Resources:
  CustomConfigRule:
    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:
            - "LambdaFunctionCustomConfigRule"
            - "Arn"
        SourceDetails:
          - EventSource: "aws.config"
            MessageType: "ConfigurationItemChangeNotification"
          - EventSource: "aws.config"
            MessageType: "OversizedConfigurationItemChangeNotification"
    DependsOn: "LambdaInvokePermissionsCustomConfigRule"
  LambdaInvokePermissionsCustomConfigRule:
    Type: "AWS::Lambda::Permission"
    Properties:
      FunctionName:
        Fn::GetAtt:
          - "LambdaFunctionCustomConfigRule"
          - "Arn"
      Action: "lambda:InvokeFunction"
      Principal: "config.amazonaws.com"
  LambdaFunctionCustomConfigRule:
    Type: "AWS::Lambda::Function"
    Properties:
      FunctionName: "LambdaForec2_vpc_public_subnet"
      Handler: "index.lambda_handler"
      Role:
        Fn::GetAtt:
          - "LambdaIamRoleCustomConfigRule"
          - "Arn"
      Runtime: "python3.6"
      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: "LambdaIamRoleCustomConfigRule"
  LambdaIamRoleCustomConfigRule:
    Type: "AWS::IAM::Role"
    Properties:
      RoleName: "IAMRoleForec2_vpc_public_subnetPSa"
      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"
      Policies: []
Parameters: {}
Metadata: {}
Conditions: {}

Actions



Customize Template

Rule Settings


Rule Parameters

No rule paramters

Trigger Settings

* Required field