Files
jtlPosSync/generate-cert.js
2026-07-29 18:40:19 +02:00

81 lines
2.4 KiB
JavaScript

import { execSync } from 'node:child_process';
import fs from 'node:fs';
import os from 'node:os';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import { logger } from './src/logger.js';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const certsDir = path.join(__dirname, 'certs');
const keyPath = path.join(certsDir, 'key.pem');
const certPath = path.join(certsDir, 'cert.pem');
fs.mkdirSync(certsDir, { recursive: true });
function isIp(value) {
return /^(?:\d{1,3}\.){3}\d{1,3}$/.test(value) || value.includes(':');
}
function localIpv4s() {
const ips = [];
for (const entries of Object.values(os.networkInterfaces())) {
for (const entry of entries || []) {
if (entry.family !== 'IPv4' || entry.internal) continue;
// Skip link-local / docker / libvirt bridge noise by default — keep LAN + extras via args
if (entry.address.startsWith('169.254.')) continue;
if (entry.address.startsWith('172.17.')) continue;
if (entry.address.startsWith('192.168.122.')) continue;
ips.push(entry.address);
}
}
return ips;
}
const dnsNames = new Set(['localhost']);
const ipAddrs = new Set(['127.0.0.1', '0.0.0.0']);
for (const ip of localIpv4s()) {
ipAddrs.add(ip);
}
const extras = [
...(process.env.CERT_SAN || '').split(/[,\s]+/).filter(Boolean),
...process.argv.slice(2),
];
for (const value of extras) {
if (isIp(value)) ipAddrs.add(value);
else dnsNames.add(value);
}
const sanParts = [
...[...dnsNames].map((name) => `DNS:${name}`),
...[...ipAddrs].map((ip) => `IP:${ip}`),
];
const san = `subjectAltName=${sanParts.join(',')}`;
const cn = [...dnsNames][0] || 'localhost';
const subject = `/CN=${cn}/O=JTL POS Sync/C=DE`;
// ECDSA P-256 keeps pairing QR codes much smaller than RSA-2048
execSync(
`openssl req -x509 -newkey ec -pkeyopt ec_paramgen_curve:P-256 -nodes -keyout "${keyPath}" -out "${certPath}" -days 3650 -subj "${subject}" -addext "${san}"`,
{ stdio: 'inherit' }
);
const sha1 = execSync(`openssl x509 -in "${certPath}" -noout -fingerprint -sha1`, {
encoding: 'utf8',
})
.trim()
.split('=')[1];
const serial = execSync(`openssl x509 -in "${certPath}" -noout -serial`, {
encoding: 'utf8',
})
.trim()
.split('=')[1];
logger.success(`Wrote ${keyPath}`);
logger.success(`Wrote ${certPath}`);
logger.info(`SAN: ${sanParts.join(', ')}`);
logger.info(`Fingerprint: ${sha1.replace(/:/g, '')}`);
logger.info(`Serial: ${serial}`);