一、背景
在使用AWS Config服务开启内置规则、对本账号进行诊断的时候,可能会发现有一条规则是提示S3存储桶的Bucket Key功能没有打开,这会带来成本影响。这个选项是什么意思呢?本文讲解如何启用这个选项。
S3存储桶的加密方式有SSE-S3、KMS、Dual Layer KMS三种。在这三种加密机制使用场景下,有一个名为Bucket Key的功能,与加密场景密切相关。当不使用Bucket Key时候,每次对S3存储桶的读写调用都需要访问KMS,这样带来KMS的大量请求费用。当开启Bucket Key的功能后,由S3服务管理一个短期有效的密钥并在S3服务层面缓存,日常调用存储桶的读写,将不需要访问KMS,而是使用这个Bucket key。当Bucket Key过期后,自动与KMS服务交互重新生成新的Key。由此,即可节约99%的KMS费用。
在创建S3存储桶时候,页面会询问存储加密类型,以及是否打开Bucket Key。如果本账号已经有大量的存储桶,且分别使用了不同的加密规则,但是一些存储桶创建时候没有打开Bucket Key功能,那么如何快速为所有存储桶打开Bucket Key?在AWS控制台上一个个点击存储桶的过程会非常麻烦没有效率,因此推荐编写Python脚本完成这个配置。
另外在编写脚本的过程中可发现,这几个加密选项在AWS控制台上以及API上看上去的名字是不同的,API层面的标签如下:
- 控制台网页上的SSE-S3: 在API层面的标签是
AES256
,也就是默认使用的加密算法 - 控制台网页上的SSE-KMS:在API层面的标签是
aws:kms
,表示密钥由KMS管理 - 控制台网页上的Dual-Layer SSE-KMS:在在API层面的标签是
aws:kms:dsse
,表示双层KMS级别的加密
这样就可以把本存储桶的加密类型和API调用类型对应起来了。
二、Python脚本
使用Python脚本需要事先安装好Python语言的AWS SDK,即Boto3。命令如下:
pip install boto3
然后编写如下文件:
import boto3
profile_name = 'bjs'
# 定义设置bucket key的函数
def enable_default_encryption_for_buckets(bucket_name,SSEAlgorithm):
print("Set bucket key to enabled...")
# 创建新的加密配置
new_encryption = {
'Rules': [
{
'ApplyServerSideEncryptionByDefault': {
'SSEAlgorithm': SSEAlgorithm # 输入值 AES256代表SSE-S3 或 aws:kms代表KMS
},
'BucketKeyEnabled': True
}
]
}
# 设置新的加密配置
s3_client.put_bucket_encryption(
Bucket=bucket_name,
ServerSideEncryptionConfiguration=new_encryption
)
return("Bucket key is enabled for bucket: " + bucket_name)
# 主函数
if __name__ == "__main__":
session = boto3.Session(profile_name=profile_name)
s3_client = session.client('s3')
response = s3_client.list_buckets()
# 遍历每个存储桶
for bucket in response['Buckets']:
bucket_name = bucket['Name']
print(f"Bucket: {bucket_name}")
# 获取当前存储桶的现有加密配置
encryption_response = s3_client.get_bucket_encryption(Bucket=bucket_name)
encryption_type = encryption_response["ServerSideEncryptionConfiguration"]["Rules"][0]["ApplyServerSideEncryptionByDefault"]["SSEAlgorithm"]
bucket_key_enabled = encryption_response["ServerSideEncryptionConfiguration"]["Rules"][0]["BucketKeyEnabled"]
print("Type:", encryption_type, "| BucketKey:", bucket_key_enabled)
# 跳过已经开启Bucket Key的存储桶,如果没起开启的,则打开
if bucket_key_enabled == True:
print("skipping")
else:
print("Updating...")
# 打开存储桶Bucket Key,加密类型保持现有的不变
enable_default_encryption_for_buckets(bucket_name,encryption_type)
print("")
注意,以上代码还使用了Profile配置,这是因为在开发者本机上,可能有使用AWSCLI配置多个Profile,分别用不同的AKSK连接不同的Region。参考这篇博客。那么这里可以指定要使用的Profile,确认Profile名字与~/.aws/config
文件中的相同,即可使用对应的AKSK调用对应的Region。
执行后返回结果类似如下:
Bucket: appstream-logs-ap-northeast-1-0123456789023-cdjyw6pg
Type: aws:kms | BucketKey: False
Updating...
Set bucket key to enabled...
Bucket: aws-athena-query-results-0123456789023-us-east-1
Type: AES256 | BucketKey: False
Updating...
Set bucket key to enabled...
Bucket: aws-athena-query-results-0123456789023-us-west-2
Type: AES256 | BucketKey: True
skipping
三、参考文档
https://docs.aws.amazon.com/AmazonS3/latest/userguide/bucket-key.html