@push.rocks/smartproxy 18.1.0 → 19.0.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.
Files changed (98) hide show
  1. package/dist_ts/00_commitinfo_data.js +1 -1
  2. package/dist_ts/certificate/certificate-manager.d.ts +150 -0
  3. package/dist_ts/certificate/certificate-manager.js +505 -0
  4. package/dist_ts/certificate/events/simplified-events.d.ts +56 -0
  5. package/dist_ts/certificate/events/simplified-events.js +13 -0
  6. package/dist_ts/certificate/models/certificate-errors.d.ts +69 -0
  7. package/dist_ts/certificate/models/certificate-errors.js +141 -0
  8. package/dist_ts/certificate/models/certificate-strategy.d.ts +60 -0
  9. package/dist_ts/certificate/models/certificate-strategy.js +73 -0
  10. package/dist_ts/certificate/simplified-certificate-manager.d.ts +150 -0
  11. package/dist_ts/certificate/simplified-certificate-manager.js +501 -0
  12. package/dist_ts/common/eventUtils.d.ts +1 -2
  13. package/dist_ts/common/eventUtils.js +2 -1
  14. package/dist_ts/core/models/common-types.d.ts +1 -1
  15. package/dist_ts/core/models/common-types.js +1 -1
  16. package/dist_ts/core/utils/event-utils.d.ts +9 -9
  17. package/dist_ts/core/utils/event-utils.js +6 -14
  18. package/dist_ts/http/index.d.ts +1 -9
  19. package/dist_ts/http/index.js +5 -11
  20. package/dist_ts/http/models/http-types.d.ts +13 -1
  21. package/dist_ts/http/models/http-types.js +1 -1
  22. package/dist_ts/index.d.ts +4 -6
  23. package/dist_ts/index.js +4 -10
  24. package/dist_ts/plugins.d.ts +3 -1
  25. package/dist_ts/plugins.js +4 -2
  26. package/dist_ts/proxies/index.d.ts +3 -2
  27. package/dist_ts/proxies/index.js +4 -5
  28. package/dist_ts/proxies/network-proxy/certificate-manager.d.ts +31 -49
  29. package/dist_ts/proxies/network-proxy/certificate-manager.js +77 -374
  30. package/dist_ts/proxies/network-proxy/models/types.d.ts +12 -1
  31. package/dist_ts/proxies/network-proxy/models/types.js +1 -1
  32. package/dist_ts/proxies/network-proxy/network-proxy.d.ts +2 -7
  33. package/dist_ts/proxies/network-proxy/network-proxy.js +12 -19
  34. package/dist_ts/proxies/network-proxy/simplified-certificate-bridge.d.ts +48 -0
  35. package/dist_ts/proxies/network-proxy/simplified-certificate-bridge.js +76 -0
  36. package/dist_ts/proxies/network-proxy/websocket-handler.js +21 -7
  37. package/dist_ts/proxies/smart-proxy/cert-store.d.ts +10 -0
  38. package/dist_ts/proxies/smart-proxy/cert-store.js +70 -0
  39. package/dist_ts/proxies/smart-proxy/certificate-manager.d.ts +116 -0
  40. package/dist_ts/proxies/smart-proxy/certificate-manager.js +401 -0
  41. package/dist_ts/proxies/smart-proxy/legacy-smart-proxy.d.ts +168 -0
  42. package/dist_ts/proxies/smart-proxy/legacy-smart-proxy.js +642 -0
  43. package/dist_ts/proxies/smart-proxy/models/index.d.ts +1 -1
  44. package/dist_ts/proxies/smart-proxy/models/index.js +1 -5
  45. package/dist_ts/proxies/smart-proxy/models/interfaces.d.ts +13 -1
  46. package/dist_ts/proxies/smart-proxy/models/route-types.d.ts +26 -0
  47. package/dist_ts/proxies/smart-proxy/models/route-types.js +1 -1
  48. package/dist_ts/proxies/smart-proxy/models/simplified-smartproxy-config.d.ts +65 -0
  49. package/dist_ts/proxies/smart-proxy/models/simplified-smartproxy-config.js +31 -0
  50. package/dist_ts/proxies/smart-proxy/models/smartproxy-options.d.ts +102 -0
  51. package/dist_ts/proxies/smart-proxy/models/smartproxy-options.js +73 -0
  52. package/dist_ts/proxies/smart-proxy/network-proxy-bridge.d.ts +10 -44
  53. package/dist_ts/proxies/smart-proxy/network-proxy-bridge.js +66 -202
  54. package/dist_ts/proxies/smart-proxy/route-connection-handler.d.ts +4 -0
  55. package/dist_ts/proxies/smart-proxy/route-connection-handler.js +62 -2
  56. package/dist_ts/proxies/smart-proxy/simplified-smart-proxy.d.ts +41 -0
  57. package/dist_ts/proxies/smart-proxy/simplified-smart-proxy.js +132 -0
  58. package/dist_ts/proxies/smart-proxy/smart-proxy.d.ts +18 -13
  59. package/dist_ts/proxies/smart-proxy/smart-proxy.js +80 -198
  60. package/package.json +5 -3
  61. package/readme.md +13 -5
  62. package/readme.plan.md +1422 -617
  63. package/ts/00_commitinfo_data.ts +1 -1
  64. package/ts/common/eventUtils.ts +2 -2
  65. package/ts/core/models/common-types.ts +1 -1
  66. package/ts/core/utils/event-utils.ts +12 -21
  67. package/ts/http/index.ts +5 -12
  68. package/ts/http/models/http-types.ts +8 -4
  69. package/ts/index.ts +11 -14
  70. package/ts/plugins.ts +4 -1
  71. package/ts/proxies/index.ts +7 -4
  72. package/ts/proxies/network-proxy/certificate-manager.ts +92 -417
  73. package/ts/proxies/network-proxy/models/types.ts +14 -2
  74. package/ts/proxies/network-proxy/network-proxy.ts +13 -19
  75. package/ts/proxies/network-proxy/websocket-handler.ts +18 -6
  76. package/ts/proxies/smart-proxy/cert-store.ts +86 -0
  77. package/ts/proxies/smart-proxy/certificate-manager.ts +506 -0
  78. package/ts/proxies/smart-proxy/models/index.ts +2 -1
  79. package/ts/proxies/smart-proxy/models/interfaces.ts +14 -1
  80. package/ts/proxies/smart-proxy/models/route-types.ts +34 -4
  81. package/ts/proxies/smart-proxy/network-proxy-bridge.ts +86 -239
  82. package/ts/proxies/smart-proxy/route-connection-handler.ts +74 -1
  83. package/ts/proxies/smart-proxy/smart-proxy.ts +106 -224
  84. package/ts/certificate/acme/acme-factory.ts +0 -48
  85. package/ts/certificate/acme/challenge-handler.ts +0 -110
  86. package/ts/certificate/acme/index.ts +0 -3
  87. package/ts/certificate/events/certificate-events.ts +0 -36
  88. package/ts/certificate/index.ts +0 -75
  89. package/ts/certificate/models/certificate-types.ts +0 -109
  90. package/ts/certificate/providers/cert-provisioner.ts +0 -519
  91. package/ts/certificate/providers/index.ts +0 -3
  92. package/ts/certificate/storage/file-storage.ts +0 -234
  93. package/ts/certificate/storage/index.ts +0 -3
  94. package/ts/certificate/utils/certificate-helpers.ts +0 -50
  95. package/ts/http/port80/acme-interfaces.ts +0 -169
  96. package/ts/http/port80/challenge-responder.ts +0 -246
  97. package/ts/http/port80/index.ts +0 -13
  98. package/ts/http/port80/port80-handler.ts +0 -728
