MFAを強制しながらCodeCommitをgitコマンドや各種ツールから利用する

# これは

AWSのGitリポジトリサービスであるCodeCommitを利用しつつ、AWS Webコンソールログインや各種サービスの利用にはMFAを強制するための方法を記載します。

なお本内容に関してはAWSサポートにご支援頂きましたことを明記しておきます。（まずかったら消します...）

# やり方

MFAの強制を行う場合は、[AWSドキュメント](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/reference_policies_examples_aws_my-sec-creds-self-manage-mfa-only.html)に従ってIAMにポリシーを作成して割り当てるのですが、ドキュメント通りのポリシーを当ててしまうと、gitコマンドやgitを利用できる各種ツール（VSCとか）などからのCodeCommitへのアクセスも拒否されてしまいます。

そこで、ドキュメントのMFAを強制するポリシーに対し、CodeCommitの許可を追加した以下のポリシーに変更します。

```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllowViewAccountInfo",
            "Effect": "Allow",
            "Action": "iam:ListVirtualMFADevices",
            "Resource": "*"
        },
        {
            "Sid": "AllowManageOwnVirtualMFADevice",
            "Effect": "Allow",
            "Action": [
                "iam:CreateVirtualMFADevice",
                "iam:DeleteVirtualMFADevice"
            ],
            "Resource": "arn:aws:iam::*:mfa/${aws:username}"
        },
        {
            "Sid": "AllowManageOwnUserMFA",
            "Effect": "Allow",
            "Action": [
                "iam:DeactivateMFADevice",
                "iam:EnableMFADevice",
                "iam:GetUser",
                "iam:ListMFADevices",
                "iam:ResyncMFADevice"
            ],
            "Resource": "arn:aws:iam::*:user/${aws:username}"
        },
        {
            "Sid": "DenyAllExceptListedIfNoMFA",
            "Effect": "Deny",
            "NotAction": [
                "iam:CreateVirtualMFADevice",
                "iam:EnableMFADevice",
                "iam:GetUser",
                "iam:ListMFADevices",
                "iam:ListVirtualMFADevices",
                "iam:ResyncMFADevice",
                "sts:GetSessionToken",
                "iam:ChangePassword",
                "codecommit:*"
            ],
            "Resource": "*",
            "Condition": {
                "BoolIfExists": {
                    "aws:MultiFactorAuthPresent": "false"
                },
                "Null": {
                    "kms:ViaService": true
                }
            }
        }
    ]
}
```

ポイントとしては以下の2点です。

1. NotAction に "codecommit:*" を追加
* Condition に kms:ViaService 条件キーを追加

1でCodeCommit に関する操作を行う上でMFAを不要にします。
2についてはCodeCommitを利用する場合、KMSキーによる暗号化が行われるため、リポジトリに対してgitコマンドを実行する際に、KMSに対する操作が明示的に拒否されないようする必要があるとのことでした。([参考資料](https://docs.aws.amazon.com/ja_jp/codecommit/latest/userguide/encryption.html))

さらに 2 の Condition を加えることにより、AWS のサービスを通じて KMS に対するアクセスが発生する場合にステートメントの評価の対象外とする条件が追加されるため、MFA を使用しない状態でも CodeCommit へのアクセスが可能となります。

また、kms:ViaService 条件キーの指定により AWS のサービスが KMS を使用する場合のみを MFA を不要とするための条件としているため、ポリシーを付与した IAM ユーザが KMS API を直接実行する場合は引き続き MFA が必要となります。


これでMFAを強制したまま快適なCodeCommitライフを送ることができますね！

補足： 実際には上記の他にCodeCommitを利用するための権限や、ssh鍵を登録する権限なども必要です。

* AWSCodeCommitReadOnly(またはPowerUser?Admin?)
* IAMUserSSHKeys

## 余談、最初はトラブった

対象システムが構築期間中だったこともあり、設定当初はドキュメントのポリシーそのまま流用し、いくつかの簡単な確認してサクッとポリシー適用によりMFAを強制しました。
すると、、、しばらくして開発メンバーから「Gitが使えなくなった！」と悲鳴が上がり、慌ててMFA強制ポリシーを解除しました。

## 参考資料

* [AWS: MFA で認証された IAM ユーザーが [My Security Credentials (セキュリティ認証情報)] ページで自分の MFA デバイスを管理できるようにします。](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/reference_policies_examples_aws_my-sec-creds-self-manage-mfa-only.html)
* [AWS Key Management Service および AWS CodeCommit リポジトリの暗号化](https://docs.aws.amazon.com/ja_jp/codecommit/latest/userguide/encryption.html)
* [IAM のサインインページでの MFA デバイスの使用](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/console_sign-in-mfa.html)