@push.rocks/smartacme 9.1.2 → 9.2.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_ts/00_commitinfo_data.js +2 -2
- package/dist_ts/acme/acme.classes.account.js +1 -1
- package/dist_ts/acme/acme.classes.challenge.js +1 -1
- package/dist_ts/acme/acme.classes.client.js +1 -1
- package/dist_ts/acme/acme.classes.crypto.d.ts +1 -1
- package/dist_ts/acme/acme.classes.crypto.js +1 -1
- package/dist_ts/acme/acme.classes.directory.js +1 -1
- package/dist_ts/acme/acme.classes.error.js +1 -1
- package/dist_ts/acme/acme.classes.http-client.js +1 -1
- package/dist_ts/acme/acme.classes.order.js +1 -1
- package/dist_ts/acme/acme.interfaces.js +1 -1
- package/dist_ts/acme/index.js +1 -1
- package/dist_ts/certmanagers/index.js +1 -1
- package/dist_ts/certmanagers/memory.js +1 -1
- package/dist_ts/certmanagers/mongo.js +1 -1
- package/dist_ts/handlers/Dns01Handler.js +1 -1
- package/dist_ts/handlers/Http01Handler.js +1 -1
- package/dist_ts/handlers/Http01MemoryHandler.js +1 -1
- package/dist_ts/handlers/IChallengeHandler.js +1 -1
- package/dist_ts/handlers/index.js +1 -1
- package/dist_ts/index.d.ts +2 -0
- package/dist_ts/index.js +4 -1
- package/dist_ts/interfaces/accountdata.js +1 -1
- package/dist_ts/interfaces/certmanager.js +1 -1
- package/dist_ts/interfaces/index.js +1 -1
- package/dist_ts/plugins.js +1 -1
- package/dist_ts/smartacme.classes.cert.js +1 -1
- package/dist_ts/smartacme.classes.certmatcher.js +1 -1
- package/dist_ts/smartacme.classes.smartacme.js +2 -1
- package/dist_ts_server/index.d.ts +4 -0
- package/dist_ts_server/index.js +4 -0
- package/dist_ts_server/server.classes.account.store.d.ts +12 -0
- package/dist_ts_server/server.classes.account.store.js +25 -0
- package/dist_ts_server/server.classes.acmeserver.d.ts +22 -0
- package/dist_ts_server/server.classes.acmeserver.js +100 -0
- package/dist_ts_server/server.classes.ca.d.ts +25 -0
- package/dist_ts_server/server.classes.ca.js +109 -0
- package/dist_ts_server/server.classes.challenge.verifier.d.ts +16 -0
- package/dist_ts_server/server.classes.challenge.verifier.js +56 -0
- package/dist_ts_server/server.classes.jws.verifier.d.ts +31 -0
- package/dist_ts_server/server.classes.jws.verifier.js +116 -0
- package/dist_ts_server/server.classes.nonce.d.ts +12 -0
- package/dist_ts_server/server.classes.nonce.js +32 -0
- package/dist_ts_server/server.classes.order.store.d.ts +21 -0
- package/dist_ts_server/server.classes.order.store.js +57 -0
- package/dist_ts_server/server.classes.router.d.ts +17 -0
- package/dist_ts_server/server.classes.router.js +99 -0
- package/dist_ts_server/server.handlers.account.d.ts +8 -0
- package/dist_ts_server/server.handlers.account.js +59 -0
- package/dist_ts_server/server.handlers.authz.d.ts +7 -0
- package/dist_ts_server/server.handlers.authz.js +41 -0
- package/dist_ts_server/server.handlers.cert.d.ts +7 -0
- package/dist_ts_server/server.handlers.cert.js +18 -0
- package/dist_ts_server/server.handlers.challenge.d.ts +10 -0
- package/dist_ts_server/server.handlers.challenge.js +110 -0
- package/dist_ts_server/server.handlers.directory.d.ts +5 -0
- package/dist_ts_server/server.handlers.directory.js +23 -0
- package/dist_ts_server/server.handlers.finalize.d.ts +8 -0
- package/dist_ts_server/server.handlers.finalize.js +65 -0
- package/dist_ts_server/server.handlers.nonce.d.ts +7 -0
- package/dist_ts_server/server.handlers.nonce.js +17 -0
- package/dist_ts_server/server.handlers.order.d.ts +11 -0
- package/dist_ts_server/server.handlers.order.js +131 -0
- package/dist_ts_server/server.interfaces.d.ts +72 -0
- package/dist_ts_server/server.interfaces.js +2 -0
- package/package.json +11 -11
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/acme/acme.classes.crypto.ts +1 -1
- package/ts/index.ts +4 -0
- package/ts/smartacme.classes.smartacme.ts +1 -0
- package/ts_server/index.ts +12 -0
- package/ts_server/server.classes.account.store.ts +27 -0
- package/ts_server/server.classes.acmeserver.ts +128 -0
- package/ts_server/server.classes.ca.ts +142 -0
- package/ts_server/server.classes.challenge.verifier.ts +61 -0
- package/ts_server/server.classes.jws.verifier.ts +153 -0
- package/ts_server/server.classes.nonce.ts +36 -0
- package/ts_server/server.classes.order.store.ts +72 -0
- package/ts_server/server.classes.router.ts +116 -0
- package/ts_server/server.handlers.account.ts +85 -0
- package/ts_server/server.handlers.authz.ts +58 -0
- package/ts_server/server.handlers.cert.ts +32 -0
- package/ts_server/server.handlers.challenge.ts +142 -0
- package/ts_server/server.handlers.directory.ts +30 -0
- package/ts_server/server.handlers.finalize.ts +93 -0
- package/ts_server/server.handlers.nonce.ts +29 -0
- package/ts_server/server.handlers.order.ts +177 -0
- package/ts_server/server.interfaces.ts +98 -0
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { AcmeServerError } from './server.classes.jws.verifier.js';
|
|
2
|
+
/**
|
|
3
|
+
* Minimal HTTP router for the ACME server.
|
|
4
|
+
* Supports parameterized paths like /order/:id.
|
|
5
|
+
*/
|
|
6
|
+
export class AcmeRouter {
|
|
7
|
+
constructor(nonceManager) {
|
|
8
|
+
this.routes = [];
|
|
9
|
+
this.nonceManager = nonceManager;
|
|
10
|
+
}
|
|
11
|
+
addRoute(method, pattern, handler) {
|
|
12
|
+
this.routes.push({
|
|
13
|
+
method: method.toUpperCase(),
|
|
14
|
+
pattern,
|
|
15
|
+
segments: pattern.split('/').filter(Boolean),
|
|
16
|
+
handler,
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
async handle(req, res) {
|
|
20
|
+
const url = new URL(req.url || '/', `http://${req.headers.host || 'localhost'}`);
|
|
21
|
+
const method = (req.method || 'GET').toUpperCase();
|
|
22
|
+
const pathSegments = url.pathname.split('/').filter(Boolean);
|
|
23
|
+
// Always add a fresh nonce to every response
|
|
24
|
+
res.setHeader('Replay-Nonce', this.nonceManager.generate());
|
|
25
|
+
res.setHeader('Cache-Control', 'no-store');
|
|
26
|
+
// Find matching route
|
|
27
|
+
for (const route of this.routes) {
|
|
28
|
+
if (route.method !== method)
|
|
29
|
+
continue;
|
|
30
|
+
const params = this.matchPath(route.segments, pathSegments);
|
|
31
|
+
if (params === null)
|
|
32
|
+
continue;
|
|
33
|
+
try {
|
|
34
|
+
const body = method === 'POST' ? await this.parseBody(req) : undefined;
|
|
35
|
+
await route.handler(req, res, params, body);
|
|
36
|
+
}
|
|
37
|
+
catch (err) {
|
|
38
|
+
this.sendError(res, err);
|
|
39
|
+
}
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
// No route found
|
|
43
|
+
this.sendError(res, new AcmeServerError(404, 'urn:ietf:params:acme:error:malformed', 'Not found'));
|
|
44
|
+
}
|
|
45
|
+
matchPath(routeSegments, pathSegments) {
|
|
46
|
+
if (routeSegments.length !== pathSegments.length)
|
|
47
|
+
return null;
|
|
48
|
+
const params = {};
|
|
49
|
+
for (let i = 0; i < routeSegments.length; i++) {
|
|
50
|
+
if (routeSegments[i].startsWith(':')) {
|
|
51
|
+
params[routeSegments[i].slice(1)] = pathSegments[i];
|
|
52
|
+
}
|
|
53
|
+
else if (routeSegments[i] !== pathSegments[i]) {
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return params;
|
|
58
|
+
}
|
|
59
|
+
parseBody(req) {
|
|
60
|
+
return new Promise((resolve, reject) => {
|
|
61
|
+
const chunks = [];
|
|
62
|
+
req.on('data', (chunk) => chunks.push(chunk));
|
|
63
|
+
req.on('end', () => {
|
|
64
|
+
const raw = Buffer.concat(chunks).toString('utf-8');
|
|
65
|
+
if (!raw) {
|
|
66
|
+
resolve(undefined);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
try {
|
|
70
|
+
resolve(JSON.parse(raw));
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
reject(new AcmeServerError(400, 'urn:ietf:params:acme:error:malformed', 'Invalid JSON body'));
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
req.on('error', reject);
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
sendError(res, err) {
|
|
80
|
+
if (err instanceof AcmeServerError) {
|
|
81
|
+
res.writeHead(err.status, { 'Content-Type': 'application/problem+json' });
|
|
82
|
+
res.end(JSON.stringify({
|
|
83
|
+
type: err.type,
|
|
84
|
+
detail: err.detail,
|
|
85
|
+
status: err.status,
|
|
86
|
+
}));
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
const message = err instanceof Error ? err.message : 'Internal server error';
|
|
90
|
+
res.writeHead(500, { 'Content-Type': 'application/problem+json' });
|
|
91
|
+
res.end(JSON.stringify({
|
|
92
|
+
type: 'urn:ietf:params:acme:error:serverInternal',
|
|
93
|
+
detail: message,
|
|
94
|
+
status: 500,
|
|
95
|
+
}));
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmVyLmNsYXNzZXMucm91dGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdHNfc2VydmVyL3NlcnZlci5jbGFzc2VzLnJvdXRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFHQSxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sa0NBQWtDLENBQUM7QUFTbkU7OztHQUdHO0FBQ0gsTUFBTSxPQUFPLFVBQVU7SUFJckIsWUFBWSxZQUEwQjtRQUg5QixXQUFNLEdBQWEsRUFBRSxDQUFDO1FBSTVCLElBQUksQ0FBQyxZQUFZLEdBQUcsWUFBWSxDQUFDO0lBQ25DLENBQUM7SUFFRCxRQUFRLENBQUMsTUFBYyxFQUFFLE9BQWUsRUFBRSxPQUFzQjtRQUM5RCxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQztZQUNmLE1BQU0sRUFBRSxNQUFNLENBQUMsV0FBVyxFQUFFO1lBQzVCLE9BQU87WUFDUCxRQUFRLEVBQUUsT0FBTyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDO1lBQzVDLE9BQU87U0FDUixDQUFDLENBQUM7SUFDTCxDQUFDO0lBRUQsS0FBSyxDQUFDLE1BQU0sQ0FBQyxHQUF5QixFQUFFLEdBQXdCO1FBQzlELE1BQU0sR0FBRyxHQUFHLElBQUksR0FBRyxDQUFDLEdBQUcsQ0FBQyxHQUFHLElBQUksR0FBRyxFQUFFLFVBQVUsR0FBRyxDQUFDLE9BQU8sQ0FBQyxJQUFJLElBQUksV0FBVyxFQUFFLENBQUMsQ0FBQztRQUNqRixNQUFNLE1BQU0sR0FBRyxDQUFDLEdBQUcsQ0FBQyxNQUFNLElBQUksS0FBSyxDQUFDLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDbkQsTUFBTSxZQUFZLEdBQUcsR0FBRyxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBRTdELDZDQUE2QztRQUM3QyxHQUFHLENBQUMsU0FBUyxD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
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type * as http from 'node:http';
|
|
2
|
+
import type { JwsVerifier } from './server.classes.jws.verifier.js';
|
|
3
|
+
import type { IServerAccountStore } from './server.interfaces.js';
|
|
4
|
+
/**
|
|
5
|
+
* POST /new-account — Register or retrieve an ACME account.
|
|
6
|
+
* Expects JWS with JWK in protected header (not kid).
|
|
7
|
+
*/
|
|
8
|
+
export declare function createAccountHandler(baseUrl: string, jwsVerifier: JwsVerifier, accountStore: IServerAccountStore): (req: http.IncomingMessage, res: http.ServerResponse, _params: Record<string, string>, body: any) => Promise<void>;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import * as crypto from 'node:crypto';
|
|
2
|
+
import { AcmeCrypto } from '../dist_ts/acme/acme.classes.crypto.js';
|
|
3
|
+
import { AcmeServerError } from './server.classes.jws.verifier.js';
|
|
4
|
+
/**
|
|
5
|
+
* POST /new-account — Register or retrieve an ACME account.
|
|
6
|
+
* Expects JWS with JWK in protected header (not kid).
|
|
7
|
+
*/
|
|
8
|
+
export function createAccountHandler(baseUrl, jwsVerifier, accountStore) {
|
|
9
|
+
return async (req, res, _params, body) => {
|
|
10
|
+
const requestUrl = `${baseUrl}/new-account`;
|
|
11
|
+
const verified = await jwsVerifier.verify(body, requestUrl);
|
|
12
|
+
// Account creation must use JWK, not kid
|
|
13
|
+
if (verified.kid) {
|
|
14
|
+
throw new AcmeServerError(400, 'urn:ietf:params:acme:error:malformed', 'newAccount requests must use JWK, not kid');
|
|
15
|
+
}
|
|
16
|
+
const { payload, jwk, thumbprint } = verified;
|
|
17
|
+
// Check if account already exists
|
|
18
|
+
const existing = await accountStore.getByThumbprint(thumbprint);
|
|
19
|
+
if (existing) {
|
|
20
|
+
// If onlyReturnExisting, or just returning the existing account
|
|
21
|
+
res.writeHead(200, {
|
|
22
|
+
'Content-Type': 'application/json',
|
|
23
|
+
'Location': existing.url,
|
|
24
|
+
});
|
|
25
|
+
res.end(JSON.stringify({
|
|
26
|
+
status: existing.status,
|
|
27
|
+
contact: existing.contact,
|
|
28
|
+
orders: `${baseUrl}/account/${existing.id}/orders`,
|
|
29
|
+
}));
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
// onlyReturnExisting = true but no account found
|
|
33
|
+
if (payload?.onlyReturnExisting) {
|
|
34
|
+
throw new AcmeServerError(400, 'urn:ietf:params:acme:error:accountDoesNotExist', 'Account does not exist');
|
|
35
|
+
}
|
|
36
|
+
// Create new account
|
|
37
|
+
const id = crypto.randomBytes(16).toString('hex');
|
|
38
|
+
const accountUrl = `${baseUrl}/account/${id}`;
|
|
39
|
+
const account = await accountStore.create({
|
|
40
|
+
id,
|
|
41
|
+
thumbprint,
|
|
42
|
+
url: accountUrl,
|
|
43
|
+
jwk,
|
|
44
|
+
status: 'valid',
|
|
45
|
+
contact: payload?.contact || [],
|
|
46
|
+
createdAt: new Date().toISOString(),
|
|
47
|
+
});
|
|
48
|
+
res.writeHead(201, {
|
|
49
|
+
'Content-Type': 'application/json',
|
|
50
|
+
'Location': accountUrl,
|
|
51
|
+
});
|
|
52
|
+
res.end(JSON.stringify({
|
|
53
|
+
status: account.status,
|
|
54
|
+
contact: account.contact,
|
|
55
|
+
orders: `${baseUrl}/account/${id}/orders`,
|
|
56
|
+
}));
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmVyLmhhbmRsZXJzLmFjY291bnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90c19zZXJ2ZXIvc2VydmVyLmhhbmRsZXJzLmFjY291bnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxLQUFLLE1BQU0sTUFBTSxhQUFhLENBQUM7QUFDdEMsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLG1DQUFtQyxDQUFDO0FBRS9ELE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxrQ0FBa0MsQ0FBQztBQUduRTs7O0dBR0c7QUFDSCxNQUFNLFVBQVUsb0JBQW9CLENBQ2xDLE9BQWUsRUFDZixXQUF3QixFQUN4QixZQUFpQztJQUVqQyxPQUFPLEtBQUssRUFDVixHQUF5QixFQUN6QixHQUF3QixFQUN4QixPQUErQixFQUMvQixJQUFTLEVBQ00sRUFBRTtRQUNqQixNQUFNLFVBQVUsR0FBRyxHQUFHLE9BQU8sY0FBYyxDQUFDO1FBQzVDLE1BQU0sUUFBUSxHQUFHLE1BQU0sV0FBVyxDQUFDLE1BQU0sQ0FBQyxJQUFJLEVBQUUsVUFBVSxDQUFDLENBQUM7UUFFNUQseUNBQXlDO1FBQ3pDLElBQUksUUFBUSxDQUFDLEdBQUcsRUFBRSxDQUFDO1lBQ2pCLE1BQU0sSUFBSSxlQUFlLENBQ3ZCLEdBQUcsRUFDSCxzQ0FBc0MsRUFDdEMsMkNBQTJDLENBQzVDLENBQUM7UUFDSixDQUFDO1FBRUQsTUFBTSxFQUFFLE9BQU8sRUFBRSxHQUFHLEVBQUUsVUFBVSxFQUFFLEdBQUcsUUFBUSxDQUFDO1FBRTlDLGtDQUFrQztRQUNsQyxNQUFNLFFBQVEsR0FBRyxNQUFNLFlBQVksQ0FBQyxlQUFlLENBQUMsVUFBVSxDQUFDLENBQUM7UUFDaEUsSUFBSSxRQUFRLEVBQUUsQ0FBQztZQUNiLGdFQUFnRTtZQUNoRSxHQUFHLENBQUMsU0FBUyxDQUFDLEdBQUcsRUFBRTtnQkFDakIsY0FBYyxFQUFFLGtCQUFrQjtnQkFDbEMsVUFBVSxFQUFFLFFBQVEsQ0FBQyxHQUFHO2FBQ3pCLENBQUMsQ0FBQztZQUNILEdBQUcsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQztnQkFDckIsTUFBTSxFQUFFLFFBQVEsQ0FBQyxNQUFNO2dCQUN2QixPQUFPLEVBQUUsUUFBUSxDQUFDLE9BQU87Z0JBQ3pCLE1BQU0sRUFBRSxHQUFHLE9BQU8sWUFBWSxRQUFRLENBQUMsRUFBRSxTQUFTO2FBQ25ELENBQUMsQ0FBQyxDQUFDO1lBQ0osT0FBTztRQUNULENBQUM7UUFFRCxpREFBaUQ7UUFDakQsSUFBSSxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsQ0FBQztZQUNoQyxNQUFNLElBQUksZUFBZSxDQUN2QixHQUFHLEVBQ0gsZ0RBQWdELEVBQ2hELHdCQUF3QixDQUN6QixDQUFDO1FBQ0osQ0FBQztRQUVELHFCQUFxQjtRQUNyQixNQUFNLEVBQUUsR0FBRyxNQUFNLENBQUMsV0FBVyxDQUFDLEVBQUUsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUNsRCxNQUFNLFVBQVUsR0FBRyxHQUFHLE9BQU8sWUFBWSxFQUFFLEVBQUUsQ0FBQztRQUM5QyxNQUFNLE9BQU8sR0FBRyxNQUFNLFlBQVksQ0FBQyxNQUFNLENBQUM7WUFDeEMsRUFBRTtZQUNGLFVBQVU7WUFDVixHQUFHLEVBQUUsVUFBVTtZQUNmLEdBQUc7WUFDSCxNQUFNLEVBQUUsT0FBTztZQUNmLE9BQU8sRUFBRSxPQUFPLEVBQUUsT0FBTyxJQUFJLEVBQUU7WUFDL0IsU0FBUyxFQUFFLElBQUksSUFBSSxFQUFFLENBQUMsV0FBVyxFQUFFO1NBQ3BDLENBQUMsQ0FBQztRQUVILEdBQUcsQ0FBQyxTQUFTLENBQUMsR0FBRyxFQUFFO1lBQ2pCLGNBQWMsRUFBRSxrQkFBa0I7WUFDbEMsVUFBVSxFQUFFLFVBQVU7U0FDdkIsQ0FBQyxDQUFDO1FBQ0gsR0FBRyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDO1lBQ3JCLE1BQU0sRUFBRSxPQUFPLENBQUMsTUFBTTtZQUN0QixPQUFPLEVBQUUsT0FBTyxDQUFDLE9BQU87WUFDeEIsTUFBTSxFQUFFLEdBQUcsT0FBTyxZQUFZLEVBQUUsU0FBUztTQUMxQyxDQUFDLENBQUMsQ0FBQztJQUNOLENBQUMsQ0FBQztBQUNKLENBQUMifQ==
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type * as http from 'node:http';
|
|
2
|
+
import type { JwsVerifier } from './server.classes.jws.verifier.js';
|
|
3
|
+
import type { IServerOrderStore } from './server.interfaces.js';
|
|
4
|
+
/**
|
|
5
|
+
* POST /authz/:id — Return authorization with embedded challenges (POST-as-GET).
|
|
6
|
+
*/
|
|
7
|
+
export declare function createAuthzHandler(baseUrl: string, jwsVerifier: JwsVerifier, orderStore: IServerOrderStore): (req: http.IncomingMessage, res: http.ServerResponse, params: Record<string, string>, body: any) => Promise<void>;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { AcmeServerError } from './server.classes.jws.verifier.js';
|
|
2
|
+
/**
|
|
3
|
+
* POST /authz/:id — Return authorization with embedded challenges (POST-as-GET).
|
|
4
|
+
*/
|
|
5
|
+
export function createAuthzHandler(baseUrl, jwsVerifier, orderStore) {
|
|
6
|
+
return async (req, res, params, body) => {
|
|
7
|
+
const authzId = params.id;
|
|
8
|
+
const requestUrl = `${baseUrl}/authz/${authzId}`;
|
|
9
|
+
await jwsVerifier.verify(body, requestUrl);
|
|
10
|
+
const authz = await orderStore.getAuthorization(authzId);
|
|
11
|
+
if (!authz) {
|
|
12
|
+
throw new AcmeServerError(404, 'urn:ietf:params:acme:error:malformed', 'Authorization not found');
|
|
13
|
+
}
|
|
14
|
+
// Build challenge objects
|
|
15
|
+
const challenges = [];
|
|
16
|
+
for (const challengeId of authz.challengeIds) {
|
|
17
|
+
const challenge = await orderStore.getChallenge(challengeId);
|
|
18
|
+
if (challenge) {
|
|
19
|
+
challenges.push({
|
|
20
|
+
type: challenge.type,
|
|
21
|
+
url: `${baseUrl}/challenge/${challenge.id}`,
|
|
22
|
+
status: challenge.status,
|
|
23
|
+
token: challenge.token,
|
|
24
|
+
...(challenge.validated ? { validated: challenge.validated } : {}),
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
const responseBody = {
|
|
29
|
+
identifier: authz.identifier,
|
|
30
|
+
status: authz.status,
|
|
31
|
+
expires: authz.expires,
|
|
32
|
+
challenges,
|
|
33
|
+
};
|
|
34
|
+
if (authz.wildcard) {
|
|
35
|
+
responseBody.wildcard = true;
|
|
36
|
+
}
|
|
37
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
38
|
+
res.end(JSON.stringify(responseBody));
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmVyLmhhbmRsZXJzLmF1dGh6LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdHNfc2VydmVyL3NlcnZlci5oYW5kbGVycy5hdXRoei50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFFQSxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sa0NBQWtDLENBQUM7QUFHbkU7O0dBRUc7QUFDSCxNQUFNLFVBQVUsa0JBQWtCLENBQ2hDLE9BQWUsRUFDZixXQUF3QixFQUN4QixVQUE2QjtJQUU3QixPQUFPLEtBQUssRUFDVixHQUF5QixFQUN6QixHQUF3QixFQUN4QixNQUE4QixFQUM5QixJQUFTLEVBQ00sRUFBRTtRQUNqQixNQUFNLE9BQU8sR0FBRyxNQUFNLENBQUMsRUFBRSxDQUFDO1FBQzFCLE1BQU0sVUFBVSxHQUFHLEdBQUcsT0FBTyxVQUFVLE9BQU8sRUFBRSxDQUFDO1FBQ2pELE1BQU0sV0FBVyxDQUFDLE1BQU0sQ0FBQyxJQUFJLEVBQUUsVUFBVSxDQUFDLENBQUM7UUFFM0MsTUFBTSxLQUFLLEdBQUcsTUFBTSxVQUFVLENBQUMsZ0JBQWdCLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDekQsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO1lBQ1gsTUFBTSxJQUFJLGVBQWUsQ0FBQyxHQUFHLEVBQUUsc0NBQXNDLEVBQUUseUJBQXlCLENBQUMsQ0FBQztRQUNwRyxDQUFDO1FBRUQsMEJBQTBCO1FBQzFCLE1BQU0sVUFBVSxHQUFHLEVBQUUsQ0FBQztRQUN0QixLQUFLLE1BQU0sV0FBVyxJQUFJLEtBQUssQ0FBQyxZQUFZLEVBQUUsQ0FBQztZQUM3QyxNQUFNLFNBQVMsR0FBRyxNQUFNLFVBQVUsQ0FBQyxZQUFZLENBQUMsV0FBVyxDQUFDLENBQUM7WUFDN0QsSUFBSSxTQUFTLEVBQUUsQ0FBQztnQkFDZCxVQUFVLENBQUMsSUFBSSxDQUFDO29CQUNkLElBQUksRUFBRSxTQUFTLENBQUMsSUFBSTtvQkFDcEIsR0FBRyxFQUFFLEdBQUcsT0FBTyxjQUFjLFNBQVMsQ0FBQyxFQUFFLEVBQUU7b0JBQzNDLE1BQU0sRUFBRSxTQUFTLENBQUMsTUFBTTtvQkFDeEIsS0FBSyxFQUFFLFNBQVMsQ0FBQyxLQUFLO29CQUN0QixHQUFHLENBQUMsU0FBUyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsRUFBRSxTQUFTLEVBQUUsU0FBUyxDQUFDLFNBQVMsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7aUJBQ25FLENBQUMsQ0FBQztZQUNMLENBQUM7UUFDSCxDQUFDO1FBRUQsTUFBTSxZQUFZLEdBQXdCO1lBQ3hDLFVBQVUsRUFBRSxLQUFLLENBQUMsVUFBVTtZQUM1QixNQUFNLEVBQUUsS0FBSyxDQUFDLE1BQU07WUFDcEIsT0FBTyxFQUFFLEtBQUssQ0FBQyxPQUFPO1lBQ3RCLFVBQVU7U0FDWCxDQUFDO1FBRUYsSUFBSSxLQUFLLENBQUMsUUFBUSxFQUFFLENBQUM7WUFDbkIsWUFBWSxDQUFDLFFBQVEsR0FBRyxJQUFJLENBQUM7UUFDL0IsQ0FBQztRQUVELEdBQUcsQ0FBQyxTQUFTLENBQUMsR0FBRyxFQUFFLEVBQUUsY0FBYyxFQUFFLGtCQUFrQixFQUFFLENBQUMsQ0FBQztRQUMzRCxHQUFHLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQztJQUN4QyxDQUFDLENBQUM7QUFDSixDQUFDIn0=
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type * as http from 'node:http';
|
|
2
|
+
import type { JwsVerifier } from './server.classes.jws.verifier.js';
|
|
3
|
+
import type { IServerOrderStore } from './server.interfaces.js';
|
|
4
|
+
/**
|
|
5
|
+
* POST /cert/:id — Download certificate chain (POST-as-GET).
|
|
6
|
+
*/
|
|
7
|
+
export declare function createCertHandler(baseUrl: string, jwsVerifier: JwsVerifier, orderStore: IServerOrderStore): (req: http.IncomingMessage, res: http.ServerResponse, params: Record<string, string>, body: any) => Promise<void>;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { AcmeServerError } from './server.classes.jws.verifier.js';
|
|
2
|
+
/**
|
|
3
|
+
* POST /cert/:id — Download certificate chain (POST-as-GET).
|
|
4
|
+
*/
|
|
5
|
+
export function createCertHandler(baseUrl, jwsVerifier, orderStore) {
|
|
6
|
+
return async (req, res, params, body) => {
|
|
7
|
+
const orderId = params.id;
|
|
8
|
+
const requestUrl = `${baseUrl}/cert/${orderId}`;
|
|
9
|
+
await jwsVerifier.verify(body, requestUrl);
|
|
10
|
+
const certPem = await orderStore.getCertPem(orderId);
|
|
11
|
+
if (!certPem) {
|
|
12
|
+
throw new AcmeServerError(404, 'urn:ietf:params:acme:error:malformed', 'Certificate not found');
|
|
13
|
+
}
|
|
14
|
+
res.writeHead(200, { 'Content-Type': 'application/pem-certificate-chain' });
|
|
15
|
+
res.end(certPem);
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmVyLmhhbmRsZXJzLmNlcnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90c19zZXJ2ZXIvc2VydmVyLmhhbmRsZXJzLmNlcnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBRUEsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLGtDQUFrQyxDQUFDO0FBR25FOztHQUVHO0FBQ0gsTUFBTSxVQUFVLGlCQUFpQixDQUMvQixPQUFlLEVBQ2YsV0FBd0IsRUFDeEIsVUFBNkI7SUFFN0IsT0FBTyxLQUFLLEVBQ1YsR0FBeUIsRUFDekIsR0FBd0IsRUFDeEIsTUFBOEIsRUFDOUIsSUFBUyxFQUNNLEVBQUU7UUFDakIsTUFBTSxPQUFPLEdBQUcsTUFBTSxDQUFDLEVBQUUsQ0FBQztRQUMxQixNQUFNLFVBQVUsR0FBRyxHQUFHLE9BQU8sU0FBUyxPQUFPLEVBQUUsQ0FBQztRQUNoRCxNQUFNLFdBQVcsQ0FBQyxNQUFNLENBQUMsSUFBSSxFQUFFLFVBQVUsQ0FBQyxDQUFDO1FBRTNDLE1BQU0sT0FBTyxHQUFHLE1BQU0sVUFBVSxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUNyRCxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7WUFDYixNQUFNLElBQUksZUFBZSxDQUFDLEdBQUcsRUFBRSxzQ0FBc0MsRUFBRSx1QkFBdUIsQ0FBQyxDQUFDO1FBQ2xHLENBQUM7UUFFRCxHQUFHLENBQUMsU0FBUyxDQUFDLEdBQUcsRUFBRSxFQUFFLGNBQWMsRUFBRSxtQ0FBbUMsRUFBRSxDQUFDLENBQUM7UUFDNUUsR0FBRyxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUNuQixDQUFDLENBQUM7QUFDSixDQUFDIn0=
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type * as http from 'node:http';
|
|
2
|
+
import type { JwsVerifier } from './server.classes.jws.verifier.js';
|
|
3
|
+
import type { IServerOrderStore, IServerAccountStore } from './server.interfaces.js';
|
|
4
|
+
import type { ChallengeVerifier } from './server.classes.challenge.verifier.js';
|
|
5
|
+
/**
|
|
6
|
+
* POST /challenge/:id — Trigger or poll an ACME challenge.
|
|
7
|
+
* - POST with `{}` payload: trigger challenge validation
|
|
8
|
+
* - POST-as-GET (null payload): return current challenge state
|
|
9
|
+
*/
|
|
10
|
+
export declare function createChallengeHandler(baseUrl: string, jwsVerifier: JwsVerifier, orderStore: IServerOrderStore, accountStore: IServerAccountStore, challengeVerifier: ChallengeVerifier): (req: http.IncomingMessage, res: http.ServerResponse, params: Record<string, string>, body: any) => Promise<void>;
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import * as crypto from 'node:crypto';
|
|
2
|
+
import { AcmeCrypto } from '../dist_ts/acme/acme.classes.crypto.js';
|
|
3
|
+
import { AcmeServerError } from './server.classes.jws.verifier.js';
|
|
4
|
+
/**
|
|
5
|
+
* POST /challenge/:id — Trigger or poll an ACME challenge.
|
|
6
|
+
* - POST with `{}` payload: trigger challenge validation
|
|
7
|
+
* - POST-as-GET (null payload): return current challenge state
|
|
8
|
+
*/
|
|
9
|
+
export function createChallengeHandler(baseUrl, jwsVerifier, orderStore, accountStore, challengeVerifier) {
|
|
10
|
+
return async (req, res, params, body) => {
|
|
11
|
+
const challengeId = params.id;
|
|
12
|
+
const requestUrl = `${baseUrl}/challenge/${challengeId}`;
|
|
13
|
+
const verified = await jwsVerifier.verify(body, requestUrl);
|
|
14
|
+
const challenge = await orderStore.getChallenge(challengeId);
|
|
15
|
+
if (!challenge) {
|
|
16
|
+
throw new AcmeServerError(404, 'urn:ietf:params:acme:error:malformed', 'Challenge not found');
|
|
17
|
+
}
|
|
18
|
+
// POST-as-GET: just return current state
|
|
19
|
+
if (verified.payload === null) {
|
|
20
|
+
sendChallengeResponse(res, challenge, baseUrl);
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
// Trigger validation (payload should be `{}`)
|
|
24
|
+
if (challenge.status !== 'pending') {
|
|
25
|
+
// Already processing or completed
|
|
26
|
+
sendChallengeResponse(res, challenge, baseUrl);
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
// Set to processing
|
|
30
|
+
await orderStore.updateChallenge(challengeId, { status: 'processing' });
|
|
31
|
+
// Get the authorization to find the domain
|
|
32
|
+
const authz = await orderStore.getAuthorization(challenge.authorizationId);
|
|
33
|
+
if (!authz) {
|
|
34
|
+
throw new AcmeServerError(500, 'urn:ietf:params:acme:error:serverInternal', 'Authorization not found');
|
|
35
|
+
}
|
|
36
|
+
// Resolve the account's JWK for key authorization computation
|
|
37
|
+
const account = await accountStore.getByUrl(verified.kid);
|
|
38
|
+
if (!account) {
|
|
39
|
+
throw new AcmeServerError(400, 'urn:ietf:params:acme:error:accountDoesNotExist', 'Account not found');
|
|
40
|
+
}
|
|
41
|
+
const thumbprint = AcmeCrypto.getJwkThumbprint(account.jwk);
|
|
42
|
+
const keyAuth = `${challenge.token}.${thumbprint}`;
|
|
43
|
+
// Verify the challenge
|
|
44
|
+
let valid = false;
|
|
45
|
+
const domain = authz.identifier.value;
|
|
46
|
+
if (challenge.type === 'http-01') {
|
|
47
|
+
valid = await challengeVerifier.verifyHttp01(domain, challenge.token, keyAuth);
|
|
48
|
+
}
|
|
49
|
+
else if (challenge.type === 'dns-01') {
|
|
50
|
+
const hash = crypto.createHash('sha256').update(keyAuth).digest('base64url');
|
|
51
|
+
valid = await challengeVerifier.verifyDns01(domain, hash);
|
|
52
|
+
}
|
|
53
|
+
if (valid) {
|
|
54
|
+
await orderStore.updateChallenge(challengeId, {
|
|
55
|
+
status: 'valid',
|
|
56
|
+
validated: new Date().toISOString(),
|
|
57
|
+
});
|
|
58
|
+
challenge.status = 'valid';
|
|
59
|
+
challenge.validated = new Date().toISOString();
|
|
60
|
+
// Check if all challenges for this authorization's required type are valid
|
|
61
|
+
// One valid challenge is enough to validate the authorization
|
|
62
|
+
await orderStore.updateAuthorization(authz.id, { status: 'valid' });
|
|
63
|
+
// Check if all authorizations for the order are now valid
|
|
64
|
+
const order = await orderStore.getOrder(authz.orderId);
|
|
65
|
+
if (order && order.status === 'pending') {
|
|
66
|
+
let allValid = true;
|
|
67
|
+
for (const authzId of order.authorizationIds) {
|
|
68
|
+
const a = await orderStore.getAuthorization(authzId);
|
|
69
|
+
if (!a || a.status !== 'valid') {
|
|
70
|
+
allValid = false;
|
|
71
|
+
break;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
if (allValid) {
|
|
75
|
+
await orderStore.updateOrder(order.id, { status: 'ready' });
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
await orderStore.updateChallenge(challengeId, {
|
|
81
|
+
status: 'invalid',
|
|
82
|
+
error: {
|
|
83
|
+
type: 'urn:ietf:params:acme:error:incorrectResponse',
|
|
84
|
+
detail: `Challenge verification failed for ${domain}`,
|
|
85
|
+
},
|
|
86
|
+
});
|
|
87
|
+
challenge.status = 'invalid';
|
|
88
|
+
// Mark authorization as invalid too
|
|
89
|
+
await orderStore.updateAuthorization(authz.id, { status: 'invalid' });
|
|
90
|
+
}
|
|
91
|
+
sendChallengeResponse(res, challenge, baseUrl);
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
function sendChallengeResponse(res, challenge, baseUrl) {
|
|
95
|
+
const responseBody = {
|
|
96
|
+
type: challenge.type,
|
|
97
|
+
url: `${baseUrl}/challenge/${challenge.id}`,
|
|
98
|
+
status: challenge.status,
|
|
99
|
+
token: challenge.token,
|
|
100
|
+
};
|
|
101
|
+
if (challenge.validated) {
|
|
102
|
+
responseBody.validated = challenge.validated;
|
|
103
|
+
}
|
|
104
|
+
res.writeHead(200, {
|
|
105
|
+
'Content-Type': 'application/json',
|
|
106
|
+
'Link': `<${baseUrl}/directory>;rel="index"`,
|
|
107
|
+
});
|
|
108
|
+
res.end(JSON.stringify(responseBody));
|
|
109
|
+
}
|
|
110
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmVyLmhhbmRsZXJzLmNoYWxsZW5nZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzX3NlcnZlci9zZXJ2ZXIuaGFuZGxlcnMuY2hhbGxlbmdlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUNBLE9BQU8sS0FBSyxNQUFNLE1BQU0sYUFBYSxDQUFDO0FBQ3RDLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxtQ0FBbUMsQ0FBQztBQUUvRCxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sa0NBQWtDLENBQUM7QUFJbkU7Ozs7R0FJRztBQUNILE1BQU0sVUFBVSxzQkFBc0IsQ0FDcEMsT0FBZSxFQUNmLFdBQXdCLEVBQ3hCLFVBQTZCLEVBQzdCLFlBQWlDLEVBQ2pDLGlCQUFvQztJQUVwQyxPQUFPLEtBQUssRUFDVixHQUF5QixFQUN6QixHQUF3QixFQUN4QixNQUE4QixFQUM5QixJQUFTLEVBQ00sRUFBRTtRQUNqQixNQUFNLFdBQVcsR0FBRyxNQUFNLENBQUMsRUFBRSxDQUFDO1FBQzlCLE1BQU0sVUFBVSxHQUFHLEdBQUcsT0FBTyxjQUFjLFdBQVcsRUFBRSxDQUFDO1FBQ3pELE1BQU0sUUFBUSxHQUFHLE1BQU0sV0FBVyxDQUFDLE1BQU0sQ0FBQyxJQUFJLEVBQUUsVUFBVSxDQUFDLENBQUM7UUFFNUQsTUFBTSxTQUFTLEdBQUcsTUFBTSxVQUFVLENBQUMsWUFBWSxDQUFDLFdBQVcsQ0FBQyxDQUFDO1FBQzdELElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztZQUNmLE1BQU0sSUFBSSxlQUFlLENBQUMsR0FBRyxFQUFFLHNDQUFzQyxFQUFFLHFCQUFxQixDQUFDLENBQUM7UUFDaEcsQ0FBQztRQUVELHlDQUF5QztRQUN6QyxJQUFJLFFBQVEsQ0FBQyxPQUFPLEtBQUssSUFBSSxFQUFFLENBQUM7WUFDOUIscUJBQXFCLENBQUMsR0FBRyxFQUFFLFNBQVMsRUFBRSxPQUFPLENBQUMsQ0FBQztZQUMvQyxPQUFPO1FBQ1QsQ0FBQztR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
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type * as http from 'node:http';
|
|
2
|
+
/**
|
|
3
|
+
* GET /directory — Returns the ACME directory object with all endpoint URLs.
|
|
4
|
+
*/
|
|
5
|
+
export declare function createDirectoryHandler(baseUrl: string): (_req: http.IncomingMessage, res: http.ServerResponse, _params: Record<string, string>, _body: any) => Promise<void>;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GET /directory — Returns the ACME directory object with all endpoint URLs.
|
|
3
|
+
*/
|
|
4
|
+
export function createDirectoryHandler(baseUrl) {
|
|
5
|
+
return async (_req, res, _params, _body) => {
|
|
6
|
+
const directory = {
|
|
7
|
+
newNonce: `${baseUrl}/new-nonce`,
|
|
8
|
+
newAccount: `${baseUrl}/new-account`,
|
|
9
|
+
newOrder: `${baseUrl}/new-order`,
|
|
10
|
+
revokeCert: `${baseUrl}/revoke-cert`,
|
|
11
|
+
keyChange: `${baseUrl}/key-change`,
|
|
12
|
+
meta: {
|
|
13
|
+
termsOfService: `${baseUrl}/terms`,
|
|
14
|
+
website: `${baseUrl}`,
|
|
15
|
+
caaIdentities: [],
|
|
16
|
+
externalAccountRequired: false,
|
|
17
|
+
},
|
|
18
|
+
};
|
|
19
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
20
|
+
res.end(JSON.stringify(directory));
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmVyLmhhbmRsZXJzLmRpcmVjdG9yeS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzX3NlcnZlci9zZXJ2ZXIuaGFuZGxlcnMuZGlyZWN0b3J5LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUdBOztHQUVHO0FBQ0gsTUFBTSxVQUFVLHNCQUFzQixDQUFDLE9BQWU7SUFDcEQsT0FBTyxLQUFLLEVBQ1YsSUFBMEIsRUFDMUIsR0FBd0IsRUFDeEIsT0FBK0IsRUFDL0IsS0FBVSxFQUNLLEVBQUU7UUFDakIsTUFBTSxTQUFTLEdBQW1CO1lBQ2hDLFFBQVEsRUFBRSxHQUFHLE9BQU8sWUFBWTtZQUNoQyxVQUFVLEVBQUUsR0FBRyxPQUFPLGNBQWM7WUFDcEMsUUFBUSxFQUFFLEdBQUcsT0FBTyxZQUFZO1lBQ2hDLFVBQVUsRUFBRSxHQUFHLE9BQU8sY0FBYztZQUNwQyxTQUFTLEVBQUUsR0FBRyxPQUFPLGFBQWE7WUFDbEMsSUFBSSxFQUFFO2dCQUNKLGNBQWMsRUFBRSxHQUFHLE9BQU8sUUFBUTtnQkFDbEMsT0FBTyxFQUFFLEdBQUcsT0FBTyxFQUFFO2dCQUNyQixhQUFhLEVBQUUsRUFBRTtnQkFDakIsdUJBQXVCLEVBQUUsS0FBSzthQUMvQjtTQUNGLENBQUM7UUFDRixHQUFHLENBQUMsU0FBUyxDQUFDLEdBQUcsRUFBRSxFQUFFLGNBQWMsRUFBRSxrQkFBa0IsRUFBRSxDQUFDLENBQUM7UUFDM0QsR0FBRyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUM7SUFDckMsQ0FBQyxDQUFDO0FBQ0osQ0FBQyJ9
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type * as http from 'node:http';
|
|
2
|
+
import type { JwsVerifier } from './server.classes.jws.verifier.js';
|
|
3
|
+
import type { IServerOrderStore } from './server.interfaces.js';
|
|
4
|
+
import type { AcmeServerCA } from './server.classes.ca.js';
|
|
5
|
+
/**
|
|
6
|
+
* POST /finalize/:id — Submit CSR and issue certificate.
|
|
7
|
+
*/
|
|
8
|
+
export declare function createFinalizeHandler(baseUrl: string, jwsVerifier: JwsVerifier, orderStore: IServerOrderStore, ca: AcmeServerCA): (req: http.IncomingMessage, res: http.ServerResponse, params: Record<string, string>, body: any) => Promise<void>;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { AcmeServerError } from './server.classes.jws.verifier.js';
|
|
2
|
+
/**
|
|
3
|
+
* POST /finalize/:id — Submit CSR and issue certificate.
|
|
4
|
+
*/
|
|
5
|
+
export function createFinalizeHandler(baseUrl, jwsVerifier, orderStore, ca) {
|
|
6
|
+
return async (req, res, params, body) => {
|
|
7
|
+
const orderId = params.id;
|
|
8
|
+
const requestUrl = `${baseUrl}/finalize/${orderId}`;
|
|
9
|
+
const verified = await jwsVerifier.verify(body, requestUrl);
|
|
10
|
+
if (!verified.kid) {
|
|
11
|
+
throw new AcmeServerError(400, 'urn:ietf:params:acme:error:malformed', 'Finalize requires kid');
|
|
12
|
+
}
|
|
13
|
+
const order = await orderStore.getOrder(orderId);
|
|
14
|
+
if (!order) {
|
|
15
|
+
throw new AcmeServerError(404, 'urn:ietf:params:acme:error:malformed', 'Order not found');
|
|
16
|
+
}
|
|
17
|
+
// Check all authorizations are valid and update order status if needed
|
|
18
|
+
if (order.status === 'pending') {
|
|
19
|
+
let allValid = true;
|
|
20
|
+
for (const authzId of order.authorizationIds) {
|
|
21
|
+
const authz = await orderStore.getAuthorization(authzId);
|
|
22
|
+
if (!authz || authz.status !== 'valid') {
|
|
23
|
+
allValid = false;
|
|
24
|
+
break;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
if (allValid) {
|
|
28
|
+
await orderStore.updateOrder(orderId, { status: 'ready' });
|
|
29
|
+
order.status = 'ready';
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
if (order.status !== 'ready') {
|
|
33
|
+
throw new AcmeServerError(403, 'urn:ietf:params:acme:error:orderNotReady', `Order is in "${order.status}" state, expected "ready"`);
|
|
34
|
+
}
|
|
35
|
+
const { payload } = verified;
|
|
36
|
+
if (!payload?.csr) {
|
|
37
|
+
throw new AcmeServerError(400, 'urn:ietf:params:acme:error:malformed', 'Missing CSR in finalize request');
|
|
38
|
+
}
|
|
39
|
+
// Transition to processing
|
|
40
|
+
await orderStore.updateOrder(orderId, { status: 'processing' });
|
|
41
|
+
// Sign the certificate
|
|
42
|
+
const certPem = await ca.signCsr(payload.csr);
|
|
43
|
+
// Store certificate and update order
|
|
44
|
+
const certUrl = `${baseUrl}/cert/${orderId}`;
|
|
45
|
+
await orderStore.storeCertPem(orderId, certPem);
|
|
46
|
+
await orderStore.updateOrder(orderId, {
|
|
47
|
+
status: 'valid',
|
|
48
|
+
certificate: certUrl,
|
|
49
|
+
});
|
|
50
|
+
const responseBody = {
|
|
51
|
+
status: 'valid',
|
|
52
|
+
expires: order.expires,
|
|
53
|
+
identifiers: order.identifiers,
|
|
54
|
+
authorizations: order.authorizationIds.map((id) => `${baseUrl}/authz/${id}`),
|
|
55
|
+
finalize: order.finalize,
|
|
56
|
+
certificate: certUrl,
|
|
57
|
+
};
|
|
58
|
+
res.writeHead(200, {
|
|
59
|
+
'Content-Type': 'application/json',
|
|
60
|
+
'Location': `${baseUrl}/order/${orderId}`,
|
|
61
|
+
});
|
|
62
|
+
res.end(JSON.stringify(responseBody));
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmVyLmhhbmRsZXJzLmZpbmFsaXplLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdHNfc2VydmVyL3NlcnZlci5oYW5kbGVycy5maW5hbGl6ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFFQSxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sa0NBQWtDLENBQUM7QUFJbkU7O0dBRUc7QUFDSCxNQUFNLFVBQVUscUJBQXFCLENBQ25DLE9BQWUsRUFDZixXQUF3QixFQUN4QixVQUE2QixFQUM3QixFQUFnQjtJQUVoQixPQUFPLEtBQUssRUFDVixHQUF5QixFQUN6QixHQUF3QixFQUN4QixNQUE4QixFQUM5QixJQUFTLEVBQ00sRUFBRTtRQUNqQixNQUFNLE9BQU8sR0FBRyxNQUFNLENBQUMsRUFBRSxDQUFDO1FBQzFCLE1BQU0sVUFBVSxHQUFHLEdBQUcsT0FBTyxhQUFhLE9BQU8sRUFBRSxDQUFDO1FBQ3BELE1BQU0sUUFBUSxHQUFHLE1BQU0sV0FBVyxDQUFDLE1BQU0sQ0FBQyxJQUFJLEVBQUUsVUFBVSxDQUFDLENBQUM7UUFFNUQsSUFBSSxDQUFDLFFBQVEsQ0FBQyxHQUFHLEVBQUUsQ0FBQztZQUNsQixNQUFNLElBQUksZUFBZSxDQUFDLEdBQUcsRUFBRSxzQ0FBc0MsRUFBRSx1QkFBdUIsQ0FBQyxDQUFDO1FBQ2xHLENBQUM7UUFFRCxNQUFNLEtBQUssR0FBRyxNQUFNLFVBQVUsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDakQsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO1lBQ1gsTUFBTSxJQUFJLGVBQWUsQ0FBQyxHQUFHLEVBQUUsc0NBQXNDLEVBQUUsaUJBQWlCLENBQUMsQ0FBQztRQUM1RixDQUFDO1FBRUQsdUVBQXVFO1FBQ3ZFLElBQUksS0FBSyxDQUFDLE1BQU0sS0FBSyxTQUFTLEVBQUUsQ0FBQztZQUMvQixJQUFJLFFBQVEsR0FBRyxJQUFJLENBQUM7WUFDcEIsS0FBSyxNQUFNLE9BQU8sSUFBSSxLQUFLLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztnQkFDN0MsTUFBTSxLQUFLLEdBQUcsTUFBTSxVQUFVLENBQUMsZ0JBQWdCLENBQUMsT0FBTyxDQUFDLENBQUM7Z0JBQ3pELElBQUksQ0FBQyxLQUFLLElBQUksS0FBSyxDQUFDLE1BQU0sS0FBSyxPQUFPLEVBQUUsQ0FBQztvQkFDdkMsUUFBUSxHQUFHLEtBQUssQ0FBQztvQkFDakIsTUFBTTtnQkFDUixDQUFDO1lBQ0gsQ0FBQztZQUNELElBQUksUUFBUSxFQUFFLENBQUM7Z0JBQ2IsTUFBTSxVQUFVLENBQUMsV0FBVyxDQUFDLE9BQU8sRUFBRSxFQUFFLE1BQU0sRUFBRSxPQUFPLEVBQUUsQ0FBQyxDQUFDO2dCQUMzRCxLQUFLLENBQUMsTUFBTSxHQUFHLE9BQU8sQ0FBQztZQUN6QixDQUFDO1FBQ0gsQ0FBQztRQUVELElBQUksS0FBSyxDQUFDLE1BQU0sS0FBSyxPQUFPLEVBQUUsQ0FBQztZQUM3QixNQUFNLElBQUksZUFBZSxDQUN2QixHQUFHLEVBQ0gsMENBQTBDLEVBQzFDLGdCQUFnQixLQUFLLENBQUMsTUFBTSwyQkFBMkIsQ0FDeEQsQ0FBQztRQUNKLENBQUM7UUFFRCxNQUFNLEVBQUUsT0FBTyxFQUFFLEdBQUcsUUFBUSxDQUFDO1FBQzdCLElBQUksQ0FBQyxPQUFPLEVBQUUsR0FBRyxFQUFFLENBQUM7WUFDbEIsTUFBTSxJQUFJLGVBQWUsQ0FBQyxHQUFHLEVBQUUsc0NBQXNDLEVBQUUsaUNBQWlDLENBQUMsQ0FBQztRQUM1RyxDQUFDO1FBRUQsMkJBQTJCO1FBQzNCLE1BQU0sVUFBVSxDQUFDLFdBQVcsQ0FBQyxPQUFPLEVBQUUsRUFBRSxNQUFNLEVBQUUsWUFBWSxFQUFFLENBQUMsQ0FBQztRQUVoRSx1QkFBdUI7UUFDdkIsTUFBTSxPQUFPLEdBQUcsTUFBTSxFQUFFLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUU5QyxxQ0FBcUM7UUFDckMsTUFBTSxPQUFPLEdBQUcsR0FBRyxPQUFPLFNBQVMsT0FBTyxFQUFFLENBQUM7UUFDN0MsTUFBTSxVQUFVLENBQUMsWUFBWSxDQUFDLE9BQU8sRUFBRSxPQUFPLENBQUMsQ0FBQztRQUNoRCxNQUFNLFVBQVUsQ0FBQyxXQUFXLENBQUMsT0FBTyxFQUFFO1lBQ3BDLE1BQU0sRUFBRSxPQUFPO1lBQ2YsV0FBVyxFQUFFLE9BQU87U0FDckIsQ0FBQyxDQUFDO1FBRUgsTUFBTSxZQUFZLEdBQUc7WUFDbkIsTUFBTSxFQUFFLE9BQU87WUFDZixPQUFPLEVBQUUsS0FBSyxDQUFDLE9BQU87WUFDdEIsV0FBVyxFQUFFLEtBQUssQ0FBQyxXQUFXO1lBQzlCLGNBQWMsRUFBRSxLQUFLLENBQUMsZ0JBQWdCLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxHQUFHLE9BQU8sVUFBVSxFQUFFLEVBQUUsQ0FBQztZQUM1RSxRQUFRLEVBQUUsS0FBSyxDQUFDLFFBQVE7WUFDeEIsV0FBVyxFQUFFLE9BQU87U0FDckIsQ0FBQztRQUVGLEdBQUcsQ0FBQyxTQUFTLENBQUMsR0FBRyxFQUFFO1lBQ2pCLGNBQWMsRUFBRSxrQkFBa0I7WUFDbEMsVUFBVSxFQUFFLEdBQUcsT0FBTyxVQUFVLE9BQU8sRUFBRTtTQUMxQyxDQUFDLENBQUM7UUFDSCxHQUFHLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQztJQUN4QyxDQUFDLENBQUM7QUFDSixDQUFDIn0=
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type * as http from 'node:http';
|
|
2
|
+
/**
|
|
3
|
+
* HEAD /new-nonce — Returns 200 with Replay-Nonce header (added by router).
|
|
4
|
+
* GET /new-nonce — Returns 204 with Replay-Nonce header (added by router).
|
|
5
|
+
*/
|
|
6
|
+
export declare function createNonceHeadHandler(): (_req: http.IncomingMessage, res: http.ServerResponse, _params: Record<string, string>, _body: any) => Promise<void>;
|
|
7
|
+
export declare function createNonceGetHandler(): (_req: http.IncomingMessage, res: http.ServerResponse, _params: Record<string, string>, _body: any) => Promise<void>;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HEAD /new-nonce — Returns 200 with Replay-Nonce header (added by router).
|
|
3
|
+
* GET /new-nonce — Returns 204 with Replay-Nonce header (added by router).
|
|
4
|
+
*/
|
|
5
|
+
export function createNonceHeadHandler() {
|
|
6
|
+
return async (_req, res, _params, _body) => {
|
|
7
|
+
res.writeHead(200, { 'Content-Type': 'application/octet-stream' });
|
|
8
|
+
res.end();
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
export function createNonceGetHandler() {
|
|
12
|
+
return async (_req, res, _params, _body) => {
|
|
13
|
+
res.writeHead(204);
|
|
14
|
+
res.end();
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmVyLmhhbmRsZXJzLm5vbmNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdHNfc2VydmVyL3NlcnZlci5oYW5kbGVycy5ub25jZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFFQTs7O0dBR0c7QUFDSCxNQUFNLFVBQVUsc0JBQXNCO0lBQ3BDLE9BQU8sS0FBSyxFQUNWLElBQTBCLEVBQzFCLEdBQXdCLEVBQ3hCLE9BQStCLEVBQy9CLEtBQVUsRUFDSyxFQUFFO1FBQ2pCLEdBQUcsQ0FBQyxTQUFTLENBQUMsR0FBRyxFQUFFLEVBQUUsY0FBYyxFQUFFLDBCQUEwQixFQUFFLENBQUMsQ0FBQztRQUNuRSxHQUFHLENBQUMsR0FBRyxFQUFFLENBQUM7SUFDWixDQUFDLENBQUM7QUFDSixDQUFDO0FBRUQsTUFBTSxVQUFVLHFCQUFxQjtJQUNuQyxPQUFPLEtBQUssRUFDVixJQUEwQixFQUMxQixHQUF3QixFQUN4QixPQUErQixFQUMvQixLQUFVLEVBQ0ssRUFBRTtRQUNqQixHQUFHLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQ25CLEdBQUcsQ0FBQyxHQUFHLEVBQUUsQ0FBQztJQUNaLENBQUMsQ0FBQztBQUNKLENBQUMifQ==
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type * as http from 'node:http';
|
|
2
|
+
import type { JwsVerifier } from './server.classes.jws.verifier.js';
|
|
3
|
+
import type { IServerOrderStore } from './server.interfaces.js';
|
|
4
|
+
/**
|
|
5
|
+
* POST /new-order — Create a new ACME order.
|
|
6
|
+
*/
|
|
7
|
+
export declare function createNewOrderHandler(baseUrl: string, jwsVerifier: JwsVerifier, orderStore: IServerOrderStore): (req: http.IncomingMessage, res: http.ServerResponse, _params: Record<string, string>, body: any) => Promise<void>;
|
|
8
|
+
/**
|
|
9
|
+
* POST /order/:id — Poll order status (POST-as-GET).
|
|
10
|
+
*/
|
|
11
|
+
export declare function createOrderPollHandler(baseUrl: string, jwsVerifier: JwsVerifier, orderStore: IServerOrderStore): (req: http.IncomingMessage, res: http.ServerResponse, params: Record<string, string>, body: any) => Promise<void>;
|