hashipi

Raspberry Pi home lab with Nomad and OpenBao
git clone https://git.in0rdr.ch/hashipi.git
Log | Files | Refs | Pull requests |Archive | README

commit 7dceebd028c82b6530f6f3847fe94713b4d3f5ea
parent 5a7162d0b72066fe5381bff055fc2adce1ab12d1
Author: Andreas Gruhler <agruhl@gmx.ch>
Date:   Sat, 22 Nov 2025 11:58:18 +0100

doc: Nomad ACL & OIDC setup

Diffstat:
MREADME.md | 14+++-----------
Anomad-acl/README.md | 110+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Anomad-acl/auth-method-vault.json | 20++++++++++++++++++++
Anomad-acl/policy-admin.hcl | 36++++++++++++++++++++++++++++++++++++
4 files changed, 169 insertions(+), 11 deletions(-)

diff --git a/README.md b/README.md @@ -84,17 +84,6 @@ certificates in the directory `./tls/nomad/certs`: ./nomad-tls.sh ``` -## Nomad ACL -TODO - -* Describe ACLs for Nomad -* https://write.in0rdr.ch/nomad-authentication-with-openbao - -## Nomad SSO with OpenBao OIDC provider -TODO - -Nomad SSO is configured with OpenBao OpenID Connect provider. - ## Nomad workload identity configuration Follow along the tutorial to configure Nomad workload identities with Bao: * https://developer.hashicorp.com/nomad/tutorials/integrate-vault/vault-acl @@ -137,6 +126,9 @@ path "kv/+/{{identity.entity.aliases.AUTH_METHOD_ACCESSOR.metadata.nomad_job_id} $ bao policy write nomad-workloads vault-policy-nomad-workloads.hcl ``` +## Nomad ACL +Manual setup, see [nomad-acl/README.md](./nomad-acl/README.md) + ## Authorized Keys Copy the contents of an openssh pubkey to `authorized_keys` Packer variable. diff --git a/nomad-acl/README.md b/nomad-acl/README.md @@ -0,0 +1,110 @@ +## Nomad ACL +The ACL setup is configured manually (not automated): +* user of the `userpass` auth method is member of the admin group in OpenBao +* admin group of OpenBao translates to Nomad admin role on login, see + [auth-method-vault.json](./auth-method-vault.json) +* Nomad binding rule connects auth method and role via claim/selector (see + Nomad binding rule below) +* [admin policy](./policy-admin.hcl) connected to "admin" role in Nomad (see + Nomad role config below) + +## Nomad SSO with OpenBao OIDC provider +Nomad SSO is configured with OpenBao OpenID Connect provider. +* https://developer.hashicorp.com/nomad/tutorials/archive/sso-oidc-vault +* https://write.in0rdr.ch/nomad-authentication-with-openbao + +## Changes required on node leave/join +Update the list of `redirect_uris` when nodes join/leave. +* In the OpenBao client (see below) +* In the [auth-method-vault.json](./auth-method-vault.json) (see below) + +### OpenBao OIDC provider and client configuration +The OpenBao OIDC provider for Nomad restricts usage to the nomad client: +```bash +$ bao read identity/oidc/provider/nomad +Key Value +--- ----- +allowed_client_ids [$OPENBAO_NOMAD_CLIENT_ID] +issuer https://vault.in0rdr.ch/v1/identity/oidc/provider/nomad +scopes_supported [groups] +``` + +The OpenBao client for Nomad configures the `redirect_uris`: +```bash +$ bao read identity/oidc/client/nomad +Key Value +--- ----- +access_token_ttl 1h +assignments [nomad-oidc-admin] +client_id *** +client_secret hvo_secret_*** +client_type confidential +id_token_ttl 30m +key default +redirect_uris [http://localhost:4200/ui/settings/tokens http://localhost:4649/oidc/callback https://intel0.lan:4646/ui/settings/tokens https://pi0.lan:4646/ui/settings/tokens https://pi1.lan:4646/ui/settings/tokens https://pi2.lan:4646/ui/settings/tokens https://pi3.lan:4646/ui/settings/tokens https://pi4.lan:4646/ui/settings/tokens] +``` + +To update `redirect_uris`: +```bash +$ bao write identity/oidc/client/nomad redirect_uris="space separated" +``` + +The "assignment" restricts users of OpenBao admin group to use the Nomad client: +```bash +$ bao read identity/oidc/assignment/nomad-oidc-admin +Key Value +--- ----- +entity_ids [] +group_ids [$OPENBAO_ADMIN_GROUP_ID] +``` + +### Nomad ACL configuration +The auth method in Nomad is configured with 1h TTL for the `NOMAD_TOKENS`. + +```bash +$ nomad acl auth-method info vault +Name = vault +Type = OIDC +Locality = global +Max Token TTL = 1h0m0s +... + +OIDC Discovery URL = https://vault.in0rdr.ch/v1/identity/oidc/provider/nomad +OIDC Enable PKCE = false +List claim mappings = {groups: roles} +... +``` + +The file [auth-method-vault.json](./auth-method-vault.json) is used to +configure the Nomad authentication method. + +Prepare variables: +```bash +ISSUER=$(curl -s https://vault.in0rdr.ch/v1/identity/oidc/provider/nomad/.well-known/openid-configuration | jq -r .issuer) +CLIENT_ID=$(vault read -field=client_id identity/oidc/client/nomad) +CLIENT_SECRET=$(vault read -field=client_secret identity/oidc/client/nomad) +``` + +Update the JSON file and apply in Nomad (requires management token): +```bash +nomad acl auth-method update -config @auth-method-vault.json vault +``` + +Nomad ACL binding rule creates connection between JWT claim (signed by OpenBao +provider) and role: +```bash +$ nomad acl binding-rule info $RULE_ID +... +Auth Method = vault +Selector = "admin in list.roles" +Bind Type = role +Bind Name = admin +``` + +Nomad ACL role assigns policy: +```bash +$ nomad acl role info $ROLE_ID +... +Name = admin +Policies = admin +``` diff --git a/nomad-acl/auth-method-vault.json b/nomad-acl/auth-method-vault.json @@ -0,0 +1,20 @@ +{ + "OIDCDiscoveryURL": "https://vault.in0rdr.ch/v1/identity/oidc/provider/nomad", + "OIDCClientID": "$CLIENT_ID", + "OIDCClientSecret": "$CLIENT_SECRET", + "BoundAudiences": ["$CLIENT_ID"], + "OIDCScopes": ["groups"], + "AllowedRedirectURIs": [ + "http://localhost:4200/ui/settings/tokens", + "http://localhost:4649/oidc/callback", + "https://intel0.lan:4646/ui/settings/tokens", + "https://pi0.lan:4646/ui/settings/tokens", + "https://pi1.lan:4646/ui/settings/tokens", + "https://pi2.lan:4646/ui/settings/tokens", + "https://pi3.lan:4646/ui/settings/tokens", + "https://pi4.lan:4646/ui/settings/tokens" + ], + "ListClaimMappings": { + "groups": "roles" + } +} diff --git a/nomad-acl/policy-admin.hcl b/nomad-acl/policy-admin.hcl @@ -0,0 +1,36 @@ +namespace "*" { + policy = "write" + variables { + path "*" { + capabilities = ["write", "read", "destroy", "list"] + } + } +} + +node { + policy = "write" +} + +node_pool "*" { + policy = "write" +} + +agent { + policy = "write" +} + +operator { + policy = "write" +} + +quota { + policy = "write" +} + +host_volume "*" { + policy = "write" +} + +plugin { + policy = "read" +}