Skip to content
Merged
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
6 changes: 6 additions & 0 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,12 @@
context: ./authbridge
dockerfile: authproxy/Dockerfile.authbridge

# Unified AuthBridge binary (Envoy + authbridge in one container)
# Drop-in replacement for envoy-with-processor
- name: authbridge-unified
context: ./authbridge
dockerfile: cmd/authbridge/Dockerfile

# Demo application for testing
- name: demo-app
context: ./authbridge/authproxy/quickstart/demo-app
Expand Down Expand Up @@ -100,7 +106,7 @@
# Always use the computed tag
type=raw,value=${{ steps.tag.outputs.tag }}
# Add 'latest' tag for version tags, workflow_dispatch, and pushes to main
type=raw,value=latest,enable=${{ (github.ref_type == 'tag' && startsWith(github.ref_name, 'v')) || github.event_name == 'workflow_dispatch' || github.ref == 'refs/heads/main' }}

Check warning on line 109 in .github/workflows/build.yaml

View workflow job for this annotation

GitHub Actions / YAML Lint

109:151 [line-length] line too long (189 > 150 characters)

# 7. Build and push image
- name: Build and push ${{ matrix.image_config.name }}
Expand Down
57 changes: 57 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,63 @@ jobs:
- name: Test
run: go test -v -race -cover ./...

go-ci-authlib:
name: Go CI (authlib)
runs-on: ubuntu-latest
timeout-minutes: 15
defaults:
run:
working-directory: authbridge/authlib
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6

- uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6
with:
go-version-file: authbridge/authlib/go.mod
cache-dependency-path: authbridge/authlib/go.sum

- name: Lint
run: |
go fmt ./...
go vet ./...

- name: Build
run: go build -v ./...

- name: Test
run: go test -v -race -cover ./...

go-ci-authbridge-cmd:
name: Go CI (authbridge cmd)
runs-on: ubuntu-latest
timeout-minutes: 15
defaults:
run:
working-directory: authbridge/cmd/authbridge
env:
# Disable go.work — the workspace at authbridge/ includes ./authproxy
# which would pull in the old go-processor module. The replace directive
# in go.mod handles the authlib dependency for CI builds.
GOWORK: "off"
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6

- uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6
with:
go-version-file: authbridge/cmd/authbridge/go.mod
cache-dependency-path: authbridge/cmd/authbridge/go.sum

- name: Lint
run: |
go fmt ./...
go vet ./...

- name: Build
run: go build -v ./...

- name: Test
run: go test -v -race -cover ./...

