OSS Bucket Policy 和 RAM Policy 都支持在 Statement 中通过 Condition 引入 acs:CurrentTime 时间条件,实现策略语句到期自动失效。本文介绍如何为临时封禁、限时授权等场景配置带有效期的 Statement,并提供清理过期 Statement 的参考实现。
使用场景
在以下场景中,可以通过在 Statement 中引入时间条件,让策略语句到期后自动失效,避免手工撤销操作的滞后和疏漏:
临时封禁:在指定日期之前禁止一切访问,到达日期后自动恢复访问。
限时授权:仅允许在指定的时间窗口内访问资源,过期后权限自动失效。
实现方式:在 Statement 的 Condition 块中使用 acs:CurrentTime 条件键和日期类比较操作符,将语句的生效与否绑定到系统时间。
Bucket Policy 配置示例
以下 Bucket Policy 表示:在 2026 年 8 月 12 日 17:00:00(北京时间)之前,允许(Allow)所有用户对 mytestbucket 中的任意 Object 执行 oss:GetObject 操作;到期后该 Statement 自动失效,访问失败。
{
"Version": "1",
"Statement": [
{
"Action": [
"oss:GetObject"
],
"Effect": "Allow",
"Resource": [
"acs:oss:*:*:mytestbucket/*"
],
"Condition": {
"DateLessThan": {
"acs:CurrentTime": [
"2026-08-12T17:00:00+08:00"
]
}
}
}
]
}生效逻辑:
失效前(当前时间 < 2026-08-12 17:00):
DateLessThan条件为真(True),Allow语句生效,用户GetObject成功。失效后(当前时间 ≥ 2026-08-12 17:00):
DateLessThan条件为假(False),该 Statement 不再生效,用户访问失败。
RAM Policy 配置示例
以下 RAM Policy 表示:被授予此策略的 RAM 用户只能在 2026 年 8 月 12 日 17:00:00(北京时间)之前对 mytestbucket 中的任意 Object 访问 OSS 中的 Bucket。
{
"Version": "1",
"Statement": [
{
"Action": "oss:*",
"Effect": "Allow",
"Resource": [
"acs:oss:*:*:mytestbucket/*"
],
"Condition": {
"DateLessThan": {
"acs:CurrentTime": "2026-08-12T17:00:00+08:00"
}
}
}
]
}关于 RAM Policy 中时间条件的更多说明,请参见 在指定的时间段访问阿里云。
Condition 条件键与操作符
OSS Bucket Policy 与 RAM Policy 支持的 Condition 条件键和操作符完全一致。设置 Statement 有效期时常用以下组合:
条件键
条件键 | 说明 |
| 请求到达 OSS 服务端时的系统时间,需要使用 ISO 8601 格式。 |
日期类操作符
acs:CurrentTime 属于日期类型,支持以下 6 个操作符:
操作符 | 含义 |
| 当前时间等于指定时间。 |
| 当前时间不等于指定时间。 |
| 当前时间早于指定时间。常用于"到期前 Allow / 到期前 Deny"场景。 |
| 当前时间早于或等于指定时间。 |
| 当前时间晚于指定时间。常用于"生效后 Allow"场景。 |
| 当前时间晚于或等于指定时间。 |
完整的 Bucket Policy 元素与条件,请参考Condition。
定期清理过期 Statement
带时间条件的 Statement 到期后不会自动从 Bucket Policy 中移除。如果长期累积,可能触发以下问题:
大小上限:Bucket Policy JSON 文本上限为 16 KB,累积过多过期 Statement 会导致无法添加新策略。
管理与排查:冗余 Statement 会干扰管理员审阅当前生效的权限边界。
合规要求:及时清理过期的 Allow 或 Deny 条目,符合权限最小化原则。
建议定期清理过期 Statement,可手动通过 Sid 识别后删除,或将自动化脚本部署到函数计算(FC)并配置定时触发器(例如每周一次)。以下为建议的过期 Statement 清理方式,供参考。具体的清理请结合业务逻辑和实际需要进行制定。
清理流程
调用
GetBucketPolicy获取完整的 Policy JSON 文本。解析 JSON,遍历每一条 Statement。
查找
Condition中的DateLessThan或DateGreaterThan,提取acs:CurrentTime对应的时间字符串。将时间字符串解析为 datetime 对象,与当前系统时间对比。
如果时间条件已经永远不会再触发(例如
DateLessThan的指定时间早于当前时间),则将该 Statement 标记为过期并从列表中移除。调用
PutBucketPolicy将剔除过期条目后的 Statement 列表重新提交。
如何识别"过期"
清理脚本判定过期时,需要结合 Condition 操作符和 Effect 综合理解业务意图:
条件组合 | 业务含义 | 清理建议 |
| 在指定日期之前禁止访问,到期后自动解除封禁。 | 指定日期早于当前时间后可安全删除,删除后不再有拦截,符合业务预期。 |
| 在指定日期之前限时授权,到期后权限自动失效。 | 指定日期早于当前时间后可安全删除。 |
| 指定日期之后才允许访问。当前时间晚于该日期后条件永远为真。 | 如果业务希望该权限永久化,可移除 |
Python 自动化脚本示例
以下示例脚本基于 oss2 SDK,演示如何识别并清理仅含 DateLessThan 时间条件的过期 Statement。请根据实际业务逻辑调整识别和清理规则。
该脚本会修改 Bucket Policy,请务必先在测试 Bucket 上验证后再用于生产环境。建议安装 python-dateutil 以便解析带时区的 ISO 8601 时间字符串。
import json
import alibabacloud_oss_v2 as oss
from datetime import datetime, timezone
import dateutil.parser # 建议安装 python-dateutil 库来完美解析 ISO8601 格式
# 配置信息
access_key = '您的AccessKey'
secret_key = '您的SecretKey'
region = 'cn-hangzhou'
bucket_name = '您的Bucket名称'
cfg = oss.config.load_default()
cfg.credentials_provider = oss.credentials.StaticCredentialsProvider(access_key, secret_key)
cfg.region = region
client = oss.Client(cfg)
def clean_expired_policy():
try:
# 1. 获取当前 Bucket Policy
result = client.get_bucket_policy(oss.models.GetBucketPolicyRequest(bucket=bucket_name))
policy_data = json.loads(result.body)
statements = policy_data.get('Statement', [])
now = datetime.now(timezone.utc) # 使用 UTC 时间进行对比
new_statements = []
removed_count = 0
# 2. 遍历并检查
for stmt in statements:
is_expired = False
# 检查是否有时间限制条件 (以 DateLessThan 为例)
condition = stmt.get('Condition', {})
date_less_than = condition.get('DateLessThan', {}).get('acs:CurrentTime')
if date_less_than:
# 提取策略里的时间 (例如 "2026-08-12T17:00:00+08:00")
# dateutil.parser 可以自动处理 +08:00 等时区信息
expiry_time = dateutil.parser.isoparse(date_less_than[0])
# 如果设定时间早于当前时间,说明该 Deny/Allow 已经再也不会触发了
if expiry_time < now:
is_expired = True
print(f"发现失效 Statement [Sid: {stmt.get('Sid', 'N/A')}]: 设定时间 {date_less_than[0]} 已过期。")
if not is_expired:
new_statements.append(stmt)
else:
removed_count += 1
# 3. 写回 Policy
if removed_count > 0:
if not new_statements:
# 如果删空了,直接删除整个 Policy
client.delete_bucket_policy(oss.models.DeleteBucketPolicyRequest(bucket=bucket_name))
print("所有 Statement 已过期,已清空 Bucket Policy。")
else:
policy_data['Statement'] = new_statements
client.put_bucket_policy(oss.models.PutBucketPolicyRequest(
bucket=bucket_name,
body=json.dumps(policy_data),
))
print(f"清理完成,共移除 {removed_count} 条过期条目。")
else:
print("未发现过期条目。")
except oss.exceptions.OperationError as e:
cause = e.unwrap() if hasattr(e, 'unwrap') else None
if isinstance(cause, oss.exceptions.ServiceError) and cause.code == 'NoSuchBucketPolicy':
print("该 Bucket 没有配置 Policy。")
else:
print(f"发生错误: {e}")
except Exception as e:
print(f"发生错误: {e}")
if __name__ == "__main__":
clean_expired_policy()注意事项
时间格式:时间字符串必须符合 ISO 8601 格式,建议显式带上时区(如
+08:00),否则可能因服务端时区解析差异导致 Statement 失效时间不符合预期。操作符匹配:请根据业务场景设置合理的时间和操作符,以满足不同业务场景需求。
测试先行:变更生产 Bucket Policy 前,请先在测试 Bucket 上验证配置和清理脚本的行为符合预期。