MFA強制時にCodeCommitのHTTPSアクセスだけ対象外にする

## 問題

AWSにアクセスするユーザーに対して、こちらで紹介されているように、MFAしていない操作を全て弾くように設定したとします。

https://dev.classmethod.jp/articles/forced_mfa/

そうすると、CodeCommitへの[Git認証情報によるHTTPSアクセス](https://docs.aws.amazon.com/ja_jp/codecommit/latest/userguide/setting-up-gc.html "Setup for HTTPS users using Git credentials")も、MFAしていないアクセスなので以下のように拒否されてしまいます。 [^1]

```sh
$ git push origin test
fatal: unable to access 'https://git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/myapp/': The requested URL returned error: 403
```

この認証情報はCodeCommit専用のものなので、そこまで危険でもないし、なんとかMFA無しのアクセスを許していただけませんかね… という場合はどうすれば良いでしょうか。


## 対応方法

Gitクライアントで必要な操作のみMFA対象外にするよう、IAMポリシーを修正します。

まず、上記ページに記載の Deny の部分で、以下のように `codecommit:` と `kms:` の一部アクションも `NotAction` に追加します[^2]。これらのアクションは、GitクライアントからCodeCommitへのアクセスに必要になります。

```json
{
    "Sid": "BlockMostAccessUnlessSignedInWithMFA",
    "Effect": "Deny",
    "NotAction": [
        "iam:CreateVirtualMFADevice",
        "iam:DeleteVirtualMFADevice",
        "iam:DeactivateMFADevice",
        "iam:EnableMFADevice",
        "iam:ResyncMFADevice",
        "iam:ListMFADevices",
        "iam:ChangePassword",
        "codecommit:GitPull",
        "codecommit:GitPush",
        "kms:Encrypt",
        "kms:Decrypt",
        "kms:ReEncryptFrom",
        "kms:ReEncryptTo",
        "kms:GenerateDataKey",
        "kms:GenerateDataKeyWithoutPlaintext",
        "kms:DescribeKey"
    ],
    "Resource": "*",
    "Condition": {
        "BoolIfExists": {
            "aws:MultiFactorAuthPresent": "false"
        }
    }
}
```

また、必要なのはCodeCommit用のKMSキーのみなので、上記で許可したKMSアクションについて、他のキーに対するMFA外操作を禁止する設定も追加します。

```json
{
    "Sid": "BlockMostKmsKeysUnlessSignedInWithMFA",
    "Effect": "Deny",
    "Action": [
        "kms:Encrypt",
        "kms:Decrypt",
        "kms:ReEncryptFrom",
        "kms:ReEncryptTo",
        "kms:GenerateDataKey",
        "kms:GenerateDataKeyWithoutPlaintext",
        "kms:DescribeKey"
    ],
    "NotResource": [
        "arn:aws:kms:*:*:alias/aws/codecommit",
        "arn:aws:kms:*:*:key/{エイリアス aws/codecommit のキーのID}"
    ],
    "Condition": {
        "BoolIfExists": {
            "aws:MultiFactorAuthPresent": "false"
        }
    }
}
```

キーの指定はエイリアスではだめで、キーIDを直接指定しないといけないようです[^3]（エイリアス `aws/codecommit` のキーのARN）。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43355/b0973bc9-78cb-dc9f-4a85-4e61a7492250.png)


## 解決

無事、Git認証情報でアクセスできるようになりました。🎉

```sh
$ git push origin test
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 24 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 262 bytes | 262.00 KiB/s, done.
Total 3 (delta 1), reused 0 (delta 0), pack-reused 0
remote: processing .
To https://git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/myapp
   27f9230..0e14615  test -> test

$ git pull origin test
From https://git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/myapp
 * branch            test       -> FETCH_HEAD
Already up to date.
```

[^1]: [git-remote-codecommit](https://docs.aws.amazon.com/ja_jp/codecommit/latest/userguide/setting-up-git-remote-codecommit.html "Setup steps for HTTPS connections to AWS CodeCommit with git-remote-codecommit") を使用すれば可能かもしれませんが、非標準ツールを使うモチベーションが無いので確認していません。
[^2]: 参照: [Git クライアントのコマンドに必要なアクセス許可](https://docs.aws.amazon.com/ja_jp/codecommit/latest/userguide/auth-and-access-control-permissions-reference.html#aa-git)、[AWS Key Management Service と AWS CodeCommit リポジトリの暗号化](https://docs.aws.amazon.com/ja_jp/codecommit/latest/userguide/encryption.html)
[^3]: 現状ではエイリアスの方を `NotResource` に書く必要は無いようです。内部動作が不明のため、一応指定しています。