Rubiooo
Rubiooo

Reputation: 11

how to upload files to s3 with server side encryption enabled by custom kms key

created 2 new kms key:

custom-client-side-encrypt-kms-key. (encrypt file on client side);
custom-server-side-encrypt-kms-key. (enable S3 server side encryption)

created new user:

test-user-encrypt

gave the user access to key and bucket; set up new key policy to allow user to use the key

  1. ran command(new user credential, with key id options)
 aws s3api put-object --body newFile --bucket <bucket-name> --key inbound/newFile --server-side-encryption aws:kms --ssekms-key-id newKeyId

error: when calling the PutObject operation: Access Denied

  1. ran command (new user credential, without key id options)
aws s3api put-object --body newFile --bucket <bucket-name> --key inbound/newFile --server-side-encryption aws:kms 

it works, but the object was encrypted with AWS managed default kms key

based on the above test, it seems the user has correct permissions to S3, but kms key permission was not correct.

here is my policies in brief:

key policy

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "Enable IAM User Permissions",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::xxxxxxid:root"
            },
            "Action": "kms:*",
            "Resource": "*"
        },
        {
            "Sid": "Allow use of the key",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::xxxxxxid:user/test_user_encrypt"
            },
            "Action": [
                "kms:ReEncrypt",
                "kms:GenerateDataKey",
                "kms:Encrypt",
                "kms:DescribeKey",
                "kms:Decrypt"
            ],
            "Resource": "*",
            "Condition": {
                "ForAnyValue:IpAddress": {
                    "aws:SourceIp": [
                        "xx.xx.xx.xx",(IP addresses allowed)
                        "xx.xx.xx.xx",
                
                    ]
                }
            }
        },
        {
            "Sid": "Allow attachment of persistent resources",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::xxxxid:user/test_user_encrypt"
            },
            "Action": [
                "kms:RevokeGrant",
                "kms:ListGrants",
                "kms:CreateGrant"
            ],
            "Resource": "*",
            "Condition": {
                "Bool": {
                    "kms:GrantIsForAWSResource": "true"
                }
            }
            "Condition": {
                "ForAnyValue:IpAddress": {
                    "aws:SourceIp": [
                        "xx.xx.xx.xx", (IP addresses allowed)  
                        "xx.xx.xx.xx",
                
                    ]
                }
            }
        }
    ]
}

IAM user policy

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "",
      "Effect": "Allow",
      "Action": [
        "kms:ReEncrypt",
        "kms:GenerateDataKey",
        "kms:Encrypt",
        "kms:DescribeKey",
        "kms:Decrypt"
      ],
      "Resource": "arn:aws:kms:<region>:xxID:key/custom-client-side-encrypt-kms-key-id",
      "Condition": {
        "ForAnyValue:IpAddress": {
          "aws:SourceIp": [
             "xx.xx.xx.xx" (IP address allowed)
          ]
        }
      }
    },
    {
      "Sid": "",
      "Effect": "Allow",
      "Action": [
        "kms:RevokeGrant",
        "kms:ReEncrypt",
        "kms:ListGrants",
        "kms:GenerateDataKey",
        "kms:Encrypt",
        "kms:DescribeKey",
        "kms:Decrypt",
        "kms:CreateGrant"
      ],
      "Resource": "arn:aws:kms:<region>:xxxID:key/<custom-server-side-encrypt-key-id>"
      "Condition": {
          "ForAnyValue:IpAddress": {
             "aws:SourceIp": [
                "xx.xx.xx.xx", (IP address allowed)
              
              ]
           }
        }
    },
    {
      "Sid": "",
      "Effect": "Allow",
      "Action": "s3:PutObject",
      "Resource": "arn:aws:s3:::bucket/inbound/*",
      "Condition": {
        "ForAnyValue:IpAddress": {
          "aws:SourceIp": [
            "xx.xxx.xxx.xx", (IP address allowed)
          
          ]
        }
      }
    },
    {
      "Sid": "",
      "Effect": "Deny",
      "Action": [
        "s3:PutObjectAcl",
        "s3:PutObject",
        "s3:ListMultipartUploadParts"
      ],
      "Resource": [
        "arn:aws:s3:::bucket/*/*/*",
        "arn:aws:s3:::bucket/*/*/",
        "arn:aws:s3:::bucket/*/"
      ]
    }
  ]
}

bucket policy

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::xxxid:user/test_user_encrypt"
            },
            "Action": "s3:PutObject",
            "Resource": "arn:aws:s3:::bucket/inbound/*",
            "Condition": {
                "ForAnyValue:IpAddress": {
                    "aws:SourceIp": [
                        "xx.xx.xx.xx", (IP address allowed)
                    
                    ]
                }
            }
        },
        {
            "Sid": "",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::xxxid:user/test_user_encrypt"
            },
            "Action": "s3:ListMultipartUploadParts",
            "Resource": "arn:aws:s3:::bucket/inbound/*",
            "Condition": {
                "ForAnyValue:IpAddress": {
                    "aws:SourceIp": [
                        "xx.xx.xx.xx", (IP address allowed)
              
                    ]
                }
            }
        },
        {
            "Sid": "DenyIncorrectEncryptKey",
            "Effect": "Deny",
            "Principal": {
                "AWS": "*"
            },
            "Action": "s3:PutObject",
            "Resource": "arn:aws:s3:::bucket/*",
            "Condition": {
                "StringNotEquals": {
                    "s3:x-amz-server-side-encryption-aws-kms-key-id": "arn:aws:kms:region:xxxid:key/custom-server-side-encrypt-kms-key-id"
                }
            }
        },
        {
            "Sid": "DenyUnEncryptedObjectUploads",
            "Effect": "Deny",
            "Principal": {
                "AWS": "*"
            },
            "Action": "s3:PutObject",
            "Resource": "arn:aws:s3:::bucket/*",
            "Condition": {
                "StringNotEquals": {
                    "s3:x-amz-server-side-encryption": "aws:kms"
                }
            }
        },
        {
            "Sid": "AllowSSLRequestsOnly",
            "Effect": "Deny",
            "Principal": {
                "AWS": "*"
            },
            "Action": "s3:*",
            "Resource": [
                "arn:aws:s3:::bucket/*",
                "arn:aws:s3:::bucket"
            ],
            "Condition": {
                "Bool": {
                    "aws:SecureTransport": "false"
                }
            }
        }
    ]
}

Upvotes: 1

Views: 1429

Answers (1)

Rubiooo
Rubiooo

Reputation: 11

I figured out. I should NOT put condition "ip range" around kms:grant permissions.

            "Condition": {
                "ForAnyValue:IpAddress": {
                    "aws:SourceIp": [
                        "xx.xx.xx.xx", (IP address allowed)
              
                    ]
                }
            }

that condition make kms:grant invalid. my guess....

after removed the condition, it works fine.

Upvotes: 0

Related Questions