291 lines
7.2 KiB
TypeScript
291 lines
7.2 KiB
TypeScript
import { EndpointType } from "$lib/server/enums/endpoints"
|
|
import { httpVersion, protocolToString, proxyProtocol, secureProtocol, stringToProtocol, 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, parseDefaultHeader, parseGenericHeader } from "../utils"
|
|
import { hashUtil } from "$lib/server/utils/filesystem-utils"
|
|
import type { IEndpoint } from "$lib/server/classes/endpoints/endpoints-interfaces"
|
|
import { SSLTermination } from "$lib/server/classes/endpoints/ssl-termination-endpoint"
|
|
|
|
// TODO: add broker implementation
|
|
|
|
|
|
export class SSLTerminationFS implements IEndpointFS {
|
|
|
|
private static __type = EndpointType.SSL_TERMINATION
|
|
|
|
public get type() {
|
|
return SSLTerminationFS.__type
|
|
}
|
|
|
|
|
|
public name: string
|
|
public stats: Stats
|
|
public get path() {
|
|
return `${this.protocol}/name.conf`
|
|
}
|
|
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,
|
|
hash: string,
|
|
sslPort: number,
|
|
clearPort: number,
|
|
servicePort: number,
|
|
serviceEndpoint: string,
|
|
protocol: NginxProtocol,
|
|
certificateURI: string,
|
|
privateKeyURI: string
|
|
) {
|
|
|
|
this.name = name
|
|
this.stats = stats
|
|
this.hash = hash
|
|
this.sslPort = sslPort
|
|
this.clearPort = clearPort
|
|
this.servicePort = servicePort
|
|
this.serviceEndpoint = serviceEndpoint
|
|
this.protocol = protocol
|
|
this.certificateURI = certificateURI
|
|
this.privateKeyURI = privateKeyURI
|
|
|
|
}
|
|
|
|
public toIEndpoint(): IEndpoint {
|
|
return new SSLTermination(
|
|
this.name,
|
|
this.path,
|
|
this.sslPort,
|
|
this.clearPort,
|
|
this.servicePort,
|
|
this.serviceEndpoint,
|
|
this.protocol,
|
|
this.certificateURI,
|
|
this.privateKeyURI
|
|
)
|
|
}
|
|
|
|
|
|
headerHash(): string {
|
|
return hashUtil(
|
|
this.createHeader()
|
|
)
|
|
}
|
|
|
|
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
|
|
const defHeader = parseDefaultHeader(conf)
|
|
|
|
const keyValue = parseGenericHeader(conf)
|
|
|
|
const name = keyValue.get("NAME")
|
|
|
|
if (!name) {
|
|
throw new Error("Could not parse")
|
|
}
|
|
|
|
const protocol = stringToProtocol(
|
|
keyValue.get("PROTOCOL") ?? ""
|
|
)
|
|
|
|
const sslPort = Number.parseInt(
|
|
keyValue.get(
|
|
"SSL_PORT"
|
|
) ?? ""
|
|
)
|
|
|
|
validatePort(sslPort)
|
|
|
|
const clearPort = Number.parseInt(
|
|
keyValue.get(
|
|
"CLEAR_PORT"
|
|
) ?? ""
|
|
)
|
|
|
|
validatePort(clearPort)
|
|
|
|
const servicePort = Number.parseInt(
|
|
keyValue.get(
|
|
"SERVICE_PORT"
|
|
) ?? ""
|
|
)
|
|
|
|
validatePort(servicePort)
|
|
|
|
const serviceEndpoint = keyValue.get("SERVICE_ENDPOINT")
|
|
|
|
if (!serviceEndpoint) {
|
|
throw new Error("Could not parse")
|
|
}
|
|
|
|
const certificateURI = keyValue.get("CERTIFICATE_PATH")
|
|
|
|
if (!certificateURI) {
|
|
throw new Error("Could not parse")
|
|
}
|
|
|
|
const privateKeyURI = keyValue.get("KEY_PATH")
|
|
|
|
if (!privateKeyURI) {
|
|
throw new Error("Could not parse")
|
|
}
|
|
|
|
return new SSLTerminationFS(
|
|
name,
|
|
fsHeader.stats,
|
|
fsHeader.hash,
|
|
sslPort,
|
|
clearPort,
|
|
servicePort,
|
|
serviceEndpoint,
|
|
protocol,
|
|
certificateURI,
|
|
privateKeyURI
|
|
)
|
|
|
|
|
|
}
|
|
|
|
|
|
private createHeader() {
|
|
return createHeader(
|
|
this,
|
|
[
|
|
{
|
|
key: "NAME",
|
|
value: this.name
|
|
},
|
|
{
|
|
key: "PROTOCOL",
|
|
value: protocolToString(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")
|
|
}
|
|
|
|
|
|
} |