【AWS CodeCommit】 クロスアカウントでのリポジトリ接続

## はじめに
本記事は、私自身の備忘録を兼ねてAWS CDKをこれから始める方の一助になればと思い、AWS CDKの使い方等をまとめたものです。
今回は、AWS CDK自体の内容からは少し外れますが、AWS CDKのソースコードを別アカウントのCodeCommitから取得したり更新したりする方法を確認します。
なお、本記事は私自身の経験を基に記載していますが、間違いがあったらすみません。

## AWS CDKのソースコードを別アカウントのCodeCommitで管理したい！
具体的には以下のような構成になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3445559/ada9167e-513d-27b9-2152-2e4382d4641d.png)
概要としては、
1. Account Bに用意したリポジトリにアクセス可能なポリシーを持ったRoleにAssumeRole
2. git-remote-codecommitを使用してgitコマンドを実行

※ AWS CDKのソースコードと書いてますが、やってることはクロスアカウントでのソースコード管理なので、AWS CDK以外のソースコードでも同じです。

## 環境
本記事は以下の環境を使用して記載しています。
* AWS Cloud9

## クロスアカウントでのリポジトリ接続
以下の流れでクロスアカウントでのリポジトリ接続確認をしていきます。

[準備1. （Account B）リポジトリの作成](#準備1-account-bリポジトリの作成)
[準備2. （Account A）Cloud9の作成](#準備2-account-acloud9の作成)
[1. （Account B）リポジトリアクセス可能なRoleの作成](#1-account-bリポジトリアクセス可能なroleの作成)
[2. （Account A）Cloud9にアタッチするインスタンスプロファイルの作成](#2-account-acloud9にアタッチするインスタンスプロファイルの作成)
[3. （Account A）AWS CLIのconfig作成](#3-account-aaws-cliのconfig作成)
[4. （Account A）git-remote-codecommitによるリポジトリアクセス](#4-account-agit-remote-codecommitによるリポジトリアクセス)
***

#### 準備1. （Account B）リポジトリの作成
まず、ソースコードを管理するリポジトリを作成します。
マネージメントコンソールのサービスメニューから開発者用ツール>CodeCommitを選び、リポジトリを作成をクリックしてリポジトリ作成画面を開きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3445559/27933a50-e1ff-a376-c9d6-eeff5aab50ec.png)

作成するリポジトリの名前を入力し、リポジトリを作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3445559/e0e55899-e518-afb6-ec5d-83f462ca609e.png)

ついでに確認用のファイルをリポジトリに作っておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3445559/00dcb29b-4c5c-797b-fde4-25804a5afe2d.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3445559/d914a537-0ff2-68a8-f5a4-b42cb466e245.png)

これでリポジトリの準備は完了です。

#### 準備2. （Account A）Cloud9の作成
次に、作業場所になるCloud9を作成します。
Cloud9の作成は、以下の記事を参考にしてください。
* [【AWS CDK/Python】 AWS CDKの始め方](https://qiita.com/takataka987/items/4448dbf06d8c70173305)

#### 1. （Account B）リポジトリアクセス可能なRoleの作成
ここから本題のクロスアカウントによるリポジトリアクセスに必要な設定を行っていきます。
まずは、リポジトリを持つアカウントにリポジトリにアクセス可能なポリシーを持つRoleを作成します。
マネージメントコンソールのサービスメニューからIAMのコンソールに行き、Roleの作成画面を開きます。
今回作成するRoleは、Account AからAssumeRoleするRoleになるので、信頼されたエンティティタイプをAWSアカウントにし、アカウントIDにAccount Aを設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3445559/13c04ad9-c979-162f-d828-1de76ab17ef1.png)

Roleに適当な名前を付けて作成します。（ポリシーは一旦何も付けずに作成します。）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3445559/0f8f12dc-68d4-40c8-aeae-9f1b67579d35.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3445559/a041cdb9-7d5c-46c6-c51f-5d0df4678546.png)

Roleを作成したらRoleの編集画面を開き、ポリシーを作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3445559/bf84949c-106a-5031-4452-b7af3a6acede.png)

ポリシーは以下のドキュメントを参考に作成します。
* [リポジトリへのクロスアカウントアクセス: AccountA の管理者のアクション](https://docs.aws.amazon.com/ja_jp/codecommit/latest/userguide/cross-account-administrator-a.html)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3445559/c701eaef-6024-83fc-c6b5-c8ad965df05c.png)

```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "codecommit:BatchGet*",
                "codecommit:Create*",
                "codecommit:DeleteBranch",
                "codecommit:Get*",
                "codecommit:List*",
                "codecommit:Describe*",
                "codecommit:Put*",
                "codecommit:Post*",
                "codecommit:Merge*",
                "codecommit:Test*",
                "codecommit:Update*",
                "codecommit:GitPull",
                "codecommit:GitPush"
            ],
            "Resource": [
                "arn:aws:codecommit:ap-northeast-1:<Account B>:<作成したリポジトリ名>"
            ]
        },
        {
            "Effect": "Allow",
            "Action": "codecommit:ListRepositories",
            "Resource": "*"
        }
    ]
}
```
ポリシーに適当な名前を付けて変更を保存してください。
これでRoleの準備が出来ました。

#### 2. （Account A）Cloud9にアタッチするインスタンスプロファイルの作成
次にCloud9にアタッチするインスタンスプロファイルを作成します。
Cloud9には、標準でAWSCloud9SSMInstanceProfileというインスタンスプロファイルが付いているのですが、このインスタンスプロファイルのままでは、先ほど作成したRoleにAssumeRoleできないので、インスタンスプロファイルを個別に作成します。
先ほどと同様にIAMの画面からRoleを作成します。今度は、Cloud9用のRoleなので、信頼されたエンティティタイプはAWSのサービスを選択し、サービスでEC2を選びます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3445559/22e3c3a3-fc94-720e-121f-c788346652de.png)

ポリシーには、AWSCloud9SSMInstanceProfileを選択し、適当な名前を付けてRoleを作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3445559/ffb3c450-2aab-073f-53ff-a4e3c20f1ab0.png)

