@entity-access/server-pages 1.0.31 → 1.0.32
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/ServerPages.d.ts +1 -1
- package/dist/ServerPages.d.ts.map +1 -1
- package/dist/ServerPages.js +7 -2
- package/dist/ServerPages.js.map +1 -1
- package/dist/ssl/{ACME.d.ts → AcmeCertificateService.d.ts} +3 -2
- package/dist/ssl/AcmeCertificateService.d.ts.map +1 -0
- package/dist/ssl/{ACME.js → AcmeCertificateService.js} +17 -39
- package/dist/ssl/AcmeCertificateService.js.map +1 -0
- package/dist/ssl/{ChallengeStore.d.ts → AcmeChallengeStore.d.ts} +2 -3
- package/dist/ssl/AcmeChallengeStore.d.ts.map +1 -0
- package/dist/ssl/{ChallengeStore.js → AcmeChallengeStore.js} +2 -2
- package/dist/ssl/AcmeChallengeStore.js.map +1 -0
- package/dist/ssl/CertificateStore.d.ts +15 -0
- package/dist/ssl/CertificateStore.d.ts.map +1 -0
- package/dist/ssl/CertificateStore.js +65 -0
- package/dist/ssl/CertificateStore.js.map +1 -0
- package/dist/ssl/ChallengeServer.d.ts +5 -0
- package/dist/ssl/ChallengeServer.d.ts.map +1 -0
- package/dist/ssl/ChallengeServer.js +45 -0
- package/dist/ssl/ChallengeServer.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/ServerPages.ts +9 -2
- package/src/ssl/{ACME.ts → AcmeCertificateService.ts} +225 -247
- package/src/ssl/{ChallengeStore.ts → AcmeChallengeStore.ts} +25 -25
- package/src/ssl/CertificateStore.ts +68 -0
- package/src/ssl/ChallengeServer.ts +34 -0
- package/dist/ssl/ACME.d.ts.map +0 -1
- package/dist/ssl/ACME.js.map +0 -1
- package/dist/ssl/ChallengeStore.d.ts.map +0 -1
- package/dist/ssl/ChallengeStore.js.map +0 -1
|
@@ -1,247 +1,225 @@
|
|
|
1
|
-
import * as forge from "node-forge";
|
|
2
|
-
import * as crypto from "crypto";
|
|
3
|
-
import * as acme from "acme-client";
|
|
4
|
-
import DateTime from "@entity-access/entity-access/dist/types/DateTime.js";
|
|
5
|
-
import cluster from "cluster";
|
|
6
|
-
import { existsSync, writeFileSync, readFileSync, unlinkSync, mkdirSync } from "fs";
|
|
7
|
-
import { join } from "path"
|
|
8
|
-
import ensureDir, { deleteIfExists } from "../core/FileApi.js";
|
|
9
|
-
import Inject, { RegisterSingleton } from "@entity-access/entity-access/dist/di/di.js";
|
|
10
|
-
import ChallengeStore from "./
|
|
11
|
-
import * as tls from "node:tls";
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
const
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
const
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
shortName: 'OU',
|
|
227
|
-
value: 'Test'
|
|
228
|
-
}
|
|
229
|
-
];
|
|
230
|
-
|
|
231
|
-
// here we set subject and issuer as the same one
|
|
232
|
-
crt.setSubject(attrs);
|
|
233
|
-
crt.setIssuer(attrs);
|
|
234
|
-
|
|
235
|
-
// the actual certificate signing
|
|
236
|
-
crt.sign(keys.privateKey);
|
|
237
|
-
|
|
238
|
-
// now convert the Forge certificate to PEM format
|
|
239
|
-
cert = pki.certificateToPem(crt);
|
|
240
|
-
key = pki.privateKeyToPem(keys.privateKey);
|
|
241
|
-
|
|
242
|
-
writeFileSync(certPath, cert);
|
|
243
|
-
writeFileSync(keyPath, key);
|
|
244
|
-
|
|
245
|
-
return { key, cert };
|
|
246
|
-
}
|
|
247
|
-
}
|
|
1
|
+
import * as forge from "node-forge";
|
|
2
|
+
import * as crypto from "crypto";
|
|
3
|
+
import * as acme from "acme-client";
|
|
4
|
+
import DateTime from "@entity-access/entity-access/dist/types/DateTime.js";
|
|
5
|
+
import cluster from "cluster";
|
|
6
|
+
import { existsSync, writeFileSync, readFileSync, unlinkSync, mkdirSync } from "fs";
|
|
7
|
+
import { join } from "path"
|
|
8
|
+
import ensureDir, { deleteIfExists } from "../core/FileApi.js";
|
|
9
|
+
import Inject, { RegisterSingleton } from "@entity-access/entity-access/dist/di/di.js";
|
|
10
|
+
import ChallengeStore from "./AcmeChallengeStore.js";
|
|
11
|
+
import * as tls from "node:tls";
|
|
12
|
+
import CertificateStore from "./CertificateStore.js";
|
|
13
|
+
|
|
14
|
+
export interface IAcmeOptions {
|
|
15
|
+
sslMode?: string,
|
|
16
|
+
accountPrivateKeyPath?: string,
|
|
17
|
+
emailAddress?: string,
|
|
18
|
+
mode?: "production" | "self-signed" | "staging",
|
|
19
|
+
endPoint?: string,
|
|
20
|
+
eabKid?: string,
|
|
21
|
+
eabHmac?: string
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface ICertOptions extends IAcmeOptions {
|
|
25
|
+
host: string,
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
@RegisterSingleton
|
|
29
|
+
export default class AcmeCertficateService {
|
|
30
|
+
|
|
31
|
+
@Inject
|
|
32
|
+
private challengeStore: ChallengeStore;
|
|
33
|
+
|
|
34
|
+
@Inject
|
|
35
|
+
private certificateStore: CertificateStore;
|
|
36
|
+
|
|
37
|
+
private map = new Map<string, tls.SecureContext>();
|
|
38
|
+
|
|
39
|
+
public async getSecureContext(options: ICertOptions) {
|
|
40
|
+
const { host } = options;
|
|
41
|
+
let sc = this.map.get(host);
|
|
42
|
+
if (sc) {
|
|
43
|
+
return sc;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const { key , cert } = await this.setup(options)
|
|
47
|
+
sc = tls.createSecureContext({ cert, key });
|
|
48
|
+
this.map.set(host, sc);
|
|
49
|
+
return sc;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
public async setup({
|
|
53
|
+
host,
|
|
54
|
+
sslMode = "./",
|
|
55
|
+
accountPrivateKeyPath = "./",
|
|
56
|
+
emailAddress = "",
|
|
57
|
+
mode = "production" as "production" | "self-signed" | "staging",
|
|
58
|
+
endPoint = "",
|
|
59
|
+
eabKid = "",
|
|
60
|
+
eabHmac = ""
|
|
61
|
+
}) {
|
|
62
|
+
|
|
63
|
+
if (mode === "self-signed") {
|
|
64
|
+
return this.setupSelfSigned(sslMode);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const hostRoot = join(sslMode, host);
|
|
68
|
+
|
|
69
|
+
ensureDir(hostRoot);
|
|
70
|
+
|
|
71
|
+
const keyPath = join(hostRoot, "cert.key");
|
|
72
|
+
const certPath = join(hostRoot, "cert.crt");
|
|
73
|
+
|
|
74
|
+
const logs = [];
|
|
75
|
+
|
|
76
|
+
try {
|
|
77
|
+
|
|
78
|
+
const maintainerEmail = emailAddress;
|
|
79
|
+
|
|
80
|
+
let externalAccountBinding;
|
|
81
|
+
|
|
82
|
+
if (eabKid) {
|
|
83
|
+
externalAccountBinding = {
|
|
84
|
+
kid: eabKid,
|
|
85
|
+
hmacKey: eabHmac
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
let { cert, key } = await this.certificateStore.get({ host });
|
|
90
|
+
|
|
91
|
+
// load cert...
|
|
92
|
+
if (cert) {
|
|
93
|
+
const certificate = new crypto.X509Certificate(cert);
|
|
94
|
+
const validTo = DateTime.parse(certificate.validTo).diff(DateTime.now);
|
|
95
|
+
if (validTo.totalDays > 30) {
|
|
96
|
+
console.log(`Reusing certificate, valid for ${validTo.totalDays}`);
|
|
97
|
+
return { cert , key };
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const accountKey = await this.certificateStore.getAccountKey();
|
|
102
|
+
|
|
103
|
+
acme.setLogger((message) => {
|
|
104
|
+
// console.log(message);
|
|
105
|
+
logs.push(message);
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
let altNames;
|
|
109
|
+
|
|
110
|
+
// auto renew...
|
|
111
|
+
const client = new acme.Client({
|
|
112
|
+
directoryUrl: endPoint || acme.directory.letsencrypt[mode],
|
|
113
|
+
accountKey,
|
|
114
|
+
externalAccountBinding,
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
/* Create CSR */
|
|
118
|
+
const [csrKey, csr] = await acme.crypto.createCsr({
|
|
119
|
+
commonName: host,
|
|
120
|
+
altNames
|
|
121
|
+
}, key);
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
/* Certificate */
|
|
126
|
+
cert = await client.auto({
|
|
127
|
+
csr,
|
|
128
|
+
email: maintainerEmail,
|
|
129
|
+
termsOfServiceAgreed: true,
|
|
130
|
+
skipChallengeVerification: true,
|
|
131
|
+
challengePriority: ["http-01"],
|
|
132
|
+
challengeCreateFn: (authz, challenge, keyAuthorization) => {
|
|
133
|
+
if (challenge.type !== "http-01") {
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
return this.challengeStore.save(challenge.token, keyAuthorization);
|
|
137
|
+
},
|
|
138
|
+
challengeRemoveFn: (authz, challenge, keyAuthorization) => {
|
|
139
|
+
return this.challengeStore.remove(challenge.token);
|
|
140
|
+
},
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
writeFileSync(certPath, cert);
|
|
144
|
+
|
|
145
|
+
return { cert, key };
|
|
146
|
+
} catch (error) {
|
|
147
|
+
console.log(logs.join("\n"));
|
|
148
|
+
console.error(error);
|
|
149
|
+
throw error;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
public setupSelfSigned(sslMode = "./") {
|
|
154
|
+
|
|
155
|
+
const selfSigned = `${sslMode}/self-signed/`;
|
|
156
|
+
|
|
157
|
+
ensureDir(selfSigned);
|
|
158
|
+
|
|
159
|
+
const certPath = `${selfSigned}/cert.crt`;
|
|
160
|
+
const keyPath = `${selfSigned}/key.pem`;
|
|
161
|
+
|
|
162
|
+
let key;
|
|
163
|
+
let cert;
|
|
164
|
+
|
|
165
|
+
if (existsSync(certPath) && existsSync(keyPath)) {
|
|
166
|
+
key = readFileSync(keyPath);
|
|
167
|
+
cert = readFileSync(certPath);
|
|
168
|
+
return { key, cert };
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
const pki = forge.default.pki;
|
|
172
|
+
|
|
173
|
+
// generate a key pair or use one you have already
|
|
174
|
+
const keys = pki.rsa.generateKeyPair(2048);
|
|
175
|
+
|
|
176
|
+
// create a new certificate
|
|
177
|
+
const crt = pki.createCertificate();
|
|
178
|
+
|
|
179
|
+
// fill the required fields
|
|
180
|
+
crt.publicKey = keys.publicKey;
|
|
181
|
+
crt.serialNumber = '01';
|
|
182
|
+
crt.validity.notBefore = new Date();
|
|
183
|
+
crt.validity.notAfter = new Date();
|
|
184
|
+
crt.validity.notAfter.setFullYear(crt.validity.notBefore.getFullYear() + 40);
|
|
185
|
+
|
|
186
|
+
// use your own attributes here, or supply a csr (check the docs)
|
|
187
|
+
const attrs = [
|
|
188
|
+
{
|
|
189
|
+
name: 'commonName',
|
|
190
|
+
value: 'dev.socialmail.in'
|
|
191
|
+
}, {
|
|
192
|
+
name: 'countryName',
|
|
193
|
+
value: 'IN'
|
|
194
|
+
}, {
|
|
195
|
+
shortName: 'ST',
|
|
196
|
+
value: 'Maharashtra'
|
|
197
|
+
}, {
|
|
198
|
+
name: 'localityName',
|
|
199
|
+
value: 'Navi Mumbai'
|
|
200
|
+
}, {
|
|
201
|
+
name: 'organizationName',
|
|
202
|
+
value: 'NeuroSpeech Technologies Pvt Ltd'
|
|
203
|
+
}, {
|
|
204
|
+
shortName: 'OU',
|
|
205
|
+
value: 'Test'
|
|
206
|
+
}
|
|
207
|
+
];
|
|
208
|
+
|
|
209
|
+
// here we set subject and issuer as the same one
|
|
210
|
+
crt.setSubject(attrs);
|
|
211
|
+
crt.setIssuer(attrs);
|
|
212
|
+
|
|
213
|
+
// the actual certificate signing
|
|
214
|
+
crt.sign(keys.privateKey);
|
|
215
|
+
|
|
216
|
+
// now convert the Forge certificate to PEM format
|
|
217
|
+
cert = pki.certificateToPem(crt);
|
|
218
|
+
key = pki.privateKeyToPem(keys.privateKey);
|
|
219
|
+
|
|
220
|
+
writeFileSync(certPath, cert);
|
|
221
|
+
writeFileSync(keyPath, key);
|
|
222
|
+
|
|
223
|
+
return { key, cert };
|
|
224
|
+
}
|
|
225
|
+
}
|
|
@@ -1,26 +1,26 @@
|
|
|
1
|
-
import { RegisterSingleton } from "@entity-access/entity-access/dist/di/di.js";
|
|
2
|
-
import ensureDir from "../core/FileApi.js";
|
|
3
|
-
import { readFileSync, unlinkSync, writeFileSync } from "fs";
|
|
4
|
-
import { join } from "node:path";
|
|
5
|
-
|
|
6
|
-
const path = "./challenges";
|
|
7
|
-
|
|
8
|
-
@RegisterSingleton
|
|
9
|
-
export default class ChallengeStore {
|
|
10
|
-
|
|
11
|
-
constructor() {
|
|
12
|
-
ensureDir(path);
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
async get(name: string) {
|
|
16
|
-
return readFileSync(join(path, name));
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
async save(name: string, value: string) {
|
|
20
|
-
writeFileSync(join(path, name), value, "utf8");
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
async remove(name: string) {
|
|
24
|
-
unlinkSync(join(path, name));
|
|
25
|
-
}
|
|
1
|
+
import { RegisterSingleton } from "@entity-access/entity-access/dist/di/di.js";
|
|
2
|
+
import ensureDir from "../core/FileApi.js";
|
|
3
|
+
import { readFileSync, unlinkSync, writeFileSync } from "fs";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
|
|
6
|
+
const path = "./challenges";
|
|
7
|
+
|
|
8
|
+
@RegisterSingleton
|
|
9
|
+
export default class ChallengeStore {
|
|
10
|
+
|
|
11
|
+
constructor() {
|
|
12
|
+
ensureDir(path);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
async get(name: string) {
|
|
16
|
+
return readFileSync(join(path, name), "utf8");
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
async save(name: string, value: string) {
|
|
20
|
+
writeFileSync(join(path, name), value, "utf8");
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
async remove(name: string) {
|
|
24
|
+
unlinkSync(join(path, name));
|
|
25
|
+
}
|
|
26
26
|
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { RegisterSingleton } from "@entity-access/entity-access/dist/di/di.js";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import ensureDir from "../core/FileApi.js";
|
|
4
|
+
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
5
|
+
import * as acme from "acme-client";
|
|
6
|
+
|
|
7
|
+
export interface ICertificate {
|
|
8
|
+
host?: string;
|
|
9
|
+
key?: Buffer;
|
|
10
|
+
cert?: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
let folder = "./certs";
|
|
14
|
+
|
|
15
|
+
@RegisterSingleton
|
|
16
|
+
export default class CertificateStore {
|
|
17
|
+
|
|
18
|
+
public get folder() {
|
|
19
|
+
return folder;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
public set folder(v: string) {
|
|
23
|
+
folder = v;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
public async getAccountKey() {
|
|
27
|
+
const keyPath = join(folder, "keys");
|
|
28
|
+
let key: Buffer;
|
|
29
|
+
ensureDir(keyPath);
|
|
30
|
+
if (!existsSync(keyPath)) {
|
|
31
|
+
key = await acme.crypto.createPrivateRsaKey();
|
|
32
|
+
writeFileSync(keyPath, key);
|
|
33
|
+
console.log(`Creating New Account key: ${keyPath}`);
|
|
34
|
+
} else {
|
|
35
|
+
key = readFileSync(keyPath);
|
|
36
|
+
}
|
|
37
|
+
return key;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
public async get( { host }: ICertificate): Promise<ICertificate> {
|
|
41
|
+
const { certPath, keyPath } = this.getPaths(folder, host);
|
|
42
|
+
const cert = existsSync(certPath) ? readFileSync(certPath, "utf8") : "";
|
|
43
|
+
let key: Buffer;
|
|
44
|
+
if (!existsSync(keyPath)) {
|
|
45
|
+
key = await acme.crypto.createPrivateRsaKey();
|
|
46
|
+
writeFileSync(keyPath, key);
|
|
47
|
+
console.log(`Creating New key: ${keyPath}`);
|
|
48
|
+
} else {
|
|
49
|
+
key = readFileSync(keyPath);
|
|
50
|
+
}
|
|
51
|
+
return { host, cert, key };
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
public async save({ host, cert, key }: ICertificate) {
|
|
55
|
+
const { certPath, keyPath } = this.getPaths(folder, host);
|
|
56
|
+
writeFileSync(certPath, cert, "utf8");
|
|
57
|
+
writeFileSync(keyPath, key);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
private getPaths(folder: string, host: string) {
|
|
61
|
+
const hostRoot = join(folder, host);
|
|
62
|
+
ensureDir(hostRoot);
|
|
63
|
+
const certPath = join(hostRoot, "cert.crt");
|
|
64
|
+
const keyPath = join(hostRoot, "key.pem");
|
|
65
|
+
return { certPath, keyPath }
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import * as http from "node:http";
|
|
2
|
+
import Inject, { RegisterSingleton } from "@entity-access/entity-access/dist/di/di.js";
|
|
3
|
+
import ChallengeStore from "./AcmeChallengeStore.js";
|
|
4
|
+
|
|
5
|
+
@RegisterSingleton
|
|
6
|
+
export default class ChallengeServer {
|
|
7
|
+
|
|
8
|
+
@Inject
|
|
9
|
+
private challengeStore: ChallengeStore;
|
|
10
|
+
|
|
11
|
+
start() {
|
|
12
|
+
const server = http.createServer(async (req, res) => {
|
|
13
|
+
try {
|
|
14
|
+
const url = new URL(req.url, `https://${req.headers.host || "localhost"}`);
|
|
15
|
+
const path = url.pathname.split("/").filter((x) => x);
|
|
16
|
+
if(url.pathname.startsWith("/.well-known/acme-challenge/")) {
|
|
17
|
+
const token = path[2];
|
|
18
|
+
const value = await this.challengeStore.get(token);
|
|
19
|
+
res.writeHead(200, { "content-type": "text/plain" });
|
|
20
|
+
await new Promise<void>((resolve, reject) => res.write(Buffer.from(value), (error) => error ? reject(error) : resolve()));
|
|
21
|
+
} else {
|
|
22
|
+
res.writeHead(301, { location: url.toString() });
|
|
23
|
+
}
|
|
24
|
+
await new Promise<void>((resolve) => res.end(resolve));
|
|
25
|
+
|
|
26
|
+
} catch (error) {
|
|
27
|
+
console.error(error);
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
server.listen(80);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
}
|
package/dist/ssl/ACME.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ACME.d.ts","sourceRoot":"","sources":["../../src/ssl/ACME.ts"],"names":[],"mappings":";AAUA,OAAO,KAAK,GAAG,MAAM,UAAU,CAAC;AAEhC,MAAM,WAAW,YAAY;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,IAAI,CAAC,EAAG,YAAY,GAAG,aAAa,GAAG,SAAS,CAAC;IACjD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,YAAa,SAAQ,YAAY;IAC9C,IAAI,EAAE,MAAM,CAAC;CAChB;AAGD,MAAM,CAAC,OAAO,OAAO,IAAI;IAGrB,OAAO,CAAC,cAAc,CAAiB;IAEvC,OAAO,CAAC,GAAG,CAAwC;IAEtC,gBAAgB,CAAC,OAAO,EAAE,YAAY;IAatC,KAAK,CAAC,EACf,IAAI,EACJ,OAAc,EACd,qBAA4B,EAC5B,YAAiB,EACjB,IAA+D,EAC/D,QAAa,EACb,MAAW,EACX,OAAY,EACf;;;;;;;;;KAAA;;;;IAsHM,eAAe,CAAC,OAAO,SAAO;;;;CAwExC"}
|
package/dist/ssl/ACME.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ACME.js","sourceRoot":"","sources":["../../src/ssl/ACME.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ChallengeStore.d.ts","sourceRoot":"","sources":["../../src/ssl/ChallengeStore.ts"],"names":[],"mappings":";AAQA,MAAM,CAAC,OAAO,OAAO,cAAc;;IAMzB,GAAG,CAAC,IAAI,EAAE,MAAM;IAIhB,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;IAIhC,MAAM,CAAC,IAAI,EAAE,MAAM;CAG5B"}
|