@push.rocks/smartproxy 4.2.4 → 4.3.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.
@@ -1,22 +1,49 @@
1
1
  import * as plugins from './plugins.js';
2
+ import { IncomingMessage, ServerResponse } from 'http';
2
3
  /**
3
- * Events emitted by the ACME Certificate Manager
4
+ * Custom error classes for better error handling
4
5
  */
5
- export var CertManagerEvents;
6
- (function (CertManagerEvents) {
7
- CertManagerEvents["CERTIFICATE_ISSUED"] = "certificate-issued";
8
- CertManagerEvents["CERTIFICATE_RENEWED"] = "certificate-renewed";
9
- CertManagerEvents["CERTIFICATE_FAILED"] = "certificate-failed";
10
- CertManagerEvents["CERTIFICATE_EXPIRING"] = "certificate-expiring";
11
- CertManagerEvents["MANAGER_STARTED"] = "manager-started";
12
- CertManagerEvents["MANAGER_STOPPED"] = "manager-stopped";
13
- })(CertManagerEvents || (CertManagerEvents = {}));
6
+ export class Port80HandlerError extends Error {
7
+ constructor(message) {
8
+ super(message);
9
+ this.name = 'Port80HandlerError';
10
+ }
11
+ }
12
+ export class CertificateError extends Port80HandlerError {
13
+ constructor(message, domain, isRenewal = false) {
14
+ super(`${message} for domain ${domain}${isRenewal ? ' (renewal)' : ''}`);
15
+ this.domain = domain;
16
+ this.isRenewal = isRenewal;
17
+ this.name = 'CertificateError';
18
+ }
19
+ }
20
+ export class ServerError extends Port80HandlerError {
21
+ constructor(message, code) {
22
+ super(message);
23
+ this.code = code;
24
+ this.name = 'ServerError';
25
+ }
26
+ }
27
+ /**
28
+ * Events emitted by the Port80Handler
29
+ */
30
+ export var Port80HandlerEvents;
31
+ (function (Port80HandlerEvents) {
32
+ Port80HandlerEvents["CERTIFICATE_ISSUED"] = "certificate-issued";
33
+ Port80HandlerEvents["CERTIFICATE_RENEWED"] = "certificate-renewed";
34
+ Port80HandlerEvents["CERTIFICATE_FAILED"] = "certificate-failed";
35
+ Port80HandlerEvents["CERTIFICATE_EXPIRING"] = "certificate-expiring";
36
+ Port80HandlerEvents["MANAGER_STARTED"] = "manager-started";
37
+ Port80HandlerEvents["MANAGER_STOPPED"] = "manager-stopped";
38
+ Port80HandlerEvents["REQUEST_FORWARDED"] = "request-forwarded";
39
+ })(Port80HandlerEvents || (Port80HandlerEvents = {}));
14
40
  /**
15
- * Improved ACME Certificate Manager with event emission and external certificate management
41
+ * Port80Handler with ACME certificate management and request forwarding capabilities
42
+ * Now with glob pattern support for domain matching
16
43
  */
