AuthBox

This documentation describes AuthBox v0.3.0-133-g71cb5564.

Protect a service with an authorizing proxy

In short

Stand a proxy in front of a service that knows nothing about certificates and cannot be changed to learn. One binary and one configuration cover one service, many told apart by name, or a whole Kubernetes cluster as its ingress controller.

What it is for

You have a service that knows nothing about certificates and cannot be changed to learn. Stand the proxy in front of it. The same binary and the same configuration cover three sizes: one service, many services told apart by the name they are asked for, or an entire Kubernetes cluster, where the proxy runs as the ingress controller and reads its routes off the annotations on your Services.

One authorizing proxy in front of three services: the caller's certificate ends at the proxy, which decides and forwards; the same proxy fronts one service, many services told apart by name, or a whole Kubernetes cluster, reading its routes from Service annotations

The caller's identity arrives already verified, the decision is made from the same policy the rest of the deployment uses, and a signed receipt rides every request. Nothing about the caller is ever trusted from a header — not who they are, not what they may do. When the proxy cannot reach a decision it refuses the request, so the worst a failure does is turn people away.

This is not an L7 ingress standing in front of AuthBox. The client certificate ends at AuthBox: the proxy terminates the handshake itself, because a hop that has already replaced the caller's certificate with its own has nothing left to decide from.

The topology

One proxy in front of the services, with the caller's certificate ending at the proxy — which decides, and only then forwards.

   CALLER                 PROXY                       YOUR SERVICE
   client cert  --mTLS->  decides                ->   one service
                          forwards               ->   many services, told apart by name
                          signs a receipt        ->   one cluster, as the ingress
                                                      (routes read from Service annotations)

The three sizes are the same binary and the same configuration file. What changes is how many routes it holds and where they came from: written down for one service or many, discovered from a single annotation on a Service in the cluster case.

Stand it up

A front door in front of the server: a request passes a door that decides and signs a receipt before anything behind it is reached.DOORAUTHBOXconsole
$ docker run --rm authboxus/authbox-eval -evaluate -scenario door -print docker | sh
$ docker logs writer

A front door in front of it: the box, and the front door on its own image in front of it, answering on port 8444. What it fronts is the box's own console, a real service behind a real door: the door ends the caller's certificate, decides from the bundle the box publishes, and forwards with the verified identity and a signed receipt. The evaluation runbook says what to open and how it ends.

What the smoke proves

The evaluation's own proof runs the printed recipe from the built image, opens the console through the door with the administrator's certificate, and finds the permit the door's receipt was minted from in the door's own audit trail.

The scenario's proof goes further, against a real authboxd writer and a real authboxproxy fronting one plain-HTTP application that knows nothing and one application that speaks mutual TLS. It proves four consumption modes against one deployment — headers pushed to an application that has only a header parser; a receipt the application verifies offline against the proxy's own exported key set; the two-entry chain an AuthBox-aware service reads instead of headers; and the injected callback token, redeemed at the writer — and then pauses the writer to show the door still deciding, which is the steady-state property rather than an assertion about it.

A second proof starts a proxy Pod with no routes at all, against a real Kubernetes API server, and watches it pick up a route the moment a Service is annotated. There is no writer in that cluster — the door decides from a signed bundle published earlier.

Read on