BREAKING CHANGE(smartproxy/configuration): Migrate SmartProxy to a fully unified route‐based configuration by removing legacy domain-based settings and conversion code. CertProvisioner, NetworkProxyBridge, and RouteManager now use IRouteConfig exclusively, and related legacy interfaces and files have been removed.
This commit is contained in:
@ -54,8 +54,30 @@ export function createCertificateProvisioner(
|
||||
} = acmeOptions;
|
||||
|
||||
// Create and return the certificate provisioner
|
||||
// Convert domain configs to route configs for the new CertProvisioner
|
||||
const routeConfigs = domainConfigs.map(config => {
|
||||
// Create a basic route config with the minimum required properties
|
||||
return {
|
||||
match: {
|
||||
ports: 443,
|
||||
domains: config.domains
|
||||
},
|
||||
action: {
|
||||
type: 'forward' as const,
|
||||
target: config.forwarding.target,
|
||||
tls: {
|
||||
mode: config.forwarding.type === 'https-terminate-to-https' ?
|
||||
'terminate-and-reencrypt' as const :
|
||||
'terminate' as const,
|
||||
certificate: 'auto' as 'auto'
|
||||
},
|
||||
security: config.forwarding.security
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
return new CertProvisioner(
|
||||
domainConfigs,
|
||||
routeConfigs,
|
||||
port80Handler,
|
||||
networkProxyBridge,
|
||||
certProvider,
|
||||
|
@ -1,4 +1,5 @@
|
||||
import * as plugins from '../../plugins.js';
|
||||
import type { IRouteConfig } from '../../proxies/smart-proxy/models/route-types.js';
|
||||
|
||||
/**
|
||||
* Certificate data structure containing all necessary information
|
||||
@ -12,6 +13,11 @@ export interface ICertificateData {
|
||||
// Optional source and renewal information for event emissions
|
||||
source?: 'static' | 'http01' | 'dns01';
|
||||
isRenewal?: boolean;
|
||||
// Reference to the route that requested this certificate (if available)
|
||||
routeReference?: {
|
||||
routeId?: string;
|
||||
routeName?: string;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@ -29,6 +35,10 @@ export interface ICertificateFailure {
|
||||
domain: string;
|
||||
error: string;
|
||||
isRenewal: boolean;
|
||||
routeReference?: {
|
||||
routeId?: string;
|
||||
routeName?: string;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@ -38,35 +48,46 @@ export interface ICertificateExpiring {
|
||||
domain: string;
|
||||
expiryDate: Date;
|
||||
daysRemaining: number;
|
||||
routeReference?: {
|
||||
routeId?: string;
|
||||
routeName?: string;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Domain forwarding configuration
|
||||
* Route-specific forwarding configuration for ACME challenges
|
||||
*/
|
||||
export interface IForwardConfig {
|
||||
ip: string;
|
||||
port: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Domain-specific forwarding configuration for ACME challenges
|
||||
*/
|
||||
export interface IDomainForwardConfig {
|
||||
export interface IRouteForwardConfig {
|
||||
domain: string;
|
||||
forwardConfig?: IForwardConfig;
|
||||
acmeForwardConfig?: IForwardConfig;
|
||||
target: {
|
||||
host: string;
|
||||
port: number;
|
||||
};
|
||||
sslRedirect?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Domain configuration options
|
||||
* Domain configuration options for Port80Handler
|
||||
*
|
||||
* This is used internally by the Port80Handler to manage domains
|
||||
* but will eventually be replaced with route-based options.
|
||||
*/
|
||||
export interface IDomainOptions {
|
||||
domainName: string;
|
||||
sslRedirect: boolean; // if true redirects the request to port 443
|
||||
acmeMaintenance: boolean; // tries to always have a valid cert for this domain
|
||||
forward?: IForwardConfig; // forwards all http requests to that target
|
||||
acmeForward?: IForwardConfig; // forwards letsencrypt requests to this config
|
||||
forward?: {
|
||||
ip: string;
|
||||
port: number;
|
||||
}; // forwards all http requests to that target
|
||||
acmeForward?: {
|
||||
ip: string;
|
||||
port: number;
|
||||
}; // forwards letsencrypt requests to this config
|
||||
routeReference?: {
|
||||
routeId?: string;
|
||||
routeName?: string;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@ -83,6 +104,6 @@ export interface IAcmeOptions {
|
||||
autoRenew?: boolean; // Whether to automatically renew certificates
|
||||
certificateStore?: string; // Directory to store certificates
|
||||
skipConfiguredCerts?: boolean; // Skip domains with existing certificates
|
||||
domainForwards?: IDomainForwardConfig[]; // Domain-specific forwarding configs
|
||||
routeForwards?: IRouteForwardConfig[]; // Route-specific forwarding configs
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
import * as plugins from '../../plugins.js';
|
||||
import type { IDomainConfig } from '../../forwarding/config/domain-config.js';
|
||||
import type { IRouteConfig } from '../../proxies/smart-proxy/models/route-types.js';
|
||||
import type { ICertificateData, IDomainForwardConfig, IDomainOptions } from '../models/certificate-types.js';
|
||||
import { Port80HandlerEvents, CertProvisionerEvents } from '../events/certificate-events.js';
|
||||
import { Port80Handler } from '../../http/port80/port80-handler.js';
|
||||
@ -28,6 +29,45 @@ export class CertProvisioner extends plugins.EventEmitter {
|
||||
private port80Handler: Port80Handler;
|
||||
private networkProxyBridge: INetworkProxyBridge;
|
||||
private certProvisionFunction?: (domain: string) => Promise<TCertProvisionObject>;
|
||||
|
||||
/**
|
||||
* Extract domains from route configurations for certificate management
|
||||
* @param routes Route configurations
|
||||
*/
|
||||
private extractDomainsFromRoutes(routes: IRouteConfig[]): void {
|
||||
// Process all HTTPS routes that need certificates
|
||||
for (const route of routes) {
|
||||
// Only process routes with TLS termination that need certificates
|
||||
if (route.action.type === 'forward' &&
|
||||
route.action.tls &&
|
||||
(route.action.tls.mode === 'terminate' || route.action.tls.mode === 'terminate-and-reencrypt') &&
|
||||
route.match.domains) {
|
||||
|
||||
// Extract domains from the route
|
||||
const domains = Array.isArray(route.match.domains)
|
||||
? route.match.domains
|
||||
: [route.match.domains];
|
||||
|
||||
// Skip wildcard domains that can't use ACME
|
||||
const eligibleDomains = domains.filter(d => !d.includes('*'));
|
||||
|
||||
if (eligibleDomains.length > 0) {
|
||||
// Create a domain config object for certificate provisioning
|
||||
const domainConfig: IDomainConfig = {
|
||||
domains: eligibleDomains,
|
||||
forwarding: {
|
||||
type: route.action.tls.mode === 'terminate' ? 'https-terminate-to-http' : 'https-terminate-to-https',
|
||||
target: route.action.target || { host: 'localhost', port: 80 },
|
||||
// Add any other required properties from the legacy format
|
||||
security: route.action.security || {}
|
||||
}
|
||||
};
|
||||
|
||||
this.domainConfigs.push(domainConfig);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
private forwardConfigs: IDomainForwardConfig[];
|
||||
private renewThresholdDays: number;
|
||||
private renewCheckIntervalHours: number;
|
||||
@ -47,7 +87,7 @@ export class CertProvisioner extends plugins.EventEmitter {
|
||||
* @param forwardConfigs Domain forwarding configurations for ACME challenges
|
||||
*/
|
||||
constructor(
|
||||
domainConfigs: IDomainConfig[],
|
||||
routeConfigs: IRouteConfig[],
|
||||
port80Handler: Port80Handler,
|
||||
networkProxyBridge: INetworkProxyBridge,
|
||||
certProvider?: (domain: string) => Promise<TCertProvisionObject>,
|
||||
@ -57,7 +97,8 @@ export class CertProvisioner extends plugins.EventEmitter {
|
||||
forwardConfigs: IDomainForwardConfig[] = []
|
||||
) {
|
||||
super();
|
||||
this.domainConfigs = domainConfigs;
|
||||
this.domainConfigs = [];
|
||||
this.extractDomainsFromRoutes(routeConfigs);
|
||||
this.port80Handler = port80Handler;
|
||||
this.networkProxyBridge = networkProxyBridge;
|
||||
this.certProvisionFunction = certProvider;
|
||||
|
Reference in New Issue
Block a user