create-dwy 0.16.1 → 0.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +9 -0
- package/bin/index.js +1 -1
- package/package.json +1 -1
- package/src/sync-all.js +303 -59
- package/src/sync-global-skills.js +167 -0
- package/src/sync.js +21 -11
- package/templates/ai-tools/CHANGELOG.md +134 -0
- package/templates/ai-tools/VERSION +1 -1
- package/templates/ai-tools/rules/Android/dwy-android-core.md +65 -1
- package/templates/ai-tools/rules/Python/dwy-python-core.md +47 -0
- package/templates/ai-tools/rules/Vue/dwy-vue-core.md +55 -0
- package/templates/ai-tools/rules/iOS/dwy-swift-core.md +46 -0
- package/templates/ai-tools/rules//345/274/200/345/217/221/346/265/201/347/250/213/dwy-oss-commercial-license.md +128 -0
- package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-ios-app-store-release/SKILL.md +65 -0
- package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-ios-app-store-release/assets/appstore-submission.yaml +43 -0
- package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-ios-app-store-release/references/api-workflow.md +17 -0
- package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-ios-app-store-release/references/in-app-purchase-review.md +16 -0
- package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-ios-app-store-release/references/screenshot-workflow.md +16 -0
- package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-ios-app-store-release/scripts/appstore_config.sh +140 -0
- package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-publish/SKILL.md +11 -8
- package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-publish/references/android.md +2 -1
- package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-publish/references/backend-deploy.md +2 -1
- package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-publish/references/changelog.md +24 -4
- package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-publish/references/frontend-deploy.md +2 -1
- package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-publish/references/generic-release.md +2 -1
- package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-publish/references/git-tag.md +82 -0
- package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-publish/references/harmony.md +2 -1
- package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-publish/references/ios.md +3 -2
- package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-publish/references/monitor-notify.md +2 -2
- package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-semver/SKILL.md +1 -1
- package/templates/ai-tools/skills//345/237/272/347/241/200/345/272/223/dwy-eapi/references/tasks-integration-guide.md +2 -2
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/README.md +57 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/dwy-doubao-tts/SKILL.md +147 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/dwy-doubao-tts/references/api.md +43 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/dwy-doubao-tts/references/config.example.yaml +33 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/dwy-doubao-tts/scripts/global_config.py +89 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/dwy-doubao-tts/scripts/setup_config.py +175 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/dwy-doubao-tts/scripts/synthesize.py +339 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/media-platform-packaging/SKILL.md +127 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/media-platform-packaging/assets/cover-style-master-v1.png +0 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/media-platform-packaging/references/platform-copy-examples.md +37 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/media-platform-packaging/references/platform-posting-times.md +193 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0005-ideation/SKILL.md +42 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0005-ideation/templates/topic-backlog.template.md +50 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0005-ideation/templates//351/200/211/351/242/230/346/261/240.template.md +16 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0010-product/SKILL.md +106 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0010-product/templates/channel-profile.template.md +52 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0010-product/templates//344/272/247/345/223/201/345/215/241.template.md +132 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0030-facts/SKILL.md +60 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0030-facts/scripts/build_facts_html.py +430 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0030-facts/scripts/generate_html.py +1287 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0030-facts/scripts/generate_report.py +189 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0030-facts/templates//344/272/213/345/256/236/350/265/204/346/226/231/345/272/223.template.md +55 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0040-script/SKILL.md +36 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0040-script/templates/README.md +10 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0040-script/templates//344/272/213/345/256/236.template.md +82 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0040-script/templates//345/215/225/351/233/206/346/226/207/346/241/243.template.md +175 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0040-script/templates//350/204/232/346/234/254.template.md +69 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0040-script/templates//351/252/250/346/236/266-v1.1.md +174 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0050-design/SKILL.md +55 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0060-assets/SKILL.md +29 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0070-package/SKILL.md +42 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0070-package/scripts/validate_shots.py +207 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0070-package/shots.schema.json +186 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0070-package//344/272/272/345/256/241/345/214/205.template.md +1 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0070-package//344/272/272/345/256/241/350/257/264/346/230/216.md +15 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0070-package//346/210/220/347/211/207/345/214/205.template.md +49 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0080-factory/SKILL.md +58 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-comic-kit/SKILL.md +424 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-comic-kit/evals.md +41 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-flow/CONTRACT.md +123 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-flow/SKILL.md +81 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-flow//346/211/247/350/241/214/346/270/205/345/215/225.template.md +60 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-knowledge-town/SKILL.md +78 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-knowledge-town/agents/openai.yaml +4 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-knowledge-town/assets/knowledge-town-paper-film-v1.json +80 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-knowledge-town/assets/remotion/AudioTracks.tsx +20 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-knowledge-town/assets/remotion/CaptionLayer.tsx +18 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-knowledge-town/assets/remotion/CueTimeline.ts +24 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-knowledge-town/assets/remotion/KnowledgeTownComposition.tsx +21 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-knowledge-town/references/cinematic-direction.md +73 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-knowledge-town/references/sticker-asset-production.md +30 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-knowledge-town/references/style-guide.md +43 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-knowledge-town/scripts/build_cue_timeline.py +75 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-knowledge-town/scripts/validate_cue_timeline.py +68 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-knowledge-town/scripts/validate_style_preset.py +22 -0
- package/templates/ai-tools/skills/unitcircle/uc-deploy-audit/SKILL.md +0 -511
- package/templates/ai-tools/skills/unitcircle/uc-deploy-audit/references/checks-data.md +0 -126
- package/templates/ai-tools/skills/unitcircle/uc-deploy-audit/references/checks-network.md +0 -88
- package/templates/ai-tools/skills/unitcircle/uc-deploy-audit/references/checks-runtime.md +0 -195
- package/templates/ai-tools/skills/unitcircle/uc-deploy-audit/references/security-doc-search.md +0 -179
- package/templates/ai-tools/skills/unitcircle/uc-deploy-audit/scripts/check_base.sh +0 -39
- package/templates/ai-tools/skills/unitcircle/uc-deploy-audit/scripts/check_capacity.sh +0 -278
- package/templates/ai-tools/skills/unitcircle/uc-deploy-audit/scripts/check_db.sh +0 -147
- package/templates/ai-tools/skills/unitcircle/uc-deploy-audit/scripts/check_docker.sh +0 -230
- package/templates/ai-tools/skills/unitcircle/uc-deploy-audit/scripts/check_env.sh +0 -64
- package/templates/ai-tools/skills/unitcircle/uc-deploy-audit/scripts/check_https.sh +0 -60
- package/templates/ai-tools/skills/unitcircle/uc-deploy-audit/scripts/check_logs.sh +0 -209
- package/templates/ai-tools/skills/unitcircle/uc-deploy-audit/scripts/check_nginx.sh +0 -100
- package/templates/ai-tools/skills/unitcircle/uc-deploy-audit/scripts/check_resilience.sh +0 -157
- package/templates/ai-tools/skills/unitcircle/uc-deploy-audit/scripts/check_secrets.sh +0 -265
- package/templates/ai-tools/skills/unitcircle/uc-deploy-audit/scripts/check_services.sh +0 -94
- package/templates/ai-tools/skills/unitcircle/uc-deploy-audit/scripts/check_ssh.sh +0 -56
- package/templates/ai-tools/skills/unitcircle/uc-deploy-audit/scripts/run_all.sh +0 -105
|
@@ -1,265 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
# 凭证强度审计 (只读, 全脱敏)
|
|
3
|
-
#
|
|
4
|
-
# 检查范围 (5 类):
|
|
5
|
-
# 1. .env 文件: PASSWORD/SECRET/TOKEN/KEY/AK/SK 字段
|
|
6
|
-
# 2. docker 容器内联 env (Config.Env)
|
|
7
|
-
# 3. Redis 容器 --requirepass 启动参数
|
|
8
|
-
# 4. Postgres 容器 POSTGRES_PASSWORD
|
|
9
|
-
# 5. SSH 私钥 类型 + 位数 (~/.ssh/id_*)
|
|
10
|
-
#
|
|
11
|
-
# 强制脱敏: 只输出派生指标 (len/classes/strength), 永不输出明文
|
|
12
|
-
# 字典词: 内置 ~30 个最常见弱口令
|
|
13
|
-
|
|
14
|
-
TARGET="$1"; shift
|
|
15
|
-
SSH_OPTS=("$@")
|
|
16
|
-
|
|
17
|
-
ssh "${SSH_OPTS[@]}" "${TARGET}" bash -s <<'REMOTE'
|
|
18
|
-
# ---------- 强度评估函数 ----------
|
|
19
|
-
# 输入: 一个秘密字符串(从 stdin)
|
|
20
|
-
# 输出: "len=N classes=K strength=STRONG/MEDIUM/WEAK reason=xxx"
|
|
21
|
-
# 不打印明文, 不写文件
|
|
22
|
-
strength_of() {
|
|
23
|
-
local val
|
|
24
|
-
IFS= read -r val
|
|
25
|
-
local len=${#val}
|
|
26
|
-
|
|
27
|
-
# 字典词内置(精简, 30 个最常见弱口令; 大小写不敏感子串匹配)
|
|
28
|
-
local weak_dict='password|passwd|123456|123123|qwerty|abc123|admin|administrator|root|test|demo|guest|user|welcome|letmein|changeme|secret|default|temp|public|private|master|sample|example|prod|dev|staging|backup|hello|monkey'
|
|
29
|
-
local is_dict=0
|
|
30
|
-
echo "$val" | grep -qiE "($weak_dict)" && is_dict=1
|
|
31
|
-
|
|
32
|
-
# 字符类
|
|
33
|
-
local has_upper=0 has_lower=0 has_digit=0 has_symbol=0
|
|
34
|
-
[[ "$val" =~ [A-Z] ]] && has_upper=1
|
|
35
|
-
[[ "$val" =~ [a-z] ]] && has_lower=1
|
|
36
|
-
[[ "$val" =~ [0-9] ]] && has_digit=1
|
|
37
|
-
[[ "$val" =~ [^a-zA-Z0-9] ]] && has_symbol=1
|
|
38
|
-
local classes=$(( has_upper + has_lower + has_digit + has_symbol ))
|
|
39
|
-
|
|
40
|
-
# 评级
|
|
41
|
-
local strength reason
|
|
42
|
-
if [[ "$len" -lt 8 ]]; then strength="WEAK"; reason="len<8"
|
|
43
|
-
elif [[ "$is_dict" == "1" ]]; then strength="WEAK"; reason="dict_match"
|
|
44
|
-
elif [[ "$len" -lt 16 ]]; then strength="MEDIUM"; reason="len<16"
|
|
45
|
-
elif [[ "$classes" -lt 3 ]]; then strength="MEDIUM"; reason="classes<3"
|
|
46
|
-
else strength="STRONG"; reason="ok"
|
|
47
|
-
fi
|
|
48
|
-
printf "len=%d classes=%d strength=%s reason=%s" "$len" "$classes" "$strength" "$reason"
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
# 排除明显是"数值/枚举配置参数"而非凭证的 key 名
|
|
52
|
-
# (子串匹配 TOKEN/KEY 会误命中 ACCESS_TOKEN_EXPIRE_MINUTES / KEY_TIMEOUT 这种)
|
|
53
|
-
is_config_not_secret() {
|
|
54
|
-
local key="$1"
|
|
55
|
-
echo "$key" | grep -qiE '(EXPIRE|EXPIRY|TTL|TIMEOUT|SECONDS|MINUTES|HOURS|DAYS|COUNT|LIMIT|RETRY|MAX|MIN|SIZE|LENGTH|INTERVAL|DELAY|ENABLED|DISABLED|MODE|TYPE|VERSION|PORT|HOST|URL|PATH|FILE|DIR)$|_(EXPIRE|TTL|TIMEOUT|SECONDS|MINUTES|HOURS|DAYS|COUNT|LIMIT|MAX|MIN|SIZE|MODE|TYPE)_'
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
# 包装: 给定 key+value, 加上"高敏字段长度门槛 32"判定
|
|
59
|
-
evaluate_secret() {
|
|
60
|
-
local key="$1"
|
|
61
|
-
local val="$2"
|
|
62
|
-
[[ -z "$val" ]] && { echo " (空值)"; return; }
|
|
63
|
-
|
|
64
|
-
# 判定是否真凭证字段 (key 名含 PASSWORD/SECRET/ACCESS_KEY_SECRET 等明确含义的)
|
|
65
|
-
# 这类即使值是纯数字短串(如某些服务默认密码 123456) 也必须评估为 WEAK 而非 SKIP
|
|
66
|
-
local is_true_credential=0
|
|
67
|
-
echo "$key" | grep -qiE '(PASSWORD|PASSWD|SECRET|PRIVATE[_-]?KEY|ACCESS[_-]?KEY[_-]?SECRET|_SK$|^SK_)' && is_true_credential=1
|
|
68
|
-
|
|
69
|
-
# Bug fix 1: 跳过明显是配置参数的 key (含 EXPIRE/TTL/TIMEOUT/MAX/MIN 等)
|
|
70
|
-
# 但真凭证字段不跳过
|
|
71
|
-
if [[ "$is_true_credential" == "0" ]] && is_config_not_secret "$key"; then
|
|
72
|
-
printf " %-30s [i] SKIP: 看起来是配置参数(非凭证), key 名含 EXPIRE/TTL/TIMEOUT/MAX 等\n" "$key"
|
|
73
|
-
return
|
|
74
|
-
fi
|
|
75
|
-
# Bug fix 1.b: 纯数字短值(像 30 / 86400 这种 TTL/expire) 跳过
|
|
76
|
-
# 但真凭证字段不跳过 (服务默认密码 123456 / Redis 默认 123 这种弱密码必须报)
|
|
77
|
-
if [[ "$is_true_credential" == "0" ]] && [[ "$val" =~ ^[0-9]+$ ]] && [[ ${#val} -lt 10 ]]; then
|
|
78
|
-
printf " %-30s [i] SKIP: 纯数字短值(看起来是配置参数, len=%d)\n" "$key" "${#val}"
|
|
79
|
-
return
|
|
80
|
-
fi
|
|
81
|
-
|
|
82
|
-
# 是否高敏字段
|
|
83
|
-
local high_sens=0
|
|
84
|
-
echo "$key" | grep -qiE 'SECRET|JWT|TOKEN|API[_-]?KEY|ACCESS[_-]?KEY[_-]?SECRET|PRIVATE[_-]?KEY|_AK$|_SK$|^AK_|^SK_' && high_sens=1
|
|
85
|
-
|
|
86
|
-
local result
|
|
87
|
-
result=$(printf '%s\n' "$val" | strength_of)
|
|
88
|
-
local len=$(echo "$result" | grep -oE 'len=[0-9]+' | cut -d= -f2)
|
|
89
|
-
local classes=$(echo "$result" | grep -oE 'classes=[0-9]+' | cut -d= -f2)
|
|
90
|
-
local strength=$(echo "$result" | grep -oE 'strength=[A-Z]+' | cut -d= -f2)
|
|
91
|
-
|
|
92
|
-
# Bug fix 2: 长度 >= 24 即视为 STRONG (即使 classes 少, 熵足够)
|
|
93
|
-
# 例如 48 字符 base64 / 64 字符 hex 即使只 2 类, 熵 >= 192 bits 远超 128 bits 安全门槛
|
|
94
|
-
if [[ "$strength" != "WEAK" && "$len" -ge 24 ]]; then
|
|
95
|
-
strength="STRONG"
|
|
96
|
-
result="${result/strength=MEDIUM/strength=STRONG}"
|
|
97
|
-
result="${result/reason=classes<3/reason=long_enough}"
|
|
98
|
-
result="${result/reason=len<16/reason=long_enough}"
|
|
99
|
-
fi
|
|
100
|
-
|
|
101
|
-
printf " %-30s %s" "$key" "$result"
|
|
102
|
-
# 严重级标记
|
|
103
|
-
if [[ "$strength" == "WEAK" ]]; then
|
|
104
|
-
printf " [!!!] CRITICAL: 弱凭证, 必须立即轮换\n"
|
|
105
|
-
elif [[ "$high_sens" == "1" && "$len" -lt 32 ]]; then
|
|
106
|
-
printf " [!!] HIGH: 高敏字段建议 >= 32 字符随机串\n"
|
|
107
|
-
elif [[ "$strength" == "MEDIUM" ]]; then
|
|
108
|
-
printf " [!] MEDIUM: 建议加长至 16+ 且 3 类字符\n"
|
|
109
|
-
else
|
|
110
|
-
printf " [OK]\n"
|
|
111
|
-
fi
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
# ---------- 1. .env 文件扫描 ----------
|
|
115
|
-
echo "########## 1. .env 文件凭证强度 ##########"
|
|
116
|
-
ENV_FILES=$(sudo -n find /home /opt /srv /root -maxdepth 6 -type f \
|
|
117
|
-
\( -name ".env" -o -name ".env.*" -o -name "*.env" \) 2>/dev/null \
|
|
118
|
-
| grep -vE '\.example|\.template|\.sample|\.bak|\.old|node_modules' \
|
|
119
|
-
| sort -u | head -20)
|
|
120
|
-
[[ -z "$ENV_FILES" ]] && ENV_FILES=$(find /home /opt /srv /root -maxdepth 6 -type f \
|
|
121
|
-
\( -name ".env" -o -name ".env.*" -o -name "*.env" \) 2>/dev/null \
|
|
122
|
-
| grep -vE '\.example|\.template|\.sample|\.bak|\.old|node_modules' \
|
|
123
|
-
| sort -u | head -20)
|
|
124
|
-
|
|
125
|
-
if [[ -z "$ENV_FILES" ]]; then
|
|
126
|
-
echo "[i] 未找到 .env 文件"
|
|
127
|
-
else
|
|
128
|
-
for f in $ENV_FILES; do
|
|
129
|
-
echo ""
|
|
130
|
-
echo "[$f]"
|
|
131
|
-
# 只挑密码类字段, 解析 KEY=VALUE
|
|
132
|
-
if ! sudo -n cat "$f" 2>/dev/null | head -1 >/dev/null && ! cat "$f" 2>/dev/null | head -1 >/dev/null; then
|
|
133
|
-
echo " [i] 不可读"
|
|
134
|
-
continue
|
|
135
|
-
fi
|
|
136
|
-
(sudo -n cat "$f" 2>/dev/null || cat "$f" 2>/dev/null) \
|
|
137
|
-
| grep -E '^[[:space:]]*[A-Z][A-Z0-9_]*[[:space:]]*=' \
|
|
138
|
-
| grep -iE '(PASSWORD|PASSWD|SECRET|TOKEN|API[_-]?KEY|ACCESS[_-]?KEY|PRIVATE[_-]?KEY|_AK|_SK|^AK_|^SK_)' \
|
|
139
|
-
| while IFS='=' read -r key val; do
|
|
140
|
-
key=$(echo "$key" | tr -d ' \t')
|
|
141
|
-
# 去引号 + 行尾注释
|
|
142
|
-
val=$(echo "$val" | sed -E 's/^[[:space:]]*//; s/[[:space:]]*#.*$//; s/^"//; s/"$//; s/^'\''//; s/'\''$//')
|
|
143
|
-
evaluate_secret "$key" "$val"
|
|
144
|
-
done
|
|
145
|
-
done
|
|
146
|
-
fi
|
|
147
|
-
|
|
148
|
-
# ---------- 2. docker 容器内联 env ----------
|
|
149
|
-
echo ""
|
|
150
|
-
echo "########## 2. Docker 容器内联 env 凭证强度 ##########"
|
|
151
|
-
if command -v docker >/dev/null 2>&1; then
|
|
152
|
-
for c in $(docker ps -q 2>/dev/null); do
|
|
153
|
-
name=$(docker inspect -f '{{.Name}}' "$c" 2>/dev/null | sed 's|^/||')
|
|
154
|
-
echo ""
|
|
155
|
-
echo "[$name]"
|
|
156
|
-
docker inspect --format '{{range .Config.Env}}{{println .}}{{end}}' "$c" 2>/dev/null \
|
|
157
|
-
| grep -iE '(PASSWORD|PASSWD|SECRET|TOKEN|API[_-]?KEY|ACCESS[_-]?KEY|PRIVATE[_-]?KEY|_AK=|_SK=|^AK_|^SK_)' \
|
|
158
|
-
| while IFS='=' read -r key val; do
|
|
159
|
-
key=$(echo "$key" | tr -d ' \t')
|
|
160
|
-
evaluate_secret "$key" "$val"
|
|
161
|
-
done
|
|
162
|
-
done
|
|
163
|
-
else
|
|
164
|
-
echo "[i] Docker 未安装"
|
|
165
|
-
fi
|
|
166
|
-
|
|
167
|
-
# ---------- 3. Redis requirepass (从启动参数提取) ----------
|
|
168
|
-
echo ""
|
|
169
|
-
echo "########## 3. Redis --requirepass 强度 ##########"
|
|
170
|
-
if command -v docker >/dev/null 2>&1; then
|
|
171
|
-
REDIS_FOUND=0
|
|
172
|
-
for c in $(docker ps -q 2>/dev/null); do
|
|
173
|
-
image=$(docker inspect -f '{{.Config.Image}}' "$c" 2>/dev/null)
|
|
174
|
-
if echo "$image" | grep -qi "redis"; then
|
|
175
|
-
REDIS_FOUND=1
|
|
176
|
-
name=$(docker inspect -f '{{.Name}}' "$c" 2>/dev/null | sed 's|^/||')
|
|
177
|
-
echo ""
|
|
178
|
-
echo "[$name]"
|
|
179
|
-
args=$(docker inspect -f '{{range .Args}}{{.}} {{end}}' "$c" 2>/dev/null)
|
|
180
|
-
pass=$(echo "$args" | grep -oE -- '--requirepass [^ ]+' | head -1 | awk '{print $2}')
|
|
181
|
-
if [[ -n "$pass" ]]; then
|
|
182
|
-
evaluate_secret "REDIS_PASSWORD(--requirepass)" "$pass"
|
|
183
|
-
else
|
|
184
|
-
echo " [!!!] CRITICAL: Redis 未设置 --requirepass"
|
|
185
|
-
fi
|
|
186
|
-
fi
|
|
187
|
-
done
|
|
188
|
-
[[ "$REDIS_FOUND" == "0" ]] && echo "[i] 未发现 Redis 容器"
|
|
189
|
-
fi
|
|
190
|
-
|
|
191
|
-
# ---------- 4. Postgres POSTGRES_PASSWORD (容器 env, 已在 2 覆盖, 此处单独 highlight) ----------
|
|
192
|
-
echo ""
|
|
193
|
-
echo "########## 4. Postgres POSTGRES_PASSWORD 强度 ##########"
|
|
194
|
-
if command -v docker >/dev/null 2>&1; then
|
|
195
|
-
PG_FOUND=0
|
|
196
|
-
for c in $(docker ps -q 2>/dev/null); do
|
|
197
|
-
image=$(docker inspect -f '{{.Config.Image}}' "$c" 2>/dev/null)
|
|
198
|
-
if echo "$image" | grep -qi "postgres"; then
|
|
199
|
-
PG_FOUND=1
|
|
200
|
-
name=$(docker inspect -f '{{.Name}}' "$c" 2>/dev/null | sed 's|^/||')
|
|
201
|
-
echo ""
|
|
202
|
-
echo "[$name]"
|
|
203
|
-
pass=$(docker inspect --format '{{range .Config.Env}}{{println .}}{{end}}' "$c" 2>/dev/null \
|
|
204
|
-
| grep '^POSTGRES_PASSWORD=' | head -1 | cut -d= -f2-)
|
|
205
|
-
if [[ -n "$pass" ]]; then
|
|
206
|
-
evaluate_secret "POSTGRES_PASSWORD" "$pass"
|
|
207
|
-
else
|
|
208
|
-
echo " [!!!] CRITICAL: 未取得 POSTGRES_PASSWORD (是否 secrets 挂载或 trust 认证?)"
|
|
209
|
-
fi
|
|
210
|
-
fi
|
|
211
|
-
done
|
|
212
|
-
[[ "$PG_FOUND" == "0" ]] && echo "[i] 未发现 Postgres 容器"
|
|
213
|
-
fi
|
|
214
|
-
|
|
215
|
-
# ---------- 5. SSH 私钥强度 ----------
|
|
216
|
-
echo ""
|
|
217
|
-
echo "########## 5. SSH 私钥类型 / 位数 ##########"
|
|
218
|
-
# 当前用户 + root 的 ~/.ssh/ (Bug fix 3: 去重, root 用户登录时 $HOME=/root 会重复)
|
|
219
|
-
SSH_DIRS=$(printf '%s\n' "$HOME/.ssh" /root/.ssh /home/*/.ssh 2>/dev/null | sort -u)
|
|
220
|
-
for ssh_dir in $SSH_DIRS; do
|
|
221
|
-
[[ -d "$ssh_dir" ]] || continue
|
|
222
|
-
for kf in "$ssh_dir"/id_rsa "$ssh_dir"/id_ed25519 "$ssh_dir"/id_ecdsa "$ssh_dir"/id_dsa; do
|
|
223
|
-
[[ -f "$kf" ]] || continue
|
|
224
|
-
info=$(ssh-keygen -l -f "$kf" 2>/dev/null || sudo -n ssh-keygen -l -f "$kf" 2>/dev/null)
|
|
225
|
-
if [[ -z "$info" ]]; then
|
|
226
|
-
echo " $kf [i] 无法读取(权限?)"
|
|
227
|
-
continue
|
|
228
|
-
fi
|
|
229
|
-
bits=$(echo "$info" | awk '{print $1}')
|
|
230
|
-
type=$(echo "$info" | grep -oE '\([A-Z0-9]+\)$' | tr -d '()')
|
|
231
|
-
perm=$(stat -c '%a' "$kf" 2>/dev/null)
|
|
232
|
-
|
|
233
|
-
case "$type" in
|
|
234
|
-
ED25519)
|
|
235
|
-
printf " %-40s type=%-8s bits=%-4s perm=%s [OK]\n" "$kf" "$type" "$bits" "$perm" ;;
|
|
236
|
-
RSA)
|
|
237
|
-
if [[ "$bits" -ge 4096 ]]; then mark="[OK]"
|
|
238
|
-
elif [[ "$bits" -ge 3072 ]]; then mark="[OK] (建议升 ed25519)"
|
|
239
|
-
elif [[ "$bits" -ge 2048 ]]; then mark="[!] MEDIUM: RSA-${bits} 可接受但建议升 ed25519 或 RSA-4096"
|
|
240
|
-
else mark="[!!!] CRITICAL: RSA-${bits} 已不安全, 立即轮换"
|
|
241
|
-
fi
|
|
242
|
-
printf " %-40s type=%-8s bits=%-4s perm=%s %s\n" "$kf" "$type" "$bits" "$perm" "$mark" ;;
|
|
243
|
-
ECDSA)
|
|
244
|
-
printf " %-40s type=%-8s bits=%-4s perm=%s [!] MEDIUM: ECDSA 存疑(NIST 曲线), 建议 ed25519\n" "$kf" "$type" "$bits" "$perm" ;;
|
|
245
|
-
DSA)
|
|
246
|
-
printf " %-40s type=%-8s bits=%-4s perm=%s [!!!] CRITICAL: DSA 已废弃, 立即轮换\n" "$kf" "$type" "$bits" "$perm" ;;
|
|
247
|
-
*)
|
|
248
|
-
printf " %-40s type=%-8s bits=%-4s perm=%s\n" "$kf" "$type" "$bits" "$perm" ;;
|
|
249
|
-
esac
|
|
250
|
-
|
|
251
|
-
# 权限检查
|
|
252
|
-
if [[ -n "$perm" && "$perm" != "600" && "$perm" != "400" ]]; then
|
|
253
|
-
echo " [!!] HIGH: 私钥权限 $perm 过宽, 应 600"
|
|
254
|
-
fi
|
|
255
|
-
done
|
|
256
|
-
done
|
|
257
|
-
|
|
258
|
-
echo ""
|
|
259
|
-
echo "########## 凭证强度汇总 ##########"
|
|
260
|
-
echo "[i] 修复指引:"
|
|
261
|
-
echo " - WEAK 密码: 立即轮换 (建议 >= 16 字符 + 三类字符的强密码)"
|
|
262
|
-
echo " - 高敏字段 (JWT/SECRET/AK/SK): >= 32 字符随机串"
|
|
263
|
-
echo " - 生成命令: openssl rand -base64 24 | tr -d '=+/' | cut -c1-20"
|
|
264
|
-
echo " - 高敏: openssl rand -hex 32 (生成 64 字符 hex token)"
|
|
265
|
-
REMOTE
|
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
# 依赖服务连通性 / 防火墙
|
|
3
|
-
TARGET="$1"; shift
|
|
4
|
-
SSH_OPTS=("$@")
|
|
5
|
-
|
|
6
|
-
ssh "${SSH_OPTS[@]}" "${TARGET}" bash -s <<'REMOTE'
|
|
7
|
-
echo "--- 防火墙状态 ---"
|
|
8
|
-
if command -v ufw >/dev/null 2>&1; then
|
|
9
|
-
echo "[ufw]"
|
|
10
|
-
sudo -n ufw status verbose 2>/dev/null || echo " [!] 需 sudo 查看 ufw"
|
|
11
|
-
fi
|
|
12
|
-
if command -v firewall-cmd >/dev/null 2>&1; then
|
|
13
|
-
echo "[firewalld]"
|
|
14
|
-
sudo -n firewall-cmd --state 2>/dev/null
|
|
15
|
-
sudo -n firewall-cmd --list-all 2>/dev/null
|
|
16
|
-
fi
|
|
17
|
-
echo "[iptables]"
|
|
18
|
-
sudo -n iptables -L INPUT -n --line-numbers 2>/dev/null | head -20 || echo " [i] 无法读取 iptables"
|
|
19
|
-
|
|
20
|
-
echo ""
|
|
21
|
-
echo "--- 监听端口 (按地址分组) ---"
|
|
22
|
-
(ss -tlnp 2>/dev/null || netstat -tlnp 2>/dev/null) | awk 'NR>1 {print $4}' | awk -F: '{
|
|
23
|
-
port=$NF;
|
|
24
|
-
ip=substr($0,1,length($0)-length(port)-1);
|
|
25
|
-
if (ip=="0.0.0.0" || ip=="*" || ip=="[::]") public[port]++;
|
|
26
|
-
else if (ip=="127.0.0.1" || ip=="[::1]") loop[port]++;
|
|
27
|
-
else internal[port]++;
|
|
28
|
-
}
|
|
29
|
-
END {
|
|
30
|
-
print "公网监听 (0.0.0.0 / *):"
|
|
31
|
-
for (p in public) print " " p
|
|
32
|
-
print "内网监听 (具体 IP):"
|
|
33
|
-
for (p in internal) print " " p
|
|
34
|
-
print "回环监听 (127.0.0.1):"
|
|
35
|
-
for (p in loop) print " " p
|
|
36
|
-
}'
|
|
37
|
-
|
|
38
|
-
echo ""
|
|
39
|
-
echo "--- 系统负载与内存 ---"
|
|
40
|
-
uptime
|
|
41
|
-
free -h 2>/dev/null | head -3
|
|
42
|
-
|
|
43
|
-
echo ""
|
|
44
|
-
echo "--- 磁盘 ---"
|
|
45
|
-
df -h | grep -vE "tmpfs|udev" | head -10
|
|
46
|
-
|
|
47
|
-
echo ""
|
|
48
|
-
echo "--- 已安装的 Web 应用进程 (常见) ---"
|
|
49
|
-
ps -eo user,pid,%cpu,%mem,cmd --sort=-%mem 2>/dev/null \
|
|
50
|
-
| grep -E "(nginx|node|python|uvicorn|gunicorn|java|php-fpm|redis-server|postgres|mysql|mongod)" \
|
|
51
|
-
| grep -v grep | head -20
|
|
52
|
-
|
|
53
|
-
echo ""
|
|
54
|
-
echo "--- 应用健康检查端点 (经本地 nginx 回环 + --resolve, 避免 hairpin NAT) ---"
|
|
55
|
-
NGINX_DUMP=$(sudo -n nginx -T 2>/dev/null || nginx -T 2>/dev/null || true)
|
|
56
|
-
# 只取真实 server_name 指令行(行首仅空白 + 关键字), 去行内注释, 拆多域名, 过滤 _ / 通配 / 空 / 非法 token
|
|
57
|
-
# 旧实现用 awk '/server_name/' 会误匹配注释行里的 server_name 文字, 产出 _) 1. :80 等垃圾域名
|
|
58
|
-
DOMAINS=$(echo "$NGINX_DUMP" \
|
|
59
|
-
| grep -E '^[[:space:]]*server_name[[:space:]]' \
|
|
60
|
-
| sed -E 's/#.*$//; s/^[[:space:]]*server_name[[:space:]]+//; s/;.*$//' \
|
|
61
|
-
| tr ' ' '\n' \
|
|
62
|
-
| grep -E '^[A-Za-z0-9]([A-Za-z0-9.-]*[A-Za-z0-9])?$' \
|
|
63
|
-
| grep -v '^_$' \
|
|
64
|
-
| sort -u | head -5)
|
|
65
|
-
[[ -z "$DOMAINS" ]] && DOMAINS="localhost"
|
|
66
|
-
# 是否启用 https(443 在监听); 公网域名从本机直连会触发 hairpin NAT 返回 000,
|
|
67
|
-
# 用 --resolve 把域名钉到回环, 既走本地 nginx 又匹配 SNI 证书, 才是白盒正解
|
|
68
|
-
HAS_HTTPS=$( (ss -tln 2>/dev/null || netstat -tln 2>/dev/null) | grep -qE ':443[[:space:]]' && echo yes || echo no )
|
|
69
|
-
for D in $DOMAINS; do
|
|
70
|
-
for path in "/api/health" "/health" "/healthz" "/_health" "/status"; do
|
|
71
|
-
if [[ "$HAS_HTTPS" == "yes" ]]; then
|
|
72
|
-
code=$(curl -k -sS -o /dev/null -w "%{http_code}" --max-time 3 --resolve "$D:443:127.0.0.1" "https://$D$path" 2>/dev/null || echo "000")
|
|
73
|
-
scheme="https"
|
|
74
|
-
else
|
|
75
|
-
code=$(curl -sS -o /dev/null -w "%{http_code}" --max-time 3 --resolve "$D:80:127.0.0.1" "http://$D$path" 2>/dev/null || echo "000")
|
|
76
|
-
scheme="http"
|
|
77
|
-
fi
|
|
78
|
-
[[ "$code" != "404" && "$code" != "000" ]] && printf " %s://%s%s -> %s\n" "$scheme" "$D" "$path" "$code"
|
|
79
|
-
done
|
|
80
|
-
done
|
|
81
|
-
|
|
82
|
-
echo ""
|
|
83
|
-
echo "--- 系统更新提示 ---"
|
|
84
|
-
if command -v apt >/dev/null 2>&1; then
|
|
85
|
-
sudo -n apt list --upgradable 2>/dev/null | head -10 || echo " [i] 无法检查 apt 更新"
|
|
86
|
-
elif command -v yum >/dev/null 2>&1; then
|
|
87
|
-
sudo -n yum check-update 2>/dev/null | head -10 || echo " [i] 无法检查 yum 更新"
|
|
88
|
-
fi
|
|
89
|
-
|
|
90
|
-
echo ""
|
|
91
|
-
echo "--- 内核/系统启动时间 ---"
|
|
92
|
-
who -b 2>/dev/null
|
|
93
|
-
echo "kernel: $(uname -r)"
|
|
94
|
-
REMOTE
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
# SSH 安全检查 (只读)
|
|
3
|
-
TARGET="$1"; shift
|
|
4
|
-
SSH_OPTS=("$@")
|
|
5
|
-
|
|
6
|
-
ssh "${SSH_OPTS[@]}" "${TARGET}" bash -s <<'REMOTE'
|
|
7
|
-
echo "--- /etc/ssh/sshd_config (filtered key directives) ---"
|
|
8
|
-
SSHD_CONF="/etc/ssh/sshd_config"
|
|
9
|
-
SSHD_DIR="/etc/ssh/sshd_config.d"
|
|
10
|
-
if [[ -r "$SSHD_CONF" ]]; then
|
|
11
|
-
grep -Ei "^[[:space:]]*(PermitRootLogin|PasswordAuthentication|PubkeyAuthentication|PermitEmptyPasswords|Port|Protocol|MaxAuthTries|LoginGraceTime|AllowUsers|AllowGroups|DenyUsers|DenyGroups|ChallengeResponseAuthentication|UsePAM|X11Forwarding|ClientAliveInterval|ClientAliveCountMax|LogLevel|Banner)" "$SSHD_CONF" 2>/dev/null
|
|
12
|
-
if [[ -d "$SSHD_DIR" ]]; then
|
|
13
|
-
echo "--- $SSHD_DIR/*.conf ---"
|
|
14
|
-
grep -EiH "^[[:space:]]*(PermitRootLogin|PasswordAuthentication|PubkeyAuthentication|PermitEmptyPasswords|Port|Protocol|MaxAuthTries)" "$SSHD_DIR"/*.conf 2>/dev/null
|
|
15
|
-
fi
|
|
16
|
-
else
|
|
17
|
-
echo "[!] $SSHD_CONF 不可读 (需要 sudo)"
|
|
18
|
-
fi
|
|
19
|
-
|
|
20
|
-
echo ""
|
|
21
|
-
echo "--- effective sshd config (sshd -T, 需 sudo) ---"
|
|
22
|
-
sudo -n sshd -T 2>/dev/null | grep -Ei "^(permitrootlogin|passwordauthentication|pubkeyauthentication|permitemptypasswords|port|protocol|maxauthtries|logingracetime|allowusers|allowgroups|x11forwarding|loglevel)" || echo "[i] 无法读取 effective config (需要 sudo 或 sshd -T 不可用)"
|
|
23
|
-
|
|
24
|
-
echo ""
|
|
25
|
-
echo "--- ssh process & version ---"
|
|
26
|
-
sshd -V 2>&1 | head -2 || ssh -V 2>&1
|
|
27
|
-
|
|
28
|
-
echo ""
|
|
29
|
-
echo "--- recent failed logins (last 20) ---"
|
|
30
|
-
sudo -n journalctl _COMM=sshd --since "7 days ago" 2>/dev/null | grep -Ei "failed|invalid" | tail -20 \
|
|
31
|
-
|| sudo -n grep -Ei "failed|invalid" /var/log/auth.log 2>/dev/null | tail -20 \
|
|
32
|
-
|| echo "[i] 无法读取认证日志 (需要 sudo)"
|
|
33
|
-
|
|
34
|
-
echo ""
|
|
35
|
-
echo "--- fail2ban status ---"
|
|
36
|
-
if command -v fail2ban-client >/dev/null 2>&1; then
|
|
37
|
-
sudo -n fail2ban-client status 2>/dev/null || echo "[i] fail2ban 已安装,但需要 sudo 查看状态"
|
|
38
|
-
else
|
|
39
|
-
echo "[!] fail2ban 未安装"
|
|
40
|
-
fi
|
|
41
|
-
|
|
42
|
-
echo ""
|
|
43
|
-
echo "--- authorized_keys 概览 (当前用户) ---"
|
|
44
|
-
if [[ -r ~/.ssh/authorized_keys ]]; then
|
|
45
|
-
awk '{print " key: " $1 " " substr($2,1,16) "... " $3}' ~/.ssh/authorized_keys
|
|
46
|
-
echo " total: $(wc -l < ~/.ssh/authorized_keys) keys"
|
|
47
|
-
else
|
|
48
|
-
echo "[i] 当前用户无 authorized_keys"
|
|
49
|
-
fi
|
|
50
|
-
|
|
51
|
-
echo ""
|
|
52
|
-
echo "--- /root/.ssh/authorized_keys (需 sudo) ---"
|
|
53
|
-
sudo -n test -f /root/.ssh/authorized_keys 2>/dev/null && \
|
|
54
|
-
echo " [!] root 用户存在 authorized_keys, 共 $(sudo -n wc -l < /root/.ssh/authorized_keys 2>/dev/null) 行" \
|
|
55
|
-
|| echo "[i] 无 root authorized_keys 或无 sudo 权限"
|
|
56
|
-
REMOTE
|
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
# uc-deploy-audit: 一键全量巡检(subagent 不可用时的串行/并行退化方案)
|
|
3
|
-
#
|
|
4
|
-
# 优先做法是让 Claude 用 subagent 并行派遣多个 Agent 跑各类 check_xxx.sh
|
|
5
|
-
# (见 SKILL.md Step 4)。本脚本仅作为本地一键回退使用。
|
|
6
|
-
#
|
|
7
|
-
# 用法:
|
|
8
|
-
# ./run_all.sh <user>@<host> [-p <port>] [-i <key>] [--serial]
|
|
9
|
-
#
|
|
10
|
-
# 默认 8 路并行。--serial 强制串行。
|
|
11
|
-
|
|
12
|
-
set -uo pipefail
|
|
13
|
-
|
|
14
|
-
if [[ $# -lt 1 ]]; then
|
|
15
|
-
echo "Usage: $0 <user>@<host|alias> [-p <port>] [-i <key>] [--serial]" >&2
|
|
16
|
-
exit 1
|
|
17
|
-
fi
|
|
18
|
-
|
|
19
|
-
TARGET="$1"; shift
|
|
20
|
-
SSH_OPTS=(-o ConnectTimeout=10 -o BatchMode=yes -o StrictHostKeyChecking=accept-new)
|
|
21
|
-
PARALLEL=true
|
|
22
|
-
|
|
23
|
-
while [[ $# -gt 0 ]]; do
|
|
24
|
-
case "$1" in
|
|
25
|
-
-p) SSH_OPTS+=(-p "$2"); shift 2;;
|
|
26
|
-
-i) SSH_OPTS+=(-i "$2"); shift 2;;
|
|
27
|
-
--serial) PARALLEL=false; shift;;
|
|
28
|
-
*) echo "Unknown arg: $1" >&2; exit 1;;
|
|
29
|
-
esac
|
|
30
|
-
done
|
|
31
|
-
|
|
32
|
-
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
33
|
-
TMP_DIR=$(mktemp -d -t uc-audit-XXXXXX)
|
|
34
|
-
trap 'rm -rf "$TMP_DIR"' EXIT
|
|
35
|
-
|
|
36
|
-
# 检查项: <section_name>:<script_name>
|
|
37
|
-
SECTIONS=(
|
|
38
|
-
"BASE_INFO:check_base.sh"
|
|
39
|
-
"SSH:check_ssh.sh"
|
|
40
|
-
"NGINX:check_nginx.sh"
|
|
41
|
-
"DB:check_db.sh"
|
|
42
|
-
"HTTPS:check_https.sh"
|
|
43
|
-
"ENV:check_env.sh"
|
|
44
|
-
"DOCKER:check_docker.sh"
|
|
45
|
-
"SERVICES:check_services.sh"
|
|
46
|
-
"RESILIENCE:check_resilience.sh"
|
|
47
|
-
"LOGS:check_logs.sh"
|
|
48
|
-
"CAPACITY:check_capacity.sh"
|
|
49
|
-
"SECRETS:check_secrets.sh"
|
|
50
|
-
)
|
|
51
|
-
|
|
52
|
-
echo "========================================"
|
|
53
|
-
echo " uc-deploy-audit | target: ${TARGET}"
|
|
54
|
-
echo " timestamp: $(date -u +%Y-%m-%dT%H:%M:%SZ)"
|
|
55
|
-
echo " mode: $([ "$PARALLEL" = true ] && echo "parallel (${#SECTIONS[@]} workers)" || echo 'serial')"
|
|
56
|
-
echo "========================================"
|
|
57
|
-
|
|
58
|
-
run_section() {
|
|
59
|
-
local name="$1"
|
|
60
|
-
local script="$2"
|
|
61
|
-
local out_file="${TMP_DIR}/${name}.out"
|
|
62
|
-
{
|
|
63
|
-
echo "########## SECTION: ${name} ##########"
|
|
64
|
-
bash "${SCRIPT_DIR}/${script}" "${TARGET}" "${SSH_OPTS[@]}" 2>&1 \
|
|
65
|
-
|| echo "[!] ${name} 部分失败"
|
|
66
|
-
echo "########## END: ${name} ##########"
|
|
67
|
-
} > "$out_file" 2>&1
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
if [[ "$PARALLEL" == "true" ]]; then
|
|
71
|
-
# 并行:所有 section 后台启动
|
|
72
|
-
pids=()
|
|
73
|
-
for entry in "${SECTIONS[@]}"; do
|
|
74
|
-
name="${entry%%:*}"
|
|
75
|
-
script="${entry##*:}"
|
|
76
|
-
run_section "$name" "$script" &
|
|
77
|
-
pids+=($!)
|
|
78
|
-
done
|
|
79
|
-
|
|
80
|
-
# 等所有完成
|
|
81
|
-
for pid in "${pids[@]}"; do
|
|
82
|
-
wait "$pid"
|
|
83
|
-
done
|
|
84
|
-
|
|
85
|
-
# 按顺序输出结果(保证报告分类有序)
|
|
86
|
-
for entry in "${SECTIONS[@]}"; do
|
|
87
|
-
name="${entry%%:*}"
|
|
88
|
-
echo ""
|
|
89
|
-
cat "${TMP_DIR}/${name}.out"
|
|
90
|
-
done
|
|
91
|
-
else
|
|
92
|
-
# 串行
|
|
93
|
-
for entry in "${SECTIONS[@]}"; do
|
|
94
|
-
name="${entry%%:*}"
|
|
95
|
-
script="${entry##*:}"
|
|
96
|
-
echo ""
|
|
97
|
-
run_section "$name" "$script"
|
|
98
|
-
cat "${TMP_DIR}/${name}.out"
|
|
99
|
-
done
|
|
100
|
-
fi
|
|
101
|
-
|
|
102
|
-
echo ""
|
|
103
|
-
echo "========================================"
|
|
104
|
-
echo " 巡检数据采集完成,请由 Claude 分析生成报告"
|
|
105
|
-
echo "========================================"
|