17
- export class AcmeCertManager extends plugins.EventEmitter {
44
+ export class Port80Handler extends plugins.EventEmitter {
18
45
  /**
19
- * Creates a new ACME Certificate Manager
46
+ * Creates a new Port80Handler
20
47
  * @param options Configuration options
21
48
  */
22
49
  constructor(options = {}) {
@@ -32,7 +59,7 @@ export class AcmeCertManager extends plugins.EventEmitter {
32
59
  port: options.port ?? 80,
33
60
  contactEmail: options.contactEmail ?? 'admin@example.com',
34
61
  useProduction: options.useProduction ?? false, // Safer default: staging
35
- renewThresholdDays: options.renewThresholdDays ?? 30,
62
+ renewThresholdDays: options.renewThresholdDays ?? 10, // Changed to 10 days as per requirements
36
63
  httpsRedirectPort: options.httpsRedirectPort ?? 443,
37
64
  renewCheckIntervalHours: options.renewCheckIntervalHours ?? 24,
38
65
  };
@@ -42,34 +69,48 @@ export class AcmeCertManager extends plugins.EventEmitter {
42
69
  */
43
70
  async start() {
44
71
  if (this.server) {
45
- throw new Error('Server is already running');
72
+ throw new ServerError('Server is already running');
46
73
  }
47
74
  if (this.isShuttingDown) {
48
- throw new Error('Server is shutting down');
75
+ throw new ServerError('Server is shutting down');
49
76
  }
50
77
  return new Promise((resolve, reject) => {
51
78
  try {
52
79
  this.server = plugins.http.createServer((req, res) => this.handleRequest(req, res));
53
80
  this.server.on('error', (error) => {
54
81
  if (error.code === 'EACCES') {
55
- reject(new Error(`Permission denied to bind to port ${this.options.port}. Try running with elevated privileges or use a port > 1024.`));
82
+ reject(new ServerError(`Permission denied to bind to port ${this.options.port}. Try running with elevated privileges or use a port > 1024.`, error.code));
56
83
  }
57
84
  else if (error.code === 'EADDRINUSE') {
58
- reject(new Error(`Port ${this.options.port} is already in use.`));
85
+ reject(new ServerError(`Port ${this.options.port} is already in use.`, error.code));
59
86
  }
60
87
  else {
61
- reject(error);
88
+ reject(new ServerError(error.message, error.code));
62
89
  }
63
90
  });
64
91
  this.server.listen(this.options.port, () => {
65
- console.log(`AcmeCertManager is listening on port ${this.options.port}`);
92
+ console.log(`Port80Handler is listening on port ${this.options.port}`);
66
93
  this.startRenewalTimer();
67
- this.emit(CertManagerEvents.MANAGER_STARTED, this.options.port);
94
+ this.emit(Port80HandlerEvents.MANAGER_STARTED, this.options.port);
95
+ // Start certificate process for domains with acmeMaintenance enabled
96
+ for (const [domain, domainInfo] of this.domainCertificates.entries()) {
97
+ // Skip glob patterns for certificate issuance
98
+ if (this.isGlobPattern(domain)) {
99
+ console.log(`Skipping initial certificate for glob pattern: ${domain}`);
100
+ continue;
101
+ }
102
+ if (domainInfo.options.acmeMaintenance && !domainInfo.certObtained && !domainInfo.obtainingInProgress) {
103
+ this.obtainCertificate(domain).catch(err => {
104
+ console.error(`Error obtaining initial certificate for ${domain}:`, err);
105
+ });
106
+ }
107
+ }
68
108
  resolve();
69
109
  });
70
110
  }
71
111
  catch (error) {
72
- reject(error);
112
+ const message = error instanceof Error ? error.message : 'Unknown error starting server';
113
+ reject(new ServerError(message));
73
114
  }
74
115
  });
75
116
  }
@@ -91,7 +132,7 @@ export class AcmeCertManager extends plugins.EventEmitter {
91
132
  this.server.close(() => {
92
133
  this.server = null;
93
134
  this.isShuttingDown = false;
94
- this.emit(CertManagerEvents.MANAGER_STOPPED);
135
+ this.emit(Port80HandlerEvents.MANAGER_STOPPED);
95
136
  resolve();
96
137
  });
97
138
  }
@@ -102,13 +143,38 @@ export class AcmeCertManager extends plugins.EventEmitter {
102
143
  });
103
144
  }
104
145
  /**
105
- * Adds a domain to be managed for certificates
106
- * @param domain The domain to add
146
+ * Adds a domain with configuration options
147
+ * @param options Domain configuration options
107
148
  */
108
- addDomain(domain) {
109
- if (!this.domainCertificates.has(domain)) {
110
- this.domainCertificates.set(domain, { certObtained: false, obtainingInProgress: false });
111
- console.log(`Domain added: ${domain}`);
149
+ addDomain(options) {
150
+ if (!options.domainName || typeof options.domainName !== 'string') {
151
+ throw new Port80HandlerError('Invalid domain name');
152
+ }
153
+ const domainName = options.domainName;
154
+ if (!this.domainCertificates.has(domainName)) {
155
+ this.domainCertificates.set(domainName, {
156
+ options,
157
+ certObtained: false,
158
+ obtainingInProgress: false
159
+ });
160
+ console.log(`Domain added: ${domainName} with configuration:`, {
161
+ sslRedirect: options.sslRedirect,
162
+ acmeMaintenance: options.acmeMaintenance,
163
+ hasForward: !!options.forward,
164
+ hasAcmeForward: !!options.acmeForward
165
+ });
166
+ // If acmeMaintenance is enabled and not a glob pattern, start certificate process immediately
167
+ if (options.acmeMaintenance && this.server && !this.isGlobPattern(domainName)) {
168
+ this.obtainCertificate(domainName).catch(err => {
169
+ console.error(`Error obtaining initial certificate for ${domainName}:`, err);
170
+ });
171
+ }
172
+ }
173
+ else {
174
+ // Update existing domain with new options
175
+ const existing = this.domainCertificates.get(domainName);
176
+ existing.options = options;
177
+ console.log(`Domain ${domainName} configuration updated`);
112
178
  }
113
179
  }
114
180
  /**
@@ -128,9 +194,26 @@ export class AcmeCertManager extends plugins.EventEmitter {
128
194
  * @param expiryDate Optional expiry date
129
195
  */
130
196
  setCertificate(domain, certificate, privateKey, expiryDate) {
197
+ if (!domain || !certificate || !privateKey) {
198
+ throw new Port80HandlerError('Domain, certificate and privateKey are required');
199
+ }
200
+ // Don't allow setting certificates for glob patterns
201
+ if (this.isGlobPattern(domain)) {
202
+ throw new Port80HandlerError('Cannot set certificate for glob pattern domains');
203
+ }
131
204
  let domainInfo = this.domainCertificates.get(domain);
132
205
  if (!domainInfo) {
133
- domainInfo = { certObtained: false, obtainingInProgress: false };
206
+ // Create default domain options if not already configured
207
+ const defaultOptions = {
208
+ domainName: domain,
209
+ sslRedirect: true,
210
+ acmeMaintenance: true
211
+ };
212
+ domainInfo = {
213
+ options: defaultOptions,
214
+ certObtained: false,
215
+ obtainingInProgress: false
216
+ };
134
217
  this.domainCertificates.set(domain, domainInfo);
135
218
  }
136
219
  domainInfo.certificate = certificate;
@@ -141,26 +224,16 @@ export class AcmeCertManager extends plugins.EventEmitter {
141
224
  domainInfo.expiryDate = expiryDate;
142
225
  }
143
226
  else {
144
- // Try to extract expiry date from certificate
145
- try {
146
- // This is a simplistic approach - in a real implementation, use a proper
147
- // certificate parsing library like node-forge or x509
148
- const matches = certificate.match(/Not After\s*:\s*(.*?)(?:\n|$)/i);
149
- if (matches && matches[1]) {
150
- domainInfo.expiryDate = new Date(matches[1]);
151
- }
152
- }
153
- catch (error) {
154
- console.warn(`Failed to extract expiry date from certificate for ${domain}`);
155
- }
227
+ // Extract expiry date from certificate
228
+ domainInfo.expiryDate = this.extractExpiryDateFromCertificate(certificate, domain);
156
229
  }
157
230
  console.log(`Certificate set for ${domain}`);
158
231
  // Emit certificate event
159
- this.emitCertificateEvent(CertManagerEvents.CERTIFICATE_ISSUED, {
232
+ this.emitCertificateEvent(Port80HandlerEvents.CERTIFICATE_ISSUED, {
160
233
  domain,
161
234
  certificate,
162
235
  privateKey,
163
- expiryDate: domainInfo.expiryDate || new Date(Date.now() + 90 * 24 * 60 * 60 * 1000) // 90 days default
236
+ expiryDate: domainInfo.expiryDate || this.getDefaultExpiryDate()
164
237
  });
165
238
  }
166
239
  /**
@@ -168,6 +241,10 @@ export class AcmeCertManager extends plugins.EventEmitter {
168
241
  * @param domain The domain to get the certificate for
169
242
  */
170
243
  getCertificate(domain) {
244
+ // Can't get certificates for glob patterns
245
+ if (this.isGlobPattern(domain)) {
246
+ return null;
247
+ }
171
248
  const domainInfo = this.domainCertificates.get(domain);
172
249
  if (!domainInfo || !domainInfo.certObtained || !domainInfo.certificate || !domainInfo.privateKey) {
173
250
  return null;
@@ -176,9 +253,66 @@ export class AcmeCertManager extends plugins.EventEmitter {
176
253
  domain,
177
254
  certificate: domainInfo.certificate,
178
255
  privateKey: domainInfo.privateKey,
179
- expiryDate: domainInfo.expiryDate || new Date(Date.now() + 90 * 24 * 60 * 60 * 1000) // 90 days default
256
+ expiryDate: domainInfo.expiryDate || this.getDefaultExpiryDate()
180
257
  };
181
258
  }
259
+ /**
260
+ * Check if a domain is a glob pattern
261
+ * @param domain Domain to check
262
+ * @returns True if the domain is a glob pattern
263
+ */
264
+ isGlobPattern(domain) {
265
+ return domain.includes('*');
266
+ }
267
+ /**
268
+ * Get domain info for a specific domain, using glob pattern matching if needed
269
+ * @param requestDomain The actual domain from the request
270
+ * @returns The domain info or null if not found
271
+ */
272
+ getDomainInfoForRequest(requestDomain) {
273
+ // Try direct match first
274
+ if (this.domainCertificates.has(requestDomain)) {
275
+ return {
276
+ domainInfo: this.domainCertificates.get(requestDomain),
277
+ pattern: requestDomain
278
+ };
279
+ }
280
+ // Then try glob patterns
281
+ for (const [pattern, domainInfo] of this.domainCertificates.entries()) {
282
+ if (this.isGlobPattern(pattern) && this.domainMatchesPattern(requestDomain, pattern)) {
283
+ return { domainInfo, pattern };
284
+ }
285
+ }
286
+ return null;
287
+ }
288
+ /**
289
+ * Check if a domain matches a glob pattern
290
+ * @param domain The domain to check
291
+ * @param pattern The pattern to match against
292
+ * @returns True if the domain matches the pattern
293
+ */
294
+ domainMatchesPattern(domain, pattern) {
295
+ // Handle different glob pattern styles
296
+ if (pattern.startsWith('*.')) {
297
+ // *.example.com matches any subdomain
298
+ const suffix = pattern.substring(2);
299
+ return domain.endsWith(suffix) && domain.includes('.') && domain !== suffix;
300
+ }
301
+ else if (pattern.endsWith('.*')) {
302
+ // example.* matches any TLD
303
+ const prefix = pattern.substring(0, pattern.length - 2);
304
+ const domainParts = domain.split('.');
305
+ return domain.startsWith(prefix + '.') && domainParts.length >= 2;
306
+ }
307
+ else if (pattern === '*') {
308
+ // Wildcard matches everything
309
+ return true;
310
+ }
311
+ else {
312
+ // Exact match (shouldn't reach here as we check exact matches first)
313
+ return domain === pattern;
314
+ }
315
+ }
182
316
  /**
183
317
  * Lazy initialization of the ACME client
184
318
  * @returns An ACME client instance
@@ -187,20 +321,26 @@ export class AcmeCertManager extends plugins.EventEmitter {
187
321
  if (this.acmeClient) {
188
322
  return this.acmeClient;
189
323
  }
190
- // Generate a new account key
191
- this.accountKey = (await plugins.acme.forge.createPrivateKey()).toString();
192
- this.acmeClient = new plugins.acme.Client({
193
- directoryUrl: this.options.useProduction
194
- ? plugins.acme.directory.letsencrypt.production
195
- : plugins.acme.directory.letsencrypt.staging,
196
- accountKey: this.accountKey,
197
- });
198
- // Create a new account
199
- await this.acmeClient.createAccount({
200
- termsOfServiceAgreed: true,
201
- contact: [`mailto:${this.options.contactEmail}`],
202
- });
203
- return this.acmeClient;
324
+ try {
325
+ // Generate a new account key
326
+ this.accountKey = (await plugins.acme.forge.createPrivateKey()).toString();
327
+ this.acmeClient = new plugins.acme.Client({
328
+ directoryUrl: this.options.useProduction
329
+ ? plugins.acme.directory.letsencrypt.production
330
+ : plugins.acme.directory.letsencrypt.staging,
331
+ accountKey: this.accountKey,
332
+ });
333
+ // Create a new account
334
+ await this.acmeClient.createAccount({
335
+ termsOfServiceAgreed: true,
336
+ contact: [`mailto:${this.options.contactEmail}`],
337
+ });
338
+ return this.acmeClient;
339
+ }
340
+ catch (error) {
341
+ const message = error instanceof Error ? error.message : 'Unknown error initializing ACME client';
342
+ throw new Port80HandlerError(`Failed to initialize ACME client: ${message}`);
343
+ }
204
344
  }
205
345
  /**
206
346
  * Handles incoming HTTP requests
@@ -216,36 +356,117 @@ export class AcmeCertManager extends plugins.EventEmitter {
216
356
  }
217
357
  // Extract domain (ignoring any port in the Host header)
218
358
  const domain = hostHeader.split(':')[0];
219
- // If the request is for an ACME HTTP-01 challenge, handle it
220
- if (req.url && req.url.startsWith('/.well-known/acme-challenge/')) {
221
- this.handleAcmeChallenge(req, res, domain);
222
- return;
223
- }
224
- if (!this.domainCertificates.has(domain)) {
359
+ // Get domain config, using glob pattern matching if needed
360
+ const domainMatch = this.getDomainInfoForRequest(domain);
361
+ if (!domainMatch) {
225
362
  res.statusCode = 404;
226
363
  res.end('Domain not configured');
227
364
  return;
228
365
  }
229
- const domainInfo = this.domainCertificates.get(domain);
230
- // If certificate exists, redirect to HTTPS
231
- if (domainInfo.certObtained) {
366
+ const { domainInfo, pattern } = domainMatch;
367
+ const options = domainInfo.options;
368
+ // If the request is for an ACME HTTP-01 challenge, handle it
369
+ if (req.url && req.url.startsWith('/.well-known/acme-challenge/') && (options.acmeMaintenance || options.acmeForward)) {
370
+ // Check if we should forward ACME requests
371
+ if (options.acmeForward) {
372
+ this.forwardRequest(req, res, options.acmeForward, 'ACME challenge');
373
+ return;
374
+ }
375
+ // Only handle ACME challenges for non-glob patterns
376
+ if (!this.isGlobPattern(pattern)) {
377
+ this.handleAcmeChallenge(req, res, domain);
378
+ return;
379
+ }
380
+ }
381
+ // Check if we should forward non-ACME requests
382
+ if (options.forward) {
383
+ this.forwardRequest(req, res, options.forward, 'HTTP');
384
+ return;
385
+ }
386
+ // If certificate exists and sslRedirect is enabled, redirect to HTTPS
387
+ // (Skip for glob patterns as they won't have certificates)
388
+ if (!this.isGlobPattern(pattern) && domainInfo.certObtained && options.sslRedirect) {
232
389
  const httpsPort = this.options.httpsRedirectPort;
233
390
  const portSuffix = httpsPort === 443 ? '' : `:${httpsPort}`;
234
391
  const redirectUrl = `https://${domain}${portSuffix}${req.url || '/'}`;
235
392
  res.statusCode = 301;
236
393
  res.setHeader('Location', redirectUrl);
237
394
  res.end(`Redirecting to ${redirectUrl}`);
395
+ return;
238
396
  }
239
- else {
397
+ // Handle case where certificate maintenance is enabled but not yet obtained
398
+ // (Skip for glob patterns as they can't have certificates)
399
+ if (!this.isGlobPattern(pattern) && options.acmeMaintenance && !domainInfo.certObtained) {
240
400
  // Trigger certificate issuance if not already running
241
401
  if (!domainInfo.obtainingInProgress) {
242
402
  this.obtainCertificate(domain).catch(err => {
243
- this.emit(CertManagerEvents.CERTIFICATE_FAILED, { domain, error: err.message });
403
+ const errorMessage = err instanceof Error ? err.message : 'Unknown error';
404
+ this.emit(Port80HandlerEvents.CERTIFICATE_FAILED, {
405
+ domain,
406
+ error: errorMessage,
407
+ isRenewal: false
408
+ });
244
409
  console.error(`Error obtaining certificate for ${domain}:`, err);
245
410
  });
246
411
  }
247
412
  res.statusCode = 503;
248
413
  res.end('Certificate issuance in progress, please try again later.');
414
+ return;
415
+ }
416
+ // Default response for unhandled request
417
+ res.statusCode = 404;
418
+ res.end('No handlers configured for this request');
419
+ }
420
+ /**
421
+ * Forwards an HTTP request to the specified target
422
+ * @param req The original request
423
+ * @param res The response object
424
+ * @param target The forwarding target (IP and port)
425
+ * @param requestType Type of request for logging
426
+ */
427
+ forwardRequest(req, res, target, requestType) {
428
+ const options = {
429
+ hostname: target.ip,
430
+ port: target.port,
431
+ path: req.url,
432
+ method: req.method,
433
+ headers: { ...req.headers }
434
+ };
435
+ const domain = req.headers.host?.split(':')[0] || 'unknown';
436
+ console.log(`Forwarding ${requestType} request for ${domain} to ${target.ip}:${target.port}`);
437
+ const proxyReq = plugins.http.request(options, (proxyRes) => {
438
+ // Copy status code
439
+ res.statusCode = proxyRes.statusCode || 500;
440
+ // Copy headers
441
+ for (const [key, value] of Object.entries(proxyRes.headers)) {
442
+ if (value)
443
+ res.setHeader(key, value);
444
+ }
445
+ // Pipe response data
446
+ proxyRes.pipe(res);
447
+ this.emit(Port80HandlerEvents.REQUEST_FORWARDED, {
448
+ domain,
449
+ requestType,
450
+ target: `${target.ip}:${target.port}`,
451
+ statusCode: proxyRes.statusCode
452
+ });
453
+ });
454
+ proxyReq.on('error', (error) => {
455
+ console.error(`Error forwarding request to ${target.ip}:${target.port}:`, error);
456
+ if (!res.headersSent) {
457
+ res.statusCode = 502;
458
+ res.end(`Proxy error: ${error.message}`);
459
+ }
460
+ else {
461
+ res.end();
462
+ }
463
+ });
464
+ // Pipe original request to proxy request
465
+ if (req.readable) {
466
+ req.pipe(proxyReq);
467
+ }
468
+ else {
469
+ proxyReq.end();
249
470
  }
250
471
  }
251
472
  /**
@@ -281,10 +502,19 @@ export class AcmeCertManager extends plugins.EventEmitter {
281
502
  * @param isRenewal Whether this is a renewal attempt
282
503
  */
283
504
  async obtainCertificate(domain, isRenewal = false) {
505
+ // Don't allow certificate issuance for glob patterns
506
+ if (this.isGlobPattern(domain)) {
507
+ throw new CertificateError('Cannot obtain certificates for glob pattern domains', domain, isRenewal);
508
+ }
284
509
  // Get the domain info
285
510
  const domainInfo = this.domainCertificates.get(domain);
286
511
  if (!domainInfo) {
287
- throw new Error(`Domain not found: ${domain}`);
512
+ throw new CertificateError('Domain not found', domain, isRenewal);
513
+ }
514
+ // Verify that acmeMaintenance is enabled
515
+ if (!domainInfo.options.acmeMaintenance) {
516
+ console.log(`Skipping certificate issuance for ${domain} - acmeMaintenance is disabled`);
517
+ return;
288
518
  }
289
519
  // Prevent concurrent certificate issuance
290
520
  if (domainInfo.obtainingInProgress) {
@@ -301,35 +531,8 @@ export class AcmeCertManager extends plugins.EventEmitter {
301
531
  });
302
532
  // Get the authorizations for the order
303
533
  const authorizations = await client.getAuthorizations(order);
304
- for (const authz of authorizations) {
305
- const challenge = authz.challenges.find(ch => ch.type === 'http-01');
306
- if (!challenge) {
307
- throw new Error('HTTP-01 challenge not found');
308
- }
309
- // Get the key authorization for the challenge
310
- const keyAuthorization = await client.getChallengeKeyAuthorization(challenge);
311
- // Store the challenge data
312
- domainInfo.challengeToken = challenge.token;
313
- domainInfo.challengeKeyAuthorization = keyAuthorization;
314
- // ACME client type definition workaround - use compatible approach
315
- // First check if challenge verification is needed
316
- const authzUrl = authz.url;
317
- try {
318
- // Check if authzUrl exists and perform verification
319
- if (authzUrl) {
320
- await client.verifyChallenge(authz, challenge);
321
- }
322
- // Complete the challenge
323
- await client.completeChallenge(challenge);
324
- // Wait for validation
325
- await client.waitForValidStatus(challenge);
326
- console.log(`HTTP-01 challenge completed for ${domain}`);
327
- }
328
- catch (error) {
329
- console.error(`Challenge error for ${domain}:`, error);
330
- throw error;
331
- }
332
- }
534
+ // Process each authorization
535
+ await this.processAuthorizations(client, domain, authorizations);
333
536
  // Generate a CSR and private key
334
537
  const [csrBuffer, privateKeyBuffer] = await plugins.acme.forge.createCsr({
335
538
  commonName: domain,
@@ -348,26 +551,17 @@ export class AcmeCertManager extends plugins.EventEmitter {
348
551
  delete domainInfo.challengeToken;
349
552
  delete domainInfo.challengeKeyAuthorization;
350
553
  // Extract expiry date from certificate
351
- try {
352
- const matches = certificate.match(/Not After\s*:\s*(.*?)(?:\n|$)/i);
353
- if (matches && matches[1]) {
354
- domainInfo.expiryDate = new Date(matches[1]);
355
- console.log(`Certificate for ${domain} will expire on ${domainInfo.expiryDate.toISOString()}`);
356
- }
357
- }
358
- catch (error) {
359
- console.warn(`Failed to extract expiry date from certificate for ${domain}`);
360
- }
554
+ domainInfo.expiryDate = this.extractExpiryDateFromCertificate(certificate, domain);
361
555
  console.log(`Certificate ${isRenewal ? 'renewed' : 'obtained'} for ${domain}`);
362
556
  // Emit the appropriate event
363
557
  const eventType = isRenewal
364
- ? CertManagerEvents.CERTIFICATE_RENEWED
365
- : CertManagerEvents.CERTIFICATE_ISSUED;
558
+ ? Port80HandlerEvents.CERTIFICATE_RENEWED
559
+ : Port80HandlerEvents.CERTIFICATE_ISSUED;
366
560
  this.emitCertificateEvent(eventType, {
367
561
  domain,
368
562
  certificate,
369
563
  privateKey,
370
- expiryDate: domainInfo.expiryDate || new Date(Date.now() + 90 * 24 * 60 * 60 * 1000) // 90 days default
564
+ expiryDate: domainInfo.expiryDate || this.getDefaultExpiryDate()
371
565
  });
372
566
  }
373
567
  catch (error) {
@@ -381,17 +575,60 @@ export class AcmeCertManager extends plugins.EventEmitter {
381
575
  console.error(`Error during certificate issuance for ${domain}:`, error);
382
576
  }
383
577
  // Emit failure event
384
- this.emit(CertManagerEvents.CERTIFICATE_FAILED, {
578
+ this.emit(Port80HandlerEvents.CERTIFICATE_FAILED, {
385
579
  domain,
386
580
  error: error.message || 'Unknown error',
387
581
  isRenewal
388
582
  });
583
+ throw new CertificateError(error.message || 'Certificate issuance failed', domain, isRenewal);
389
584
  }
390
585
  finally {
391
586
  // Reset flag whether successful or not
392
587
  domainInfo.obtainingInProgress = false;
393
588
  }
394
589
  }
590
+ /**
591
+ * Process ACME authorizations by verifying and completing challenges
592
+ * @param client ACME client
593
+ * @param domain Domain name
594
+ * @param authorizations Authorizations to process
595
+ */
596
+ async processAuthorizations(client, domain, authorizations) {
597
+ const domainInfo = this.domainCertificates.get(domain);
598
+ if (!domainInfo) {
599
+ throw new CertificateError('Domain not found during authorization', domain);
600
+ }
601
+ for (const authz of authorizations) {
602
+ const challenge = authz.challenges.find(ch => ch.type === 'http-01');
603
+ if (!challenge) {
604
+ throw new CertificateError('HTTP-01 challenge not found', domain);
605
+ }
606
+ // Get the key authorization for the challenge
607
+ const keyAuthorization = await client.getChallengeKeyAuthorization(challenge);
608
+ // Store the challenge data
609
+ domainInfo.challengeToken = challenge.token;
610
+ domainInfo.challengeKeyAuthorization = keyAuthorization;
611
+ // ACME client type definition workaround - use compatible approach
612
+ // First check if challenge verification is needed
613
+ const authzUrl = authz.url;
614
+ try {
615
+ // Check if authzUrl exists and perform verification
616
+ if (authzUrl) {
617
+ await client.verifyChallenge(authz, challenge);
618
+ }
619
+ // Complete the challenge
620
+ await client.completeChallenge(challenge);
621
+ // Wait for validation
622
+ await client.waitForValidStatus(challenge);
623
+ console.log(`HTTP-01 challenge completed for ${domain}`);
624
+ }
625
+ catch (error) {
626
+ const errorMessage = error instanceof Error ? error.message : 'Unknown challenge error';
627
+ console.error(`Challenge error for ${domain}:`, error);
628
+ throw new CertificateError(`Challenge verification failed: ${errorMessage}`, domain);
629
+ }
630
+ }
631
+ }
395
632
  /**
396
633
  * Starts the certificate renewal timer
397
634
  */
@@ -419,6 +656,14 @@ export class AcmeCertManager extends plugins.EventEmitter {
419
656
  const now = new Date();
420
657
  const renewThresholdMs = this.options.renewThresholdDays * 24 * 60 * 60 * 1000;
421
658
  for (const [domain, domainInfo] of this.domainCertificates.entries()) {
659
+ // Skip glob patterns
660
+ if (this.isGlobPattern(domain)) {
661
+ continue;
662
+ }
663
+ // Skip domains with acmeMaintenance disabled
664
+ if (!domainInfo.options.acmeMaintenance) {
665
+ continue;
666
+ }
422
667
  // Skip domains without certificates or already in renewal
423
668
  if (!domainInfo.certObtained || domainInfo.obtainingInProgress) {
424
669
  continue;
@@ -431,18 +676,54 @@ export class AcmeCertManager extends plugins.EventEmitter {
431
676
  // Check if certificate is near expiry
432
677
  if (timeUntilExpiry <= renewThresholdMs) {
433
678
  console.log(`Certificate for ${domain} expires soon, renewing...`);
434
- this.emit(CertManagerEvents.CERTIFICATE_EXPIRING, {
679
+ const daysRemaining = Math.ceil(timeUntilExpiry / (24 * 60 * 60 * 1000));
680
+ this.emit(Port80HandlerEvents.CERTIFICATE_EXPIRING, {
435
681
  domain,
436
682
  expiryDate: domainInfo.expiryDate,
437
- daysRemaining: Math.ceil(timeUntilExpiry / (24 * 60 * 60 * 1000))
683
+ daysRemaining
438
684
  });
439
685
  // Start renewal process
440
686
  this.obtainCertificate(domain, true).catch(err => {
441
- console.error(`Error renewing certificate for ${domain}:`, err);
687
+ const errorMessage = err instanceof Error ? err.message : 'Unknown error';
688
+ console.error(`Error renewing certificate for ${domain}:`, errorMessage);
442
689
  });
443
690
  }
444
691
  }
445
692
  }
693
+ /**
694
+ * Extract expiry date from certificate using a more robust approach
695
+ * @param certificate Certificate PEM string
696
+ * @param domain Domain for logging
697
+ * @returns Extracted expiry date or default
698
+ */
699
+ extractExpiryDateFromCertificate(certificate, domain) {
700
+ try {
701
+ // This is still using regex, but in a real implementation you would use
702
+ // a library like node-forge or x509 to properly parse the certificate
703
+ const matches = certificate.match(/Not After\s*:\s*(.*?)(?:\n|$)/i);
704
+ if (matches && matches[1]) {
705
+ const expiryDate = new Date(matches[1]);
706
+ // Validate that we got a valid date
707
+ if (!isNaN(expiryDate.getTime())) {
708
+ console.log(`Certificate for ${domain} will expire on ${expiryDate.toISOString()}`);
709
+ return expiryDate;
710
+ }
711
+ }
712
+ console.warn(`Could not extract valid expiry date from certificate for ${domain}, using default`);
713
+ return this.getDefaultExpiryDate();
714
+ }
715
+ catch (error) {
716
+ console.warn(`Failed to extract expiry date from certificate for ${domain}, using default`);
717
+ return this.getDefaultExpiryDate();
718
+ }
719
+ }
720
+ /**
721
+ * Get a default expiry date (90 days from now)
722
+ * @returns Default expiry date
723
+ */
724
+ getDefaultExpiryDate() {
725
+ return new Date(Date.now() + 90 * 24 * 60 * 60 * 1000); // 90 days default
726
+ }
446
727
  /**
447
728
  * Emits a certificate event with the certificate data
448
729
  * @param eventType The event type to emit
@@ -452,4 +733,4 @@ export class AcmeCertManager extends plugins.EventEmitter {
452
733
  this.emit(eventType, data);
453
734
  }
454
735
  }
455
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5wb3J0ODBoYW5kbGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvY2xhc3Nlcy5wb3J0ODBoYW5kbGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sY0FBYyxDQUFDO0FBc0N4Qzs7R0FFRztBQUNILE1BQU0sQ0FBTixJQUFZLGlCQU9YO0FBUEQsV0FBWSxpQkFBaUI7SUFDM0IsOERBQXlDLENBQUE7SUFDekMsZ0VBQTJDLENBQUE7SUFDM0MsOERBQXlDLENBQUE7SUFDekMsa0VBQTZDLENBQUE7SUFDN0Msd0RBQW1DLENBQUE7SUFDbkMsd0RBQW1DLENBQUE7QUFDckMsQ0FBQyxFQVBXLGlCQUFpQixLQUFqQixpQkFBaUIsUUFPNUI7QUFFRDs7R0FFRztBQUNILE1BQU0sT0FBTyxlQUFnQixTQUFRLE9BQU8sQ0FBQyxZQUFZO0lBU3ZEOzs7T0FHRztJQUNILFlBQVksVUFBbUMsRUFBRTtRQUMvQyxLQUFLLEVBQUUsQ0FBQztRQVpGLFdBQU0sR0FBK0IsSUFBSSxDQUFDO1FBQzFDLGVBQVUsR0FBK0IsSUFBSSxDQUFDO1FBQzlDLGVBQVUsR0FBa0IsSUFBSSxDQUFDO1FBQ2pDLGlCQUFZLEdBQTBCLElBQUksQ0FBQztRQUMzQyxtQkFBYyxHQUFZLEtBQUssQ0FBQztRQVN0QyxJQUFJLENBQUMsa0JBQWtCLEdBQUcsSUFBSSxHQUFHLEVBQThCLENBQUM7UUFFaEUsa0JBQWtCO1FBQ2xCLElBQUksQ0FBQyxPQUFPLEdBQUc7WUFDYixJQUFJLEVBQUUsT0FBTyxDQUFDLElBQUksSUFBSSxFQUFFO1lBQ3hCLFlBQVksRUFBRSxPQUFPLENBQUMsWUFBWSxJQUFJLG1CQUFtQjtZQUN6RCxhQUFhLEVBQUUsT0FBTyxDQUFDLGFBQWEsSUFBSSxLQUFLLEVBQUUseUJBQXlCO1lBQ3hFLGtCQUFrQixFQUFFLE9BQU8sQ0FBQyxrQkFBa0IsSUFBSSxFQUFFO1lBQ3BELGlCQUFpQixFQUFF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
736
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5wb3J0ODBoYW5kbGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvY2xhc3Nlcy5wb3J0ODBoYW5kbGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sY0FBYyxDQUFDO0FBQ3hDLE9BQU8sRUFBRSxlQUFlLEVBQUUsY0FBYyxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBRXZEOztHQUVHO0FBQ0gsTUFBTSxPQUFPLGtCQUFtQixTQUFRLEtBQUs7SUFDM0MsWUFBWSxPQUFlO1FBQ3pCLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUNmLElBQUksQ0FBQyxJQUFJLEdBQUcsb0JBQW9CLENBQUM7SUFDbkMsQ0FBQztDQUNGO0FBRUQsTUFBTSxPQUFPLGdCQUFpQixTQUFRLGtCQUFrQjtJQUN0RCxZQUNFLE9BQWUsRUFDQyxNQUFjLEVBQ2QsWUFBcUIsS0FBSztRQUUxQyxLQUFLLENBQUMsR0FBRyxPQUFPLGVBQWUsTUFBTSxHQUFHLFNBQVMsQ0FBQyxDQUFDLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBSHpELFdBQU0sR0FBTixNQUFNLENBQVE7UUFDZCxjQUFTLEdBQVQsU0FBUyxDQUFpQjtRQUcxQyxJQUFJLENBQUMsSUFBSSxHQUFHLGtCQUFrQixDQUFDO0lBQ2pDLENBQUM7Q0FDRjtBQUVELE1BQU0sT0FBTyxXQUFZLFNBQVEsa0JBQWtCO0lBQ2pELFlBQVksT0FBZSxFQUFrQixJQUFhO1FBQ3hELEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUQ0QixTQUFJLEdBQUosSUFBSSxDQUFTO1FBRXhELElBQUksQ0FBQyxJQUFJLEdBQUcsYUFBYSxDQUFDO0lBQzVCLENBQUM7Q0FDRjtBQTBERDs7R0FFRztBQUNILE1BQU0sQ0FBTixJQUFZLG1CQVFYO0FBUkQsV0FBWSxtQkFBbUI7SUFDN0IsZ0VBQXlDLENBQUE7SUFDekMsa0VBQTJDLENB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