Open menu
-->

AWS EC2 Instance IAM Roles

Cloud Conformity allows you to automate the auditing process of this resolution page. Register for a 14 day evaluation and check your compliance level for free!

Start a Free Trial Product features
Security

Risk level: Medium (should be achieved)

Use IAM Roles/Instance Profiles instead of IAM Access Keys to appropriately grant access permissions to any application that perform AWS API requests running on your EC2 instances. With IAM roles you can avoid sharing long-term credentials and protect your instances against unauthorized access.

This rule resolution is part of the Cloud Conformity Security Package

Using IAM Roles over IAM Access Keys to sign AWS API requests has multiple benefits. For example, once enabled, you or your administrators don't have to manage credentials anymore as the credentials provided by the IAM roles are temporary and rotated automatically behind the scenes. You can use a single role for multiple EC2 instances within your stack, manage its access policies in one place and allow these to propagate automatically to all instances. Also, you can easily restrict which role a IAM user can assign to an EC2 instance during the launch process in order to stop the user from trying to gain elevated (overly permissive) privileges.

Audit

To determine if your EC2 instances are using IAM roles to sign AWS API requests, perform the following:

Using AWS Console

01 Sign in to the AWS Management Console.

02 Navigate to EC2 dashboard at https://console.aws.amazon.com/ec2/.

03 In the left navigation panel, under INSTANCES section, choose Instances.

04 Select the EC2 instance that you want to examine.

05 Select the Description tab from the dashboard bottom panel.

06 In the right column, check the IAM role attribute value. If the attribute has no value assigned, the selected EC2 instance has no IAM roles associated. Cloud Conformity strongly recommends using IAM roles when your applications need to perform AWS API requests.

07 Repeat steps no. 4 – 6 to check other EC2 instances provisioned in the current region for associated IAM roles.

08 Change the AWS region from the navigation bar and repeat the audit process for other regions.

Using AWS CLI

01 Run describe-instances command (OSX/Linux/UNIX) using appropriate filtering to list the IDs of all the existing EC2 instances currently available in the selected region:

aws ec2 describe-instances
	--region us-east-1
	--output table
	--query 'Reservations[*].Instances[*].InstanceId'

02 The command output should return a table with the requested instance IDs:

-------------------------
|   DescribeInstances   |
+-----------------------+
|  i-07a2ad8872fb3226b  |
|  i-05e4a39942208532d  |
|  i-035601b9c55f55f5d  |
+-----------------------+

03 Now run describe-instances command (OSX/Linux/UNIX) using an instance ID returned at the previous step and custom filtering to determine whether the selected instance has any IAM Roles/Instance Profiles assigned:

aws ec2 describe-instances
	--region us-east-1
	--instance-ids i-07a2ad8872fb3226b
	--query 'Reservations[*].Instances[*].IamInstanceProfile'

04 The command output should return the IAM Instance Profile identifiers (ID and ARN) or an empty array, i.e. [ ], if the selected EC2 instance does not have any associated IAM Roles/ Instance Profiles:

[
    []
]

05 Repeat steps no. 3 and 4 to verify other EC2 instances provisioned within the current region.

06 Repeat steps no. 1 – 5 to perform the audit process for other AWS regions.

Remediation / Resolution

To assign IAM roles to your running EC2 instances, you must re-launch those instances by creating images (AMIs) of the instances then launch new ones from images with the desired roles attached. To implement IAM role based access for existing instances, perform the following:

Using AWS Console

01 Sign in to the AWS Management Console.

02 Navigate to IAM dashboard at https://console.aws.amazon.com/iam/.

03 In the left navigation panel, choose Roles.

04 On the Roles page, click Create New Role to set up a new IAM role that your instance(s) can assume by performing the following actions:

  1. In the Role Name field enter a name for the role. Choose a name that will reflect the purpose of the role (e.g. EC2-Admin-Role) and click Next Step.
  2. Choose the AWS Service Roles section and then select the Amazon EC2 option.
  3. On the Attach Policy page, select the access policy to attach to the IAM role. This policy defines what actions your application can take and what AWS resources can access. As example, we will use the AmazonEC2FullAccess policy, which provides full access to all AWS EC2 services and resources (EC2, ELB, ASG, etc). You can also create your own custom policy using the AWS Policy Generator: https://awspolicygen.s3.amazonaws.com/policygen.html. Click Next Step to continue.
  4. On the Review page, review the role information (name, ARN, etc) and click Create Role to generate the new IAM role.

