smartproxy/ts/http/port80/acme-interfaces.ts
2025-05-10 13:59:34 +00:00

169 lines
4.4 KiB
TypeScript

/**
* Type definitions for SmartAcme interfaces used by ChallengeResponder
* These reflect the actual SmartAcme API based on the documentation
*
* Also includes route-based interfaces for Port80Handler to extract domains
* that need certificate management from route configurations.
*/
import * as plugins from '../../plugins.js';
import type { IRouteConfig } from '../../proxies/smart-proxy/models/route-types.js';
/**
* Structure for SmartAcme certificate result
*/
export interface ISmartAcmeCert {
id?: string;
domainName: string;
created?: number | Date | string;
privateKey: string;
publicKey: string;
csr?: string;
validUntil: number | Date | string;
}
/**
* Structure for SmartAcme options
*/
export interface ISmartAcmeOptions {
accountEmail: string;
certManager: ICertManager;
environment: 'production' | 'integration';
challengeHandlers: IChallengeHandler<any>[];
challengePriority?: string[];
retryOptions?: {
retries?: number;
factor?: number;
minTimeoutMs?: number;
maxTimeoutMs?: number;
};
}
/**
* Interface for certificate manager
*/
export interface ICertManager {
init(): Promise<void>;
get(domainName: string): Promise<ISmartAcmeCert | null>;
put(cert: ISmartAcmeCert): Promise<ISmartAcmeCert>;
delete(domainName: string): Promise<void>;
close?(): Promise<void>;
}
/**
* Interface for challenge handler
*/
export interface IChallengeHandler<T> {
getSupportedTypes(): string[];
prepare(ch: T): Promise<void>;
verify?(ch: T): Promise<void>;
cleanup(ch: T): Promise<void>;
checkWetherDomainIsSupported(domain: string): Promise<boolean>;
}
/**
* HTTP-01 challenge type
*/
export interface IHttp01Challenge {
type: string; // 'http-01'
token: string;
keyAuthorization: string;
webPath: string;
}
/**
* HTTP-01 Memory Handler Interface
*/
export interface IHttp01MemoryHandler extends IChallengeHandler<IHttp01Challenge> {
handleRequest(req: plugins.http.IncomingMessage, res: plugins.http.ServerResponse, next?: () => void): void;
}
/**
* SmartAcme main class interface
*/
export interface ISmartAcme {
start(): Promise<void>;
stop(): Promise<void>;
getCertificateForDomain(domain: string): Promise<ISmartAcmeCert>;
on?(event: string, listener: (data: any) => void): void;
eventEmitter?: plugins.EventEmitter;
}
/**
* Port80Handler route options
*/
export interface IPort80RouteOptions {
// The domain for the certificate
domain: string;
// Whether to redirect HTTP to HTTPS
sslRedirect: boolean;
// Whether to enable ACME certificate management
acmeMaintenance: boolean;
// Optional target for forwarding HTTP requests
forward?: {
ip: string;
port: number;
};
// Optional target for forwarding ACME challenge requests
acmeForward?: {
ip: string;
port: number;
};
// Reference to the route that requested this certificate
routeReference?: {
routeId?: string;
routeName?: string;
};
}
/**
* Extract domains that need certificate management from routes
* @param routes Route configurations to extract domains from
* @returns Array of Port80RouteOptions for each domain
*/
export function extractPort80RoutesFromRoutes(routes: IRouteConfig[]): IPort80RouteOptions[] {
const result: IPort80RouteOptions[] = [];
for (const route of routes) {
// Skip routes that don't have domains or TLS configuration
if (!route.match.domains || !route.action.tls) continue;
// Skip routes that don't terminate TLS
if (route.action.tls.mode !== 'terminate' && route.action.tls.mode !== 'terminate-and-reencrypt') continue;
// Only routes with automatic certificates need ACME
if (route.action.tls.certificate !== 'auto') continue;
// Get domains from route
const domains = Array.isArray(route.match.domains)
? route.match.domains
: [route.match.domains];
// Create Port80RouteOptions for each domain
for (const domain of domains) {
// Skip wildcards (we can't get certificates for them)
if (domain.includes('*')) continue;
// Create Port80RouteOptions
const options: IPort80RouteOptions = {
domain,
sslRedirect: true, // Default to true for HTTPS routes
acmeMaintenance: true, // Default to true for auto certificates
// Add route reference
routeReference: {
routeName: route.name
}
};
// Add domain to result
result.push(options);
}
}
return result;
}