华为云 OBS 返回 403 AccessDenied:从错误码到权限策略的排查清单
引言
用 SDK、obsutil、OBS Browser+ 或者浏览器访问 OBS 时,最让人头疼的往往是一个 403 Forbidden。很多人一看到 403 就去加 IAM 权限,结果权限越加越大,问题还在。实际上 OBS 里返回 403 的错误码不止 AccessDenied 一个,签名、时钟、密钥、欠费都可能落在 403 上;即使确实是 AccessDenied,也可能来自 IAM 策略、桶策略、ACL、防盗链、阻止公共访问(BPA)、VPCEP 策略等不同层面。
这篇按「先看响应 → 再分层排查」的顺序整理成一份清单,所有结论都对照了华为云 OBS 官方文档(链接见文末)。
第一步:先看错误码和请求 ID,别急着改权限
OBS 报错时的响应由状态码、响应头和 XML 响应体组成,其中最关键的几个字段是:
HTTP/1.1 403 Forbidden
x-obs-request-id: <RequestId>
<Error>
<Code>AccessDenied</Code>
<Message>...</Message>
<RequestId>...</RequestId>
<HostId>...</HostId>
<BucketName>example-bucket</BucketName>
<Key>path/to/object</Key>
</Error>
Code:通用错误码,决定排查方向。Message:详细原因。新版鉴权的AccessDenied会直接写明是谁(user)、做什么操作(action)、对哪个资源(resource)、被哪类策略(policy_type)拒绝。RequestId/x-obs-request-id:请求唯一标识,提工单时连同桶名、对象名一起提供。
我习惯先用 curl -v 或 SDK 的调试日志把完整响应拿下来,再对照下表判断方向:
| 状态码 / 错误码 | 含义(官方) | 方向 |
|---|---|---|
403 AccessDenied |
没有权限执行操作 | 权限策略、防盗链、BPA、WORM 等 |
403 SignatureDoesNotMatch |
服务端算出的签名与请求不一致 | SK、StringToSign、Endpoint |
403 InvalidAccessKeyId |
系统中不存在该 AK | AK 填错、已删除 |
403 RequestTimeTooSkewed |
客户端与服务端时间差超过 15 分钟 | 系统时钟 |
403 AccessForbidden |
桶未配置 CORS 或规则不匹配 | CORS |
403 InArrearOrInsufficientBalance |
欠费或余额不足 | 账户 |
403 InvalidObjectState |
归档/深度归档对象需先恢复 | 存储类别 |
AccessDenied 的 Message 如果是 ... because no <policy_type> policy allows ...,说明是没有被明确授权;如果是 ... with an explicit deny in ... policy,说明是被显式拒绝。policy_type 取值含义:identity-based 是 IAM 策略,resource-based 是桶策略或 ACL(显式拒绝场景只会是桶策略),session 是 VPCEP 策略,service control 是组织的服务控制策略(SCP)。看懂这一行,往往就能直接定位到该改哪里。
编号排查步骤
1. 确认用的是哪个身份、哪对 AK/SK
官方 FAQ 把「使用了错误的账号或 AK/SK」列为高频原因之一:权限给了用户 A,实际请求却用的是用户 B 的 AK/SK。常见的情况是环境变量、配置文件、SDK 代码里各有一套密钥。可以把 Message 里的 user、SignatureDoesNotMatch 响应里的 AccessKeyId 和自己以为在用的身份对比一下。
# 只看当前进程拿到的是哪个 AK(只打印前几位,不要打印 SK)
echo "${OBS_AK:0:4}****"
2. 同账号还是跨账号
- 同账号:IAM 策略(推荐)或桶策略任选其一授权即可。
- 跨账号(账号 A 访问账号 B 的桶):需要 A 的管理员用 IAM 给自己的用户授权,同时 B 的桶拥有者用桶策略或 ACL 给 A 的用户授权,只配一边会 403。另外官方说明暂不支持用控制台跨账号访问桶,需要用 OBS Browser+、API、SDK 或 obsutil。
3. 核对 Resource 和 Action
官方总结的常见错误:
- Resource 只授权了桶 A,却访问桶 B;只授了桶级权限,却操作桶内对象;只授了对象权限,却列举桶。
- Action 配错或遗漏,比如要上传(PutObject)却只给了下载(GetObject)。
- 策略里写了 Condition(如源 IP),要确认请求满足条件。
一个只授予上传权限的桶策略示例(占位符请替换):
{
"Statement": [
{
"Sid": "allow_put",
"Action": ["PutObject"],
"Effect": "Allow",
"Resource": "example-bucket/*",
"Principal": { "ID": ["domain/<domain-id>:user/<user-id>"] }
}
]
}
4. 控制台 / OBS Browser+ 访问还要额外的列举权限
给用户配置 OBS OperateAccess 等系统权限或桶读写权限后,用 API/SDK 正常,但在控制台、OBS Browser+ 里提示「拒绝访问」——这是因为界面加载桶列表、对象列表时会调用 ListAllMyBuckets、ListBucket 等接口。桶开启多版本时,还需要 obs:bucket:ListBucketVersions。
5. 查找显式 Deny
OBS 权限遵循 Deny 优先:IAM 策略、桶策略、VPCEP 策略、SCP 中任一处显式 Deny,都会覆盖其他地方的 Allow。逐项检查这四类策略里是否有 Deny 命中当前 action。
6. 临时 AK/SK 是否带了 securitytoken
用 IAM 获取的临时访问密钥时,临时 AK/SK 和 securitytoken 必须一起用:Header 签名需加 x-obs-security-token 头域(并参与签名),URL 签名需带 x-obs-security-token 参数。临时密钥有效期为 15 分钟到 24 小时;如果获取时传了 policy,有效权限是 IAM 用户原有权限与临时策略的交集,临时策略里没写的权限默认拒绝。
PUT /object.txt HTTP/1.1
Host: example-bucket.obs.<region-id>.myhuaweicloud.com
x-obs-date: <GMT 时间>
x-obs-security-token: <security-token>
Authorization: OBS <临时AK>:<Signature>
7. 签名与时钟
RequestTimeTooSkewed:客户端与服务端时间差大于 15 分钟会被拒绝。先date -u看 UTC 时间,不准就用 NTP / chrony 等时间同步服务校正。SignatureDoesNotMatch:响应里会返回服务端的StringToSign,和客户端的逐行对比。常见原因有:SK 不匹配;漏了x-obs-*头域或?acl这类 query 参数;URL 签名应使用Expires而不是Date;SDK 的 Endpoint 误填成了桶域名(应为obs.<region-id>.myhuaweicloud.com,前面不加桶名)。官方推荐尽量用 SDK,避免手工算签。
date -u # 与真实 UTC 时间相差不应接近 15 分钟
8. 防盗链(Referer)
防盗链的检查发生在读写权限判断之前。规则要点:白名单非空时,只有在白名单且不在黑名单的 Referer 才能访问;黑白名单有交集时交集部分被禁止;如果下载时 Referer 带 http/https,规则里也要带。浏览器的 Referrer-Policy: no-referrer、<video> 播放等会产生空 Referer,配白名单时需要考虑打开「允许空 Referer」。桶日志中 Referer 字段为 - 表示空 Referer,可以据此核对。
9. 阻止公共访问(BPA)
桶开启 BPA 后:BlockPublicAcls 开启时设置含公开语义的对象 ACL 会被拒绝;RestrictPublicBuckets 开启且桶策略里有公开策略时,其他操作也可能被拒。可在「权限控制 > 阻止公共访问」查看开关。
10. 加密对象的 KMS 权限
SSE-KMS 加密的对象:匿名用户不能访问,即使对象是公共读;相关 GET/PUT 请求必须使用 HTTPS;下载时除了对象下载权限,还需要 IAM 授予 kms:cmk:get、kms:cmk:list、kms:cmk:create、kms:dek:create、kms:dek:encrypt、kms:dek:decrypt。使用自定义密钥时,桶和密钥必须在同一区域;跨账号场景应使用自定义密钥。需要给匿名用户看加密对象,可以用对象分享生成的临时 URL。
11. 其他 403:WORM、欠费、归档、缓存
- 试图修改或删除受 WORM 保护的对象,会返回
AccessDenied,只能等保护期过。 - 欠费、余额不足、账号受限或冻结也会 403。
- 归档 / 深度归档对象要先恢复才能下载。
- 对象不存在也可能是 403:有 GetObject 但没有 ListBucket 权限时,下载不存在的对象返回 403 而不是 404。
- IAM 策略修改后一般要 10~15 分钟才生效,改完立刻测试失败不代表配置错了。
12. 区域 / Endpoint 不对通常不是 403
请求发到了错误区域的地址,官方错误码是 301 PermanentRedirect,按返回的地址重发即可;而 SDK 把 Endpoint 写成桶域名,表现为 SignatureDoesNotMatch。所以如果看到的是 301 或签名错误,优先核对 Endpoint 与桶所在区域。
现象-可能原因-怎么确认
| 现象 | 可能原因 | 怎么确认 |
|---|---|---|
Message 含 no ... policy allows |
未授权或 Resource/Action 不覆盖 | 按 user/action/resource/policy_type 查对应策略 |
Message 含 explicit deny |
IAM/桶策略/VPCEP/SCP 显式 Deny | 在 policy_type 指向的策略里找 Deny |
| API 正常,控制台/Browser+ 拒绝 | 缺 ListAllMyBuckets / ListBucket | 检查 IAM 自定义策略 |
| 跨账号只有一方配了权限 | 缺 IAM 或桶策略/ACL 其中一侧 | 两个账号分别核对 |
| 临时密钥 403 | 没带 securitytoken、已过期、临时策略未授权 | 检查请求头/URL 参数与有效期 |
SignatureDoesNotMatch |
SK 错、StringToSign 不一致、Endpoint 含桶名 | 对比响应中的 StringToSign、AccessKeyId |
RequestTimeTooSkewed |
时钟偏差超过 15 分钟 | date -u |
| 网页嵌入 403,直接访问正常(或反之) | 防盗链规则、空 Referer | 看防盗链配置与桶日志 Referer 字段 |
| 设置公共读 ACL / 策略被拒 | BPA 开关 | 权限控制 > 阻止公共访问 |
| 加密对象下载 403,普通对象正常 | 缺 KMS 权限、HTTP 访问、匿名访问 | 核对 IAM 中 KMS 授权与协议 |
| 下载不存在的对象返回 403 | 无 ListBucket 权限 | 授予 ListBucket 后应返回 404 |
| 刚改完权限仍 403 | IAM 缓存 | 等 10~15 分钟重试 |
小结
OBS 的 403 排查,我一般按三层走:先看 Code(区分权限、签名、时钟、账户问题);再读 Message(user / action / resource / policy_type 往往直接指出该改哪个策略);最后按层核对身份与 AK/SK、同账号还是跨账号、Resource/Action、显式 Deny、securitytoken、防盗链、BPA、KMS。改完 IAM 记得等 10~15 分钟。仍解决不了时,把 RequestId、桶名、对象名整理好提工单,定位会快很多。
参考
- AccessDenied 错误码说明:https://support.huaweicloud.com/api-obs/obs_errorcode_0003.html
- 错误码概述:https://support.huaweicloud.com/api-obs/obs_04_0115.html
- 已配置 OBS 权限仍然 403 AccessDenied:https://support.huaweicloud.com/obs_faq/obs_faq_0147.html
- 配置系统权限或桶读写权限后仍提示拒绝访问:https://support.huaweicloud.com/obs_faq/obs_faq_0142.html
- SignatureDoesNotMatch 错误码说明:https://support.huaweicloud.com/api-obs/obs_errorcode_0013.html
- 签名不匹配如何处理:https://support.huaweicloud.com/obs_faq/obs_faq_0173.html
- 如何使用 V4 签名访问 OBS(含 RequestTimeTooSkewed):https://support.huaweicloud.com/obs_faq/obs_faq_0274.html
- Header 中携带签名(含临时 AK/SK 示例):https://support.huaweicloud.com/api-obs/obs_04_0010.html
- 通过临时访问密钥访问 OBS:https://support.huaweicloud.com/perms-cfg-obs/obs_40_0008.html
- 配置防盗链:https://support.huaweicloud.com/usermanual-obs/obs_03_0341.html
- SSE-KMS 加密:https://support.huaweicloud.com/usermanual-obs/obs_03_0090.html
- 如何访问或下载已加密的对象:https://support.huaweicloud.com/obs_faq/obs_faq_0168.html
- 点赞
- 收藏
- 关注作者
评论(0)