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

Config Rules

No EC2 Instances in Public Subnets Check

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

Try out CloudAdvisor: Your AI-Powered Assistant for AWS Cloud

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.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: "LambdaIamRoleCustomConfigRule"
  LambdaIamRoleCustomConfigRule:
    Type: "AWS::IAM::Role"
    Properties:
      RoleName: "IAMRoleForec2_vpc_public_subnetNyF"
      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"
Parameters: {}
Metadata: {}
Conditions: {}

Actions



Customize Template

Rule Settings


Rule Parameters

No rule parameters

Trigger Settings

* Required field

Upgrade to Premium for More Features
Sign up

Guided Walkthroughs
Step-by-step configuration wizards for your environment
Dedicated Security Account
AWS Backup Strategy
VPC Connectivity Setup
Automated Patching
All Guides
Configuration Packages
Pre-built packages for common configuration
Common SCPs
CloudFormation Guard Rules
Auto Remediation Rules
IAM Monitoring & Compliance
All Packages
Automated Assessments
  • 350+ security checks
  • Well-architected reviews
  • Detailed compliance reports
  • Remediation templates
  • Email summaries
  • Learn more