华为云作品展览馆发布实战:STS 自委托与五道发布门禁
华为云作品展览馆发布实战:STS 自委托与五道发布门禁
引子
最近要把一个作品发布到「华为云开发者作品展览馆」。看起来只是"上传一个 zip",实际走通之后才发现,平台设计了一套相当严谨的链路:
身份校验靠 STS 临时凭证 + 自委托,内容审核靠五道本地门禁。
这篇文章把这套流程完整拆开复盘,包括每一步的真实命令、每道门禁的作用,以及几个必须踩过才知道的坑。
一、为什么不能直接用 AK/SK 发布?
发布接口是:
POST /open-api-public/v1/gallery/works
但它不接受你的永久 AK/SK,而是要求请求头携带:
X-Tmp-Ak / X-Tmp-Sk / X-Security-Token
也就是临时凭证(STS),且必须由 IAM 自委托(SELF_VERIFY) 生成。网关会用这份临时凭证调用 STS.GetCallerIdentity 解析账号(Domain)ID,校验通过后再注入 X-Domain-Id 供服务端记录作者。
这样设计的好处很清楚:
- 永久 AK/SK 不需要出现在任何请求里;
- 临时凭证 900 秒过期,泄露面极小;
- 服务端能确认"调用者确实是该 Domain"。
二、四步生成可用的 STS
1. 配置 hcloud 凭证
npx huaweicloud-devkit auth init
它会提示两种方式:交互终端输入,或设置 HW_ACCESS_KEY/HW_SECRET_KEY 环境变量。前者适合本机,后者适合非交互环境。
2. 解析 Domain ID
resolve-domain.mjs --hcloud /root/.local/bin/hcloud
# 输出:#domain=4c39fe5b... name=hw030690224
3. 生成 STS(900 秒有效)
gen_sts.py --account 4c39fe5b... --hcloud /root/.local/bin/hcloud \
--creds-out ./sts-creds.json --sh-out ./sts-creds.sh
产物 sts-creds.json 里除了 AK/SK/Token,还有一个关键的 _refresh 字段:
{"accountId":"...","agencyUrn":"iam::...:agency:SELF_VERIFY","region":"cn-north-4"}
有了它,后续接口返回 401 时可以自动刷新,不必手动重跑。
4. 验证 STS
api.mjs GET /v1/gallery/camps --creds-file ./sts-creds.json
# #status=200
三、五道发布门禁
真正的发布脚本在发请求前会本地复检五道门禁,任何一道不过就拒绝发布:
| 门禁 | 检查内容 | 失败后果 |
|---|---|---|
preflight |
Python 依赖 + Chromium + CJK 字体 | 无法截图/生成封面 |
ensure-utf8 |
项目文件编码是否为 UTF-8 | 中文乱码 |
screenshot-guard |
截图产物是否存在且可用 | 封面空白 |
| 封面校验 | 产物存在 + 16:9 比例 | 展示变形 |
| 详情包校验 | zip 存在 + README 在根目录 | 详情页空白 |
其中最容易被忽略的是 ensure-utf8——我第一次发布就卡在这里:
✖ [ensure-utf8] 标记文件不存在: /tmp/utf8-gate-ok
❌ 1 个门禁未通过 — 禁止发布。
补跑一次编码检查后才通过:
ensure-utf8.mjs /path/to/project
# ✅ 编码门禁通过(检查 1 个文件,UTF-8 保留 1,自动修正 0)
教训一:门禁是"标记文件"驱动的。少了某个标记,不是"没检查",而是"没通过"。
四、发布参数与结果
参数 JSON 的必填项:
{
"idempotencyKey": "gallery-publish-<domainID>-<timestamp>",
"accessKeyId": "<STS AK>",
"secretAccessKey": "<STS SK>",
"securityToken": "<STS Token>",
"trainingCampId": "<活动 ID>",
"workName": "<作品名>",
"introduction": "<15~50 字符简介>",
"coverImage": "<封面 PNG 绝对路径>",
"detailZip": "<详情 zip 绝对路径>",
"gitUrl": "<https://... .git>",
"gitBranch": "<分支>",
"envUrl": ""
}
注意两个细节:
- 字段名是
coverImage/detailZip,不是coverImagePath/detailsZipPath——脚本会对未知 key 直接报错拦截; introduction有严格的 15~50 字符限制(中英文、标点都算)。我写的简介是 42 字符,正好合格。
提交成功返回:
#status=201
workId=007809cb69c00000
workUrl=https://gallery.developer.huaweicloud.com/gallery/007809cb69c00000
reward=success value=200
作品页可以公开访问,作者、活动、简介、详情全部正确显示。
五、几个实战坑
坑 1:hcloud 不在 PATH
auth sync 报 KooCLI current profile unresolved,原因是 hcloud 未安装。装上后必须先接受隐私协议(非交互环境用 echo y |),否则命令直接报 Invalid character。
坑 2:region 必须显式给
auth_switch(mode=import) 如果 creds-import.json 里没有 region,会直接报错:
invalid_region: region is required to persist credentials
坑 3:封面生成是"阻塞 + 耗时"的
build-cover.mjs 会真的启动浏览器、打开页面、截图、合成,单次约 60~120 秒。preflight 首次还要下载字体与 Chromium,可能 5~10 分钟。必须给足超时。
坑 4:Git 信息要"核对远端分支"
read-git-info.mjs 不只是读本地配置,还会 git ls-remote 核对分支是否真实存在——这避免了"提交到不存在的分支"这种低级失败。
六、小结
这套发布流程的设计思路值得借鉴:
- 最小权限:用 900 秒的 STS 替代永久 AK/SK,且由自委托生成;
- 本地门禁前置:五道检查在发请求之前完成,避免"传上去才发现封面不对";
- 幂等键:
idempotencyKey防止重试导致重复发布; - 产物即证据:门禁检查的是真实文件(字体渲染、比例、zip 结构),而不是"你声称做了"。
把这套链路跑通一次之后,后续作品发布就变成了可重复、可校验的工程动作,而不是"玄学上传"。
本文基于本人在华为云开发者作品展览馆的真实发布记录整理,命令、门禁名称、返回码与作品 ID 均来自实际执行,纯原创,欢迎交流。
- 点赞
- 收藏
- 关注作者
评论(0)