@push.rocks/smartproxy 18.2.0 → 19.2.2
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 +1 -1
- package/dist_ts/common/eventUtils.d.ts +1 -2
- package/dist_ts/common/eventUtils.js +2 -1
- package/dist_ts/core/models/common-types.d.ts +1 -1
- package/dist_ts/core/models/common-types.js +1 -1
- package/dist_ts/core/utils/event-utils.d.ts +9 -9
- package/dist_ts/core/utils/event-utils.js +6 -14
- package/dist_ts/http/models/http-types.d.ts +13 -1
- package/dist_ts/http/models/http-types.js +1 -1
- package/dist_ts/index.d.ts +4 -6
- package/dist_ts/index.js +4 -10
- package/dist_ts/proxies/index.d.ts +3 -2
- package/dist_ts/proxies/index.js +4 -5
- package/dist_ts/proxies/network-proxy/certificate-manager.d.ts +31 -49
- package/dist_ts/proxies/network-proxy/certificate-manager.js +77 -374
- package/dist_ts/proxies/network-proxy/models/types.d.ts +12 -1
- package/dist_ts/proxies/network-proxy/models/types.js +1 -1
- package/dist_ts/proxies/network-proxy/network-proxy.d.ts +2 -7
- package/dist_ts/proxies/network-proxy/network-proxy.js +10 -19
- package/dist_ts/proxies/smart-proxy/certificate-manager.d.ts +6 -0
- package/dist_ts/proxies/smart-proxy/certificate-manager.js +24 -5
- package/dist_ts/proxies/smart-proxy/models/index.d.ts +1 -1
- package/dist_ts/proxies/smart-proxy/models/index.js +1 -5
- package/dist_ts/proxies/smart-proxy/models/interfaces.d.ts +30 -1
- package/dist_ts/proxies/smart-proxy/route-manager.d.ts +4 -0
- package/dist_ts/proxies/smart-proxy/route-manager.js +7 -1
- package/dist_ts/proxies/smart-proxy/smart-proxy.d.ts +4 -0
- package/dist_ts/proxies/smart-proxy/smart-proxy.js +112 -26
- package/package.json +1 -2
- package/readme.hints.md +31 -1
- package/readme.md +82 -6
- package/readme.plan.md +109 -1417
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/common/eventUtils.ts +2 -2
- package/ts/core/models/common-types.ts +1 -1
- package/ts/core/utils/event-utils.ts +12 -21
- package/ts/http/models/http-types.ts +8 -4
- package/ts/index.ts +11 -14
- package/ts/proxies/index.ts +7 -4
- package/ts/proxies/network-proxy/certificate-manager.ts +92 -417
- package/ts/proxies/network-proxy/models/types.ts +14 -2
- package/ts/proxies/network-proxy/network-proxy.ts +10 -19
- package/ts/proxies/smart-proxy/certificate-manager.ts +31 -4
- package/ts/proxies/smart-proxy/models/index.ts +2 -1
- package/ts/proxies/smart-proxy/models/interfaces.ts +31 -2
- package/ts/proxies/smart-proxy/models/route-types.ts +1 -1
- package/ts/proxies/smart-proxy/route-manager.ts +7 -0
- package/ts/proxies/smart-proxy/smart-proxy.ts +142 -25
- package/ts/certificate/acme/acme-factory.ts +0 -48
- package/ts/certificate/acme/challenge-handler.ts +0 -110
- package/ts/certificate/acme/index.ts +0 -3
- package/ts/certificate/events/certificate-events.ts +0 -36
- package/ts/certificate/index.ts +0 -75
- package/ts/certificate/models/certificate-types.ts +0 -109
- package/ts/certificate/providers/cert-provisioner.ts +0 -519
- package/ts/certificate/providers/index.ts +0 -3
- package/ts/certificate/storage/file-storage.ts +0 -234
- package/ts/certificate/storage/index.ts +0 -3
- package/ts/certificate/utils/certificate-helpers.ts +0 -50
- package/ts/http/port80/acme-interfaces.ts +0 -169
- package/ts/http/port80/challenge-responder.ts +0 -246
- package/ts/http/port80/index.ts +0 -13
- package/ts/http/port80/port80-handler.ts +0 -728
|
@@ -3,21 +3,17 @@ import * as fs from 'fs';
|
|
|
3
3
|
import * as path from 'path';
|
|
4
4
|
import { fileURLToPath } from 'url';
|
|
5
5
|
import { type INetworkProxyOptions, type ICertificateEntry, type ILogger, createLogger } from './models/types.js';
|
|
6
|
-
import { Port80Handler } from '../../http/port80/port80-handler.js';
|
|
7
|
-
import { CertificateEvents } from '../../certificate/events/certificate-events.js';
|
|
8
|
-
import { buildPort80Handler } from '../../certificate/acme/acme-factory.js';
|
|
9
|
-
import { subscribeToPort80Handler } from '../../core/utils/event-utils.js';
|
|
10
|
-
import type { IDomainOptions } from '../../certificate/models/certificate-types.js';
|
|
11
6
|
import type { IRouteConfig } from '../smart-proxy/models/route-types.js';
|
|
12
7
|
|
|
13
8
|
/**
|
|
14
|
-
*
|
|
9
|
+
* @deprecated This class is deprecated. Use SmartCertManager instead.
|
|
10
|
+
*
|
|
11
|
+
* This is a stub implementation that maintains backward compatibility
|
|
12
|
+
* while the functionality has been moved to SmartCertManager.
|
|
15
13
|
*/
|
|
16
14
|
export class CertificateManager {
|
|
17
15
|
private defaultCertificates: { key: string; cert: string };
|
|
18
16
|
private certificateCache: Map<string, ICertificateEntry> = new Map();
|
|
19
|
-
private port80Handler: Port80Handler | null = null;
|
|
20
|
-
private externalPort80Handler: boolean = false;
|
|
21
17
|
private certificateStoreDir: string;
|
|
22
18
|
private logger: ILogger;
|
|
23
19
|
private httpsServer: plugins.https.Server | null = null;
|
|
@@ -26,6 +22,8 @@ export class CertificateManager {
|
|
|
26
22
|
this.certificateStoreDir = path.resolve(options.acme?.certificateStore || './certs');
|
|
27
23
|
this.logger = createLogger(options.logLevel || 'info');
|
|
28
24
|
|
|
25
|
+
this.logger.warn('CertificateManager is deprecated - use SmartCertManager instead');
|
|
26
|
+
|
|
29
27
|
// Ensure certificate store directory exists
|
|
30
28
|
try {
|
|
31
29
|
if (!fs.existsSync(this.certificateStoreDir)) {
|
|
@@ -44,7 +42,6 @@ export class CertificateManager {
|
|
|
44
42
|
*/
|
|
45
43
|
public loadDefaultCertificates(): void {
|
|
46
44
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
47
|
-
// Fix the path to look for certificates at the project root instead of inside ts directory
|
|
48
45
|
const certPath = path.join(__dirname, '..', '..', '..', 'assets', 'certs');
|
|
49
46
|
|
|
50
47
|
try {
|
|
@@ -52,467 +49,145 @@ export class CertificateManager {
|
|
|
52
49
|
key: fs.readFileSync(path.join(certPath, 'key.pem'), 'utf8'),
|
|
53
50
|
cert: fs.readFileSync(path.join(certPath, 'cert.pem'), 'utf8')
|
|
54
51
|
};
|
|
55
|
-
this.logger.info('
|
|
52
|
+
this.logger.info('Loaded default certificates from filesystem');
|
|
56
53
|
} catch (error) {
|
|
57
|
-
this.logger.error(
|
|
58
|
-
|
|
59
|
-
// Generate self-signed fallback certificates
|
|
60
|
-
try {
|
|
61
|
-
// This is a placeholder for actual certificate generation code
|
|
62
|
-
// In a real implementation, you would use a library like selfsigned to generate certs
|
|
63
|
-
this.defaultCertificates = {
|
|
64
|
-
key: "FALLBACK_KEY_CONTENT",
|
|
65
|
-
cert: "FALLBACK_CERT_CONTENT"
|
|
66
|
-
};
|
|
67
|
-
this.logger.warn('Using fallback self-signed certificates');
|
|
68
|
-
} catch (fallbackError) {
|
|
69
|
-
this.logger.error('Failed to generate fallback certificates', fallbackError);
|
|
70
|
-
throw new Error('Could not load or generate SSL certificates');
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* Set the HTTPS server reference for context updates
|
|
77
|
-
*/
|
|
78
|
-
public setHttpsServer(server: plugins.https.Server): void {
|
|
79
|
-
this.httpsServer = server;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* Get default certificates
|
|
84
|
-
*/
|
|
85
|
-
public getDefaultCertificates(): { key: string; cert: string } {
|
|
86
|
-
return { ...this.defaultCertificates };
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* Sets an external Port80Handler for certificate management
|
|
91
|
-
*/
|
|
92
|
-
public setExternalPort80Handler(handler: Port80Handler): void {
|
|
93
|
-
if (this.port80Handler && !this.externalPort80Handler) {
|
|
94
|
-
this.logger.warn('Replacing existing internal Port80Handler with external handler');
|
|
95
|
-
|
|
96
|
-
// Clean up existing handler if needed
|
|
97
|
-
if (this.port80Handler !== handler) {
|
|
98
|
-
// Unregister event handlers to avoid memory leaks
|
|
99
|
-
this.port80Handler.removeAllListeners(CertificateEvents.CERTIFICATE_ISSUED);
|
|
100
|
-
this.port80Handler.removeAllListeners(CertificateEvents.CERTIFICATE_RENEWED);
|
|
101
|
-
this.port80Handler.removeAllListeners(CertificateEvents.CERTIFICATE_FAILED);
|
|
102
|
-
this.port80Handler.removeAllListeners(CertificateEvents.CERTIFICATE_EXPIRING);
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
// Set the external handler
|
|
107
|
-
this.port80Handler = handler;
|
|
108
|
-
this.externalPort80Handler = true;
|
|
109
|
-
|
|
110
|
-
// Subscribe to Port80Handler events
|
|
111
|
-
subscribeToPort80Handler(this.port80Handler, {
|
|
112
|
-
onCertificateIssued: this.handleCertificateIssued.bind(this),
|
|
113
|
-
onCertificateRenewed: this.handleCertificateIssued.bind(this),
|
|
114
|
-
onCertificateFailed: this.handleCertificateFailed.bind(this),
|
|
115
|
-
onCertificateExpiring: (data) => {
|
|
116
|
-
this.logger.info(`Certificate for ${data.domain} expires in ${data.daysRemaining} days`);
|
|
117
|
-
}
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
this.logger.info('External Port80Handler connected to CertificateManager');
|
|
121
|
-
|
|
122
|
-
// Register domains with Port80Handler if we have any certificates cached
|
|
123
|
-
if (this.certificateCache.size > 0) {
|
|
124
|
-
const domains = Array.from(this.certificateCache.keys())
|
|
125
|
-
.filter(domain => !domain.includes('*')); // Skip wildcard domains
|
|
126
|
-
|
|
127
|
-
this.registerDomainsWithPort80Handler(domains);
|
|
54
|
+
this.logger.error(`Failed to load default certificates: ${error}`);
|
|
55
|
+
this.generateSelfSignedCertificate();
|
|
128
56
|
}
|
|
129
57
|
}
|
|
130
58
|
|
|
131
59
|
/**
|
|
132
|
-
*
|
|
133
|
-
* This method is called when route configurations change
|
|
134
|
-
*
|
|
135
|
-
* @param routes Array of route configurations
|
|
60
|
+
* Generates self-signed certificates as fallback
|
|
136
61
|
*/
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
62
|
+
private generateSelfSignedCertificate(): void {
|
|
63
|
+
// Generate a self-signed certificate using forge or similar
|
|
64
|
+
// For now, just use a placeholder
|
|
65
|
+
const selfSignedCert = `-----BEGIN CERTIFICATE-----
|
|
66
|
+
MIIBkTCB+wIJAKHHIgIIA0/cMA0GCSqGSIb3DQEBBQUAMA0xCzAJBgNVBAYTAlVT
|
|
67
|
+
MB4XDTE0MDEwMTAwMDAwMFoXDTI0MDEwMTAwMDAwMFowDTELMAkGA1UEBhMCVVMw
|
|
68
|
+
gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMRiH0VwnOH3jCV7c6JFZWYrvuqy
|
|
69
|
+
-----END CERTIFICATE-----`;
|
|
70
|
+
|
|
71
|
+
const selfSignedKey = `-----BEGIN PRIVATE KEY-----
|
|
72
|
+
MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAMRiH0VwnOH3jCV7
|
|
73
|
+
c6JFZWYrvuqyALCLXj0pcr1iqNdHjegNXnkl5zjdaUjq4edNOKl7M1AlFiYjG2xk
|
|
74
|
+
-----END PRIVATE KEY-----`;
|
|
145
75
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
}
|
|
76
|
+
this.defaultCertificates = {
|
|
77
|
+
key: selfSignedKey,
|
|
78
|
+
cert: selfSignedCert
|
|
79
|
+
};
|
|
150
80
|
|
|
151
|
-
this.logger.
|
|
81
|
+
this.logger.warn('Using self-signed certificate as fallback');
|
|
152
82
|
}
|
|
153
|
-
|
|
83
|
+
|
|
154
84
|
/**
|
|
155
|
-
*
|
|
85
|
+
* Gets the default certificates
|
|
156
86
|
*/
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
this.logger.info(`Certificate ${this.certificateCache.has(domain) ? 'renewed' : 'issued'} for ${domain}, valid until ${expiryDate.toISOString()}`);
|
|
161
|
-
|
|
162
|
-
// Update certificate in HTTPS server
|
|
163
|
-
this.updateCertificateCache(domain, certificate, privateKey, expiryDate);
|
|
164
|
-
|
|
165
|
-
// Save the certificate to the filesystem if not using external handler
|
|
166
|
-
if (!this.externalPort80Handler && this.options.acme?.certificateStore) {
|
|
167
|
-
this.saveCertificateToStore(domain, certificate, privateKey);
|
|
168
|
-
}
|
|
87
|
+
public getDefaultCertificates(): { key: string; cert: string } {
|
|
88
|
+
return this.defaultCertificates;
|
|
169
89
|
}
|
|
170
|
-
|
|
90
|
+
|
|
171
91
|
/**
|
|
172
|
-
*
|
|
92
|
+
* @deprecated Use SmartCertManager instead
|
|
173
93
|
*/
|
|
174
|
-
|
|
175
|
-
this.logger.
|
|
94
|
+
public setExternalPort80Handler(handler: any): void {
|
|
95
|
+
this.logger.warn('setExternalPort80Handler is deprecated - use SmartCertManager instead');
|
|
176
96
|
}
|
|
177
|
-
|
|
97
|
+
|
|
178
98
|
/**
|
|
179
|
-
*
|
|
99
|
+
* @deprecated Use SmartCertManager instead
|
|
180
100
|
*/
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
const certPath = path.join(this.certificateStoreDir, `${domain}.cert.pem`);
|
|
184
|
-
const keyPath = path.join(this.certificateStoreDir, `${domain}.key.pem`);
|
|
185
|
-
|
|
186
|
-
fs.writeFileSync(certPath, certificate);
|
|
187
|
-
fs.writeFileSync(keyPath, privateKey);
|
|
188
|
-
|
|
189
|
-
// Ensure private key has restricted permissions
|
|
190
|
-
try {
|
|
191
|
-
fs.chmodSync(keyPath, 0o600);
|
|
192
|
-
} catch (error) {
|
|
193
|
-
this.logger.warn(`Failed to set permissions on private key for ${domain}: ${error}`);
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
this.logger.info(`Saved certificate for ${domain} to ${certPath}`);
|
|
197
|
-
} catch (error) {
|
|
198
|
-
this.logger.error(`Failed to save certificate for ${domain}: ${error}`);
|
|
199
|
-
}
|
|
101
|
+
public async updateRoutes(routes: IRouteConfig[]): Promise<void> {
|
|
102
|
+
this.logger.warn('updateRoutes is deprecated - use SmartCertManager instead');
|
|
200
103
|
}
|
|
201
|
-
|
|
104
|
+
|
|
202
105
|
/**
|
|
203
|
-
* Handles SNI
|
|
204
|
-
* Used by the HTTPS server to select the correct certificate for each domain
|
|
106
|
+
* Handles SNI callback to provide appropriate certificate
|
|
205
107
|
*/
|
|
206
108
|
public handleSNI(domain: string, cb: (err: Error | null, ctx: plugins.tls.SecureContext) => void): void {
|
|
207
|
-
this.
|
|
208
|
-
|
|
209
|
-
// Check if we have a certificate for this domain
|
|
210
|
-
const certs = this.certificateCache.get(domain);
|
|
211
|
-
if (certs) {
|
|
212
|
-
try {
|
|
213
|
-
// Create TLS context with the cached certificate
|
|
214
|
-
const context = plugins.tls.createSecureContext({
|
|
215
|
-
key: certs.key,
|
|
216
|
-
cert: certs.cert
|
|
217
|
-
});
|
|
218
|
-
this.logger.debug(`Using cached certificate for ${domain}`);
|
|
219
|
-
cb(null, context);
|
|
220
|
-
return;
|
|
221
|
-
} catch (err) {
|
|
222
|
-
this.logger.error(`Error creating secure context for ${domain}:`, err);
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
// No existing certificate: trigger dynamic provisioning via Port80Handler
|
|
226
|
-
if (this.port80Handler) {
|
|
227
|
-
try {
|
|
228
|
-
this.logger.info(`Triggering on-demand certificate retrieval for ${domain}`);
|
|
229
|
-
this.port80Handler.addDomain({
|
|
230
|
-
domainName: domain,
|
|
231
|
-
sslRedirect: false,
|
|
232
|
-
acmeMaintenance: true
|
|
233
|
-
});
|
|
234
|
-
} catch (err) {
|
|
235
|
-
this.logger.error(`Error registering domain for on-demand certificate: ${domain}`, err);
|
|
236
|
-
}
|
|
237
|
-
}
|
|
109
|
+
const certificate = this.getCachedCertificate(domain);
|
|
238
110
|
|
|
239
|
-
|
|
240
|
-
if (this.options.acme?.enabled && this.port80Handler && !domain.includes('*')) {
|
|
241
|
-
// Check if this domain is already registered
|
|
242
|
-
const certData = this.port80Handler.getCertificate(domain);
|
|
243
|
-
|
|
244
|
-
if (!certData) {
|
|
245
|
-
this.logger.info(`No certificate found for ${domain}, registering for issuance`);
|
|
246
|
-
|
|
247
|
-
// Register with new domain options format
|
|
248
|
-
const domainOptions: IDomainOptions = {
|
|
249
|
-
domainName: domain,
|
|
250
|
-
sslRedirect: true,
|
|
251
|
-
acmeMaintenance: true
|
|
252
|
-
};
|
|
253
|
-
|
|
254
|
-
this.port80Handler.addDomain(domainOptions);
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
// Fall back to default certificate
|
|
259
|
-
try {
|
|
111
|
+
if (certificate) {
|
|
260
112
|
const context = plugins.tls.createSecureContext({
|
|
261
|
-
key:
|
|
262
|
-
cert:
|
|
113
|
+
key: certificate.key,
|
|
114
|
+
cert: certificate.cert
|
|
263
115
|
});
|
|
264
|
-
|
|
265
|
-
this.logger.debug(`Using default certificate for ${domain}`);
|
|
266
116
|
cb(null, context);
|
|
267
|
-
|
|
268
|
-
this.logger.error(`Error creating default secure context:`, err);
|
|
269
|
-
cb(new Error('Cannot create secure context'), null);
|
|
117
|
+
return;
|
|
270
118
|
}
|
|
119
|
+
|
|
120
|
+
// Use default certificate if no domain-specific certificate found
|
|
121
|
+
const defaultContext = plugins.tls.createSecureContext({
|
|
122
|
+
key: this.defaultCertificates.key,
|
|
123
|
+
cert: this.defaultCertificates.cert
|
|
124
|
+
});
|
|
125
|
+
cb(null, defaultContext);
|
|
271
126
|
}
|
|
272
|
-
|
|
127
|
+
|
|
273
128
|
/**
|
|
274
|
-
* Updates certificate in cache
|
|
129
|
+
* Updates a certificate in the cache
|
|
275
130
|
*/
|
|
276
|
-
public
|
|
277
|
-
// Update certificate context in HTTPS server if it's running
|
|
278
|
-
if (this.httpsServer) {
|
|
279
|
-
try {
|
|
280
|
-
this.httpsServer.addContext(domain, {
|
|
281
|
-
key: privateKey,
|
|
282
|
-
cert: certificate
|
|
283
|
-
});
|
|
284
|
-
this.logger.debug(`Updated SSL context for domain: ${domain}`);
|
|
285
|
-
} catch (error) {
|
|
286
|
-
this.logger.error(`Error updating SSL context for domain ${domain}:`, error);
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
// Update certificate in cache
|
|
131
|
+
public updateCertificate(domain: string, cert: string, key: string): void {
|
|
291
132
|
this.certificateCache.set(domain, {
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
expires:
|
|
133
|
+
cert,
|
|
134
|
+
key,
|
|
135
|
+
expires: new Date(Date.now() + 90 * 24 * 60 * 60 * 1000) // 90 days
|
|
295
136
|
});
|
|
137
|
+
|
|
138
|
+
this.logger.info(`Certificate updated for ${domain}`);
|
|
296
139
|
}
|
|
297
|
-
|
|
140
|
+
|
|
298
141
|
/**
|
|
299
|
-
* Gets a certificate
|
|
142
|
+
* Gets a cached certificate
|
|
300
143
|
*/
|
|
301
|
-
|
|
302
|
-
return this.certificateCache.get(domain);
|
|
144
|
+
private getCachedCertificate(domain: string): ICertificateEntry | null {
|
|
145
|
+
return this.certificateCache.get(domain) || null;
|
|
303
146
|
}
|
|
304
|
-
|
|
147
|
+
|
|
305
148
|
/**
|
|
306
|
-
*
|
|
149
|
+
* @deprecated Use SmartCertManager instead
|
|
307
150
|
*/
|
|
308
|
-
public async
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
return false;
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
if (!this.port80Handler) {
|
|
315
|
-
this.logger.error('Port80Handler is not initialized');
|
|
316
|
-
return false;
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
// Skip wildcard domains - can't get certs for these with HTTP-01 validation
|
|
320
|
-
if (domain.includes('*')) {
|
|
321
|
-
this.logger.error(`Cannot request certificate for wildcard domain: ${domain}`);
|
|
322
|
-
return false;
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
try {
|
|
326
|
-
// Use the new domain options format
|
|
327
|
-
const domainOptions: IDomainOptions = {
|
|
328
|
-
domainName: domain,
|
|
329
|
-
sslRedirect: true,
|
|
330
|
-
acmeMaintenance: true
|
|
331
|
-
};
|
|
332
|
-
|
|
333
|
-
this.port80Handler.addDomain(domainOptions);
|
|
334
|
-
this.logger.info(`Certificate request submitted for domain: ${domain}`);
|
|
335
|
-
return true;
|
|
336
|
-
} catch (error) {
|
|
337
|
-
this.logger.error(`Error requesting certificate for domain ${domain}:`, error);
|
|
338
|
-
return false;
|
|
339
|
-
}
|
|
151
|
+
public async initializePort80Handler(): Promise<any> {
|
|
152
|
+
this.logger.warn('initializePort80Handler is deprecated - use SmartCertManager instead');
|
|
153
|
+
return null;
|
|
340
154
|
}
|
|
341
|
-
|
|
155
|
+
|
|
342
156
|
/**
|
|
343
|
-
*
|
|
344
|
-
* @param domains String array of domains to register
|
|
157
|
+
* @deprecated Use SmartCertManager instead
|
|
345
158
|
*/
|
|
346
|
-
public
|
|
347
|
-
|
|
348
|
-
this.logger.warn('Port80Handler is not initialized');
|
|
349
|
-
return;
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
for (const domain of domains) {
|
|
353
|
-
// Skip wildcard domains - can't get certs for these with HTTP-01 validation
|
|
354
|
-
if (domain.includes('*')) {
|
|
355
|
-
this.logger.info(`Skipping wildcard domain for ACME: ${domain}`);
|
|
356
|
-
continue;
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
// Skip domains already with certificates if configured to do so
|
|
360
|
-
if (this.options.acme?.skipConfiguredCerts) {
|
|
361
|
-
const cachedCert = this.certificateCache.get(domain);
|
|
362
|
-
if (cachedCert) {
|
|
363
|
-
this.logger.info(`Skipping domain with existing certificate: ${domain}`);
|
|
364
|
-
continue;
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
// Register the domain for certificate issuance with new domain options format
|
|
369
|
-
const domainOptions: IDomainOptions = {
|
|
370
|
-
domainName: domain,
|
|
371
|
-
sslRedirect: true,
|
|
372
|
-
acmeMaintenance: true
|
|
373
|
-
};
|
|
374
|
-
|
|
375
|
-
this.port80Handler.addDomain(domainOptions);
|
|
376
|
-
this.logger.info(`Registered domain for ACME certificate issuance: ${domain}`);
|
|
377
|
-
}
|
|
159
|
+
public async stopPort80Handler(): Promise<void> {
|
|
160
|
+
this.logger.warn('stopPort80Handler is deprecated - use SmartCertManager instead');
|
|
378
161
|
}
|
|
379
162
|
|
|
380
163
|
/**
|
|
381
|
-
*
|
|
382
|
-
* This method enables direct integration with route-based configuration
|
|
383
|
-
*
|
|
384
|
-
* @param routes Array of route configurations
|
|
164
|
+
* @deprecated Use SmartCertManager instead
|
|
385
165
|
*/
|
|
386
|
-
public
|
|
387
|
-
|
|
388
|
-
this.logger.warn('Port80Handler is not initialized');
|
|
389
|
-
return;
|
|
390
|
-
}
|
|
391
|
-
|
|
392
|
-
// Extract domains from route configurations
|
|
393
|
-
const domains: Set<string> = new Set();
|
|
394
|
-
|
|
395
|
-
for (const route of routes) {
|
|
396
|
-
// Skip disabled routes
|
|
397
|
-
if (route.enabled === false) {
|
|
398
|
-
continue;
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
// Skip routes without HTTPS termination
|
|
402
|
-
if (route.action.type !== 'forward' || route.action.tls?.mode !== 'terminate') {
|
|
403
|
-
continue;
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
// Extract domains from match criteria
|
|
407
|
-
if (route.match.domains) {
|
|
408
|
-
if (typeof route.match.domains === 'string') {
|
|
409
|
-
domains.add(route.match.domains);
|
|
410
|
-
} else if (Array.isArray(route.match.domains)) {
|
|
411
|
-
for (const domain of route.match.domains) {
|
|
412
|
-
domains.add(domain);
|
|
413
|
-
}
|
|
414
|
-
}
|
|
415
|
-
}
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
// Register extracted domains
|
|
419
|
-
this.registerDomainsWithPort80Handler(Array.from(domains));
|
|
166
|
+
public registerDomainsWithPort80Handler(domains: string[]): void {
|
|
167
|
+
this.logger.warn('registerDomainsWithPort80Handler is deprecated - use SmartCertManager instead');
|
|
420
168
|
}
|
|
421
169
|
|
|
422
170
|
/**
|
|
423
|
-
*
|
|
424
|
-
* @param route Route configuration to process
|
|
171
|
+
* @deprecated Use SmartCertManager instead
|
|
425
172
|
*/
|
|
426
|
-
public
|
|
427
|
-
|
|
428
|
-
if (route.enabled === false) {
|
|
429
|
-
return;
|
|
430
|
-
}
|
|
431
|
-
|
|
432
|
-
// Skip routes without HTTPS termination or auto certificate
|
|
433
|
-
if (route.action.type !== 'forward' ||
|
|
434
|
-
route.action.tls?.mode !== 'terminate' ||
|
|
435
|
-
route.action.tls?.certificate !== 'auto') {
|
|
436
|
-
return;
|
|
437
|
-
}
|
|
438
|
-
|
|
439
|
-
// Extract domains from match criteria
|
|
440
|
-
const domains: string[] = [];
|
|
441
|
-
if (route.match.domains) {
|
|
442
|
-
if (typeof route.match.domains === 'string') {
|
|
443
|
-
domains.push(route.match.domains);
|
|
444
|
-
} else if (Array.isArray(route.match.domains)) {
|
|
445
|
-
domains.push(...route.match.domains);
|
|
446
|
-
}
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
// Request certificates for the domains
|
|
450
|
-
for (const domain of domains) {
|
|
451
|
-
if (!domain.includes('*')) { // Skip wildcard domains
|
|
452
|
-
this.requestCertificate(domain).catch(err => {
|
|
453
|
-
this.logger.error(`Error requesting certificate for domain ${domain}:`, err);
|
|
454
|
-
});
|
|
455
|
-
}
|
|
456
|
-
}
|
|
173
|
+
public registerRoutesWithPort80Handler(routes: IRouteConfig[]): void {
|
|
174
|
+
this.logger.warn('registerRoutesWithPort80Handler is deprecated - use SmartCertManager instead');
|
|
457
175
|
}
|
|
458
|
-
|
|
176
|
+
|
|
459
177
|
/**
|
|
460
|
-
*
|
|
178
|
+
* Sets the HTTPS server for certificate updates
|
|
461
179
|
*/
|
|
462
|
-
public
|
|
463
|
-
|
|
464
|
-
if (this.externalPort80Handler) {
|
|
465
|
-
this.logger.info('Using external Port80Handler, skipping initialization');
|
|
466
|
-
return this.port80Handler;
|
|
467
|
-
}
|
|
468
|
-
|
|
469
|
-
if (!this.options.acme?.enabled) {
|
|
470
|
-
return null;
|
|
471
|
-
}
|
|
472
|
-
|
|
473
|
-
// Build and configure Port80Handler
|
|
474
|
-
this.port80Handler = buildPort80Handler({
|
|
475
|
-
port: this.options.acme.port,
|
|
476
|
-
accountEmail: this.options.acme.accountEmail,
|
|
477
|
-
useProduction: this.options.acme.useProduction,
|
|
478
|
-
httpsRedirectPort: this.options.port, // Redirect to our HTTPS port
|
|
479
|
-
enabled: this.options.acme.enabled,
|
|
480
|
-
certificateStore: this.options.acme.certificateStore,
|
|
481
|
-
skipConfiguredCerts: this.options.acme.skipConfiguredCerts
|
|
482
|
-
});
|
|
483
|
-
// Subscribe to Port80Handler events
|
|
484
|
-
subscribeToPort80Handler(this.port80Handler, {
|
|
485
|
-
onCertificateIssued: this.handleCertificateIssued.bind(this),
|
|
486
|
-
onCertificateRenewed: this.handleCertificateIssued.bind(this),
|
|
487
|
-
onCertificateFailed: this.handleCertificateFailed.bind(this),
|
|
488
|
-
onCertificateExpiring: (data) => {
|
|
489
|
-
this.logger.info(`Certificate for ${data.domain} expires in ${data.daysRemaining} days`);
|
|
490
|
-
}
|
|
491
|
-
});
|
|
492
|
-
|
|
493
|
-
// Start the handler
|
|
494
|
-
try {
|
|
495
|
-
await this.port80Handler.start();
|
|
496
|
-
this.logger.info(`Port80Handler started on port ${this.options.acme.port}`);
|
|
497
|
-
return this.port80Handler;
|
|
498
|
-
} catch (error) {
|
|
499
|
-
this.logger.error(`Failed to start Port80Handler: ${error}`);
|
|
500
|
-
this.port80Handler = null;
|
|
501
|
-
return null;
|
|
502
|
-
}
|
|
180
|
+
public setHttpsServer(server: plugins.https.Server): void {
|
|
181
|
+
this.httpsServer = server;
|
|
503
182
|
}
|
|
504
|
-
|
|
183
|
+
|
|
505
184
|
/**
|
|
506
|
-
*
|
|
185
|
+
* Gets statistics for metrics
|
|
507
186
|
*/
|
|
508
|
-
public
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
} catch (error) {
|
|
514
|
-
this.logger.error('Error stopping Port80Handler', error);
|
|
515
|
-
}
|
|
516
|
-
}
|
|
187
|
+
public getStats() {
|
|
188
|
+
return {
|
|
189
|
+
cachedCertificates: this.certificateCache.size,
|
|
190
|
+
defaultCertEnabled: true
|
|
191
|
+
};
|
|
517
192
|
}
|
|
518
193
|
}
|
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
import * as plugins from '../../../plugins.js';
|
|
2
|
-
|
|
2
|
+
// Certificate types removed - define IAcmeOptions locally
|
|
3
|
+
export interface IAcmeOptions {
|
|
4
|
+
enabled: boolean;
|
|
5
|
+
email?: string;
|
|
6
|
+
accountEmail?: string;
|
|
7
|
+
port?: number;
|
|
8
|
+
certificateStore?: string;
|
|
9
|
+
environment?: 'production' | 'staging';
|
|
10
|
+
useProduction?: boolean;
|
|
11
|
+
renewThresholdDays?: number;
|
|
12
|
+
autoRenew?: boolean;
|
|
13
|
+
skipConfiguredCerts?: boolean;
|
|
14
|
+
}
|
|
3
15
|
import type { IRouteConfig } from '../../smart-proxy/models/route-types.js';
|
|
4
16
|
import type { IRouteContext } from '../../../core/models/route-context.js';
|
|
5
17
|
|
|
@@ -22,7 +34,7 @@ export interface INetworkProxyOptions {
|
|
|
22
34
|
// Settings for SmartProxy integration
|
|
23
35
|
connectionPoolSize?: number; // Maximum connections to maintain in the pool to each backend
|
|
24
36
|
portProxyIntegration?: boolean; // Flag to indicate this proxy is used by SmartProxy
|
|
25
|
-
useExternalPort80Handler?: boolean; //
|
|
37
|
+
useExternalPort80Handler?: boolean; // @deprecated - use SmartCertManager instead
|
|
26
38
|
// Protocol to use when proxying to backends: HTTP/1.x or HTTP/2
|
|
27
39
|
backendProtocol?: 'http1' | 'http2';
|
|
28
40
|
|