使用KMS对S3存储桶进行加密

一、背景

本文描述了如何使用Server Side Encryption – KMS方式对S3存储桶的文件加密,并测试解密和访问。

二、创建KMS CMK

点击KMS,点击Customer managed keys,点击创建。如下截图。

image-20210401185023048

在向导第一步,点击配置key,选择Symmetric对称加密,在下方的高级选项中,选择密钥的源是KMS,点击右下角下一步继续。如下截图。

image-20210401185133320

在向导第二步,输入密钥的别名(Alias),在本账户内需要唯一,例如输入s3demo01,在描述部分输入备注信息,点击下一步继续。

image-20210401185331956

在第三步设置权限位置,从右侧类型中,找到类型是User的表示是IAM账户,在下方选中允许管理员删除Key的选项。点击下一步继续。如下截图。

image-20210401185744182

在向导的下一个界面,选择有权限使用Key的位置,选择当前用户。将页面滚动到最下方,点击下一步继续。如下截图。

image-20210401200456701

在配置参数review界面,不需要修改任何内容,点击创建即可完成。如下截图。

image-20210401200610815

KMS提示创建成功。如下截图。

image-20210401200636897

三、对存储桶启用默认加密

进入S3服务界面,点击创建存储桶。

在创建存储桶的界面上,输入存储桶名称,选择本次实验正确的区域,并选中组织所有公开访问的选项。接下来向下滚动屏幕。如下截图。

image-20210401200820876

在创建S3桶的页面的下半部分,选择启用服务器端加密,选择密钥类型是KMS管理的密钥(SSE-KMS)。在KMS密钥中选择第二个选项“从密钥中选择”,然后在下拉框中找到本实验前一步创建的密钥别名是 s3demo01,选中这个密钥,然后在下方选中本存储桶密钥的位置是启用。如下截图。

image-20210401200951965

继续向下滚动页面,在高级设置部分,保持默认值不变(默认是Disable禁用)。然后点击右下角创建存储桶。

image-20210401201147504

创建存储桶成功后,点击存储桶的名字进入。点击第二个标签页属性,并将页面向下滚动。如下截图。

image-20210401201311156

在存储桶的默认加密位置,可以看到存储桶默认已经启用了KMS加密。

image-20210401201350429

至此存储桶的配置完成。

四、创建S3只读权限的IAM用户和并赋予KMS使用权限

1、创建S3只读权限的IAM用户

进入IAM模块,点击左侧用户,点击右侧创建用户。

在用户名位置输入s3read,在访问类型位置选择编程访问,也就是只有API访问,不能登陆WEB界面控制台。点击下一步继续。如下截图。

image-20210403114224291

在配置权限界面,点击右侧第三个图标直接挂载权限。在搜索框中输入S3,在下方从搜索结果中选中S3Readonly这一条,然后点击下一步继续。

image-20210403114354813

点击下一步标签继续。可跳过不用输入。如下截图。

image-20210403114622552

点击创建用户,完成创建。

image-20210403114706429

点击查看密钥,或者点击Download.csv下载到本地可获取密码。注意密码只能获取一次,后续就无法再查看了。如下截图。

image-20210403114745562

2、赋予KMS使用权限

进入KMS模块,点击客户管理的密钥,点击山实验前一步创建的密钥。如下截图。

image-20210403120017380

在密钥详情界面,请复制下来密钥的ARN,下边测试中将会使用。接下来向下滚动页面。如下截图。

image-20210403120303150

向下滚动鼠标,找到密钥用户,点击添加按钮。

image-20210403120100658

将上一步生成的用户加入到密钥使用者清单中。

image-20210403120140783

设置IAM用户完成。

3、使用IAM Policy编辑器快速设置一个最小权限用户(本步骤可选,推荐跳过)

上文使用的是图形界面的AWS控制台创建一个新配置用户,并通过KMS控制台为用户赋予权限。如果您是AWS用户并且具有IAM使用经验,还可以使用如下IAM策略替代以上图形界面的操作,即可创建一个最小权限的用户。

{
"Version": "2012-10-17",
"Statement": [
  {
    "Sid": "VisualEditor0",
    "Effect": "Allow",
    "Action": [
      "kms:Decrypt",
      "s3:GetObject"
    ],
    "Resource": [
      "arn:aws:kms:example-region-1:123456789012:key/example-key-id",
      "arn:aws:s3:::DOC-EXAMPLE-BUCKET/*"
    ]
  }
]
}

五、加密存储桶的读写测试

本文将进行两个测试,先使用管理员身份写入一个文件,确认其是处于加密状态。在使用上文创建的S3只读用户读取加密数据。

环境需要Python3,安装完毕Python3后请安装boto3库,使用如下命令即可安装完毕。

pip3 install boto3

为了测试上传下载,请将要上传的文件和python脚本放到同一个路径下。

1、使用管理员权限上传文件到S3,并验证加密

构建s3PutObject.py ,并替换其中的密钥为管理员对应的AccessKey,拥有写入S3权限。然后执行这段Python代码。

#
# Check Boto3 API Document here:
# https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/s3.html#s3
#

import boto3

from botocore.config import Config
my_config = Config(
  region_name = 'cn-northwest-1',
  signature_version = 's3v4'
)

