Amazon Web Services Identity and Access Management, AWS IAM, provides a robust framework for controlling access to AWS services and resources. Managing permissions and access control in cloud environments is critical for ensuring the security and integrity of your environment and applications.
AWS CloudFormation is a great way to manage and automate your AWS infrastructure by provisioning templates written in JSON or YAML. With CloudFormation, you can define your infrastructure as code and deploy it consistently across multiple environments and accounts.
What is an IAM Role?
Let's briefly understand what IAM roles are in the context of AWS.
AWS IAM consists of several key components that provide robust access control and security management within the AWS environment. The main components of AWS IAM are:
Users: Users are the entities representing individual people within your organization who interact with AWS services. Each user has a unique set of security credentials, including an access key and a secret access key, which are used to authenticate and authorize API requests.
Groups: Groups are collections of IAM users. Organizing users into groups allows you to manage and assign permissions to multiple users simultaneously. All users automatically inherit permissions granted to a group.
Roles: IAM roles define a set of permissions and access policies that AWS resources or IAM users can assume. Roles are often used to delegate access to AWS services or cross-account access. By assuming a role, an entity can temporarily receive specific permissions and carry out authorized actions on behalf of another entity.
Policies: IAM policies are JSON documents that define permissions and access control rules. They can be attached to users, groups, or roles. Policies explain what actions are allowed or denied on specific resources or services and provide fine-grained control over who can perform what actions.
An IAM role is a secure way to grant permissions to entities in AWS, such as IAM users, AWS services, or external identities, without needing long-term access keys.
IAM Roles define a set of permissions, which can be assumed by trusted entities, allowing them to perform actions on AWS resources.
IAM roles often grant AWS services permissions or establish trust relationships with external entities, such as identity providers or cross-account access.
Creating IAM Roles with AWS CloudFormation
AWS CloudFormation provides a declarative way to define and provision infrastructure resources. To create an IAM role with CloudFormation, you need to define a resource of the type AWS::IAM::Role
.
In this example, we define a role named AppDevRole
with a policy that allows EC2 instances to assume this role. The role also has a policy that grants permission to read objects from an S3 bucket resource AppDevBucket
.
AWSTemplateFormatVersion: 2010-09-09
Resources:
AppDevBucket:
Type: AWS::S3::Bucket
AppDevRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
Service:
- ec2.amazonaws.com
Action:
- sts:AssumeRole
Policies:
- PolicyName: AppDevRolePolicy
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- s3:GetObject
Resource: !Sub arn:aws:s3:::${AppDevBucket}/*
The AssumeRolePolicyDocument
specifies the trust policy that is associated with this role. Trust policies define which entities can assume the role.
In this case, we allow the EC2 service to assume the IAM Role by specifying ec2.amazonaws.com
as the principal in the Service
field. You can associate only one trust policy with a role.
The Policies
section defines the inline policy document embedded in the role. In our example, we create a policy named AppDevRolePolicy
that grants permission to perform the s3:GetObject
action on objects in the app-dev-bucket
S3 bucket.
When you embed an inline policy in a role, the inline policy is used as part of the role's access permissions policy. The role's trust policy is created at the same time as the role.
A complete list of properties can be found in the CloudFormation documentation for the AWS::IAM::Role
resource type.
Using IAM Roles with CloudFormation Resources
Once you have created an IAM role, you can use it with other AWS resources in your CloudFormation templates.
Let's consider an example where we create an EC2 instance and associate the previously created IAM role with it:
AWSTemplateFormatVersion: 2010-09-09
Resources:
# ...
AppDevEC2InstanceProfile:
Type: AWS::IAM::InstanceProfile
Properties:
Roles:
- !Ref AppDevRole
AppDevSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: AppDev Security Group
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: 0.0.0.0/0
AppDevEC2Instance:
Type: AWS::EC2::Instance
Properties:
InstanceType: t3.small
ImageId: ami-06b09bfacae1453cb
IamInstanceProfile: !Ref AppDevEC2InstanceProfile
SecurityGroups:
- !Ref AppDevSecurityGroup
Outputs:
AppDevBucketName:
Value: !Ref AppDevBucket
Description: Name of the AppDev S3 Bucket
AppDevEC2InstanceIp:
Value: !GetAtt AppDevEC2Instance.PublicIp
Description: Public IP address of the AppDev EC2 Instance
In this example, we define components to create an EC2 instance resource named AppDevEC2Instance
.
We specify the AppDevEC2InstanceProfile
to allow the EC2 instance to have specific permissions assigned to it through an IAM role. We reference the AppDevRole
IAM role we created earlier.
This ensures that the EC2 instance assumes the specified IAM role, inheriting its permissions and policies. By associating IAM roles with resources, you can enforce the principle of least privilege, granting only the necessary permissions to perform specific actions.
We are using the CloudFormation intrinsic function !Ref
to return the resource value reference.
The AppDevSecurityGroup
is an Amazon EC2 security group. It acts as a virtual firewall for the EC2 instance, controlling inbound and outbound traffic. This example template allows incoming SSH traffic on port 22 from any IP address (0.0.0.0/0).
Updating IAM Roles permissions
For every AWS service, you can specify what actions are allowed, which resources those actions can be applied to, and any additional conditions that need to be met in IAM policies.
The AWS documentation page Service Authorization Reference contains the actions, resources, and condition keys for AWS services.
Let's update our IAM Role permission to allow our application to put objects in the S3 bucket. Looking at the Amazon S3 actions table, we can use s3:PutObject
to enable our application to send files to S3:
AWSTemplateFormatVersion: 2010-09-09
Resources:
# ...
AppDevRole:
# ...
Policies:
- PolicyName: AppDevRolePolicy
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- s3:GetObject
- s3:PutObject # <--- New Action!
Resource: !Sub arn:aws:s3:::${AppDevBucket}/*
Conclusion
AWS CloudFormation simplifies the creation, usage, and management of IAM Roles, providing a streamlined approach to managing access control and permissions for your AWS resources.
CloudFormation enables you to manage IAM roles over time through stack updates. If you need to modify the permissions or policies of an IAM role, you can update the CloudFormation template, and CloudFormation will handle the necessary updates during stack update operations.
By utilizing CloudFormation and IAM Roles together, you can enhance the security and governance of your AWS infrastructure. The declarative nature of CloudFormation allows for consistent and reproducible deployments, while IAM Roles enforce the least privileged access, granting only the necessary permissions for your resources.
To learn more about the IAM Role and IAM Policies relationship, check out our guide AWS IAM Policies: A Practical Approach.
Related Reads
If you liked this article, you may be interested in these related articles: