top of page

AWS IAM Concepts - Roles

Updated: May 28, 2023

When it comes to AWS IAM (Identity and Access Management), roles are one of the key building blocks. Roles are used to grant permissions to an entity (such as a user or a service) without needing access keys or credentials.


In this post, we'll explore some of the key concepts around IAM roles and provide some practical examples of how roles can be used in different scenarios.


What is an IAM Role?


An IAM role is an AWS identity that is designed to be assumed by another AWS identity, such as an AWS service or a user. When a role is assumed, it grants permissions to the identity that is assuming the role based on the policies attached to it.


Roles can be used to grant permissions to a wide range of AWS services, including EC2 instances, Lambda functions, and more. Using roles, you can grant temporary access to resources and avoid needing long-lived access keys or credentials.


How Do IAM Roles Work?


When a role is created, one or more policies are attached to the role. These policies define the permissions that are granted to the role. When an identity (such as a user or a service) assumes the role, it gains the permissions that are defined in the policies.

One of the key benefits of roles is that they allow you to grant temporary access to resources. For example, you might create a role that grants an EC2 instance access to an S3 bucket. When the instance is launched, it can assume the role and access the S3 bucket without the need for long-lived credentials.


Practical Examples of Using IAM Roles


Let's take a look at some practical examples of how IAM roles can be used in different scenarios.


EC2 Instance Roles


One of the most common use cases for IAM roles is to grant permissions to EC2 instances. Using an IAM role, you can grant temporary access to resources such as S3 buckets without needing long-lived access keys or credentials.


To use an IAM role with an EC2 instance, you need to create a role with the necessary permissions and then attach the role to the instance when it is launched. Here's an example of how to create a role that grants an EC2 instance access to an S3 bucket:


[cloudshell-user@ip-10-2-61-174 ~]$ aws iam create-role --role-name MyEC2Role --assume-role-policy-document '{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"Service":"ec2.amazonaws.com"},"Action":"sts:AssumeRole"}]}'

{
    "Role": {
        "Path": "/",
        "RoleName": "MyEC2Role",
        "RoleId": "AROA3OC5MSRWTHN7UWQAS",
        "Arn": "arn:aws:iam::786XXXXXX733:role/MyEC2Role",
        "CreateDate": "2023-04-24T14:41:19+00:00",
        "AssumeRolePolicyDocument": {
            "Version": "2012-10-17",
            "Statement": [
                {
                    "Effect": "Allow",
                    "Principal": {
                        "Service": "ec2.amazonaws.com"
                    },
                    "Action": "sts:AssumeRole"
                }
            ]
        }
    }
}

Here we are providing an inline policy to list objects from an S3 bucket and put objects to a specific directory.


[cloudshell-user@ip-10-2-61-174 ~]$ aws iam put-role-policy --role-name MyEC2Role --policy-name S3AccessPolicy --policy-document \
'{  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:PutObject"
      ],
      "Resource": [
        "arn:aws:s3:::prahari-shared-data/logs/*"
      ]
    },
    {
      "Effect": "Allow",
      "Action": [
        "s3:ListBucket"
      ],
      "Resource": [
        "arn:aws:s3:::prahari-shared-data"
      ]
    }
  ]
}'


Then we will create an instance profile so that we can create an EC2 instance using that profile and add MyEC2Role to the new profile.


[cloudshell-user@ip-10-2-61-174 ~]$ aws iam create-instance-profile --instance-profile-name MyEC2RoleInstanceProfile01

{
    "InstanceProfile": {
        "Path": "/",
        "InstanceProfileName": "MyEC2RoleInstanceProfile01",
        "InstanceProfileId": "AIPA3OC5MSRWYVWIKYDLZ",
        "Arn": "arn:aws:iam::786XXXXXX733:instance-profile/MyEC2RoleInstanceProfile01",
        "CreateDate": "2023-04-26T10:35:20+00:00",
        "Roles": []
    }
}

[cloudshell-user@ip-10-2-61-174 ~]$ aws iam add-role-to-instance-profile --role-name MyEC2Role --instance-profile-name MyEC2RoleInstanceProfile01

Then we will prepare our S3 bucket


