Skip to content
Development docs · last release v1.8.1 · tested on Kubernetes 1.35 to 1.37Release notes

Changelog

  • Enable the metrics listener and dedicated Service automatically when the Helm ServiceMonitor switch is enabled, with setup guidance and unchanged opt-out defaults.

  • Bump golang.org/x/net from 0.58.0 to 0.60.0 to fix 5 govulncheck findings in the HTTP/2 code that the proxy calls. Also bump golang.org/x/crypto to 0.57.0, x/mod to 0.41.0, x/sync to 0.23.0, x/sys to 0.48.0, x/term to 0.46.0 and x/text to 0.42.0.

  • A documentation website with a product landing page, the guides and references from docs/ and a version banner, published to GitHub Pages from a gated workflow.

  • The Helm chart renders the helm test connection hook image from test.image.repository and test.image.tag (default docker.io/library/busybox:1.37.0) instead of a bare busybox literal, so image mirrors can redirect it.

  • Enrol in the OpenSSF Best Practices Badge, with proposed answers in .bestpractices.json, the badge in the README, explicit bug and vulnerability reporting links, and a release-notes rule that security fixes name their advisory.

  • Bump google.golang.org/grpc from 1.83.1 to 1.83.2 (the gRPC server now rejects requests missing both :authority and Host headers), go.opentelemetry.io/otel, otel/sdk, otel/exporters/otlp/otlptrace and otlptracegrpc from 1.44.0 to 1.45.0, and golang.org/x/crypto from 0.55.0 to 0.56.0 to remediate GO-2026-6354 and GO-2026-6355.

  • Build against Go 1.26.10, which fixes a crypto/x509 certificate verification vulnerability (CVE-2026-111943, golang/go#82345). The proxy uses crypto/x509 to verify client TLS certificates and the TLS certificates of OIDC issuers.

  • Document that an issuer entry in --authentication-config may list several audiences with audienceMatchPolicy: MatchAny, and cover it in the unit and end-to-end suites: a token carrying any listed audience is accepted, one carrying none is rejected, and an audience listed for one issuer does not admit tokens from another.

  • Load the Helm chart’s structured OIDC authentication configuration from an existing Secret with a configurable key.
  • Configure single-issuer OIDC in the Helm chart through environment variables sourced from an existing Secret, with configurable keys for required and optional settings.
  • The Helm chart can enable the metrics endpoint (metrics.enabled), rendering the flag, a named container port and a dedicated ClusterIP Service <release>-metrics that is never part of the main Service, plus an optional Prometheus Operator ServiceMonitor or PodMonitor, an empty PrometheusRule and a NetworkPolicy that admits only the listed peers to the metrics port while keeping the proxy and readiness ports open.
  • Bump github.com/prometheus/client_golang from 1.24.0 (indirect) to a direct dependency at 1.24.1, which fixes a promhttp panic on requests carrying a nil URL, ahead of the proxy exposing a Prometheus metrics endpoint.
  • Three Grafana dashboards (overview, security and identity, capacity and dependencies) shipped by the chart as a sidecar-loaded ConfigMap when metrics.dashboards.enabled is set, a data-flow diagram of where the metrics attach in docs/metrics.md, and a reproducible kind demo (make metrics_demo_up) that installs the chart with Prometheus and Grafana, generates every kind of traffic, verifies every panel has data and captures the documented screenshots.
  • The proxy now refuses to start when two configured issuers share a host (for example https://idp.example.com/realms/a and https://idp.example.com/realms/b). Issuers are identified by host in every log record and metric series, so such a configuration could not be reported unambiguously. Give each issuer its own host.
  • A 1xx informational response forwarded from the API server (for example 103 Early Hints) is no longer recorded as the request’s final http_status in the request.response.completed record; only the final status is.
  • Metrics for authentication attempts, access decisions by reason, TokenReview and SubjectAccessReview API calls and latency, review cache hits and misses, per-issuer initialization, readiness and observable audit backend failures, documented in docs/metrics.md as a versioned contract generated from the code and verified in CI.
  • An opt-in Prometheus metrics endpoint. --metrics-bind-address=host:port serves GET /metrics over plain HTTP on a dedicated listener with request counters, a latency histogram that excludes long-running requests, in-flight and open-stream gauges and build information. Off by default; every label value comes from a closed set, so no identity, path or client-chosen value ever becomes a series.
  • The Helm chart’s ClusterRole now lets the proxy’s ServiceAccount create SubjectAccessReviews. The proxy authorizes every inbound Impersonate-* header value with one before forwarding, so on a chart install every kubectl --as request failed with HTTP 500 and reason=internal_error (authz.sar.failed carried cannot create resource "subjectaccessreviews"). The end-to-end suite grants this in its own fixture, which is why it never surfaced there. Plain token requests were unaffected.
  • The Helm chart’s ClusterRole now grants impersonate on userextras/<key> for every claimMappings.extra[].key declared in authenticationConfig.content, plus any keys listed in the new rbac.userExtras value. Previously an issuer that mapped extra claims had every request rejected with 403, because the API server authorizes each Impersonate-Extra-<key> header separately and the chart only granted a fixed set of keys. The chart’s development baseline appVersion is 1.7.0.
  • Every namespaced object the Helm chart renders now carries metadata.namespace set to the release namespace. helm install was unaffected, but helm template ... | kubectl apply -f placed the Deployment, Service, ServiceAccount, Secrets and Ingress in the caller’s current namespace while the ClusterRoleBinding still named the rendered one, so a proxy applied that way ran without its RBAC grants. Manifests rendered for GitOps now land in the namespace they were rendered for.
  • Security denials now appear at the default verbosity as AuFail records with a reason; the readiness transition is INFO; “issuers pending” is logged on change only; Kubernetes library output is JSON under component=k8s.
  • Operational log messages changed value. The access record’s msg was proxied request or rejected request and is now access decision for both, with the outcome in the frozen event field (AuSuccess/AuFail); other records carry new msg text as well. Queries and alerts must key on event_type (and event for the access record), not on msg, which is descriptive and not part of the contract.
  • The access log no longer emits the original user’s full extra-claims map under outbound_extra, and configured impersonation header values are no longer logged at any verbosity.
  • One JSON log stream with a per-request request_id (also sent upstream as Audit-ID), a closed event_type registry documented in docs/logging.md, and --logging-format.
  • Helm chart now deploys the image matching its appVersion by default. Charts 1.2.0 through 1.6.0 shipped with a hardcoded image.tag of 1.1.0, so installs without an explicit image.tag override ran the 1.1.0 binary; the release pipeline now refuses to publish a chart whose default image tag differs from the release version.
  • Bump github.com/google/cel-go to v0.30.0 and go.etcd.io/etcd/{api,client/pkg,client}/v3 to v3.7.1 to remediate GO-2026-6094 and GO-2026-6107.
  • Impersonation requests are now capped at a configurable number of Impersonate-* header values (—max-impersonation-header-values, default 64). Requests exceeding the cap are rejected with HTTP 431 before any SubjectAccessReview is sent, bounding the per-request authorization load a client can generate.
  • Impersonation SubjectAccessReview decisions are now served from a bounded in-memory cache with separately configurable TTLs (—subject-access-review-cache-allow-ttl and —subject-access-review-cache-deny-ttl, default 10s, 0 disables). Revoking or granting an RBAC impersonation permission can take up to the corresponding TTL to be enforced through the proxy.
  • Token passthrough now caches TokenReview results in a bounded in-memory cache with separately configurable TTLs (—token-passthrough-cache-success-ttl and —token-passthrough-cache-failure-ttl, default 10s, 0 disables). A revoked token can continue to pass for up to the success TTL and a newly valid token can be rejected for up to the failure TTL.
  • Audit event sourceIPs now follow the trusted-proxy contract — forwarded headers from untrusted peers are stripped before auditing and before the request is forwarded upstream, so clients can no longer spoof the audit trail via X-Forwarded-For. Operators with a load balancer in front of the proxy must set —trusted-proxies to resolve the real client IP.
  • Unauthenticated (401) requests now produce audit events — the unauthorized audit chain initialises the audit context, so failed authentication attempts are recorded with a ResponseStarted event instead of leaving no trace in the audit log.
  • Update k8s.io modules to v0.37.0, sigs.k8s.io/kind to v0.33.0, and test dependencies; refresh the distroless base image digest and move test tool images to alpine 3.24; bump all pinned GitHub Actions to current releases.
  • Pull request e2e runs now exercise the full supported Kubernetes window (currently 1.37.0, 1.36.4, 1.35.8) instead of only the newest minor; the release path stays newest-only since the same code already passed the full window on its pull request.
  • Test and CI tooling now targets Kubernetes 1.37 — the e2e suite boots kindest/node v1.37.0 by default, the kind CLI in the e2e workflows moves to v0.33.0 (kubeadm v1beta4 support, required since 1.37 dropped v1beta3), and the Makefile kubectl download fallback moves to v1.37.0.
  • UID impersonation works end to end — an authorized Impersonate-Uid header is forwarded to the API server, the impersonation check reviews uids in the authentication.k8s.io group, and the chart grants the proxy impersonate on uids and on the originaluser.jetstack.io-uid extra. Deployments that map a uid claim now emit Impersonate-Uid and need the new RBAC.
  • New —token-passthrough-request-timeout flag bounds each TokenReview call the proxy makes when validating a passthrough token (default 10s, previously hardcoded).
  • Replace —allow-reserved-identity-claims with —allow-reserved-groups, which permits named system:-prefixed groups instead of disabling the reserved-identity guard wholesale. Reserved usernames can no longer be permitted at all. The flag it replaces was added after v1.2.0 and has not appeared in a release.
  • Update go.opentelemetry.io/otel to v1.44.0 and golang.org/x/mod to v0.40.0, clearing three advisories reported against the dependency tree.
  • Harden CI — scope the Prepare Release and GitHub Actions OIDC e2e workflow tokens to the jobs that need them, and stop the e2e fake API server from logging request header values or echoing a caller-controlled body as sniffable content.
  • Build against Go 1.26.6, which resolves six reachable Go standard library advisories in crypto/tls, net/http, net/url, html/template, and encoding/asn1.
  • Log OIDC token validation failures at -v=2 with the resolved remote address, instead of -v=5. An error from the bearer-token authenticator always means a token was present and failed validation, so it was previously invisible at any verbosity operators run. Request routing is unchanged.
  • The readiness endpoint now reports not-ready until the proxy is actually serving, instead of reporting ready as soon as an OIDC issuer initialized. Previously the readiness server started before the proxy’s handler chain did, so a pod could join its Service while requests to the proxy port could only queue.
  • Audit streaming requests as long-running — exec, attach, portforward, log and proxy are now recorded when the response starts instead of only when the stream ends, so a long session is no longer missing from the audit log while it runs, or entirely if the proxy dies first. These requests now emit a ResponseStarted event as well as ResponseComplete, so audit volume for exec, attach and portforward increases.
  • Refuse authenticated identities carrying the Kubernetes-reserved system: prefix from token claims, so an OIDC issuer can no longer mint system:masters or a service-account username through the proxy’s blanket impersonation rights. The check runs before the SubjectAccessReview that authorizes inbound impersonation, and the 403 is audited against the identity that was presented. system:authenticated remains permitted as a group because the proxy adds it to every request itself. Name specific reserved groups in --allow-reserved-groups if a directory legitimately holds one.
  • Audit requests to the core API group (/api/…) are now classified correctly. The audit server config named no legacy API prefix, so every core group request — which is where pods and services live, and with them exec, attach, portforward, log and proxy — was recorded as a non-resource request, with the lowercased HTTP method as its verb and no objectRef, and neither the long-running check nor a watch could ever be recognised. Audit events for these requests now carry the Kubernetes verb (list, create, watch and so on) and an objectRef naming the resource, namespace, name and subresource. If you parse audit logs or write audit policy rules matching on verb or resource, expect the corrected values.

enhancements:

  • Multi-issuer OIDC authentication via —authentication-config (AuthenticationConfiguration v1/v1beta1), based on #85 with strict versioned config loading, whole-document validation, a shared CEL compiler and configurable readiness (—readiness-require-all-issuers)

tasks:

  • 1.0.12 build #83

bugs:

  • Critical Vulnerability CVE-2025-68121 #78

tasks:

  • 1.0.10 build #74

tasks:

enhancements:

  • Add flags to be able to configure kubernetes client throttling #65

tasks:

enhancements:

  • change oidc config to line up with new kube authenticator #55

tasks:

  • 1.0.7 Release #54

bugs:

  • e2e tests failing to complete #45
  • Auditing is not working anymore #39

tasks:

  • 1.0.6 build #41

tasks:

  • 1.0.5 build #34

tasks:

  • 1.0.4 build #29

enhancements:

  • 1.0.3 release #26

bugs:

  • CVE-2022-1996 #20

enhancements:

bugs:

  • fix timing issues in e2e tests #18
  • runtime error: slice bounds out of range [:-2] #17

enhancements:

  • 1.0.0 Release #10
  • Access logging to standard out #2
  • create github action to automate builds #8
  • Switch from alpine —> ubuntu 20.04 #9
  • Support kubectl --as #3
  • Upgrade KinD #1

bugs:

  • update dependencies #5