141 lines
4.6 KiB
Bash
Executable File
141 lines
4.6 KiB
Bash
Executable File
#!/usr/bin/env bash
|
||
# 法规知识库组合门禁(U8)。缺环境直接失败,不静默跳过。
|
||
# 不回显任何 KBREG_* 值;扫描结果只打印文件路径与变量名。
|
||
set -euo pipefail
|
||
|
||
here="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||
pin="${REGKB_PIN:-$here/components.pin}"
|
||
|
||
# 与 scripts/fetch-rdm-pin.sh 同规则:只认已知键、40 位 hex,不执行 pin 文件。
|
||
[ -f "$pin" ] || { echo "components.pin 不存在:$pin" >&2; exit 1; }
|
||
declare -A got=()
|
||
while IFS= read -r line || [ -n "$line" ]; do
|
||
case "$line" in
|
||
''|\#*) continue ;;
|
||
esac
|
||
case "$line" in
|
||
*=*) ;;
|
||
*) echo "components.pin 行格式错误(须为 key=sha)" >&2; exit 1 ;;
|
||
esac
|
||
key="${line%%=*}"
|
||
val="${line#*=}"
|
||
case "$key" in
|
||
rdm_sha|kb_sha) ;;
|
||
*) echo "components.pin 未知键:$key" >&2; exit 1 ;;
|
||
esac
|
||
[[ "$val" =~ ^[0-9a-f]{40}$ ]] || { echo "components.pin 的 $key 不是 40 位 hex" >&2; exit 1; }
|
||
[ -z "${got[$key]:-}" ] || { echo "components.pin 重复键:$key" >&2; exit 1; }
|
||
got["$key"]="$val"
|
||
done < "$pin"
|
||
[ "${#got[@]}" -eq 2 ] || { echo "components.pin 必须同时有 rdm_sha、kb_sha" >&2; exit 1; }
|
||
rdm_sha="${got[rdm_sha]}"
|
||
kb_sha="${got[kb_sha]}"
|
||
|
||
missing=0
|
||
for v in KBREG_TEST_DATABASE_URL SVC_RDM_SRC_DIR KB_SRC_DIR; do
|
||
if [ -z "${!v:-}" ]; then
|
||
echo "regulations-kb: $v 未设置(组合门禁必需,不静默跳过)" >&2
|
||
missing=1
|
||
fi
|
||
done
|
||
[ "$missing" -eq 0 ] || exit 2
|
||
|
||
rdm_dir="$SVC_RDM_SRC_DIR"
|
||
kb_dir="$KB_SRC_DIR"
|
||
|
||
head_of() { git -C "$1" rev-parse --verify -q HEAD 2>/dev/null || true; }
|
||
rdm_head="$(head_of "$rdm_dir")"
|
||
[ "$rdm_head" = "$rdm_sha" ] || { echo "regulations-kb: SVC_RDM_SRC_DIR HEAD=${rdm_head:-<无>},须为 rdm_sha=$rdm_sha" >&2; exit 1; }
|
||
kb_head="$(head_of "$kb_dir")"
|
||
[ "$kb_head" = "$kb_sha" ] || { echo "regulations-kb: KB_SRC_DIR HEAD=${kb_head:-<无>},须为 kb_sha=$kb_sha" >&2; exit 1; }
|
||
|
||
kb_link="$(git -C "$rdm_dir" rev-parse --verify -q "HEAD:pins/agent-system-kb-regulations" 2>/dev/null || true)"
|
||
[ -n "$kb_link" ] || { echo "regulations-kb: RDM 检出缺少 pins/agent-system-kb-regulations gitlink" >&2; exit 1; }
|
||
if ! git -C "$kb_dir" merge-base --is-ancestor "$kb_link" "$kb_sha" 2>/dev/null; then
|
||
echo "regulations-kb: RDM 的 KB gitlink $kb_link 不是 kb_sha=$kb_sha 的祖先(或 KB 检出缺该对象)" >&2
|
||
exit 1
|
||
fi
|
||
echo "regulations-kb: rdm=$rdm_sha kb=$kb_sha(RDM KB gitlink $kb_link 为其祖先)"
|
||
|
||
failed=0
|
||
# 在 if 条件中 set -e 不生效:阶段函数内多条命令须显式 && 串联。
|
||
stage() {
|
||
local name="$1"; shift
|
||
echo "=== stage $name ==="
|
||
if ( "$@" ); then
|
||
echo "PASS $name"
|
||
else
|
||
echo "FAIL $name"
|
||
failed=1
|
||
fi
|
||
}
|
||
|
||
stage_kb() {
|
||
make -C "$kb_dir" test-pg
|
||
}
|
||
|
||
stage_rdm() {
|
||
cd "$rdm_dir" &&
|
||
GOWORK=off go test -count=1 ./plugins/kbreg/... &&
|
||
GOWORK=off go test -count=1 -run 'Composed|RegCite|Citation|RegCheck|RegBatch|RegAudit' ./internal/rdmapp/... ./plugins/rdm/...
|
||
}
|
||
|
||
stage_scan() {
|
||
local dirs=() d
|
||
if [ -n "${REGKB_SCAN_DIRS:-}" ]; then
|
||
read -r -a dirs <<< "$REGKB_SCAN_DIRS"
|
||
else
|
||
for d in "$rdm_dir/.build/product/frontend/dist"; do
|
||
[ -d "$d" ] && dirs+=("$d")
|
||
done
|
||
fi
|
||
if [ "${#dirs[@]}" -eq 0 ]; then
|
||
echo "scan: 没有可扫描的客户端制品目录(先构建 RDM 产品以生成 .build/product/frontend/dist,或设置 REGKB_SCAN_DIRS)" >&2
|
||
return 1
|
||
fi
|
||
local secret_vars=() name
|
||
while IFS= read -r name; do
|
||
case "$name" in
|
||
KBREG_*KEY*|KBREG_*TOKEN*|KBREG_DATABASE_URL)
|
||
[ -n "${!name:-}" ] && secret_vars+=("$name") ;;
|
||
esac
|
||
done < <(compgen -e)
|
||
local tmp rc=0 hits f
|
||
tmp="$(mktemp)" || return 1
|
||
for d in "${dirs[@]}"; do
|
||
if [ ! -d "$d" ]; then
|
||
echo "scan: 目录不存在:$d" >&2
|
||
rc=1
|
||
continue
|
||
fi
|
||
echo "scan: $d"
|
||
hits="$(grep -rlF -e 'KBREG_' -- "$d" || true)"
|
||
if [ -n "$hits" ]; then
|
||
while IFS= read -r f; do echo "scan: $f 含字符串 KBREG_" >&2; done <<< "$hits"
|
||
rc=1
|
||
fi
|
||
for name in "${secret_vars[@]}"; do
|
||
printf '%s\n' "${!name}" | grep -v '^$' > "$tmp" || true
|
||
[ -s "$tmp" ] || continue
|
||
hits="$(grep -rlF -f "$tmp" -- "$d" || true)"
|
||
if [ -n "$hits" ]; then
|
||
while IFS= read -r f; do echo "scan: $f 含 $name 的值" >&2; done <<< "$hits"
|
||
rc=1
|
||
fi
|
||
done
|
||
done
|
||
rm -f "$tmp"
|
||
echo "scan: 已核对 ${#secret_vars[@]} 个凭据变量:${secret_vars[*]:-<无>}"
|
||
return "$rc"
|
||
}
|
||
|
||
stage kb-test-pg stage_kb
|
||
stage rdm-kbreg stage_rdm
|
||
stage client-asset-secret-scan stage_scan
|
||
|
||
if [ "$failed" -ne 0 ]; then
|
||
echo "regulations-kb: FAIL"
|
||
exit 1
|
||
fi
|
||
echo "regulations-kb: PASS"
|