07bd94c55a
## Why
NetBox 4.6.5 refuses to save v2 API tokens without `API_TOKEN_PEPPERS` ("Unable to save v2 tokens: API_TOKEN_PEPPERS is not defined"), which blocks creating the superuser token the NetBox Vault engine needs (it defaults to v2 tokens). The chart only auto-generates a pepper when it creates the config secret itself; it does not do that while `existingSecret` (`netbox-secret-key`) is set, so the config secret carries no `api_token_peppers` key.
## Changes
- Document `api_token_peppers` on the `netbox-secret-key` VaultStaticSecret: a JSON pepper map `{"1": "<random>"}` seeded once into Vault alongside `secret_key`. VSO syncs every key at the path into the config secret, which the chart already mounts as an optional file into `API_TOKEN_PEPPERS`.
- Add a reloader annotation via `commonAnnotations` so the `netbox` and `netbox-worker` Deployments roll when `netbox-secret-key` changes, picking up the seeded pepper (and any rotated `secret_key`) without a manual restart.
## Follow-up (out of band)
seed the pepper once (rotating it invalidates existing v2 tokens):
```
PEP=$(openssl rand -base64 48 | tr -d '\n')
vault kv patch kv/kubernetes/namespace/netbox/default/netbox-secret-key \
api_token_peppers="{\"1\": \"$PEP\"}"
```
---------
Co-authored-by: Ben Vincent <neotheo@gmail.com>
Reviewed-on: #346
Co-authored-by: Ben Vincent <ben@unkin.net>
Co-committed-by: Ben Vincent <ben@unkin.net>
151 lines
4.7 KiB
YAML
151 lines
4.7 KiB
YAML
---
|
|
# NetBox (netbox-community chart 8.3.40, appVersion v4.6.5).
|
|
# Postgres = external CNPG cluster, Valkey = standalone Deployment, both defined
|
|
# in apps/base/netbox. Secrets come from Vault via VSO (see base/vaultstaticsecret.yaml).
|
|
|
|
image:
|
|
# ghcr.io is mirrored through artifactapi at the containerd level; the pull is
|
|
# gated by the ^netbox-community/ allowlist added in terraform-artifactapi.
|
|
# tag defaults to the chart appVersion (v4.6.5).
|
|
registry: ghcr.io
|
|
repository: netbox-community/netbox
|
|
|
|
# Two web replicas for zero-downtime rollouts (media is RWX, see below).
|
|
replicaCount: 2
|
|
|
|
# Config secret. Must contain key: secret_key (Django SECRET_KEY). Also carries
|
|
# api_token_peppers — a JSON object {"1": "<50+ char random>"} the chart mounts
|
|
# (optional file) into API_TOKEN_PEPPERS; NetBox 4.6 refuses to save v2 tokens
|
|
# without it. The chart only auto-generates a pepper when it creates this secret
|
|
# itself, which it does NOT do while existingSecret is set — so the pepper is
|
|
# seeded into Vault alongside secret_key (see base/vaultstaticsecret.yaml).
|
|
existingSecret: netbox-secret-key
|
|
|
|
# Bootstrap superuser — existingSecret keys: username, password, email, api_token.
|
|
superuser:
|
|
existingSecret: netbox-superuser
|
|
|
|
# Roll NetBox (web + worker) when the config secret changes, so a Vault-seeded
|
|
# api_token_peppers (or a rotated secret_key) is picked up without a manual
|
|
# restart. commonAnnotations lands on Deployment metadata, where reloader reads it.
|
|
commonAnnotations:
|
|
secret.reloader.stakater.com/reload: netbox-secret-key
|
|
|
|
# Disable the bundled Bitnami subcharts; we bring our own Postgres and Valkey.
|
|
postgresql:
|
|
enabled: false
|
|
valkey:
|
|
enabled: false
|
|
|
|
# External Postgres = the CNPG cluster's pgbouncer pooler (session mode).
|
|
externalDatabase:
|
|
host: netbox-postgres-pooler-rw
|
|
port: 5432
|
|
database: netbox
|
|
username: netbox
|
|
existingSecretName: postgres-credentials
|
|
existingSecretKey: password
|
|
disableServerSideCursors: false
|
|
|
|
# External Valkey — one instance, DB 0 = RQ task queue, DB 1 = cache. No auth
|
|
# (in-cluster, namespace-isolated).
|
|
tasksDatabase:
|
|
host: netbox-valkey
|
|
port: 6379
|
|
database: 0
|
|
cachingDatabase:
|
|
host: netbox-valkey
|
|
port: 6379
|
|
database: 1
|
|
|
|
# Uploaded media/attachments, shared across web replicas (RWX CephFS).
|
|
persistence:
|
|
enabled: true
|
|
storageClass: cephfs-raid6-delete
|
|
accessMode: ReadWriteMany
|
|
size: 5Gi
|
|
|
|
allowedHosts:
|
|
- netbox.k8s.syd1.au.unkin.net
|
|
|
|
serviceAccount:
|
|
create: true
|
|
automountServiceAccountToken: false
|
|
|
|
resources:
|
|
requests:
|
|
cpu: 200m
|
|
memory: 512Mi
|
|
limits:
|
|
cpu: "1"
|
|
memory: 2Gi
|
|
|
|
worker:
|
|
replicaCount: 1
|
|
resources:
|
|
requests:
|
|
cpu: 100m
|
|
memory: 256Mi
|
|
limits:
|
|
cpu: "1"
|
|
memory: 1Gi
|
|
|
|
# --- Authentik OIDC SSO via python-social-auth ---
|
|
# remoteAuth wires REMOTE_AUTH_ENABLED + REMOTE_AUTH_BACKEND; the SOCIAL_AUTH_*
|
|
# settings are supplied via extraConfig (YAML fragments the chart loads into the
|
|
# NetBox config). New OIDC users are auto-provisioned on first login.
|
|
remoteAuth:
|
|
enabled: true
|
|
backends:
|
|
- social_core.backends.open_id_connect.OpenIdConnectAuth
|
|
autoCreateUser: true
|
|
extraConfig:
|
|
# index 0 -> /run/config/extra/0/extra-0.yaml (non-secret OIDC config).
|
|
# Canonical Authentik host identity.unkin.net (served by the internal unkin.net
|
|
# CA; trusted via the combined bundle mounted below).
|
|
- values:
|
|
SOCIAL_AUTH_OIDC_OIDC_ENDPOINT: https://identity.unkin.net/application/o/netbox/
|
|
SOCIAL_AUTH_OIDC_KEY: netbox
|
|
# index 1 -> /run/config/extra/1/oidc.yaml (client secret, from Vault via VSO)
|
|
- secret:
|
|
secretName: oauth-credentials
|
|
items:
|
|
- key: oidc.yaml
|
|
path: oidc.yaml
|
|
|
|
# python-social-auth uses `requests` to reach identity.unkin.net, whose cert is
|
|
# signed by the internal unkin.net CA. Combine the image's public roots with the
|
|
# reflected vault-ca-cert into one bundle and point requests/OpenSSL at it, so
|
|
# both internal (OIDC) and public HTTPS keep working.
|
|
initContainers:
|
|
- name: combine-certs
|
|
image: alpine:3
|
|
command:
|
|
- sh
|
|
- -c
|
|
- cat /etc/ssl/certs/ca-certificates.crt /custom-ca/ca.crt > /combined-certs/ca-certificates.crt
|
|
volumeMounts:
|
|
- name: vault-ca-cert
|
|
mountPath: /custom-ca
|
|
readOnly: true
|
|
- name: combined-certs
|
|
mountPath: /combined-certs
|
|
extraVolumes:
|
|
- name: vault-ca-cert
|
|
secret:
|
|
secretName: vault-ca-cert
|
|
items:
|
|
- key: ca.crt
|
|
path: ca.crt
|
|
- name: combined-certs
|
|
emptyDir: {}
|
|
extraVolumeMounts:
|
|
- name: combined-certs
|
|
mountPath: /etc/ssl/combined
|
|
readOnly: true
|
|
extraEnvs:
|
|
- name: REQUESTS_CA_BUNDLE
|
|
value: /etc/ssl/combined/ca-certificates.crt
|
|
- name: SSL_CERT_FILE
|
|
value: /etc/ssl/combined/ca-certificates.crt
|