feat(provision): automated user provisioning via Authentik webhook
- Expand CI Vault policy: write secret/data/platform + Transit SOPS keys - Add Woodpecker provision-user.yml pipeline (manual event, API-triggered) - Add env vars to webhook-handler deployment for Woodpecker/Authentik integration - Update add-user skill with automated flow documentation - Update Woodpecker repo ID list in CLAUDE.md
This commit is contained in:
parent
82b9dd9e8a
commit
fd130971aa
5 changed files with 287 additions and 22 deletions
|
|
@ -72,7 +72,7 @@
|
|||
- `.woodpecker/build-fallback.yml` — Old full build pipeline preserved (event: `deployment` — never auto-fires)
|
||||
|
||||
**Woodpecker API**: Uses **numeric repo IDs** (`/api/repos/2/pipelines`), NOT owner/name paths (those return HTML).
|
||||
Repo IDs: Website=2, travel_blog=5, health=4, audiblez-web=9, f1-stream=10, plotting-book=43, claude-memory-mcp=78, infra-onboarding=79
|
||||
Repo IDs: infra=1, Website=2, finance=3, health=4, travel_blog=5, webhook-handler=6, audiblez-web=9, f1-stream=10, plotting-book=43, claude-memory-mcp=78, infra-onboarding=79
|
||||
|
||||
**Woodpecker YAML gotchas**:
|
||||
- Commands with `${VAR}:${VAR}` must be **quoted** — unquoted `:` triggers YAML map parsing when vars are empty
|
||||
|
|
|
|||
|
|
@ -10,11 +10,51 @@ description: |
|
|||
|
||||
# Add User
|
||||
|
||||
Add a new namespace-owner to the cluster. No code changes needed — only Vault KV update + stack applies.
|
||||
Add a new namespace-owner to the cluster. Two modes: **automated** (preferred) and **manual** (fallback).
|
||||
|
||||
SOPS state encryption access is **automatically provisioned** by the vault stack — per-stack Transit keys, policies, identity groups, and group aliases are all created from the `k8s_users` map. No manual SOPS setup required.
|
||||
|
||||
## Workflow
|
||||
## Automated Flow (Preferred)
|
||||
|
||||
**Admin creates an Authentik invite → user signs up → provisioning happens automatically.**
|
||||
|
||||
### Steps
|
||||
|
||||
1. **Create Authentik Invitation**
|
||||
- Go to [Authentik Admin](https://authentik.viktorbarzin.me/if/admin/#/core/invitations)
|
||||
- Create a new invitation
|
||||
- Pre-assign the user to the **`kubernetes-namespace-owners`** group
|
||||
- Copy the invite link
|
||||
|
||||
2. **Send Invite Link to User**
|
||||
- The user clicks the link and signs up
|
||||
|
||||
3. **Automatic Provisioning**
|
||||
- Authentik fires a webhook to `webhook.viktorbarzin.me/authentik/provision`
|
||||
- The webhook handler validates the event and triggers the Woodpecker `provision-user` pipeline
|
||||
- Pipeline automatically:
|
||||
- Adds user to Vault KV (`secret/platform` → `k8s_users`) with convention defaults
|
||||
- Creates `sops-<username>` group in Authentik and assigns the user
|
||||
- Applies stacks: vault → rbac → cloudflared → woodpecker
|
||||
- Commits encrypted state and pushes
|
||||
- Sends Slack notification
|
||||
|
||||
4. **Convention Defaults** (applied automatically)
|
||||
- Namespace: `username`
|
||||
- Quota: CPU 2, Memory 4Gi requests / 8Gi limits, 20 pods
|
||||
- Domains: none (user can request later)
|
||||
|
||||
5. **Post-Provisioning**
|
||||
- Send user the onboarding link: `https://k8s-portal.viktorbarzin.me/onboarding?role=namespace-owner`
|
||||
- If custom quota/domains needed, update Vault KV manually and re-apply stacks
|
||||
|
||||
### Monitoring the Pipeline
|
||||
|
||||
Watch the pipeline at: `https://ci.viktorbarzin.me` → infra repo → provision-user pipeline
|
||||
|
||||
## Manual Flow (Fallback)
|
||||
|
||||
Use when automated flow isn't available or custom configuration is needed.
|
||||
|
||||
### Step 1: Collect Information
|
||||
|
||||
|
|
@ -98,20 +138,7 @@ cd stacks/woodpecker && ../../scripts/tg apply --non-interactive
|
|||
cd ../..
|
||||
```
|
||||
|
||||
### Step 4: Create Per-Stack Encrypted State
|
||||
|
||||
For each of the user's namespaces, ensure the Transit key is used for state encryption. New stacks created for the user will automatically use per-stack keys via `scripts/state-sync`.
|
||||
|
||||
If the user's stack already has state, re-encrypt it with the new per-stack key:
|
||||
```bash
|
||||
# Force re-encrypt (delete old .enc, state-sync will use per-stack Transit key)
|
||||
rm state/stacks/NAMESPACE/terraform.tfstate.enc
|
||||
scripts/state-sync encrypt NAMESPACE
|
||||
git add state/stacks/NAMESPACE/terraform.tfstate.enc
|
||||
git commit -m "state(NAMESPACE): re-encrypt with per-stack Transit key"
|
||||
```
|
||||
|
||||
### Step 5: Verify
|
||||
### Step 4: Verify
|
||||
|
||||
```bash
|
||||
# Namespace exists
|
||||
|
|
@ -135,12 +162,9 @@ vault write kubernetes/creds/NAMESPACE-deployer kubernetes_namespace=NAMESPACE
|
|||
|
||||
# SOPS Transit key exists
|
||||
vault read transit/keys/sops-state-NAMESPACE
|
||||
|
||||
# DNS record (if domains specified)
|
||||
dig DOMAIN.viktorbarzin.me
|
||||
```
|
||||
|
||||
### Step 6: Notify User
|
||||
### Step 5: Notify User
|
||||
|
||||
Tell the user to share these onboarding instructions with the new user:
|
||||
- K8s Portal: `https://k8s-portal.viktorbarzin.me/onboarding?role=namespace-owner`
|
||||
|
|
@ -171,7 +195,7 @@ scripts/state-sync decrypt NAMESPACE # decrypts only their stack
|
|||
| Cloudflare DNS records | cloudflared | `domains` list |
|
||||
| Woodpecker admin access | woodpecker | user key |
|
||||
|
||||
## Checklist
|
||||
## Checklist (Manual Flow)
|
||||
|
||||
- [ ] Authentik: user added to `kubernetes-namespace-owners` group
|
||||
- [ ] Authentik: user added to `sops-USERNAME` group (for SOPS state decrypt)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue