64 lines
1.9 KiB
JavaScript
64 lines
1.9 KiB
JavaScript
|
|
/*
|
||
|
|
* 内部本机 socket 接口 · 给神笔马良 (zhuyuan-pen) 拉密钥用.
|
||
|
|
* 只允许 127.0.0.1 / ::1 (IPv6 loopback) 来源, 其他一律 403.
|
||
|
|
* 不需要 basic-auth (本机进程权限 = vault 用户已经够了).
|
||
|
|
*
|
||
|
|
* GET /internal/fetch/:key → { value }
|
||
|
|
*
|
||
|
|
* baton-005 C 节: 神笔马良不走环境变量, 走本地 socket. 这里其实是 loopback HTTP,
|
||
|
|
* 比 unix domain socket 简单 (2C2G 上少一份 socket 文件管理负担), 实质等价.
|
||
|
|
*/
|
||
|
|
"use strict";
|
||
|
|
|
||
|
|
const express = require("express");
|
||
|
|
const { KEY_RE } = require("./secrets");
|
||
|
|
|
||
|
|
function buildInternalRouter({ vault }) {
|
||
|
|
const router = express.Router();
|
||
|
|
|
||
|
|
// 只允许本机
|
||
|
|
router.use((req, res, next) => {
|
||
|
|
const ip = req.ip || (req.socket && req.socket.remoteAddress) || "";
|
||
|
|
// express 的 req.ip: 如果 trust proxy 没开, 是 socket.remoteAddress
|
||
|
|
// 我们 server.js 不开 trust proxy, 所以 req.ip 直接是 socket 地址.
|
||
|
|
if (
|
||
|
|
ip === "127.0.0.1" ||
|
||
|
|
ip === "::1" ||
|
||
|
|
ip === "::ffff:127.0.0.1" ||
|
||
|
|
ip === "localhost"
|
||
|
|
) {
|
||
|
|
return next();
|
||
|
|
}
|
||
|
|
return res
|
||
|
|
.status(403)
|
||
|
|
.json({ error: true, code: "forbidden_non_local", message: "只允许本机访问 (来源=" + ip + ")" });
|
||
|
|
});
|
||
|
|
|
||
|
|
router.get("/fetch/:key", (req, res) => {
|
||
|
|
const key = String(req.params.key || "");
|
||
|
|
if (!KEY_RE.test(key)) {
|
||
|
|
return res
|
||
|
|
.status(400)
|
||
|
|
.json({ error: true, code: "invalid_key", message: "密钥名格式不对: " + key });
|
||
|
|
}
|
||
|
|
let val;
|
||
|
|
try {
|
||
|
|
val = vault.get(key);
|
||
|
|
} catch (e) {
|
||
|
|
return res
|
||
|
|
.status(500)
|
||
|
|
.json({ error: true, code: "vault_decrypt_failed", message: e.message });
|
||
|
|
}
|
||
|
|
if (val == null) {
|
||
|
|
return res
|
||
|
|
.status(404)
|
||
|
|
.json({ error: true, code: "not_configured", message: "密钥未配置: " + key });
|
||
|
|
}
|
||
|
|
res.json({ ok: true, key, value: val });
|
||
|
|
});
|
||
|
|
|
||
|
|
return router;
|
||
|
|
}
|
||
|
|
|
||
|
|
module.exports = { buildInternalRouter };
|