- Go 91.1%
- Go Template 5.2%
- Nix 2.7%
- Makefile 1%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| .forgejo/workflows | ||
| cmd/oidc-discovery-proxy | ||
| deploy/charts/oidc-discovery-proxy | ||
| proxy | ||
| .envrc | ||
| .gitignore | ||
| .goreleaser.yaml | ||
| Dockerfile.goreleaser | ||
| flake.lock | ||
| flake.nix | ||
| go.mod | ||
| Makefile | ||
| README.md | ||
| renovate.json | ||
OIDC discovery proxy
This service adapts authenticated Kubernetes ServiceAccount issuer discovery for
anonymous OIDC consumers such as KCP. It periodically reads a projected
ServiceAccount token, fetches and validates upstream discovery and JWKS,
rewrites only jwks_uri, then atomically publishes both documents.
Endpoints
GET/HEAD /.well-known/openid-configurationGET/HEAD /openid/v1/jwksGET/HEAD /healthz: live whenever the HTTP process is runningGET/HEAD /readyz:503before the first successful full refresh; remains ready with the last-known-good snapshot during later failures
Other methods return 405; other paths return 404. All responses use
application/json.
Flags
| Flag | Default | Purpose |
|---|---|---|
-listen-address |
:8443 |
Serving address |
-upstream-discovery-url |
Kubernetes in-cluster issuer discovery URL | Authenticated discovery source |
-upstream-jwks-url |
unset | Optional trusted authenticated JWKS URL override |
-expected-issuer |
https://kubernetes.default.svc.cluster.local |
Exact required discovery issuer |
-public-base-url |
in-cluster proxy HTTPS URL | Base used for rewritten jwks_uri |
-token-file |
default projected SA token | Bearer token, reread every refresh |
-upstream-ca-file |
system roots | Optional additional PEM CA certificates |
-allow-insecure-upstream-http |
false |
Permit token-bearing HTTP upstream requests for local tests only |
-refresh-interval |
5m |
Refresh period |
-request-timeout |
10s |
Per-upstream-request timeout; a full refresh has twice this total budget |
-tls-cert-file, -tls-key-file |
unset | Serving TLS pair; both are required together |
-tls-reload-interval |
1m |
Polling period for serving certificate rotation |
Local development
nix run nixpkgs#go -- test ./...
nix run nixpkgs#go -- run ./cmd/oidc-discovery-proxy \
-listen-address=:8080 \
-upstream-discovery-url=http://127.0.0.1:9000/.well-known/openid-configuration \
-allow-insecure-upstream-http \
-expected-issuer=https://kubernetes.default.svc.cluster.local \
-public-base-url=http://127.0.0.1:8080 \
-token-file=/tmp/token
Inside a Go-enabled development shell, make check verifies module tidiness,
formats, vets, race-tests, and builds the service. On a Nix host without Go
installed globally, run individual commands as
nix run nixpkgs#go -- <command>.
Release
Forgejo Actions validate every branch and pull request with Go tests, GoReleaser
snapshot builds, and Trivy scans of both supported container architectures. Tags
matching v* create Forgejo releases and publish linux/amd64 and
linux/arm64 images to the Forgejo package registry through GoReleaser.
Dockerfile.goreleaser is the sole supported image build path.
Security
The proxy exposes only validated public OIDC metadata. Upstream requests always
carry the token, redirects are rejected, responses are size-limited, and logs
contain neither token nor response body. By default, a discovered jwks_uri
must have the exact same origin (scheme, hostname, and effective port) as the
configured discovery URL, preventing bearer-token forwarding to another host.
JWKS keys must be objects with a non-empty kty.
Some Kubernetes API servers advertise a jwks_uri on a different API origin,
such as a host IP and dynamic port. In that case, explicitly set
-upstream-jwks-url to the operator-trusted authenticated endpoint, typically
https://kubernetes.default.svc/openid/v1/jwks, while retaining
-expected-issuer=https://kubernetes.default.svc.cluster.local. The advertised
URI must remain syntactically valid, but the proxy fetches only the configured
override. An override is an explicit trust boundary and therefore need not share
the discovery origin.
Token-bearing upstream traffic requires HTTPS by default. TLS verification
cannot be disabled; -upstream-ca-file extends system roots. The explicit
-allow-insecure-upstream-http escape hatch is only for local tests. Production
serving should supply a certificate/key and restrict the ServiceAccount to
discovery access. Each request has -request-timeout; the complete
discovery-plus-JWKS refresh is also canceled after twice that duration and on
process shutdown.
Kubernetes Secret projection updates are eventually propagated to the mount. The TLS reload interval is therefore a polling interval and practical lower bound, not a strict upper bound on when a new certificate becomes visible.