Credential Server
The Credential Server serves the User Service, which is defined in an OpenAPI 3.0 spec and lives in /openapi/user.yaml
.
Usage
First-time setup
Make sure you have Bazel installed. For more detailed instructions on some of the tools we use and how we use them, check out the Silicon Ally Developer Handbook.
Once that's done, make sure the cmd/server/configs/local.conf
is relevant for your setup. Specifically:
secret_azure_ad_*
configuration parameters are only required if use_local_jwts
is false
secret_auth_private_key_data
is the Ed25519 private key used for JWT signing (and the public key is used for validation in the testcreds
endpoint).
-
To generate a new key you can run:
bazel run //scripts:run_keygen
Which will create test_server.{pub,key}
files in the root of the project. From there it can be copied into the config, be careful to replace newlines with \n
.
Running the Credential Server
To run the Credential Server, run:
# Run the backend
bazel run //scripts:run_server
# Note: If you want to use Azure instead of local JWTs, run
# bazel run //scripts:run_server -- --use_azure_auth
Once all dependencies are installed and the server actually starts, you'll see something that looks like:
█▀▄░█▄█░▀█▀
█▀▄░█░█░░█░
▀░▀░▀░▀░▀▀▀
░█▀▀░█▀▄░█▀▀░█▀▄░█▀▀░█▀▄░█░█
░█░░░█▀▄░█▀▀░█░█░▀▀█░█▀▄░▀▄▀
░▀▀▀░▀░▀░▀▀▀░▀▀░░▀▀▀░▀░▀░░▀░
At this point, the server is running and accessible at localhost:8080
.
Calling the service
The User API exists to exchange end-user credentials from an auth service (in this case, Azure AD B2C) for RMI-specific credentials. When testing locally, there are two different ways to test things out:
- Using the web frontend - This repo contains a basic web frontend in the
frontend/
directory, check out the README.md
there for set up and running instructions. The frontend integrates with Microsoft's MSAL.js to do the full authentication flow + credential exchange.
- Make sure to run the server with the
--use_azure_auth
flag.
- Using
genjwt
- The genjwt
tool uses your local keypair to generate JWTs. It can generate both the source
JWTs (which would normally be issued by Azure AD et al) and apikey
JWTs, which are usually the result of the credential exchange
bazel run //scripts:run_genjwt
# This will output something like:
# Token: <header>.<payload>.<sig>
You can take that token from above and exchange it for API credentials, like:
# Be wary of storing sensitive credentials in your Bash (or similar) history.
APIKEY='<token from above>'
curl -H "Authorization: BEARER $APIKEY" -X POST localhost:8080/login/apikey
# This will output something like:
# {"id":"key123","key":"<another token>"}
You can use this new token to query an RMI API:
APIKEY='<the new token>'
# Check the credentials with the Test API
curl -H "Authorization: BEARER $APIKEY" -X POST localhost:8080/credentials:check
Building and running the Docker container locally
To build and run the image locally:
# Build the image
bazel build --@io_bazel_rules_go//go/config:pure //cmd/server:image_tarball
# Load it into Docker. This will print out something like:
# Loaded image ID: sha256:<image SHA>
docker load < bazel-bin/cmd/server/image_tarball/tarball.tar
docker run --rm -it sha256:<image SHA from previous step> --config=/configs/local.conf
If you get an error like:
/server: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.32' not found (required by /server)
/server: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.34' not found (required by /server)
Make sure you included the --@io_bazel_rules_go//go/config:pure
flag in bazel build
, see pure
docs. The problem is that without it, the compiled binary dynamically links glibc against your system, which may use a different version of glibc than the Docker container, which currently uses Debian 11 + glibc 2.28