删除CloudFront OAI后S3桶策略异常引发报错,如何规避?
问题背景
我有一个配置了如下策略的S3桶:
{ "Version": "2008-10-17", "Statement": [ { "Sid": "EB73SOC545AIK", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity EB73SOC545AIK" }, "Action": "s3:GetObject", "Resource": "arn:aws:s3:::mybucket-app-dev-bucket/*" } ] }
删除关联该OAI(EB73SOC545AIK)的CloudFront分发后,桶策略被自动修改为如下畸形策略:
{ "Version": "2008-10-17", "Statement": [ { "Sid": "EB73SOC545AIK", "Effect": "Allow", "Principal": { "AWS": "AIDAIHJ7YKCENOC6XHCIQ" }, "Action": "s3:GetObject", "Resource": "arn:aws:s3:::mybucket-app-dev-bucket/*" } ] }
后续用boto3追加新策略语句时(代码如下),触发MalformedPolicy错误,初期误以为是新语句问题,排查耗时:
client = boto3.client('s3') pol = client.get_bucket_policy(Bucket=bucket)['Policy'] pol = json.loads(pol) pol['Statement'].append(....) client.put_bucket_policy( Bucket=bucket, Policy=json.dumps(bucket_policy) )
请问该如何规避这一问题?
规避方案
1. 提前清理失效OAI关联策略
删除CloudFront分发前,手动移除S3桶中对应OAI的策略语句,避免AWS自动将OAI ARN替换成无效的纯IAM用户ID(如AIDAIHJ7YKCENOC6XHCIQ)。
2. 修复已存在的畸形策略
如果已经出现畸形策略,可通过代码过滤掉Principal为纯IAM用户ID的失效语句:
import json import boto3 client = boto3.client('s3') bucket = "mybucket-app-dev-bucket" # 获取并解析现有桶策略 policy_str = client.get_bucket_policy(Bucket=bucket)['Policy'] policy = json.loads(policy_str) # 过滤无效的OAI策略语句 valid_statements = [] for stmt in policy['Statement']: principal = stmt.get('Principal', {}).get('AWS') # 有效CloudFront OAI的ARN格式以arn:aws:iam::cloudfront:user/开头 if isinstance(principal, str): if principal.startswith('arn:aws:iam::cloudfront:user/'): valid_statements.append(stmt) elif isinstance(principal, list): # 处理多Principal场景 valid_principals = [p for p in principal if p.startswith('arn:aws:iam::cloudfront:user/')] if valid_principals: stmt['Principal']['AWS'] = valid_principals valid_statements.append(stmt) policy['Statement'] = valid_statements # 重新设置合法的桶策略 client.put_bucket_policy( Bucket=bucket, Policy=json.dumps(policy) )
3. 追加策略前做合法性校验
在追加新策略语句前,先校验现有策略的完整性:
- 检查所有
Principal.AWS是否为有效ARN格式,而非纯用户ID - 可调用S3的
validate_policyAPI提前验证策略格式(需额外权限):
# 提前验证策略合法性 validation = client.validate_policy( PolicyDocument=json.dumps(policy) ) if validation['IsValid']: client.put_bucket_policy(Bucket=bucket, Policy=json.dumps(policy)) else: print(f"策略无效: {validation['ValidationErrors']}")
4. 手动管理策略,避免依赖AWS自动修改
不要依赖AWS在删除CloudFront分发时自动调整S3桶策略,建议用Terraform、CloudFormation等基础设施即代码工具维护桶策略,确保策略变更可追溯、可控制。
内容的提问来源于stack exchange,提问作者santos82h
相关产品推荐
相关产品推荐

