2025-07-02 18:22:41 +00:00
|
|
|
import { EndpointType } from "$lib/server/enums/endpoints"
|
|
|
|
|
import { httpVersion, proxyProtocol, secureProtocol, type NginxProtocol } from "$lib/server/enums/protocols"
|
|
|
|
|
import { validatePort } from "$lib/server/utils/ports-utils"
|
|
|
|
|
import type { Stats } from "fs"
|
|
|
|
|
import type { FSHeader, IEndpointFS } from "./endpoints"
|
|
|
|
|
import { createHeader } from "../utils"
|
2025-07-03 18:25:50 +00:00
|
|
|
import { hashUtil } from "$lib/server/utils/filesystem-utils"
|
|
|
|
|
|
|
|
|
|
// TODO: add broker implementation
|
|
|
|
|
|
2025-07-02 18:22:41 +00:00
|
|
|
|
|
|
|
|
export class SSLTerminationFS implements IEndpointFS {
|
|
|
|
|
|
|
|
|
|
private static __type = EndpointType.SSL_TERMINATION
|
|
|
|
|
|
|
|
|
|
public get type() {
|
|
|
|
|
return SSLTerminationFS.__type
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public name: string
|
|
|
|
|
public stats: Stats
|
|
|
|
|
public path: string
|
|
|
|
|
public hash: string
|
|
|
|
|
public sslPort: number
|
|
|
|
|
public clearPort: number
|
|
|
|
|
public servicePort: number
|
|
|
|
|
public serviceEndpoint: string
|
|
|
|
|
public protocol: NginxProtocol
|
|
|
|
|
public certificateURI: string
|
|
|
|
|
public privateKeyURI: string
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
constructor(
|
|
|
|
|
name: string,
|
|
|
|
|
stats: Stats,
|
|
|
|
|
path: string,
|
|
|
|
|
hash: string,
|
|
|
|
|
sslPort: number,
|
|
|
|
|
clearPort: number,
|
|
|
|
|
servicePort: number,
|
|
|
|
|
serviceEndpoint: string,
|
|
|
|
|
protocol: NginxProtocol,
|
|
|
|
|
certificateURI: string,
|
|
|
|
|
privateKeyURI: string
|
|
|
|
|
) {
|
|
|
|
|
|
|
|
|
|
this.name = name
|
|
|
|
|
this.stats = stats
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-03 18:25:50 +00:00
|
|
|
|
|
|
|
|
headerHash(): string {
|
|
|
|
|
return hashUtil(
|
|
|
|
|
this.createHeader()
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-02 18:22:41 +00:00
|
|
|
toConf(): string {
|
|
|
|
|
|
|
|
|
|
const HEADER = this.createHeader()
|
|
|
|
|
const SSL_SERVER = this.createSSLServer()
|
|
|
|
|
const CLEAR_SERVER = this.createClearServer()
|
|
|
|
|
|
|
|
|
|
const CONF = HEADER + SSL_SERVER + CLEAR_SERVER
|
|
|
|
|
|
|
|
|
|
return CONF
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ports(): number[]{
|
|
|
|
|
|
|
|
|
|
return [
|
|
|
|
|
this.sslPort,
|
|
|
|
|
this.clearPort
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static parseConf(fsHeader: FSHeader, conf: string) : SSLTerminationFS {
|
|
|
|
|
// TODO: parse header
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private createHeader() {
|
|
|
|
|
return createHeader(
|
|
|
|
|
this,
|
|
|
|
|
[
|
|
|
|
|
{
|
|
|
|
|
key: "NAME",
|
|
|
|
|
value: this.name
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
key: "PROTOCOL",
|
|
|
|
|
value: this.protocol
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
key: "SSL_PORT",
|
|
|
|
|
value: this.sslPort
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
key: "CLEAR_PORT",
|
|
|
|
|
value: this.clearPort
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
key: "SERVICE_PORT",
|
|
|
|
|
value: this.servicePort
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
key: "SERVICE_ENDPOINT",
|
|
|
|
|
value: this.serviceEndpoint
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
key: "CERTIFICATE_PATH",
|
|
|
|
|
value: this.certificateURI
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
key: "KEY_PATH",
|
|
|
|
|
value: this.privateKeyURI
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// UGLY: refactor into a flexible method
|
|
|
|
|
private createSSLServer() {
|
|
|
|
|
|
|
|
|
|
const CLEAR_PROTOCOL = `${this.protocol}`
|
|
|
|
|
const HTTP_VERSION = httpVersion(this.protocol)
|
|
|
|
|
const PROXY_OPTION = proxyProtocol(this.protocol)
|
|
|
|
|
|
|
|
|
|
// UGLY: put to constants
|
|
|
|
|
let conf = [
|
|
|
|
|
"server {\n",
|
|
|
|
|
"\tmore_clear_headers Server;\n",
|
|
|
|
|
`\tlisten ${this.sslPort};`
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
if (HTTP_VERSION !== 1) {
|
|
|
|
|
conf.push(
|
|
|
|
|
`\thttp${HTTP_VERSION} on;`
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TODO: check if we should support less protocols
|
|
|
|
|
conf.push(
|
|
|
|
|
"\n",
|
|
|
|
|
"\tlocation / {",
|
|
|
|
|
`\t\t${PROXY_OPTION} ${CLEAR_PROTOCOL}://127.0.0.1:${this.clearPort};`,
|
|
|
|
|
"\t}",
|
|
|
|
|
"\n",
|
|
|
|
|
`ssl_certificate ${this.certificateURI};`,
|
|
|
|
|
`ssl_certificate_key ${this.privateKeyURI};`,
|
|
|
|
|
"\tssl_protocols TLSv1.1 TLSv1.2 TLSv1.3;",
|
|
|
|
|
"\n",
|
|
|
|
|
"}"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
return conf.join("\n")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private createClearServer() {
|
|
|
|
|
|
|
|
|
|
const SSL_PROTOCOL = secureProtocol(this.protocol)
|
|
|
|
|
const HTTP_VERSION = httpVersion(this.protocol)
|
|
|
|
|
const PROXY_OPTION = proxyProtocol(this.protocol)
|
|
|
|
|
|
|
|
|
|
// UGLY: put to constants
|
|
|
|
|
let conf = [
|
|
|
|
|
"server {\n",
|
|
|
|
|
"\tmore_clear_headers Server;\n",
|
|
|
|
|
`\tlisten ${this.clearPort};`
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
if (HTTP_VERSION !== 1) {
|
|
|
|
|
conf.push(
|
|
|
|
|
`\thttp${HTTP_VERSION} on;`
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TODO: check if we should support less protocols
|
|
|
|
|
conf.push(
|
|
|
|
|
"\n",
|
|
|
|
|
"\tlocation / {",
|
|
|
|
|
`\t\t${PROXY_OPTION} ${SSL_PROTOCOL}://${this.serviceEndpoint}:${this.servicePort};`,
|
|
|
|
|
"\t}",
|
|
|
|
|
"\n",
|
|
|
|
|
"}"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
return conf.join("\n")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|