vk-ssl-auto-deploy 0.2.0 → 0.2.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.
- package/package.json +1 -1
- package/routes/cert.js +73 -72
package/package.json
CHANGED
package/routes/cert.js
CHANGED
|
@@ -38,8 +38,8 @@ router.post('/deploy-cert', upload.single('file'), async (req, res, next) => {
|
|
|
38
38
|
const clientIP = getClientIP(req);
|
|
39
39
|
if (!isIPInWhitelist(clientIP, config.ipWhitelist)) {
|
|
40
40
|
console.warn(`[IP白名单拦截] IP: ${clientIP} 尝试部署证书但不在白名单中`);
|
|
41
|
-
return res.json({
|
|
42
|
-
code: 4030,
|
|
41
|
+
return res.json({
|
|
42
|
+
code: 4030,
|
|
43
43
|
msg: 'IP地址不在白名单中,访问被拒绝',
|
|
44
44
|
ip: clientIP
|
|
45
45
|
});
|
|
@@ -66,10 +66,11 @@ router.post('/deploy-cert', upload.single('file'), async (req, res, next) => {
|
|
|
66
66
|
// 2. 创建cert目录和子目录
|
|
67
67
|
const projectRoot = path.join(__dirname, '..');
|
|
68
68
|
// 使用配置文件中的 certPath,支持绝对路径和相对路径
|
|
69
|
-
const certBaseDir = path.isAbsolute(config.certPath)
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
const certDir = path.resolve(certBaseDir, certName);
|
|
69
|
+
const certBaseDir = path.isAbsolute(config.certPath) ?
|
|
70
|
+
config.certPath :
|
|
71
|
+
path.join(projectRoot, config.certPath);
|
|
72
|
+
const certDir = path.resolve(certBaseDir, certName);
|
|
73
|
+
const userCertDir = certDir.replace(/\\/g, '/');
|
|
73
74
|
|
|
74
75
|
// 确保cert根目录存在
|
|
75
76
|
if (!fs.existsSync(certBaseDir)) {
|
|
@@ -91,18 +92,18 @@ router.post('/deploy-cert', upload.single('file'), async (req, res, next) => {
|
|
|
91
92
|
|
|
92
93
|
// 统计信息
|
|
93
94
|
const stats = {
|
|
94
|
-
total: 0,
|
|
95
|
-
saved: 0,
|
|
96
|
-
filtered: 0,
|
|
97
|
-
savedFiles: [],
|
|
98
|
-
filteredFiles: []
|
|
95
|
+
total: 0, // 总文件数
|
|
96
|
+
saved: 0, // 成功保存的文件数
|
|
97
|
+
filtered: 0, // 被过滤的文件数
|
|
98
|
+
savedFiles: [], // 保存的文件列表
|
|
99
|
+
filteredFiles: [] // 被过滤的文件列表(含原因)
|
|
99
100
|
};
|
|
100
101
|
|
|
101
102
|
// 遍历并验证每个文件
|
|
102
103
|
zipEntries.forEach((entry) => {
|
|
103
104
|
if (!entry.isDirectory) {
|
|
104
105
|
stats.total++;
|
|
105
|
-
|
|
106
|
+
|
|
106
107
|
const filename = path.basename(entry.entryName);
|
|
107
108
|
const entryData = entry.getData();
|
|
108
109
|
|
|
@@ -122,10 +123,10 @@ router.post('/deploy-cert', upload.single('file'), async (req, res, next) => {
|
|
|
122
123
|
|
|
123
124
|
// 写入文件
|
|
124
125
|
fs.writeFileSync(entryPath, entryData);
|
|
125
|
-
|
|
126
|
+
|
|
126
127
|
stats.saved++;
|
|
127
128
|
stats.savedFiles.push(entry.entryName);
|
|
128
|
-
|
|
129
|
+
|
|
129
130
|
console.log(`[文件已保存] ${entry.entryName} (${entryData.length} bytes)`);
|
|
130
131
|
} catch (writeError) {
|
|
131
132
|
console.error(`[文件写入失败] ${entry.entryName}:`, writeError.message);
|
|
@@ -142,7 +143,7 @@ router.post('/deploy-cert', upload.single('file'), async (req, res, next) => {
|
|
|
142
143
|
filename: entry.entryName,
|
|
143
144
|
reason: validation.reason
|
|
144
145
|
});
|
|
145
|
-
|
|
146
|
+
|
|
146
147
|
console.warn(`[文件已过滤] ${entry.entryName}: ${validation.reason}`);
|
|
147
148
|
}
|
|
148
149
|
}
|
|
@@ -162,68 +163,68 @@ router.post('/deploy-cert', upload.single('file'), async (req, res, next) => {
|
|
|
162
163
|
});
|
|
163
164
|
}
|
|
164
165
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
166
|
+
console.log(`[证书部署成功] 名称: ${certName}, 路径: ${userCertDir}, 保存: ${stats.saved}个, 过滤: ${stats.filtered}个`);
|
|
167
|
+
|
|
168
|
+
// 4. 执行回调命令
|
|
169
|
+
const commandResults = [];
|
|
170
|
+
if (config.callbackCommand && Array.isArray(config.callbackCommand) && config.callbackCommand.length > 0) {
|
|
171
|
+
console.log(`[开始执行回调命令] 共${config.callbackCommand.length}个命令`);
|
|
172
|
+
|
|
173
|
+
for (let i = 0; i < config.callbackCommand.length; i++) {
|
|
174
|
+
const command = config.callbackCommand[i];
|
|
175
|
+
const commandResult = {
|
|
176
|
+
command: command,
|
|
177
|
+
index: i + 1,
|
|
178
|
+
success: false,
|
|
179
|
+
output: '',
|
|
180
|
+
error: ''
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
try {
|
|
184
|
+
console.log(`[执行命令 ${i + 1}/${config.callbackCommand.length}] ${command}`);
|
|
185
|
+
const { stdout, stderr } = await execAsync(command, {
|
|
186
|
+
timeout: 30000, // 30秒超时
|
|
187
|
+
maxBuffer: 1024 * 1024 // 1MB buffer
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
commandResult.success = true;
|
|
191
|
+
commandResult.output = stdout ? stdout.trim() : '';
|
|
192
|
+
if (stderr) {
|
|
193
|
+
commandResult.error = stderr.trim();
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
console.log(`[命令执行成功 ${i + 1}/${config.callbackCommand.length}] ${command}`);
|
|
197
|
+
if (stdout) console.log(`[命令输出] ${stdout.trim()}`);
|
|
198
|
+
if (stderr) console.warn(`[命令stderr] ${stderr.trim()}`);
|
|
199
|
+
|
|
200
|
+
} catch (cmdError) {
|
|
201
|
+
commandResult.success = false;
|
|
202
|
+
commandResult.error = cmdError.message;
|
|
203
|
+
if (cmdError.stdout) commandResult.output = cmdError.stdout.trim();
|
|
204
|
+
if (cmdError.stderr) commandResult.error += '\n' + cmdError.stderr.trim();
|
|
205
|
+
|
|
206
|
+
console.error(`[命令执行失败 ${i + 1}/${config.callbackCommand.length}] ${command}:`, cmdError.message);
|
|
193
207
|
}
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
if (stdout) console.log(`[命令输出] ${stdout.trim()}`);
|
|
197
|
-
if (stderr) console.warn(`[命令stderr] ${stderr.trim()}`);
|
|
198
|
-
|
|
199
|
-
} catch (cmdError) {
|
|
200
|
-
commandResult.success = false;
|
|
201
|
-
commandResult.error = cmdError.message;
|
|
202
|
-
if (cmdError.stdout) commandResult.output = cmdError.stdout.trim();
|
|
203
|
-
if (cmdError.stderr) commandResult.error += '\n' + cmdError.stderr.trim();
|
|
204
|
-
|
|
205
|
-
console.error(`[命令执行失败 ${i + 1}/${config.callbackCommand.length}] ${command}:`, cmdError.message);
|
|
208
|
+
|
|
209
|
+
commandResults.push(commandResult);
|
|
206
210
|
}
|
|
207
211
|
|
|
208
|
-
commandResults.
|
|
212
|
+
console.log(`[回调命令执行完成] 成功: ${commandResults.filter(r => r.success).length}个, 失败: ${commandResults.filter(r => !r.success).length}个`);
|
|
209
213
|
}
|
|
210
214
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
},
|
|
225
|
-
commandResults: commandResults.length > 0 ? commandResults : undefined
|
|
226
|
-
});
|
|
215
|
+
return res.json({
|
|
216
|
+
code: 0,
|
|
217
|
+
msg: '证书部署成功',
|
|
218
|
+
path: userCertDir,
|
|
219
|
+
stats: {
|
|
220
|
+
total: stats.total,
|
|
221
|
+
saved: stats.saved,
|
|
222
|
+
filtered: stats.filtered,
|
|
223
|
+
savedFiles: stats.savedFiles,
|
|
224
|
+
filteredFiles: stats.filteredFiles
|
|
225
|
+
},
|
|
226
|
+
commandResults: commandResults.length > 0 ? commandResults : undefined
|
|
227
|
+
});
|
|
227
228
|
|
|
228
229
|
} catch (zipError) {
|
|
229
230
|
console.error('[解压失败]', zipError);
|