Skip to content

feat(gateway): add Kubernetes auth for gateway enrollment - #7525

Merged
bernie-g merged 27 commits into
mainfrom
bernie/pam-341-add-kubernetes-auth-support-for-gateway-enrollment
Aug 20, 2026
Merged

feat(gateway): add Kubernetes auth for gateway enrollment#7525
bernie-g merged 27 commits into
mainfrom
bernie/pam-341-add-kubernetes-auth-support-for-gateway-enrollment

Conversation

@bernie-g

@bernie-g bernie-g commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Context

Adds Kubernetes auth as a third gateway auth method alongside aws and token. The gateway authenticates with its own pod's service account token, which Infisical verifies against the cluster's TokenReview API, so no enrollment token needs distributing to the cluster.

Requires Infisical/cli#353. PAM-341.

Screenshots

New "Kubernetes Auth" option under Authentication on the gateway detail page.

Steps to verify the change

  1. Set a gateway's Authentication to Kubernetes Auth, fill in the cluster host and one allowlist.
  2. Deploy it with the Helm chart using gateway.enrollment.method=kubernetes.
  3. Gateway reports Healthy.

Type

  • Fix
  • Feature
  • Improvement
  • Breaking
  • Docs
  • Chore

Checklist

  • Title follows the conventional commit format: type(scope): short description (scope is optional, e.g., fix: prevent crash on sync or fix(api): handle null response).
  • Tested locally
  • Updated docs (if needed)
  • Updated CLAUDE.md files (if needed)
  • Read the contributing guide

@mintlify

mintlify Bot commented Aug 4, 2026

Copy link
Copy Markdown

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated (UTC)
infisical 🟢 Ready View Preview Aug 4, 2026, 5:45 PM

💡 Tip: Enable Workflows to automatically generate PRs for you.

@infisical-review-police

Copy link
Copy Markdown

💬 Discussion in Slack: #pr-review-infisical-7525-feat-gateway-add-kubernetes-auth-for-gateway-enrollment

Posted by Review Police — reviews, comments, new commits, and CI failures will stream into this channel.

@linear

linear Bot commented Aug 4, 2026

Copy link
Copy Markdown

PAM-341

@greptile-apps

greptile-apps Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

Adds Kubernetes service-account authentication for gateway enrollment, including TokenReview validation, encrypted configuration storage, gateway UI and deployment commands, Helm support, API schemas, and documentation.

  • Adds create, update, login, view, and revoke handling for the Kubernetes resource-auth method.
  • Adds allowlists for namespaces, service-account names, and audiences.
  • Adds Kubernetes-focused gateway configuration and Helm deployment flows.

Confidence Score: 4/5

The PR should not merge until the DNS-rebinding credential-disclosure path and the mismatched update-time validation are fixed.

Kubernetes login resolves a user-controlled host without pinning the address while transmitting service-account credentials and trusting its response, and configuration updates can validate different credentials from those retained for subsequent logins.

Files Needing Attention: backend/src/ee/services/resource-auth-method/kubernetes-auth-fns.ts; backend/src/ee/services/resource-auth-method/resource-auth-method-service.ts

Security Review

The TokenReview request resolves a previously validated user-controlled hostname again without IP pinning, leaving a DNS-rebinding path to internal endpoints that carries Kubernetes credentials and trusts the returned authentication verdict.

Important Files Changed

Filename Overview
backend/src/ee/services/resource-auth-method/kubernetes-auth-fns.ts Implements host checks, TokenReview calls, and allowlists, but the request remains vulnerable to DNS rebinding because it does not pin the validated address.
backend/src/ee/services/resource-auth-method/resource-auth-method-service.ts Adds the Kubernetes auth lifecycle and encrypted secrets, but update-time validation can use a different credential set from the effective persisted configuration.
backend/src/ee/routes/v3/gateway-router.ts Adds validated Kubernetes configuration and login API variants with audit and telemetry handling.
backend/src/ee/services/gateway-v2/gateway-v2-service.ts Integrates Kubernetes configuration validation and encryption into gateway creation before opening the database transaction.
backend/src/db/migrations/20260804134122_resource-kubernetes-auth.ts Adds the Kubernetes auth configuration table with encrypted credential columns and cascading ownership.
helm-charts/infisical-gateway/templates/deployment.yaml Adds Kubernetes enrollment arguments and validates service-account token mounting requirements.
frontend/src/pages/organization/NetworkingPage/components/NetworkingAuthMethodForm.tsx Adds the gateway-only Kubernetes auth form, allowlists, optional reviewer credentials, and explicit TLS behavior controls.

Reviews (1): Last reviewed commit: "feat(gateway): add Kubernetes auth for g..." | Re-trigger Greptile

Comment thread backend/src/ee/services/resource-auth-method/kubernetes-auth-fns.ts Outdated
Comment thread backend/src/ee/services/resource-auth-method/kubernetes-auth-fns.ts Outdated
Comment thread backend/src/ee/services/resource-auth-method/kubernetes-auth-fns.ts Outdated
@veria-ai

veria-ai Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

PR overview

All previously flagged issues have been addressed. No open security concerns remain on this pull request.

Security review

No open security issues remain on this pull request.

Fixed/addressed: 11 · PR risk: 0/10

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 77647efe76

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread backend/src/ee/services/resource-auth-method/kubernetes-auth-fns.ts Outdated
Comment thread helm-charts/infisical-gateway/templates/deployment.yaml
Gateways are deployed in-cluster, so they can authenticate with the projected
service account token of their own pod instead of being handed an enrollment
token. This removes the credential-distribution step that made automated
gateway creation awkward.

Backend:
- New resource_kubernetes_auths table holding the cluster host, namespace and
  service account allowlists, an optional audience, and KMS-encrypted CA
  certificate and token reviewer JWT.
- kubernetes added as a third ResourceAuthMethodType alongside aws and token,
  wired through create, update, read, revoke, and a new loginWithKubernetes.
- Login submits a TokenReview to the cluster's API server, then checks the
  reviewed namespace, service account, and audience against the allowlists
  before minting a GATEWAY_ACCESS_TOKEN.
- At least one allowlist is required, enforced in the route schema and again in
  the service, so an unrestricted config cannot authenticate any pod.
- Host is checked against private address ranges and for reachability at config
  time, reusing the identity Kubernetes auth validators so a misconfiguration
  surfaces on save rather than at gateway start.
- Audit log and telemetry carry the new method, plus the reviewed namespace and
  service account on success and a reason code on failure.
- Extracted the auth-method view schema that was triplicated across the gateway,
  relay, and KMIP routers into one shared module.

Frontend:
- Kubernetes option in the gateway auth method form, with placeholders and
  tooltips matching the machine identity Kubernetes auth page.
- Deployment card gains Helm and container-command tabs for this method.
- Removed the read-view components orphaned by the v3 UI migration; the
  always-editable form is the display now.

Docs and chart:
- Kubernetes auth documented in gateway deployment, the CLI command reference,
  and the Helm chart reference.
- Chart 1.3.0 adds gateway.enrollment.method=kubernetes with gatewayId and an
  optional service account token path.

The CA certificate round-trips through the API since it is public key material
already mounted into every pod. The reviewer JWT is a live cluster credential
and is never returned, only reported as configured, following the alert channel
convention for secret fields.
@bernie-g
bernie-g force-pushed the bernie/pam-341-add-kubernetes-auth-support-for-gateway-enrollment branch from 77647ef to 5009b21 Compare August 4, 2026 17:54
Comment thread backend/src/ee/services/resource-auth-method/kubernetes-auth-fns.ts
Addresses review findings on the Kubernetes auth path.

- TokenReview now goes through safeRequest, which validates and pins the
  connection to the addresses it resolved. The config-time host check could not
  stop a hostname that re-resolved to a private address before login, which let
  an unauthenticated login POST the reviewer JWT and service account token to an
  internal endpoint, and trust a forged TokenReview response back from it.
- verifyTlsCertificate is honoured as configured instead of being silently
  dropped when no CA is set. A cluster CA is not in the system trust store, so
  that combination now fails the config-time check with a TLS error rather than
  quietly authenticating over an unverified connection. Turning verification off
  is still an explicit choice.
- setMethod validates the host against the credentials that will actually be
  stored. Omitting a secret keeps the stored one, so validating with only what
  the request carried checked a different config than the one a gateway would
  later log in with.
- Chart records that Kubernetes enrollment needs a CLI image containing
  --enroll-method=kubernetes, since the default tag predates it.
The Kubernetes host is operator-supplied and the login route is unauthenticated,
so cap how much of the response Axios will buffer.
Comment thread backend/src/ee/services/resource-auth-method/kubernetes-auth-fns.ts Outdated
Bumps image.tag from 0.43.84 to 0.43.118, and the two places the helm docs
mirror it. 0.43.118 does not exist yet: it is the next release after v0.43.117
and needs to be the one that carries Infisical/cli#353, so this has to be
confirmed when that release is cut.
The preflight reused the identity Kubernetes auth validators, which run a DNS
safety check and then issue the request on a separate lookup. A rebinding
hostname could pass the check on a public address and resolve to a private one
for the request itself, so a gateway editor could make the backend probe
internal hosts and could leak a supplied reviewer JWT to them.

Both preflight calls now go through safeRequest, which pins the connection to
the addresses it validated, and the response size is bounded like the login
path. Error classification is preserved, so the messages for an unresolvable
host, a failed certificate check, and a reviewer without system:auth-delegator
are unchanged.
Revoking a Kubernetes-auth gateway returns "kubernetes", which the frontend type
did not allow. Nothing branches on it today, so this was a silent type lie rather
than a visible bug.
Drops the three-line explanation above the kubernetes block in values.yaml and
the copy of it in the chart docs. The per-key comments below it already say what
each value is for.
Preserving the stored reviewer JWT for validation, added so the preflight checks
the config that will actually be stored, meant the credential travelled to
whatever host the request carried. Someone with gateway edit access could point
the host at a server they control, omit the write-only field, and read the token
off the Authorization header.

The stored token is now only reused when the host is unchanged. Changing the host
requires re-entering it, or sending an empty value to remove it. Both earlier
properties still hold: the preflight validates the credentials that will be
stored, and a host and reviewer pair is never stored unvalidated.
Comment thread helm-charts/infisical-gateway/templates/deployment.yaml
Comment thread backend/src/ee/services/resource-auth-method/kubernetes-auth-fns.ts Outdated
Comment thread backend/src/ee/services/resource-auth-method/kubernetes-auth-fns.ts
Comment thread backend/src/ee/routes/v3/gateway-router.ts Outdated
Comment thread backend/src/@types/knex.d.ts
Comment thread backend/src/@types/knex.d.ts
- kubernetesHost is normalised and validated in one place. The scheme is matched
  case-insensitively, so "HTTPS://host" no longer becomes "https://HTTPS://host"
  and "HTTP://host" no longer slips past the https-only check. A path, query or
  credentials are rejected, which is what let a typo'd host save and then kill
  the gateway on startup. The stored value is canonical, so a trailing slash no
  longer reads as a host change.
- The preflight also rejects a 404 from /version, since that means the address
  does not serve the Kubernetes API. 401 and 403 are still allowed, because
  /version can require authentication.
- The form can remove a stored token reviewer JWT again. Without it, changing the
  host was a dead end: the guard requires the token re-entered or cleared, and a
  blank field means keep.
- Corrected the Verify TLS tooltip, which still claimed the toggle only takes
  effect with a CA certificate. It is honoured either way, and without a CA the
  system trust store is used, which a cluster CA will not be in.
- Installing with serviceAccount.createAsAuthDelegator disabled now fails unless
  gateway.enrollment.kubernetes.externalTokenReview is set. Previously the
  install succeeded, the pod ran, and the gateway silently never connected.
- Login failure reason codes, the TokenReview apiVersion/kind/path and the probe
  token are consts rather than repeated literals.
Comment thread backend/src/ee/services/resource-auth-method/resource-auth-method-service.ts Outdated
…n guard

Selecting a gateway or pool to review through now requires AttachGateways,
and a pool additionally requires the gateway pool entitlement. Machine
identity Kubernetes auth gates its gateway selection the same way; this path
only checked that the gateway existed in the org.

The preservation guard also compared the host alone, so a preserved reviewer
token could be redirected by routing it through a different gateway, trusting
a different CA, or turning TLS verification off, none of which changed the
host. It now covers every input that decides where the token travels and who
can read it in transit.

The stored CA is decrypted before the comparison rather than after, so an
unchanged config still saves without re-entering the token.
…stor

In gateway review mode the selected gateway supplies the TokenReview verdict,
so it decides every login for the gateway that points at it. A pool is the
wrong shape for that: its membership can change after the config is saved,
under a permission unrelated to editing the gateway being protected, so a
pool editor could add a gateway they control and have it authenticate as
the protected one.

Pools remain available for the token reviewer JWT mode, where the gateway
only carries traffic and the API server still decides.
Comment thread backend/src/ee/services/resource-auth-method/resource-auth-method-service.ts Outdated
Attaching a gateway pool was gated on AttachGateways, so a role granted that
but denied attach-gateway-pools could still route TokenReview traffic through
a pool. Each proxy type now requires its own attach permission.
…bernetes-auth-support-for-gateway-enrollment

# Conflicts:
#	helm-charts/infisical-gateway/CHANGELOG.md
…ation

The committed schema listed the new columns after the timestamps, which is
the order my dev database happened to have them in after the columns were
added by hand. Running the migration from scratch produces the declared
order, so the generated file never matched and the schema check failed.
A rejected review comes back as a Status object, where `status` is the
string "Failure" rather than a review result. The truthiness check passed it
through and the `in` operator then threw on a string, turning a denied login
into a 500 with no explanation.

Reject anything that is not an object and surface the API server's own
message, so an expired reviewer token reads as "did not return a token
review: Unauthorized" instead.
Selecting a pool that contains the gateway being configured was accepted, and
the request then hung: pool selection can pick the very gateway trying to
authenticate, which cannot vouch for itself because the proxy runs over a
tunnel that only exists after it has authenticated.

A gateway that is down has no heartbeat and would not be picked, so this only
bites while a stale heartbeat is still inside its TTL, which is exactly the
restart case the proxy exists to serve.

The check moves into the service, where the pool membership DAL is reachable,
and now covers both a directly selected gateway and pool membership.
The API field carried the database column name, gatewayV2Id. That "V2" only
exists to separate the column from a legacy v1 gateway reference, a
distinction gateways v3 does not have, and machine identity Kubernetes auth
already exposes plain gatewayId while mapping to the same column.

It also sat next to gatewayPoolId, which carries no V2, so the pair read as
though they pointed at different generations of the same thing.

The column keeps its name to match the identity table and the gateways_v2
foreign key; only the request and response fields change.
The dialog printed a helm repo URL for a host that does not exist, so copying
the command failed at the first line. Use the URL the docs use, and note that
the CLI form runs inside the cluster, since it reads the pod's service account
token and so cannot reach a loopback address.

Reviewer cycles are also now refused. Pointing a gateway at a reviewer that
eventually reviews back through it left both unable to authenticate, each
waiting on a tunnel the other had not built. The walk is depth bounded, which
also keeps a cycle already in the data from spinning.
…view mode

Gateway review mode is exempt from the reviewer preservation guard, because
the token is not sent anywhere in that mode. That exemption let a host be
parked: switch to gateway mode with a new host, which stores it without
requiring the write-only token, then switch back to API mode where the host
already matches and so does not count as a destination change. The preserved
token was then sent to it.

Two layers. The review mode now counts as part of the destination, so any
transition requires re-entering the token. And a host is refused outright in
gateway review mode, where it is unused, which removes the parking step.
Comment thread backend/src/@types/knex.d.ts
Comment thread backend/src/@types/knex.d.ts
…reviewer

Editing the host with a reviewer token configured was rejected outright,
which is a confusing wall for an ordinary edit. The concern was real, the
stored token must not reach an address it was never validated against, but
refusing the save is the wrong way to hold that line.

Follow what PAM account updates already do and test only with credentials
supplied in the request: the stored token is kept, and simply is not used
against a destination it has not been validated against. The reviewer probe
is skipped until the token is supplied again, so a bad token surfaces at the
next login rather than at save.

The config-time preflight also stops attaching the reviewer in gateway review
mode, matching the login path, where the gateway reviews with its own service
account and ours would only be exposed to it.
Comment thread backend/src/ee/services/resource-auth-method/resource-auth-method-service.ts Outdated
Deleting an organisation cascades away both a reviewer gateway and the auth
config pointing at it, but the inbound constraint was checked at statement
time, so it fired before the cascade had removed the referencer and the
delete failed as a 500.

Defer the check to COMMIT, by which point both rows are gone. RESTRICT is not
deferrable in Postgres even when the constraint is declared so, hence NO
ACTION, which gives the same protection for a direct gateway delete: that is
still refused while another gateway reviews through it, and the delete path
names the dependents before it gets that far.
Preserving it only guarded the config-time probe. The next gateway login
decrypts the same token and sends it as a bearer to whatever destination is
now stored, so pointing the host at a server you control still captured it.

Clear it instead. The save succeeds, which is what made refusing it the wrong
answer, and the credential does not follow the config somewhere it was never
authorised for. The response reports it as no longer configured, so the
operator sees they need to supply one for the new destination.

An edit that changes nothing still keeps the stored token.
…bernetes-auth-support-for-gateway-enrollment

# Conflicts:
#	frontend/src/pages/organization/NetworkingPage/GatewayDetailsByIDPage/components/GatewayDeploySection/GatewayDeploySection.tsx
@gitguardian

gitguardian Bot commented Aug 19, 2026

Copy link
Copy Markdown

⚠️ GitGuardian has uncovered 1 secret following the scan of your pull request.

Please consider investigating the findings and remediating the incidents. Failure to do so may lead to compromising the associated services or software components.

🔎 Detected hardcoded secret in your pull request
GitGuardian id GitGuardian status Secret Commit Filename
35997175 Triggered Username Password 4663b19 backend/src/ee/services/dynamic-secret/providers/models.test.ts View secret
🛠 Guidelines to remediate hardcoded secrets
  1. Understand the implications of revoking this secret by investigating where it is used in your code.
  2. Replace and store your secret safely. Learn here the best practices.
  3. Revoke and rotate this secret.
  4. If possible, rewrite git history. Rewriting git history is not a trivial act. You might completely break other contributing developers' workflow and you risk accidentally deleting legitimate data.

To avoid such incidents in the future consider


🦉 GitGuardian detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request.

0.43.118 predated the CLI change, so the chart defaulted to an image whose
gateway command rejects --enroll-method=kubernetes. 0.43.123 is the first
release cut after it landed.
@bernie-g
bernie-g merged commit ad43367 into main Aug 20, 2026
18 of 21 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants