Cross-Account CodeCommit Access from EC2
Tags: aws, tutorial, security, devops
Published: 2023-11-07 05:26:42

## Table of contents
- [Introduction](#introduction)
- [Cross-Account CodeCommit Access from EC2](#cross-account-codecommit-access-from-ec2)
    - [Step 1: Create an IAM role in Account A](#step-1-create-an-iam-role-in-account-a)
    - [Step 2: Create a policy in Account B](#step-2-create-a-policy-in-account-b)
    - [Step 3: Create an IAM role in Account B](#step-3-create-an-iam-role-in-account-b)
    - [Step 4: Create a CodeCommit repository in Account A](#step-4-create-a-codecommit-repository-in-account-a)
    - [Step 5: Create an EC2 instance in Account B](#step-5-create-an-ec2-instance-in-account-b)
    - [Step 6: Connect to the instance and checkout files](#step-6-connect-to-the-instance-and-checkout-files)
- [Lessons learned](#lessons-learned)

## Introduction
In this two-part series, I will guide you on how to access an [AWS CodeCommit](https://aws.amazon.com/codecommit/) repository using [git-remote-codecommit](https://github.com/aws/git-remote-codecommit). This tutorial will specifically focus on accessing a repository from a different account. In contrast, [the first part](https://dev.to/aporiadin/codecommit-access-from-ec2-2h8j) of this series explains how to access a repository from the same account.

While working on a project, I came across a situation where a client was using SSH keys to interact with CodeCommit on their EC2 server. In my opinion, this approach is not secure, as there is a risk of the key being leaked, and it is difficult to keep track of who has access to it. I believe a more secure and transparent approach should be adopted to ensure better security.

My client might be one of many using this method to interact with CodeCommit. Therefore, I wrote a tutorial to help others secure their repository interactions.

While I suggest going through the tutorial to consolidate your knowledge, you can also see the entire process through the numerous screenshots I have provided to make the tutorial more straightforward.

## Cross-Account CodeCommit Access from EC2
To complete this tutorial, we need to create certain resources in two AWS accounts. In Account A, we need to create an IAM role and a CodeCommit repository. In Account B, we need to create an IAM policy, an IAM role, and an EC2 instance.

Additionally, after completing the tutorial, it's recommended to delete these resources to avoid unnecessary AWS charges.

### Step 1: Create an IAM role in Account A
[//]: # (Use case: AWS Account. Select another AWS account. Provide account ID;)
[//]: # (Permissions: AWSCodeCommitReadOnly;)
[//]: # (Name: account_a_cross_account_role;)

Let's start by creating the first role. Go to the console and search for **Identity and Access Management**. Then, select **Roles** from the left-hand menu and click **Create Role**. This time, we will allow a different account to use our role from Account A. Therefore, we will choose **AWS Account** as the use case. In the section below, select **Another AWS Account** and provide the account ID.

![A step-by-step guide showing the initial phase of creating a new role in the AWS Management Console, starting with selecting the appropriate use case from the list provided.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/afnty6lmnhv3vak0xidy.png)

Afterward, click **Next** and attach the **AWSCodeCommitReadOnly** permission. This will ensure that the other account can't push any changes to our repository.

![A step-by-step guide showing the second step of creating a new role in the AWS Management Console, highlighting the permissions selection process for role configuration.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1vddaxfl5zuptfj3rrfo.png)

Finally, name the role **account_a_cross_account_role**. Scroll down and click **Create Role**.

![A step-by-step guide showing the third step of creating a new role in the AWS Management Console, highlighting the role configuration details section.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/iwr3ji1h9sxvuf4qsmdg.png)

Congratulations! You have successfully created a role for cross-account access. Let's move on to the next step.

### Step 2: Create a policy in Account B
[//]: # (Create a new policy that allow to assume a role.)
[//]: # (Service: STS.)
[//]: # (Access level: AssumeRole. Provide specific role from account A.)
[//]: # (Name: account_b_cross_account_access_policy;)

It's time to switch to Account B. To proceed, let's create a policy first. Go to the console and search for **Identity and Access Management**. From the left-hand menu, select **Policies**, then create a policy.

![A step-by-step guide showing the initial phase of creating a new policy in the AWS Management Console, starting with selecting the appropriate service from the list provided.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9bflsdmif41qis0p5nt6.png)

Select **STS** from the service dropdown. In the actions section, we need to configure granular access. To do this, expand options under the Write access level and select the **AssumeRole** option. 

Next, let's specify a resource under the resource section. Choose the specific option and click on **Add ARNs**. Set the ARN of the role that we created in the previous step, which should look like `arn:aws:iam:123456789012:role/account_a_cross_account_role`.

![A step-by-step guide showing the first step of creating a new policy in the AWS Management Console, highlighting the access level selection process for policy configuration.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e6dbl09n0nfgoqu61r40.png)

Navigate to the next screen and name the policy **account_b_cross_account_access_policy**. 

![A step-by-step guide showing the second step of creating a new policy in the AWS Management Console, highlighting the policy configuration details section.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/duhxnxrjqdodppmo8eh2.png)

Click **Create**.

### Step 3: Create an IAM role in Account B
[//]: # (Basically we need a role that we will use with the EC2 instance. So you might have a role you created before, or just create a new one.)
[//]: # (Use case: AWS Service. Select EC2. Select policy created in #2.)
[//]: # (Name: account_b_ec2_role;)

It's time to create a classic EC2 role and attach the policy we previously created. From the left-hand menu, select **Roles** and then create a role. Ensure that **AWS service** is selected. Next, select **EC2** under **Common Use Cases** and click **Next**.

![A step-by-step guide showing the initial phase of creating a new role in the AWS Management Console, starting with selecting the appropriate use case from the list provided.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s8j2pe8fwscgp6yzi6nk.png)

Next, we will add the managed policy we previously created to our role. Search for **account_b_cross_account_access_policy** and press "Enter". You will find the managed policy that provides the necessary permissions to assume the role from Account A on your EC2 instance. Select the policy and click **Next**.

![A step-by-step guide showing the second step of creating a new role in the AWS Management Console, highlighting the permissions selection process for role configuration.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qykmh5je75t97c0bfagr.png)

We will name our role **account_b_ec2_role**, and then scroll down to click the **Create Role** button.

![A step-by-step guide showing the third step of creating a new role in the AWS Management Console, highlighting the role configuration details section.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w9k36gcwj70yo2cbgoad.png)

### Step 4: Create a CodeCommit repository in Account A

If you've completed the previous tutorial and haven't deleted the repo, you can skip this step. Otherwise, let's create a new repository. For this demo, I have created a repository named **repository**.

![Screenshot of Amazon Web Services (AWS) Management Console displaying the 'Create new repository' form.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oliuzhec0cqh4ypdstxj.png)

Once you have created the repository, you'll see a screen with different connection options. We will use the recommended **HTTPS (GRC)** method to support connections made with federated access, identity providers, and temporary credentials.

![Newly created empty AWS CodeCommit repository with three connection options: HTTPS, SSH, and HTTPS (GRC).](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zewtwdt5ra7flosna8s9.png)

To add content to the repository, we need to create a simple text file. Firstly, scroll down to the section that says "empty repository" and click on the center button that says **Create File**.

![Empty AWS CodeCommit repository interface showcasing the 'Create file' button.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9vl2x70zr7z0srs3pfhr.png)

Next, put "Hello World!" as the content and "file.txt" as the file name to match the file created in the previous tutorial. You also must put your author name and email, and then click on **Commit Changes** to complete the process.

![Screenshot of AWS Console with 'Create a file' form for CodeCommit repository.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0rn8iv9qmba442dffb3z.png)

That's all for this step. You can move on to the next one.

### Step 5: Create an EC2 instance in Account B
[//]: # (Name: account_b_instance)

Let's move forward to the next step. We need to create an EC2 instance and name it **account_b_instance**. We'll use Amazon Linux 2023, which is the perfect fit for our needs.

![Screenshot of AWS EC2 instance launch screen with instance name input box and a selection menu of operating systems featuring Amazon Linux among others.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4eashm1r8bxm7k0a7knb.png)

Regarding hardware, we'll select the latest toys and choose an arm-based image. For our demo, t4g.nano is more than enough. This time, we'll proceed without a keypair.

![Screenshot of AWS EC2 instance launch screen displaying 'Instance Type' selection dropdown and 'Key Pair' field with 'Proceed without a Key Pair' option highlighted.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zfw4ewe6axdmsg84249t.png)

Now, expand the **Advanced details** tab and select the IAM instance profile we created earlier.

![Screenshot of AWS EC2 instance launch screen with a highlighted instance profile field.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t68solya2k50dkybbqun.png)

To ensure that we have all the necessary tools, we will install them with the User Data script. Here is the script we will use:

```
#!/bin/bash
dnf install git -y
curl -O https://bootstrap.pypa.io/get-pip.py
python3 get-pip.py
pip install git-remote-codecommit
```

Let me explain what we'll do here:

1. First, we'll install git as we can't interact with our repository without it.
2. We need to download PIP, which is a package manager for Python packages.
3. After downloading, we'll install PIP.
4. Finally, we'll install **git-remote-codecommit** using pip.

Here is a screenshot that shows how the field appears in the console.

![Screenshot of AWS EC2 instance launch screen with a highlighted User Data script field.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ahajvlrm5luzehcs44h3.png)

That's all we need to do. Let's wait for a moment while AWS creates an instance for us.

### Step 6: Connect to the instance and checkout files
Once the instance is ready, let's proceed with the next steps. To connect through the console, switch to the EC2 console, where you will see a page similar to the screenshot below.

![Screenshot of Amazon Web Services (AWS) EC2 console dashboard displaying a list of running instances, their respective statuses, types, and key metrics.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i41vc4l13rd7o7ccfixt.png)

Select the instance and click the **Connect** button at the top right corner. Then, click **Connect** again on the next screen.

![Screenshot of AWS Management Console showing the process of establishing a secure connection to an EC2 instance.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yodluul9hp169b9civoq.png)

After logging in, we can start with the necessary actions. The first step is to set up a profile based on the assumed role from account A. You will need to replace the ARN of the role with your own ARN in the first line.

```
aws configure set role_arn arn:aws:iam::123456789012:role/account_a_cross_account_role --profile CodeAccess
aws configure set credential_source Ec2InstanceMetadata --profile CodeAccess
aws configure set role_session_name "code_access" --profile CodeAccess
```

By following these commands, you will create a profile. There should be no output.

![Screenshot of a computer terminal showing the command line interface with a list of commands for creating a profile.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lgnb1yafz8yzwps7pdyh.png)

You have created a profile, but tools like the CLI can't predict whether to use the default profile or any named profile you created, so you need to specify it if you don't want to use default. Let's try to list repositories. First, we will use a simple AWS CLI command without the profile parameter:

```
aws codecommit list-repositories
```

Since we do not have permissions with the default role, this call will result in an error. However, we can specify the profile we created with the `--profile` parameter, and the command will return our repository from account A. So let's try that:

```
aws codecommit list-repositories --profile CodeAccess
```

You can see the result in the screenshot below if you don't want to follow along in your console.

![Screenshot of a terminal displaying a list of repositories retrieved using the AWS CLI command.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/za6bwca8c6b2s3gprtwe.png)

We have confirmed that we have access to the repository in Account A, and now it's time to check it out. To do this, we need to specify the profile for git-remote-codecommit. You can find the documentation for this process [here](https://github.com/aws/git-remote-codecommit). Let's attempt to run the following command:

```
git clone codecommit::us-east-1://CodeAccess@repository
```

![Screenshot showing successful Git checkout command output in terminal.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1ryp042cwyxl0i0p99z2.png)

We have successfully checked out the repository. Now, let's test our read-only permissions. We will attempt to modify the file and push the changes. These are the steps we need to follow:

```
cd repository/
nano file.txt
git add file.txt
git commit -m "Second release of Hello World!"
git push
```

Let me explain the commands above in detail. Firstly, go to the "repository" directory. Once you're there, use a text editor such as Nano or any other editor you prefer to make changes to the file. After making the changes, add the modified file to Git. Then, create a new commit and push the changes to the repository.

However, we encountered a 403 error due to our limited read-only permissions.

![Screenshot showing a 403 Forbidden Error message, resulting from an attempted 'git push' command in a terminal without the necessary write permissions, indicating the user does not have authorization to push changes to the git repository.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wkfyq9ilj81kj38yj7lt.png)

If you need to push changes from a different account, you can jump to Account A and replace the **AWSCodeCommitReadOnly** policy with **AWSCodeCommitFullAccess** for the **account_a_cross_account_role** role to grant full access.

![Screenshot of AWS IAM console showing the policy change process from AWSCodeCommitReadOnly to AWSCodeCommitFullAccess, enabling a user to gain full access permissions to push changes to a CodeCommit repository.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b1gwr2sqib5r4r7juiql.png)

And push the changes after that without any errors.

![Screenshot of a computer terminal displaying the successful execution of a 'git push' command.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/va8gcd8nz3qrjwjihze6.png)

## Lessons learned

I hope you found the article about accessing a CodeCommit repository from a different account using git-remote-codecommit helpful. Perhaps you even learned something new!

To summarize, you now have the skills to securely access a CodeCommit repository from a different account using the recommended approach. Additionally, you have learned how to create roles for cross-account access, which is quite useful.

I hope you enjoyed reading the article and gained valuable insights from it. If you found it helpful, please feel free to share, ask questions, or share your thoughts. Let's continue the conversation. Until next time, happy coding!