[cloudshell-user@ip-10-2-61-174 ~]$ aws s3api create-bucket --bucket "prahari-shared-data" --region 'us-east-1'
{
    "Location": "/prahari-shared-data"
}
[cloudshell-user@ip-10-2-61-174 ~]$ aws s3api put-object --bucket prahari-shared-data --key logs/ --acl bucket-owner-full-control
{
    "ETag": "\"d41d8cd98f00b204e9800998ecf8427e\"",
    "ServerSideEncryption": "AES256"
}


Now in order to test the Role and Policy, we will create an EC2 instance.

We will need an SSH keypair to access the instance.


[cloudshell-user@ip-10-2-61-174 ~]$ aws ec2 create-key-pair --key-name my-keypair --query 'KeyMaterial' --output text > my-keypair.pem

Then we need the SecurityGroup ID


[cloudshell-user@ip-10-2-61-174 ~]$ aws ec2 describe-security-groups  --query "SecurityGroups[*].[GroupName,GroupId]"  --output table
-------------------------------------
|      DescribeSecurityGroups       |
+----------+------------------------+
|  default |  sg-0191686dd44d845f1  |
+----------+------------------------+

And a subnet ID


[cloudshell-user@ip-10-4-63-100 ~]$ aws ec2 describe-subnets --query "Subnets[*].[SubnetId,AvailabilityZone,CidrBlock,DefaultForAz,State]"  --output table
-----------------------------------------------------------------------------------
|                                 DescribeSubnets                                 |
+---------------------------+-------------+-----------------+-------+-------------+
|  subnet-017461a7a601e2b5f |  us-east-1f |  172.31.64.0/20 |  True |  available  |
|  subnet-04a05705da4f60806 |  us-east-1d |  172.31.80.0/20 |  True |  available  |
|  subnet-07a2b20860e5656f1 |  us-east-1a |  172.31.16.0/20 |  True |  available  |
|  subnet-0340a903f623c30df |  us-east-1b |  172.31.32.0/20 |  True |  available  |
|  subnet-0e3888b25d1062256 |  us-east-1c |  172.31.0.0/20  |  True |  available  |
|  subnet-040c423e95f87d916 |  us-east-1e |  172.31.48.0/20 |  True |  available  |
+---------------------------+-------------+-----------------+-------+-------------+

Now we can create an EC2 instance with our previously created IAM instance profile.


[cloudshell-user@ip-10-4-63-100 ~]$ aws ec2 run-instances --image-id ami-02396cdd13e9a1257 --count 1 --instance-type t2.micro --key-name my-keypair --security-group-ids sg-0191686dd44d845f1 --subnet-id subnet-07a2b20860e5656f1 --iam-instance-profile Name=MyEC2RoleInstanceProfile01

Let us make sure to allow SSH from only our IP so that we can access the instance


[cloudshell-user@ip-10-6-31-69 ~]$ aws ec2 authorize-security-group-ingress --group-id sg-0191686dd44d845f1 --protocol tcp --port 22 --cidr `curl -s ifconfig.me`/32
{
    "Return": true,
    "SecurityGroupRules": [
        {
            "SecurityGroupRuleId": "sgr-02abbe57696658cca",
            "GroupId": "sg-0191686dd44d845f1",
            "GroupOwnerId": "786XXXXXX733",
            "IsEgress": false,
            "IpProtocol": "tcp",
            "FromPort": 22,
            "ToPort": 22,
            "CidrIpv4": "34.201.94.65/32"
        }
    ]
}

Let's get some details of the newly created instance


[cloudshell-user@ip-10-6-31-69 ~]$ aws ec2 describe-instances --query "Reservations[*].Instances[*].[InstanceId,KeyName,PublicDnsName,IamInstanceProfile.Arn]" --output=table
-----------------------------------------------------------------------------------------------------------------------------------------------------------
|                                                                    DescribeInstances                                                                    |
+---------------------+-------------+-------------------------------------------+-------------------------------------------------------------------------+
|  i-03c488febe4690f79|  my-keypair |  ec2-34-224-78-1.compute-1.amazonaws.com  |  arn:aws:iam::786XXXXXX733:instance-profile/MyEC2RoleInstanceProfile01  |                                                   
+---------------------+-------------+-------------------------------------------+-------------------------------------------------------------------------+


Let's SSH into the instance



