CodeCommit with EC2 Role Credentials

2015-07-30

I had trouble getting AWS CodeCommit to work using an EC2 instance's role/instance profile credentials. My goal was to use a cloud-init script to pull down source from CodeCommit at instance launch time, then kick off some processing. I spent more time that I wanted to struggling with CodeCommit credentials, and I'd like to share the results in the hope of saving someone else the anguish.

My initial desire to use CodeCommit rather than github was that it used IAM credentials. An EC2 instance with credentials from an IAM Role seems like a pretty vanilla use case to me, but is not covered in the CodeCommit docs for setting up a git client. The documentation focuses on interactive or desktop use rather than automated agent access.

TL;DR

There were three configuration challenges and one obvious task:

  1. I ran into errors running git as root from the cloud-init script. I used git system-wide seetings as a workaround.
  2. The AWS CodeCommit credential helper for git must be configured with the "default" named profile to use the instance's role/instance profile credentials.
  3. The "default" named profile must be set to use the us-east-1 region by default, to match CodeCommit.
  4. The EC2 role needs to have permissions to the CodeCommit repo.

Below, I'll explain the setup in more detail and show a sample cloud-init script that puts it in action.

Running git as root

The recommended method to set up the CodeCommit credential helper involves the following git commands:

git config --global credential.helper '!aws --profile CodeCommitProfile codecommit credential-helper $@'
git config --global credential.UseHttpPath true

But when I ran this as root, I ran into the error fatal: $HOME not set, because git config --global is trying to read/write the current user's $HOME/.gitconfig file, and root seems to be $HOME-less in this context.

After being thoroughly schooled in git settings management, I can tell you that there is another option -- to set the system-wide git preferences with git config --system, which results in modifications to /etc/gitconfig, no errors. Try this instead:

git config --system credential.https://git-codecommit.us-east-1.amazonaws.com.helper '!aws --profile default codecommit credential-helper $@'
git config --system credential.https://git-codecommit.us-east-1.amazonaws.com.UseHttpPath true

Now that we've set this for all users, you might want to do your own personal configuration if you are later logging in and working as a named user, but this covers root in the instance launch sequence.

AWS "default" Profile

Note that in the sample git configuration above, I am using the "default" name profile for the credential helper, rather than the "CodeCommitProfile" suggested by the CodeCommit documentation. Your EC2 role credentials will apply to the "default" profile.

git config --system credential.https://git-codecommit.us-east-1.amazonaws.com.helper '!aws --profile default codecommit credential-helper $@'

AWS Region

The default region of the "default" named profile is defined in ~/.aws/config. This region needs to match the region of your CodeCommit repo. My CodeCommit repo was in us-east-1 (only region supported for now), but my instance was not. Without setting this property, I got the error Unknown component: credential_provider when attempting to run git clone. You can set the region as follows:

aws configure set region us-east-1

When CodeCommit supports regions outside us-east-1, you will have to modify this to point to your repo's region.

I know it seems dumb to depend on the default region matching the location of your CodeCommit repo. What if you have two repos, in different regions? What if you need to set the default region to something other than us-east-1? This is the only way I know of right now, but there must be a better way to configure the intersection between region, repo, and credentials. Please comment if you know how to do this!

Role Permissions for CodeCommit

You need to ensure that your EC2 role has the correct permissions to read and/or write to CodeCommit. AWS has made this fairly easy through preconfigured Managed Policies you can attach to your role (as long as you only need 2 of them). I used the AWSCodeCommitReadOnly managed policy, which reads as follows:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "codecommit:BatchGetRepositories",
                "codecommit:Get*",
                "codecommit:GitPull",
                "codecommit:List*"
            ],
            "Resource": "*"
        }
    ]
}

Config Script for cloud-init

Here is a script for cloud-init, showing these steps scripted out in practice. I pruned out the other commands the code to make the sample more concise to the CodeCommit credential issues.

#cloud-config
repo_update: true
repo_upgrade: all

packages:
- git

runcmd:
- mkdir /var/build
- pushd /var/build
- git config --system credential.https://git-codecommit.us-east-1.amazonaws.com.helper '!aws --profile default codecommit credential-helper $@'
- git config --system credential.https://git-codecommit.us-east-1.amazonaws.com.UseHttpPath true
- aws configure set region us-east-1
- git clone https://git-codecommit.us-east-1.amazonaws.com/v1/repos/my-awesome-repo

I hope this helped, please share your experience.