Skip to content
MetaformPublic

About

Token exchange service for participant context operations

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

18 Commits

Folders and files

Repository files navigation

Jwtlet

Jwtlet is an RFC 8693 OAuth 2.0 token exchange service for participant context operations. Clients exchange a Kubernetes service account token for a signed JWT that encodes participant context claims. The service validates the incoming token against a Kubernetes OIDC issuer, resolves resource mappings and scope-to-claims mappings, and signs the resulting token via HashiCorp Vault.

Jwtlet runs two HTTP servers: a token exchange API (default port 8080) and a management API (default port 8081) for administering resource and scope mappings.

Building

Requires Rust (stable toolchain).

# Build all crates
cargo build

# Build the release binary
cargo build --release -p jwtlet-server

Running the Tests

Unit and integration tests:

cargo nextest run

or

cargo test

End-to-end tests run against a local kind Kubernetes cluster with Vault. Requires Docker and kind installed.

cd e2e

make all          # full cycle: cluster setup, build, test, cleanup

# or individual steps:
make setup        # create KIND cluster and initialize Vault
make build        # build and load the Docker image into the cluster
make test         # run tests
make cleanup      # tear down the cluster

Running the Server

Pass a TOML config file as the first argument, or set JWTLET_CONFIG_FILE:

jwtlet-server /path/to/config.toml
# or
JWTLET_CONFIG_FILE=/path/to/config.toml jwtlet-server

Individual settings can also be overridden with environment variables using the JWTLET__ prefix (double underscore as the nesting separator), e.g. JWTLET__TOKEN_EXCHANGE_PORT=9090.

Configuration Reference

# Ports and bind address
token_exchange_port = 8080   # default
management_port = 8081   # default; must differ from token_exchange_port
bind = "0.0.0.0"

# Storage backend: "memory" (default) or "postgres"
[storage_backend]
type = "memory"
# type = "postgres"
# url  = "postgresql://user:pass@host:5432/jwtlet"

# Kubernetes OIDC validation
[k8s]
api_server_url = "https://kubernetes.default.svc"               # required
cluster_issuer = "https://kubernetes.default.svc.cluster.local" # required
token_file = "/var/run/secrets/kubernetes.io/serviceaccount/token"

# Token issuance
[token]
client_audience = "https://kubernetes.default.svc.cluster.local" # required – expected aud of incoming tokens
audience = "my-service"                                    # required – aud of issued tokens
participant_context_claim = "jwtlet_pc"  # default
token_ttl_secs = 3600         # default

# Vault signing backend
[vault]
url = "http://vault:8200"           # required
token_file = "/vault/secrets/.vault-token" # use token_file in production
# token    = "s.xxxxx"                     # or a literal token for development

# Management API authorization
# Keys are Kubernetes service account identifiers; values are lists of roles.
# A caller must hold the "management:write" role to use any management endpoint.
[service_accounts]
"system:serviceaccount:my-namespace:my-sa" = ["management:write"]

Management API Authentication

All management API endpoints (/api/v1/mappings, /api/v1/scopes) require a Authorization: Bearer <token> header. The token must be a valid Kubernetes service account token issued with the same audience as token.client_audience. Jwtlet verifies the token via the Kubernetes TokenReview API and checks that the resolved service account identity holds the management:write role.

To obtain a suitable token from within a cluster:

kubectl create token my-sa -n my-namespace \
  --audience=https://kubernetes.default.svc.cluster.local

Logging

Set RUST_LOG to control verbosity (trace, debug, info, warn, error):

RUST_LOG=debug jwtlet-server config.toml

License

Apache-2.0

About

Token exchange service for participant context operations

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages