Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# AGENTS.md

`oauth-proxy` is an OpenShift-focused reverse proxy that authenticates requests with the cluster OAuth server and can authorize them with Kubernetes APIs before forwarding them upstream.

## Commands

```sh
make build
make test-unit
go test ./providers/openshift/...
go test . -run TestName
make test-e2e # requires a configured OpenShift cluster; serial, 3h timeout
```

After dependency changes, run `go mod tidy`, `go mod vendor`, and the unit tests. The Makefile uses vendored `openshift/build-machinery-go`; inspect the included makefiles before assuming a target exists.

## Repository Map

```text
main.go flags, config loading, startup and shutdown
options.go defaults and configuration validation
oauthproxy.go OAuth handlers, sessions, routing and reverse proxy
http.go HTTP/HTTPS listeners and dynamic certificates
providers/openshift/ OpenShift OAuth, authentication and authorization
providers/ provider contract and session representation
cookie/ signed and encrypted cookies
api/, util/ HTTP, certificate and file helpers
contrib/ deployment and configuration examples
test/e2e/ cluster-dependent end-to-end tests
```

See [ARCHITECTURE.md](ARCHITECTURE.md) for request flows and [CONTRIBUTING.md](CONTRIBUTING.md) for the development workflow.

## Engineering Rules

- Add co-located `*_test.go` coverage; prefer table-driven tests for related cases.
- Run `gofmt` on changed Go files and `make test-unit` before submitting.
- Keep flags in `main.go`, `Options` fields/tags/defaults in `options.go`, validation, examples, and tests aligned.
- Preserve `RequestURI`/`URL.Opaque` handling when changing proxy directors; it prevents encoded slash decoding. See `TestEncodedSlashes`.
- Strip or overwrite client-supplied authentication and forwarding headers before adding trusted identity headers. Include adversarial normalization tests.
- Propagate an available `context.Context` and keep shutdown/watchers tied to it.
- Use `library-go/pkg/crypto` secure TLS defaults. Do not weaken verification to make a deployment work.
- Never log or commit secrets, tokens, private keys, kubeconfigs, or real credentials.
- Never edit `vendor/` by hand; use Go module commands and commit all resulting changes.

Ask maintainers before changing public flags/defaults, endpoints, cookie formats, identity headers, OAuth scopes, or authentication/authorization cache semantics. Changes under `providers/openshift/` should consider interactive OAuth, delegated credentials, and SubjectAccessReview authorization, including malformed and deny paths.

54 changes: 54 additions & 0 deletions ARCHITECTURE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# Architecture

## Overview

`oauth-proxy` sits in front of HTTP(S) applications or static files. It supports interactive OpenShift OAuth, validates the resulting session, optionally authorizes the user through Kubernetes APIs, and proxies requests with configured identity headers. It is commonly a sidecar beside an application listening only inside the pod.

```text
browser/API client
-> HTTP/HTTPS server (http.go)
-> OAuthProxy.ServeHTTP (oauthproxy.go)
-> OAuth endpoints -> OpenShift OAuth server
-> session/authz -> Kubernetes/OpenShift API
-> delegated authn/authz for bearer tokens or client certificates
-> HTTP(S), WebSocket, or file upstream
```

## Startup and Configuration

`main.go` defines flags, reads an optional TOML file, applies supported environment variables, and resolves them into `Options`. `options.go` validates configuration and parses upstream and redirect URLs. The OpenShift provider can discover cluster OAuth endpoints and, with `--openshift-service-account`, derive the client ID from the namespace/account and read the mounted token as its client secret.

Startup constructs `OAuthProxy`, optionally loads htpasswd data and a pprof listener, then serves until SIGTERM or interrupt cancels the root context. HTTPS serving certificates are watched and reloaded.

## Request Flow

With the default `--proxy-prefix=/oauth`, proxy-owned paths are:

| Path | Purpose |
| --- | --- |
| `/robots.txt` | Disallow crawlers |
| `/oauth/healthz` | Liveness |
| `/oauth/sign_in`, `/oauth/sign_out` | Login UI and session removal |
| `/oauth/start`, `/oauth/callback` | Start and complete OAuth |
| `/oauth/auth` | Accepted/unauthorized response for `auth_request` |

For an ordinary request, the proxy applies protected-path and bypass rules; verifies and refreshes the session cookie; falls back to Basic Auth or delegated authentication when no session remains; validates identity rules and SubjectAccessReviews; normalizes untrusted header variants; adds configured trusted headers; and dispatches to the selected upstream. An unauthenticated browser enters OAuth, while failed delegated API authentication returns an error.

## OpenShift Provider

The provider contract is in `providers/providers.go`; the binary currently selects only OpenShift. `providers/openshift/` implements OAuth discovery/redemption/user lookup, session refresh, global and host-specific access reviews, TokenAccessReview and client-certificate authentication, SubjectAccessReview authorization, caches, and cluster CA handling.

`--openshift-sar` checks an interactively logged-in identity. `--openshift-delegate-urls` authenticates credentials supplied on the request and authorizes the longest matching path. Delegated bearer tokens are forwarded only when `--pass-user-bearer-token` is also enabled, extending the security boundary to the upstream.

## Sessions, Upstreams, and Headers

Session state lives in `providers/session_state.go`. Cookies are signed; contents are encrypted when token storage or refresh requires it. A separate CSRF cookie binds callback to login. Serialization is a compatibility boundary requiring tampering, expiry, and round-trip tests.

Each `--upstream` is registered by URL path. HTTP(S) uses Go's reverse proxy with HTTP/2 transport, WebSocket upgrades use the WebSocket proxy, and `file://` serves local files. Encoded paths are deliberately preserved.

Client-supplied variants of identity headers are normalized and removed. Configuration controls Basic Auth, `X-Forwarded-*`, access-token, and `X-Auth-Request-*` headers. Optional `GAP-Signature` HMAC protects selected request data for an upstream that verifies it.

## TLS

HTTP accepts TCP or Unix-socket addresses. HTTPS uses OpenShift secure TLS defaults and dynamically reloads its certificate/key. Upstream and OpenShift CA bundles have separate trust pools. Insecure certificate verification is a legacy escape hatch and should not be used in production.

Loading