JWT Issuer in Rust
The jwt-issuer-rs project implements a simple JWT (JSON Web Token) Issuer in Rust. The project provides an example of how the JWT Issuer can be used as a JWT authenticator for Hashicorp Vault.
JWT Issuer
The jwt-issuer-rs project implements a JWT (JSON Web Token) Issuer in Rust using actix, jsonwebtoken and jsonwebkey.
Key generation
The first step in using the JWT issuer is to generate a key pair using openssl to sign the JWTs.
openssl ecparam -name prime256v1 -genkey -noout -out key.pem
openssl ec -in key.pem -pubout -out public.pem
The next step is to convert the private key into a JWK
cat key.pem | docker run -i danedmunds/pem-to-jwk:latest > key.json
Usage
Using your JWK stored in a file called key.json, run the JWT Issuer service as follows
cargo run
The above command starts a HTTP server which exposes two endpoints
- auth/token: JWT token issuer
- auth/jwks: The public JSON Web Keys
A JWT token for a user can be requested using the following curl command
curl -X POST http://localhost:8080/auth/token -d '{"name": "vishpat"}' -H 'Content-Type: application/json'
(In the real world this endpoint would have authentication and would be exposed via https. However, for simplicity, this is not the case)
The issued JWT can then be verified against the jwks endpoint as follows
# A simple python program to verify the JWT using the
# JWKS endpoint.
# Requires python packages pyjwt,requests,cryptography
import jwt
import requests
token = "TOKEN"
jwk_url = "http://localhost:8080/auth/jwks"
jwk = requests.get(jwk_url).json()
key = jwt.algorithms.ECAlgorithm.from_jwk(jwk["keys"][0])
data = jwt.decode(token, key=key, algorithms=['ES256'])
print(data)
Hashicorp Vault Integration
Vault Overview
Hashicorp Vault is an enterprise grade secret management system. Vault enables storing of secrets and accessing them using various authentication mechanisms.
We will be using Vault to store a username and password in it's kv secret store. The JWT Issuer will be used to setup JWT authentication to access the secrets stored in the Vault.
Vault Server
Start a local dev vault server
vault server -dev
Key Value Secret Engine
The above command will spit out the admin token that is required to manage the Vault instance. Use the admin token to enable the kv (version 1) secret engine for Vault as shown below.
export VAULT_ADDR='http://127.0.0.1:8200'
export VAULT_TOKEN=<VAULT_ADMIN_TOKEN>
vault secrets enable -version=1 kv
Authentication Setup
The next step is to setup the JWT authentication for Vault. This can be done using terraform as follows.
provider "vault" {
}
resource "vault_jwt_auth_backend" "vishpat" {
description = "Enable JWT auth"
path = "jwt"
default_role = "jwt_vishpat"
jwks_url = "http://localhost:8080/auth/jwks"
}
resource "vault_jwt_auth_backend_role" "jwt_vishpat" {
backend = vault_jwt_auth_backend.vishpat.path
role_name = "jwt_vishpat"
token_policies = ["vishpat_keys_policy"]
bound_subject = "vishpat"
user_claim = "sub"
role_type = "jwt"
}
Policy setup
Now setup a policy (using terraform) in Vault to allow the user vishpat to access the secrets stored under kv/vishpat/*
resource "vault_policy" "vishpat_keys_policy" {
name = "vishpat_keys_policy"
policy = <<EOT
path "kv/vishpat/*" {
capabilities = [ "create", "read", "update", "delete", "list" ]
}
EOT
}
Terraform
Apply the terraform plan as shown below
terraform plan -out plan.out
terraform apply plan.out
JWT token
Now get the JWT token for the user vishpat as shown below.
curl -X POST -d '{"name": "vishpat"}' -H 'Content-Type: application/json' http://localhost:8080/auth/token
Vault authentication
Use the JWT token to authenticate against Vault inorder to get the Vault token to access the secrets.
vault write auth/jwt/login jwt=<JWT_TOKEN>
Key Value
--- -----
token hvs.CAESIDZZ-ol5ich3gnllpS6yhuaHDVnqEXwZUiRNlKqBslpIGh4KHGh2cy5pbURralBsZlhTdTRSdlBnMkRjVDJDQng
token_accessor LY5IENUHKtxvugEiSAiLalH9
token_duration 768h
token_renewable true
token_policies ["default" "vishpat_keys_policy"]
identity_policies []
policies ["default" "vishpat_keys_policy"]
token_meta_role jwt_vishpat
Access secrets
The secrets at kv/vishpat can now be accessed using the Vault user token.
export VAULT_TOKEN=hvs.CAESIDZZ-ol5ich3gnllpS6yhuaHDVnqEXwZUiRNlKqBslpIGh4KHGh2cy5pbURralBsZlhTdTRSdlBnMkRjVDJDQng
➜ vault kv put kv/vishpat/test username=X password=Y
Success! Data written to: kv/vishpat/test
➜ vault kv get kv/vishpat/test
=== Data ===
Key Value
--- -----
password Y
username X