AWSアカウントを跨いだCloudShellからのCodeCommitアクセス

AWS アカウントを跨いで、CloudShell 経由で CodeCommit にアクセスしてみます。

コピー元 AccountA (ID: 111122223333) 側の CodeCommit の git リポジトリから pull して、
コピー先 AccountB (ID: 888888888888) 側の CodeCommit の git リポジトリに push する手順です。

コピー先 AccountB 側の CloudShell で中継します。
いずれも IAM ロール・HTTPS を使います。
IAM ユーザ・SSH は使わないので、SSH 鍵の管理が不要になります。

コピー元 A から fetch するまでの手順は、手順１〜５になります。
fetch したものを、コピー先 B に push する手順は、手順６〜以降になります。

https://docs.aws.amazon.com/codecommit/latest/userguide/cross-account.html
などが参考になりました。

### （手順１） コピー先ロール

コピー先 AccountB で CloudShell を使う IAM ロール `test-console-role` を作成します。
https://us-east-1.console.aws.amazon.com/iam/home?region=ap-northeast-1#/roles/create
すでに IAM ロールがあるなら、新規作成は不要です。

- 信頼されたエンティティタイプ：AWS アカウント
- AWS アカウント：このアカウント
- MFA が必要：ON がオススメ
- 許可ポリシー：AWSCloudShellFullAccess と AWSCodeCommitPowerUser
- ロール名：`test-console-role`

ロールを作成したら、
https://us-east-1.console.aws.amazon.com/iamv2/home?region=ap-northeast-1#/roles 
から当該ロールを探して、ARN を確認しておきます。

https://us-east-1.console.aws.amazon.com/iam/home?region=ap-northeast-1#/roles/details/test-console-role?section=permissions
（例）`arn:aws:iam::888888888888:role/test-console-role`

また、「コンソールでロールを切り替えるためのリンク」を確認します。
https://signin.aws.amazon.com/switchrole?roleName=test-console-role&account=888888888888
のような URL にアクセスすると、スイッチロールできます。

### （手順２） コピー元リポジトリ

コピー元 AccountA 側で CodeCommit の git リポジトリ `test-project` を作成します。
https://ap-northeast-1.console.aws.amazon.com/codesuite/codecommit/repositories?region=ap-northeast-1

予め適当なコミットを push しておきます。
すでにリポジトリがあるなら、新規作成は不要です。

### （手順３） コピー元ロール

コピー元 AccountA 側で CodeCommit の参照権限を持つ IAM ロール `codecommit-888888888888-role` を作成します。
https://us-east-1.console.aws.amazon.com/iamv2/home?region=ap-northeast-1#/roles/create

- 信頼されたエンティティタイプ：カスタム信頼ポリシー
- カスタム信頼ポリシー：（Principal には、手順１の ARN を指定します）

```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "sts:AssumeRole",
            "Principal": {
                "AWS": "arn:aws:iam::888888888888:role/test-console-role"
            }
        }
    ]
}
```

- 許可ポリシー：AWSCodeCommitReadOnly（必要に応じて権限を厳しくする）
- ロール名：`codecommit-888888888888-role`（例）

ロールを作成したら、当該ロールの ARN を確認しておきます。
（例）`arn:aws:iam::111122223333:role/codecommit-888888888888-role`

### （手順４） コピー先ロール（ポリシー追加）

コピー先 AccountB の IAM ロール `test-console-role` に、コピー元リポジトリに接続するためのポリシーを追加します。
許可ポリシー＞許可を追加＞インラインポリシーを作成から、手順３で作成した IAM ロールへの AssumeRole を許可します。

```json
{
	"Version": "2012-10-17",
	"Statement": {
		"Effect": "Allow",
		"Action": "sts:AssumeRole",
		"Resource": "arn:aws:iam::111122223333:role/codecommit-888888888888-role"
	}
}
```

ポリシー名は `codecommit-111122223333` など。

### （手順５） CloudShell に pull

手順１で作成したコピー先 AccountB の IAM ロール `test-console-role` にスイッチロールしてから、CloudShell を開きます。
https://ap-northeast-1.console.aws.amazon.com/cloudshell/home/?region=ap-northeast-1

まず `.aws/config` を作っていきます。

```
aws configure --profile SRC

AWS Access Key ID [None]: （空のままでOK）
AWS Secret Access Key [None]: （空のままでOK）
Default region name [None]: （空のままでOK）
Default output format [None]: json（ここだけ「json」と入力）

cat ~/.aws/config 

[profile SRC]
output = json

vi ~/.aws/config 

[profile SRC]
output = json
account = 111122223333
credential_source = EcsContainer
region = ap-northeast-1
role_arn = arn:aws:iam::111122223333:role/codecommit-888888888888-role
```

`credential_source = EcsContainer` により CloudShell を開いている IAM ロールを参照してくれます。

`role_arn` には、手順４で作成した IAM ロールを指定します。

今回の手順では `git clone` せずに進めるので、自前でディレクトリを作成して `git init` します。

```sh
mkdir test-project
cd test-project
git init
```

そして、コピー元リポジトリに接続する設定を行って、fetch します。
`--profile SRC` の部分で、`.aws/config` のプロファイル名を指定しています。

```sh
SRC=https://git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/test-project
git config credential.$SRC.helper '!aws --profile SRC codecommit credential-helper $@'
git config credential.$SRC.useHttpPath true
git remote add SRC $SRC
git fetch SRC
git switch main
```

以上で、AccountA の CodeCommit から AccountB の CloudShell への参照ができました。
次の手順では、AccountB の CloudShell から AccountB の CodeCommit に push します。

### （手順６） コピー先リポジトリ

コピー先 AccountB の CodeCommit で、リポジトリ `test-project-dest` を作成します。
https://ap-northeast-1.console.aws.amazon.com/codesuite/codecommit/repositories?region=ap-northeast-1

AccountA と AccountB のリポジトリ名が全く同じだと、うまくプロファイルを切り替えできないようなので、残念ですがここは妥協して、ユニークなリポジトリ名（A/B で異なる名前）を指定します。

なお AWSCodeCommitPowerUser 権限だけでリポジトリを作成できない場合は、
必要に応じて別のロール（ユーザ）に切り替えるか、スイッチバックしてください。

### （手順７） CloudShell から push

さきほどの手順５で使った AccountB の CloudShell を再び開いて、コピー先リポジトリの設定を行って、push します。
デフォルトのプロファイルを参照するため、`--profile SRC` オプションがない点に注意してください。

```sh
DEST=https://git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/test-project-dest
git config credential.$DEST.helper '!aws codecommit credential-helper $@'
git config credential.$DEST.useHttpPath true
git remote add DEST $DEST
git push DEST
```

このうち `git config` や `git remote` の初期設定は初回のみです。

以後は `git pull SRC && git push DEST` でコピーできます。