2025-07-02 14:49:23 +00:00
|
|
|
import { EndpointType } from "$lib/server/enums/endpoints"
|
|
|
|
|
import type { NginxProtocol } from "$lib/server/enums/protocols"
|
|
|
|
|
import { doesFileExist } from "$lib/server/utils/filesystem-utils"
|
|
|
|
|
import { isPortAvailable, validatePort } from "$lib/server/utils/ports-utils"
|
|
|
|
|
import type { init } from "../../../hooks.server"
|
2025-07-01 17:59:23 +00:00
|
|
|
import type { IEndpoint } from "./endpoints"
|
|
|
|
|
|
|
|
|
|
// TODO: inherit from a super class
|
|
|
|
|
export interface ISSLTerminationBroker {
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Initialize the Broker and everything related to it
|
|
|
|
|
*/
|
|
|
|
|
init(): Promise<void>
|
|
|
|
|
|
|
|
|
|
// Creation should throw if something goes wrong
|
|
|
|
|
// with reasons why
|
|
|
|
|
createSSLTerminationSimple(
|
|
|
|
|
name: string,
|
|
|
|
|
servicePort: number,
|
|
|
|
|
serviceEndpoint: string,
|
|
|
|
|
certificateURI: string,
|
|
|
|
|
privateKeyURI: string
|
|
|
|
|
): Promise<SSLTermination>
|
|
|
|
|
|
|
|
|
|
createSSLTerminationComplete(
|
|
|
|
|
name: string,
|
|
|
|
|
sslPort: number,
|
|
|
|
|
clearPort: number,
|
|
|
|
|
servicePort: number,
|
|
|
|
|
serviceEndpoint: string,
|
|
|
|
|
certificateURI: string,
|
|
|
|
|
privateKeyURI: string
|
|
|
|
|
): Promise<SSLTermination>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Getting endpoints may be null, react over them
|
|
|
|
|
getSSLTerminationByName(
|
|
|
|
|
name: string
|
|
|
|
|
): Promise<SSLTermination|null>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Throw if something goes wrong
|
|
|
|
|
modifySSLTerminationByName(
|
|
|
|
|
name: string,
|
|
|
|
|
changes: SSLTerminationChanges
|
|
|
|
|
): Promise<SSLTermination>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
deleteSSLTerminationByName(
|
|
|
|
|
name: string
|
|
|
|
|
): Promise<SSLTermination|null>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
getAllSSLTerminations(): Promise<SSLTermination[]>
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* This class represents an SSL Termination Endpoint.
|
|
|
|
|
*
|
|
|
|
|
* While it's possible to create it directly, it is
|
|
|
|
|
* discouraged in favor of the Factory methods as it does
|
|
|
|
|
* more checks than this class
|
|
|
|
|
*/
|
|
|
|
|
export class SSLTermination implements IEndpoint {
|
|
|
|
|
|
|
|
|
|
private static _type: EndpointType = EndpointType.SSL_TERMINATION
|
|
|
|
|
|
|
|
|
|
public path: string
|
|
|
|
|
public hash: string
|
|
|
|
|
public name: string
|
|
|
|
|
public sslPort: number
|
|
|
|
|
public clearPort: number
|
|
|
|
|
public servicePort: number
|
|
|
|
|
public serviceEndpoint: string
|
|
|
|
|
public protocol: NginxProtocol
|
|
|
|
|
public certificateURI: string
|
|
|
|
|
public privateKeyURI: string
|
|
|
|
|
|
|
|
|
|
public get type() {
|
|
|
|
|
return SSLTermination._type
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
constructor(
|
|
|
|
|
name: string,
|
|
|
|
|
path: string,
|
|
|
|
|
hash: string,
|
|
|
|
|
sslPort: number,
|
|
|
|
|
clearPort: number,
|
|
|
|
|
servicePort: number,
|
|
|
|
|
serviceEndpoint: string,
|
|
|
|
|
protocol: NginxProtocol,
|
|
|
|
|
certificateURI: string,
|
|
|
|
|
privateKeyURI: string
|
|
|
|
|
) {
|
|
|
|
|
|
|
|
|
|
validatePort(sslPort)
|
|
|
|
|
validatePort(clearPort)
|
|
|
|
|
validatePort(servicePort)
|
|
|
|
|
|
|
|
|
|
this.name = name
|
|
|
|
|
this.path = path
|
|
|
|
|
this.hash = hash
|
|
|
|
|
this.sslPort = sslPort
|
|
|
|
|
this.clearPort = clearPort
|
|
|
|
|
this.servicePort = servicePort
|
|
|
|
|
this.serviceEndpoint = serviceEndpoint
|
|
|
|
|
this.protocol = protocol
|
|
|
|
|
this.certificateURI = certificateURI
|
|
|
|
|
this.privateKeyURI = privateKeyURI
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type SSLTerminationChanges = {
|
|
|
|
|
name?: string,
|
|
|
|
|
sslPort?: number,
|
|
|
|
|
clearPort?: number,
|
|
|
|
|
servicePort?: number,
|
|
|
|
|
serviceEndpoint?: string,
|
|
|
|
|
protocol?: NginxProtocol,
|
|
|
|
|
certificateURI?: string,
|
|
|
|
|
privateKeyURI?: string
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export class SSLTerminationEndpointApp {
|
|
|
|
|
|
|
|
|
|
private static initialized: boolean = false
|
|
|
|
|
private static broker: ISSLTerminationBroker
|
|
|
|
|
|
|
|
|
|
public static get ready() {
|
|
|
|
|
return SSLTerminationEndpointApp.initialized
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static init(broker: ISSLTerminationBroker) {
|
|
|
|
|
SSLTerminationEndpointApp.assureNotInitialized()
|
|
|
|
|
|
|
|
|
|
SSLTerminationEndpointApp.broker = broker
|
|
|
|
|
broker.init()
|
|
|
|
|
SSLTerminationEndpointApp.initialized = true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Creation should throw if something goes wrong
|
|
|
|
|
// with reasons why
|
|
|
|
|
public static async createSSLTerminationSimple(
|
|
|
|
|
name: string,
|
|
|
|
|
servicePort: number,
|
|
|
|
|
serviceEndpoint: string,
|
|
|
|
|
certificateURI: string,
|
|
|
|
|
privateKeyURI: string
|
|
|
|
|
): Promise<SSLTermination> {
|
|
|
|
|
|
|
|
|
|
SSLTerminationEndpointApp.assureInitialized()
|
|
|
|
|
|
|
|
|
|
return await this.broker.createSSLTerminationSimple(
|
|
|
|
|
name,
|
|
|
|
|
servicePort,
|
|
|
|
|
serviceEndpoint,
|
|
|
|
|
certificateURI,
|
|
|
|
|
privateKeyURI
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static async createSSLTerminationComplete(
|
|
|
|
|
name: string,
|
|
|
|
|
sslPort: number,
|
|
|
|
|
clearPort: number,
|
|
|
|
|
servicePort: number,
|
|
|
|
|
serviceEndpoint: string,
|
|
|
|
|
certificateURI: string,
|
|
|
|
|
privateKeyURI: string
|
|
|
|
|
): Promise<SSLTermination> {
|
|
|
|
|
|
|
|
|
|
SSLTerminationEndpointApp.assureInitialized()
|
|
|
|
|
|
|
|
|
|
return await this.broker.createSSLTerminationComplete(
|
|
|
|
|
name,
|
|
|
|
|
sslPort,
|
|
|
|
|
clearPort,
|
|
|
|
|
servicePort,
|
|
|
|
|
serviceEndpoint,
|
|
|
|
|
certificateURI,
|
|
|
|
|
privateKeyURI
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Getting endpoints may be null, react over them
|
|
|
|
|
public static async getSSLTerminationByName(
|
|
|
|
|
name: string
|
|
|
|
|
): Promise<SSLTermination|null> {
|
|
|
|
|
|
|
|
|
|
SSLTerminationEndpointApp.assureInitialized()
|
|
|
|
|
|
|
|
|
|
return await this.broker.getSSLTerminationByName(
|
|
|
|
|
name
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Throw if something goes wrong
|
|
|
|
|
public static async modifySSLTerminationByName(
|
|
|
|
|
name: string,
|
|
|
|
|
changes: SSLTerminationChanges
|
|
|
|
|
): Promise<SSLTermination> {
|
|
|
|
|
SSLTerminationEndpointApp.assureInitialized()
|
|
|
|
|
|
|
|
|
|
return await this.broker.modifySSLTerminationByName(
|
|
|
|
|
name,
|
|
|
|
|
changes
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public static async deleteSSLTerminationByName(
|
|
|
|
|
name: string
|
|
|
|
|
): Promise<SSLTermination|null> {
|
|
|
|
|
SSLTerminationEndpointApp.assureInitialized()
|
|
|
|
|
|
|
|
|
|
return await this.broker.deleteSSLTerminationByName(
|
|
|
|
|
name
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public static async getAllSSLTerminations(): Promise<SSLTermination[]> {
|
|
|
|
|
SSLTerminationEndpointApp.assureInitialized()
|
|
|
|
|
|
|
|
|
|
return await this.broker.getAllSSLTerminations()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private static assureNotInitialized() {
|
|
|
|
|
if (SSLTerminationEndpointApp.initialized) {
|
|
|
|
|
// UGLY: more specific
|
|
|
|
|
throw new Error("SSLTerminationEndpointApp has been already initialized")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static assureInitialized() {
|
|
|
|
|
if (SSLTerminationEndpointApp.initialized) {
|
|
|
|
|
// UGLY: more specific
|
|
|
|
|
throw new Error("SSLTerminationEndpointApp has not been initialized yet")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|