@@ -11,12 +11,8 @@ import { RouteManager } from './route-manager.js';
11
11
  import { RouteConnectionHandler } from './route-connection-handler.js';
12
12
  import { NFTablesManager } from './nftables-manager.js';
13
13
 
14
- // External dependencies
15
- import { Port80Handler } from '../../http/port80/port80-handler.js';
16
- import { CertProvisioner } from '../../certificate/providers/cert-provisioner.js';
17
- import type { ICertificateData } from '../../certificate/models/certificate-types.js';
18
- import { buildPort80Handler } from '../../certificate/acme/acme-factory.js';
19
- import { createPort80HandlerOptions } from '../../common/port80-adapter.js';
14
+ // Certificate manager
15
+ import { SmartCertManager, type ICertStatus } from './certificate-manager.js';
20
16
 
21
17
  // Import types and utilities
22
18
  import type {
@@ -53,10 +49,8 @@ export class SmartProxy extends plugins.EventEmitter {
53
49
  private routeConnectionHandler: RouteConnectionHandler;
54
50
  private nftablesManager: NFTablesManager;
55
51
 
56
- // Port80Handler for ACME certificate management
57
- private port80Handler: Port80Handler | null = null;
58
- // CertProvisioner for unified certificate workflows
59
- private certProvisioner?: CertProvisioner;
52
+ // Certificate manager for ACME and static certificates
53
+ private certManager: SmartCertManager | null = null;
60
54
 
61
55
  /**
62
56
  * Constructor for SmartProxy
@@ -127,13 +121,12 @@ export class SmartProxy extends plugins.EventEmitter {
127
121
  this.settings.acme = {
128
122
  enabled: false,
129
123
  port: 80,
130
- accountEmail: 'admin@example.com',
124
+ email: 'admin@example.com',
131
125
  useProduction: false,
132
126
  renewThresholdDays: 30,
133
127
  autoRenew: true,
134
128
  certificateStore: './certs',
135
129
  skipConfiguredCerts: false,
136
- httpsRedirectPort: 443,
137
130
  renewCheckIntervalHours: 24,
138
131
  routeForwards: []
139
132
  };
@@ -180,29 +173,53 @@ export class SmartProxy extends plugins.EventEmitter {
180
173
  public settings: ISmartProxyOptions;
181
174
 
182
175
  /**
183
- * Initialize the Port80Handler for ACME certificate management
176
+ * Initialize certificate manager
184
177
  */
185
- private async initializePort80Handler(): Promise<void> {
186
- const config = this.settings.acme!;
187
- if (!config.enabled) {
188
- console.log('ACME is disabled in configuration');
178
+ private async initializeCertificateManager(): Promise<void> {
179
+ // Extract global ACME options if any routes use auto certificates
180
+ const autoRoutes = this.settings.routes.filter(r =>
181
+ r.action.tls?.certificate === 'auto'
182
+ );
183
+
184
+ if (autoRoutes.length === 0 && !this.hasStaticCertRoutes()) {
185
+ console.log('No routes require certificate management');
189
186
  return;
190
187
  }
191
188
 
192
- try {
193
- // Build and start the Port80Handler
194
- this.port80Handler = buildPort80Handler({
195
- ...config,
196
- httpsRedirectPort: config.httpsRedirectPort || 443
197
- });
198
-
199
- // Share Port80Handler with NetworkProxyBridge before start
200
- this.networkProxyBridge.setPort80Handler(this.port80Handler);
201
- await this.port80Handler.start();
202
- console.log(`Port80Handler started on port ${config.port}`);
203
- } catch (err) {
204
- console.log(`Error initializing Port80Handler: ${err}`);
189
+ // Use the first auto route's ACME config as defaults
190
+ const defaultAcme = autoRoutes[0]?.action.tls?.acme;
191
+
192
+ this.certManager = new SmartCertManager(
193
+ this.settings.routes,
194
+ './certs', // Certificate directory
195
+ defaultAcme ? {
196
+ email: defaultAcme.email,
197
+ useProduction: defaultAcme.useProduction,
198
+ port: defaultAcme.challengePort || 80
199
+ } : undefined
200
+ );
201
+
202
+ // Connect with NetworkProxy
203
+ if (this.networkProxyBridge.getNetworkProxy()) {
204
+ this.certManager.setNetworkProxy(this.networkProxyBridge.getNetworkProxy());
205
205
  }
206
+
207
+ // Set route update callback for ACME challenges
208
+ this.certManager.setUpdateRoutesCallback(async (routes) => {
209
+ await this.updateRoutes(routes);
210
+ });
211
+
212
+ await this.certManager.initialize();
213
+ }
214
+
215
+ /**
216
+ * Check if we have routes with static certificates
217
+ */
218
+ private hasStaticCertRoutes(): boolean {
219
+ return this.settings.routes.some(r =>
220
+ r.action.tls?.certificate &&
221
+ r.action.tls.certificate !== 'auto'
222
+ );
206
223
  }
207
224
 
208
225
  /**
@@ -215,51 +232,18 @@ export class SmartProxy extends plugins.EventEmitter {
215
232
  return;
216
233
  }
217
234
 
218
- // Pure route-based configuration - no domain configs needed
219
-
220
- // Initialize Port80Handler if enabled
221
- await this.initializePort80Handler();
222
-
223
- // Initialize CertProvisioner for unified certificate workflows
224
- if (this.port80Handler) {
225
- const acme = this.settings.acme!;
226
-
227
- // Setup route forwards
228
- const routeForwards = acme.routeForwards?.map(f => f) || [];
229
-
230
- // Create CertProvisioner with appropriate parameters
231
- // No longer need to support multiple configuration types
232
- // Just pass the routes directly
233
- this.certProvisioner = new CertProvisioner(
234
- this.settings.routes,
235
- this.port80Handler,
236
- this.networkProxyBridge,
237
- this.settings.certProvisionFunction,
238
- acme.renewThresholdDays!,
239
- acme.renewCheckIntervalHours!,
240
- acme.autoRenew!,
241
- routeForwards
242
- );
243
-
244
- // Register certificate event handler
245
- this.certProvisioner.on('certificate', (certData) => {
246
- this.emit('certificate', {
247
- domain: certData.domain,
248
- publicKey: certData.certificate,
249
- privateKey: certData.privateKey,
250
- expiryDate: certData.expiryDate,
251
- source: certData.source,
252
- isRenewal: certData.isRenewal
253
- });
254
- });
255
-
256
- await this.certProvisioner.start();
257
- console.log('CertProvisioner started');
258
- }
235
+ // Initialize certificate manager before starting servers
236
+ await this.initializeCertificateManager();
259
237
 
260
238
  // Initialize and start NetworkProxy if needed
261
239
  if (this.settings.useNetworkProxy && this.settings.useNetworkProxy.length > 0) {
262
240
  await this.networkProxyBridge.initialize();
241
+
242
+ // Connect NetworkProxy with certificate manager
243
+ if (this.certManager) {
244
+ this.certManager.setNetworkProxy(this.networkProxyBridge.getNetworkProxy());
245
+ }
246
+
263
247
  await this.networkProxyBridge.start();
264
248
  }
265
249
 
@@ -371,27 +355,16 @@ export class SmartProxy extends plugins.EventEmitter {
371
355
  this.isShuttingDown = true;
372
356
  this.portManager.setShuttingDown(true);
373
357
 
374
- // Stop CertProvisioner if active
375
- if (this.certProvisioner) {
376
- await this.certProvisioner.stop();
377
- console.log('CertProvisioner stopped');
358
+ // Stop certificate manager
359
+ if (this.certManager) {
360
+ await this.certManager.stop();
361
+ console.log('Certificate manager stopped');
378
362
  }
379
363
 
380
364
  // Stop NFTablesManager
381
365
  await this.nftablesManager.stop();
382
366
  console.log('NFTablesManager stopped');
383
367
 
384
- // Stop the Port80Handler if running
385
- if (this.port80Handler) {
386
- try {
387
- await this.port80Handler.stop();
388
- console.log('Port80Handler stopped');
389
- this.port80Handler = null;
390
- } catch (err) {
391
- console.log(`Error stopping Port80Handler: ${err}`);
392
- }
393
- }
394
-
395
368
  // Stop the connection logger
396
369
  if (this.connectionLogger) {
397
370
  clearInterval(this.connectionLogger);
@@ -498,104 +471,60 @@ export class SmartProxy extends plugins.EventEmitter {
498
471
  await this.networkProxyBridge.syncRoutesToNetworkProxy(newRoutes);
499
472
  }
500
473
 
501
- // If Port80Handler is running, provision certificates based on routes
502
- if (this.port80Handler && this.settings.acme?.enabled) {
503
- // Register all eligible domains from routes
504
- this.port80Handler.addDomainsFromRoutes(newRoutes);
505
-
506
- // Handle static certificates from certProvisionFunction if available
507
- if (this.settings.certProvisionFunction) {
508
- for (const route of newRoutes) {
509
- // Skip routes without domains
510
- if (!route.match.domains) continue;
511
-
512
- // Skip non-forward routes
513
- if (route.action.type !== 'forward') continue;
514
-
515
- // Skip routes without TLS termination
516
- if (!route.action.tls ||
517
- route.action.tls.mode === 'passthrough' ||
518
- !route.action.target) continue;
519
-
520
- // Skip certificate provisioning if certificate is not auto
521
- if (route.action.tls.certificate !== 'auto') continue;
522
-
523
- const domains = Array.isArray(route.match.domains)
524
- ? route.match.domains
525
- : [route.match.domains];
526
-
527
- for (const domain of domains) {
528
- try {
529
- const provision = await this.settings.certProvisionFunction(domain);
530
-
531
- // Skip http01 as those are handled by Port80Handler
532
- if (provision !== 'http01') {
533
- // Handle static certificate (e.g., DNS-01 provisioned)
534
- const certObj = provision as plugins.tsclass.network.ICert;
535
- const certData: ICertificateData = {
536
- domain: certObj.domainName,
537
- certificate: certObj.publicKey,
538
- privateKey: certObj.privateKey,
539
- expiryDate: new Date(certObj.validUntil),
540
- routeReference: {
541
- routeName: route.name
542
- }
543
- };
544
- this.networkProxyBridge.applyExternalCertificate(certData);
545
- console.log(`Applied static certificate for ${domain} from certProvider`);
546
- }
547
- } catch (err) {
548
- console.log(`certProvider error for ${domain}: ${err}`);
549
- }
550
- }
551
- }
474
+ // Update certificate manager with new routes
475
+ if (this.certManager) {
476
+ await this.certManager.stop();
477
+
478
+ this.certManager = new SmartCertManager(
479
+ newRoutes,
480
+ './certs',
481
+ this.certManager.getAcmeOptions()
482
+ );
483
+
484
+ if (this.networkProxyBridge.getNetworkProxy()) {
485
+ this.certManager.setNetworkProxy(this.networkProxyBridge.getNetworkProxy());
552
486
  }
553
-
554
- console.log('Provisioned certificates for new routes');
487
+
488
+ await this.certManager.initialize();
555
489
  }
556
490
  }
557
491
 
558
492
  /**
559
- * Request a certificate for a specific domain
560
- *
561
- * @param domain The domain to request a certificate for
562
- * @param routeName Optional route name to associate with the certificate
493
+ * Manually provision a certificate for a route
563
494
  */
564
- public async requestCertificate(domain: string, routeName?: string): Promise<boolean> {
565
- // Validate domain format
566
- if (!this.isValidDomain(domain)) {
567
- console.log(`Invalid domain format: ${domain}`);
568
- return false;
495
+ public async provisionCertificate(routeName: string): Promise<void> {
496
+ if (!this.certManager) {
497
+ throw new Error('Certificate manager not initialized');
569
498
  }
570
-
571
- // Use Port80Handler if available
572
- if (this.port80Handler) {
573
- try {
574
- // Check if we already have a certificate
575
- const cert = this.port80Handler.getCertificate(domain);
576
- if (cert) {
577
- console.log(`Certificate already exists for ${domain}, valid until ${cert.expiryDate.toISOString()}`);
578
- return true;
579
- }
580
-
581
- // Register domain for certificate issuance
582
- this.port80Handler.addDomain({
583
- domain,
584
- sslRedirect: true,
585
- acmeMaintenance: true,
586
- routeReference: routeName ? { routeName } : undefined
587
- });
588
-
589
- console.log(`Domain ${domain} registered for certificate issuance` + (routeName ? ` for route '${routeName}'` : ''));
590
- return true;
591
- } catch (err) {
592
- console.log(`Error registering domain with Port80Handler: ${err}`);
593
- return false;
594
- }
499
+
500
+ const route = this.settings.routes.find(r => r.name === routeName);
501
+ if (!route) {
502
+ throw new Error(`Route ${routeName} not found`);
503
+ }
504
+
505
+ await this.certManager.provisionCertificate(route);
506
+ }
507
+
508
+ /**
509
+ * Force renewal of a certificate
510
+ */
511
+ public async renewCertificate(routeName: string): Promise<void> {
512
+ if (!this.certManager) {
513
+ throw new Error('Certificate manager not initialized');
514
+ }
515
+
516
+ await this.certManager.renewCertificate(routeName);
517
+ }
518
+
519
+ /**
520
+ * Get certificate status for a route
521
+ */
522
+ public getCertificateStatus(routeName: string): ICertStatus | undefined {
523
+ if (!this.certManager) {
524
+ return undefined;
595
525
  }
596
526
 
597
- // Fall back to NetworkProxyBridge
598
- return this.networkProxyBridge.requestCertificate(domain);
527
+ return this.certManager.getCertificateStatus(routeName);
599
528
  }
600
529
 
601
530
  /**
@@ -685,8 +614,8 @@ export class SmartProxy extends plugins.EventEmitter {
685
614
  keepAliveConnections,
686
615
  networkProxyConnections,
687
616
  terminationStats,
688
- acmeEnabled: !!this.port80Handler,
689
- port80HandlerPort: this.port80Handler ? this.settings.acme?.port : null,
617
+ acmeEnabled: !!this.certManager,
618
+ port80HandlerPort: this.certManager ? 80 : null,
690
619
  routes: this.routeManager.getListeningPorts().length,
691
620
  listeningPorts: this.portManager.getListeningPorts(),
692
621
  activePorts: this.portManager.getListeningPorts().length
@@ -735,51 +664,4 @@ export class SmartProxy extends plugins.EventEmitter {
735
664
  return this.nftablesManager.getStatus();
736
665
  }
737
666
 
738
- /**
739
- * Get status of certificates managed by Port80Handler
740
- */
741
- public getCertificateStatus(): any {
742
- if (!this.port80Handler) {
743
- return {
744
- enabled: false,
745
- message: 'Port80Handler is not enabled'
746
- };
747
- }
748
-
749
- // Get eligible domains
750
- const eligibleDomains = this.getEligibleDomainsForCertificates();
751
- const certificateStatus: Record<string, any> = {};
752
-
753
- // Check each domain
754
- for (const domain of eligibleDomains) {
755
- const cert = this.port80Handler.getCertificate(domain);
756
-
757
- if (cert) {
758
- const now = new Date();
759
- const expiryDate = cert.expiryDate;
760
- const daysRemaining = Math.floor((expiryDate.getTime() - now.getTime()) / (24 * 60 * 60 * 1000));
761
-
762
- certificateStatus[domain] = {
763
- status: 'valid',
764
- expiryDate: expiryDate.toISOString(),
765
- daysRemaining,
766
- renewalNeeded: daysRemaining <= (this.settings.acme?.renewThresholdDays ?? 0)
767
- };
768
- } else {
769
- certificateStatus[domain] = {
770
- status: 'missing',
771
- message: 'No certificate found'
772
- };
773
- }
774
- }
775
-
776
- const acme = this.settings.acme!;
777
- return {
778
- enabled: true,
779
- port: acme.port!,
780
- useProduction: acme.useProduction!,
781
- autoRenew: acme.autoRenew!,
782
- certificates: certificateStatus
783
- };
784
- }
785
667
  }
@@ -1,48 +0,0 @@
1
- import * as fs from 'fs';
2
- import * as path from 'path';
3
- import type { IAcmeOptions } from '../models/certificate-types.js';
4
- import { ensureCertificateDirectory } from '../utils/certificate-helpers.js';
5
- // We'll need to update this import when we move the Port80Handler
6
- import { Port80Handler } from '../../http/port80/port80-handler.js';
7
-
8
- /**
9
- * Factory to create a Port80Handler with common setup.
10
- * Ensures the certificate store directory exists and instantiates the handler.
11
- * @param options Port80Handler configuration options
12
- * @returns A new Port80Handler instance
13
- */
14
- export function buildPort80Handler(
15
- options: IAcmeOptions
16
- ): Port80Handler {
17
- if (options.certificateStore) {
18
- ensureCertificateDirectory(options.certificateStore);
19
- console.log(`Ensured certificate store directory: ${options.certificateStore}`);
20
- }
21
- return new Port80Handler(options);
22
- }
23
-
24
- /**
25
- * Creates default ACME options with sensible defaults
26
- * @param email Account email for ACME provider
27
- * @param certificateStore Path to store certificates
28
- * @param useProduction Whether to use production ACME servers
29
- * @returns Configured ACME options
30
- */
31
- export function createDefaultAcmeOptions(
32
- email: string,
33
- certificateStore: string,
34
- useProduction: boolean = false
35
- ): IAcmeOptions {
36
- return {
37
- accountEmail: email,
38
- enabled: true,
39
- port: 80,
40
- useProduction,
41
- httpsRedirectPort: 443,
42
- renewThresholdDays: 30,
43
- renewCheckIntervalHours: 24,
44
- autoRenew: true,
45
- certificateStore,
46
- skipConfiguredCerts: false
47
- };
48
- }
@@ -1,110 +0,0 @@
1
- import * as plugins from '../../plugins.js';
2
- import type { IAcmeOptions, ICertificateData } from '../models/certificate-types.js';
3
- import { CertificateEvents } from '../events/certificate-events.js';
4
-
5
- /**
6
- * Manages ACME challenges and certificate validation
7
- */
8
- export class AcmeChallengeHandler extends plugins.EventEmitter {
9
- private options: IAcmeOptions;
10
- private client: any; // ACME client from plugins
11
- private pendingChallenges: Map<string, any>;
12
-
13
- /**
14
- * Creates a new ACME challenge handler
15
- * @param options ACME configuration options
16
- */
17
- constructor(options: IAcmeOptions) {
18
- super();
19
- this.options = options;
20
- this.pendingChallenges = new Map();
21
-
22
- // Initialize ACME client if needed
23
- // This is just a placeholder implementation since we don't use the actual
24
- // client directly in this implementation - it's handled by Port80Handler
25
- this.client = null;
26
- console.log('Created challenge handler with options:',
27
- options.accountEmail,
28
- options.useProduction ? 'production' : 'staging'
29
- );
30
- }
31
-
32
- /**
33
- * Gets or creates the ACME account key
34
- */
35
- private getAccountKey(): Buffer {
36
- // Implementation details would depend on plugin requirements
37
- // This is a simplified version
38
- if (!this.options.certificateStore) {
39
- throw new Error('Certificate store is required for ACME challenges');
40
- }
41
-
42
- // This is just a placeholder - actual implementation would check for
43
- // existing account key and create one if needed
44
- return Buffer.from('account-key-placeholder');
45
- }
46
-
47
- /**
48
- * Validates a domain using HTTP-01 challenge
49
- * @param domain Domain to validate
50
- * @param challengeToken ACME challenge token
51
- * @param keyAuthorization Key authorization for the challenge
52
- */
53
- public async handleHttpChallenge(
54
- domain: string,
55
- challengeToken: string,
56
- keyAuthorization: string
57
- ): Promise<void> {
58
- // Store challenge for response
59
- this.pendingChallenges.set(challengeToken, keyAuthorization);
60
-
61
- try {
62
- // Wait for challenge validation - this would normally be handled by the ACME client
63
- await new Promise(resolve => setTimeout(resolve, 1000));
64
- this.emit(CertificateEvents.CERTIFICATE_ISSUED, {
65
- domain,
66
- success: true
67
- });
68
- } catch (error) {
69
- this.emit(CertificateEvents.CERTIFICATE_FAILED, {
70
- domain,
71
- error: error instanceof Error ? error.message : String(error),
72
- isRenewal: false
73
- });
74
- throw error;
75
- } finally {
76
- // Clean up the challenge
77
- this.pendingChallenges.delete(challengeToken);
78
- }
79
- }
80
-
81
- /**
82
- * Responds to an HTTP-01 challenge request
83
- * @param token Challenge token from the request path
84
- * @returns The key authorization if found
85
- */
86
- public getChallengeResponse(token: string): string | null {
87
- return this.pendingChallenges.get(token) || null;
88
- }
89
-
90
- /**
91
- * Checks if a request path is an ACME challenge
92
- * @param path Request path
93
- * @returns True if this is an ACME challenge request
94
- */
95
- public isAcmeChallenge(path: string): boolean {
96
- return path.startsWith('/.well-known/acme-challenge/');
97
- }
98
-
99
- /**
100
- * Extracts the challenge token from an ACME challenge path
101
- * @param path Request path
102
- * @returns The challenge token if valid
103
- */
104
- public extractChallengeToken(path: string): string | null {
105
- if (!this.isAcmeChallenge(path)) return null;
106
-
107
- const parts = path.split('/');
108
- return parts[parts.length - 1] || null;
109
- }
110
- }
@@ -1,3 +0,0 @@
1
- /**
2
- * ACME certificate provisioning
3
- */
@@ -1,36 +0,0 @@
1
- /**
2
- * Certificate-related events emitted by certificate management components
3
- */
4
- export enum CertificateEvents {
5
- CERTIFICATE_ISSUED = 'certificate-issued',
6
- CERTIFICATE_RENEWED = 'certificate-renewed',
7
- CERTIFICATE_FAILED = 'certificate-failed',
8
- CERTIFICATE_EXPIRING = 'certificate-expiring',
9
- CERTIFICATE_APPLIED = 'certificate-applied',
10
- // Events moved from Port80Handler for compatibility
11
- MANAGER_STARTED = 'manager-started',
12
- MANAGER_STOPPED = 'manager-stopped',
13
- }
14
-
15
- /**
16
- * Port80Handler-specific events including certificate-related ones
17
- * @deprecated Use CertificateEvents and HttpEvents instead
18
- */
19
- export enum Port80HandlerEvents {
20
- CERTIFICATE_ISSUED = 'certificate-issued',
21
- CERTIFICATE_RENEWED = 'certificate-renewed',
22
- CERTIFICATE_FAILED = 'certificate-failed',
23
- CERTIFICATE_EXPIRING = 'certificate-expiring',
24
- MANAGER_STARTED = 'manager-started',
25
- MANAGER_STOPPED = 'manager-stopped',
26
- REQUEST_FORWARDED = 'request-forwarded',
27
- }
28
-
29
- /**
30
- * Certificate provider events
31
- */
32
- export enum CertProvisionerEvents {
33
- CERTIFICATE_ISSUED = 'certificate',
34
- CERTIFICATE_RENEWED = 'certificate',
35
- CERTIFICATE_FAILED = 'certificate-failed'
36
- }