@push.rocks/smartacme 9.5.0 → 9.6.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/.smartconfig.json +12 -7
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/acme/acme.classes.client.d.ts +2 -0
- package/dist_ts/acme/acme.classes.client.js +5 -2
- package/dist_ts/acme/acme.classes.http-client.d.ts +2 -1
- package/dist_ts/acme/acme.classes.http-client.js +4 -2
- package/dist_ts/acme/acme.classes.order.d.ts +3 -0
- package/dist_ts/acme/acme.classes.order.js +11 -2
- package/dist_ts/classes.exact-certificate-issuer.d.ts +36 -0
- package/dist_ts/classes.exact-certificate-issuer.js +393 -0
- package/dist_ts/index.d.ts +2 -0
- package/dist_ts/index.js +2 -1
- package/dist_ts/interfaces/exact-issuance.d.ts +79 -0
- package/dist_ts/interfaces/exact-issuance.js +2 -0
- package/dist_ts/plugins.d.ts +5 -1
- package/dist_ts/plugins.js +6 -2
- package/dist_ts/smartacme.classes.smartacme.d.ts +22 -0
- package/dist_ts/smartacme.classes.smartacme.js +131 -10
- package/package.json +11 -15
- package/readme.md +75 -1
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/acme/acme.classes.client.ts +6 -1
- package/ts/acme/acme.classes.http-client.ts +2 -1
- package/ts/acme/acme.classes.order.ts +12 -1
- package/ts/classes.exact-certificate-issuer.ts +403 -0
- package/ts/index.ts +2 -0
- package/ts/interfaces/exact-issuance.ts +104 -0
- package/ts/plugins.ts +5 -1
- package/ts/smartacme.classes.smartacme.ts +139 -8
- package/readme.hints.md +0 -81
- package/readme.plan.md +0 -3
|
@@ -0,0 +1,393 @@
|
|
|
1
|
+
import * as plugins from './plugins.js';
|
|
2
|
+
export function normalizeCertificateIdentifiers(input) {
|
|
3
|
+
if (!Array.isArray(input) || input.length < 1 || input.length > 100) {
|
|
4
|
+
throw new Error('Between one and 100 explicit DNS identifiers are required');
|
|
5
|
+
}
|
|
6
|
+
return [...new Set(Array.from(input, (value) => {
|
|
7
|
+
if (typeof value !== 'string' || value.length > 1024)
|
|
8
|
+
throw new Error('Invalid DNS identifier');
|
|
9
|
+
const trimmed = value.trim().toLowerCase().replace(/\.$/, '');
|
|
10
|
+
if (/[/\\:@?#%\s]/.test(trimmed))
|
|
11
|
+
throw new Error('Invalid DNS identifier');
|
|
12
|
+
const wildcard = trimmed.startsWith('*.');
|
|
13
|
+
const name = plugins.url.domainToASCII(wildcard ? trimmed.slice(2) : trimmed);
|
|
14
|
+
if (!name || plugins.net.isIP(name) !== 0 || name.length > 253 || name.split('.').length < 2
|
|
15
|
+
|| name.split('.').some((label) => !/^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/.test(label))) {
|
|
16
|
+
throw new Error('Invalid DNS identifier');
|
|
17
|
+
}
|
|
18
|
+
return `${wildcard ? '*.' : ''}${name}`;
|
|
19
|
+
}))].sort();
|
|
20
|
+
}
|
|
21
|
+
/** Owns exact-name issuance and recovery; the embedding service supplies storage. */
|
|
22
|
+
export class ExactCertificateIssuer {
|
|
23
|
+
constructor(options) {
|
|
24
|
+
this.options = options;
|
|
25
|
+
}
|
|
26
|
+
identity(request) {
|
|
27
|
+
if (typeof request.namespace !== 'string' || !/^[\x21-\x7e]{1,200}$/.test(request.namespace)) {
|
|
28
|
+
throw new Error('A nonempty printable isolation namespace of at most 200 characters is required');
|
|
29
|
+
}
|
|
30
|
+
const identifiers = normalizeCertificateIdentifiers(request.identifiers);
|
|
31
|
+
const binding = {
|
|
32
|
+
namespace: request.namespace,
|
|
33
|
+
identifiers,
|
|
34
|
+
directoryUrl: this.options.directoryUrl,
|
|
35
|
+
accountThumbprint: this.options.accountThumbprint,
|
|
36
|
+
};
|
|
37
|
+
return {
|
|
38
|
+
...binding,
|
|
39
|
+
certificateKey: `exact-v1:${plugins.crypto.createHash('sha256').update(JSON.stringify(binding)).digest('hex')}`,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
async status(request) {
|
|
43
|
+
const identity = this.identity(request);
|
|
44
|
+
const record = await this.options.store.getIssuance(identity.certificateKey);
|
|
45
|
+
if (record)
|
|
46
|
+
this.validateRecord(record, identity);
|
|
47
|
+
return record ? this.info(record) : null;
|
|
48
|
+
}
|
|
49
|
+
/** Validate the cache before taking any issuance or CA rate-limit slot. */
|
|
50
|
+
async cached(request) {
|
|
51
|
+
const identity = this.identity(request);
|
|
52
|
+
const certificate = await this.options.store.getCertificate(identity.certificateKey);
|
|
53
|
+
if (!certificate)
|
|
54
|
+
return null;
|
|
55
|
+
this.validateCertificate(certificate, identity);
|
|
56
|
+
const record = await this.options.store.getIssuance(identity.certificateKey);
|
|
57
|
+
if (record?.status !== 'ready' || certificate.id !== record.issuanceId
|
|
58
|
+
|| Date.now() >= certificate.renewAfter || Date.now() >= certificate.validUntil)
|
|
59
|
+
return null;
|
|
60
|
+
this.validateRecord(record, identity);
|
|
61
|
+
return { status: 'ready', certificate, issuance: this.info(record) };
|
|
62
|
+
}
|
|
63
|
+
async run(request) {
|
|
64
|
+
this.options.signal.throwIfAborted();
|
|
65
|
+
const identity = this.identity(request);
|
|
66
|
+
let record = await this.options.store.getIssuance(identity.certificateKey);
|
|
67
|
+
const cached = await this.options.store.getCertificate(identity.certificateKey);
|
|
68
|
+
if (cached) {
|
|
69
|
+
this.validateCertificate(cached, identity);
|
|
70
|
+
if (record?.status === 'ready' && cached.id === record.issuanceId && Date.now() < cached.renewAfter) {
|
|
71
|
+
this.validateRecord(record, identity);
|
|
72
|
+
return { status: 'ready', certificate: cached, issuance: this.info(record) };
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
if (record?.status === 'ready' && !cached) {
|
|
76
|
+
this.validateRecord(record, identity);
|
|
77
|
+
return await this.advance(record, true);
|
|
78
|
+
}
|
|
79
|
+
if (!record || record.status === 'ready') {
|
|
80
|
+
const [privateKey, csr] = await plugins.acme.AcmeCrypto.createCsr({
|
|
81
|
+
commonName: identity.identifiers[0], altNames: identity.identifiers.slice(1),
|
|
82
|
+
});
|
|
83
|
+
const next = {
|
|
84
|
+
...identity, issuanceId: plugins.crypto.randomUUID(), revision: (record?.revision ?? -1) + 1,
|
|
85
|
+
status: 'prepared', createdAt: Date.now(), updatedAt: Date.now(), privateKey, csr,
|
|
86
|
+
pendingChallenges: [],
|
|
87
|
+
};
|
|
88
|
+
this.options.signal.throwIfAborted();
|
|
89
|
+
if (!await this.options.store.compareAndSetIssuance(identity.certificateKey, record?.revision ?? null, next)) {
|
|
90
|
+
const current = await this.requiredRecord(identity.certificateKey);
|
|
91
|
+
return { status: 'pending', issuance: this.info(current) };
|
|
92
|
+
}
|
|
93
|
+
record = next;
|
|
94
|
+
}
|
|
95
|
+
this.validateRecord(record, identity);
|
|
96
|
+
return await this.advance(record, false);
|
|
97
|
+
}
|
|
98
|
+
async recover(request) {
|
|
99
|
+
if (!['recheck', 'retry-proven-unapplied', 'abandon'].includes(request.action)
|
|
100
|
+
|| !Number.isSafeInteger(request.expectedRevision) || request.expectedRevision < 0
|
|
101
|
+
|| typeof request.issuanceId !== 'string' || !request.issuanceId) {
|
|
102
|
+
throw new Error('Invalid issuance recovery request');
|
|
103
|
+
}
|
|
104
|
+
const identity = this.identity(request);
|
|
105
|
+
let record = await this.requiredRecord(identity.certificateKey);
|
|
106
|
+
this.validateRecord(record, identity);
|
|
107
|
+
if (record.issuanceId !== request.issuanceId || record.revision !== request.expectedRevision) {
|
|
108
|
+
throw new Error('Issuance recovery revision conflict');
|
|
109
|
+
}
|
|
110
|
+
if (request.action === 'abandon') {
|
|
111
|
+
if (record.status === 'ready')
|
|
112
|
+
throw new Error('A completed issuance cannot be abandoned');
|
|
113
|
+
record = await this.save(record, { status: 'abandoned_unverified' });
|
|
114
|
+
await this.cleanup(record);
|
|
115
|
+
return { status: 'pending', issuance: this.info(await this.requiredRecord(record.certificateKey)) };
|
|
116
|
+
}
|
|
117
|
+
if (record.status === 'abandoned_unverified') {
|
|
118
|
+
throw new Error('Abandoned issuance requires external resolution; new issuance remains blocked');
|
|
119
|
+
}
|
|
120
|
+
if (request.action === 'retry-proven-unapplied') {
|
|
121
|
+
// Only an acknowledged rejection of newOrder proves no order was created.
|
|
122
|
+
if (record.order || record.status !== 'failed' || record.errorCode !== 'rate_limited') {
|
|
123
|
+
throw new Error('The previous external effect is not proven unapplied');
|
|
124
|
+
}
|
|
125
|
+
if (record.retryAfter && record.retryAfter > Date.now()) {
|
|
126
|
+
return { status: 'pending', issuance: this.info(record) };
|
|
127
|
+
}
|
|
128
|
+
record = await this.save(record, { status: 'prepared', errorCode: undefined, retryAfter: undefined });
|
|
129
|
+
return await this.advance(record, false);
|
|
130
|
+
}
|
|
131
|
+
return await this.advance(record, true);
|
|
132
|
+
}
|
|
133
|
+
async advance(initial, recheckOnly) {
|
|
134
|
+
let record = initial;
|
|
135
|
+
this.options.signal.throwIfAborted();
|
|
136
|
+
if (record.status === 'abandoned_unverified' || record.status === 'failed') {
|
|
137
|
+
return { status: 'pending', issuance: this.info(record) };
|
|
138
|
+
}
|
|
139
|
+
if (record.status === 'creating' || (record.status === 'indeterminate' && !record.order)) {
|
|
140
|
+
record = await this.save(record, { status: 'indeterminate', errorCode: 'order_outcome_unknown' });
|
|
141
|
+
return { status: 'pending', issuance: this.info(record) };
|
|
142
|
+
}
|
|
143
|
+
if (record.status === 'prepared') {
|
|
144
|
+
if (recheckOnly)
|
|
145
|
+
return { status: 'pending', issuance: this.info(record) };
|
|
146
|
+
// Prove challenge support before creating an irreversible CA order.
|
|
147
|
+
await this.handler(record);
|
|
148
|
+
record = await this.save(record, { status: 'creating' });
|
|
149
|
+
let order;
|
|
150
|
+
try {
|
|
151
|
+
this.options.signal.throwIfAborted();
|
|
152
|
+
order = await this.options.client.createOrder({
|
|
153
|
+
identifiers: record.identifiers.map((value) => ({ type: 'dns', value })),
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
catch (error) {
|
|
157
|
+
const rejected = error instanceof plugins.acme.AcmeError && error.isRateLimited;
|
|
158
|
+
record = await this.save(record, {
|
|
159
|
+
status: rejected ? 'failed' : 'indeterminate',
|
|
160
|
+
errorCode: rejected ? 'rate_limited' : 'order_outcome_unknown',
|
|
161
|
+
retryAfter: rejected ? Date.now() + Math.max(error.retryAfter, 60) * 1000 : undefined,
|
|
162
|
+
});
|
|
163
|
+
return { status: 'pending', issuance: this.info(record) };
|
|
164
|
+
}
|
|
165
|
+
if (!order.url) {
|
|
166
|
+
record = await this.save(record, { status: 'indeterminate', errorCode: 'order_outcome_unknown' });
|
|
167
|
+
return { status: 'pending', issuance: this.info(record) };
|
|
168
|
+
}
|
|
169
|
+
record = await this.save(record, { order, status: 'authorizing' });
|
|
170
|
+
}
|
|
171
|
+
if (!record.order)
|
|
172
|
+
throw new Error('Issuance record has no acknowledged order');
|
|
173
|
+
const observed = await this.options.client.getOrder(record.order.url);
|
|
174
|
+
this.validateOrder(observed, record);
|
|
175
|
+
record = await this.save(record, { order: observed, errorCode: undefined });
|
|
176
|
+
if (observed.status === 'invalid' || observed.status === 'expired' || observed.status === 'revoked') {
|
|
177
|
+
record = await this.save(record, { status: 'failed', errorCode: 'order_invalid' });
|
|
178
|
+
await this.cleanup(record);
|
|
179
|
+
return { status: 'pending', issuance: this.info(await this.requiredRecord(record.certificateKey)) };
|
|
180
|
+
}
|
|
181
|
+
if (observed.status === 'valid')
|
|
182
|
+
return await this.finish(record);
|
|
183
|
+
if (recheckOnly) {
|
|
184
|
+
return { status: 'pending', issuance: this.info(record) };
|
|
185
|
+
}
|
|
186
|
+
if (record.status === 'finalizing' || record.status === 'indeterminate') {
|
|
187
|
+
// Acknowledged processing/ready observations do not prove a previous
|
|
188
|
+
// finalize request was unapplied. Never send a new CSR on uncertainty.
|
|
189
|
+
record = await this.save(record, { status: 'indeterminate', errorCode: 'order_outcome_unknown' });
|
|
190
|
+
return { status: 'pending', issuance: this.info(record) };
|
|
191
|
+
}
|
|
192
|
+
if (observed.status === 'pending') {
|
|
193
|
+
record = await this.authorize(record);
|
|
194
|
+
if (record.status === 'failed')
|
|
195
|
+
return { status: 'pending', issuance: this.info(record) };
|
|
196
|
+
}
|
|
197
|
+
const ready = await this.options.client.getOrder(record.order.url);
|
|
198
|
+
this.validateOrder(ready, record);
|
|
199
|
+
record = await this.save(record, { order: ready });
|
|
200
|
+
if (ready.status === 'valid')
|
|
201
|
+
return await this.finish(record);
|
|
202
|
+
if (ready.status !== 'ready') {
|
|
203
|
+
return { status: 'pending', issuance: this.info(record) };
|
|
204
|
+
}
|
|
205
|
+
record = await this.save(record, { status: 'finalizing' });
|
|
206
|
+
try {
|
|
207
|
+
this.options.signal.throwIfAborted();
|
|
208
|
+
await this.options.client.finalizeOrder(structuredClone(ready), record.csr);
|
|
209
|
+
}
|
|
210
|
+
catch {
|
|
211
|
+
// Preserve the acknowledged order and original key/CSR for safe recheck.
|
|
212
|
+
record = await this.save(record, { status: 'indeterminate', errorCode: 'order_outcome_unknown' });
|
|
213
|
+
return { status: 'pending', issuance: this.info(record) };
|
|
214
|
+
}
|
|
215
|
+
const finalized = await this.options.client.getOrder(ready.url);
|
|
216
|
+
this.validateOrder(finalized, record);
|
|
217
|
+
record = await this.save(record, { order: finalized });
|
|
218
|
+
return finalized.status === 'valid'
|
|
219
|
+
? await this.finish(record)
|
|
220
|
+
: { status: 'pending', issuance: this.info(record) };
|
|
221
|
+
}
|
|
222
|
+
async authorize(initial) {
|
|
223
|
+
let record = initial;
|
|
224
|
+
const handler = await this.handler(record);
|
|
225
|
+
const authorizations = await this.options.client.getAuthorizations(record.order);
|
|
226
|
+
for (const authorization of authorizations) {
|
|
227
|
+
this.options.signal.throwIfAborted();
|
|
228
|
+
const identifier = `${authorization.wildcard ? '*.' : ''}${authorization.identifier.value}`;
|
|
229
|
+
if (authorization.identifier.type !== 'dns' || !record.identifiers.includes(identifier)) {
|
|
230
|
+
throw new Error('CA authorization is outside the requested identifiers');
|
|
231
|
+
}
|
|
232
|
+
if (authorization.status === 'valid')
|
|
233
|
+
continue;
|
|
234
|
+
if (authorization.status !== 'pending') {
|
|
235
|
+
return await this.save(record, { status: 'failed', errorCode: 'authorization_failed' });
|
|
236
|
+
}
|
|
237
|
+
const challenge = authorization.challenges.find((value) => value.type === 'dns-01');
|
|
238
|
+
if (!challenge)
|
|
239
|
+
throw new Error('The CA did not offer DNS-01');
|
|
240
|
+
const input = {
|
|
241
|
+
hostName: `_acme-challenge.${authorization.identifier.value}`,
|
|
242
|
+
challenge: this.options.client.getChallengeKeyAuthorization(challenge),
|
|
243
|
+
};
|
|
244
|
+
if (!record.pendingChallenges.some((value) => value.hostName === input.hostName && value.challenge === input.challenge)) {
|
|
245
|
+
record = await this.save(record, { pendingChallenges: [...record.pendingChallenges, input] });
|
|
246
|
+
}
|
|
247
|
+
try {
|
|
248
|
+
await handler.prepare(input);
|
|
249
|
+
if (handler.verify) {
|
|
250
|
+
await handler.verify(input);
|
|
251
|
+
}
|
|
252
|
+
else {
|
|
253
|
+
let visible = false;
|
|
254
|
+
for (let attempt = 0; attempt < 100; attempt++) {
|
|
255
|
+
this.options.signal.throwIfAborted();
|
|
256
|
+
const records = await this.options.dns.getRecords(input.hostName, 'TXT', 0);
|
|
257
|
+
if (records.some((value) => value.value === input.challenge)) {
|
|
258
|
+
visible = true;
|
|
259
|
+
break;
|
|
260
|
+
}
|
|
261
|
+
await plugins.timers.setTimeout(1000, undefined, { signal: this.options.signal });
|
|
262
|
+
}
|
|
263
|
+
if (!visible)
|
|
264
|
+
throw new Error('DNS-01 propagation timed out');
|
|
265
|
+
}
|
|
266
|
+
await plugins.timers.setTimeout(this.options.dnsPropagationDelayMs, undefined, { signal: this.options.signal });
|
|
267
|
+
await this.options.client.completeChallenge(challenge);
|
|
268
|
+
await this.options.client.waitForValidStatus(challenge);
|
|
269
|
+
}
|
|
270
|
+
finally {
|
|
271
|
+
// Persist cleanup intent until cleanup actually succeeds, including
|
|
272
|
+
// failure during prepare, process shutdown, or certificate retrieval.
|
|
273
|
+
await handler.cleanup(input);
|
|
274
|
+
record = await this.save(record, {
|
|
275
|
+
pendingChallenges: record.pendingChallenges.filter((value) => value.hostName !== input.hostName || value.challenge !== input.challenge),
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
return record;
|
|
280
|
+
}
|
|
281
|
+
async finish(initial) {
|
|
282
|
+
let record = initial;
|
|
283
|
+
if (!record.order?.certificate)
|
|
284
|
+
throw new Error('Completed order has no certificate URL');
|
|
285
|
+
const pem = await this.options.client.getCertificate(record.order);
|
|
286
|
+
const x509 = new plugins.crypto.X509Certificate(pem);
|
|
287
|
+
const validFrom = new Date(x509.validFrom).getTime();
|
|
288
|
+
const validUntil = new Date(x509.validTo).getTime();
|
|
289
|
+
const certificate = {
|
|
290
|
+
...this.identity(record), id: record.issuanceId, created: Date.now(),
|
|
291
|
+
privateKey: record.privateKey, csr: record.csr, publicKey: pem, validFrom, validUntil,
|
|
292
|
+
renewAfter: validUntil - Math.min(10 * 86400000, (validUntil - validFrom) / 3),
|
|
293
|
+
};
|
|
294
|
+
try {
|
|
295
|
+
this.validateCertificate(certificate, record);
|
|
296
|
+
if (validUntil <= Date.now())
|
|
297
|
+
throw new Error('CA returned an expired certificate');
|
|
298
|
+
}
|
|
299
|
+
catch {
|
|
300
|
+
record = await this.save(record, { status: 'failed', errorCode: 'certificate_invalid' });
|
|
301
|
+
return { status: 'pending', issuance: this.info(record) };
|
|
302
|
+
}
|
|
303
|
+
await this.cleanup(record);
|
|
304
|
+
record = await this.requiredRecord(record.certificateKey);
|
|
305
|
+
if (record.status === 'abandoned_unverified') {
|
|
306
|
+
return { status: 'pending', issuance: this.info(record) };
|
|
307
|
+
}
|
|
308
|
+
await this.options.store.storeCertificate(certificate);
|
|
309
|
+
record = await this.save(record, { status: 'ready', errorCode: undefined });
|
|
310
|
+
return { status: 'ready', certificate, issuance: this.info(record) };
|
|
311
|
+
}
|
|
312
|
+
async handler(record) {
|
|
313
|
+
const handler = this.options.handlers.find((value) => value.getSupportedTypes().includes('dns-01'));
|
|
314
|
+
if (!handler)
|
|
315
|
+
throw new Error('Exact issuance requires DNS-01');
|
|
316
|
+
for (const identifier of record.identifiers) {
|
|
317
|
+
if (!await handler.checkWetherDomainIsSupported(identifier.replace(/^\*\./, ''))) {
|
|
318
|
+
throw new Error('DNS-01 ownership is unavailable for a requested identifier');
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
return handler;
|
|
322
|
+
}
|
|
323
|
+
async cleanup(initial) {
|
|
324
|
+
let record = initial;
|
|
325
|
+
if (!record.pendingChallenges.length)
|
|
326
|
+
return;
|
|
327
|
+
const handler = this.options.handlers.find((value) => value.getSupportedTypes().includes('dns-01'));
|
|
328
|
+
if (!handler)
|
|
329
|
+
throw new Error('DNS-01 cleanup handler is unavailable');
|
|
330
|
+
for (const input of [...record.pendingChallenges]) {
|
|
331
|
+
await handler.cleanup(input);
|
|
332
|
+
record = await this.save(record, {
|
|
333
|
+
pendingChallenges: record.pendingChallenges.filter((value) => value.hostName !== input.hostName || value.challenge !== input.challenge),
|
|
334
|
+
});
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
validateRecord(record, identity) {
|
|
338
|
+
if (record.certificateKey !== identity.certificateKey
|
|
339
|
+
|| this.identity(record).certificateKey !== identity.certificateKey
|
|
340
|
+
|| record.accountThumbprint !== identity.accountThumbprint || record.directoryUrl !== identity.directoryUrl) {
|
|
341
|
+
throw new Error('Issuance storage identity mismatch');
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
validateOrder(order, record) {
|
|
345
|
+
if (!order.url || order.identifiers.some((value) => value.type !== 'dns')
|
|
346
|
+
|| JSON.stringify(normalizeCertificateIdentifiers(order.identifiers.map((value) => value.value))) !== JSON.stringify(record.identifiers)) {
|
|
347
|
+
throw new Error('CA order identifiers do not match the certificate request');
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
validateCertificate(certificate, identity) {
|
|
351
|
+
if (certificate.certificateKey !== identity.certificateKey
|
|
352
|
+
|| this.identity(certificate).certificateKey !== identity.certificateKey
|
|
353
|
+
|| certificate.accountThumbprint !== identity.accountThumbprint || certificate.directoryUrl !== identity.directoryUrl) {
|
|
354
|
+
throw new Error('Certificate storage identity mismatch');
|
|
355
|
+
}
|
|
356
|
+
const parsed = new plugins.x509.X509Certificate(certificate.publicKey);
|
|
357
|
+
const names = parsed.getExtension(plugins.x509.SubjectAlternativeNameExtension)?.names.toJSON();
|
|
358
|
+
if (!names || names.some((value) => value.type !== 'dns')
|
|
359
|
+
|| JSON.stringify(normalizeCertificateIdentifiers(names.map((value) => value.value))) !== JSON.stringify(identity.identifiers)) {
|
|
360
|
+
throw new Error('Certificate identifiers exceed or differ from the requested scope');
|
|
361
|
+
}
|
|
362
|
+
const x509 = new plugins.crypto.X509Certificate(certificate.publicKey);
|
|
363
|
+
if (x509.ca || !x509.checkPrivateKey(plugins.crypto.createPrivateKey(certificate.privateKey))
|
|
364
|
+
|| new Date(x509.validFrom).getTime() !== certificate.validFrom
|
|
365
|
+
|| new Date(x509.validTo).getTime() !== certificate.validUntil
|
|
366
|
+
|| certificate.validFrom > Date.now() + 300000
|
|
367
|
+
|| !Number.isFinite(certificate.renewAfter) || certificate.renewAfter >= certificate.validUntil) {
|
|
368
|
+
throw new Error('Invalid certificate key, lifetime, or constraints');
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
info(record) {
|
|
372
|
+
return {
|
|
373
|
+
certificateKey: record.certificateKey, issuanceId: record.issuanceId,
|
|
374
|
+
identifiers: [...record.identifiers], status: record.status, revision: record.revision,
|
|
375
|
+
createdAt: record.createdAt, updatedAt: record.updatedAt,
|
|
376
|
+
errorCode: record.errorCode, retryAfter: record.retryAfter,
|
|
377
|
+
};
|
|
378
|
+
}
|
|
379
|
+
async requiredRecord(key) {
|
|
380
|
+
const record = await this.options.store.getIssuance(key);
|
|
381
|
+
if (!record)
|
|
382
|
+
throw new Error('Issuance recovery record is missing');
|
|
383
|
+
return record;
|
|
384
|
+
}
|
|
385
|
+
async save(record, patch) {
|
|
386
|
+
const next = { ...record, ...patch, revision: record.revision + 1, updatedAt: Date.now() };
|
|
387
|
+
if (!await this.options.store.compareAndSetIssuance(record.certificateKey, record.revision, next)) {
|
|
388
|
+
throw new Error('Issuance changed concurrently; reload its durable state before proceeding');
|
|
389
|
+
}
|
|
390
|
+
return next;
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5leGFjdC1jZXJ0aWZpY2F0ZS1pc3N1ZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9jbGFzc2VzLmV4YWN0LWNlcnRpZmljYXRlLWlzc3Vlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGNBQWMsQ0FBQztBQVl4QyxNQUFNLFVBQVUsK0JBQStCLENBQUMsS0FBd0I7SUFDdEUsSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLElBQUksS0FBSyxDQUFDLE1BQU0sR0FBRyxDQUFDLElBQUksS0FBSyxDQUFDLE1BQU0sR0FBRyxHQUFHLEVBQUUsQ0FBQztRQUNwRSxNQUFNLElBQUksS0FBSyxDQUFDLDJEQUEyRCxDQUFDLENBQUM7SUFDL0UsQ0FBQztJQUNELE9BQU8sQ0FBQyxHQUFHLElBQUksR0FBRyxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFFLENBQUMsS0FBSyxFQUFFLEVBQUU7WUFDN0MsSUFBSSxPQUFPLEtBQUssS0FBSyxRQUFRLElBQUksS0FBSyxDQUFDLE1BQU0sR0FBRyxJQUFJO2dCQUFFLE1BQU0sSUFBSSxLQUFLLENBQUMsd0JBQXdCLENBQUMsQ0FBQztZQUNoRyxNQUFNLE9BQU8sR0FBRyxLQUFLLENBQUMsSUFBSSxFQUFFLENBQUMsV0FBVyxFQUFFLENBQUMsT0FBTyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsQ0FBQztZQUM5RCxJQUFJLGNBQWMsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDO2dCQUFFLE1BQU0sSUFBSSxLQUFLLENBQUMsd0JBQXdCLENBQUMsQ0FBQztZQUM1RSxNQUFNLFFBQVEsR0FBRyxPQUFPLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQzFDLE1BQU0sSUFBSSxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMsYUFBYSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFD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
|
package/dist_ts/index.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
export * from './smartacme.classes.smartacme.js';
|
|
2
2
|
export { SmartacmeCert as Cert } from './smartacme.classes.cert.js';
|
|
3
3
|
export type { ICertManager } from './interfaces/certmanager.js';
|
|
4
|
+
export type * from './interfaces/exact-issuance.js';
|
|
5
|
+
export { normalizeCertificateIdentifiers } from './classes.exact-certificate-issuer.js';
|
|
4
6
|
import * as certmanagers from './certmanagers/index.js';
|
|
5
7
|
export { certmanagers };
|
|
6
8
|
import * as handlers from './handlers/index.js';
|
package/dist_ts/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export * from './smartacme.classes.smartacme.js';
|
|
2
2
|
export { SmartacmeCert as Cert } from './smartacme.classes.cert.js';
|
|
3
|
+
export { normalizeCertificateIdentifiers } from './classes.exact-certificate-issuer.js';
|
|
3
4
|
// certmanagers
|
|
4
5
|
import * as certmanagers from './certmanagers/index.js';
|
|
5
6
|
export { certmanagers };
|
|
@@ -9,4 +10,4 @@ export { handlers };
|
|
|
9
10
|
// server (ACME Directory Server / CA)
|
|
10
11
|
import * as server from '../dist_ts_server/index.js';
|
|
11
12
|
export { server };
|
|
12
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
13
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxjQUFjLGtDQUFrQyxDQUFDO0FBQ2pELE9BQU8sRUFBRSxhQUFhLElBQUksSUFBSSxFQUFFLE1BQU0sNkJBQTZCLENBQUM7QUFHcEUsT0FBTyxFQUFFLCtCQUErQixFQUFFLE1BQU0sdUNBQXVDLENBQUM7QUFFeEYsZUFBZTtBQUNmLE9BQU8sS0FBSyxZQUFZLE1BQU0seUJBQXlCLENBQUM7QUFDeEQsT0FBTyxFQUFFLFlBQVksRUFBRSxDQUFDO0FBRXhCLFdBQVc7QUFDWCxPQUFPLEtBQUssUUFBUSxNQUFNLHFCQUFxQixDQUFDO0FBQ2hELE9BQU8sRUFBRSxRQUFRLEVBQUUsQ0FBQztBQUVwQixzQ0FBc0M7QUFDdEMsT0FBTyxLQUFLLE1BQU0sTUFBTSx1QkFBdUIsQ0FBQztBQUNoRCxPQUFPLEVBQUUsTUFBTSxFQUFFLENBQUMifQ==
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import type { IAcmeOrder } from '../acme/acme.interfaces.js';
|
|
2
|
+
/** Explicit identifiers never inherit parent or wildcard coverage. */
|
|
3
|
+
export interface IExactCertificateRequest {
|
|
4
|
+
namespace: string;
|
|
5
|
+
identifiers: string[];
|
|
6
|
+
}
|
|
7
|
+
export interface IExactCertificateIdentity extends IExactCertificateRequest {
|
|
8
|
+
certificateKey: string;
|
|
9
|
+
directoryUrl: string;
|
|
10
|
+
accountThumbprint: string;
|
|
11
|
+
}
|
|
12
|
+
export interface IExactCertificate extends IExactCertificateIdentity {
|
|
13
|
+
id: string;
|
|
14
|
+
privateKey: string;
|
|
15
|
+
publicKey: string;
|
|
16
|
+
csr: string;
|
|
17
|
+
created: number;
|
|
18
|
+
validFrom: number;
|
|
19
|
+
validUntil: number;
|
|
20
|
+
renewAfter: number;
|
|
21
|
+
}
|
|
22
|
+
export type TExactIssuanceStatus = 'prepared' | 'creating' | 'authorizing' | 'finalizing' | 'ready' | 'failed' | 'indeterminate' | 'abandoned_unverified';
|
|
23
|
+
export type TExactIssuanceErrorCode = 'order_outcome_unknown' | 'order_invalid' | 'authorization_failed' | 'certificate_invalid' | 'challenge_cleanup_pending' | 'rate_limited' | 'transport_unavailable';
|
|
24
|
+
export interface IExactDnsChallenge {
|
|
25
|
+
hostName: string;
|
|
26
|
+
challenge: string;
|
|
27
|
+
}
|
|
28
|
+
/** Sensitive durable state. Never return this record through a status API. */
|
|
29
|
+
export interface IExactIssuanceRecord extends IExactCertificateIdentity {
|
|
30
|
+
issuanceId: string;
|
|
31
|
+
revision: number;
|
|
32
|
+
status: TExactIssuanceStatus;
|
|
33
|
+
createdAt: number;
|
|
34
|
+
updatedAt: number;
|
|
35
|
+
privateKey: string;
|
|
36
|
+
csr: string;
|
|
37
|
+
order?: IAcmeOrder;
|
|
38
|
+
pendingChallenges: IExactDnsChallenge[];
|
|
39
|
+
errorCode?: TExactIssuanceErrorCode;
|
|
40
|
+
retryAfter?: number;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Storage must acknowledge durable writes and atomically compare revisions.
|
|
44
|
+
* A null revision means insert only if absent. No filesystem fallback is used.
|
|
45
|
+
* Keep unresolved records until their external outcome has been reconciled.
|
|
46
|
+
*/
|
|
47
|
+
export interface IExactIssuanceStore {
|
|
48
|
+
getAccountKey(accountId: string): Promise<string | null>;
|
|
49
|
+
createAccountKey(accountId: string, privateKey: string): Promise<boolean>;
|
|
50
|
+
getIssuance(certificateKey: string): Promise<IExactIssuanceRecord | null>;
|
|
51
|
+
compareAndSetIssuance(certificateKey: string, expectedRevision: number | null, record: IExactIssuanceRecord): Promise<boolean>;
|
|
52
|
+
getCertificate(certificateKey: string): Promise<IExactCertificate | null>;
|
|
53
|
+
storeCertificate(certificate: IExactCertificate): Promise<void>;
|
|
54
|
+
}
|
|
55
|
+
/** Safe status projection; contains neither keys nor challenge material. */
|
|
56
|
+
export interface IExactIssuanceInfo {
|
|
57
|
+
certificateKey: string;
|
|
58
|
+
issuanceId: string;
|
|
59
|
+
identifiers: string[];
|
|
60
|
+
status: TExactIssuanceStatus;
|
|
61
|
+
revision: number;
|
|
62
|
+
createdAt: number;
|
|
63
|
+
updatedAt: number;
|
|
64
|
+
errorCode?: TExactIssuanceErrorCode;
|
|
65
|
+
retryAfter?: number;
|
|
66
|
+
}
|
|
67
|
+
export type TExactCertificateResult = {
|
|
68
|
+
status: 'ready';
|
|
69
|
+
certificate: IExactCertificate;
|
|
70
|
+
issuance: IExactIssuanceInfo;
|
|
71
|
+
} | {
|
|
72
|
+
status: 'pending';
|
|
73
|
+
issuance: IExactIssuanceInfo;
|
|
74
|
+
};
|
|
75
|
+
export interface IExactIssuanceRecoveryRequest extends IExactCertificateRequest {
|
|
76
|
+
issuanceId: string;
|
|
77
|
+
expectedRevision: number;
|
|
78
|
+
action: 'recheck' | 'retry-proven-unapplied' | 'abandon';
|
|
79
|
+
}
|
package/dist_ts/plugins.d.ts
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
import 'reflect-metadata';
|
|
2
2
|
import * as crypto from 'node:crypto';
|
|
3
|
+
import * as url from 'node:url';
|
|
4
|
+
import * as net from 'node:net';
|
|
5
|
+
import * as timers from 'node:timers/promises';
|
|
6
|
+
import * as x509 from '@peculiar/x509';
|
|
3
7
|
import * as fs from 'fs';
|
|
4
8
|
import * as path from 'path';
|
|
5
|
-
export { crypto, fs, path };
|
|
9
|
+
export { crypto, fs, path, url, net, timers, x509 };
|
|
6
10
|
import * as cloudflare from '@apiclient.xyz/cloudflare';
|
|
7
11
|
export { cloudflare };
|
|
8
12
|
import * as lik from '@push.rocks/lik';
|
package/dist_ts/plugins.js
CHANGED
|
@@ -2,9 +2,13 @@
|
|
|
2
2
|
import 'reflect-metadata';
|
|
3
3
|
// node native
|
|
4
4
|
import * as crypto from 'node:crypto';
|
|
5
|
+
import * as url from 'node:url';
|
|
6
|
+
import * as net from 'node:net';
|
|
7
|
+
import * as timers from 'node:timers/promises';
|
|
8
|
+
import * as x509 from '@peculiar/x509';
|
|
5
9
|
import * as fs from 'fs';
|
|
6
10
|
import * as path from 'path';
|
|
7
|
-
export { crypto, fs, path };
|
|
11
|
+
export { crypto, fs, path, url, net, timers, x509 };
|
|
8
12
|
// @apiclient.xyz scope
|
|
9
13
|
import * as cloudflare from '@apiclient.xyz/cloudflare';
|
|
10
14
|
export { cloudflare };
|
|
@@ -29,4 +33,4 @@ export { acme };
|
|
|
29
33
|
// local handlers for challenge types
|
|
30
34
|
import * as handlers from './handlers/index.js';
|
|
31
35
|
export { handlers };
|
|
32
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
36
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGx1Z2lucy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzL3BsdWdpbnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEseUVBQXlFO0FBQ3pFLE9BQU8sa0JBQWtCLENBQUM7QUFFMUIsY0FBYztBQUNkLE9BQU8sS0FBSyxNQUFNLE1BQU0sYUFBYSxDQUFDO0FBQ3RDLE9BQU8sS0FBSyxHQUFHLE1BQU0sVUFBVSxDQUFDO0FBQ2hDLE9BQU8sS0FBSyxHQUFHLE1BQU0sVUFBVSxDQUFDO0FBQ2hDLE9BQU8sS0FBSyxNQUFNLE1BQU0sc0JBQXNCLENBQUM7QUFDL0MsT0FBTyxLQUFLLElBQUksTUFBTSxnQkFBZ0IsQ0FBQztBQUN2QyxPQUFPLEtBQUssRUFBRSxNQUFNLElBQUksQ0FBQztBQUN6QixPQUFPLEtBQUssSUFBSSxNQUFNLE1BQU0sQ0FBQztBQUU3QixPQUFPLEVBQUUsTUFBTSxFQUFFLEVBQUUsRUFBRSxJQUFJLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLENBQUM7QUFFcEQsdUJBQXVCO0FBQ3ZCLE9BQU8sS0FBSyxVQUFVLE1BQU0sMkJBQTJCLENBQUM7QUFFeEQsT0FBTyxFQUFFLFVBQVUsRUFBRSxDQUFDO0FBRXRCLG9CQUFvQjtBQUNwQixPQUFPLEtBQUssR0FBRyxNQUFNLGlCQUFpQixDQUFDO0FBQ3ZDLE9BQU8sS0FBSyxTQUFTLE1BQU0sdUJBQXVCLENBQUM7QUFDbkQsT0FBTyxLQUFLLFVBQVUsTUFBTSx3QkFBd0IsQ0FBQztBQUNyRCxPQUFPLEtBQUssY0FBYyxNQUFNLDZCQUE2QixDQUFDO0FBQzlELE9BQU8sS0FBSyxRQUFRLE1BQU0sc0JBQXNCLENBQUM7QUFDakQsT0FBTyxLQUFLLFlBQVksTUFBTSwwQkFBMEIsQ0FBQztBQUN6RCxPQUFPLEtBQUssV0FBVyxNQUFNLHlCQUF5QixDQUFDO0FBQ3ZELE9BQU8sS0FBSyxXQUFXLE1BQU0seUJBQXlCLENBQUM7QUFDdkQsT0FBTyxLQUFLLFNBQVMsTUFBTSx1QkFBdUIsQ0FBQztBQUNuRCxPQUFPLEtBQUssVUFBVSxNQUFNLHdCQUF3QixDQUFDO0FBRXJELE9BQU8sRUFDTCxHQUFHLEVBQ0gsU0FBUyxFQUNULFVBQVUsRUFDVixjQUFjLEVBQ2QsUUFBUSxFQUNSLFlBQVksRUFDWixXQUFXLEVBQ1gsV0FBVyxFQUNYLFNBQVMsRUFDVCxVQUFVLEdBQ1gsQ0FBQztBQUVGLGlCQUFpQjtBQUNqQixPQUFPLEtBQUssT0FBTyxNQUFNLGtCQUFrQixDQUFDO0FBRTVDLE9BQU8sRUFBRSxPQUFPLEVBQUUsQ0FBQztBQUVuQix3Q0FBd0M7QUFDeEMsT0FBTyxLQUFLLElBQUksTUFBTSxpQkFBaUIsQ0FBQztBQUV4QyxPQUFPLEVBQUUsSUFBSSxFQUFFLENBQUM7QUFDaEIscUNBQXFDO0FBQ3JDLE9BQU8sS0FBSyxRQUFRLE1BQU0scUJBQXFCLENBQUM7QUFDaEQsT0FBTyxFQUFFLFFBQVEsRUFBRSxDQUFDIn0=
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as plugins from './plugins.js';
|
|
2
2
|
import type { ICertManager } from './interfaces/certmanager.js';
|
|
3
3
|
import { SmartacmeCert } from './smartacme.classes.cert.js';
|
|
4
|
+
import type { IExactCertificateIdentity, IExactCertificateRequest, IExactIssuanceRecoveryRequest, IExactIssuanceStore, IExactIssuanceInfo, TExactCertificateResult } from './interfaces/exact-issuance.js';
|
|
4
5
|
/**
|
|
5
6
|
* the options for the class @see SmartAcme
|
|
6
7
|
*/
|
|
@@ -12,6 +13,14 @@ export interface ISmartAcmeOptions {
|
|
|
12
13
|
*/
|
|
13
14
|
certManager: ICertManager;
|
|
14
15
|
environment: 'production' | 'integration';
|
|
16
|
+
/** Optional explicit ACME directory, for private CAs and isolated integration. */
|
|
17
|
+
directoryUrl?: string;
|
|
18
|
+
/** Enables isolated explicit-identifier issuance with durable recovery. */
|
|
19
|
+
exactIssuanceStore?: IExactIssuanceStore;
|
|
20
|
+
/** Bounded number of admitted exact-identity operations (default 64). */
|
|
21
|
+
maxPendingExactRequests?: number;
|
|
22
|
+
/** DNS propagation grace period for explicit issuance; defaults to 60 seconds. */
|
|
23
|
+
exactDnsPropagationDelayMs?: number;
|
|
15
24
|
/**
|
|
16
25
|
* Optional retry/backoff configuration for transient failures
|
|
17
26
|
*/
|
|
@@ -66,6 +75,10 @@ export declare class SmartAcme {
|
|
|
66
75
|
private smartdns;
|
|
67
76
|
logger: plugins.smartlog.Smartlog;
|
|
68
77
|
private privateKey;
|
|
78
|
+
private exactIssuer?;
|
|
79
|
+
private exactRequests;
|
|
80
|
+
private lifecycleAbort;
|
|
81
|
+
private started;
|
|
69
82
|
certmanager: ICertManager;
|
|
70
83
|
challengeHandlers: plugins.handlers.IChallengeHandler<any>[];
|
|
71
84
|
private certmatcher;
|
|
@@ -92,6 +105,15 @@ export declare class SmartAcme {
|
|
|
92
105
|
* Stops the SmartAcme instance and closes certificate store connections.
|
|
93
106
|
*/
|
|
94
107
|
stop(): Promise<void>;
|
|
108
|
+
/** Bind durable work to the current account and issuer without creating an order. */
|
|
109
|
+
getCertificateIdentity(request: IExactCertificateRequest): IExactCertificateIdentity;
|
|
110
|
+
/** Ensure a certificate whose SANs exactly match the explicit identifiers. */
|
|
111
|
+
getCertificateForIdentifiers(request: IExactCertificateRequest): Promise<TExactCertificateResult>;
|
|
112
|
+
getCertificateIssuanceStatus(request: IExactCertificateRequest): Promise<IExactIssuanceInfo | null>;
|
|
113
|
+
/** Administrative recovery; embedding services must authorize the caller. */
|
|
114
|
+
recoverCertificateIssuance(request: IExactIssuanceRecoveryRequest): Promise<TExactCertificateResult>;
|
|
115
|
+
private requireExactIssuer;
|
|
116
|
+
private runExact;
|
|
95
117
|
/** Retry helper with exponential backoff and AcmeError awareness */
|
|
96
118
|
private retry;
|
|
97
119
|
/** Clean up pending challenges and shut down */
|