kube-rbac-proxy: putting an RBAC check in front of a single upstream
Kubernetes RBAC authorizing HTTP proxy for a single upstream.
At a glance
- What is it?
- kube-rbac-proxy is a small HTTP proxy that sits in front of one upstream and authorizes each request against the Kubernetes API with a SubjectAccessReview, so a pod needs a valid RBAC granted token or client certificate to reach the service behind it. It exists because without NetworkPolicies any pod can talk to any other pod, and the price is a component that the project itself still labels alpha while trying to align with upstream Kubernetes conventions.
- Who is it for?
- Adopt kube-rbac-proxy if you need to expose one service to other workloads in a cluster and want the check to be an RBAC decision rather than a hand written token check, since the SubjectAccessReview path means the same roles and bindings you already manage decide access.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 31 days ago.
- What is it written in?
- Mainly Go, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 24, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The gap it fills: no NetworkPolicies means every pod can reach every pod
The problem statement is one sentence and it is worth quoting precisely, because the whole design follows from it. In Kubernetes clusters without NetworkPolicies any Pod can perform requests to every other Pod in the cluster, and the proxy was developed in order to restrict requests to only those Pods that present a valid and RBAC authorized token or client TLS certificate.
So the unit of protection is a service, not a network segment. You point the proxy at one upstream, and a request arriving at the proxy is forwarded only if the caller presents a credential that Kubernetes RBAC says may perform that action.
The authorization primitive is SubjectAccessReview, the Kubernetes API object that asks the API server whether a given subject can perform a given verb on a given resource in a given namespace. That is what makes this different from a hand rolled check. Instead of the proxy deciding what is allowed, it asks the cluster's own policy engine, so the roles and bindings an administrator already writes are the source of truth.
The tool is a small HTTP proxy for a single upstream, written in Go, Apache-2.0 licensed. The last push was on 2026-09-24 and the most recent release is v0.23.0 from the same day.
The flags that decide how a request is authenticated
The full flag list is embedded in the readme, and the interesting subset is the authentication and path handling.
There are two ways in. The --oidc-* family configures OpenID Connect: --oidc-issuer sets the URL of the OpenID issuer, where only the HTTPS scheme is accepted, and it is used to verify the OIDC JSON Web Token. --oidc-clientID must be set if the issuer is set. --oidc-ca-file names the authorities used to verify the OpenID server's certificate, otherwise the host's root CA set is used. --oidc-sign-alg lists supported signing algorithms with a default of RS256, --oidc-username-claim picks the identifier of the user in the JWT claim with a default of email, and --oidc-groups-claim does the same for groups with a default of groups.
The alternative is a client certificate. --client-ca-file means that any request presenting a client certificate signed by one of the listed authorities is authenticated with an identity corresponding to the CommonName of the certificate.
--kubeconfig selects how the proxy connects to the API server, and if it is unset, in-cluster configuration is used, which is the normal case for a deployment. --kube-api-qps and --kube-api-burst throttle the proxy's own calls to the API, because a proxy that authorises every request can itself become a bottleneck against the API server.
Two path flags are mutually exclusive by design. --allow-paths is a comma-separated list of paths the proxy pattern-matches against the incoming request, and if the request does not match, the proxy responds with a 404 status code, and if omitted the incoming request path is not checked at all. --ignore-paths is the mirror image, and if the request matches it is proxied without performing an authentication or authorization check. Neither can be used with the other.
Passing identity upstream, and the paths you let through untouched
Once a request is authorized, the proxy can tell the upstream who the caller was, and the flags for that are named after the headers they set.
--auth-header-fields-enabled adds auth-related fields to the headers of HTTP requests sent to the upstream. The field names themselves are configurable: --auth-header-user-field-name names the field that tells the upstream the user's name, with a default of x-remote-user, and --auth-header-groups-field-name names the field carrying the user's groups, with a default of x-remote-groups, while --auth-header-groups-field-separator is the string used to concatenate multiple group names in that field's value, with a default of a pipe character.
That is a meaningful design point for anyone building on this. The upstream does not have to call the Kubernetes API to find out who called it, the proxy injects the answer into the request headers, which means the upstream can stay a plain HTTP service and enforce its own logic on top of an identity it trusts.
The --ignore-paths flag is the escape hatch and also the risk. A path matched there is proxied without any authentication or authorization check, so it is a deliberate hole in the security model and belongs only on paths that are safe to expose, such as a health endpoint. The --auth-token-audiences flag narrows the other side of the model by listing the token audiences to accept, and by default a token does not have to have any specific audience, though the documentation recommends setting one.
The proxy also exposes a config file, --config-file, which specifies the details of the SubjectAccessReview to be performed on a request. The documentation gives the shape of it, for example that an entity performing a request has to be allowed to perform a get on the Deployment called my-frontend-app, as well as the ability to configure whether SubjectAccessReviews are rewritten based on requests.
Four example configurations, each showing a different shape
The examples/ directory is the most useful part of the repository for an adopter, because each entry isolates one question you would otherwise have to work out from the flag list.
The non-resource-url example covers the case where the upstream serves a URL that is not a Kubernetes API path, which is where the SubjectAccessReview attributes have to be constructed by hand rather than derived from the request. The resource-attributes example is the other half, where the request path maps onto a resource and the attributes are extracted from it.
The oidc example shows a full OpenID Connect setup, with the issuer, the client id, the claim names and the certificate authorities, which is the configuration most deployments need and the one with the most flags to get right.
The rewrites example covers the feature the config file describes, rewriting SubjectAccessReviews based on request query parameters, which lets one upstream serve several resources with different permissions depending on the query string.
There are more examples beyond the four linked in the readme, and the directory listing shows them: an example-client, an example-client-http2, an example-client-urlquery, a grpcc directory, a minikube-rbac setup, a non-resource-url-token-request, a static-auth directory, and a resource-attributes directory. The static-auth and grpcc entries are the interesting ones for anyone wondering whether the proxy works in front of something that is not a plain HTTP service.
The minikube-rbac example is the practical one, since it shows how to reproduce the whole arrangement locally before deploying it.
Alpha status, deprecated flags and the alignment work
The project states plainly that it is alpha stage, and that flags, configuration, behavior and design may change significantly in following releases. That warning is at the top of the readme, and it is not decorative.
The reason for the alpha status is given too, and it is a governance reason rather than a technical one. The project is seeking to be accepted as a k8s project and therefore needs to align tighter with k8s. As a result, more of the k8s code is used and features need to be deprecated, while introducing others. The stated reasons for deprecation are that Kubernetes does not support them anymore, and partially that it is not a best practice, with the example given being insecure listening, and the upstream deprecation example being some of the logging flags.
The --insecure-listen-address flag is marked [DEPRECATED] in the flag list, which is the concrete shape that policy takes.
The project also notes that although it is alpha, it was treated like a production-v1 project, so no breaking changes were introduced, and that a feature branch called sig-auth-acceptance will show how kube-rbac-proxy will change.
On maintenance, the statement is candid: they try to keep the current release secure by making necessary updates when necessary, but this is best effort. The example given is specific. An update of Kubernetes from v0.25.2 to v0.25.5 was rolled back as it removed the --logtostderr flag.
That last detail is a good summary of the project's real risk profile, a proxy whose security depends on a Kubernetes API surface that can shift under it, with only best effort maintenance behind it.
Building it, and the module path that has not moved yet
The Dockerfile is short and builds a static binary into a distroless image:
ARG GOARCH=amd64
ARG BASEIMAGE=gcr.io/distroless/static:nonroot-$GOARCH
FROM $BASEIMAGE
ARG GOARCH
ARG GOOS=linux
ARG BINARY=kube-rbac-proxy-$GOOS-$GOARCH
COPY _output/$BINARY /usr/local/bin/kube-rbac-proxy
EXPOSE 8080
USER 65532:65532
ENTRYPOINT ["/usr/local/bin/kube-rbac-proxy"]The image exposes port 8080, runs as the nonroot user 65532, and the build target is a CGO_ENABLED=0 Go build so the result is a static binary that suits a distroless base. The Makefile cross-builds for amd64, arm, arm64, ppc64le and s390x on Linux plus darwin-amd64 and windows-amd64.exe, and the all target runs check-license, build, generate and test, where the license check is a script at scripts/check_license.sh that verifies the headers on the source files.
One detail in the Makefile is a trap for anyone wiring a CI pipeline. This repository moved to github.com/kube-rbac-proxy/kube-rbac-proxy, but the old module path is kept until the 1.0 release, where this is subject to change. The go.mod still declares module github.com/brancz/kube-rbac-proxy even though the repository now lives under the kube-rbac-proxy organisation, and the container repository is likewise still quay.io/brancz/kube-rbac-proxy while the badge points at the Quay repository under the same owner.
The dependencies are current Kubernetes client libraries at version 0.37.0, including client-go, apiserver, component-base and apimachinery, plus cobra, pflag, klog for logging and oklog/run for the run group pattern.
Editorial conclusion
Adopt kube-rbac-proxy if you need to expose one service to other workloads in a cluster and want the check to be an RBAC decision rather than a hand written token check, since the SubjectAccessReview path means the same roles and bindings you already manage decide access. Do not adopt it as a general mesh or as a replacement for NetworkPolicies, because it fronts a single upstream and it does not restrict which pods may talk to each other, it only decides who may talk through it. Before you deploy, read the alpha warning, because flags, configuration and behaviour are expected to change, and check the deprecation list, since the insecure listening option is marked deprecated and the project is removing features to align with Kubernetes conventions.
Frequently asked questions
What problem does kube-rbac-proxy solve?
In Kubernetes clusters without NetworkPolicies any Pod can perform requests to every other Pod in the cluster. The proxy restricts requests to a single upstream to only those Pods that present a valid and RBAC authorized token or client TLS certificate, authorizing each request with a SubjectAccessReview.
How do I configure kube-rbac-proxy to authenticate callers?
Either with OpenID Connect, by setting --oidc-issuer, --oidc-clientID, the claim names and optionally --oidc-ca-file, or with client certificates, where --client-ca-file names the authorities and the identity comes from the certificate CommonName. The --kubeconfig flag selects how the proxy reaches the API server, and in-cluster configuration is used when it is unset.
What is the difference between --allow-paths and --ignore-paths?
They are mutually exclusive. --allow-paths lists paths the proxy pattern-matches, and a request that does not match gets a 404 status code, while if the flag is omitted the request path is not checked. --ignore-paths is the mirror, and a matching request is proxied without any authentication or authorization check.
How does kube-rbac-proxy tell the upstream who the caller was?
With --auth-header-fields-enabled, which adds auth-related fields to the headers of the HTTP requests sent upstream. The header names are configurable with --auth-header-user-field-name, defaulting to x-remote-user, and --auth-header-groups-field-name, defaulting to x-remote-groups, with a separator set by --auth-header-groups-field-separator.
Is kube-rbac-proxy ready for production use?
The project describes itself as alpha stage, with flags, configuration, behavior and design possibly changing significantly in following releases, and says it is seeking acceptance as a k8s project. It also states that maintenance is best effort, and gives the example of a Kubernetes update from v0.25.2 to v0.25.5 being rolled back because it removed the --logtostderr flag.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/kube-rbac-proxy-kube-rbac-proxy)Was this useful?