Description
Listing users in the Users property of AWS::IAM::Policy attaches an inline policy to those users. Maintaining shared job permissions through individual attachments makes changes and revocation easier to miss.
Potential impact
Unnecessary permissions can remain on individual users after their responsibilities change. Moving a policy to a group does not automatically narrow its allowed actions or resources.
Remediation
Attach shared permissions through Groups and manage approved membership. Prefer roles with the required permissions for workloads. Verify replacement access before removing direct attachments, and review exceptions regularly.
Examples
The TestUser declaration is omitted, and user_group names an existing group. Replace the object ARN with the intended scope. Group membership must be managed separately.
Before
Resources:
BadPolicy:
Type: AWS::IAM::Policy
Properties:
PolicyName: example-access
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action: s3:GetObject
Resource: arn:aws:s3:::example-bucket/*
Users:
- Ref: TestUser
Object-read permission is attached directly to the user.
After
Resources:
BadPolicy:
Type: AWS::IAM::Policy
Properties:
PolicyName: example-access
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action: s3:GetObject
Resource: arn:aws:s3:::example-bucket/*
Groups:
- user_group
The same permission is attached to the group. The policy’s actions and resource scope remain unchanged.