Search code examples
amazon-web-servicesaws-codecommitmulti-factor-authentication

AWS CodeCommit With Multi-factor Authentication. Keep getting fatal: unable to access .. The requested URL returned error: 403


What's the Problem?

My IAM User has two policies: AdministratorAccess and ForceMultiFactorAuthentication. When ForceMultiFactorAuthentication policy is attached, from the Windows command-line, I get 403 errors when trying to do anything to the repository (ex: git clone ..). When I remove the policy, I can work with the repo (ex: git clone works).

My Question

Is there something about my ForceMultiFactorAuthentication policy that is preventing codecommit from working? How do I properly setup CodeCommit with Multi-factor authentication?

General Recreation Steps

  1. Create an IAM user group named "Admins" with AdministratorAccess and ForceMultiFactorAuthentication permissions
  2. Create a non-root IAM user
  3. Add non-root IAM user to "Admins" group
  4. Logged in as non-root IAM user, on Security Credentials tab, setup MFA auth (scan QR code, etc.), AND create HTTPS Git credentials for AWS CodeCommit
  5. Create a repo in CodeCommit
  6. From command-line, attempt git clone https://git-codecommit... locally
  7. Command-line returns fatal: unable to access 'https://git-codecommit...': The requested URL returned error: 403
  8. My non-root IAM user removes ForceMultiFactorAuthentication policy from "Admins" group
  9. git clone .. and it clones the repo. It works.

Doesn't make sense because...

My IAM user has AdministratorAccess. Plus, policy summary shows CodeCommit has full access to all resources.


My ForceMultiFactorAuthentication policy is below (and is very similar to AWS-provided one):

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllowViewAccountInfo",
            "Effect": "Allow",
            "Action": [
                "iam:GetAccountPasswordPolicy",
                "iam:GetAccountSummary",
                "iam:ListVirtualMFADevices",
                "iam:ListUsers"
            ],
            "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": "AllowManageOwnSigningCertificates",
            "Effect": "Allow",
            "Action": [
                "iam:DeleteSigningCertificate",
                "iam:ListSigningCertificates",
                "iam:UpdateSigningCertificate",
                "iam:UploadSigningCertificate"
            ],
            "Resource": "arn:aws:iam::*:user/${aws:username}"
        },
        {
            "Sid": "AllowManageOwnSSHPublicKeys",
            "Effect": "Allow",
            "Action": [
                "iam:DeleteSSHPublicKey",
                "iam:GetSSHPublicKey",
                "iam:ListSSHPublicKeys",
                "iam:UpdateSSHPublicKey",
                "iam:UploadSSHPublicKey"
            ],
            "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",
                "iam:DeleteVirtualMFADevice"
            ],
            "Resource": "arn:aws:iam::*:mfa/${aws:username}"
        },
        {
            "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",
                "iam:ListUsers"
            ],
            "Resource": "*",
            "Condition": {
                "BoolIfExists": {
                    "aws:MultiFactorAuthPresent": "false"
                }
            }
        }
    ]
}

Solution

  • The following section in your ForceMultiFactorAuthentication policy deny all requests (except the actions mentioned in the NotAction section) that are not authenticated using MFA

    {
                "Sid": "DenyAllExceptListedIfNoMFA",
                "Effect": "Deny",
                "NotAction": [
                    "iam:CreateVirtualMFADevice",
                    "iam:EnableMFADevice",
                    "iam:GetUser",
                    "iam:ListMFADevices",
                    "iam:ListVirtualMFADevices",
                    "iam:ResyncMFADevice",
                    "sts:GetSessionToken",
                    "iam:ListUsers"
                ],
                "Resource": "*",
                "Condition": {
                    "BoolIfExists": {
                        "aws:MultiFactorAuthPresent": "false"
                    }
                }
            }
    

    With HTTPS GIT credentials, you are authenticating to the CodeCommit repository using the username & password. There is no usage of session token (basically MFA code). So it is not possible to validate MFA for authentication. As a result your request is denied. Similar is the case with SSH key pair authentication for CodeCommit.

    To fix this you can add required codecommit actions in the NotAction list of the policy. You need to include kms actions as well. Because data in CodeCommit repositories is encrypted in transit and at rest. So permission required for encrypt and decrypt actions while you are performing clone, pull or push activities from/to repos.

    The following policy fix your CodeCommit 403 error.

    {
                "Sid": "DenyAllExceptListedIfNoMFA",
                "Effect": "Deny",
                "NotAction": [
                    "iam:CreateVirtualMFADevice",
                    "iam:EnableMFADevice",
                    "iam:GetUser",
                    "iam:ListMFADevices",
                    "iam:ListVirtualMFADevices",
                    "iam:ResyncMFADevice",
                    "sts:GetSessionToken",
                    "iam:ListUsers",
                    "codecommit:GitPull",
                    "codecommit:GitPush",
                    "kms:Encrypt",
                    "kms:Decrypt",
                    "kms:GenerateDataKey",
                    "kms:GenerateDataKeyWithoutPlaintext",
                    "kms:DescribeKey"
    
                ],
                "Resource": "*",
                "Condition": {
                    "BoolIfExists": {
                        "aws:MultiFactorAuthPresent": "false"
                    }
                }
            }
    

    Since you have already attached Administrator access policy to your user, you don't require the entire content of ForceMultiFactorAuthentication policy. The above policy is sufficient. If you want to enable the MFA restriction for all IAM users(non-admin users), use entire content of your policy attach it to users.