node-opcua-pki 6.14.0 → 6.15.0
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/dist/bin/pki.mjs +140 -5
- package/dist/bin/pki.mjs.map +1 -1
- package/dist/index.d.mts +76 -0
- package/dist/index.d.ts +76 -0
- package/dist/index.js +140 -5
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +140 -5
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/bin/pki.mjs
CHANGED
|
@@ -1944,9 +1944,15 @@ function setEnv(varName, value) {
|
|
|
1944
1944
|
process.env[varName] = value;
|
|
1945
1945
|
}
|
|
1946
1946
|
}
|
|
1947
|
+
function hasEnv(varName) {
|
|
1948
|
+
return Object.prototype.hasOwnProperty.call(exportedEnvVars, varName);
|
|
1949
|
+
}
|
|
1947
1950
|
function getEnv(varName) {
|
|
1948
1951
|
return exportedEnvVars[varName];
|
|
1949
1952
|
}
|
|
1953
|
+
function unsetEnv(varName) {
|
|
1954
|
+
delete exportedEnvVars[varName];
|
|
1955
|
+
}
|
|
1950
1956
|
function getEnvironmentVarNames() {
|
|
1951
1957
|
return Object.keys(exportedEnvVars).map((varName) => {
|
|
1952
1958
|
return { key: varName, pattern: `\\$ENV\\:\\:${varName}` };
|
|
@@ -2416,10 +2422,17 @@ function openssl_require2DigitYearInDate() {
|
|
|
2416
2422
|
}
|
|
2417
2423
|
return g_config.opensslVersion.match(/OpenSSL 0\.9/);
|
|
2418
2424
|
}
|
|
2425
|
+
function stripConditionalBlocks(template) {
|
|
2426
|
+
return template.replace(/\{\{#([A-Z_][A-Z0-9_]*)\}\}([\s\S]*?)\{\{\/\1\}\}\r?\n?/g, (_match, key, content) => {
|
|
2427
|
+
const keep = hasEnv(key) && getEnv(key) !== "";
|
|
2428
|
+
return keep ? content : "";
|
|
2429
|
+
});
|
|
2430
|
+
}
|
|
2419
2431
|
function generateStaticConfig(configPath, options) {
|
|
2420
2432
|
const prePath = options?.cwd || "";
|
|
2421
2433
|
const originalFilename = !path4.isAbsolute(configPath) ? path4.join(prePath, configPath) : configPath;
|
|
2422
2434
|
let staticConfig = fs7.readFileSync(originalFilename, { encoding: "utf8" });
|
|
2435
|
+
staticConfig = stripConditionalBlocks(staticConfig);
|
|
2423
2436
|
for (const envVar of getEnvironmentVarNames()) {
|
|
2424
2437
|
staticConfig = staticConfig.replace(new RegExp(envVar.pattern, "gi"), getEnv(envVar.key));
|
|
2425
2438
|
}
|
|
@@ -2672,7 +2685,9 @@ nsComment = ''OpenSSL Generated Certificate''
|
|
|
2672
2685
|
#nsSslServerName =
|
|
2673
2686
|
keyUsage = critical, digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment, keyAgreement
|
|
2674
2687
|
extendedKeyUsage = critical,serverAuth ,clientAuth
|
|
2675
|
-
|
|
2688
|
+
{{#CDP_URL}}crlDistributionPoints = URI:$ENV::CDP_URL
|
|
2689
|
+
{{/CDP_URL}}{{#AIA_VALUE}}authorityInfoAccess = $ENV::AIA_VALUE
|
|
2690
|
+
{{/AIA_VALUE}}
|
|
2676
2691
|
[ v3_req ]
|
|
2677
2692
|
basicConstraints = critical, CA:FALSE
|
|
2678
2693
|
keyUsage = nonRepudiation, digitalSignature, keyEncipherment, dataEncipherment, keyAgreement
|
|
@@ -2695,10 +2710,9 @@ nsComment = "CA Certificate generated by Node-OPCUA Certificate
|
|
|
2695
2710
|
#nsCertType = sslCA, emailCA
|
|
2696
2711
|
#issuerAltName = issuer:copy
|
|
2697
2712
|
#obj = DER:02:03
|
|
2698
|
-
crlDistributionPoints =
|
|
2699
|
-
|
|
2700
|
-
|
|
2701
|
-
[ v3_selfsigned]
|
|
2713
|
+
{{#CDP_URL}}crlDistributionPoints = URI:$ENV::CDP_URL
|
|
2714
|
+
{{/CDP_URL}}{{#AIA_VALUE}}authorityInfoAccess = $ENV::AIA_VALUE
|
|
2715
|
+
{{/AIA_VALUE}}[ v3_selfsigned]
|
|
2702
2716
|
basicConstraints = critical, CA:FALSE
|
|
2703
2717
|
keyUsage = nonRepudiation, digitalSignature, keyEncipherment, dataEncipherment, keyAgreement
|
|
2704
2718
|
extendedKeyUsage = critical,serverAuth ,clientAuth
|
|
@@ -2790,6 +2804,7 @@ async function construct_CertificateAuthority(certificateAuthority) {
|
|
|
2790
2804
|
const subjectOpt = ` -subj "${subject.toString()}" `;
|
|
2791
2805
|
const caCommonName = subject.commonName || "NodeOPCUA-CA";
|
|
2792
2806
|
setEnv("ALTNAME", `URI:urn:${caCommonName}`);
|
|
2807
|
+
certificateAuthority._wireRevocationEnvVars();
|
|
2793
2808
|
const options = { cwd: caRootDir };
|
|
2794
2809
|
const configFile = generateStaticConfig("conf/caconfig.cnf", options);
|
|
2795
2810
|
const configOption = ` -config ${q4(n5(configFile))}`;
|
|
@@ -2843,6 +2858,33 @@ function parseOpenSSLDate(dateStr) {
|
|
|
2843
2858
|
const sec = raw.substring(10, 12);
|
|
2844
2859
|
return `${year}-${month}-${day}T${hour}:${min}:${sec}Z`;
|
|
2845
2860
|
}
|
|
2861
|
+
function validateRevocationUrl(url2, fieldName) {
|
|
2862
|
+
if (url2 === void 0) {
|
|
2863
|
+
return void 0;
|
|
2864
|
+
}
|
|
2865
|
+
if (url2 === "") {
|
|
2866
|
+
throw new Error(`${fieldName} must not be empty \u2014 pass undefined to disable the extension`);
|
|
2867
|
+
}
|
|
2868
|
+
let parsed;
|
|
2869
|
+
try {
|
|
2870
|
+
parsed = new URL(url2);
|
|
2871
|
+
} catch {
|
|
2872
|
+
throw new Error(`${fieldName} is not a valid URL: ${url2}`);
|
|
2873
|
+
}
|
|
2874
|
+
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
|
2875
|
+
throw new Error(`${fieldName} must use http: or https: (got ${parsed.protocol} in ${url2})`);
|
|
2876
|
+
}
|
|
2877
|
+
if (!parsed.pathname || parsed.pathname === "/") {
|
|
2878
|
+
throw new Error(`${fieldName} must include a path component (got ${url2})`);
|
|
2879
|
+
}
|
|
2880
|
+
const isLoopback = parsed.hostname === "localhost" || parsed.hostname === "::1" || parsed.hostname.startsWith("127.");
|
|
2881
|
+
if (isLoopback) {
|
|
2882
|
+
console.warn(
|
|
2883
|
+
`[node-opcua-pki] ${fieldName} points at loopback (${url2}) \u2014 certificates issued with this URL will be unreachable from any other host.`
|
|
2884
|
+
);
|
|
2885
|
+
}
|
|
2886
|
+
return url2;
|
|
2887
|
+
}
|
|
2846
2888
|
var defaultSubject, configurationFileTemplate, configurationFileSimpleTemplate2, config3, n5, q4, CertificateAuthority;
|
|
2847
2889
|
var init_certificate_authority = __esm({
|
|
2848
2890
|
"packages/node-opcua-pki/lib/ca/certificate_authority.ts"() {
|
|
@@ -2873,6 +2915,10 @@ var init_certificate_authority = __esm({
|
|
|
2873
2915
|
subject;
|
|
2874
2916
|
/** @internal Parent CA (undefined for root CAs). */
|
|
2875
2917
|
_issuerCA;
|
|
2918
|
+
/** @internal Configured CDP / AIA URLs (US-202). */
|
|
2919
|
+
_crlDistributionUrl;
|
|
2920
|
+
_ocspResponderUrl;
|
|
2921
|
+
_caIssuersUrl;
|
|
2876
2922
|
constructor(options) {
|
|
2877
2923
|
assert10(Object.prototype.hasOwnProperty.call(options, "location"));
|
|
2878
2924
|
assert10(Object.prototype.hasOwnProperty.call(options, "keySize"));
|
|
@@ -2880,6 +2926,93 @@ var init_certificate_authority = __esm({
|
|
|
2880
2926
|
this.keySize = options.keySize || 2048;
|
|
2881
2927
|
this.subject = new Subject4(options.subject || defaultSubject);
|
|
2882
2928
|
this._issuerCA = options.issuerCA;
|
|
2929
|
+
if (options.crlDistributionUrl !== void 0) {
|
|
2930
|
+
this.setCrlDistributionUrl(options.crlDistributionUrl);
|
|
2931
|
+
}
|
|
2932
|
+
if (options.ocspResponderUrl !== void 0) {
|
|
2933
|
+
this.setOcspResponderUrl(options.ocspResponderUrl);
|
|
2934
|
+
}
|
|
2935
|
+
if (options.caIssuersUrl !== void 0) {
|
|
2936
|
+
this.setCaIssuersUrl(options.caIssuersUrl);
|
|
2937
|
+
}
|
|
2938
|
+
}
|
|
2939
|
+
/**
|
|
2940
|
+
* Public URL where the CRL produced by this CA is reachable, or
|
|
2941
|
+
* `undefined` if no CDP extension should be emitted on issued certs.
|
|
2942
|
+
*/
|
|
2943
|
+
get crlDistributionUrl() {
|
|
2944
|
+
return this._crlDistributionUrl;
|
|
2945
|
+
}
|
|
2946
|
+
/**
|
|
2947
|
+
* Public URL of the OCSP responder, or `undefined` if no AIA OCSP
|
|
2948
|
+
* leg should be emitted on issued certs.
|
|
2949
|
+
*/
|
|
2950
|
+
get ocspResponderUrl() {
|
|
2951
|
+
return this._ocspResponderUrl;
|
|
2952
|
+
}
|
|
2953
|
+
/**
|
|
2954
|
+
* Public URL where the issuer's certificate can be fetched, or
|
|
2955
|
+
* `undefined` if no AIA caIssuers leg should be emitted.
|
|
2956
|
+
*/
|
|
2957
|
+
get caIssuersUrl() {
|
|
2958
|
+
return this._caIssuersUrl;
|
|
2959
|
+
}
|
|
2960
|
+
/**
|
|
2961
|
+
* Configure the URL embedded as `crlDistributionPoints` in every
|
|
2962
|
+
* subsequently-issued certificate. Pass `undefined` to disable
|
|
2963
|
+
* the extension entirely. Validated synchronously — throws on
|
|
2964
|
+
* empty string, non-http(s) protocol, missing path. Warns (does
|
|
2965
|
+
* not throw) when the URL points at loopback.
|
|
2966
|
+
*
|
|
2967
|
+
* @see US-202
|
|
2968
|
+
*/
|
|
2969
|
+
setCrlDistributionUrl(url2) {
|
|
2970
|
+
this._crlDistributionUrl = validateRevocationUrl(url2, "crlDistributionUrl");
|
|
2971
|
+
}
|
|
2972
|
+
/**
|
|
2973
|
+
* Configure the OCSP responder URL embedded as the `OCSP` leg of
|
|
2974
|
+
* the `authorityInfoAccess` extension on every subsequently-issued
|
|
2975
|
+
* certificate. Pass `undefined` to disable.
|
|
2976
|
+
*
|
|
2977
|
+
* @see US-202
|
|
2978
|
+
*/
|
|
2979
|
+
setOcspResponderUrl(url2) {
|
|
2980
|
+
this._ocspResponderUrl = validateRevocationUrl(url2, "ocspResponderUrl");
|
|
2981
|
+
}
|
|
2982
|
+
/**
|
|
2983
|
+
* Configure the caIssuers URL embedded as the `caIssuers` leg of
|
|
2984
|
+
* the `authorityInfoAccess` extension on every subsequently-issued
|
|
2985
|
+
* certificate. Pass `undefined` to disable.
|
|
2986
|
+
*
|
|
2987
|
+
* @see US-202
|
|
2988
|
+
*/
|
|
2989
|
+
setCaIssuersUrl(url2) {
|
|
2990
|
+
this._caIssuersUrl = validateRevocationUrl(url2, "caIssuersUrl");
|
|
2991
|
+
}
|
|
2992
|
+
/**
|
|
2993
|
+
* @internal
|
|
2994
|
+
* Populate the OpenSSL config substitution env vars (`CDP_URL` and
|
|
2995
|
+
* `AIA_VALUE`) from the configured URLs, or unset them so the
|
|
2996
|
+
* matching `{{#KEY}}...{{/KEY}}` blocks in the templates are
|
|
2997
|
+
* stripped. MUST be called before every `generateStaticConfig`
|
|
2998
|
+
* invocation that signs a certificate.
|
|
2999
|
+
*/
|
|
3000
|
+
_wireRevocationEnvVars() {
|
|
3001
|
+
unsetEnv("CDP_URL");
|
|
3002
|
+
unsetEnv("AIA_VALUE");
|
|
3003
|
+
if (this._crlDistributionUrl) {
|
|
3004
|
+
setEnv("CDP_URL", this._crlDistributionUrl);
|
|
3005
|
+
}
|
|
3006
|
+
const aiaLegs = [];
|
|
3007
|
+
if (this._ocspResponderUrl) {
|
|
3008
|
+
aiaLegs.push(`OCSP;URI:${this._ocspResponderUrl}`);
|
|
3009
|
+
}
|
|
3010
|
+
if (this._caIssuersUrl) {
|
|
3011
|
+
aiaLegs.push(`caIssuers;URI:${this._caIssuersUrl}`);
|
|
3012
|
+
}
|
|
3013
|
+
if (aiaLegs.length > 0) {
|
|
3014
|
+
setEnv("AIA_VALUE", aiaLegs.join(","));
|
|
3015
|
+
}
|
|
2883
3016
|
}
|
|
2884
3017
|
/** Absolute path to the CA root directory (alias for {@link location}). */
|
|
2885
3018
|
get rootDir() {
|
|
@@ -3482,6 +3615,7 @@ var init_certificate_authority = __esm({
|
|
|
3482
3615
|
async signCACertificateRequest(certFile, csrFile, params) {
|
|
3483
3616
|
const caRootDir = path6.resolve(this.rootDir);
|
|
3484
3617
|
const options = { cwd: caRootDir };
|
|
3618
|
+
this._wireRevocationEnvVars();
|
|
3485
3619
|
const configFile = generateStaticConfig("conf/caconfig.cnf", options);
|
|
3486
3620
|
const validity = params.validity ?? 3650;
|
|
3487
3621
|
await execute_openssl(
|
|
@@ -3648,6 +3782,7 @@ var init_certificate_authority = __esm({
|
|
|
3648
3782
|
ip
|
|
3649
3783
|
};
|
|
3650
3784
|
processAltNames(params);
|
|
3785
|
+
this._wireRevocationEnvVars();
|
|
3651
3786
|
const configFile = generateStaticConfig("conf/caconfig.cnf", options);
|
|
3652
3787
|
displaySubtitle("- then we ask the authority to sign the certificate signing request");
|
|
3653
3788
|
const configOption = ` -config ${configFile}`;
|