Cyber Defense Advisors

Creating a Role for an EC2 Instance with CloudFormation

ACM.107 Using an IAM Role Profile with an EC2 Instance for short-term rotating credentials

This is a continuation of my series on Automating Cybersecurity Metrics.

In the last post we created a VPC endpoint for CloudFormation so we can access the AWS service from a private network. The post also showed you when you might not actually be using a private network when you have a VPC Endpoint configured.

VPC Endpoint for CloudFormation

In this post we want to test our VPC endpoint, but before we can do that we need some credentials on the VM that we want to use to test CloudFormation.

We’re going to create a role in this post that we can assign to this instance to perform CloudFormation actions. We’re going to use our AppDeploy role and modify it so it can be assigned to an EC2 instance.

This role will look similar to other roles we created with one exception. To enable the ability to associate this role with an EC2 instance we need to create an instance profile.

Instance Profiles in the AWS Console

When you assign a role to an EC2 instance in the AWS console you don’t need to create the instance profile. You can right click on an instance to assign a role to an instance, or do the same thing from the actions menu.

The roles you see on the next screen will be any roles that have a trust policy that allows EC2 to use that role. I explained what trust policies are here:

You can see the assigned role on the EC2 dashboard instance details.

An instance profile gets added to roles you create in the console for EC2 instances automatically by AWS.

Role profiles in CloudFormation

In CloudFormation you need to explicitly define the role profile:

AWS::IAM::InstanceProfile

We are going to add an instance profile and a trust policy to the AppDeploy role we created and test it out. When you create a server to deploy applications for you, they generally run with a role. Using a role instead of long term developer credentials is preferred when using automation that is not initiated by humans. In other words, a server is running unattended and taking actions as required to perform some task.

Why use an AWS IAM Role on an EC2 instance instead of developer credentials?

If you use an AWS access key id and secret access key id in that scenario, any attacker who gets the credentials can use them on any other machine for as long as those credentials are valid. Recall that we cannot enforce MFA with long term credentials except for role assumption.

When you use an AWS role, credentials are still present. However, they get rotated frequently. If an attacker steals them, they will be good for a shorter period of time. Additionally, if you use AWS GuardDuty, it will detect when role credentials are used outside your AWS account.

Intelligent threat detection – Amazon GuardDuty – Amazon Web Services

MFA can trump IAM roles

Using IAM roles on EC2 instances is a best practice — however that also assumes you are not enforcing MFA. If you require users to assume a role via MFA to take actions then that is probably as good or better than an IAM role The role assumption will likely have a similar session length (and you can control that to make it longer or shorter) and cannot be initiated without a second factor, unlike a role always available on an EC2 instance.

We’ve looked at scenarios throughout this series where you can and cannot enforce MFA in IAM policies. You’ll need to be careful to understand when MFA is not actually enforced. For example, we looked at weaknesses in policies when using ifexists and the fact that the AWS documentation at the time that blog post was written was possibly be misleading on that point. It may have been updated since.

When you have to use a role

If you have some automation responding to events without human interaction, then you will need to use an IAM role or some other form of non-MFA credentials. Of course, you can require MFA on a prior event that triggers the chain of events that led to the automation. That’s what we are going to try to do in this blog series with batch jobs.

Creating an AWS Batch Job That Requires MFA

This is not a typical implementation, by the way. It’s pretty much an experiment just because I want to see if I can make it work and consider any downsides to my approach.

Add ec2 to our service role template

Use the function we created for deploying service roles to deploy a new EC2 role — in this case named EC2AppDeployRole:

That deploys the role and trust policy but no permissions:

We can use the existing AppDeployment Group Role Policies for this role.

We have two policies applied to the AppDeploymentGroup and we can simply add this role to those policy templates.

AppDeploymentGroupRolePolicy.yaml

AppDeploymentGroupRoleKMSPolicy.yaml

Once deployed you should see two policies associated with the IAM role:

Add an instance profile to our AppDeployment role template

Now we need to add the EC2 instance role profile via a CloudFormation template. Where should we create this role profile? Should it be created by the AppDeployment role or should we have the IAM administrators create it? As always there’s no one right answer but in this POC we are going to let the IAM administrators define which roles can be used with EC2 instances. These role profiles will be defined in the IAM directory and the template will be deployed by IAM administrators.