python-test:
name: Python Tests
runs-on: ubuntu-latest
Expand Down
48 changes: 42 additions & 6 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,21 @@ The sidecar injection webhook lives in a separate repo: [kagenti/kagenti-operato
```
kagenti-extensions/
├── authbridge/ # Authentication bridge components
│ ├── authproxy/ # Envoy + ext-proc sidecar (Go) — token validation & exchange
│ │ ├── go-processor/ # gRPC ext-proc server (inbound JWT validation, outbound token exchange)
│ ├── authlib/ # Shared auth building blocks (Go module)
│ │ ├── validation/ # JWKS-backed JWT verifier
│ │ ├── exchange/ # RFC 8693 token exchange client
│ │ ├── cache/ # SHA-256 keyed token cache
│ │ ├── bypass/ # Path pattern matcher
│ │ ├── spiffe/ # SPIFFE credential sources
│ │ ├── routing/ # Host-to-audience router
│ │ ├── auth/ # HandleInbound + HandleOutbound composition
│ │ └── config/ # Mode presets, YAML config, validation
│ ├── cmd/authbridge/ # Unified binary — 3 modes, 1 codebase
│ │ ├── listener/ # Protocol adapters (ext_proc, ext_authz, forward/reverse proxy)
│ │ ├── entrypoint.sh # Envoy + authbridge process supervision
│ │ └── Dockerfile # Combined Envoy + authbridge image
│ ├── authproxy/ # [DEPRECATED] Old Envoy + ext-proc sidecar
│ │ ├── go-processor/ # [DEPRECATED] Use cmd/authbridge instead
│ │ ├── quickstart/ # Standalone demo (no SPIFFE)
│ │ └── k8s/ # Standalone K8s manifests
│ ├── client-registration/ # Keycloak auto-registration (Python)
Expand Down Expand Up @@ -88,12 +101,34 @@ The kagenti-operator (in a separate repo) injects AuthBridge sidecars into workl
└────────────────────────────────────┘
```

## Unified AuthBridge Binary

The `cmd/authbridge/` directory contains a unified binary that replaces three separate
codebases (go-processor, waypoint, klaviger) with a single binary supporting three modes:

| Mode | Interception | Listeners | Use Case |
|------|-------------|-----------|----------|
| `envoy-sidecar` | Envoy iptables + ext_proc | gRPC ext_proc on :9090 | Sidecar per agent pod |
| `waypoint` | Istio ambient + ext_authz | gRPC ext_authz + HTTP forward proxy | Shared service |
| `proxy-sidecar` | Reverse proxy + forward proxy | HTTP reverse proxy + forward proxy | Sidecar without Envoy |

**Go modules:**
- `authbridge/authlib/` — pure library, no protocol deps (validation, exchange, cache, bypass, spiffe, routing, auth, config)
- `authbridge/cmd/authbridge/` — binary + listeners, imports authlib + gRPC/Envoy deps
- `authbridge/go.work` — workspace linking both modules for local development

**Config format:** YAML with `${ENV_VAR}` expansion, mode presets, and startup validation.
Supports `keycloak_url` + `keycloak_realm` derivation for operator compatibility.

**Image:** `ghcr.io/kagenti/kagenti-extensions/authbridge-unified` — Envoy + authbridge
in one container (drop-in replacement for `envoy-with-processor`).

## CI/CD Workflows

| Workflow | Trigger | Purpose |
|----------|---------|---------|
| `ci.yaml` | PR to main/release-* | Go fmt, vet, build for AuthProxy; Python tests |
| `build.yaml` | Tag push (`v*`) or manual | Multi-arch Docker builds for: client-registration, auth-proxy, proxy-init, envoy-with-processor, authbridge, demo-app |
| `ci.yaml` | PR to main/release-* | Go fmt, vet, build, test for authproxy, authlib, and cmd/authbridge; Python tests |
| `build.yaml` | Tag push (`v*`) or manual | Multi-arch Docker builds for: client-registration, auth-proxy, proxy-init, envoy-with-processor, authbridge, authbridge-unified, demo-app |
| `security-scans.yaml` | PR to main | Dependency review, shellcheck, YAML lint, Hadolint, Bandit, Trivy, CodeQL |
| `scorecard.yaml` | Weekly / push to main | OpenSSF Scorecard security health metrics |
| `spellcheck_action.yml` | PR | Spellcheck on markdown files |
Expand All @@ -114,11 +149,12 @@ All images are pushed to `ghcr.io/kagenti/kagenti-extensions/`:

| Image | Source | Description |
|-------|--------|-------------|
| `envoy-with-processor` | `authbridge/authproxy/Dockerfile.envoy` | Envoy 1.28 + go-processor ext-proc |
| **`authbridge-unified`** | **`authbridge/cmd/authbridge/Dockerfile`** | **Unified Envoy + authbridge binary (recommended)** |
| `envoy-with-processor` | `authbridge/authproxy/Dockerfile.envoy` | [DEPRECATED] Envoy + go-processor ext-proc |
| `proxy-init` | `authbridge/authproxy/Dockerfile.init` | Alpine + iptables init container |
| `client-registration` | `authbridge/client-registration/Dockerfile` | Python Keycloak client registrar |
| `spiffe-helper` | `authbridge/spiffe-helper/Dockerfile` | Fetches SPIFFE credentials from SPIRE |
| `authbridge` | `authbridge/authproxy/Dockerfile.authbridge` | Combined sidecar (Envoy + go-processor + spiffe-helper + client-registration) |
| `authbridge` | `authbridge/authproxy/Dockerfile.authbridge` | [DEPRECATED] Combined sidecar (old architecture) |
| `auth-proxy` | `authbridge/authproxy/Dockerfile` | Example pass-through proxy (for demos) |
| `demo-app` | `authbridge/authproxy/quickstart/demo-app/Dockerfile` | Demo target service |

Expand Down
10 changes: 10 additions & 0 deletions authbridge/CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,16 @@ This file provides context for Claude (AI assistant) when working with the `Auth
For repo-level context (CI/CD, cross-component relationships), see [`../CLAUDE.md`](../CLAUDE.md).
The sidecar injection webhook lives in [kagenti-operator](https://github.com/kagenti/kagenti-operator).

## Unified Binary

The `cmd/authbridge/` directory contains the unified authbridge binary that replaces the
old `go-processor` ext_proc server. It supports three modes (`envoy-sidecar`, `waypoint`,
`proxy-sidecar`) with shared auth logic in `authlib/`. See [`cmd/authbridge/README.md`](cmd/authbridge/README.md)
for config format and [`authlib/README.md`](authlib/README.md) for the library reference.

The old `authproxy/go-processor/` is deprecated. New development should target
`authlib/` and `cmd/authbridge/`.

## What AuthBridge Does

AuthBridge provides **zero-trust, transparent token management** for Kubernetes workloads. It combines three capabilities:
Expand Down
24 changes: 22 additions & 2 deletions authbridge/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,25 @@ AuthBridge provides **secure, transparent token management** for Kubernetes work

> **📘 Looking to run the demo?** See the [Single-Target Demo](./demos/single-target/demo.md) or [Multi-Target Demo](./demos/multi-target/demo.md) for step-by-step instructions.

## What AuthBridge Does
## Unified AuthBridge Binary (New)

The [`cmd/authbridge/`](./cmd/authbridge/) directory contains a unified binary that supports three deployment modes in a single codebase:

| Mode | Use Case | Replaces |
|------|----------|----------|
| `envoy-sidecar` | Sidecar per agent pod (Envoy + ext_proc) | `envoy-with-processor` (go-processor) |
| `waypoint` | Shared service in Istio ambient mesh | Waypoint token-exchange-service |
| `proxy-sidecar` | Sidecar without Envoy (reverse + forward proxy) | Klaviger |

The unified image (`authbridge-unified`) is a **drop-in replacement** for `envoy-with-processor` with the same base image, UID (1337), and ports. See [`cmd/authbridge/README.md`](./cmd/authbridge/README.md) for config format and usage.

The shared auth library at [`authlib/`](./authlib/) contains the building blocks (JWT validation, token exchange, caching, routing) with no protocol dependencies. See [`authlib/README.md`](./authlib/README.md) for package reference.

## Classic Architecture (Operator-Injected)

The following describes the current production deployment using operator-injected split sidecars. The unified binary (`cmd/authbridge/`) replaces the `envoy-proxy` sidecar in this architecture.

### What AuthBridge Does

AuthBridge solves the challenge of **secure service-to-service authentication** in Kubernetes:

Expand Down Expand Up @@ -357,7 +375,9 @@ This creates target clients, audience scopes, and assigns scopes to the agent.

## Component Documentation

- [AuthProxy](authproxy/README.md) - Token validation and exchange proxy
- [Unified AuthBridge Binary](cmd/authbridge/README.md) - Single binary, three modes (recommended)
- [authlib](authlib/README.md) - Shared auth building blocks (Go library)
- [AuthProxy](authproxy/README.md) - Token validation and exchange proxy (deprecated, use cmd/authbridge)
- [Client Registration](client-registration/README.md) - Automatic Keycloak client registration with SPIFFE

## References
Expand Down
42 changes: 42 additions & 0 deletions authbridge/authlib/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# authlib — Shared Auth Building Blocks

A pure Go library providing reusable building blocks for JWT validation, OAuth 2.0 token exchange, and SPIFFE-based authentication. No protocol dependencies (no gRPC, no Envoy).

## Packages

| Package | Purpose |
|---------|---------|
| `validation/` | JWKS-backed JWT verifier (`lestrrat-go/jwx`) with required audience parameter |
| `exchange/` | RFC 8693 token exchange + client credentials grant with pluggable auth |
| `cache/` | SHA-256 keyed token cache with TTL eviction |
| `bypass/` | Path pattern matcher for public endpoints (health, agent card) |
| `spiffe/` | SPIFFE credential sources (file-based JWT-SVID) |
| `routing/` | Host-to-audience router with glob pattern matching |
| `auth/` | Composition layer: `HandleInbound` + `HandleOutbound` |
| `config/` | YAML config, mode presets, startup validation, URL derivation |

## Usage

```go
import (
"github.com/kagenti/kagenti-extensions/authbridge/authlib/auth"
"github.com/kagenti/kagenti-extensions/authbridge/authlib/config"
)

// Load and resolve config
cfg, _ := config.Load("config.yaml")
resolved, _ := config.Resolve(ctx, cfg)
handler := auth.New(*resolved)

// Handle requests
inResult := handler.HandleInbound(ctx, authHeader, path, "")
outResult := handler.HandleOutbound(ctx, authHeader, host)
```

## Go Module

```
module github.com/kagenti/kagenti-extensions/authbridge/authlib
```

Direct dependencies: `lestrrat-go/jwx/v2`, `gobwas/glob`, `gopkg.in/yaml.v3`. No gRPC or Envoy deps.
2 changes: 2 additions & 0 deletions authbridge/authproxy/Dockerfile.envoy
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# Deprecated: This Dockerfile builds the old envoy-with-processor image.
# Use authbridge/cmd/authbridge/Dockerfile instead (unified binary).
FROM golang:1.26-alpine AS go-builder
WORKDIR /app
COPY go.mod go.sum ./
Expand All @@ -10,7 +12,7 @@

FROM registry.access.redhat.com/ubi9/ubi-minimal@sha256:83006d535923fcf1345067873524a3980316f51794f01d8655be55d6e9387183

RUN microdnf install -y ca-certificates && microdnf clean all

Check failure on line 15 in authbridge/authproxy/Dockerfile.envoy

View workflow job for this annotation

GitHub Actions / Dockerfile Lint (Hadolint)

DL3041 warning: Specify version with `dnf install -y <package>-<version>`.

COPY --from=envoy-source /usr/local/bin/envoy /usr/local/bin/envoy
COPY --from=go-builder /go-processor /usr/local/bin/go-processor
Expand Down
5 changes: 5 additions & 0 deletions authbridge/authproxy/README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# AuthProxy

> **Deprecated:** The go-processor ext_proc server and `Dockerfile.envoy` are replaced by
> the [unified authbridge binary](../cmd/authbridge/). The unified binary is a drop-in
> replacement for `envoy-with-processor` with the same image structure, UID, and ports.
> This directory is kept for backwards compatibility during migration.

AuthProxy is a **token validation and exchange sidecar** for Kubernetes workloads. It enables secure service-to-service communication by:
- **Validating** incoming requests with JWT token verification (inbound)
- **Exchanging** tokens for ones with the correct audience for downstream services (outbound)
Expand Down
1 change: 1 addition & 0 deletions authbridge/authproxy/entrypoint-envoy.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#!/bin/bash
# Deprecated: Use authbridge/cmd/authbridge/entrypoint.sh instead (unified binary).
set -eu

# Envoy + go-processor entrypoint with process supervision.
Expand Down
4 changes: 4 additions & 0 deletions authbridge/authproxy/go-processor/main.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
// Deprecated: This go-processor ext_proc server is replaced by the unified
// authbridge binary at cmd/authbridge/. The unified binary supports envoy-sidecar,
// waypoint, and proxy-sidecar modes with a shared auth library (authlib/).
// This file is kept for backwards compatibility during migration.
package main

import (
Expand Down
Loading
Loading