From e40f65836f18b9cfb480a3f511bd132469808856 Mon Sep 17 00:00:00 2001 From: carlosmonastyrski Date: Tue, 10 Jun 2025 08:25:06 -0300 Subject: [PATCH 1/6] feat(docs): Added a small note to clarify the usage of the env variable INFISICAL_API_URL for EU users --- docs/cli/usage.mdx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/cli/usage.mdx b/docs/cli/usage.mdx index a3bfd83f0e..8d0236ed5c 100644 --- a/docs/cli/usage.mdx +++ b/docs/cli/usage.mdx @@ -120,6 +120,12 @@ The CLI is designed for a variety of secret management applications ranging from + + Starting with CLI version v0.4.0, you can now choose to log in via Infisical Cloud (US/EU) or your own self-hosted instance by simply running `infisical login` and following the on-screen instructions — no need to manually set the `INFISICAL_API_URL` environment variable. + + For versions prior to v0.4.0, the CLI defaults to the US Cloud. To connect to the EU Cloud or a self-hosted instance, set the `INFISICAL_API_URL` environment variable to `https://eu.infisical.com` or your custom URL. + + ## Custom Request Headers From 47e778a0b8305a44256e5139287e896970ccc27f Mon Sep 17 00:00:00 2001 From: Daniel Hougaard Date: Tue, 10 Jun 2025 23:59:10 +0400 Subject: [PATCH 2/6] feat(gateway): use gateway for full k8s request life-cycle --- ...ntity-kubernetes-auth-optional-host-url.ts | 45 ++++++++ .../db/schemas/identity-kubernetes-auths.ts | 2 +- backend/src/lib/gateway/types.ts | 3 +- .../v1/identity-kubernetes-auth-router.ts | 23 +++- .../identity-kubernetes-auth-service.ts | 72 +++++-------- .../identity-kubernetes-auth-types.ts | 4 +- cli/packages/gateway/connection.go | 60 +++++++++-- cli/packages/gateway/constants.go | 17 +++ frontend/src/hooks/api/identities/types.ts | 4 +- .../IdentityKubernetesAuthForm.tsx | 102 ++++++++++++------ helm-charts/infisical-gateway/CHANGELOG.md | 11 +- helm-charts/infisical-gateway/Chart.yaml | 4 +- helm-charts/infisical-gateway/values.yaml | 2 +- 13 files changed, 245 insertions(+), 104 deletions(-) create mode 100644 backend/src/db/migrations/20250610173646_identity-kubernetes-auth-optional-host-url.ts create mode 100644 cli/packages/gateway/constants.go diff --git a/backend/src/db/migrations/20250610173646_identity-kubernetes-auth-optional-host-url.ts b/backend/src/db/migrations/20250610173646_identity-kubernetes-auth-optional-host-url.ts new file mode 100644 index 0000000000..6d2dd66646 --- /dev/null +++ b/backend/src/db/migrations/20250610173646_identity-kubernetes-auth-optional-host-url.ts @@ -0,0 +1,45 @@ +import { Knex } from "knex"; + +import { selectAllTableCols } from "@app/lib/knex"; + +import { TableName } from "../schemas"; + +const BATCH_SIZE = 1000; + +export async function up(knex: Knex): Promise { + const hasKubernetesHostColumn = await knex.schema.hasColumn(TableName.IdentityKubernetesAuth, "kubernetesHost"); + + if (hasKubernetesHostColumn) { + await knex.schema.alterTable(TableName.IdentityKubernetesAuth, (table) => { + table.string("kubernetesHost").nullable().alter(); + }); + } +} + +export async function down(knex: Knex): Promise { + const hasKubernetesHostColumn = await knex.schema.hasColumn(TableName.IdentityKubernetesAuth, "kubernetesHost"); + + // find all rows where kubernetesHost is null + const rows = await knex(TableName.IdentityKubernetesAuth) + .whereNull("kubernetesHost") + .select(selectAllTableCols(TableName.IdentityKubernetesAuth)); + + if (rows.length > 0) { + for (let i = 0; i < rows.length; i += BATCH_SIZE) { + const batch = rows.slice(i, i + BATCH_SIZE); + // eslint-disable-next-line no-await-in-loop + await knex(TableName.IdentityKubernetesAuth) + .whereIn( + "id", + batch.map((row) => row.id) + ) + .update({ kubernetesHost: "" }); + } + } + + if (hasKubernetesHostColumn) { + await knex.schema.alterTable(TableName.IdentityKubernetesAuth, (table) => { + table.string("kubernetesHost").notNullable().alter(); + }); + } +} diff --git a/backend/src/db/schemas/identity-kubernetes-auths.ts b/backend/src/db/schemas/identity-kubernetes-auths.ts index 8a351014a4..deb78bf8ae 100644 --- a/backend/src/db/schemas/identity-kubernetes-auths.ts +++ b/backend/src/db/schemas/identity-kubernetes-auths.ts @@ -18,7 +18,7 @@ export const IdentityKubernetesAuthsSchema = z.object({ createdAt: z.date(), updatedAt: z.date(), identityId: z.string().uuid(), - kubernetesHost: z.string(), + kubernetesHost: z.string().nullable().optional(), encryptedCaCert: z.string().nullable().optional(), caCertIV: z.string().nullable().optional(), caCertTag: z.string().nullable().optional(), diff --git a/backend/src/lib/gateway/types.ts b/backend/src/lib/gateway/types.ts index 5d0ac8237f..fdb13d2562 100644 --- a/backend/src/lib/gateway/types.ts +++ b/backend/src/lib/gateway/types.ts @@ -10,7 +10,8 @@ export enum GatewayProxyProtocol { } export enum GatewayHttpProxyActions { - InjectGatewayK8sServiceAccountToken = "inject-k8s-sa-auth-token" + InjectGatewayK8sServiceAccountToken = "inject-k8s-sa-auth-token", + UseGatewayK8sServiceAccount = "use-k8s-sa" } export interface IGatewayProxyOptions { diff --git a/backend/src/server/routes/v1/identity-kubernetes-auth-router.ts b/backend/src/server/routes/v1/identity-kubernetes-auth-router.ts index 5eb0c69901..879310790e 100644 --- a/backend/src/server/routes/v1/identity-kubernetes-auth-router.ts +++ b/backend/src/server/routes/v1/identity-kubernetes-auth-router.ts @@ -108,17 +108,21 @@ export const registerIdentityKubernetesRouter = async (server: FastifyZodProvide .string() .trim() .min(1) + .nullable() .describe(KUBERNETES_AUTH.ATTACH.kubernetesHost) .refine( - (val) => - characterValidator([ + (val) => { + if (val === null) return true; + + return characterValidator([ CharacterType.Alphabets, CharacterType.Numbers, CharacterType.Colon, CharacterType.Period, CharacterType.ForwardSlash, CharacterType.Hyphen - ])(val), + ])(val); + }, { message: "Kubernetes host must only contain alphabets, numbers, colons, periods, hyphen, and forward slashes." @@ -164,6 +168,13 @@ export const registerIdentityKubernetesRouter = async (server: FastifyZodProvide .describe(KUBERNETES_AUTH.ATTACH.accessTokenNumUsesLimit) }) .superRefine((data, ctx) => { + if (data.tokenReviewMode === IdentityKubernetesAuthTokenReviewMode.Api && !data.kubernetesHost) { + ctx.addIssue({ + path: ["kubernetesHost"], + code: z.ZodIssueCode.custom, + message: "When token review mode is set to API, a Kubernetes host must be provided" + }); + } if (data.tokenReviewMode === IdentityKubernetesAuthTokenReviewMode.Gateway && !data.gatewayId) { ctx.addIssue({ path: ["gatewayId"], @@ -171,6 +182,7 @@ export const registerIdentityKubernetesRouter = async (server: FastifyZodProvide message: "When token review mode is set to Gateway, a gateway must be selected" }); } + if (data.accessTokenTTL > data.accessTokenMaxTTL) { ctx.addIssue({ path: ["accessTokenTTL"], @@ -203,7 +215,7 @@ export const registerIdentityKubernetesRouter = async (server: FastifyZodProvide type: EventType.ADD_IDENTITY_KUBERNETES_AUTH, metadata: { identityId: identityKubernetesAuth.identityId, - kubernetesHost: identityKubernetesAuth.kubernetesHost, + kubernetesHost: identityKubernetesAuth.kubernetesHost ?? "", allowedNamespaces: identityKubernetesAuth.allowedNamespaces, allowedNames: identityKubernetesAuth.allowedNames, accessTokenTTL: identityKubernetesAuth.accessTokenTTL, @@ -243,6 +255,7 @@ export const registerIdentityKubernetesRouter = async (server: FastifyZodProvide .string() .trim() .min(1) + .nullable() .optional() .describe(KUBERNETES_AUTH.UPDATE.kubernetesHost) .refine( @@ -345,7 +358,7 @@ export const registerIdentityKubernetesRouter = async (server: FastifyZodProvide type: EventType.UPDATE_IDENTITY_KUBENETES_AUTH, metadata: { identityId: identityKubernetesAuth.identityId, - kubernetesHost: identityKubernetesAuth.kubernetesHost, + kubernetesHost: identityKubernetesAuth.kubernetesHost ?? "", allowedNamespaces: identityKubernetesAuth.allowedNamespaces, allowedNames: identityKubernetesAuth.allowedNames, accessTokenTTL: identityKubernetesAuth.accessTokenTTL, diff --git a/backend/src/services/identity-kubernetes-auth/identity-kubernetes-auth-service.ts b/backend/src/services/identity-kubernetes-auth/identity-kubernetes-auth-service.ts index a1231c3536..b599c4ff95 100644 --- a/backend/src/services/identity-kubernetes-auth/identity-kubernetes-auth-service.ts +++ b/backend/src/services/identity-kubernetes-auth/identity-kubernetes-auth-service.ts @@ -104,11 +104,15 @@ export const identityKubernetesAuthServiceFactory = ({ cert: relayDetails.certificate, key: relayDetails.privateKey.toString() }, - // we always pass this, because its needed for both tcp and http protocol - httpsAgent: new https.Agent({ - ca: inputs.caCert, - rejectUnauthorized: Boolean(inputs.caCert) - }) + // only needed for TCP protocol, because the gateway as reviewer will use the pod's CA cert for auth directly + ...(!inputs.reviewTokenThroughGateway + ? { + httpsAgent: new https.Agent({ + ca: inputs.caCert, + rejectUnauthorized: Boolean(inputs.caCert) + }) + } + : {}) } ); @@ -142,8 +146,15 @@ export const identityKubernetesAuthServiceFactory = ({ caCert = decryptor({ cipherTextBlob: identityKubernetesAuth.encryptedKubernetesCaCertificate }).toString(); } - const tokenReviewCallbackRaw = async (host: string = identityKubernetesAuth.kubernetesHost, port?: number) => { + const tokenReviewCallbackRaw = async (host = identityKubernetesAuth.kubernetesHost, port?: number) => { logger.info({ host, port }, "tokenReviewCallbackRaw: Processing kubernetes token review using raw API"); + + if (!host || !identityKubernetesAuth.kubernetesHost) { + throw new BadRequestError({ + message: "Kubernetes host is required when token review mode is set to API" + }); + } + let tokenReviewerJwt = ""; if (identityKubernetesAuth.encryptedKubernetesTokenReviewerJwt) { tokenReviewerJwt = decryptor({ @@ -211,11 +222,7 @@ export const identityKubernetesAuthServiceFactory = ({ return res.data; }; - const tokenReviewCallbackThroughGateway = async ( - host: string = identityKubernetesAuth.kubernetesHost, - port?: number, - httpsAgent?: https.Agent - ) => { + const tokenReviewCallbackThroughGateway = async (host: string, port?: number) => { logger.info( { host, @@ -224,11 +231,9 @@ export const identityKubernetesAuthServiceFactory = ({ "tokenReviewCallbackThroughGateway: Processing kubernetes token review using gateway" ); - const baseUrl = port ? `${host}:${port}` : host; - const res = await axios .post( - `${baseUrl}/apis/authentication.k8s.io/v1/tokenreviews`, + `${host}:${port}/apis/authentication.k8s.io/v1/tokenreviews`, { apiVersion: "authentication.k8s.io/v1", kind: "TokenReview", @@ -240,11 +245,10 @@ export const identityKubernetesAuthServiceFactory = ({ { headers: { "Content-Type": "application/json", - "x-infisical-action": GatewayHttpProxyActions.InjectGatewayK8sServiceAccountToken + "x-infisical-action": GatewayHttpProxyActions.UseGatewayK8sServiceAccount }, signal: AbortSignal.timeout(10000), - timeout: 10000, - ...(httpsAgent ? { httpsAgent } : {}) + timeout: 10000 } ) .catch((err) => { @@ -273,29 +277,6 @@ export const identityKubernetesAuthServiceFactory = ({ let data: TCreateTokenReviewResponse | undefined; if (identityKubernetesAuth.tokenReviewMode === IdentityKubernetesAuthTokenReviewMode.Gateway) { - const { kubernetesHost } = identityKubernetesAuth; - - let urlString = kubernetesHost; - if (!kubernetesHost.startsWith("http://") && !kubernetesHost.startsWith("https://")) { - urlString = `https://${kubernetesHost}`; - } - - const url = new URL(urlString); - let { port: k8sPort } = url; - const { protocol, hostname: k8sHost } = url; - - const cleanedProtocol = new RE2(/[^a-zA-Z0-9]/g).replace(protocol, "").toLowerCase(); - - if (!["https", "http"].includes(cleanedProtocol)) { - throw new BadRequestError({ - message: "Invalid Kubernetes host URL, must start with http:// or https://" - }); - } - - if (!k8sPort) { - k8sPort = cleanedProtocol === "https" ? "443" : "80"; - } - if (!identityKubernetesAuth.gatewayId) { throw new BadRequestError({ message: "Gateway ID is required when token review mode is set to Gateway" @@ -305,14 +286,19 @@ export const identityKubernetesAuthServiceFactory = ({ data = await $gatewayProxyWrapper( { gatewayId: identityKubernetesAuth.gatewayId, - targetHost: `${cleanedProtocol}://${k8sHost}`, // note(daniel): must include the protocol (https|http) - targetPort: k8sPort ? Number(k8sPort) : 443, - caCert, + 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 ); } else if (identityKubernetesAuth.tokenReviewMode === IdentityKubernetesAuthTokenReviewMode.Api) { + if (!identityKubernetesAuth.kubernetesHost) { + throw new BadRequestError({ + message: "Kubernetes host is required when token review mode is set to API" + }); + } + let { kubernetesHost } = identityKubernetesAuth; if (kubernetesHost.startsWith("https://") || kubernetesHost.startsWith("http://")) { kubernetesHost = new RE2("^https?:\\/\\/").replace(kubernetesHost, ""); diff --git a/backend/src/services/identity-kubernetes-auth/identity-kubernetes-auth-types.ts b/backend/src/services/identity-kubernetes-auth/identity-kubernetes-auth-types.ts index 03dd7fd77b..269fa19e08 100644 --- a/backend/src/services/identity-kubernetes-auth/identity-kubernetes-auth-types.ts +++ b/backend/src/services/identity-kubernetes-auth/identity-kubernetes-auth-types.ts @@ -12,7 +12,7 @@ export enum IdentityKubernetesAuthTokenReviewMode { export type TAttachKubernetesAuthDTO = { identityId: string; - kubernetesHost: string; + kubernetesHost: string | null; caCert: string; tokenReviewerJwt?: string; tokenReviewMode: IdentityKubernetesAuthTokenReviewMode; @@ -29,7 +29,7 @@ export type TAttachKubernetesAuthDTO = { export type TUpdateKubernetesAuthDTO = { identityId: string; - kubernetesHost?: string; + kubernetesHost?: string | null; caCert?: string; tokenReviewerJwt?: string | null; tokenReviewMode?: IdentityKubernetesAuthTokenReviewMode; diff --git a/cli/packages/gateway/connection.go b/cli/packages/gateway/connection.go index 3f4ffdf03f..460956d3e4 100644 --- a/cli/packages/gateway/connection.go +++ b/cli/packages/gateway/connection.go @@ -116,7 +116,9 @@ func handleStream(stream quic.Stream, quicConn quic.Connection) { targetURL := string(argParts[0]) - if !isValidURL(targetURL) { + // ? note(daniel): special case: if the target URL is "/:0", we don't validate it. + // ? the reason for this is because we want to be able to send requests to the gateway without knowing the actual target URL, and instead let the gateway construct the target URL. + if targetURL != "/:0" && !isValidURL(targetURL) { log.Error().Msgf("Invalid target URL: %s", targetURL) return } @@ -183,11 +185,6 @@ func handleHTTPProxy(stream quic.Stream, reader *bufio.Reader, targetURL string, transport.TLSClientConfig = tlsConfig } - client := &http.Client{ - Transport: transport, - Timeout: 30 * time.Second, - } - // Loop to handle multiple HTTP requests on the same stream for { req, err := http.ReadRequest(reader) @@ -201,18 +198,56 @@ func handleHTTPProxy(stream quic.Stream, reader *bufio.Reader, targetURL string, } log.Info().Msgf("Received HTTP request: %s", req.URL.Path) - actionHeader := req.Header.Get("x-infisical-action") + actionHeader := HttpProxyAction(req.Header.Get(INFISICAL_HTTP_PROXY_ACTION_HEADER)) if actionHeader != "" { - if actionHeader == "inject-k8s-sa-auth-token" { - token, err := os.ReadFile("/var/run/secrets/kubernetes.io/serviceaccount/token") + if actionHeader == HttpProxyActionInjectGatewayK8sServiceAccountToken { + token, err := os.ReadFile(KUBERNETES_SERVICE_ACCOUNT_TOKEN_PATH) if err != nil { stream.Write([]byte(buildHttpInternalServerError("failed to read k8s sa auth token"))) continue // Continue to next request instead of returning } req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", string(token))) log.Info().Msgf("Injected gateway k8s SA auth token in request to %s", targetURL) + } else if actionHeader == HttpProxyActionUseGatewayK8sServiceAccount { + + // set the ca cert to the pod's k8s service account ca cert: + caCert, err := os.ReadFile(KUBERNETES_SERVICE_ACCOUNT_CA_CERT_PATH) + if err != nil { + stream.Write([]byte(buildHttpInternalServerError("failed to read k8s sa ca cert"))) + continue + } + + caCertPool := x509.NewCertPool() + appendSuccess := caCertPool.AppendCertsFromPEM(caCert) + + if !appendSuccess { + stream.Write([]byte(buildHttpInternalServerError("failed to parse k8s sa ca cert"))) + continue + } + + transport.TLSClientConfig = &tls.Config{ + RootCAs: caCertPool, + } + + // set authorization header to the pod's k8s service account token: + token, err := os.ReadFile(KUBERNETES_SERVICE_ACCOUNT_TOKEN_PATH) + if err != nil { + stream.Write([]byte(buildHttpInternalServerError("failed to read k8s sa auth token"))) + continue + } + req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", string(token))) + + // update the target URL to point to the kubernetes API server: + kubernetesServiceHost := os.Getenv(KUBERNETES_SERVICE_HOST_ENV_NAME) + kubernetesServicePort := os.Getenv(KUBERNETES_SERVICE_PORT_HTTPS_ENV_NAME) + + fullBaseUrl := fmt.Sprintf("https://%s:%s", kubernetesServiceHost, kubernetesServicePort) + targetURL = fullBaseUrl + + log.Info().Msgf("Redirected request to Kubernetes API server: %s", targetURL) } - req.Header.Del("x-infisical-action") + + req.Header.Del(INFISICAL_HTTP_PROXY_ACTION_HEADER) } // Build full target URL @@ -242,6 +277,11 @@ func handleHTTPProxy(stream quic.Stream, reader *bufio.Reader, targetURL string, log.Info().Msgf("Proxying %s %s to %s", req.Method, req.URL.Path, targetFullURL) + client := &http.Client{ + Transport: transport, + Timeout: 30 * time.Second, + } + resp, err := client.Do(proxyReq) if err != nil { log.Error().Msgf("Failed to reach target: %v", err) diff --git a/cli/packages/gateway/constants.go b/cli/packages/gateway/constants.go new file mode 100644 index 0000000000..aa260ed2e2 --- /dev/null +++ b/cli/packages/gateway/constants.go @@ -0,0 +1,17 @@ +package gateway + +const ( + KUBERNETES_SERVICE_HOST_ENV_NAME = "KUBERNETES_SERVICE_HOST" + KUBERNETES_SERVICE_PORT_HTTPS_ENV_NAME = "KUBERNETES_SERVICE_PORT_HTTPS" + KUBERNETES_SERVICE_ACCOUNT_CA_CERT_PATH = "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt" + KUBERNETES_SERVICE_ACCOUNT_TOKEN_PATH = "/var/run/secrets/kubernetes.io/serviceaccount/token" + + INFISICAL_HTTP_PROXY_ACTION_HEADER = "x-infisical-action" +) + +type HttpProxyAction string + +const ( + HttpProxyActionInjectGatewayK8sServiceAccountToken HttpProxyAction = "inject-k8s-sa-auth-token" + HttpProxyActionUseGatewayK8sServiceAccount HttpProxyAction = "use-k8s-sa" +) diff --git a/frontend/src/hooks/api/identities/types.ts b/frontend/src/hooks/api/identities/types.ts index f5e0f10650..6b00eb40ca 100644 --- a/frontend/src/hooks/api/identities/types.ts +++ b/frontend/src/hooks/api/identities/types.ts @@ -403,7 +403,7 @@ export type IdentityKubernetesAuth = { export type AddIdentityKubernetesAuthDTO = { organizationId: string; identityId: string; - kubernetesHost: string; + kubernetesHost: string | null; tokenReviewerJwt?: string; tokenReviewMode: IdentityKubernetesAuthTokenReviewMode; allowedNamespaces: string; @@ -422,7 +422,7 @@ export type AddIdentityKubernetesAuthDTO = { export type UpdateIdentityKubernetesAuthDTO = { organizationId: string; identityId: string; - kubernetesHost?: string; + kubernetesHost?: string | null; tokenReviewerJwt?: string | null; tokenReviewMode?: IdentityKubernetesAuthTokenReviewMode; allowedNamespaces?: string; diff --git a/frontend/src/pages/organization/AccessManagementPage/components/OrgIdentityTab/components/IdentitySection/IdentityKubernetesAuthForm.tsx b/frontend/src/pages/organization/AccessManagementPage/components/OrgIdentityTab/components/IdentitySection/IdentityKubernetesAuthForm.tsx index e43c94a7ee..d621997215 100644 --- a/frontend/src/pages/organization/AccessManagementPage/components/OrgIdentityTab/components/IdentitySection/IdentityKubernetesAuthForm.tsx +++ b/frontend/src/pages/organization/AccessManagementPage/components/OrgIdentityTab/components/IdentitySection/IdentityKubernetesAuthForm.tsx @@ -46,13 +46,13 @@ const schema = z tokenReviewMode: z .nativeEnum(IdentityKubernetesAuthTokenReviewMode) .default(IdentityKubernetesAuthTokenReviewMode.Api), - kubernetesHost: z.string().min(1), + kubernetesHost: z.string().min(1).optional().nullable(), tokenReviewerJwt: z.string().optional(), gatewayId: z.string().optional().nullable(), allowedNames: z.string(), allowedNamespaces: z.string(), allowedAudience: z.string(), - caCert: z.string(), + caCert: z.string().optional(), accessTokenTTL: z.string().refine((val) => Number(val) <= 315360000, { message: "Access Token TTL cannot be greater than 315360000" }), @@ -69,6 +69,17 @@ const schema = z .min(1) }) .superRefine((data, ctx) => { + if ( + data.tokenReviewMode === IdentityKubernetesAuthTokenReviewMode.Api && + !data.kubernetesHost + ) { + ctx.addIssue({ + path: ["kubernetesHost"], + code: z.ZodIssueCode.custom, + message: "When token review mode is set to API, a Kubernetes host must be provided" + }); + } + if (data.tokenReviewMode === IdentityKubernetesAuthTokenReviewMode.Gateway && !data.gatewayId) { ctx.addIssue({ path: ["gatewayId"], @@ -201,7 +212,13 @@ export const IdentityKubernetesAuthForm = ({ if (data) { await updateMutateAsync({ organizationId: orgId, - kubernetesHost, + ...(tokenReviewMode === IdentityKubernetesAuthTokenReviewMode.Api + ? { + kubernetesHost: kubernetesHost || "" + } + : { + kubernetesHost: null + }), tokenReviewerJwt: tokenReviewerJwt || null, allowedNames, allowedNamespaces, @@ -219,7 +236,13 @@ export const IdentityKubernetesAuthForm = ({ await addMutateAsync({ organizationId: orgId, identityId, - kubernetesHost: kubernetesHost || "", + ...(tokenReviewMode === IdentityKubernetesAuthTokenReviewMode.Api + ? { + kubernetesHost: kubernetesHost || "" + } + : { + kubernetesHost: null + }), tokenReviewerJwt: tokenReviewerJwt || undefined, allowedNames: allowedNames || "", allowedNamespaces: allowedNamespaces || "", @@ -278,22 +301,29 @@ export const IdentityKubernetesAuthForm = ({ Advanced - ( - - - - )} - /> + {tokenReviewMode === IdentityKubernetesAuthTokenReviewMode.Api && ( + ( + + + + )} + /> + )}
@@ -384,7 +414,7 @@ export const IdentityKubernetesAuthForm = ({ />
- {tokenReviewMode === "api" && ( + {tokenReviewMode === IdentityKubernetesAuthTokenReviewMode.Api && ( )} /> - ( - -