We really only need two properties: The name and the roles. Path is an optional identifier. Here’s our template which we are once again keeping generic so we can reuse it.

We’ll create a common function to deploy the profile:

Call the function from the deploy.sh script using the role name we just deployed.

Now you can see that this role has an Instance Profile:

Assign the role to the EC2 instance in the EC2 CloudFormation template

We can assign the role to the instance now using the IAMInstanceProfile property:

We can use the output export to ensure that only valid CloudFormation exports are used for role profiles:

OK here’s where some funky CloudFormation things happened again. There’s always *something*.

First of all, when adding that line to associate the IAM profile I got the following error in CloudFormation which says this user does not have runInstances permissions:

Now, I know this user and group had this permission the last time I deployed this VM and I didn’t change anything. To confirm, I deleted the new line I just added above.

Then I got an error saying a new resource could not be created due to the existing EIP association. Hmm. That could be a problem but I’m ignoring it for now. I deleted the association and deployed again.

Now I get a different error message that is the actual problem:

That makes more sense and is appropriate. Seems like a CloudForamtion bug there. In any case, we need to add that permission to our AppDeploy Role Policy. While I’m at it I’m going to allow all Ec2 Instance Profile actions:

Deploy that policy and then try the VM deployment again.

I got an error about a different action. Initially I thought it was related to the * at the end of the action above but that was not it.

I break down and decode the associated error message using these steps:

Decoding AWS Error Messages

As it turns out the reported action that is reported as not allowed in CloudFormation is not the action in the encoded message. It says the action is IAM:PassRole. This seems like another CloudFormation bug.

Our policy has permission for the IAM::PassRole action but only for a specific role:

We need to add our new EC2 Role.

Deploy the policy again. Try the VM deployment again.

Still not correct. We have to use the role ARN in this case, not the Instance Profile ARN. Hint: look at the role IAM:PassRole is trying to use in the error message. Copy and paste to save yourself some hassle.

Deploy the policy again. Try the VM deployment again.

I kept getting errors so I ended up hardcoding all the actions related to instance profiles:

Actions, resources, and condition keys for Amazon EC2

This works:

Finally. That took way too long for something that should be simple.

Return to the Network folder and redeploy the EIP association.

Verify the AWS CLI exists or install it on the EC2 instance

Start and log into the Developer VM we just updated.

Follow the steps to download the GitHub repository. If I have time I’ll show you how to create an AMI so you don’t have to do that over and over again. Remember we set up our network to allow access to GitHub in a prior post using a prefix list.

sudo yum install git
git clone [repo]

Run the following command to validate the AWS CLI is installed.

aws –version

run aws configure to define the region in which you want to run your commands. I’m presuming you are familiar with this but if not review the AWS CLI installation and configuration documentation.

Now recall that our deployment role has permission to deploy specific CloudFormation stacks. I added permission to the AppDeploy role for DescribeStacks for any resource “*” to make it easier to test this particular functionality. After doing that the user can run this command:

aws cloudformation describe-stacks

It does not work. Why does not work?

We’ll look at that in the next post. We’re going to troubleshoot our VPC Endpoint and look at required DNS settings for private connections.

Follow for updates.

Teri Radichel

If you liked this story please clap and follow:

Medium: Teri Radichel or Email List: Teri Radichel
Twitter: @teriradichel or @2ndSightLab
Requests services via LinkedIn: Teri Radichel or IANS Research

© 2nd Sight Lab 2022

All the posts in this series:

Automating Cybersecurity Metrics (ACM)

Github Repo

GitHub – tradichel/SecurityMetricsAutomation

____________________________________________

Author:

Cybersecurity for Executives in the Age of Cloud on Amazon

Need Cloud Security Training? 2nd Sight Lab Cloud Security Training

Is your cloud secure? Hire 2nd Sight Lab for a penetration test or security assessment.

Have a Cybersecurity or Cloud Security Question? Ask Teri Radichel by scheduling a call with IANS Research.

Cybersecurity & Cloud Security Resources by Teri Radichel: Cybersecurity and Cloud security classes, articles, white papers, presentations, and podcasts

Creating a Role for an EC2 Instance with CloudFormation was originally published in Cloud Security on Medium, where people are continuing the conversation by highlighting and responding to this story.