Merge remote-tracking branch 'origin/main' into feat/allow-k8-dynamic-secret-multi-namespace-and-others

This commit is contained in:
Sheen Capadngan
2025-06-11 14:28:15 +08:00
7 changed files with 58 additions and 44 deletions
+32 -15
View File
@@ -149,8 +149,8 @@ const setupProxyServer = async ({
protocol = GatewayProxyProtocol.Tcp,
httpsAgent
}: {
targetHost: string;
targetPort: number;
targetHost?: string;
targetPort?: number;
relayPort: number;
relayHost: string;
tlsOptions: TGatewayTlsOptions;
@@ -183,27 +183,44 @@ const setupProxyServer = async ({
let command: string;
if (protocol === GatewayProxyProtocol.Http) {
const targetUrl = `${targetHost}:${targetPort}`; // note(daniel): targetHost MUST include the scheme (https|http)
command = `FORWARD-HTTP ${targetUrl}`;
logger.debug(`Using HTTP proxy mode: ${command.trim()}`);
if (!targetHost && !targetPort) {
command = `FORWARD-HTTP`;
logger.debug(`Using HTTP proxy mode, no target URL provided [command=${command.trim()}]`);
} else {
if (!targetHost || targetPort === undefined) {
throw new BadRequestError({
message: `Target host and port are required for HTTP proxy mode with custom target`
});
}
// extract ca certificate from httpsAgent if present
if (httpsAgent && targetHost.startsWith("https://")) {
const agentOptions = httpsAgent.options;
if (agentOptions && agentOptions.ca) {
const caCert = Array.isArray(agentOptions.ca) ? agentOptions.ca.join("\n") : agentOptions.ca;
const caB64 = Buffer.from(caCert as string).toString("base64");
command += ` ca=${caB64}`;
const targetUrl = `${targetHost}:${targetPort}`; // note(daniel): targetHost MUST include the scheme (https|http)
command = `FORWARD-HTTP ${targetUrl}`;
logger.debug(`Using HTTP proxy mode, custom target URL provided [command=${command.trim()}]`);
const rejectUnauthorized = agentOptions.rejectUnauthorized !== false;
command += ` verify=${rejectUnauthorized}`;
// extract ca certificate from httpsAgent if present
if (httpsAgent && targetHost.startsWith("https://")) {
const agentOptions = httpsAgent.options;
if (agentOptions && agentOptions.ca) {
const caCert = Array.isArray(agentOptions.ca) ? agentOptions.ca.join("\n") : agentOptions.ca;
const caB64 = Buffer.from(caCert as string).toString("base64");
command += ` ca=${caB64}`;
logger.debug(`Using HTTP proxy mode [command=${command.trim()}]`);
const rejectUnauthorized = agentOptions.rejectUnauthorized !== false;
command += ` verify=${rejectUnauthorized}`;
logger.debug(`Using HTTP proxy mode, custom target URL provided [command=${command.trim()}]`);
}
}
}
command += "\n";
} else if (protocol === GatewayProxyProtocol.Tcp) {
if (!targetHost || !targetPort) {
throw new BadRequestError({
message: `Target host and port are required for TCP proxy mode`
});
}
// For TCP mode, send FORWARD-TCP with host:port
command = `FORWARD-TCP ${targetHost}:${targetPort}\n`;
logger.debug(`Using TCP proxy mode: ${command.trim()}`);
+2 -2
View File
@@ -15,8 +15,8 @@ export enum GatewayHttpProxyActions {
}
export interface IGatewayProxyOptions {
targetHost: string;
targetPort: number;
targetHost?: string;
targetPort?: number;
relayHost: string;
relayPort: number;
tlsOptions: TGatewayTlsOptions;
+6 -3
View File
@@ -57,9 +57,12 @@ export const registerServeUI = async (
reply.callNotFound();
return;
}
// reference: https://github.com/fastify/fastify-static?tab=readme-ov-file#managing-cache-control-headers
// to avoid ui bundle skew on new deployment
return reply.sendFile("index.html", { maxAge: 0, immutable: false });
// This should help avoid caching any chunks (temp fix)
void reply.header("Cache-Control", "no-cache, no-store, must-revalidate, private, max-age=0");
void reply.header("Pragma", "no-cache");
void reply.header("Expires", "0");
return reply.sendFile("index.html");
}
});
}
@@ -120,7 +120,7 @@ export const folderCommitChangesDALFactory = (db: TDbClient) => {
return docs.map((doc) => {
// Determine if this is a secret or folder change based on populated fields
if (doc.secretKey && doc.secretVersion && doc.secretId) {
if (doc.secretKey && doc.secretVersion !== null && doc.secretId) {
return {
...doc,
resourceType: "secret",
@@ -168,7 +168,7 @@ export const folderCommitChangesDALFactory = (db: TDbClient) => {
);
return docs
.filter((doc) => doc.secretKey && doc.secretVersion && doc.secretId)
.filter((doc) => doc.secretKey && doc.secretVersion !== null && doc.secretId)
.map(
(doc): SecretCommitChange => ({
...doc,
@@ -209,7 +209,7 @@ export const folderCommitChangesDALFactory = (db: TDbClient) => {
);
return docs
.filter((doc) => doc.folderName && doc.folderVersion && doc.folderChangeId)
.filter((doc) => doc.folderName && doc.folderVersion !== null && doc.folderChangeId)
.map(
(doc): FolderCommitChange => ({
...doc,
@@ -72,8 +72,8 @@ export const identityKubernetesAuthServiceFactory = ({
const $gatewayProxyWrapper = async <T>(
inputs: {
gatewayId: string;
targetHost: string;
targetPort: number;
targetHost?: string;
targetPort?: number;
caCert?: string;
reviewTokenThroughGateway: boolean;
},
@@ -286,8 +286,6 @@ export const identityKubernetesAuthServiceFactory = ({
data = await $gatewayProxyWrapper(
{
gatewayId: identityKubernetesAuth.gatewayId,
targetHost: `/`, // note(daniel): the targetURL will be constructed as `/:0`, which the gateway will handle as a special case, by replacing the /:0, with the internal kubernetes base URL (only when the action header is set to `GatewayHttpProxyActions.UseGatewayK8sServiceAccount`)
targetPort: 0,
reviewTokenThroughGateway: true
},
tokenReviewCallbackThroughGateway