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

 
Items
4
Size
6.7 KB
AWSTemplateFormatVersion: '2010-09-09'
Resources:
  CustomConfigRule:
    Type: 'AWS::Config::ConfigRule'
    Properties:
      ConfigRuleName: rds_vpc_public_subnet
      Description: A Config rule that checks that no RDS Instances are in Public Subnet.
      InputParameters: {}
      Scope:
        ComplianceResourceTypes:
          - 'AWS::RDS::DBInstance'
      Source:
        Owner: CUSTOM_LAMBDA
        SourceIdentifier:
          'Fn::GetAtt':
            - LambdaFunction
            - Arn
        SourceDetails:
          - EventSource: aws.config
            MessageType: ConfigurationItemChangeNotification
          - EventSource: aws.config
            MessageType: OversizedConfigurationItemChangeNotification
    DependsOn: LambdaInvokePermissions
  LambdaInvokePermissions:
    Type: 'AWS::Lambda::Permission'
    Properties:
      FunctionName:
        'Fn::GetAtt':
          - LambdaFunction
          - Arn
      Action: 'lambda:InvokeFunction'
      Principal: config.amazonaws.com
  LambdaFunction:
    Type: 'AWS::Lambda::Function'
    Properties:
      FunctionName: LambdaForrds_vpc_public_subnet
      Handler: index.lambda_handler
      Role:
        'Fn::GetAtt':
          - LambdaIamRole
          - Arn
      Runtime: python3.6
      Code:
        ZipFile:
          'Fn::Join':
            - |+

            - - ''
              - '#'
              - >-
                # This file made available under CC0 1.0 Universal
                (https://creativecommons.org/publicdomain/zero/1.0/legalcode)
              - '#'
              - '# Description: Check that no RDS Instances are in Public Subnet'
              - '#'
              - '# Trigger Type: Change Triggered'
              - '# Scope of Changes: RDS:DBInstance'
              - '# Accepted Parameters: None'
              - ''
              - ''
              - import boto3
              - import botocore
              - import json
              - import logging
              - ''
              - log = logging.getLogger()
              - log.setLevel(logging.INFO)
              - ''
              - 'def evaluate_compliance(configuration_item):'
              - '    vpc_id      = configuration_item["configuration"][''dBSubnetGroup'']["vpcId"]'
              - '    subnet_ids   = []'
              - '    for i in configuration_item["configuration"][''dBSubnetGroup''][''subnets'']:'
              - '        subnet_ids.append(i[''subnetIdentifier''])'
              - '    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'
              - ''
              - '    for subnet_id in subnet_ids:'
              - '        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: LambdaIamRole
  LambdaIamRole:
    Type: 'AWS::IAM::Role'
    Properties:
      RoleName: IAMRoleForrds_vpc_public_subnet
      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: {}

Customize Cf Template

Rule Parameters

No rule paramters
 
* Required field
Additional Attributes
Lambda Code (Python)