A Config rule that ensures that IAM policies are attached only to groups or roles.
AWSTemplateFormatVersion: '2010-09-09'
Description: ''
Resources:
CustomConfigRule:
Type: 'AWS::Config::ConfigRule'
Properties:
ConfigRuleName: iam_users_no_policies_attached
Description: >-
A Config rule that ensures that IAM policies are attached only to groups
or roles.
Scope:
ComplianceResourceTypes:
- 'AWS::IAM::User'
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: LambdaForiam_users_no_policies_attached
Handler: index.lambda_handler
Role:
'Fn::GetAtt':
- LambdaIamRole
- Arn
Runtime: python2.7
Code:
ZipFile:
'Fn::Join':
- |+
- - >-
#==================================================================================================
- '# Function: EvaluateUserPolicyAssociations'
- >-
# Purpose: Evaluates whether users have policies associated
with them. Users should inherit permissions from groups instead.
- >-
#==================================================================================================
- import json
- import boto3
- 'APPLICABLE_RESOURCES = [''AWS::IAM::User'']'
- annotation = ''
- 'def evaluate_compliance(configuration_item):'
- ' global annotation'
- ' annotation='''''
- ' if configuration_item[''resourceType''] not in APPLICABLE_RESOURCES:'
- ' return ''NOT_APPLICABLE'''
- ' user_name = configuration_item[''resourceName'']'
- ' iam = boto3.client(''iam'')'
- ' # lists all user inline attached policies'
- ' if iam.list_user_policies(UserName=user_name)[''PolicyNames'']:'
- ' annotation = annotation + ''The user has inline policies attached! '''
- ' return ''NON_COMPLIANT'''
- ' # lists all user managed attached policies'
- ' elif iam.list_attached_user_policies(UserName=user_name)[''AttachedPolicies'']:'
- ' annotation=annotation + ''The user has managed policies attached! '''
- ' return ''NON_COMPLIANT'''
- ' else:'
- ' annotation=annotation + ''The user does not have inline or managed policies attached! '''
- ' return ''COMPLIANT'''
- 'def lambda_handler(event, context):'
- ' invoking_event = json.loads(event[''invokingEvent''])'
- ' configuration_item = invoking_event[''configurationItem'']'
- ' result_token = ''No token found.'''
- ' if ''resultToken'' in event: result_token = event[''resultToken'']'
- ' config = boto3.client(''config'')'
- ' config.put_evaluations('
- ' Evaluations=['
- ' {'
- ' ''ComplianceResourceType'': configuration_item[''resourceType''],'
- ' ''ComplianceResourceId'': configuration_item[''resourceId''],'
- ' ''ComplianceType'': evaluate_compliance(configuration_item),'
- ' ''Annotation'': annotation,'
- ' ''OrderingTimestamp'': configuration_item[''configurationItemCaptureTime'']'
- ' },'
- ' ],'
- ' ResultToken=result_token'
- ' )'
- ''
Timeout: 300
DependsOn: LambdaIamRole
LambdaIamRole:
Type: 'AWS::IAM::Role'
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
Action:
- 'sts:AssumeRole'
ManagedPolicyArns:
- 'arn:aws:iam::aws:policy/IAMReadOnlyAccess'
- 'arn:aws:iam::aws:policy/service-role/AWSConfigRulesExecutionRole'
- 'arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole'
Policies: []
RoleName: IAMRoleForiam_users_no_policies_attachedEzz
Parameters: {}
Metadata: {}
Conditions: {}
Configuration Source: AWS Quickstart
Additional Documentation: