仓库自包含化:Docker/CI/文档/规范入库,路由分组拆分
CI / test (push) Successful in 15s

This commit is contained in:
Wang Defa
2026-07-09 19:18:04 +08:00
parent b9a3e97e84
commit 3e0389c1e9
83 changed files with 20241 additions and 248 deletions
+36 -7
View File
@@ -2,6 +2,7 @@ package api
import (
"context"
"errors"
"io"
"log"
"net/http"
@@ -15,10 +16,12 @@ import (
// ONS 消息头(方案A §2.2/§2.3,官方 X-OCI-NS-* 字段)。
const (
onsHeaderMessageType = "X-OCI-NS-MessageType"
onsHeaderMessageID = "X-OCI-NS-MessageId"
onsHeaderTimestamp = "X-OCI-NS-Timestamp"
onsHeaderConfirmURL = "X-OCI-NS-ConfirmationURL"
onsHeaderMessageType = "X-OCI-NS-MessageType"
onsHeaderMessageID = "X-OCI-NS-MessageId"
onsHeaderTimestamp = "X-OCI-NS-Timestamp"
onsHeaderConfirmURL = "X-OCI-NS-ConfirmationURL"
onsHeaderSigningCertURL = "X-OCI-NS-SigningCertURL"
onsHeaderSignature = "X-OCI-NS-Signature"
)
// webhook 同步路径的防御参数:body 上限高于 ONS 链路 128KB 留余量,
@@ -44,6 +47,15 @@ type webhookHandler struct {
// handle 是 webhook 入口:secret 反查租户后按消息类型分派;
// 同步路径只做 secret→分派→读body→幂等入库,5 秒投递预算内返回(方案A §2.4)。
//
// @Summary OCI 日志回传入口(ONS HTTPS 订阅投递)
// @Tags 任务与日志回传
// @Param secret path string true "面板生成的回传密钥(鉴权凭据)"
// @Param body body object true "ONS 消息原文(SubscriptionConfirmation / Notification)"
// @Success 200 "已受理"
// @Failure 403 {object} map[string]string "时间戳超窗或证书源非 Oracle 域"
// @Failure 404 "secret 无效(不暴露端点存在性)"
// @Router /api/v1/webhooks/oci-logs/{secret} [post]
func (h *webhookHandler) handle(c *gin.Context) {
cfgID, ok := h.events.ResolveSecret(c.Request.Context(), c.Param("secret"))
if !ok {
@@ -141,8 +153,25 @@ func parseOnsTime(value string) (time.Time, bool) {
}
// verifySignature 校验 ONS 消息签名。
// TODO(方案A §2.3 spike):官方未公开签名 canonical form,待 test-server 抓取
// 真实消息确认输入格式后实现;当前按方案约定以 secret+时间戳+幂等先行。
func verifySignature(http.Header) error {
//
// 现状:官方未公开 canonical form。归档任务 07-06-log-relay-plan-a 与 07-07-relay-impl
// 用真实抓包样本(body+签名+证书公钥)对 15 种常见拼接 × 2 种 PSS salt 长度全部未命中,
// 逆向成本高。P0 决策以「secret 路径段 + HTTPS + 时间戳偏差 ≤5min + MessageId 幂等」上线。
//
// 本函数做能做的**证书源头硬化**:即便未来接入 canonical form + 公钥验签,
// SigningCertURL 若允许任意域名,攻击者可自签证书构造 body+签名+cert URL 三元组绕过
// (AWS SNS 曾出现同类 GHSA-8jgf-23q5-x7xx)。这里预先把 cert URL 域名锁到 Oracle 云,
// 让未来加签名校验成为「相加」而非「返修」。
func verifySignature(h http.Header) error {
certURL := h.Get(onsHeaderSigningCertURL)
if certURL == "" {
return nil // 头缺失回退到 secret+时间戳+幂等三重防护,不误杀历史 layout
}
parsed, err := url.Parse(certURL)
if err != nil || parsed.Scheme != "https" || !service.IsOracleHost(parsed.Host) {
return errors.New("ons: signing cert url not in oracle domain")
}
// TODO(canonical form 公开后):按 SigningCertURL 拉证书(含 host 复核 + 缓存),
// 用公钥对 signing string 做 SHA256withRSA/PSS 验签,失败返回 error。
return nil
}