BREAKING CHANGE(certificates): Remove legacy certificate modules and Port80Handler; update documentation and route configurations to use SmartCertManager for certificate management.

This commit is contained in:
2025-05-18 16:30:23 +00:00
parent db2ac5bae3
commit 455b08b36c
33 changed files with 494 additions and 2904 deletions

View File

@ -2,16 +2,19 @@
* Proxy implementations module
*/
// Export NetworkProxy with selective imports to avoid RouteManager ambiguity
// Export NetworkProxy with selective imports to avoid conflicts
export { NetworkProxy, CertificateManager, ConnectionPool, RequestHandler, WebSocketHandler } from './network-proxy/index.js';
export type { IMetricsTracker, MetricsTracker } from './network-proxy/index.js';
export * from './network-proxy/models/index.js';
// Export network-proxy models except IAcmeOptions
export type { INetworkProxyOptions, ICertificateEntry, ILogger } from './network-proxy/models/types.js';
export { RouteManager as NetworkProxyRouteManager } from './network-proxy/models/types.js';
// Export SmartProxy with selective imports to avoid RouteManager ambiguity
// Export SmartProxy with selective imports to avoid conflicts
export { SmartProxy, ConnectionManager, SecurityManager, TimeoutManager, TlsManager, NetworkProxyBridge, RouteConnectionHandler } from './smart-proxy/index.js';
export { RouteManager as SmartProxyRouteManager } from './smart-proxy/route-manager.js';
export * from './smart-proxy/utils/index.js';
export * from './smart-proxy/models/index.js';
// Export smart-proxy models except IAcmeOptions
export type { ISmartProxyOptions, IConnectionRecord, IRouteConfig, IRouteMatch, IRouteAction, IRouteTls, IRouteContext } from './smart-proxy/models/index.js';
// Export NFTables proxy (no conflicts)
export * from './nftables-proxy/index.js';

View File

