Files
infrastructure/kanidm-setup.sh
T
blandClaude Opus 5 d482ac43c2
deploy / deploy (push) Failing after 2s
gdo in the vel's own stack, and portal v0.5.2
The mailer moves in. Portal decides what to send and publishes it on
this NATS; gdo is what hands it to a mail server, and it belongs here
rather than shared, so the vel's mail leaves on the vel's own terms. It
has no mail server of its own and relays through the host's - on kasse,
Klingenberg Bygg's postfix - which is the one thing this stack borrows
and the one line that changes if the vel ever gets a host of its own.

Also:

- portal v0.5.2, four releases on from the v0.3.36 this pinned.
- The Kanidm setup makes the onboarding service account and its token.
  The vel's desks invite neighbours, and portal needs a token to do it;
  without one every invite fails closed. It goes in
  idm_people_on_boarding, which may create a person and issue a first
  credential reset and nothing else, plus idm_people_pii_read so an
  invite finds someone who already has an account instead of making
  them a second one.
- The deploy workflow runs. It was pointed at a `tomtervel` runner
  label that has never existed, so every push queued and did nothing.
  It now runs on kasse's host runner, which is not root and may run one
  argumentless script that pulls this repo and brings the stack up.
- The hosts default to vel.klingenbergbygg.no and
  id.vel.klingenbergbygg.no, which is where this actually runs. Both
  already resolve to kasse.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-28 20:37:07 +02:00

77 lines
3.6 KiB
Bash
Executable File

#!/bin/sh
# The portal's OAuth2 client and one Kanidm group per desk, mapped into
# the `groups` claim under the names the pages use in `qualifies`.
# Portal reads that claim at login (portal src/auth.rs). Rerunnable.
#
# Logs in first (interactive, idm_admin's password from bootstrap.sh),
# then writes the client secret into .env and portal.env and restarts
# the portal. Needs the kanidm CLI on this machine.
set -eu
cd "$(dirname "$0")"
. ./.env
K="kanidm -D idm_admin -H https://$ID_HOST"
C=$OAUTH2_CLIENT_ID
$K login
has_client() { $K system oauth2 get "$1" 2>/dev/null | grep -q '^name:'; }
has_group() { $K group get "$1" 2>/dev/null | grep -q '^name:'; }
has_client $C || $K system oauth2 create $C "$SITE_NAME" "https://$PORTAL_HOST"
$K system oauth2 add-redirect-url $C "https://$PORTAL_HOST/auth/callback" || true
# The desk groups: every group the content gates a directory on. Keep
# this list equal to the `qualifies` values under questions/.
has_group tomtervel_members || $K group create tomtervel_members
for g in kasserer styret komiteer nabohjelp arrangementer elvesti horingsinstans lekeplasser miljogate pendlerforhold trafikk; do
has_group tomtervel_$g || $K group create tomtervel_$g
$K group add-members tomtervel_members tomtervel_$g
done
# Portal asks for openid, profile and email; groups arrive as a claim.
$K system oauth2 update-scope-map $C tomtervel_members openid profile email
for g in kasserer styret komiteer nabohjelp arrangementer elvesti horingsinstans lekeplasser miljogate pendlerforhold trafikk; do
$K system oauth2 update-claim-map $C groups tomtervel_$g $g
done
$K system oauth2 update-claim-map-join $C groups array
secret=$($K system oauth2 show-basic-secret $C 2>/dev/null | tail -1)
sed -i "s|^OAUTH2_CLIENT_SECRET=.*|OAUTH2_CLIENT_SECRET=$secret|" .env portal.env
# Onboarding from a desk. A committee inviting a neighbour, and any
# state whose `grants:` makes someone a member, both go through Kanidm
# as this service account - not as a person, and not as an admin. It is
# in idm_people_on_boarding, which may create people and issue a first
# credential reset and nothing else, so the token cannot touch anyone's
# existing credentials. idm_people_pii_read lets an invite find someone
# who already has an account by their email, and add them to the group
# instead of making a second account for the same person.
#
# The token is shown once, by Kanidm, at creation. Written straight into
# the env files here and never printed.
SA=portal-onboarding
if ! $K service-account get $SA >/dev/null 2>&1; then
$K service-account create $SA "Portal onboarding" idm_admin
$K group add-members idm_people_on_boarding $SA
$K group add-members idm_people_pii_read $SA || true
fi
if ! grep -q '^KANIDM_API_TOKEN=.' portal.env 2>/dev/null; then
token=$($K service-account api-token generate $SA "portal" --rw 2>/dev/null | tail -1)
if [ -n "$token" ]; then
grep -q '^KANIDM_API_TOKEN=' portal.env \
&& sed -i "s|^KANIDM_API_TOKEN=.*|KANIDM_API_TOKEN=$token|" portal.env \
|| printf 'KANIDM_API_TOKEN=%s\n' "$token" >> portal.env
echo "onboarding token written to portal.env"
else
echo "warning: could not generate the onboarding token - invites will fail closed until it is set"
fi
fi
podman compose restart portal
echo "client $C configured; portal restarted with its secret"
echo
echo "Give people their desk (membership is read at login):"
echo " $K group add-members tomtervel_styret <person>"
echo "Create a person:"
echo " $K person create <name> '<Display Name>' && $K person update <name> --mail <email>"
echo " $K person credential create-reset-token <name>"