Skip to content

Istio External Authorizer for transparent oidc token authentication and exchange

Notifications You must be signed in to change notification settings

holos-run/tokensmith

Repository files navigation

Tokensmith

Tokensmith is an Envoy external authorizer (ext_authz) for Istio 1.27+ that exchanges OIDC ID tokens for Kubernetes service accounts in one cluster for ID tokens for valid Kubernetes service accounts in another cluster.

Overview

In multi-cluster Kubernetes environments, services often need to authenticate across cluster boundaries. Tokensmith enables secure cross-cluster authentication by:

  1. Accepting requests from Envoy with bearer tokens from a workload cluster
  2. Validating the incoming token using Kubernetes TokenReview API
  3. Exchanging the validated token for a management cluster token using TokenRequest API
  4. Returning the new token to Envoy for use in downstream API server requests

This allows services in one Kubernetes cluster (workload) to securely access resources in another cluster (management) using their native Kubernetes service account identities.

Architecture

Tokensmith implements the Envoy External Authorization API and acts as a token translation layer between clusters:

Key Components

  • External Authorization Server: gRPC server implementing Envoy's ext_authz API
  • Token Validator: Validates tokens from workload cluster using Kubernetes TokenReview API
  • Token Exchanger: Creates new tokens for management cluster using Kubernetes TokenRequest API
  • Identity Mapping: Maps workload service accounts to identical namespace/name in management cluster

Project Status

Core Implementation Complete - See plan/004-oidc-token-exchange-overview.md for implementation details.

Development

Prerequisites

  • Go 1.23 or later
  • Make
  • golangci-lint (for linting)

Building

# Build the binary
make build

# Run tests
make test

# Run linters
make lint

# Format code
make fmt

Running Tests

Unit Tests

Run all unit tests:

go test ./...

Run tests for a specific package with verbose output:

go test -v ./internal/token/

Run a specific test:

go test -v ./internal/token/ -run TestTokenExchangeFlow

Test Coverage

Generate test coverage report:

go test -coverprofile=coverage.out ./...
go tool cover -html=coverage.out

View coverage for a specific package:

go test -cover ./internal/token/

Token Exchange Tests

The token exchange tests (internal/token/exchange_integration_test.go) use Kubernetes fake clients and generate real JWT tokens to test the complete validation and exchange flow:

  • TestTokenExchangeFlow: Validates the happy path, verifying that JWT claims (subject, audience, expiration, issuer, namespace, service account name) are preserved during exchange, while unique identifiers (JWT ID, service account UID) differ appropriately
  • TestTokenExchangeServiceAccountNotFound: Verifies error handling when the target service account doesn't exist in the management cluster
  • TestTokenValidationFails: Tests that invalid/expired tokens are rejected before exchange
  • TestTokenExpirationPreserved: Confirms that token expiration times are preserved exactly during exchange

These tests follow Kubernetes upstream testing patterns and generate valid service account JWTs for realistic verification.

Running

Start the External Authorization Server

# Build the binary
make build

# Start the ext_authz server
./bin/tokensmith authz \
  --addr 0.0.0.0 \
  --port 9001 \
  --workload-kubeconfig /path/to/workload/kubeconfig \
  --token-expiration 3600 \
  --log-level info \
  --log-format json

Flags:

  • --addr: Server address (default: 0.0.0.0)
  • --port: Server port (default: 9001)
  • --workload-kubeconfig: Path to workload cluster kubeconfig (if empty, uses in-cluster config)
  • --token-expiration: Token expiration in seconds (default: 3600 = 1 hour)
  • --log-level: Log level - debug, info, warn, error (default: info)
  • --log-format: Log format - json, text (default: json)

Requirements:

  • The server must have network access to both workload and management cluster API servers
  • For management cluster: Uses in-cluster configuration (must run as a pod in the management cluster)
  • For workload cluster: Provide kubeconfig via --workload-kubeconfig or use in-cluster config
  • The management cluster service account needs permissions to create tokens:
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRole
    metadata:
      name: tokensmith
    rules:
    - apiGroups: [""]
      resources: ["serviceaccounts/token"]
      verbs: ["create"]

Demo: Greet Service

For testing and development, a simple greet service is also available:

# Start the greet server
./bin/tokensmith serve --port 8080

# Call the greet service
./bin/tokensmith greet --name Alice
# Output: Hello, Alice!

Service Account Mapping

Tokensmith uses identity-based mapping: it maps service accounts from the workload cluster to service accounts with the same namespace and name in the management cluster.

Example:

  • Workload cluster SA: app-prod/eso-sa
  • Management cluster SA: app-prod/eso-sa (must exist)

Requirements:

  1. Service account must exist in management cluster with same namespace/name
  2. Management cluster RBAC controls what the service account can access
  3. No additional configuration needed - mapping is automatic based on identity

Contributing

See AGENTS.md for development workflow and guidelines.

Development Workflow

  1. Write a detailed plan to the plan/ directory
  2. Wait for human review and approval
  3. Implement the plan iteratively
  4. Create git commits at each todo step completion
  5. Update documentation

License

[To be determined]

References

About

Istio External Authorizer for transparent oidc token authentication and exchange

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages