A config rule that evaluates whether access logging is enabled on the CloudTrail S3 bucket and the S3 bucket is not publicly accessible.

 
Items
4
Size
5.6 KB
AWSTemplateFormatVersion: '2010-09-09'
Resources:
  CustomConfigRule:
    Type: 'AWS::Config::ConfigRule'
    Properties:
      ConfigRuleName: cloudtrail_s3_access_logging
      Description: >-
        A config rule that evaluates whether access logging is enabled on the
        CloudTrail S3 bucket and the S3 bucket is not publicly accessible.
      InputParameters: {}
      Scope:
        ComplianceResourceTypes:
          - 'AWS::CloudTrail::Trail'
      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: LambdaForcloudtrail_s3_access_logging
      Handler: index.lambda_handler
      Role:
        'Fn::GetAtt':
          - LambdaIamRole
          - Arn
      Runtime: python2.7
      Code:
        ZipFile:
          'Fn::Join':
            - |+

            - - ''
              - import json
              - import boto3
              - import datetime
              - import time
              - from botocore.exceptions import ClientError
              - 'def lambda_handler(event, context):'
              - '  # get the trail for the current region'
              - '  client_ct = boto3.client(''cloudtrail'')'
              - '  for trail in client_ct.describe_trails(includeShadowTrails = False)[''trailList'']:'
              - '    annotation = '''''
              - '    is_publicly_accessible = False'
              - '    s3_bucket_name = '''''
              - '    is_compliant = True'
              - '    # check if the cloudtrail s3 bucket is publicly accessible and logged'
              - '    if trail[''S3BucketName'']:'
              - '      s3_bucket_name = trail[''S3BucketName'']'
              - '      client_s=boto3.client(''s3'')'
              - '      try:'
              - '        for grant in client_s.get_bucket_acl(Bucket = s3_bucket_name)[''Grants'']:'
              - '          # verify cloudtrail s3 bucket ACL'
              - '          if grant[''Permission''] in [''READ'',''FULL_CONTROL''] and (''URI'' in grant[''Grantee''] and (''AuthenticatedUsers'' in grant[''Grantee''][''URI''] or ''AllUsers'' in grant[''Grantee''][''URI''])):'
              - '            is_publicly_accessible = True'
              - '        if is_publicly_accessible:'
              - '          is_compliant = False'
              - '          annotation = annotation + '' The CloudTrail S3 bucket ''{}'' is publicly accessible.''.format(s3_bucket_name)'
              - '        # verify cloudtrail s3 bucket logging'
              - '        response = client_s.get_bucket_logging(Bucket = s3_bucket_name)'
              - '        if ''LoggingEnabled'' not in response:'
              - '          is_compliant=False'
              - '          annotation = annotation + '' The CloudTrail S3 bucket ''{}'' does not have logging enabled.''.format(s3_bucket_name)'
              - '      except Exception as ex:'
              - '        print ex'
              - '        is_compliant = False'
              - '        annotation = annotation + '' There was an error looking up CloudTrail S3 bucket ''{}''.''.format(s3_bucket_name)'
              - '    else:'
              - '      annotation = annotation + '' CloudTrail is not integrated with S3.'''
              - '    result_token = ''No token found.'''
              - '    if ''resultToken'' in event: result_token = event[''resultToken'']'
              - '    evaluations = ['
              - '      {'
              - '        ''ComplianceResourceType'': ''AWS::S3::Bucket'','
              - '        ''ComplianceResourceId'': s3_bucket_name,'
              - '        ''ComplianceType'': ''COMPLIANT'' if is_compliant else ''NON_COMPLIANT'','
              - '        ''OrderingTimestamp'': datetime.datetime.now()'
              - '      }'
              - '    ]'
              - '    if is_compliant: annotation = ''Acces logging is enabled on the CloudTrail S3 bucket ''{}'' and the S3 bucket is not publicly accessible''.format(s3_bucket_name)'
              - '    if annotation: evaluations[0][''Annotation''] = annotation'
              - '    config = boto3.client(''config'')'
              - '    config.put_evaluations('
              - '      Evaluations = evaluations,'
              - '      ResultToken = result_token'
              - '    )'
              - ''
      Timeout: 300
    DependsOn: LambdaIamRole
  LambdaIamRole:
    Type: 'AWS::IAM::Role'
    Properties:
      RoleName: IAMRoleForcloudtrail_s3_access_logging
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - lambda.amazonaws.com
            Action:
              - 'sts:AssumeRole'
      ManagedPolicyArns:
        - 'arn:aws:iam::aws:policy/AWSCloudTrailReadOnlyAccess'
        - 'arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess'
        - '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)