Techfirm Cloud Architect Blog

テックファーム株式会社クラウドインフラグループのブログ

IAMユーザーでMFA強制とするが、CodeCommitはMFA認証の対象外とする方法

はじめに

以前、IAMユーザーにMFA強制させる方法について書きました。

CodeCommitを利用する場合、Git認証はAWS CodeCommit の HTTPS Git 認証情報を利用し、GitクライアントにID/パスワード設定する使い方が多数派ではないかと思います。
※git-remote-codecommit(GRC)を使ったIAM認証はIDEが対応していなかったりするため
ここでMFA強制している問題として、上記のAWS CodeCommit の HTTPS Git 認証情報が拒否されてしまいます。
そのため、今回はIAMユーザーにMFA強制させつつも、Gitクライアントからの操作はMFA対象外にする手順について記載します。

手順

事前準備

前回記事で作成した、IAMポリシーforced-mfa-and-my-sec-creds-self-manageとIAMユーザーtestを流用します。

IAMユーザーtestがCodeCommitの操作が行えるようIAMポリシー(AWS管理)AWSCodeCommitPowerUserを追加します。
IAMポリシー

CodeCommitにテスト用のリポジトリtest-codecommitを作成しておきます。
CodeCommit

この時点でGitクライアントからgit cloneすると以下のエラー(MFAなし)になります。

$ git clone https://git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/test-codecommit
Cloning into 'test-codecommit'...
fatal: unable to access 'https://git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/test-codecommit/': The requested URL returned error: 403

※Gitクライアントから初回アクセスの場合はクレデンシャルを入力します
Git認証画面

以下、CloudTrailのイベント履歴も確認してみるとgit cloneはAWS側ではGitPullアクションとして失敗しています。

{
    "eventVersion": "1.08",
    "userIdentity": {
        "type": "IAMUser",
        "principalId": "hogehoge",
        "arn": "arn:aws:iam::<AWSアカウントID>:user/test",
        "accountId": "<AWSアカウントID>",
        "userName": "test"
    },
    "eventTime": "2023-11-02T04:25:46Z",
    "eventSource": "codecommit.amazonaws.com",
    "eventName": "GitPull",
    "awsRegion": "ap-northeast-1",
    "sourceIPAddress": "hogehoge",
    "userAgent": "git/2.41.0.windows.1",
    "errorCode": "InternalFailure",
    "requestParameters": null,
    "responseElements": null,
    "additionalEventData": {
        "protocol": "HTTP",
        "dataTransferred": false,
        "repositoryName": "test-codecommit"
    },
    "requestID": "hogehoge",
    "eventID": "hogehoge",
    "readOnly": true,
    "resources": [
        {
            "accountId": "<AWSアカウントID>",
            "type": "AWS::CodeCommit::Repository",
            "ARN": "arn:aws:codecommit:ap-northeast-1:<AWSアカウントID>:test-codecommit"
        }
    ],
    "eventType": "AwsApiCall",
    "managementEvent": true,
    "recipientAccountId": "<AWSアカウントID>",
    "eventCategory": "Management"
}

IAMポリシーの修正

IAMポリシーforced-mfa-and-my-sec-creds-self-manageを以下のように修正します。
Sid-DenyAllExceptListedIfNoMFANotActioncodecommit:*Conditionkms:ViaServiceを追加します。
kms:ViaServiceの部分がポイントで、AWSサービスからのKMS操作も、MFA強制から除外しています。
これはAWS Key Management Service と AWS CodeCommit リポジトリの暗号化にも記載がある通り「CodeCommitは、デフォルトのaws/codecommitキーに対して、AWS KMSアクションを実行します」により、CodeCommitの裏側でKMSによる暗号化を行っているためです。

許可が必要なアクションはGit クライアントのコマンドに必要なアクセス許可を参考にします。
今回は記載しませんが、mainブランチへの操作は特定の人だけに制限する等、実運用ポリシーに合わせて設定できます。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllowViewAccountInfo",
            "Effect": "Allow",
            "Action": [
                "iam:GetAccountPasswordPolicy",
                "iam:ListVirtualMFADevices"
            ],
            "Resource": "*"
        },
        {
            "Sid": "AllowManageOwnPasswords",
            "Effect": "Allow",
            "Action": [
                "iam:ChangePassword",
                "iam:GetUser"
            ],
            "Resource": "arn:aws:iam::*:user/${aws:username}"
        },
        {
            "Sid": "AllowManageOwnAccessKeys",
            "Effect": "Allow",
            "Action": [
                "iam:CreateAccessKey",
                "iam:DeleteAccessKey",
                "iam:ListAccessKeys",
                "iam:UpdateAccessKey"
            ],
            "Resource": "arn:aws:iam::*:user/${aws:username}"
        },
        {
            "Sid": "AllowManageOwnGitCredentials",
            "Effect": "Allow",
            "Action": [
                "iam:CreateServiceSpecificCredential",
                "iam:DeleteServiceSpecificCredential",
                "iam:ListServiceSpecificCredentials",
                "iam:ResetServiceSpecificCredential",
                "iam:UpdateServiceSpecificCredential"
            ],
            "Resource": "arn:aws:iam::*:user/${aws:username}"
        },
        {
            "Sid": "AllowManageOwnVirtualMFADevice",
            "Effect": "Allow",
            "Action": [
                "iam:CreateVirtualMFADevice"
            ],
            "Resource": "arn:aws:iam::*:mfa/*"
        },
        {
            "Sid": "AllowManageOwnUserMFA",
            "Effect": "Allow",
            "Action": [
                "iam:DeactivateMFADevice",
                "iam:EnableMFADevice",
                "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",
                "codecommit:*"
            ],
            "Resource": "*",
            "Condition": {
                "Null": {
                    "kms:ViaService": "true"
                },
                "BoolIfExists": {
                    "aws:MultiFactorAuthPresent": "false"
                }
            }
        }
    ]
}

動作確認

最後にMFAなしでGitクライアントから利用できることを確認します。

$ git clone https://git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/test-codecommit
Cloning into 'test-codecommit'...
warning: You appear to have cloned an empty repository.

$ cd test-codecommit/
$ echo test > README.md

$ git add README.md 
warning: in the working copy of 'README.md', LF will be replaced by CRLF the next time Git touches it

$ git commit -m "first commit"
[master (root-commit) dd6560b] first commit
 1 file changed, 1 insertion(+)
 create mode 100644 README.md

$ git push origin master
Enumerating objects: 3, done.
Counting objects: 100% (3/3), done.
Writing objects: 100% (3/3), 221 bytes | 221.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
remote: Validating objects: 100%
To https://git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/test-codecommit
 * [new branch]      master -> master

AWSマネジメントコンソール上でもpushしたファイルが確認できます。
CodeCommit-Test

おわりに

今回はCodeCommitをMFAの対象外としましたが、他AWSサービスをMFAの対象外とする場合も同様の流れで実現できます。
小ネタでしたが、誰かのお役に立てばと思います。