Usar clave SSH global del monitor
This commit is contained in:
@@ -10,6 +10,8 @@ const DEFAULT_CONFIG_PATH = path.join(ROOT, "config.json");
|
||||
const PORT = Number(process.env.PORT || 8787);
|
||||
const AUTH_USERNAME = process.env.MONITOR_USERNAME || "";
|
||||
const AUTH_PASSWORD = process.env.MONITOR_PASSWORD || "";
|
||||
const DEFAULT_SSH_PRIVATE_KEY_PATH = "/ssh/monitor_rpi_ed25519";
|
||||
const DEFAULT_SSH_PUBLIC_KEY_PATH = "/ssh/monitor_rpi_ed25519.pub";
|
||||
|
||||
let config = null;
|
||||
let latestStatus = null;
|
||||
@@ -42,21 +44,26 @@ async function readConfig() {
|
||||
parsed.refreshIntervalSeconds = Number(parsed.refreshIntervalSeconds || 30);
|
||||
parsed.idleScanIntervalSeconds = Number(parsed.idleScanIntervalSeconds || 300);
|
||||
parsed.sshTimeoutSeconds = Number(parsed.sshTimeoutSeconds || 8);
|
||||
parsed.sshPrivateKeyPath = String(parsed.sshPrivateKeyPath || DEFAULT_SSH_PRIVATE_KEY_PATH);
|
||||
parsed.sshPublicKeyPath = String(parsed.sshPublicKeyPath || `${parsed.sshPrivateKeyPath}.pub` || DEFAULT_SSH_PUBLIC_KEY_PATH);
|
||||
parsed.temperatureThresholdsC = normalizeTemperatureThresholds(parsed.temperatureThresholdsC);
|
||||
parsed.metricThresholdsPercent = normalizeMetricThresholds(parsed.metricThresholdsPercent);
|
||||
parsed.devices = Array.isArray(parsed.devices) ? parsed.devices : [];
|
||||
parsed.devices = Array.isArray(parsed.devices) ? parsed.devices.map(normalizeDeviceConfig) : [];
|
||||
return parsed;
|
||||
}
|
||||
|
||||
async function writeConfig(nextConfig) {
|
||||
const sshPrivateKeyPath = String(nextConfig.sshPrivateKeyPath || DEFAULT_SSH_PRIVATE_KEY_PATH);
|
||||
const normalized = {
|
||||
...nextConfig,
|
||||
refreshIntervalSeconds: Number(nextConfig.refreshIntervalSeconds || 30),
|
||||
idleScanIntervalSeconds: Number(nextConfig.idleScanIntervalSeconds || 300),
|
||||
sshTimeoutSeconds: Number(nextConfig.sshTimeoutSeconds || 8),
|
||||
sshPrivateKeyPath,
|
||||
sshPublicKeyPath: String(nextConfig.sshPublicKeyPath || `${sshPrivateKeyPath}.pub` || DEFAULT_SSH_PUBLIC_KEY_PATH),
|
||||
temperatureThresholdsC: normalizeTemperatureThresholds(nextConfig.temperatureThresholdsC),
|
||||
metricThresholdsPercent: normalizeMetricThresholds(nextConfig.metricThresholdsPercent),
|
||||
devices: Array.isArray(nextConfig.devices) ? nextConfig.devices : []
|
||||
devices: Array.isArray(nextConfig.devices) ? nextConfig.devices.map(normalizeDeviceConfig) : []
|
||||
};
|
||||
await fs.mkdir(path.dirname(CONFIG_PATH), { recursive: true });
|
||||
await fs.writeFile(CONFIG_PATH, JSON.stringify(normalized, null, 2) + "\n", "utf8");
|
||||
@@ -64,6 +71,15 @@ async function writeConfig(nextConfig) {
|
||||
restartScanner();
|
||||
}
|
||||
|
||||
function normalizeDeviceConfig(device = {}) {
|
||||
const authMethod = device.authMethod || (device.privateKeyPath ? "key" : "password");
|
||||
return {
|
||||
...device,
|
||||
authMethod: authMethod === "key" ? "key" : "password",
|
||||
privateKeyPath: device.privateKeyPath || ""
|
||||
};
|
||||
}
|
||||
|
||||
function classifyTemp(tempC) {
|
||||
const thresholds = config.temperatureThresholdsC || {};
|
||||
if (tempC >= (thresholds.critical || 80)) return "critical";
|
||||
@@ -364,8 +380,12 @@ function runCommandWithInput(command, args, input, timeoutMs) {
|
||||
}
|
||||
|
||||
async function sshMetrics(device) {
|
||||
const hasPrivateKey = Boolean(device.privateKeyPath);
|
||||
if (!hasPrivateKey && !device.password) {
|
||||
const usesPrivateKey = device.authMethod === "key" || Boolean(device.privateKeyPath);
|
||||
const privateKeyPath = device.privateKeyPath || config.sshPrivateKeyPath;
|
||||
if (usesPrivateKey && !privateKeyPath) {
|
||||
throw new Error("Clave privada SSH global no configurada");
|
||||
}
|
||||
if (!usesPrivateKey && !device.password) {
|
||||
throw new Error("Credenciales SSH no configuradas");
|
||||
}
|
||||
|
||||
@@ -388,10 +408,10 @@ async function sshMetrics(device) {
|
||||
|
||||
let command = "ssh";
|
||||
let args = sshArgs;
|
||||
if (hasPrivateKey) {
|
||||
if (usesPrivateKey) {
|
||||
args = [
|
||||
"-i",
|
||||
device.privateKeyPath,
|
||||
privateKeyPath,
|
||||
"-o",
|
||||
"BatchMode=yes",
|
||||
"-o",
|
||||
@@ -627,6 +647,21 @@ function sendJson(res, statusCode, payload) {
|
||||
res.end(body);
|
||||
}
|
||||
|
||||
function sendText(res, statusCode, body, headers = {}) {
|
||||
res.writeHead(statusCode, {
|
||||
"Content-Type": "text/plain; charset=utf-8",
|
||||
"Cache-Control": "no-store",
|
||||
...headers
|
||||
});
|
||||
res.end(body);
|
||||
}
|
||||
|
||||
async function readSshPublicKey() {
|
||||
const publicKeyPath = config.sshPublicKeyPath || `${config.sshPrivateKeyPath || DEFAULT_SSH_PRIVATE_KEY_PATH}.pub`;
|
||||
const publicKey = (await fs.readFile(publicKeyPath, "utf8")).trim();
|
||||
return { publicKeyPath, publicKey };
|
||||
}
|
||||
|
||||
function isAuthEnabled() {
|
||||
return Boolean(AUTH_USERNAME && AUTH_PASSWORD);
|
||||
}
|
||||
@@ -737,6 +772,30 @@ async function handleRequest(req, res) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (req.method === "GET" && pathname === "/api/ssh-public-key") {
|
||||
try {
|
||||
sendJson(res, 200, await readSshPublicKey());
|
||||
} catch (error) {
|
||||
sendJson(res, 404, {
|
||||
error: `No se pudo leer la clave publica SSH: ${error.message}`,
|
||||
publicKeyPath: config.sshPublicKeyPath || `${config.sshPrivateKeyPath || DEFAULT_SSH_PRIVATE_KEY_PATH}.pub`
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (req.method === "GET" && pathname === "/api/ssh-public-key/download") {
|
||||
try {
|
||||
const { publicKeyPath, publicKey } = await readSshPublicKey();
|
||||
sendText(res, 200, `${publicKey}\n`, {
|
||||
"Content-Disposition": `attachment; filename="${path.basename(publicKeyPath)}"`
|
||||
});
|
||||
} catch (error) {
|
||||
sendText(res, 404, `No se pudo leer la clave publica SSH: ${error.message}\n`);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (req.method === "POST" && pathname === "/api/config") {
|
||||
const body = await readBody(req);
|
||||
await writeConfig(JSON.parse(body));
|
||||
|
||||
Reference in New Issue
Block a user