一、背景
本文描述了如何使用Server Side Encryption – KMS方式对S3存储桶的文件加密,并测试解密和访问。
二、创建KMS CMK
点击KMS,点击Customer managed keys
,点击创建。如下截图。
在向导第一步,点击配置key,选择Symmetric
对称加密,在下方的高级选项中,选择密钥的源是KMS
,点击右下角下一步继续。如下截图。
在向导第二步,输入密钥的别名(Alias),在本账户内需要唯一,例如输入s3demo01
,在描述部分输入备注信息,点击下一步继续。
在第三步设置权限位置,从右侧类型中,找到类型是User的表示是IAM账户,在下方选中允许管理员删除Key的选项。点击下一步继续。如下截图。
在向导的下一个界面,选择有权限使用Key的位置,选择当前用户。将页面滚动到最下方,点击下一步继续。如下截图。
在配置参数review界面,不需要修改任何内容,点击创建即可完成。如下截图。
KMS提示创建成功。如下截图。
三、对存储桶启用默认加密
进入S3服务界面,点击创建存储桶。
在创建存储桶的界面上,输入存储桶名称,选择本次实验正确的区域,并选中组织所有公开访问的选项。接下来向下滚动屏幕。如下截图。
在创建S3桶的页面的下半部分,选择启用服务器端加密,选择密钥类型是KMS管理的密钥(SSE-KMS)。在KMS密钥中选择第二个选项“从密钥中选择”,然后在下拉框中找到本实验前一步创建的密钥别名是 s3demo01
,选中这个密钥,然后在下方选中本存储桶密钥的位置是启用。如下截图。
继续向下滚动页面,在高级设置部分,保持默认值不变(默认是Disable禁用)。然后点击右下角创建存储桶。
创建存储桶成功后,点击存储桶的名字进入。点击第二个标签页属性,并将页面向下滚动。如下截图。
在存储桶的默认加密位置,可以看到存储桶默认已经启用了KMS加密。
至此存储桶的配置完成。
四、创建S3只读权限的IAM用户和并赋予KMS使用权限
1、创建S3只读权限的IAM用户
进入IAM模块,点击左侧用户,点击右侧创建用户。
在用户名位置输入s3read
,在访问类型位置选择编程访问
,也就是只有API访问,不能登陆WEB界面控制台。点击下一步继续。如下截图。
在配置权限界面,点击右侧第三个图标直接挂载权限。在搜索框中输入S3,在下方从搜索结果中选中S3Readonly这一条,然后点击下一步继续。
点击下一步标签继续。可跳过不用输入。如下截图。
点击创建用户,完成创建。
点击查看密钥,或者点击Download.csv下载到本地可获取密码。注意密码只能获取一次,后续就无法再查看了。如下截图。
2、赋予KMS使用权限
进入KMS模块,点击客户管理的密钥,点击山实验前一步创建的密钥。如下截图。
在密钥详情界面,请复制下来密钥的ARN,下边测试中将会使用。接下来向下滚动页面。如下截图。
向下滚动鼠标,找到密钥用户,点击添加按钮。
将上一步生成的用户加入到密钥使用者清单中。
设置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控制台,进入对应的存储桶,找到这个文件,点击文件名查看详情。如下截图。
将页面向下滚动后,可以看到文件已经是被加密成功。
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公开访问直接托管文件。如果被加密文件直接公开,则因为没有密钥将会被拒绝访问。下面将验证整个过程。
进入存储桶界面,点击权限,找到下方的阻止公有访问。如下截图。
保持所有选项都是没有选中状态。点击保存。如下截图。
现在进入到S3存储桶内的单个文件。从操作下拉框中,选择公开访问。如下截图。
设置为公开后,访问这个文件的公开地址。如下截图。
实测可看到,加密的文件即便设置为公开状态,也是不能通过浏览器访问的,必须通过程序访问。
至此实验完成。
六、小结
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/