[cloudshell-user@ip-10-6-31-69 ~]$ ssh -i "my-keypair.pem" ec2-user@ec2-34-224-78-1.compute-1.amazonaws.com
The authenticity of host 'ec2-34-224-78-1.compute-1.amazonaws.com (34.224.78.1)' can't be established.
ECDSA key fingerprint is SHA256:Rwk73zNMzkD84BO9lNtjZwa+ivy4UAaOQcTuBPj9Lkc.
ECDSA key fingerprint is MD5:ad:35:3d:ed:d3:14:82:44:44:f1:7e:78:c9:cf:f2:da.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'ec2-34-224-78-1.compute-1.amazonaws.com,34.224.78.1' (ECDSA) to the list of known hosts.
   ,     #_
   ~\_  ####_        Amazon Linux 2023
  ~~  \_#####\
  ~~     \###|
  ~~       \#/ ___   https://aws.amazon.com/linux/amazon-linux-2023
   ~~       V~' '->
    ~~~         /
      ~~._.   _/
         _/ _/
       _/m/'


Check if we have some sample files to upload to S3 and test our Role.


[ec2-user@ip-172-31-17-163 ~]$ ls -al 
total 12
drwx------. 3 ec2-user ec2-user  74 Apr 26 10:48 .
drwxr-xr-x. 3 root     root      22 Apr 26 10:48 ..
-rw-r--r--. 1 ec2-user ec2-user  18 Jan 28 22:29 .bash_logout
-rw-r--r--. 1 ec2-user ec2-user 141 Jan 28 22:29 .bash_profile
-rw-r--r--. 1 ec2-user ec2-user 492 Jan 28 22:29 .bashrc
drwx------. 2 ec2-user ec2-user  29 Apr 26 10:48 .ssh

[ec2-user@ip-172-31-17-163 ~]$ aws s3 cp .bashrc s3://prahari-shared-data/logs/.bashrc --region us-east-1
upload: ./.bashrc to s3://prahari-shared-data/logs/.bashrc 

[ec2-user@ip-172-31-17-163 ~]$ aws s3 ls
2023-04-26 10:38:01 prahari-shared-data

[ec2-user@ip-172-31-17-163 ~]$ aws s3 ls prahari-shared-data
                           PRE logs/

[ec2-user@ip-172-31-17-163 ~]$ aws s3 ls prahari-shared-data/logs/
2023-04-26 10:38:26          0 
2023-04-26 10:49:46        492 .bashrc

[ec2-user@ip-172-31-17-163 ~]$ exit
logout
Connection to ec2-34-224-78-1.compute-1.amazonaws.com closed.


It works! Noice!


Let's cleanup all the resources we have created.

First, the EC2 instance


[cloudshell-user@ip-10-6-31-69 ~]$ aws ec2 terminate-instances --instance-ids  i-03c488febe4690f79
{
    "TerminatingInstances": [
        {
            "CurrentState": {
                "Code": 32,
                "Name": "shutting-down"
            },
            "InstanceId": "i-03c488febe4690f79",
            "PreviousState": {
                "Code": 16,
                "Name": "running"
            }
        }
    ]
}


Then the S3 bucket



[cloudshell-user@ip-10-6-31-69 ~]$ aws s3 rm s3://prahari-shared-data --recursive
delete: s3://prahari-shared-data/logs/.bashrc
delete: s3://prahari-shared-data/logs/


Then the Role Instance Profile and Roles.


[cloudshell-user@ip-10-6-31-69 ~]$ aws iam remove-role-from-instance-profile --instance-profile-name MyEC2RoleInstanceProfile01 --role-name MyEC2Role
[cloudshell-user@ip-10-6-31-69 ~]$ aws iam delete-instance-profile --instance-profile-name MyEC2RoleInstanceProfile01

[cloudshell-user@ip-10-6-31-69 ~]$ aws iam delete-role-policy --role-name MyEC2Role --policy-name S3AccessPolicy
[cloudshell-user@ip-10-6-31-69 ~]$ aws iam delete-role --role-name MyEC2Role


Finally, the SSH allow rule from the SecurityGroup.



[cloudshell-user@ip-10-6-31-69 ~]$ aws ec2 revoke-security-group-ingress --group-id sg-0191686dd44d845f1 --protocol tcp --port 22 --cidr `curl -s ifconfig.me`/32
{
    "Return": true
}


I hope this helps you. Thank you.


29 views

コメント


bottom of page