aws-cloudformation-iam
69
总安装量
69
周安装量
#3182
全站排名
安装命令
npx skills add https://github.com/giuseppe-trisciuoglio/developer-kit --skill aws-cloudformation-iam
Agent 安装分布
claude-code
52
cursor
47
replit
45
opencode
42
codex
41
Skill 文档
AWS CloudFormation IAM Security
Create production-ready IAM infrastructure using AWS CloudFormation templates. This skill covers users, roles, policies, managed policies, permission boundaries, and best practices for implementing least privilege access.
When to Use
Use this skill when:
- Creating new IAM users with CloudFormation
- Configuring IAM roles for AWS services
- Defining inline policies and managed policies
- Implementing cross-account access with STS
- Creating permission boundaries
- Organizing templates with Parameters, Outputs, Mappings, Conditions
- Implementing cross-stack references for IAM resources
- Configuring IAM Identity Center (SSO)
- Managing service control policies (SCP)
CloudFormation Template Structure
Standard Format Base Template
AWSTemplateFormatVersion: 2010-09-09
Description: IAM infrastructure with users, roles, and policies
Metadata:
AWS::CloudFormation::Interface:
ParameterGroups:
- Label:
default: User Configuration
Parameters:
- UserName
- UserPermissionsBoundary
- Label:
default: Role Configuration
Parameters:
- RoleName
- AssumeRolePolicyService
Parameters:
UserName:
Type: String
Default: app-user
Description: Name of the IAM user
MinLength: 1
MaxLength: 64
UserPermissionsBoundary:
Type: String
Description: IAM policy ARN for permissions boundary
Default: ""
RoleName:
Type: String
Default: app-execution-role
Description: Name of the IAM role
AssumeRolePolicyService:
Type: String
Default: lambda.amazonaws.com
Description: Service that can assume the role
AllowedValues:
- lambda.amazonaws.com
- ec2.amazonaws.com
- ecs-tasks.amazonaws.com
- eks.amazonaws.com
- states.amazonaws.com
Mappings:
EnvironmentConfig:
dev:
MaxSessionDuration: 3600
PolicyArns: []
staging:
MaxSessionDuration: 7200
PolicyArns:
- arn:aws:iam::aws:policy/ReadOnlyAccess
production:
MaxSessionDuration: 43200
PolicyArns:
- arn:aws:iam::aws:policy/ReadOnlyAccess
- arn:aws:iam::aws:policy/SecurityAudit
Conditions:
HasPermissionsBoundary: !Not [!Equals [!Ref UserPermissionsBoundary, ""]]
IsProduction: !Equals [!Ref Environment, production]
Transform:
- AWS::Serverless-2016-10-31
Resources:
# IAM User
AppUser:
Type: AWS::IAM::User
Properties:
UserName: !Ref UserName
PermissionsBoundary: !If
- HasPermissionsBoundary
- !Ref UserPermissionsBoundary
- !Ref AWS::NoValue
Tags:
- Key: Environment
Value: !Ref Environment
- Key: Project
Value: !Ref ProjectName
Outputs:
UserArn:
Description: ARN of the IAM user
Value: !GetAtt AppUser.Arn
Export:
Name: !Sub "${AWS::StackName}-UserArn"
Parameters Best Practices
AWS-Specific Parameter Types
Parameters:
# AWS-specific types for validation
UserArn:
Type: AWS::IAM::User::Arn
Description: IAM user ARN for reference
RoleArn:
Type: AWS::IAM::Role::Arn
Description: IAM role ARN for reference
PolicyArn:
Type: AWS::IAM::Policy::Arn
Description: IAM policy ARN
ManagedPolicyArn:
Type: AWS::IAM::ManagedPolicy::Arn
Description: AWS managed policy ARN
InstanceProfileArn:
Type: AWS::IAM::InstanceProfile::Arn
Description: IAM instance profile ARN
S3BucketPolicy:
Type: AWS::S3::BucketPolicy::Resource
Description: S3 bucket policy reference
Parameter Constraints
Parameters:
UserName:
Type: String
Default: app-user
Description: IAM username
MinLength: 1
MaxLength: 64
ConstraintDescription: Must be 1-64 characters
AllowedPattern: "[a-zA-Z0-9+=,.@_-]+"
RoleName:
Type: String
Default: execution-role
Description: IAM role name
MinLength: 1
MaxLength: 64
ConstraintDescription: Must be 1-64 characters
AllowedPattern: "[a-zA-Z0-9+=,.@_-]+"
MaxSessionDuration:
Type: Number
Default: 3600
Description: Maximum session duration in seconds
MinValue: 900
MaxValue: 43200
ConstraintDescription: Must be between 900 and 43200 seconds
AccessKeyRotationFrequency:
Type: Number
Default: 90
Description: Days between access key rotations
MinValue: 1
MaxValue: 365
ConstraintDescription: Must be between 1 and 365 days
SSM Parameter References per Policy ARNs
Parameters:
ReadOnlyPolicyArn:
Type: AWS::SSM::Parameter::Value<String>
Default: /iam/policies/read-only-arn
Description: ARN of the read-only policy from SSM
CustomPolicyDocument:
Type: AWS::SSM::Parameter::Value<String>
Default: /iam/policies/custom-policy-json
Description: Policy document from SSM Parameter Store
Outputs and Cross-Stack References
Export/Import Patterns for IAM
# Stack A - IAM Core Stack
AWSTemplateFormatVersion: 2010-09-09
Description: Core IAM infrastructure stack
Resources:
# Execution Role for applications
ApplicationExecutionRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub "${AWS::StackName}-execution-role"
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
Service: lambda.amazonaws.com
Action: sts:AssumeRole
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
MaxSessionDuration: 3600
# Role for Cross-Account Access
CrossAccountReadRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub "${AWS::StackName}-crossaccount-read"
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
AWS: !Sub "arn:aws:iam::${TargetAccountId}:root"
Action: sts:AssumeRole
Condition:
StringEquals:
sts:Externalid: !Ref ExternalId
Policies:
- PolicyName: ReadOnlyAccess
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- s3:GetObject
- s3:GetObjectVersion
Resource: !Ref SourceBucketArn
- Effect: Allow
Action:
- dynamodb:Query
- dynamodb:Scan
- dynamodb:GetItem
Resource: !Ref SourceTableArn
Outputs:
ApplicationExecutionRoleArn:
Description: ARN of the application execution role
Value: !GetAtt ApplicationExecutionRole.Arn
Export:
Name: !Sub "${AWS::StackName}-ExecutionRoleArn"
CrossAccountReadRoleArn:
Description: ARN for cross-account read access
Value: !GetAtt CrossAccountReadRole.Arn
Export:
Name: !Sub "${AWS::StackName}-CrossAccountReadRoleArn"
CrossAccountReadRoleExternalId:
Description: External ID for cross-account role assumption
Value: !Ref ExternalId
Export:
Name: !Sub "${AWS::StackName}-CrossAccountExternalId"
# Stack B - Application Stack (imports from IAM Stack)
AWSTemplateFormatVersion: 2010-09-09
Description: Application stack importing IAM roles
Parameters:
IAMStackName:
Type: String
Default: iam-core
Description: Name of the IAM stack
Resources:
LambdaFunction:
Type: AWS::Lambda::Function
Properties:
FunctionName: !Sub "${AWS::StackName}-processor"
Runtime: python3.11
Handler: app.handler
Code:
S3Bucket: !Ref CodeBucket
S3Key: lambda/function.zip
Role: !ImportValue
!Sub "${IAMStackName}-ExecutionRoleArn"
Environment:
Variables:
TARGET_BUCKET: !Ref TargetBucket
Nested Stacks for IAM Modularity
AWSTemplateFormatVersion: 2010-09-09
Description: Main stack with nested IAM stacks
Resources:
# Nested stack for users
IAMUsersStack:
Type: AWS::CloudFormation::Stack
Properties:
TemplateURL: https://s3.amazonaws.com/bucket/iam-users.yaml
TimeoutInMinutes: 15
Parameters:
Environment: !Ref Environment
UserNames: !Ref UserNames
# Nested stack for roles
IAMRolesStack:
Type: AWS::CloudFormation::Stack
Properties:
TemplateURL: https://s3.amazonaws.com/bucket/iam-roles.yaml
TimeoutInMinutes: 15
Parameters:
Environment: !Ref Environment
TrustedServices: !Ref TrustedServices
# Nested stack for policies
IAMPoliciesStack:
Type: AWS::CloudFormation::Stack
Properties:
TemplateURL: https://s3.amazonaws.com/bucket/iam-policies.yaml
TimeoutInMinutes: 15
Parameters:
Environment: !Ref Environment
IAM Users
User with Access Keys
AWSTemplateFormatVersion: 2010-09-09
Description: IAM user with programmatic access
Resources:
AppUser:
Type: AWS::IAM::User
Properties:
UserName: !Sub "${AWS::StackName}-app-user"
Tags:
- Key: Environment
Value: !Ref Environment
- Key: Project
Value: !Ref ProjectName
UserAccessKey:
Type: AWS::IAM::AccessKey
Properties:
UserName: !Ref AppUser
Status: Active
Serial: 1
UserSecret:
Type: AWS::SecretsManager::Secret
Properties:
Name: !Sub "${AWS::StackName}/iam-user-credentials"
Description: IAM user access key credentials
SecretString: !Sub |
{
"username": "${AppUser.UserName}",
"access_key": "${UserAccessKey.Ref}",
"secret_key": "{{resolve:secretsmanager:${UserAccessKey.SecretAccessKey}}}"
}
Outputs:
AccessKeyId:
Description: Access Key ID for the user
Value: !Ref UserAccessKey
Export:
Name: !Sub "${AWS::StackName}-AccessKeyId"
SecretArn:
Description: ARN of the secret containing credentials
Value: !Ref UserSecret
User with Console Password
Resources:
ConsoleUser:
Type: AWS::IAM::User
Properties:
UserName: !Sub "${AWS::StackName}-console-user"
UserLoginProfile:
Type: AWS::IAM::UserLoginProfile
Properties:
UserName: !Ref ConsoleUser
Password: !Ref InitialPassword
PasswordResetRequired: true
UserPasswordSecret:
Type: AWS::SecretsManager::Secret
Properties:
Name: !Sub "${AWS::StackName}/console-password"
Description: Initial console login password
SecretString: !Ref InitialPassword
User with Permissions Boundary
AWSTemplateFormatVersion: 2010-09-09
Description: IAM user with permissions boundary
Resources:
# Permissions boundary policy
ReadOnlyBoundaryPolicy:
Type: AWS::IAM::ManagedPolicy
Properties:
Description: Read-only permissions boundary
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Deny
Action: "*"
Resource: "*"
NotPrincipal:
- !GetAtt ReadOnlyRole.Arn
AppUser:
Type: AWS::IAM::User
Properties:
UserName: !Sub "${AWS::StackName}-restricted-user"
PermissionsBoundary: !Ref ReadOnlyBoundaryPolicy
ManagedPolicyArns:
- arn:aws:iam::aws:policy/ReadOnlyAccess
IAM Roles
Role for Lambda Execution
AWSTemplateFormatVersion: 2010-09-09
Description: Lambda execution role with least privilege
Resources:
LambdaExecutionRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub "${AWS::StackName}-lambda-execution"
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
Service: lambda.amazonaws.com
Action: sts:AssumeRole
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
- arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole
Policies:
- PolicyName: !Sub "${AWS::StackName}-dynamodb-policy"
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- dynamodb:Query
- dynamodb:Scan
- dynamodb:GetItem
- dynamodb:PutItem
- dynamodb:UpdateItem
- dynamodb:DeleteItem
Resource: !GetAtt DataTable.Arn
Condition:
StringEquals:
dynamodb:TableName: !Ref TableName
- Effect: Allow
Action:
- dynamodb:DescribeTable
Resource: "*"
- PolicyName: !Sub "${AWS::StackName}-secrets-policy"
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- secretsmanager:GetSecretValue
- secretsmanager:DescribeSecret
Resource: !Ref SecretsArn
- PolicyName: !Sub "${AWS::StackName}-kms-policy"
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- kms:Decrypt
- kms:DescribeKey
Resource: !Ref KmsKeyArn
DataTable:
Type: AWS::DynamoDB::Table
Properties:
TableName: !Ref TableName
BillingMode: PAY_PER_REQUEST
AttributeDefinitions:
- AttributeName: pk
AttributeType: S
- AttributeName: sk
AttributeType: S
KeySchema:
- AttributeName: pk
KeyType: HASH
- AttributeName: sk
KeyType: RANGE
Role for ECS Tasks
AWSTemplateFormatVersion: 2010-09-09
Description: ECS task execution role
Resources:
ECSTaskExecutionRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub "${AWS::StackName}-ecs-task-execution"
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
Service: ecs-tasks.amazonaws.com
Action: sts:AssumeRole
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy
Policies:
- PolicyName: !Sub "${AWS::StackName}-ecr-policy"
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- ecr:GetDownloadUrlForLayer
- ecr:BatchGetImage
- ecr:BatchCheckLayerAvailability
Resource: !Ref EcrRepositoryArn
- Effect: Allow
Action:
- ecr:GetAuthorizationToken
Resource: "*"
- PolicyName: !Sub "${AWS::StackName}-cloudwatch-logs"
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- logs:CreateLogStream
- logs:PutLogEvents
- logs:CreateLogGroup
Resource: !Ref LogGroupArn
ECSTaskRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub "${AWS::StackName}-ecs-task"
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
Service: ecs-tasks.amazonaws.com
Action: sts:AssumeRole
Policies:
- PolicyName: !Sub "${AWS::StackName}-app-policy"
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- sqs:ReceiveMessage
- sqs:DeleteMessage
- sqs:GetQueueAttributes
Resource: !GetAtt Queue.Arn
- Effect: Allow
Action:
- sns:Publish
Resource: !Ref TopicArn
Role for Cross-Account Access
AWSTemplateFormatVersion: 2010-09-09
Description: Cross-account access role
Parameters:
SourceAccountId:
Type: String
Description: AWS account ID that can assume this role
ExternalId:
Type: String
Description: External ID for trust relationship
Resources:
CrossAccountReadRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub "${AWS::StackName}-crossaccount-read"
Description: Role for cross-account read access
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
AWS: !Sub "arn:aws:iam::${SourceAccountId}:root"
Action: sts:AssumeRole
Condition:
StringEquals:
sts:Externalid: !Ref ExternalId
IpAddress:
aws:SourceIp:
- 10.0.0.0/8
- 172.16.0.0/12
MaxSessionDuration: 7200
Policies:
- PolicyName: !Sub "${AWS::StackName}-s3-read"
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- s3:GetObject
- s3:GetObjectVersion
- s3:ListBucket
Resource:
- !Ref SourceBucketArn
- !Sub "${SourceBucketArn}/*"
- PolicyName: !Sub "${AWS::StackName}-dynamodb-read"
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- dynamodb:Query
- dynamodb:Scan
- dynamodb:GetItem
- dynamodb:DescribeTable
Resource:
- !GetAtt SourceTable.Arn
- !Sub "${GetAtt SourceTable.Arn}/index/*"
Outputs:
RoleArn:
Description: ARN of the cross-account role
Value: !GetAtt CrossAccountReadRole.Arn
Export:
Name: !Sub "${AWS::StackName}-CrossAccountRoleArn"
Role for API Gateway with Cognito
AWSTemplateFormatVersion: 2010-09-09
Description: API Gateway execution role for Cognito authorization
Resources:
ApiGatewayCognitoAuthorizerRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub "${AWS::StackName}-apigw-cognito-role"
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
Service: apigateway.amazonaws.com
Action: sts:AssumeRole
Policies:
- PolicyName: !Sub "${AWS::StackName}-cognito-policy"
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- cognito-idp:DescribeUserPool
- cognito-idp:DescribeUserPoolClient
Resource: !Ref UserPoolArn
ApiGatewayExecutionRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub "${AWS::StackName}-apigw-execution"
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
Service: apigateway.amazonaws.com
Action: sts:AssumeRole
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AmazonAPIGatewayPushToCloudWatchLogs
Policies:
- PolicyName: !Sub "${AWS::StackName}-lambda-invoke"
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- lambda:InvokeFunction
Resource: !Ref LambdaFunctionArn
Role for EKS Pods
AWSTemplateFormatVersion: 2010-09-09
Description: IAM role for EKS pod execution
Resources:
EKSPodRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub "${AWS::StackName}-eks-pod-role"
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
Service: eks.amazonaws.com
Action: sts:AssumeRole
Condition:
StringEquals:
aws:SourceArn: !Sub "arn:aws:eks:${AWS::Region}:${AWS::AccountId}:cluster/${EKSClusterName}"
ManagedPolicyArns:
- arn:aws:iam::aws:policy/SecretsManagerReadWrite
Policies:
- PolicyName: !Sub "${AWS::StackName}-s3-read"
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- s3:GetObject
- s3:GetObjectVersion
Resource: !Sub "${DataBucketArn}/*"
EKSPodExecutionRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub "${AWS::StackName}-eks-execution"
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
Service: eks.amazonaws.com
Action: sts:AssumeRole
ManagedPolicyArns:
- arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy
- arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy
- arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly
- arn:aws:iam::aws:policy/CloudWatchLogsReadOnly
Role for CodeBuild
AWSTemplateFormatVersion: 2010-09-09
Description: IAM role for CodeBuild project
Resources:
CodeBuildRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub "${AWS::StackName}-codebuild-role"
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
Service: codebuild.amazonaws.com
Action: sts:AssumeRole
ManagedPolicyArns:
- arn:aws:iam::aws:policy/CloudWatchLogsFullAccess
- arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryFullAccess
Policies:
- PolicyName: !Sub "${AWS::StackName}-source-access"
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- s3:GetObject
- s3:GetObjectVersion
Resource:
- !Ref SourceBucketArn
- !Sub "${SourceBucketArn}/*"
- Effect: Allow
Action:
- s3:PutObject
Resource:
- !Ref BuildOutputBucketArn
- !Sub "${BuildOutputBucketArn}/*"
- Effect: Allow
Action:
- codecommit:GitPull
Resource: !Ref CodecommitRepositoryArn
- Effect: Allow
Action:
- codebuild:CreateReportGroup
- codebuild:CreateReport
- codebuild:UpdateReport
- codebuild:BatchPutTestCases
- codebuild:BatchPutCodeCoverages
Resource: "*"
Role for Step Functions
AWSTemplateFormatVersion: 2010-09-09
Description: IAM role for Step Functions state machine
Resources:
StepFunctionsExecutionRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub "${AWS::StackName}-stepfunctions-role"
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
Service: states.amazonaws.com
Action: sts:AssumeRole
Policies:
- PolicyName: !Sub "${AWS::StackName}-lambda-tasks"
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- lambda:InvokeFunction
- lambda:InvokeAsync
Resource:
- !Ref ProcessFunctionArn
- !Ref ValidateFunctionARN
- !Ref NotifyFunctionArn
- PolicyName: !Sub "${AWS::StackName}-dynamodb-tasks"
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- dynamodb:GetItem
- dynamodb:PutItem
- dynamodb:UpdateItem
- dynamodb:DeleteItem
- dynamodb:Query
- dynamodb:Scan
Resource:
- !GetAtt WorkflowTable.Arn
- !Sub "${GetAtt WorkflowTable.Arn}/*"
- PolicyName: !Sub "${AWS::StackName}-sns-tasks"
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- sns:Publish
Resource: !Ref NotificationTopicArn
- PolicyName: !Sub "${AWS::StackName}-events"
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- events:PutTargets
- events:PutRule
- events:DescribeRule
Resource: "*"
IAM Policies
Inline Policy for S3 Access
AWSTemplateFormatVersion: 2010-09-09
Description: Role with S3 access policies
Resources:
S3AccessRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub "${AWS::StackName}-s3-access"
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
Service: lambda.amazonaws.com
Action: sts:AssumeRole
Policies:
- PolicyName: !Sub "${AWS::StackName}-s3-readonly"
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- s3:GetObject
- s3:GetObjectVersion
- s3:GetBucketPolicy
- s3:GetBucketPolicyStatus
Resource:
- !Ref DataBucketArn
- !Sub "${DataBucketArn}/*"
- Effect: Allow
Action:
- s3:ListBucket
Resource: !Ref DataBucketArn
Condition:
StringLike:
s3:prefix:
- ""
- "documents/*"
- "reports/*"
- PolicyName: !Sub "${AWS::StackName}-s3-write"
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- s3:PutObject
- s3:PutObjectAcl
- s3:DeleteObject
Resource: !Sub "${DataBucketArn}/processed/*"
Custom Managed Policy
AWSTemplateFormatVersion: 2010-09-09
Description: Custom managed policy for DynamoDB access
Resources:
DynamoDBFullAccessPolicy:
Type: AWS::IAM::ManagedPolicy
Properties:
Description: Full access to specific DynamoDB tables
ManagedPolicyName: !Sub "${AWS::StackName}-dynamodb-full-access"
Groups:
- !Ref AppUserGroup
Roles:
- !Ref AppExecutionRole
Users:
- !Ref AppUser
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- dynamodb:CreateTable
- dynamodb:UpdateTable
- dynamodb:DeleteTable
- dynamodb:DescribeTable
- dynamodb:DescribeTimeToLive
- dynamodb:ListTagsOfResource
Resource: !GetAtt DataTable.Arn
- Effect: Allow
Action:
- dynamodb:Query
- dynamodb:Scan
- dynamodb:GetItem
- dynamodb:PutItem
- dynamodb:UpdateItem
- dynamodb:DeleteItem
- dynamodb:BatchGetItem
- dynamodb:BatchWriteItem
Resource:
- !GetAtt DataTable.Arn
- !Sub "${GetAtt DataTable.Arn}/index/*"
- Effect: Allow
Action:
- dynamodb:DescribeLimits
- dynamodb:ListTables
Resource: "*"
Policy with Conditions
AWSTemplateFormatVersion: 2010-09-09
Description: Policy with IP and time-based conditions
Resources:
RestrictedAccessRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub "${AWS::StackName}-restricted-access"
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
Service: ec2.amazonaws.com
Action: sts:AssumeRole
Policies:
- PolicyName: !Sub "${AWS::StackName}-conditional-access"
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- s3:GetObject
Resource: !Sub "${DataBucketArn}/*"
Condition:
IpAddress:
aws:SourceIp:
- 10.0.0.0/8
- 192.168.1.0/24
StringEquals:
s3:ExistingObjectTag/classification: internal
- Effect: Allow
Action:
- dynamodb:GetItem
- dynamodb:Query
Resource: !GetAtt DataTable.Arn
Condition:
StringEquals:
dynamodb:Select: SPECIFIC_ATTRIBUTES
dynamodb:Attributes:
- id
- name
- status
Permission Boundaries
Permission Boundary for Developers
AWSTemplateFormatVersion: 2010-09-09
Description: Permission boundary for developer roles
Resources:
DeveloperBoundaryPolicy:
Type: AWS::IAM::ManagedPolicy
Properties:
Description: Permission boundary for developers - denies production write access
ManagedPolicyName: !Sub "${AWS::StackName}-developer-boundary"
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Deny
Action:
- "*"
Resource: "*"
Condition:
StringEquals:
aws:RequestedRegion:
- us-east-1
- us-west-2
StringLike:
aws:ResourceTag/environment:
- production
- prod
- Effect: Deny
Action:
- iam:CreateUser
- iam:DeleteUser
- iam:PutUserPolicy
- iam:AttachUserPolicy
- iam:DetachUserPolicy
Resource: "*"
- Effect: Deny
Action:
- iam:CreateRole
- iam:DeleteRole
- iam:AttachRolePolicy
- iam:DetachRolePolicy
Resource: "*"
- Effect: Allow
Action:
- s3:Get*
- s3:List*
Resource: "*"
- Effect: Allow
Action:
- dynamodb:Get*
- dynamodb:Query
- dynamodb:Scan
Resource: "*"
- Effect: Allow
Action:
- lambda:InvokeFunction
- lambda:GetFunction
Resource: "*"
DeveloperRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub "${AWS::StackName}-developer"
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
AWS: !Ref DeveloperUserArn
Action: sts:AssumeRole
PermissionsBoundary: !Ref DeveloperBoundaryPolicy
ManagedPolicyArns:
- arn:aws:iam::aws:policy/ReadOnlyAccess
IAM Identity Center (SSO)
SSO Permission Set
AWSTemplateFormatVersion: 2010-09-09
Description: IAM Identity Center permission set
Resources:
SSOPermissionSet:
Type: AWS::SSO::PermissionSet
Properties:
InstanceArn: !Ref SSOInstanceArn
PermissionSetName: !Sub "${AWS::StackName}-admin-permissions"
Description: Administrator access permission set
SessionDuration: PT8H
RelayStateType: sso.amazonaws.com
ManagedPolicies:
- arn:aws:iam::aws:policy/AdministratorAccess
InlinePolicy: |
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"aws-portal:*Billing",
"aws-portal:*Usage"
],
"Resource": "*"
}
]
}
SSOAssignment:
Type: AWS::SSO::AccountAssignment
Properties:
InstanceArn: !Ref SSOInstanceArn
PermissionSetArn: !Ref SSOPermissionSet
PrincipalId: !Ref SSOGroupId
PrincipalType: GROUP
TargetId: !Ref TargetAWSAccountId
TargetType: AWS_ACCOUNT
SSO Custom Policy with Conditions
AWSTemplateFormatVersion: 2010-09-09
Description: SSO permission set with custom policies
Resources:
ReadOnlyPermissionSet:
Type: AWS::SSO::PermissionSet
Properties:
InstanceArn: !Ref SSOInstanceArn
PermissionSetName: !Sub "${AWS::StackName}-read-only"
Description: Read-only access for auditors
SessionDuration: PT4H
ManagedPolicies:
- arn:aws:iam::aws:policy/ReadOnlyAccess
InlinePolicy: |
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:GetObjectVersion",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::${DataBucketArn}",
"arn:aws:s3:::${DataBucketArn}/*"
]
},
{
"Effect": "Deny",
"Action": [
"s3:DeleteObject",
"s3:PutObject"
],
"Resource": [
"arn:aws:s3:::${DataBucketArn}/*"
]
}
]
}
Service Control Policies (SCP)
SCP for Organizational Units
AWSTemplateFormatVersion: 2010-09-09
Description: Service control policy for production OU
Resources:
ProductionSCP:
Type: AWS::Organizations::Policy
Properties:
Name: !Sub "${AWS::StackName}-production-restrictions"
Description: SCP to restrict actions in production accounts
Type: SERVICE_CONTROL_POLICY
Content:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyDeleteResources",
"Effect": "Deny",
"Action": [
"s3:DeleteBucket",
"dynamodb:DeleteTable",
"rds:DeleteDBInstance",
"lambda:DeleteFunction"
],
"Resource": "*",
"Condition": {
"StringEquals": {
"aws:ResourceTag/environment": "production"
}
}
},
{
"Sid": "RequireEncryption",
"Effect": "Deny",
"Action": [
"s3:PutObject",
"dynamodb:PutItem"
],
"Resource": "*",
"Condition": {
"StringNotEquals": {
"s3:x-amz-server-side-encryption": "AES256"
}
}
},
{
"Sid": "DenyRootAccess",
"Effect": "Deny",
"Action": [
"iam:CreateAccessKey",
"iam:CreateLoginProfile",
"iam:EnableMFADevice"
],
"Resource": "*",
"Condition": {
"StringEquals": {
"aws:PrincipalTag/role": "breakglass"
}
}
},
{
"Sid": "AllowKnownServices",
"Effect": "Allow",
"Action": "*",
"Resource": "*",
"NotPrincipal": {
"AWS": [
"arn:aws:iam::aws:policy/AdministratorAccess"
]
}
}
]
}
Conditions and Transform
Conditions for Environment-Specific Roles
AWSTemplateFormatVersion: 2010-09-09
Description: IAM resources with conditional configurations
Parameters:
Environment:
Type: String
Default: dev
AllowedValues:
- dev
- staging
- production
Conditions:
IsProduction: !Equals [!Ref Environment, production]
IsDevelopment: !Equals [!Ref Environment, dev]
CreateAdminRole: !Or [!Equals [!Ref Environment, staging], !Equals [!Ref Environment, production]]
Resources:
# Base role for all environments
BaseExecutionRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub "${AWS::StackName}-base-role"
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
Service: lambda.amazonaws.com
Action: sts:AssumeRole
MaxSessionDuration: !FindInMap [EnvironmentConfig, !Ref Environment, MaxSessionDuration]
Policies:
- PolicyName: !Sub "${AWS::StackName}-base-policy"
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- logs:CreateLogGroup
- logs:CreateLogStream
- logs:PutLogEvents
Resource: "*"
# Admin role only for staging and production
AdminRole:
Type: AWS::IAM::Role
Condition: CreateAdminRole
Properties:
RoleName: !Sub "${AWS::StackName}-admin-role"
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
AWS: !Ref AdminUserArn
Action: sts:AssumeRole
ManagedPolicyArns:
- arn:aws:iam::aws:policy/ReadOnlyAccess
- !If
- IsProduction
- arn:aws:iam::aws:policy/ViewBilling
- !Ref AWS::NoValue
Mappings:
EnvironmentConfig:
dev:
MaxSessionDuration: 3600
staging:
MaxSessionDuration: 7200
production:
MaxSessionDuration: 43200
Transform for Policy Reuse
AWSTemplateFormatVersion: 2010-09-09
Transform: AWS::Serverless-2016-10-31
Description: Using SAM Transform for IAM patterns
Globals:
Function:
Timeout: 30
Runtime: python3.11
Policies:
- S3ReadPolicy:
BucketName: !Ref DataBucket
- DynamoDBCrudPolicy:
TableName: !Ref DataTable
- SecretsManagerReadWrite:
SecretArn: !Ref AppSecret
Resources:
ProcessorFunction:
Type: AWS::Serverless::Function
Properties:
FunctionName: !Sub "${AWS::StackName}-processor"
Handler: app.handler
CodeUri: lambda_function/
Environment:
Variables:
LOG_LEVEL: INFO
Best Practices
Security
- Always apply least privilege: start with minimal permissions and add only what’s needed
- Use IAM Access Analyzer to identify excessive permissions
- Implement permission boundaries to limit maximum permissions
- Use condition keys for granular restrictions (aws:SourceIp, aws:ResourceTag, aws:RequestedRegion)
- Enable MFA for all IAM users
- Rotate access keys regularly (max 90 days)
- Use roles instead of long-term credentials where possible
- Implement external ID for cross-account trust
- Use service-linked roles for AWS services
Template Organization
- Separate IAM into dedicated stacks for clear ownership
- Use nested stacks for modularity
- Export only necessary values for cross-stack references
- Always document intent with Description fields
- Use Parameters for environment-specific configuration
- Implement conditions to manage variants without duplication
- Tag all IAM resources for tracking and cost allocation
Monitoring
- Enable CloudTrail for audit of all IAM actions
- Configure S3 Object Lock for critical policy files
- Use IAM Access Analyzer for periodic reports
- Implement SCP for organizational guardrails
- Create alarms for unauthorized access
Compliance
- Implement separation of duties policies
- Use AWS managed policies for standard compliance
- Document all deviations from standards
- Maintain audit trail for at least 90 days
- Apply encryption at rest and in transit
CloudFormation Stack Management Best Practices
Stack Policies
Stack Policies prevent unintended updates to critical resources during stack updates.
Resources:
# Stack Policy to protect IAM roles from updates
IAMStackPolicy:
Type: AWS::CloudFormation::StackPolicy
Properties:
PolicyDocument:
Statement:
- Effect: Deny
Action: Update:Replace
UpdateReplacePolicy: Retain
Resource: "*"
Condition:
StringEquals:
aws:ResourceTag/Protected: "true"
- Effect: Allow
Action: Update:*
Resource: "*"
Termination Protection
Enable termination protection to prevent accidental stack deletion.
Resources:
ProductionStack:
Type: AWS::CloudFormation::Stack
Properties:
TemplateURL: https://s3.amazonaws.com/bucket/iam-template.yaml
TerminationProtection: true
CLI commands for termination protection:
# Enable termination protection
aws cloudformation update-termination-protection \
--stack-name my-iam-stack \
--enable-termination-protection
# Disable termination protection
aws cloudformation update-termination-protection \
--stack-name my-iam-stack \
--no-enable-termination-protection
Drift Detection
Detect when infrastructure has diverged from the template definition.
# Detect drift on a stack
aws cloudformation detect-drift \
--stack-name my-iam-stack
# Get drift detection status
aws cloudformation describe-stack-drift-detection-status \
--stack-drift-detection-id <detection-id>
# Get drift detection results
aws cloudformation describe-stack-resource-drifts \
--stack-name my-iam-stack
Change Sets
Preview and review changes before executing them.
# Create a change set
aws cloudformation create-change-set \
--stack-name my-iam-stack \
--change-set-name my-changeset \
--template-body file://template.yaml \
--capabilities CAPABILITY_IAM
# List change sets
aws cloudformation list-change-sets \
--stack-name my-iam-stack
# Describe change set
aws cloudformation describe-change-set \
--stack-name my-iam-stack \
--change-set-name my-changeset
# Execute change set
aws cloudformation execute-change-set \
--stack-name my-iam-stack \
--change-set-name my-changeset
# Delete change set (if not executing)
aws cloudformation delete-change-set \
--stack-name my-iam-stack \
--change-set-name my-changeset
Related Resources
Additional Files
For complete details on IAM resources and their properties, see:
- REFERENCE.md – Detailed reference guide for all CloudFormation IAM resources
- EXAMPLES.md – Complete production-ready examples