Use IAM role for deploying serverless on an EC2


#1

I am using a gitlab runner that is an EC2 to test and deploy my serverless code. I can’t figure out how to make serverless use my IAM role on the EC2 instance instead of using AWS access keys.

During the testing phase, I have to use the following line to set fake keys for the testing in the docker instance. If I eliminate this line, I get an error during my test that the keys are not available.

serverless config credentials --provider aws --key 1 --secret 2

Once the testing finishes it tries to run serverless deploy which of course fails because those keys are not real. How can I use the IAM role that is already on the EC2 instance? The role which is in place, currently has dynamoDB, lambda, cloudwatch, and xray full access. (I don’t use api gateway for my app). That should be enough, right?

(This is such a seemingly simple question, I’m sorry if it has already been asked but I was having a tough time searching the forums because there are so many posts about service roles for the things that serverless deploys so it was hard to differentiate those questions from the roles of instance that serverless runs on itself.)


#2

You’ll also need permissions to create CloudWatch Logs, API Gateway, etc. The minimum permissions required to deploy using Serverless is often discussed and rarely resolved. That’s why most people use accounts with admin access.


#3

Thanks for the reply- your comment makes it clear that I need to give the admin role to the EC2 server so that it can create all those cloudwatch logs and other stuff, which is great to know. Provided that I give the build server admin access then, how can I use a IAM role instead of an API access key?


#4

If your EC2 instance has an associated IAM role, then you can get temporary credentials to apply/set before deploying your serverless application. That way you wont have to store/set admin access key inside the ec2 instance.

To do this, you first need to have a user which is defined in the aws credentials file.

serverless config credentials --provider aws --key ABC --secret 12345 --profile MyBasicUserName

That user has basic access that only allows them to assume the role associated with the ec2 instance.

You need to edit the trust policy in the role and state that you want that user to assume the role, e.g.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "ec2.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    },
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::0123456789012:user/MyBasicUserName"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}

When the user assumes the role, they can get temporary access keys, which allows all of the permissions allowed in the role.

$ aws sts assume-role --role-arn arn:aws:iam::0123456789012:role/MyEc2RoleName --role-session-name "RoleSession1" --profile MyBasicUserName

Now you just need to extract the AccessKeyId and SecretAccessKey to pass them into serverless, here’s a bash script to help:

temp_creds=$(aws sts assume-role --role-arn arn:aws:iam::0123456789012:role/MyEc2RoleName --role-session-name "RoleSession1" --query "Credentials.[AccessKeyId, SecretAccessKey]"  --output text)

echo temp_creds

IFS='   ' read -a parts <<< "$temp_creds"

export AWS_ACCESS_KEY_ID="${parts[0]}"
export AWS_SECRET_ACCESS_KEY="${parts[1]}"

serverless config credentials --provider aws --key $AWS_ACCESS_KEY_ID --secret $AWS_SECRET_ACCESS_KEY

(NOTE: the long space in the IFS=’ ’ line is a tab character, press ‘ctrl-v tab’ to create it)

I hope that helps.

https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html


#5

I have since discovered that you can also get the temporary credentials through the ec2 instance using cURL, the credentials exist in instance metadata within the ec2 instance, to get them you do, e.g:

curl http://169.254.169.254/latest/meta-data/iam/security-credentials/your-role-name

The credentials file actually needs the token too, so here is an alternative script to setup temporary credentials (WARNING: this will overwrite your default profile):

temp_creds=$(curl http://169.254.169.254/latest/meta-data/iam/security-credentials/MyRole | jq -r '.AccessKeyId, .SecretAccessKey, .Token')

echo tempcreds are $temp_creds

IFS=" " readarray -t parts <<< "$temp_creds"

aws configure set aws_access_key_id "${parts[0]}"
aws configure set aws_secret_access_key "${parts[1]}"
aws configure set aws_session_token "${parts[2]}"

Note: you also need qr installed to parse the JSON returned from cURL


#6

This is really amazing, thanks so much Pete for taking the time to reply. Your last post worked perfectly!