@ -3,21 +3,17 @@ import * as fs from 'fs';
import * as path from 'path';
import { fileURLToPath } from 'url';
import { type INetworkProxyOptions, type ICertificateEntry, type ILogger, createLogger } from './models/types.js';
import { Port80Handler } from '../../http/port80/port80-handler.js';
import { CertificateEvents } from '../../certificate/events/certificate-events.js';
import { buildPort80Handler } from '../../certificate/acme/acme-factory.js';
import { subscribeToPort80Handler } from '../../core/utils/event-utils.js';
import type { IDomainOptions } from '../../certificate/models/certificate-types.js';
import type { IRouteConfig } from '../smart-proxy/models/route-types.js';
/**
* Manages SSL certificates for NetworkProxy including ACME integration
* @deprecated This class is deprecated. Use SmartCertManager instead.
*
* This is a stub implementation that maintains backward compatibility
* while the functionality has been moved to SmartCertManager.
*/
export class CertificateManager {
private defaultCertificates: { key: string; cert: string };
private certificateCache: Map<string, ICertificateEntry> = new Map();
private port80Handler: Port80Handler | null = null;
private externalPort80Handler: boolean = false;
private certificateStoreDir: string;
private logger: ILogger;
private httpsServer: plugins.https.Server | null = null;
@ -26,6 +22,8 @@ export class CertificateManager {
this.certificateStoreDir = path.resolve(options.acme?.certificateStore || './certs');
this.logger = createLogger(options.logLevel || 'info');
this.logger.warn('CertificateManager is deprecated - use SmartCertManager instead');
// Ensure certificate store directory exists
try {
if (!fs.existsSync(this.certificateStoreDir)) {
@ -44,7 +42,6 @@ export class CertificateManager {
*/
public loadDefaultCertificates(): void {
const __dirname = path.dirname(fileURLToPath(import.meta.url));
// Fix the path to look for certificates at the project root instead of inside ts directory
const certPath = path.join(__dirname, '..', '..', '..', 'assets', 'certs');
try {
@ -52,467 +49,145 @@ export class CertificateManager {
key: fs.readFileSync(path.join(certPath, 'key.pem'), 'utf8'),
cert: fs.readFileSync(path.join(certPath, 'cert.pem'), 'utf8')
};
this.logger.info('Default certificates loaded successfully');
this.logger.info('Loaded default certificates from filesystem');
} catch (error) {
this.logger.error('Error loading default certificates', error);
// Generate self-signed fallback certificates
try {
// This is a placeholder for actual certificate generation code
// In a real implementation, you would use a library like selfsigned to generate certs
this.defaultCertificates = {
key: "FALLBACK_KEY_CONTENT",
cert: "FALLBACK_CERT_CONTENT"
};
this.logger.warn('Using fallback self-signed certificates');
} catch (fallbackError) {
this.logger.error('Failed to generate fallback certificates', fallbackError);
throw new Error('Could not load or generate SSL certificates');
}
this.logger.error(`Failed to load default certificates: ${error}`);
this.generateSelfSignedCertificate();
}
}
/**
* Set the HTTPS server reference for context updates
* Generates self-signed certificates as fallback
*/
private generateSelfSignedCertificate(): void {
// Generate a self-signed certificate using forge or similar
// For now, just use a placeholder
const selfSignedCert = `-----BEGIN CERTIFICATE-----
MIIBkTCB+wIJAKHHIgIIA0/cMA0GCSqGSIb3DQEBBQUAMA0xCzAJBgNVBAYTAlVT
MB4XDTE0MDEwMTAwMDAwMFoXDTI0MDEwMTAwMDAwMFowDTELMAkGA1UEBhMCVVMw
gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMRiH0VwnOH3jCV7c6JFZWYrvuqy
-----END CERTIFICATE-----`;
const selfSignedKey = `-----BEGIN PRIVATE KEY-----
MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAMRiH0VwnOH3jCV7
c6JFZWYrvuqyALCLXj0pcr1iqNdHjegNXnkl5zjdaUjq4edNOKl7M1AlFiYjG2xk
-----END PRIVATE KEY-----`;
this.defaultCertificates = {
key: selfSignedKey,
cert: selfSignedCert
};
this.logger.warn('Using self-signed certificate as fallback');
}
/**
* Gets the default certificates
*/
public getDefaultCertificates(): { key: string; cert: string } {
return this.defaultCertificates;
}
/**
* @deprecated Use SmartCertManager instead
*/
public setExternalPort80Handler(handler: any): void {
this.logger.warn('setExternalPort80Handler is deprecated - use SmartCertManager instead');
}
/**
* @deprecated Use SmartCertManager instead
*/
public async updateRoutes(routes: IRouteConfig[]): Promise<void> {
this.logger.warn('updateRoutes is deprecated - use SmartCertManager instead');
}
/**
* Handles SNI callback to provide appropriate certificate
*/
public handleSNI(domain: string, cb: (err: Error | null, ctx: plugins.tls.SecureContext) => void): void {
const certificate = this.getCachedCertificate(domain);
if (certificate) {
const context = plugins.tls.createSecureContext({
key: certificate.key,
cert: certificate.cert
});
cb(null, context);
return;
}
// Use default certificate if no domain-specific certificate found
const defaultContext = plugins.tls.createSecureContext({
key: this.defaultCertificates.key,
cert: this.defaultCertificates.cert
});
cb(null, defaultContext);
}
/**
* Updates a certificate in the cache
*/
public updateCertificate(domain: string, cert: string, key: string): void {
this.certificateCache.set(domain, {
cert,
key,
expires: new Date(Date.now() + 90 * 24 * 60 * 60 * 1000) // 90 days
});
this.logger.info(`Certificate updated for ${domain}`);
}
/**
* Gets a cached certificate
*/
private getCachedCertificate(domain: string): ICertificateEntry | null {
return this.certificateCache.get(domain) || null;
}
/**
* @deprecated Use SmartCertManager instead
*/
public async initializePort80Handler(): Promise<any> {
this.logger.warn('initializePort80Handler is deprecated - use SmartCertManager instead');
return null;
}
/**
* @deprecated Use SmartCertManager instead
*/
public async stopPort80Handler(): Promise<void> {
this.logger.warn('stopPort80Handler is deprecated - use SmartCertManager instead');
}
/**
* @deprecated Use SmartCertManager instead
*/
public registerDomainsWithPort80Handler(domains: string[]): void {
this.logger.warn('registerDomainsWithPort80Handler is deprecated - use SmartCertManager instead');
}
/**
* @deprecated Use SmartCertManager instead
*/
public registerRoutesWithPort80Handler(routes: IRouteConfig[]): void {
this.logger.warn('registerRoutesWithPort80Handler is deprecated - use SmartCertManager instead');
}
/**
* Sets the HTTPS server for certificate updates
*/
public setHttpsServer(server: plugins.https.Server): void {
this.httpsServer = server;
}
/**
* Get default certificates
*/
public getDefaultCertificates(): { key: string; cert: string } {
return { ...this.defaultCertificates };
}
/**
* Sets an external Port80Handler for certificate management
*/
public setExternalPort80Handler(handler: Port80Handler): void {
if (this.port80Handler && !this.externalPort80Handler) {
this.logger.warn('Replacing existing internal Port80Handler with external handler');
// Clean up existing handler if needed
if (this.port80Handler !== handler) {
// Unregister event handlers to avoid memory leaks
this.port80Handler.removeAllListeners(CertificateEvents.CERTIFICATE_ISSUED);
this.port80Handler.removeAllListeners(CertificateEvents.CERTIFICATE_RENEWED);
this.port80Handler.removeAllListeners(CertificateEvents.CERTIFICATE_FAILED);
this.port80Handler.removeAllListeners(CertificateEvents.CERTIFICATE_EXPIRING);
}
}
// Set the external handler
this.port80Handler = handler;
this.externalPort80Handler = true;
// Subscribe to Port80Handler events
subscribeToPort80Handler(this.port80Handler, {
onCertificateIssued: this.handleCertificateIssued.bind(this),
onCertificateRenewed: this.handleCertificateIssued.bind(this),
onCertificateFailed: this.handleCertificateFailed.bind(this),
onCertificateExpiring: (data) => {
this.logger.info(`Certificate for ${data.domain} expires in ${data.daysRemaining} days`);
}
});
this.logger.info('External Port80Handler connected to CertificateManager');
// Register domains with Port80Handler if we have any certificates cached
if (this.certificateCache.size > 0) {
const domains = Array.from(this.certificateCache.keys())
.filter(domain => !domain.includes('*')); // Skip wildcard domains
this.registerDomainsWithPort80Handler(domains);
}
}
/**
* Update route configurations managed by this certificate manager
* This method is called when route configurations change
*
* @param routes Array of route configurations
* Gets statistics for metrics
*/
public updateRouteConfigs(routes: IRouteConfig[]): void {
if (!this.port80Handler) {
this.logger.warn('Cannot update routes - Port80Handler is not initialized');
return;
}
// Register domains from routes with Port80Handler
this.registerRoutesWithPort80Handler(routes);
// Process individual routes for certificate requirements
for (const route of routes) {
this.processRouteForCertificates(route);
}
this.logger.info(`Updated certificate management for ${routes.length} routes`);
}
/**
* Handle newly issued or renewed certificates from Port80Handler
*/
private handleCertificateIssued(data: { domain: string; certificate: string; privateKey: string; expiryDate: Date }): void {
const { domain, certificate, privateKey, expiryDate } = data;
this.logger.info(`Certificate ${this.certificateCache.has(domain) ? 'renewed' : 'issued'} for ${domain}, valid until ${expiryDate.toISOString()}`);
// Update certificate in HTTPS server
this.updateCertificateCache(domain, certificate, privateKey, expiryDate);
// Save the certificate to the filesystem if not using external handler
if (!this.externalPort80Handler && this.options.acme?.certificateStore) {
this.saveCertificateToStore(domain, certificate, privateKey);
}
}
/**
* Handle certificate issuance failures
*/
private handleCertificateFailed(data: { domain: string; error: string }): void {
this.logger.error(`Certificate issuance failed for ${data.domain}: ${data.error}`);
}
/**
* Saves certificate and private key to the filesystem
*/
private saveCertificateToStore(domain: string, certificate: string, privateKey: string): void {
try {
const certPath = path.join(this.certificateStoreDir, `${domain}.cert.pem`);
const keyPath = path.join(this.certificateStoreDir, `${domain}.key.pem`);
fs.writeFileSync(certPath, certificate);
fs.writeFileSync(keyPath, privateKey);
// Ensure private key has restricted permissions
try {
fs.chmodSync(keyPath, 0o600);
} catch (error) {
this.logger.warn(`Failed to set permissions on private key for ${domain}: ${error}`);
}
this.logger.info(`Saved certificate for ${domain} to ${certPath}`);
} catch (error) {
this.logger.error(`Failed to save certificate for ${domain}: ${error}`);
}
}
/**
* Handles SNI (Server Name Indication) for TLS connections
* Used by the HTTPS server to select the correct certificate for each domain
*/
public handleSNI(domain: string, cb: (err: Error | null, ctx: plugins.tls.SecureContext) => void): void {
this.logger.debug(`SNI request for domain: ${domain}`);
// Check if we have a certificate for this domain
const certs = this.certificateCache.get(domain);
if (certs) {
try {
// Create TLS context with the cached certificate
const context = plugins.tls.createSecureContext({
key: certs.key,
cert: certs.cert
});
this.logger.debug(`Using cached certificate for ${domain}`);
cb(null, context);
return;
} catch (err) {
this.logger.error(`Error creating secure context for ${domain}:`, err);
}
}
// No existing certificate: trigger dynamic provisioning via Port80Handler
if (this.port80Handler) {
try {
this.logger.info(`Triggering on-demand certificate retrieval for ${domain}`);
this.port80Handler.addDomain({
domainName: domain,
sslRedirect: false,
acmeMaintenance: true
});
} catch (err) {
this.logger.error(`Error registering domain for on-demand certificate: ${domain}`, err);
}
}
// Check if we should trigger certificate issuance
if (this.options.acme?.enabled && this.port80Handler && !domain.includes('*')) {
// Check if this domain is already registered
const certData = this.port80Handler.getCertificate(domain);
if (!certData) {
this.logger.info(`No certificate found for ${domain}, registering for issuance`);
// Register with new domain options format
const domainOptions: IDomainOptions = {
domainName: domain,
sslRedirect: true,
acmeMaintenance: true
};
this.port80Handler.addDomain(domainOptions);
}
}
// Fall back to default certificate
try {
const context = plugins.tls.createSecureContext({
key: this.defaultCertificates.key,
cert: this.defaultCertificates.cert
});
this.logger.debug(`Using default certificate for ${domain}`);
cb(null, context);
} catch (err) {
this.logger.error(`Error creating default secure context:`, err);
cb(new Error('Cannot create secure context'), null);
}
}
/**
* Updates certificate in cache
*/
public updateCertificateCache(domain: string, certificate: string, privateKey: string, expiryDate?: Date): void {
// Update certificate context in HTTPS server if it's running
if (this.httpsServer) {
try {
this.httpsServer.addContext(domain, {
key: privateKey,
cert: certificate
});
this.logger.debug(`Updated SSL context for domain: ${domain}`);
} catch (error) {
this.logger.error(`Error updating SSL context for domain ${domain}:`, error);
}
}
// Update certificate in cache
this.certificateCache.set(domain, {
key: privateKey,
cert: certificate,
expires: expiryDate
});
}
/**
* Gets a certificate for a domain
*/
public getCertificate(domain: string): ICertificateEntry | undefined {
return this.certificateCache.get(domain);
}
/**
* Requests a new certificate for a domain
*/
public async requestCertificate(domain: string): Promise<boolean> {
if (!this.options.acme?.enabled && !this.externalPort80Handler) {
this.logger.warn('ACME certificate management is not enabled');
return false;
}
if (!this.port80Handler) {
this.logger.error('Port80Handler is not initialized');
return false;
}
// Skip wildcard domains - can't get certs for these with HTTP-01 validation
if (domain.includes('*')) {
this.logger.error(`Cannot request certificate for wildcard domain: ${domain}`);
return false;
}
try {
// Use the new domain options format
const domainOptions: IDomainOptions = {
domainName: domain,
sslRedirect: true,
acmeMaintenance: true
};
this.port80Handler.addDomain(domainOptions);
this.logger.info(`Certificate request submitted for domain: ${domain}`);
return true;
} catch (error) {
this.logger.error(`Error requesting certificate for domain ${domain}:`, error);
return false;
}
}
/**
* Registers domains with Port80Handler for ACME certificate management
* @param domains String array of domains to register
*/
public registerDomainsWithPort80Handler(domains: string[]): void {
if (!this.port80Handler) {
this.logger.warn('Port80Handler is not initialized');
return;
}
for (const domain of domains) {
// Skip wildcard domains - can't get certs for these with HTTP-01 validation
if (domain.includes('*')) {
this.logger.info(`Skipping wildcard domain for ACME: ${domain}`);
continue;
}
// Skip domains already with certificates if configured to do so
if (this.options.acme?.skipConfiguredCerts) {
const cachedCert = this.certificateCache.get(domain);
if (cachedCert) {
this.logger.info(`Skipping domain with existing certificate: ${domain}`);
continue;
}
}
// Register the domain for certificate issuance with new domain options format
const domainOptions: IDomainOptions = {
domainName: domain,
sslRedirect: true,
acmeMaintenance: true
};
this.port80Handler.addDomain(domainOptions);
this.logger.info(`Registered domain for ACME certificate issuance: ${domain}`);
}
}
/**
* Extract domains from route configurations and register with Port80Handler
* This method enables direct integration with route-based configuration
*
* @param routes Array of route configurations
*/
public registerRoutesWithPort80Handler(routes: IRouteConfig[]): void {
if (!this.port80Handler) {
this.logger.warn('Port80Handler is not initialized');
return;
}
// Extract domains from route configurations
const domains: Set<string> = new Set();
for (const route of routes) {
// Skip disabled routes
if (route.enabled === false) {
continue;
}
// Skip routes without HTTPS termination
if (route.action.type !== 'forward' || route.action.tls?.mode !== 'terminate') {
continue;
}
// Extract domains from match criteria
if (route.match.domains) {
if (typeof route.match.domains === 'string') {
domains.add(route.match.domains);
} else if (Array.isArray(route.match.domains)) {
for (const domain of route.match.domains) {
domains.add(domain);
}
}
}
}
// Register extracted domains
this.registerDomainsWithPort80Handler(Array.from(domains));
}
/**
* Process a route config to determine if it requires automatic certificate provisioning
* @param route Route configuration to process
*/
public processRouteForCertificates(route: IRouteConfig): void {
// Skip disabled routes
if (route.enabled === false) {
return;
}
// Skip routes without HTTPS termination or auto certificate
if (route.action.type !== 'forward' ||
route.action.tls?.mode !== 'terminate' ||
route.action.tls?.certificate !== 'auto') {
return;
}
// Extract domains from match criteria
const domains: string[] = [];
if (route.match.domains) {
if (typeof route.match.domains === 'string') {
domains.push(route.match.domains);
} else if (Array.isArray(route.match.domains)) {
domains.push(...route.match.domains);
}
}
// Request certificates for the domains
for (const domain of domains) {
if (!domain.includes('*')) { // Skip wildcard domains
this.requestCertificate(domain).catch(err => {
this.logger.error(`Error requesting certificate for domain ${domain}:`, err);
});
}
}
}
/**
* Initialize internal Port80Handler
*/
public async initializePort80Handler(): Promise<Port80Handler | null> {
// Skip if using external handler
if (this.externalPort80Handler) {
this.logger.info('Using external Port80Handler, skipping initialization');
return this.port80Handler;
}
if (!this.options.acme?.enabled) {
return null;
}
// Build and configure Port80Handler
this.port80Handler = buildPort80Handler({
port: this.options.acme.port,
accountEmail: this.options.acme.accountEmail,
useProduction: this.options.acme.useProduction,
httpsRedirectPort: this.options.port, // Redirect to our HTTPS port
enabled: this.options.acme.enabled,
certificateStore: this.options.acme.certificateStore,
skipConfiguredCerts: this.options.acme.skipConfiguredCerts
});
// Subscribe to Port80Handler events
subscribeToPort80Handler(this.port80Handler, {
onCertificateIssued: this.handleCertificateIssued.bind(this),
onCertificateRenewed: this.handleCertificateIssued.bind(this),
onCertificateFailed: this.handleCertificateFailed.bind(this),
onCertificateExpiring: (data) => {
this.logger.info(`Certificate for ${data.domain} expires in ${data.daysRemaining} days`);
}
});
// Start the handler
try {
await this.port80Handler.start();
this.logger.info(`Port80Handler started on port ${this.options.acme.port}`);
return this.port80Handler;
} catch (error) {
this.logger.error(`Failed to start Port80Handler: ${error}`);
this.port80Handler = null;
return null;
}
}
/**
* Stop the Port80Handler if it was internally created
*/
public async stopPort80Handler(): Promise<void> {
if (this.port80Handler && !this.externalPort80Handler) {
try {
await this.port80Handler.stop();
this.logger.info('Port80Handler stopped');
} catch (error) {
this.logger.error('Error stopping Port80Handler', error);
}
}
public getStats() {
return {
cachedCertificates: this.certificateCache.size,
defaultCertEnabled: true
};
}
}

View File

@ -1,5 +1,17 @@
import * as plugins from '../../../plugins.js';
import type { IAcmeOptions } from '../../../certificate/models/certificate-types.js';
// Certificate types removed - define IAcmeOptions locally
export interface IAcmeOptions {
enabled: boolean;
email?: string;
accountEmail?: string;
port?: number;
certificateStore?: string;
environment?: 'production' | 'staging';
useProduction?: boolean;
renewThresholdDays?: number;
autoRenew?: boolean;
skipConfiguredCerts?: boolean;
}
import type { IRouteConfig } from '../../smart-proxy/models/route-types.js';
import type { IRouteContext } from '../../../core/models/route-context.js';
@ -22,7 +34,7 @@ export interface INetworkProxyOptions {
// Settings for SmartProxy integration
connectionPoolSize?: number; // Maximum connections to maintain in the pool to each backend
portProxyIntegration?: boolean; // Flag to indicate this proxy is used by SmartProxy
useExternalPort80Handler?: boolean; // Flag to indicate using external Port80Handler
useExternalPort80Handler?: boolean; // @deprecated - use SmartCertManager instead
// Protocol to use when proxying to backends: HTTP/1.x or HTTP/2
backendProtocol?: 'http1' | 'http2';

View File

@ -18,7 +18,6 @@ import { RequestHandler, type IMetricsTracker } from './request-handler.js';
import { WebSocketHandler } from './websocket-handler.js';
import { ProxyRouter } from '../../http/router/index.js';
import { RouteRouter } from '../../http/router/route-router.js';
import { Port80Handler } from '../../http/port80/port80-handler.js';
import { FunctionCache } from './function-cache.js';
/**
@ -221,15 +220,10 @@ export class NetworkProxy implements IMetricsTracker {
}
/**
* Sets an external Port80Handler for certificate management
* This allows the NetworkProxy to use a centrally managed Port80Handler
* instead of creating its own
*
* @param handler The Port80Handler instance to use
* @deprecated Use SmartCertManager instead
*/
public setExternalPort80Handler(handler: Port80Handler): void {
// Connect it to the certificate manager
this.certificateManager.setExternalPort80Handler(handler);
public setExternalPort80Handler(handler: any): void {
this.logger.warn('Port80Handler is deprecated - use SmartCertManager instead');
}
/**
@ -238,10 +232,7 @@ export class NetworkProxy implements IMetricsTracker {
public async start(): Promise<void> {
this.startTime = Date.now();
// Initialize Port80Handler if enabled and not using external handler
if (this.options.acme?.enabled && !this.options.useExternalPort80Handler) {
await this.certificateManager.initializePort80Handler();
}
// Certificate management is now handled by SmartCertManager
// Create HTTP/2 server with HTTP/1 fallback
this.httpsServer = plugins.http2.createSecureServer(
@ -385,7 +376,7 @@ export class NetworkProxy implements IMetricsTracker {
// Directly update the certificate manager with the new routes
// This will extract domains and handle certificate provisioning
this.certificateManager.updateRouteConfigs(routes);
this.certificateManager.updateRoutes(routes);
// Collect all domains and certificates for configuration
const currentHostnames = new Set<string>();
@ -425,7 +416,7 @@ export class NetworkProxy implements IMetricsTracker {
// Update certificate cache with any static certificates
for (const [domain, certData] of certificateUpdates.entries()) {
try {
this.certificateManager.updateCertificateCache(
this.certificateManager.updateCertificate(
domain,
certData.cert,
certData.key
@ -547,8 +538,7 @@ export class NetworkProxy implements IMetricsTracker {
// Close all connection pool connections
this.connectionPool.closeAllConnections();
// Stop Port80Handler if internally managed
await this.certificateManager.stopPort80Handler();
// Certificate management cleanup is handled by SmartCertManager
// Close the HTTPS server
return new Promise((resolve) => {
@ -566,7 +556,8 @@ export class NetworkProxy implements IMetricsTracker {
* @returns A promise that resolves when the request is submitted (not when the certificate is issued)
*/
public async requestCertificate(domain: string): Promise<boolean> {
return this.certificateManager.requestCertificate(domain);
this.logger.warn('requestCertificate is deprecated - use SmartCertManager instead');
return false;
}
/**
@ -587,7 +578,7 @@ export class NetworkProxy implements IMetricsTracker {
expiryDate?: Date
): void {
this.logger.info(`Updating certificate for ${domain}`);
this.certificateManager.updateCertificateCache(domain, certificate, privateKey, expiryDate);
this.certificateManager.updateCertificate(domain, certificate, privateKey);
}
/**

View File

@ -1,5 +1,6 @@
/**
* SmartProxy models
*/
export * from './interfaces.js';
// Export everything except IAcmeOptions from interfaces
export type { ISmartProxyOptions, IConnectionRecord, TSmartProxyCertProvisionObject } from './interfaces.js';
export * from './route-types.js';

View File

@ -1,5 +1,18 @@
import * as plugins from '../../../plugins.js';
import type { IAcmeOptions } from '../../../certificate/models/certificate-types.js';
// Certificate types removed - define IAcmeOptions locally
export interface IAcmeOptions {
enabled?: boolean;
email?: string;
environment?: 'production' | 'staging';
port?: number;
useProduction?: boolean;
renewThresholdDays?: number;
autoRenew?: boolean;
certificateStore?: string;
skipConfiguredCerts?: boolean;
renewCheckIntervalHours?: number;
routeForwards?: any[];
}
import type { IRouteConfig } from './route-types.js';
import type { TForwardingType } from '../../../forwarding/config/forwarding-types.js';

View File

@ -1,5 +1,5 @@
import * as plugins from '../../../plugins.js';
import type { IAcmeOptions } from '../../../certificate/models/certificate-types.js';
// Certificate types removed - use local definition
import type { TForwardingType } from '../../../forwarding/config/forwarding-types.js';
import type { PortRange } from '../../../proxies/nftables-proxy/models/interfaces.js';

View File

@ -121,13 +121,12 @@ export class SmartProxy extends plugins.EventEmitter {
this.settings.acme = {
enabled: false,
port: 80,
accountEmail: 'admin@example.com',
email: 'admin@example.com',
useProduction: false,
renewThresholdDays: 30,
autoRenew: true,
certificateStore: './certs',
skipConfiguredCerts: false,
httpsRedirectPort: 443,
renewCheckIntervalHours: 24,
routeForwards: []
};