mirror of
https://github.com/andwati/zitadel.git
synced 2026-10-18 21:52:54 +00:00
97 lines
2.9 KiB
JavaScript
97 lines
2.9 KiB
JavaScript
// Preload script that makes Node.js read CA certificates from SSL_CERT_DIR
|
|
// the same way Go's crypto/x509 does: every regular file in the directory is
|
|
// read regardless of filename. OpenSSL (used by Node when --use-openssl-ca
|
|
// is set) only reads files named with a subject-hash (e.g. "9d66eef0.0"),
|
|
// silently ignoring plain names like "corp-ca.crt". This script closes that
|
|
// gap so operators get identical behaviour across the Go backend and the
|
|
// Node.js login container.
|
|
//
|
|
// Usage: node --require /app/load-ssl-cert-dir.cjs ...
|
|
//
|
|
// The script is a no-op when SSL_CERT_DIR is not set.
|
|
|
|
"use strict";
|
|
|
|
const tls = require("tls");
|
|
const fs = require("fs");
|
|
const path = require("path");
|
|
|
|
const sslCertDir = process.env.SSL_CERT_DIR;
|
|
if (!sslCertDir) {
|
|
return; // nothing to do — system trust via SSL_CERT_FILE is sufficient
|
|
}
|
|
|
|
// Go splits on ":" and walks every directory in order.
|
|
const dirs = sslCertDir.split(":").filter(Boolean);
|
|
const certs = [];
|
|
|
|
for (const dir of dirs) {
|
|
let entries;
|
|
try {
|
|
entries = fs.readdirSync(dir);
|
|
} catch {
|
|
// Directory doesn't exist or isn't readable — skip, like Go does.
|
|
continue;
|
|
}
|
|
|
|
for (const entry of entries) {
|
|
const filePath = path.join(dir, entry);
|
|
|
|
try {
|
|
const stat = fs.lstatSync(filePath);
|
|
|
|
// Go's readUniqueDirectoryEntries skips symlinks whose target is a
|
|
// bare filename (no slash), because those are the c_rehash hash links
|
|
// pointing at files in the same directory. This avoids loading the
|
|
// same certificate twice.
|
|
if (stat.isSymbolicLink()) {
|
|
const target = fs.readlinkSync(filePath);
|
|
if (!target.includes("/")) {
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if (!stat.isFile() && !stat.isSymbolicLink()) {
|
|
continue;
|
|
}
|
|
|
|
const content = fs.readFileSync(filePath, "utf8");
|
|
if (content.includes("-----BEGIN CERTIFICATE-----")) {
|
|
certs.push(content);
|
|
}
|
|
} catch {
|
|
// Unreadable file — skip silently, matching Go behaviour.
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (certs.length === 0) {
|
|
return;
|
|
}
|
|
|
|
const origCreateSecureContext = tls.createSecureContext;
|
|
|
|
tls.createSecureContext = function (options) {
|
|
const ctx = origCreateSecureContext.call(this, options);
|
|
|
|
// Only inject directory CAs when the caller did not pass an explicit "ca"
|
|
// option. This matches Go's SystemCertPool() semantics: the extra certs
|
|
// are part of the system pool, not a forced override.
|
|
if (!options || !options.ca) {
|
|
for (let i = 0; i < certs.length; i++) {
|
|
try {
|
|
ctx.context.addCACert(certs[i]);
|
|
} catch (err) {
|
|
// Log once per bad cert, then remove it so subsequent contexts
|
|
// don't pay the cost of retrying a known-bad certificate.
|
|
console.error("load-ssl-cert-dir: skipping malformed certificate at index " + i + ": " + err.message);
|
|
certs.splice(i, 1);
|
|
i--;
|
|
}
|
|
}
|
|
}
|
|
|
|
return ctx;
|
|
};
|