Backups carried every password hash, encrypted MFA secret and webhook secret in plain JSON, and an import upserted arbitrary rows - including users - so anyone holding backup:import, or tricking an admin into importing a file, could overwrite the admin account with a known password. - Export (download and scheduled) is AES-256-GCM over the gzipped bundle, key from BACKUP_ENCRYPTION_KEY or derived from JWT_ACCESS_SECRET via HKDF; header is authenticated, decompression is capped. Scheduled files are written 0600 in a 0700 directory; run-now returns only the file name. - Import requires the current password (and TOTP when MFA is on). - Only a sealed file restores users, roles, grants, webhooks and audit entries; an old unsealed file restores business data only and reports what it skipped. - Audit entries are append-only on import. - Imported documents: entityType checked against the enum, MIME type allowlisted and matched against the file signature, path kept under the storage root (no more directory traversal via entityType). - Permission cache is cleared after an import. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
27 lines
1.4 KiB
YAML
27 lines
1.4 KiB
YAML
# Vorlage – keine echten Werte. Kopieren, echte Werte setzen, per `kubectl apply` außerhalb
|
||
# der Versionskontrolle anwenden (oder ueber Secret-Manager/Sealed-Secrets im Cluster).
|
||
apiVersion: v1
|
||
kind: Secret
|
||
metadata:
|
||
name: apicore-backend-secret
|
||
type: Opaque
|
||
stringData:
|
||
# Host ist der In-Cluster-Service aus deploy/k8s/postgres/service.yaml.
|
||
# Anderer Namespace als das Backend? Dann FQDN nutzen:
|
||
# apicore-postgres.<namespace>.svc.cluster.local
|
||
DATABASE_URL: "postgresql://apicore:change-me-postgres-password@apicore-postgres:5432/apicore?schema=public"
|
||
# Mindestens 32 Zeichen (server-seitig erzwungen, Start bricht sonst ab) -
|
||
# signiert jedes Access-/MFA-/SSO-Token UND verschluesselt gespeicherte
|
||
# TOTP-Secrets. Erzeugen z.B. mit: openssl rand -hex 32
|
||
JWT_ACCESS_SECRET: "change-me-to-a-random-value-at-least-32-characters-long"
|
||
# Encrypts backup files; needed to restore them on another deployment.
|
||
BACKUP_ENCRYPTION_KEY: "change-me-to-another-random-value-at-least-32-characters"
|
||
JWT_REFRESH_SECRET: "change-me-refresh-secret"
|
||
# Entra ID App-Registrierung (SSO). Siehe configmap.example.yaml
|
||
# fuer OIDC_ISSUER_URL/OIDC_REDIRECT_URI. Wird auch fuer die
|
||
# M365-Kalender-Synchronisation wiederverwendet - dafuer in der
|
||
# App-Registrierung zusaetzlich die Application-Permission
|
||
# "Calendars.ReadWrite" hinzufuegen (Admin-Consent noetig).
|
||
OIDC_CLIENT_ID: "change-me-entra-client-id"
|
||
OIDC_CLIENT_SECRET: "change-me-entra-client-secret"
|