mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-06 16:27:46 +00:00
Merge pull request #3210 from akhilmhdh/fix/gateway-patch-up
Gateway patch up
This commit is contained in:
@@ -96,6 +96,7 @@ export const pingGatewayAndVerify = async ({
|
|||||||
error: err as Error
|
error: err as Error
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
for (let attempt = 1; attempt <= maxRetries; attempt += 1) {
|
for (let attempt = 1; attempt <= maxRetries; attempt += 1) {
|
||||||
try {
|
try {
|
||||||
const stream = quicClient.connection.newStream("bidi");
|
const stream = quicClient.connection.newStream("bidi");
|
||||||
@@ -108,17 +109,13 @@ export const pingGatewayAndVerify = async ({
|
|||||||
const { value, done } = await reader.read();
|
const { value, done } = await reader.read();
|
||||||
|
|
||||||
if (done) {
|
if (done) {
|
||||||
throw new BadRequestError({
|
throw new Error("Gateway closed before receiving PONG");
|
||||||
message: "Gateway closed before receiving PONG"
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const response = Buffer.from(value).toString();
|
const response = Buffer.from(value).toString();
|
||||||
|
|
||||||
if (response !== "PONG\n" && response !== "PONG") {
|
if (response !== "PONG\n" && response !== "PONG") {
|
||||||
throw new BadRequestError({
|
throw new Error(`Failed to Ping. Unexpected response: ${response}`);
|
||||||
message: `Failed to Ping. Unexpected response: ${response}`
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
reader.releaseLock();
|
reader.releaseLock();
|
||||||
@@ -146,6 +143,7 @@ interface TProxyServer {
|
|||||||
server: net.Server;
|
server: net.Server;
|
||||||
port: number;
|
port: number;
|
||||||
cleanup: () => Promise<void>;
|
cleanup: () => Promise<void>;
|
||||||
|
getProxyError: () => string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const setupProxyServer = async ({
|
const setupProxyServer = async ({
|
||||||
@@ -170,6 +168,7 @@ const setupProxyServer = async ({
|
|||||||
error: err as Error
|
error: err as Error
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
const proxyErrorMsg = [""];
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const server = net.createServer();
|
const server = net.createServer();
|
||||||
@@ -185,31 +184,33 @@ const setupProxyServer = async ({
|
|||||||
const forwardWriter = stream.writable.getWriter();
|
const forwardWriter = stream.writable.getWriter();
|
||||||
await forwardWriter.write(Buffer.from(`FORWARD-TCP ${targetHost}:${targetPort}\n`));
|
await forwardWriter.write(Buffer.from(`FORWARD-TCP ${targetHost}:${targetPort}\n`));
|
||||||
forwardWriter.releaseLock();
|
forwardWriter.releaseLock();
|
||||||
/* eslint-disable @typescript-eslint/no-misused-promises */
|
|
||||||
// Set up bidirectional copy
|
// Set up bidirectional copy
|
||||||
const setupCopy = async () => {
|
const setupCopy = () => {
|
||||||
// Client to QUIC
|
// Client to QUIC
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
(async () => {
|
(async () => {
|
||||||
try {
|
const writer = stream.writable.getWriter();
|
||||||
const writer = stream.writable.getWriter();
|
|
||||||
|
|
||||||
// Create a handler for client data
|
// Create a handler for client data
|
||||||
clientConn.on("data", async (chunk) => {
|
clientConn.on("data", (chunk) => {
|
||||||
await writer.write(chunk);
|
writer.write(chunk).catch((err) => {
|
||||||
|
proxyErrorMsg.push((err as Error)?.message);
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
// Handle client connection close
|
// Handle client connection close
|
||||||
clientConn.on("end", async () => {
|
clientConn.on("end", () => {
|
||||||
await writer.close();
|
writer.close().catch((err) => {
|
||||||
|
logger.error(err);
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
clientConn.on("error", async (err) => {
|
clientConn.on("error", (clientConnErr) => {
|
||||||
await writer.abort(err);
|
writer.abort(clientConnErr?.message).catch((err) => {
|
||||||
|
proxyErrorMsg.push((err as Error)?.message);
|
||||||
});
|
});
|
||||||
} catch (err) {
|
});
|
||||||
clientConn.destroy();
|
|
||||||
}
|
|
||||||
})();
|
})();
|
||||||
|
|
||||||
// QUIC to Client
|
// QUIC to Client
|
||||||
@@ -238,15 +239,18 @@ const setupProxyServer = async ({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
proxyErrorMsg.push((err as Error)?.message);
|
||||||
clientConn.destroy();
|
clientConn.destroy();
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
};
|
};
|
||||||
await setupCopy();
|
|
||||||
//
|
setupCopy();
|
||||||
// Handle connection closure
|
// Handle connection closure
|
||||||
clientConn.on("close", async () => {
|
clientConn.on("close", () => {
|
||||||
await stream.destroy();
|
stream.destroy().catch((err) => {
|
||||||
|
proxyErrorMsg.push((err as Error)?.message);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
const cleanup = async () => {
|
const cleanup = async () => {
|
||||||
@@ -254,13 +258,18 @@ const setupProxyServer = async ({
|
|||||||
await stream.destroy();
|
await stream.destroy();
|
||||||
};
|
};
|
||||||
|
|
||||||
clientConn.on("error", (err) => {
|
clientConn.on("error", (clientConnErr) => {
|
||||||
logger.error(err, "Client socket error");
|
logger.error(clientConnErr, "Client socket error");
|
||||||
void cleanup();
|
cleanup().catch((err) => {
|
||||||
reject(err);
|
logger.error(err, "Client conn cleanup");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
clientConn.on("end", cleanup);
|
clientConn.on("end", () => {
|
||||||
|
cleanup().catch((err) => {
|
||||||
|
logger.error(err, "Client conn end");
|
||||||
|
});
|
||||||
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logger.error(err, "Failed to establish target connection:");
|
logger.error(err, "Failed to establish target connection:");
|
||||||
clientConn.end();
|
clientConn.end();
|
||||||
@@ -272,12 +281,12 @@ const setupProxyServer = async ({
|
|||||||
reject(err);
|
reject(err);
|
||||||
});
|
});
|
||||||
|
|
||||||
server.on("close", async () => {
|
server.on("close", () => {
|
||||||
await quicClient?.destroy();
|
quicClient?.destroy().catch((err) => {
|
||||||
|
logger.error(err, "Failed to destroy quic client");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
/* eslint-enable */
|
|
||||||
|
|
||||||
server.listen(0, () => {
|
server.listen(0, () => {
|
||||||
const address = server.address();
|
const address = server.address();
|
||||||
if (!address || typeof address === "string") {
|
if (!address || typeof address === "string") {
|
||||||
@@ -293,7 +302,8 @@ const setupProxyServer = async ({
|
|||||||
cleanup: async () => {
|
cleanup: async () => {
|
||||||
server.close();
|
server.close();
|
||||||
await quicClient?.destroy();
|
await quicClient?.destroy();
|
||||||
}
|
},
|
||||||
|
getProxyError: () => proxyErrorMsg.join(",")
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -316,7 +326,7 @@ export const withGatewayProxy = async (
|
|||||||
const { relayHost, relayPort, targetHost, targetPort, tlsOptions, identityId, orgId } = options;
|
const { relayHost, relayPort, targetHost, targetPort, tlsOptions, identityId, orgId } = options;
|
||||||
|
|
||||||
// Setup the proxy server
|
// Setup the proxy server
|
||||||
const { port, cleanup } = await setupProxyServer({
|
const { port, cleanup, getProxyError } = await setupProxyServer({
|
||||||
targetHost,
|
targetHost,
|
||||||
targetPort,
|
targetPort,
|
||||||
relayPort,
|
relayPort,
|
||||||
@@ -330,8 +340,12 @@ export const withGatewayProxy = async (
|
|||||||
// Execute the callback with the allocated port
|
// Execute the callback with the allocated port
|
||||||
await callback(port);
|
await callback(port);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logger.error(err, "Failed to proxy");
|
const proxyErrorMessage = getProxyError();
|
||||||
throw new BadRequestError({ message: (err as Error)?.message });
|
if (proxyErrorMessage) {
|
||||||
|
logger.error(new Error(proxyErrorMessage), "Failed to proxy");
|
||||||
|
}
|
||||||
|
logger.error(err, "Failed to do gateway");
|
||||||
|
throw new BadRequestError({ message: proxyErrorMessage || (err as Error)?.message });
|
||||||
} finally {
|
} finally {
|
||||||
// Ensure cleanup happens regardless of success or failure
|
// Ensure cleanup happens regardless of success or failure
|
||||||
await cleanup();
|
await cleanup();
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import crypto from "node:crypto";
|
import crypto from "node:crypto";
|
||||||
|
|
||||||
const TURN_TOKEN_TTL = 60 * 60 * 1000; // 24 hours in milliseconds
|
const TURN_TOKEN_TTL = 24 * 60 * 60 * 1000; // 24 hours in milliseconds
|
||||||
export const getTurnCredentials = (id: string, authSecret: string, ttl = TURN_TOKEN_TTL) => {
|
export const getTurnCredentials = (id: string, authSecret: string, ttl = TURN_TOKEN_TTL) => {
|
||||||
const timestamp = Math.floor((Date.now() + ttl) / 1000);
|
const timestamp = Math.floor((Date.now() + ttl) / 1000);
|
||||||
const username = `${timestamp}:${id}`;
|
const username = `${timestamp}:${id}`;
|
||||||
|
|||||||
+5
-5
@@ -29,9 +29,9 @@ require (
|
|||||||
github.com/spf13/cobra v1.6.1
|
github.com/spf13/cobra v1.6.1
|
||||||
github.com/spf13/viper v1.8.1
|
github.com/spf13/viper v1.8.1
|
||||||
github.com/stretchr/testify v1.10.0
|
github.com/stretchr/testify v1.10.0
|
||||||
golang.org/x/crypto v0.35.0
|
golang.org/x/crypto v0.36.0
|
||||||
golang.org/x/sys v0.30.0
|
golang.org/x/sys v0.31.0
|
||||||
golang.org/x/term v0.29.0
|
golang.org/x/term v0.30.0
|
||||||
gopkg.in/yaml.v2 v2.4.0
|
gopkg.in/yaml.v2 v2.4.0
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -115,8 +115,8 @@ require (
|
|||||||
golang.org/x/mod v0.23.0 // indirect
|
golang.org/x/mod v0.23.0 // indirect
|
||||||
golang.org/x/net v0.35.0 // indirect
|
golang.org/x/net v0.35.0 // indirect
|
||||||
golang.org/x/oauth2 v0.21.0 // indirect
|
golang.org/x/oauth2 v0.21.0 // indirect
|
||||||
golang.org/x/sync v0.11.0 // indirect
|
golang.org/x/sync v0.12.0 // indirect
|
||||||
golang.org/x/text v0.22.0 // indirect
|
golang.org/x/text v0.23.0 // indirect
|
||||||
golang.org/x/time v0.6.0 // indirect
|
golang.org/x/time v0.6.0 // indirect
|
||||||
golang.org/x/tools v0.30.0 // indirect
|
golang.org/x/tools v0.30.0 // indirect
|
||||||
google.golang.org/api v0.188.0 // indirect
|
google.golang.org/api v0.188.0 // indirect
|
||||||
|
|||||||
+10
@@ -486,6 +486,8 @@ golang.org/x/crypto v0.0.0-20211215165025-cf75a172585e/go.mod h1:P+XmwS30IXTQdn5
|
|||||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||||
golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs=
|
golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs=
|
||||||
golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ=
|
golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ=
|
||||||
|
golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34=
|
||||||
|
golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc=
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||||
@@ -592,6 +594,8 @@ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJ
|
|||||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=
|
golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=
|
||||||
golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||||
|
golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw=
|
||||||
|
golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||||
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
@@ -642,9 +646,13 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
|
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
|
||||||
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
|
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
|
||||||
|
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.29.0 h1:L6pJp37ocefwRRtYPKSWOWzOtWSxVajvz2ldH/xi3iU=
|
golang.org/x/term v0.29.0 h1:L6pJp37ocefwRRtYPKSWOWzOtWSxVajvz2ldH/xi3iU=
|
||||||
golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s=
|
golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s=
|
||||||
|
golang.org/x/term v0.30.0 h1:PQ39fJZ+mfadBm0y5WlL4vlM7Sx1Hgf13sMIY2+QS9Y=
|
||||||
|
golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g=
|
||||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
@@ -656,6 +664,8 @@ golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
|||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
|
golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
|
||||||
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
|
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
|
||||||
|
golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
|
||||||
|
golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
|
||||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import (
|
|||||||
"github.com/Infisical/infisical-merge/packages/api"
|
"github.com/Infisical/infisical-merge/packages/api"
|
||||||
"github.com/Infisical/infisical-merge/packages/systemd"
|
"github.com/Infisical/infisical-merge/packages/systemd"
|
||||||
"github.com/go-resty/resty/v2"
|
"github.com/go-resty/resty/v2"
|
||||||
|
"github.com/pion/dtls/v3"
|
||||||
"github.com/pion/logging"
|
"github.com/pion/logging"
|
||||||
"github.com/pion/turn/v4"
|
"github.com/pion/turn/v4"
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
@@ -54,26 +55,6 @@ func (g *Gateway) ConnectWithRelay() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
relayAddress, relayPort := strings.Split(relayDetails.TurnServerAddress, ":")[0], strings.Split(relayDetails.TurnServerAddress, ":")[1]
|
relayAddress, relayPort := strings.Split(relayDetails.TurnServerAddress, ":")[0], strings.Split(relayDetails.TurnServerAddress, ":")[1]
|
||||||
var conn net.Conn
|
|
||||||
|
|
||||||
// Dial TURN Server
|
|
||||||
if relayPort == "5349" {
|
|
||||||
log.Info().Msgf("Provided relay port %s. Using TLS", relayPort)
|
|
||||||
conn, err = tls.Dial("tcp", relayDetails.TurnServerAddress, &tls.Config{
|
|
||||||
ServerName: relayAddress,
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
log.Info().Msgf("Provided relay port %s. Using non TLS connection.", relayPort)
|
|
||||||
peerAddr, errPeer := net.ResolveTCPAddr("tcp", relayDetails.TurnServerAddress)
|
|
||||||
if errPeer != nil {
|
|
||||||
return fmt.Errorf("Failed to parse turn server address: %w", err)
|
|
||||||
}
|
|
||||||
conn, err = net.DialTCP("tcp", nil, peerAddr)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Failed to connect with relay server: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start a new TURN Client and wrap our net.Conn in a STUNConn
|
// Start a new TURN Client and wrap our net.Conn in a STUNConn
|
||||||
// This allows us to simulate datagram based communication over a net.Conn
|
// This allows us to simulate datagram based communication over a net.Conn
|
||||||
@@ -81,17 +62,46 @@ func (g *Gateway) ConnectWithRelay() error {
|
|||||||
if os.Getenv("LOG_LEVEL") == "debug" {
|
if os.Getenv("LOG_LEVEL") == "debug" {
|
||||||
logger.DefaultLogLevel = logging.LogLevelDebug
|
logger.DefaultLogLevel = logging.LogLevelDebug
|
||||||
}
|
}
|
||||||
cfg := &turn.ClientConfig{
|
|
||||||
|
turnClientCfg := &turn.ClientConfig{
|
||||||
STUNServerAddr: relayDetails.TurnServerAddress,
|
STUNServerAddr: relayDetails.TurnServerAddress,
|
||||||
TURNServerAddr: relayDetails.TurnServerAddress,
|
TURNServerAddr: relayDetails.TurnServerAddress,
|
||||||
Conn: turn.NewSTUNConn(conn),
|
|
||||||
Username: relayDetails.TurnServerUsername,
|
Username: relayDetails.TurnServerUsername,
|
||||||
Password: relayDetails.TurnServerPassword,
|
Password: relayDetails.TurnServerPassword,
|
||||||
Realm: relayDetails.TurnServerRealm,
|
Realm: relayDetails.TurnServerRealm,
|
||||||
LoggerFactory: logger,
|
LoggerFactory: logger,
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := turn.NewClient(cfg)
|
turnAddr, err := net.ResolveUDPAddr("udp4", relayDetails.TurnServerAddress)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Failed to parse turn server address: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dial TURN Server
|
||||||
|
if relayPort == "5349" {
|
||||||
|
caCertPool := x509.NewCertPool()
|
||||||
|
caCertPool.AppendCertsFromPEM([]byte(g.config.CertificateChain))
|
||||||
|
|
||||||
|
log.Info().Msgf("Provided relay port %s. Using TLS", relayPort)
|
||||||
|
conn, err := dtls.Dial("udp", turnAddr, &dtls.Config{
|
||||||
|
ServerName: relayAddress,
|
||||||
|
RootCAs: caCertPool,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Failed to connect with relay server: %w", err)
|
||||||
|
}
|
||||||
|
turnClientCfg.Conn = turn.NewSTUNConn(conn)
|
||||||
|
} else {
|
||||||
|
log.Info().Msgf("Provided relay port %s. Using non TLS connection.", relayPort)
|
||||||
|
conn, err := net.ListenPacket("udp4", turnAddr.String())
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Failed to connect with relay server: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
turnClientCfg.Conn = conn
|
||||||
|
}
|
||||||
|
|
||||||
|
client, err := turn.NewClient(turnClientCfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Failed to create relay client: %w", err)
|
return fmt.Errorf("Failed to create relay client: %w", err)
|
||||||
}
|
}
|
||||||
@@ -168,7 +178,6 @@ func (g *Gateway) Listen(ctx context.Context) error {
|
|||||||
ClientAuth: tls.RequireAndVerifyClientCert,
|
ClientAuth: tls.RequireAndVerifyClientCert,
|
||||||
NextProtos: []string{"infisical-gateway"},
|
NextProtos: []string{"infisical-gateway"},
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup QUIC listener on the relayConn
|
// Setup QUIC listener on the relayConn
|
||||||
quicConfig := &quic.Config{
|
quicConfig := &quic.Config{
|
||||||
EnableDatagrams: true,
|
EnableDatagrams: true,
|
||||||
@@ -176,7 +185,6 @@ func (g *Gateway) Listen(ctx context.Context) error {
|
|||||||
KeepAlivePeriod: 2 * time.Second,
|
KeepAlivePeriod: 2 * time.Second,
|
||||||
}
|
}
|
||||||
|
|
||||||
g.registerRelayIsActive(ctx, errCh)
|
|
||||||
quicListener, err := quic.Listen(relayUdpConnection, tlsConfig, quicConfig)
|
quicListener, err := quic.Listen(relayUdpConnection, tlsConfig, quicConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Failed to listen for QUIC: %w", err)
|
return fmt.Errorf("Failed to listen for QUIC: %w", err)
|
||||||
@@ -185,6 +193,8 @@ func (g *Gateway) Listen(ctx context.Context) error {
|
|||||||
|
|
||||||
log.Printf("Listener started on %s", quicListener.Addr())
|
log.Printf("Listener started on %s", quicListener.Addr())
|
||||||
|
|
||||||
|
g.registerRelayIsActive(ctx, quicListener.Addr().String(), errCh)
|
||||||
|
|
||||||
log.Info().Msg("Gateway started successfully")
|
log.Info().Msg("Gateway started successfully")
|
||||||
|
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
@@ -320,13 +330,12 @@ func (g *Gateway) createPermissionForStaticIps(staticIps string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *Gateway) registerRelayIsActive(ctx context.Context, errCh chan error) error {
|
func (g *Gateway) registerRelayIsActive(ctx context.Context, addr string, errCh chan error) error {
|
||||||
ticker := time.NewTicker(15 * time.Second)
|
ticker := time.NewTicker(15 * time.Second)
|
||||||
maxFailures := 3
|
maxFailures := 3
|
||||||
failures := 0
|
failures := 0
|
||||||
|
|
||||||
log.Info().Msg("Starting relay connection health check")
|
log.Info().Msg("Starting relay connection health check")
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
time.Sleep(5 * time.Second)
|
time.Sleep(5 * time.Second)
|
||||||
for {
|
for {
|
||||||
@@ -335,36 +344,26 @@ func (g *Gateway) registerRelayIsActive(ctx context.Context, errCh chan error) e
|
|||||||
log.Info().Msg("Stopping relay connection health check")
|
log.Info().Msg("Stopping relay connection health check")
|
||||||
return
|
return
|
||||||
case <-ticker.C:
|
case <-ticker.C:
|
||||||
func() {
|
log.Debug().Msg("Performing relay connection health check")
|
||||||
log.Debug().Msg("Performing relay connection health check")
|
ctxTimeout, cancel := context.WithTimeout(ctx, 5*time.Second)
|
||||||
|
defer cancel()
|
||||||
if g.client == nil {
|
// Try to establish a QUIC connection
|
||||||
failures++
|
conn, err := quic.DialAddr(ctxTimeout, addr, &tls.Config{
|
||||||
log.Warn().Int("failures", failures).Msg("TURN client is nil")
|
InsecureSkipVerify: false, // Skip certificate verification
|
||||||
if failures >= maxFailures {
|
NextProtos: []string{"infisical-gateway"},
|
||||||
errCh <- fmt.Errorf("relay connection check failed: TURN client is nil")
|
}, nil)
|
||||||
}
|
if err != nil && !strings.Contains(err.Error(), "tls:") {
|
||||||
|
failures++
|
||||||
|
log.Warn().Err(err).Int("failures", failures).Msg("Failed to refresh TURN permissions")
|
||||||
|
if failures >= maxFailures {
|
||||||
|
errCh <- fmt.Errorf("relay connection check failed: %w", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
continue
|
||||||
// we try to refresh permissions - this is a lightweight operation
|
}
|
||||||
// that will fail immediately if the UDP connection is broken. good for health check
|
if conn != nil {
|
||||||
log.Debug().Msg("Refreshing TURN permissions to verify connection")
|
defer conn.CloseWithError(0, "All good")
|
||||||
if err := g.createPermissionForStaticIps(g.config.InfisicalStaticIp); err != nil {
|
}
|
||||||
failures++
|
|
||||||
log.Warn().Err(err).Int("failures", failures).Msg("Failed to refresh TURN permissions")
|
|
||||||
if failures >= maxFailures {
|
|
||||||
errCh <- fmt.Errorf("relay connection check failed: %w", err)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Debug().Msg("Successfully refreshed TURN permissions - connection is healthy")
|
|
||||||
if failures > 0 {
|
|
||||||
log.Info().Int("previous_failures", failures).Msg("Relay connection restored")
|
|
||||||
failures = 0
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
package gateway
|
package gateway
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"errors"
|
"errors"
|
||||||
@@ -12,12 +11,13 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"runtime"
|
|
||||||
|
// "runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
udplistener "github.com/Infisical/infisical-merge/packages/gateway/udp_listener"
|
|
||||||
"github.com/Infisical/infisical-merge/packages/systemd"
|
"github.com/Infisical/infisical-merge/packages/systemd"
|
||||||
|
"github.com/pion/dtls/v3"
|
||||||
"github.com/pion/logging"
|
"github.com/pion/logging"
|
||||||
"github.com/pion/turn/v4"
|
"github.com/pion/turn/v4"
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
@@ -108,7 +108,7 @@ func NewGatewayRelay(configFilePath string) (*GatewayRelay, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (g *GatewayRelay) Run() error {
|
func (g *GatewayRelay) Run() error {
|
||||||
addr, err := net.ResolveTCPAddr("tcp", "0.0.0.0:"+strconv.Itoa(g.Config.Port))
|
addr, err := net.ResolveUDPAddr("udp", "0.0.0.0:"+strconv.Itoa(g.Config.Port))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Failed to parse server address: %s", err)
|
return fmt.Errorf("Failed to parse server address: %s", err)
|
||||||
}
|
}
|
||||||
@@ -117,13 +117,6 @@ func (g *GatewayRelay) Run() error {
|
|||||||
// and process them yourself.
|
// and process them yourself.
|
||||||
logger := logging.NewDefaultLeveledLoggerForScope("lt-creds", logging.LogLevelTrace, os.Stdout)
|
logger := logging.NewDefaultLeveledLoggerForScope("lt-creds", logging.LogLevelTrace, os.Stdout)
|
||||||
|
|
||||||
// Create `numThreads` UDP listeners to pass into pion/turn
|
|
||||||
// pion/turn itself doesn't allocate any UDP sockets, but lets the user pass them in
|
|
||||||
// this allows us to add logging, storage or modify inbound/outbound traffic
|
|
||||||
// UDP listeners share the same local address:port with setting SO_REUSEPORT and the kernel
|
|
||||||
// will load-balance received packets per the IP 5-tuple
|
|
||||||
listenerConfig := udplistener.SetupListenerConfig()
|
|
||||||
|
|
||||||
publicIP := g.Config.PublicIP
|
publicIP := g.Config.PublicIP
|
||||||
relayAddressGenerator := &turn.RelayAddressGeneratorPortRange{
|
relayAddressGenerator := &turn.RelayAddressGeneratorPortRange{
|
||||||
RelayAddress: net.ParseIP(publicIP), // Claim that we are listening on IP passed by user
|
RelayAddress: net.ParseIP(publicIP), // Claim that we are listening on IP passed by user
|
||||||
@@ -132,49 +125,54 @@ func (g *GatewayRelay) Run() error {
|
|||||||
MaxPort: g.Config.RelayMaxPort,
|
MaxPort: g.Config.RelayMaxPort,
|
||||||
}
|
}
|
||||||
|
|
||||||
threadNum := runtime.NumCPU()
|
|
||||||
listenerConfigs := make([]turn.ListenerConfig, threadNum)
|
|
||||||
var connAddress string
|
|
||||||
for i := 0; i < threadNum; i++ {
|
|
||||||
conn, listErr := listenerConfig.Listen(context.Background(), addr.Network(), addr.String())
|
|
||||||
if listErr != nil {
|
|
||||||
return fmt.Errorf("Failed to allocate TCP listener at %s:%s %s", addr.Network(), addr.String(), listErr)
|
|
||||||
}
|
|
||||||
|
|
||||||
listenerConfigs[i] = turn.ListenerConfig{
|
|
||||||
RelayAddressGenerator: relayAddressGenerator,
|
|
||||||
}
|
|
||||||
|
|
||||||
if g.Config.isTlsEnabled {
|
|
||||||
caCertPool := x509.NewCertPool()
|
|
||||||
caCertPool.AppendCertsFromPEM([]byte(g.Config.tlsCa))
|
|
||||||
|
|
||||||
listenerConfigs[i].Listener = tls.NewListener(conn, &tls.Config{
|
|
||||||
Certificates: []tls.Certificate{g.Config.tls},
|
|
||||||
ClientCAs: caCertPool,
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
listenerConfigs[i].Listener = conn
|
|
||||||
}
|
|
||||||
connAddress = conn.Addr().String()
|
|
||||||
}
|
|
||||||
|
|
||||||
loggerF := logging.NewDefaultLoggerFactory()
|
loggerF := logging.NewDefaultLoggerFactory()
|
||||||
loggerF.DefaultLogLevel = logging.LogLevelDebug
|
loggerF.DefaultLogLevel = logging.LogLevelDebug
|
||||||
|
|
||||||
|
caCertPool := x509.NewCertPool()
|
||||||
|
caCertPool.AppendCertsFromPEM([]byte(g.Config.tlsCa))
|
||||||
|
|
||||||
|
listenerConfigs := make([]turn.ListenerConfig, 0)
|
||||||
|
packetConfigs := make([]turn.PacketConnConfig, 0)
|
||||||
|
|
||||||
|
if g.Config.isTlsEnabled {
|
||||||
|
caCertPool := x509.NewCertPool()
|
||||||
|
caCertPool.AppendCertsFromPEM([]byte(g.Config.tlsCa))
|
||||||
|
dtlsServer, err := dtls.Listen("udp", addr, &dtls.Config{
|
||||||
|
Certificates: []tls.Certificate{g.Config.tls},
|
||||||
|
ClientCAs: caCertPool,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Failed to start dtls server: %w", err)
|
||||||
|
}
|
||||||
|
listenerConfigs = append(listenerConfigs, turn.ListenerConfig{
|
||||||
|
RelayAddressGenerator: relayAddressGenerator,
|
||||||
|
Listener: dtlsServer,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
udpListener, err := net.ListenPacket("udp4", "0.0.0.0:"+strconv.Itoa(g.Config.Port))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Failed to relay udp listener: %w", err)
|
||||||
|
}
|
||||||
|
packetConfigs = append(packetConfigs, turn.PacketConnConfig{
|
||||||
|
RelayAddressGenerator: relayAddressGenerator,
|
||||||
|
PacketConn: udpListener,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
server, err := turn.NewServer(turn.ServerConfig{
|
server, err := turn.NewServer(turn.ServerConfig{
|
||||||
Realm: g.Config.Realm,
|
Realm: g.Config.Realm,
|
||||||
AuthHandler: turn.LongTermTURNRESTAuthHandler(g.Config.AuthSecret, logger),
|
AuthHandler: turn.LongTermTURNRESTAuthHandler(g.Config.AuthSecret, logger),
|
||||||
// PacketConnConfigs is a list of UDP Listeners and the configuration around them
|
// PacketConnConfigs is a list of UDP Listeners and the configuration around them
|
||||||
ListenerConfigs: listenerConfigs,
|
ListenerConfigs: listenerConfigs,
|
||||||
LoggerFactory: loggerF,
|
PacketConnConfigs: packetConfigs,
|
||||||
|
LoggerFactory: loggerF,
|
||||||
})
|
})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Failed to start server: %w", err)
|
return fmt.Errorf("Failed to start server: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Info().Msgf("Relay listening on %s\n", connAddress)
|
log.Info().Msgf("Relay listening on %d\n", g.Config.Port)
|
||||||
|
|
||||||
// make this compatiable with systemd notify mode
|
// make this compatiable with systemd notify mode
|
||||||
systemd.SdNotify(false, systemd.SdNotifyReady)
|
systemd.SdNotify(false, systemd.SdNotifyReady)
|
||||||
|
|||||||
+2
-2
@@ -36,7 +36,7 @@ const formSchema = z.object({
|
|||||||
revocationStatement: z.string().min(1),
|
revocationStatement: z.string().min(1),
|
||||||
renewStatement: z.string().optional(),
|
renewStatement: z.string().optional(),
|
||||||
ca: z.string().optional(),
|
ca: z.string().optional(),
|
||||||
projectGatewayId: z.string().optional()
|
projectGatewayId: z.string().optional().nullable()
|
||||||
})
|
})
|
||||||
.partial(),
|
.partial(),
|
||||||
defaultTTL: z.string().superRefine((val, ctx) => {
|
defaultTTL: z.string().superRefine((val, ctx) => {
|
||||||
@@ -207,7 +207,7 @@ export const EditDynamicSecretSqlProviderForm = ({
|
|||||||
helperText=""
|
helperText=""
|
||||||
>
|
>
|
||||||
<Select
|
<Select
|
||||||
value={value}
|
value={value || undefined}
|
||||||
onValueChange={onChange}
|
onValueChange={onChange}
|
||||||
className="w-full border border-mineshaft-500"
|
className="w-full border border-mineshaft-500"
|
||||||
dropdownContainerClassName="max-w-none"
|
dropdownContainerClassName="max-w-none"
|
||||||
|
|||||||
Reference in New Issue
Block a user