client = boto3.client(
  's3',
  config=my_config,
  aws_access_key_id='XXXXXXXXXXXXXXXXXX',
  aws_secret_access_key='XXXXXXXXXXXXXXXXXXXXXXXXXX'
)

BucketName = 'kms-s3-demo-01'
LocalFileName = "image.jpg"
FileData = open(LocalFileName, 'rb')

client = boto3.client('s3')
response = client.put_object(
  ACL = 'private',
  Body = FileData,
  Bucket = BucketName,
  Key = "image.jpg",
  ContentType = 'image/jpeg',
  StorageClass = 'INTELLIGENT_TIERING'
)

执行后没有任何输出信息就是写入成功。

进入S3控制台,进入对应的存储桶,找到这个文件,点击文件名查看详情。如下截图。

image-20210403122440332

将页面向下滚动后,可以看到文件已经是被加密成功。

image-20210403122507798

2、使用只读用户读取加密文件

构建s3GetObject.py ,并替换其中的AccessKey为前一步创建的只读IAM用户的密钥。

#
# Check Boto3 API Document here:
# https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/s3.html#s3
#

import boto3

from botocore.config import Config
my_config = Config(
  region_name = 'cn-northwest-1',
  signature_version = 's3v4'
)

client = boto3.client(
  's3',
  config=my_config,
  aws_access_key_id='XXXXXXXXXXXXXXXXXX',
  aws_secret_access_key='XXXXXXXXXXXXXXXXXXXXXXXXXX'
)

BucketName = 'kms-s3-demo-01'
filename = 'image.jpg'

response = client.get_object(
  Bucket = BucketName,
  Key = filename,
)

print(response)

执行后,可以看到返回如下信息,表示文件解密和访问成功。

$ /usr/local/bin/python3 /Users/lxy/Documents/AWS/MyWorkshop/KMS-S3/s3get.py
{'ResponseMetadata': {'RequestId': 'TQPTTYC15W9F3XSQ', 'HostId': 'WdxbZHyb2gm9eToxzomiJ9Twb76XrBywMDiPYc0JEZYv2M++vv96PRZ96GZK5jY764ax3v/2KpY=', 'HTTPStatusCode': 200, 'HTTPHeaders': {'x-amz-id-2': 'WdxbZHyb2gm9eToxzomiJ9Twb76XrBywMDiPYc0JEZYv2M++vv96PRZ96GZK5jY764ax3v/2KpY=', 'x-amz-request-id': 'TQPTTYC15W9F3XSQ', 'date': 'Sat, 03 Apr 2021 04:29:40 GMT', 'last-modified': 'Sat, 03 Apr 2021 04:22:55 GMT', 'etag': '"8a97f0211a38ad5d712789a2dc7c1720"', 'x-amz-storage-class': 'INTELLIGENT_TIERING', 'x-amz-server-side-encryption': 'aws:kms', 'x-amz-server-side-encryption-aws-kms-key-id': 'arn:aws-cn:kms:cn-northwest-1:420029960748:key/001148dd-37f8-45de-8425-aaaaaf57b0c0', 'x-amz-server-side-encryption-bucket-key-enabled': 'true', 'accept-ranges': 'bytes', 'content-type': 'image/jpeg', 'content-length': '225121', 'server': 'AmazonS3'}, 'RetryAttempts': 0}, 'AcceptRanges': 'bytes', 'LastModified': datetime.datetime(2021, 4, 3, 4, 22, 55, tzinfo=tzutc()), 'ContentLength': 225121, 'ETag': '"8a97f0211a38ad5d712789a2dc7c1720"', 'ContentType': 'image/jpeg', 'ServerSideEncryption': 'aws:kms', 'Metadata': {}, 'SSEKMSKeyId': 'arn:aws-cn:kms:cn-northwest-1:420029960748:key/001148dd-37f8-45de-8425-aaaaaf57b0c0', 'BucketKeyEnabled': True, 'StorageClass': 'INTELLIGENT_TIERING', 'Body': <botocore.response.StreamingBody object at 0x1102bb9a0>}

3、存储桶公开测试

使用了KMS加密后,就意味着不能使用S3公开访问直接托管文件。如果被加密文件直接公开,则因为没有密钥将会被拒绝访问。下面将验证整个过程。

进入存储桶界面,点击权限,找到下方的阻止公有访问。如下截图。

image-20210403123350719

保持所有选项都是没有选中状态。点击保存。如下截图。

image-20210403123512617

现在进入到S3存储桶内的单个文件。从操作下拉框中,选择公开访问。如下截图。

image-20210403123550715

设置为公开后,访问这个文件的公开地址。如下截图。

image-20210403123630696

实测可看到,加密的文件即便设置为公开状态,也是不能通过浏览器访问的,必须通过程序访问。

image-20210403123659992

至此实验完成。

六、小结

S3不仅是合规、审计要求的体现,更是在IAM权限策略之外,为S3添加了第二层保护。只有同时满足IAM授权和KMS加解密授权的应用才能接入S3,由此大大提高了安全性。

参考文档:

https://docs.aws.amazon.com/zh_cn/AmazonS3/latest/userguide/UsingKMSEncryption.html
https://aws.amazon.com/cn/premiumsupport/knowledge-center/decrypt-kms-encrypted-objects-s3/