Roleを作成したらRoleの編集画面を開き、以下のポリシーを追加作成します。
このポリシーは、Account Bに作成したRoleへのAssumeRoleを許可するポリシーになります。

```json
{
    "Version": "2012-10-17",
    "Statement": {
        "Effect": "Allow",
        "Action": "sts:AssumeRole",
        "Resource": "arn:aws:iam::<Account B>:role/<Account Bに作成したRole名>"
    }
}
```
ポリシーに適当な名前を付けて変更を保存してください。
これでインスタンスプロファイルの準備が出来ましたので、EC2のコンソール画面からCloud9のインスタンスプロファイルを変更します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3445559/fe929952-78e0-cc7f-e917-c17526f1fc2d.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3445559/d9a81c45-4679-02db-a02b-4b5f1bc16a21.png)

Cloud9は、標準でAWS Managed Temporary Credentialsという一時クレデンシャルで動いていて、このままだとインスタンスプロファイルが無効化されているので、AWS Managed Temporary Credentialsを無効化します。
Cloud9を起動し、メニューからPreferencesを開き、AWS SettingsのAWS managed temporary credentialsをOFFにします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3445559/83669a1b-6846-93b4-9363-7eb04ccaaeba.png)

#### 3. （Account A）AWS CLIのconfig作成
次に、git-remote-codecommitでCodeCommitにアクセスするためにAWS CLIのプロファイルを作成する必要があるため、作成します。
Cloud9で~/.aws/configを作成し、以下の内容を記載します。
```text:~/.aws/config
[profile <プロファイル名>]
role_arn = arn:aws:iam::<Account B>:role/<Account Bに作成したRole名>
credential_source = Ec2InstanceMetadata
region = ap-northeast-1
```
作成後、以下のコマンドでAssumeRoleしてAccount BのRoleを使用できることを確認します。（以下のような応答が返ってくればOKです。）
```console
$ aws sts get-caller-identity --profile <プロファイル名>
{
    "UserId": "AROA6GBMA3KTLOKVCXCBK:botocore-session-1715696039",
    "Account": "<Account B>",
    "Arn": "arn:aws:sts::<Account B>:assumed-role/<Account Bに作成したRole名>/botocore-session-1715696039"
}
$ 
```

#### 4. （Account A）git-remote-codecommitによるリポジトリアクセス
では、いよいよCodeCommitに接続します。
git cloneするには以下のコマンドを実行します。
```console
$ git clone codecommit::ap-northeast-1://<プロファイル名>@<作成したリポジトリ名>
Cloning into 'test-rep'...
remote: Counting objects: 3, done.
Unpacking objects: 100% (3/3), 195 bytes | 97.00 KiB/s, done.
$ 
```

cloneした結果を確認してみます。
```console
$ ls
test-rep
$ cd test-rep/
$ ls
file.txt
$ cat file.txt 
test file
$ 
```

ちゃんとリポジトリに作成したファイルが確認できました。
今度は、ファイルを作成してpushしてみます。

```console
$ touch file2.txt
$ echo "test file for cross account access" > file2.txt 
$ cat file2.txt 
test file for cross account access
$ git add .
$ git commit -m "test cross account access"
[main d0205cb] test cross account access
 Committer: EC2 Default User <ec2-user@ip-172-31-4-51.ap-northeast-1.compute.internal>
Your name and email address were configured automatically based
on your username and hostname. Please check that they are accurate.
You can suppress this message by setting them explicitly:

    git config --global user.name "Your Name"
    git config --global user.email you@example.com

After doing this, you may fix the identity used for this commit with:

    git commit --amend --reset-author

 1 file changed, 1 insertion(+)
 create mode 100644 file2.txt
$ git push
Enumerating objects: 4, done.
Counting objects: 100% (4/4), done.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 342 bytes | 342.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
remote: Validating objects: 100%
To codecommit::ap-northeast-1://CodeCommitAccess@test-rep
   8e08dda..d0205cb  main -> main
$ 
```

うまくpushできたようなので、CodeCommitのコンソールで確認してみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3445559/e68b1e8a-2f06-32c5-fcee-da02696a43c6.png)

CodeCommitのコンソールでも確認できました！

## まとめ
クロスアカウントでのCodeCommitリポジトリへのアクセスを確認しました。複数のアカウントを管理するシステムでは、Gitを共通化しクロスアカウントでアクセスすることも多いのではないかと思いますので、そういった場合に役立つかなと思います。
最後まで読んでいただいてありがとうございます。
少しでも参考になれば幸いです。
#### 参考文献
* [Cross-account repository access: Actions for the administrator in AccountA](https://docs.aws.amazon.com/codecommit/latest/userguide/cross-account-administrator-a.html)
* [AWS Cloud9 の環境から AWS のサービス の呼び出し](https://docs.aws.amazon.com/ja_jp/cloud9/latest/user-guide/credentials.html)