Search code examples
amazon-web-servicesdevopsamazon-kms

Accessing an KMS encrypted Bucket with an Alias


Suppose I have a bucket that is encrypted with a KMS key, the KMS key policy is like so

    {
      "Effect" : "Allow",
      "Principal" : {
        "AWS" : "arn:aws:iam:::my_role_here"
      },
      "Action" : [
        "kms:Encrypt",
        "kms:Decrypt",
        "kms:ReEncrypt*",
        "kms:GenerateDataKey*",
        "kms:DescribeKey"
      ],
      "Resource" : "arn:aws:kms:::long_kms_id",
      "Condition": {
         "StringLike": {
            "kms:RequestAlias": "alias/my_kms_alias"
            }
       } 
    }

And the policy for my IAM role is

        {
            "Sid": "AllowUseOfKmsKey",
            "Effect": "Allow",
            "Action": [
                "kms:Decrypt",
                "kms:DescribeKey",
                "kms:Encrypt",
                "kms:GenerateDataKey*",
                "kms:ReEncrypt*"
            ],
            "Resource": "*",
            "Condition": {
                "StringLike": {
                    "kms:RequestAlias": "alias/my_kms_alias"
                }
            }
        }

However when I do a PUT operation, I get an access denied: An error occurred (AccessDenied) when calling the PutObject operation: Access Denied. However this works if I remove the Condition on the IAM role policy.

I've ben following this doc, but nothing seems to work or explained clearly. How do I ensure that the role that I want to access my S3 bucket is able to access it if I gave it a KMS alias?


Solution

  • As @Marcin pointed you don't need to have it on both, Key policy and Role policy.
    If you want to use this key into another account, then it is better to have the policy on Key.

    As the documentation you provided explain, when you use kms:RequestAlias the request user does needs to be explicit to use alias.

    See my example below. My Key policy allow everything from my account.

    {
        "Version": "2012-10-17",
        "Id": "key-default-1",
        "Statement": [
            {
                "Sid": "Enable IAM User Permissions",
                "Effect": "Allow",
                "Principal": {
                    "AWS": "arn:aws:iam::123412341234:root"
                },
                "Action": "kms:*",
                "Resource": "*"
            }
        ]
    }
    

    But my role doesn't have any allow statement to use this key, so it will fail.

    $ aws s3api put-object --bucket mybucket --key key1 --body ./test.txt --ssekms-key-id arn:aws:kms:us-east-1:123412341234:key/66053e20-c9e6-4df9-901a-c6aed5e51ea5 --server-side-encryption "aws:kms" --region us-east-1
    
    An error occurred (AccessDenied) when calling the PutObject operation: Access Denied
    

    I added the policy below into my role.

    {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Effect": "Allow",
                "Action": [
                    "kms:Decrypt",
                    "kms:GenerateDataKey*",
                    "kms:DescribeKey"
                ],
                "Resource": "*",
                "Condition": {
                    "StringLike": {
                        "kms:RequestAlias": "alias/test-leo"
                    }
                }
            }
        ]
    }
    

    Now I will force to use my Key (not alias). It will also fail, because I am not using alias, I am using Key.

    $ aws s3api put-object --bucket mybucket --key key2 --body ./test.txt --ssekms-key-id arn:aws:kms:us-east-1:123412341234:key/66053e20-c9e6-4df9-901a-c6aed5e51ea5 --server-side-encryption "aws:kms" --region us-east-1
    
    An error occurred (AccessDenied) when calling the PutObject operation: Access Denied
    

    When you look at CloudTrail you will see an error trail like below:

    "eventTime": "2021-05-26T13:42:24Z",
    "eventSource": "kms.amazonaws.com",
    "eventName": "GenerateDataKey",
    "awsRegion": "us-east-1",
    "sourceIPAddress": "AWS Internal",
    "userAgent": "AWS Internal",
    "errorCode": "AccessDenied",
    "errorMessage": "User: arn:aws:sts::123412341234:assumed-role/myrole/i-12adc5581f1a9b9dd is not authorized to perform: kms:GenerateDataKey on resource: arn:aws:kms:us-east-1:123412341234:key/66053e20-c9e6-4df9-901a-c6aed5e51ea5",
    

    Now I will force to use my Key Alias (not key ARN). It works because I am using the key alias ARN on command.

    $ aws s3api put-object --bucket mybucket --key key3 --body ./test.txt --ssekms-key-id arn:aws:kms:us-east-1:123412341234:alias/test-leo --server-side-encryption "aws:kms" --region us-east-1
    {
        "SSEKMSKeyId": "arn:aws:kms:us-east-1:123412341234:key/66053e20-c9e6-4df9-901a-c6aed5e51ea5",
        "ETag": "\"ab544583c58d325231bb7b11e8472a1b\"",
        "ServerSideEncryption": "aws:kms"
    }