create-dwy 0.16.1 → 0.17.1

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.
Files changed (105) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/bin/index.js +23 -19
  3. package/package.json +1 -1
  4. package/src/cli-help.js +44 -0
  5. package/src/sync-all.js +303 -59
  6. package/src/sync-global-skills.js +167 -0
  7. package/src/sync.js +21 -11
  8. package/templates/ai-tools/CHANGELOG.md +134 -0
  9. package/templates/ai-tools/VERSION +1 -1
  10. package/templates/ai-tools/rules/Android/dwy-android-core.md +65 -1
  11. package/templates/ai-tools/rules/Python/dwy-python-core.md +47 -0
  12. package/templates/ai-tools/rules/Vue/dwy-vue-core.md +55 -0
  13. package/templates/ai-tools/rules/iOS/dwy-swift-core.md +46 -0
  14. package/templates/ai-tools/rules//345/274/200/345/217/221/346/265/201/347/250/213/dwy-oss-commercial-license.md +128 -0
  15. 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
  16. 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
  17. 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
  18. 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
  19. 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
  20. 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
  21. package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-publish/SKILL.md +11 -8
  22. package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-publish/references/android.md +2 -1
  23. 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
  24. package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-publish/references/changelog.md +24 -4
  25. 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
  26. 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
  27. 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
  28. package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-publish/references/harmony.md +2 -1
  29. package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-publish/references/ios.md +3 -2
  30. 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
  31. package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-semver/SKILL.md +1 -1
  32. package/templates/ai-tools/skills//345/237/272/347/241/200/345/272/223/dwy-eapi/references/tasks-integration-guide.md +2 -2
  33. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/README.md +57 -0
  34. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/dwy-doubao-tts/SKILL.md +147 -0
  35. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/dwy-doubao-tts/references/api.md +43 -0
  36. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/dwy-doubao-tts/references/config.example.yaml +33 -0
  37. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/dwy-doubao-tts/scripts/global_config.py +89 -0
  38. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/dwy-doubao-tts/scripts/setup_config.py +175 -0
  39. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/dwy-doubao-tts/scripts/synthesize.py +339 -0
  40. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/media-platform-packaging/SKILL.md +127 -0
  41. 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
  42. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/media-platform-packaging/references/platform-copy-examples.md +37 -0
  43. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/media-platform-packaging/references/platform-posting-times.md +193 -0
  44. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0005-ideation/SKILL.md +42 -0
  45. 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
  46. 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
  47. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0010-product/SKILL.md +106 -0
  48. 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
  49. 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
  50. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0030-facts/SKILL.md +60 -0
  51. 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
  52. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0030-facts/scripts/generate_html.py +1287 -0
  53. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0030-facts/scripts/generate_report.py +189 -0
  54. 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
  55. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0040-script/SKILL.md +36 -0
  56. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0040-script/templates/README.md +10 -0
  57. 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
  58. 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
  59. 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
  60. 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
  61. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0050-design/SKILL.md +55 -0
  62. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0060-assets/SKILL.md +29 -0
  63. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0070-package/SKILL.md +42 -0
  64. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0070-package/scripts/validate_shots.py +207 -0
  65. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0070-package/shots.schema.json +186 -0
  66. 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
  67. 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
  68. 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
  69. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0080-factory/SKILL.md +58 -0
  70. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-comic-kit/SKILL.md +424 -0
  71. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-comic-kit/evals.md +41 -0
  72. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-flow/CONTRACT.md +123 -0
  73. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-flow/SKILL.md +81 -0
  74. 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
  75. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-knowledge-town/SKILL.md +78 -0
  76. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-knowledge-town/agents/openai.yaml +4 -0
  77. 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
  78. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-knowledge-town/assets/remotion/AudioTracks.tsx +20 -0
  79. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-knowledge-town/assets/remotion/CaptionLayer.tsx +18 -0
  80. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-knowledge-town/assets/remotion/CueTimeline.ts +24 -0
  81. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-knowledge-town/assets/remotion/KnowledgeTownComposition.tsx +21 -0
  82. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-knowledge-town/references/cinematic-direction.md +73 -0
  83. 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
  84. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-knowledge-town/references/style-guide.md +43 -0
  85. 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
  86. 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
  87. 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
  88. package/templates/ai-tools/skills/unitcircle/uc-deploy-audit/SKILL.md +0 -511
  89. package/templates/ai-tools/skills/unitcircle/uc-deploy-audit/references/checks-data.md +0 -126
  90. package/templates/ai-tools/skills/unitcircle/uc-deploy-audit/references/checks-network.md +0 -88
  91. package/templates/ai-tools/skills/unitcircle/uc-deploy-audit/references/checks-runtime.md +0 -195
  92. package/templates/ai-tools/skills/unitcircle/uc-deploy-audit/references/security-doc-search.md +0 -179
  93. package/templates/ai-tools/skills/unitcircle/uc-deploy-audit/scripts/check_base.sh +0 -39
  94. package/templates/ai-tools/skills/unitcircle/uc-deploy-audit/scripts/check_capacity.sh +0 -278
  95. package/templates/ai-tools/skills/unitcircle/uc-deploy-audit/scripts/check_db.sh +0 -147
  96. package/templates/ai-tools/skills/unitcircle/uc-deploy-audit/scripts/check_docker.sh +0 -230
  97. package/templates/ai-tools/skills/unitcircle/uc-deploy-audit/scripts/check_env.sh +0 -64
  98. package/templates/ai-tools/skills/unitcircle/uc-deploy-audit/scripts/check_https.sh +0 -60
  99. package/templates/ai-tools/skills/unitcircle/uc-deploy-audit/scripts/check_logs.sh +0 -209
  100. package/templates/ai-tools/skills/unitcircle/uc-deploy-audit/scripts/check_nginx.sh +0 -100
  101. package/templates/ai-tools/skills/unitcircle/uc-deploy-audit/scripts/check_resilience.sh +0 -157
  102. package/templates/ai-tools/skills/unitcircle/uc-deploy-audit/scripts/check_secrets.sh +0 -265
  103. package/templates/ai-tools/skills/unitcircle/uc-deploy-audit/scripts/check_services.sh +0 -94
  104. package/templates/ai-tools/skills/unitcircle/uc-deploy-audit/scripts/check_ssh.sh +0 -56
  105. 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 "========================================"