05 Now it’s time to create an image (AMI) from your running EC2 instance. To instantiate the Amazon Machine Image (AMI), perform the following:

  1. Navigate to EC2 dashboard at https://console.aws.amazon.com/ec2/.
  2. In the left navigation panel, under INSTANCES section, choose Instances.
  3. Select the EC2 instance that requires roles for AWS API access (see the Audit section to identify any EC2 instances without IAM roles associated).
  4. Click the Actions dropdown button from the dashboard top menu, select Image and click Create Image.
  5. Inside Create Image dialog box, provide the following information:
    • Enter a name for the new AMI in the Image Name box.
    • In the Image description box, provide a description that reflects the usage of the EC2 instance selected.
    • Leave No reboot option unchecked so the AWS can guarantee the file system integrity for the new image.
  6. Click Create Image to submit the request to create the image. Click Close to return to the EC2 dashboard. The AMI creation may take few minutes. Once the process is complete the image status should change from pending to available.

06 Once the AMI is ready, use it to (re)launch the selected EC2 instance and attach the IAM role created earlier. To launch the instance, perform the following actions:

  1. In the navigation panel, under INSTANCES section, select Instances.
  2. Click the Launch Instance button from the EC2 dashboard top menu to initiate the process.
  3. On the Choose an Amazon Machine Image (AMI) page, choose My AMIs tab then select the AMI created at step no. 5.
  4. On the Choose an Instance Type page, select the same instance type used then click Next: Configure Instance Details button.
  5. On the Configure Instance Details page, select the newly created role from the IAM role dropdown list and configure any other options available on the page based on your running instance requirements. Click Next: Add Storage and go through the next pages until you reach the Configure Security Group page, without changing any configuration.
  6. On the Configure Security Groups, choose Select an existing security group and select the existing instance security group. Click the Review and Launch button, review your instance configuration details and click Launch.
  7. In the Select an existing key pair or create a new key pair dialog box, select Choose an existing key pair and use the same key pair as the running EC2 instance. Check I acknowledge that I have access to the selected private key file option then click Launch Instances.
  8. Click View Instances to return to the Instances page. The new instance will have the same data and configuration (except the new attached role) as the existing (old) EC2 instance.

07 Once you have verified and tested the new instance, you can transfer the Elastic IP (EIP) from the old EC2 instance to the new instance for reference purposes. If the old instance does not have an EIP attached you will have to update the domain DNS record(s) or any other application references to switch to the new instance IP. To transfer the Elastic IP, perform the following actions:

  1. In the navigation panel, under NETWORK & SECURITY section, select Elastic IPs.
  2. Select the EIP address attached to the old running instance, click the Actions dropdown button then select Disassociate Address.
  3. In the Disassociate Address dialog box, review the details then click Yes, Disassociate.
  4. Select the same address, disassociated in the previous step, click the Actions dropdown button then select Associate Address.
  5. In the Associate Address dialog box, select the new EC2 instance created at step no. 6 from the Instance dropdown list and then click Associate to attach the EIP.

08 Now it’s safe to terminate the old EC2 instance in order to stop incurring charges for it. To shut down the instance, perform the following:

  1. In the navigation panel, under INSTANCES section, select Instances.
  2. Select the EC2 instance that you want to terminate.
  3. Click the Actions dropdown button from the dashboard top menu, select Instance State and click Terminate.
  4. In the Terminate Instances confirmation box, review the instance details then click Yes, Terminate.

Using AWS CLI

01 First, create a trust policy for the new IAM role. Make a new policy document called ec2-role-trust-policy.json and paste the following:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "ec2.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}

02 Run create-role command (OSX/Linux/UNIX) to create the new IAM role that will be attached to your EC2 instance and used by your applications to sign AWS API requests:

aws iam create-role
	--role-name EC2-Admin-Role
	--assume-role-policy-document file://ec2-role-trust-policy.json

03 The command output should return the new IAM role metadata:

{
    "Role": {
        "AssumeRolePolicyDocument": {
            "Version": "2012-10-17",
            "Statement": [
                {
                    "Action": "sts:AssumeRole",
                    "Effect": "Allow",
                    "Principal": {
                        "Service": "ec2.amazonaws.com"
                    }
                }
            ]
        },
        "RoleId": "AROAIMVSYYB5CATLQSAFI",
        "CreateDate": "2016-06-08T12:04:37.829Z",
        "RoleName": "EC2-Admin-Role",
        "Path": "/",
        "Arn": "arn:aws:iam::123456789012:role/EC2-Admin-Role"
    }
}

04 Run attach-role-policy command (OSX/Linux/UNIX) to assign an IAM policy to your newly created role. The AmazonEC2FullAccess AWS managed policy will be used as example to run the attach-role-policy command. This policy provides full access to AWS EC2 services and resources. The command does not produce an output:

aws iam attach-role-policy
	--policy-arn arn:aws:iam::aws:policy/AmazonEC2FullAccess
	--role-name EC2-Admin-Role

05 Now create a new IAM Instance Profile. An instance profile is basically a container for the IAM role that is attached to the EC2 instance during the launch process. Run create-instance-profile command (OSX/Linux/UNIX) to create the new instance profile:

aws iam create-instance-profile
	--region us-east-1
	--instance-profile-name EC2-Web-Server-Profile

06 The command output should return the newly created IAM Instance Profile metadata:

{
    "InstanceProfile": {
        "InstanceProfileId": "AIPAJH7HIPC6KJHJYJWNG",
        "Roles": [],
        "CreateDate": "2016-06-08T11:49:54.600Z",
        "InstanceProfileName": "EC2-Web-Server-Profile",
        "Path": "/",
        "Arn": "arn:aws:iam::123456789012:instance-profile/
                EC2-Web-Server-Profile"
    }
}

07 Run add-role-to-instance-profile command (OSX/Linux/UNIX) to integrate the role created at step no. 2 with the IAM Instance Profile created at step no. 5 (the command does not return an output):

aws iam add-role-to-instance-profile
	--role-name EC2-Admin-Role
	--instance-profile-name EC2-Web-Server-Profile

08 Run describe-instances command (OSX/Linux/UNIX) to list the running EC2 instance metadata. The metadata will be useful later when this instance will be recreated to attach the new IAM Role/Instance Profile:

aws ec2 describe-instances
	--region us-east-1
	--instance-ids i-05e4a39942208532d
	--query 'Reservations[*].Instances[*].[KeyName,InstanceType,SecurityGroups]'

09 The command output should return the running/existing EC2 instance metadata requested:

[
    "MyEC2KeyPair",
    "m3.large",
    [
        {
            "GroupName": "MyEC2SecurityGroup",
            "GroupId": "sg-a942c9d2"
        }
    ]
]

10 Now that the IAM role is ready for use and you have the running EC2 instance required metadata, run create-image command (OSX/Linux/UNIX) to create an image from your existing EC2 instance. Include the –no-reboot command parameter to guarantee the file system integrity for your new AMI:

aws ec2 create-image
	--region us-east-1
	--instance-id 07a2ad8872fb3226b
	--name "EC2 instance AMI without IAM roles attached"
	--description "Web App Stack AMI ver. 2.5"
	--no-reboot

11 The command output should return the new Amazon Machine Image (AMI) ID:

{
    "ImageId": "ami-b04eg4e5"
}

12 Run run-instances command (OSX/Linux/UNIX) to launch the EC2 instance from the image created at the previous step. The following command example (re)creates an EC2 instance (m3.large) using an AMI with the ID ami-b04eg4e5, the IAM Instance Profile that contains the new IAM role and the rest of the old running EC2 instance configuration attributes:

aws ec2 run-instances
	--region us-east-1
	--iam-instance-profile Name=EC2-Web-Server-Profile
	--image-id ami-b04eg4e5
	--count 1
	--instance-type m3.large
	--key-name MyEC2KeyPair
	--security-groups MyEC2SecurityGroup

13 The command output should return the new EC2 instance configuration metadata (including the IAM Instance Profile metadata - highlighted):

{

    {
            "OwnerId": "567392585563",
            "ReservationId": "r-03ef4a3ce591f58ac",
            "Groups": [],
            "Instances": [

                    ...

                    "Architecture": "x86_64",
                    "RootDeviceType": "ebs",
                    "IamInstanceProfile": {
                        "Id": "AIPAJABYIFVH3EOJQNPUC",
                        "Arn": "arn:aws:iam::123456789012:
                                instance-profile/EC2-Admin-Role"
                    },
                    "RootDeviceName": "/dev/xvda",
                    "VirtualizationType": "hvm",

                    ...

                    "AmiLaunchIndex": 0
                }
            ]
        }
    ]
}

14 Now transfer the Elastic IP from the old EC2 instance to the new EC2 instance in order to reference the new one. To transfer the Elastic IP, perform the following commands:

  1. Run disassociate-address command (OSX/Linux/UNIX) to detach the Elastic IP (EIP) address from the old EC2 instance:
    aws ec2 disassociate-address
    	--association-id eipassoc-70dfe9fd5
    
  2. Run associate-address command (OSX/Linux/UNIX) to associate the EIP address detached at the previous step with the new EC2 instance:
    aws ec2 associate-address
    	--instance-id i-05e4a39942208532d
    	--allocation-id eipalloc-70dfe9fd5
    

15 Once you have verified that your new EC2 instance is working 100%, you should terminate the EC2 old instance to stop incurring charges for the resource. To terminate the EC2 old instance run terminate-instances command (OSX/Linux/UNIX) using the instance ID as identifier:

aws ec2 terminate-instances
	--instance-ids i-05e4a39942208532d

16 The command output should return the shutdown request metadata:

{
    "TerminatingInstances": [
        {
            "InstanceId": "i-05e4a39942208532d",
            "CurrentState": {
                "Code": 32,
                "Name": "shutting-down"
            },
            "PreviousState": {
                "Code": 16,
                "Name": "running"
            }
        }
    ]
}

References

Publication date Jun 9, 2016