23 Commits

Author SHA1 Message Date
21fb50ba00 vw fixes 2026-05-16 15:55:18 +02:00
b90b630b06 comment 2026-05-16 15:52:10 +02:00
66de9b8a0a replicas 2026-05-16 15:48:13 +02:00
716c552be9 ns 2026-05-16 15:44:04 +02:00
f048b47a0f vaultwarden 2026-05-16 15:39:55 +02:00
66f40427ee mappings 2026-05-15 15:47:25 +02:00
332881cbd0 fix 2026-05-14 23:47:14 +02:00
f363afa087 browser flow override 2026-05-14 23:43:40 +02:00
bc42347cb6 gitea+ACCOUNT_LINKING 2026-05-14 21:30:53 +02:00
80d7bff4bc groups 2026-05-14 21:18:17 +02:00
3644a3ec87 mappers 2026-05-14 21:14:57 +02:00
bd478478f1 fix attemt 2026-05-14 20:40:44 +02:00
67b1d95509 account linking 2026-05-14 19:39:38 +02:00
fff95d98a5 remove protocol mappers 2026-05-13 23:15:28 +02:00
8b743efa43 KC fix 2026-05-13 23:13:09 +02:00
4ca9039686 kpolicy 2026-04-29 12:54:07 +02:00
6a9eadbde8 vault ignore diffs 2026-04-29 12:50:10 +02:00
f19f7c9237 icon 2026-04-29 12:07:04 +02:00
5a459d486e dbunk-demo 2026-04-29 10:53:35 +02:00
31fb476a78 row 2026-04-29 10:06:02 +02:00
a088425b70 homepage config 2026-04-29 10:04:20 +02:00
b3b3edf82c no header 2026-04-28 23:03:15 +02:00
308755a4b3 layout 2026-04-28 23:02:13 +02:00
17 changed files with 371 additions and 13 deletions

View File

@@ -0,0 +1,47 @@
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: dbunk-demo
namespace: argocd
annotations:
argocd.argoproj.io/sync-wave: "12"
labels:
app.kubernetes.io/name: dbunk-demo
app.kubernetes.io/part-of: apps
app.kubernetes.io/managed-by: argocd
finalizers:
- resources-finalizer.argocd.argoproj.io
spec:
project: default
sources:
- repoURL: ssh://git@git.forteapps.net:2222/Forte/forte-helm.git
path: forteapp
targetRevision: HEAD
helm:
valueFiles:
- $values/dbunk-demo/values.yaml
- repoURL: ssh://git@git.forteapps.net:2222/Forte/helm-prod-values.git
targetRevision: HEAD
ref: values
destination:
server: https://kubernetes.default.svc
namespace: dbunk-demo
syncPolicy:
automated:
prune: true
selfHeal: true
allowEmpty: false
syncOptions:
- CreateNamespace=true
- Validate=true
- ServerSideApply=true
retry:
limit: 5
backoff:
duration: 5s
factor: 2
maxDuration: 3m

View File

@@ -0,0 +1,4 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- dbunk-demo.yaml

View File

@@ -2,6 +2,7 @@ apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization kind: Kustomization
resources: resources:
- ../../base - ../../base
- dbunk-demo
# No patches needed — base already has "upc-dev" paths # No patches needed — base already has "upc-dev" paths
# upc-dev is the default/base cluster # upc-dev is the default/base cluster

View File

@@ -1063,6 +1063,46 @@ dind:
- Gitea admin panel (`/admin/runners`) — runners show as Online - Gitea admin panel (`/admin/runners`) — runners show as Online
- Create test workflow in `.gitea/workflows/test.yml` — job executes - Create test workflow in `.gitea/workflows/test.yml` — job executes
### Vaultwarden
**Chart**: `guerzon/vaultwarden`
**Version**: 0.36.4 (app v1.36.0-alpine)
**Namespace**: `vaultwarden`
**Purpose**: Self-hosted Bitwarden-compatible password manager.
**Configuration**:
```yaml
# infra/overlays/upc-dev/vaultwarden/ + infra/values/
domain: "https://vaultwarden.forteapps.net"
ingress:
enabled: true
class: "traefik"
tls: true
tlsSecret: vaultwarden-tls
hostname: bitwarden.forteapps.net
additionalAnnotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
database:
type: postgresql
existingSecret: prod-db-creds
storage:
data: 5Gi (ReadWriteOnce)
attachments: 5Gi (ReadWriteOnce)
```
**TLS**: cert-manager auto-provisions Let's Encrypt certificate via `letsencrypt-prod` ClusterIssuer (same pattern as Gitea, Grafana, etc).
**Endpoints**:
- Web UI: `https://bitwarden.forteapps.net`
**Secrets**:
- `prod-db-creds` — PostgreSQL credentials + SMTP credentials
- `vaultwarden-tls` — auto-managed by cert-manager
### AI Code Review (ai-review) ### AI Code Review (ai-review)
**Type**: Gitea Actions workflow (`.gitea/workflows/ai-review.yaml`) **Type**: Gitea Actions workflow (`.gitea/workflows/ai-review.yaml`)
@@ -1141,6 +1181,30 @@ ignore:
- Check Gitea Actions tab for workflow run status and logs - Check Gitea Actions tab for workflow run status and logs
- Monitor Anthropic usage dashboard for token consumption - Monitor Anthropic usage dashboard for token consumption
### Keycloak Browser Flow (IdP Auto-Redirect)
**File**: `infra/values/base/keycloak-values.yaml` (inside `forte-realm.json`)
The realm uses a custom browser authentication flow (`browser-auto-idp`) that skips the Keycloak login page and redirects directly to the Entra ID identity provider.
**Flow executions**:
| Priority | Authenticator | Requirement | Purpose |
|----------|--------------|-------------|---------|
| 10 | `auth-cookie` | ALTERNATIVE | Reuse existing session (no redirect) |
| 20 | `identity-provider-redirector` | ALTERNATIVE | Auto-redirect to `forte-entra` IdP |
**Key fields in realm JSON**:
- `"browserFlow": "browser-auto-idp"` — overrides the default `browser` flow at realm level
- `"authenticationFlows"` — defines the custom flow with its executions
- `"authenticatorConfig"` — sets `defaultProvider: "forte-entra"` on the redirector
**Why custom flow**: The default KC browser flow shows a username/password form with an IdP button. Since all authentication is via Entra ID, the custom flow eliminates this step. The `auth-cookie` execution preserves session reuse so returning users aren't redirected again.
**Important**: The `forte-entra` identity provider must exist in Keycloak (currently configured manually in the KC admin console). If the IdP alias changes, update the `defaultProvider` value in the realm JSON.
---
### Keycloak Client Registrar ### Keycloak Client Registrar
**Type**: CronJob (deployed via Keycloak Helm chart `extraDeploy`) **Type**: CronJob (deployed via Keycloak Helm chart `extraDeploy`)

View File

@@ -27,7 +27,6 @@ spec:
automated: automated:
prune: true prune: true
selfHeal: true selfHeal: true
allowEmpty: false
syncOptions: syncOptions:
- CreateNamespace=true - CreateNamespace=true
- Validate=true - Validate=true

View File

@@ -41,3 +41,9 @@ spec:
- CreateNamespace=true - CreateNamespace=true
- Validate=true - Validate=true
- ServerSideApply=true - ServerSideApply=true
ignoreDifferences:
- group: apps
kind: StatefulSet
jsonPointers:
- /spec/volumeClaimTemplates

View File

@@ -2,6 +2,7 @@ apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization kind: Kustomization
resources: resources:
- ../../base - ../../base
- vaultwarden
# No patches needed — base already has "upc-dev" paths # No patches needed — base already has "upc-dev" paths
# upc-dev is the default/base cluster # upc-dev is the default/base cluster

View File

@@ -0,0 +1,5 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- vaultwarden.yaml
- vaultwarden-db-secret-sealed.yaml

View File

@@ -0,0 +1,18 @@
---
apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
creationTimestamp: null
name: prod-db-creds
namespace: vaultwarden
spec:
encryptedData:
SMTP_PASSWORD: AgARC3vcVD2SC8GUry5SYylyiS39eKQUFAjqT4dpXQsoJX7QSLfd7Ta68BURg8Q5e2zWdzIl+nrUyBy/4TMXeHjSUhcfsH0RY2logMuTn96kV/V7YKm1Zw394hrJ3uroB7iFkf/TwiXuwFS1QvppxlpXNWVClHs+r0aW3vD2s7ViFxFqcPYGfNKlGvW2aLU6XER/TUXCffoSmHgl0wut5UaZEo+321AAaqcmk90Te/Pv4oU0SfFGn/+14zDR3VT4s6u8rgYQcSB23p2f3X3+8tCLgSLclyzSXAVfclMBYCuCtOzFjgXOQLoYfW3WW48KqsFKsoZsI/dop8L/y2P78xGJ5gYNiVcH6vEMfOr6wOTISyXqQIi3a/KZcNSY4ZZ7kH13aqru3Fpb4XAGjcmEEfWfOQ9IcPBj6Yh9pNOhxlQHPqXR9zrwx//iXdH2bsbEJ2vNHQhU9uc4t3dO1VnLO/icvMr3CFEuaB4mFDThVrPGOEi5s1YKPTHb1j8B92WSy6aNmNro0977cbbJs/linNox3rNa20kzQPfU2pdlC31vIcpMCM7vtUnx16QHyjUNe/whFqIbSG3mE19jbjIvGo0d7jhBWZYQin+m1MRv/Tv8VjzYe6FciIFX33pNTWkwkvFq+s8eQcyruWCe5hLlF361FklqXcSh1tMyqcfOScNRPxUPlWumkGPDmonULJPkmAs7eJmxKlvinrAPs8eiP7c/1SPW6FdMmxT7sq/27TII
SMTP_USERNAME: AgC1Zsv5l5Wbrq7VZC2U55+0/LQvZEbsmlxq2O5Z+Xp/admdqptEBGlLKEdIn7CmyBzvmrmWasmN4NJPJHoeLWn7SgsoULTu1UQ3W9kgcrXUJ52dwOrYLMJUxJuh+OD9HEJejfOMksc2rSM69I4NUc+NXaDSZOo+gzldWzBN7nCa778NcnMgJxVcT4gqjTIRB9EOrCo4f3ldFJzVJW7qNnxurN0UZQ51y+nj+4z2R+LvfOJ1BT5YQC+nmx80HVBMdQWK5WO4QdxCtenXfiFDNcGK3MK/Exd+kubOWse85CMt2dR0GWuIfIOp+t4XQXfb1pxhTibh/fGae9dD0RpSX1c8hobkpXaDJIYeb7ZQF5J6Zf68fgCn0YircY1hB4yF7uX5CQL1yv76M4tM9yuOn5FTJaIG6byWn/RsHZ7KPIUSd1mOce9ZqfTkKzvC/wfX45UMhPEsdXF9o67mAtOpdmBGrmeDD+7GwPwKXz3JgDovlGtzvLvMZ27+x1dpC8LrcAjcKXXGKczbs3L2Pc+tymd9dis36RvlFLEgQG32ffQu5vQXqGcoSEnlZ0l39qoU9EItkA5kp0isGiJI46hJtAdTTNr0roymvrfDyLXpAvXTQYaVMC7/8KVb2r3kIPKtnsDuU2A57ceiqtdWQgUarPn4F0O3SaCnprmTm2thgCgQOkW7BGlN3CCsVboZUIOlFr7CwTswB9ZI6tzOj2WsUOhriTfIuXv3kyrFCspo
pgpassword: AgB7F1Nvm2sjBOneDFux2mc/qni32jaq+KccTWkS7UZWWgA37owrE/XvDSOXZ0ZkrpBfhvCnsrh7/mbVnZYNWCd/GgxI2txnkp9MxW5JLpJiaZZmzznI229BgG9I08vg6ciuUS+bvRw9XJFD7SAmgeA3NaDKAHRNIhu3CFEKQJANity+pKHY1zK6gX6ubmllFtjEJg2pijM3EeSNuXdAFXZlsYIJMqFzlvQrb4MV7qeqsvW2qMeJBElMnas60l3JgeUYtsIwh6720m6FFKGXYQLm4cKbByC0M1C0/Nfwnd9j+xgIgyXharQFmgyp1qQBM+MAHxnHoHCE3V9cJqy1nCy33M16YYsZGOuAkHB9ks9I7NxGAKKjAIm5DccW7zbYINzTQKAUYIF/VhVosHv0thAHjfuH7fGzSmo9BHrLTQE3tO5RF40X2GgKFxP/R5lA+dCtR2QBNot0DaL2TEJoPc0czSYPY5y92FDOQ1j9jvcet18tkJN+bzCKwiG+BxtD0eH+tv1EAZTwvyl43xlU3E3RwWgSmOWcusMrn92fhsHwNFs9mMeeM8qeAVq4xUkatbKoijHm6q03tMgp2T6iT3EoVNLzWz+754mLQxt6serkBS8U7Mkxwpfitf64ANLaQyMF8t9Rao0c8Q/ZkIl9TEczbCPX3DvlnsoSPKDMWGB9gTzKbvvH0+Gcxxs+LZFigE7SQ20kYMlQpD8uo15ufWpMSGmFJxvto55fYgA0+wJmqe18ERy1QjxCqQYG7A==
pgusername: AgAvYmIjfz5UbstZli9gpc77rc+oAft7NYIHFrSClyV0Ugt6UU+icMMlLbU92roy7J9XUHuWoXoK5vh0y/XeF95ce1VJC0/zvMK2OXmpfERbyNvyCpwzCFtzYJ4LO7yOi8PAPstzuziqnvLt+GLCwk1enU+IWHI7G2A/qIeWEww5+Y5a4WevVrchp0Wh87PdJ88IT5EiF7qBT2ipbcSoB+Gon962nbw8+pnFedmRcUQcdOf0tQBBZOl5TUVJ6mn4WIY8u6/yOwACMlUXQ553rxXYwGKyTRjI0KbTWwpgeCJiqokyrw/RcShD6qJvZGePdq6rNmmkELOHCPo9z/WvXQIDHbuPldvcglyHuN2w4tsBcGukbmjitwS6wxYD0vp3er3FI9+0tRnD9zlkLiUpcaLi9Rrm7NPS/JP1dbGcHz7fJNXgbMZRGRx3DjV73Qnz6YHvOHT4g6BI2+9JytriRKSOJk/FlDCINgrO+6zMrbxKzBTW3+FK1cc41sJ9zClbV603wsMgtkmB1sZL4xcLmq5wOuk19uO9TsK0Xnf+ajuFUkQm42DVxtTZ9HObLnP8eygn1WiMDv3ks6W7HIpJTpc2YJVU/Pg/kTeQgBKS0JRTkzpJFPHV2UrkLTr0U6ToPYOb2SWBnPI+Lp3cTOeUsbKOylBzx4uUJGoZUL5pAorjd5tDHJhMyMm589m5J3mGMXuhXO1cWg80
template:
metadata:
creationTimestamp: null
name: prod-db-creds
namespace: vaultwarden

View File

@@ -0,0 +1,49 @@
apiVersion: v1
kind: Namespace
metadata:
name: vaultwarden
---
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: vaultwarden
namespace: argocd
annotations:
argocd.argoproj.io/sync-wave: "1"
labels:
app.kubernetes.io/name: vaultwarden
app.kubernetes.io/part-of: security
app.kubernetes.io/managed-by: argocd
finalizers:
- resources-finalizer.argocd.argoproj.io
spec:
project: default
sources:
- repoURL: https://guerzon.github.io/vaultwarden
chart: vaultwarden
targetRevision: "0.36.4"
helm:
releaseName: vaultwarden
valueFiles:
- $values/infra/values/base/vaultwarden-values.yaml
- $values/infra/values/upc-dev/vaultwarden-values.yaml
- repoURL: ssh://git@git.forteapps.net:2222/Forte/launchpad.git
targetRevision: HEAD
ref: values
destination:
server: https://kubernetes.default.svc
namespace: vaultwarden
syncPolicy:
automated:
prune: true
selfHeal: true
allowEmpty: false
syncOptions:
- CreateNamespace=true
- Validate=true
- ServerSideApply=true

View File

@@ -41,6 +41,7 @@ gitea:
oauth2: oauth2:
ENABLED: true ENABLED: true
ENABLE_AUTO_REGISTRATION: true ENABLE_AUTO_REGISTRATION: true
ACCOUNT_LINKING: auto
USERNAME: email USERNAME: email
session: session:

View File

@@ -17,7 +17,7 @@ config:
traefik: true traefik: true
settings: settings:
title: "Forte Platform" title: "Platform"
headerStyle: clean headerStyle: clean
layout: layout:
Apps: Apps:
@@ -26,12 +26,16 @@ config:
Security: Security:
style: row style: row
columns: 3 columns: 3
DevOps: Tools:
style: row style: row
header: false
columns: 2 columns: 2
DevOps:
style: column
rows: 2
Monitoring: Monitoring:
style: row style: column
columns: 1 rows: 1
# Top-of-page cluster overview widget # Top-of-page cluster overview widget
widgets: widgets:
@@ -50,12 +54,7 @@ config:
# In-cluster entries come from K8s service annotations. # In-cluster entries come from K8s service annotations.
# External (out-of-cluster) services are listed here statically. # External (out-of-cluster) services are listed here statically.
bookmarks: [] bookmarks: []
services: services: []
- Apps:
- Forte Feedback:
href: https://feedback.forteapps.net
description: Fortes internal feedback app
icon: forte
resources: resources:
requests: requests:

View File

@@ -58,6 +58,9 @@ keycloakConfigCli:
enabled: true enabled: true
image: image:
repository: bitnamilegacy/keycloak-config-cli repository: bitnamilegacy/keycloak-config-cli
extraEnvVars:
- name: IMPORT_MANAGED_PROTOCOL_MAPPER
value: "no-delete"
configuration: configuration:
forte-realm.json: | forte-realm.json: |
{ {
@@ -101,6 +104,18 @@ keycloakConfigCli:
"access.token.claim": "true", "access.token.claim": "true",
"userinfo.token.claim": "true" "userinfo.token.claim": "true"
} }
},
{
"name": "groups",
"protocol": "openid-connect",
"protocolMapper": "oidc-group-membership-mapper",
"config": {
"claim.name": "groups",
"full.path": "false",
"id.token.claim": "true",
"access.token.claim": "true",
"userinfo.token.claim": "true"
}
} }
] ]
}, },
@@ -173,7 +188,54 @@ keycloakConfigCli:
] ]
} }
], ],
"browserFlow": "browser-auto-idp",
"authenticationFlows": [
{
"alias": "browser-auto-idp",
"description": "Browser flow with auto-redirect to Forte Entra IdP",
"providerId": "basic-flow",
"topLevel": true,
"builtIn": false,
"authenticationExecutions": [
{
"authenticator": "auth-cookie",
"authenticatorFlow": false,
"requirement": "ALTERNATIVE",
"priority": 10
},
{
"authenticator": "identity-provider-redirector",
"authenticatorFlow": false,
"requirement": "ALTERNATIVE",
"priority": 20,
"authenticatorConfig": "forte-entra-redirector"
}
]
}
],
"authenticatorConfig": [
{
"alias": "forte-entra-redirector",
"config": {
"defaultProvider": "forte-entra"
}
}
],
"groups": [ "groups": [
{
"name": "k8s",
"path": "/k8s",
"clientRoles": {
"grafana": ["Editor"]
}
},
{
"name": "dev",
"path": "/dev",
"clientRoles": {
"grafana": ["Viewer"]
}
},
{ {
"name": "ArgoCD Admins", "name": "ArgoCD Admins",
"path": "/ArgoCD Admins" "path": "/ArgoCD Admins"

View File

@@ -0,0 +1,3 @@
image:
tag: "1.36.0-alpine"
domain: "https://vaultwarden.forteapps.net"

View File

@@ -6,5 +6,5 @@ ingress:
gethomepage.dev/name: "Databunker" gethomepage.dev/name: "Databunker"
gethomepage.dev/description: "Secure Database for PII and PCI Records" gethomepage.dev/description: "Secure Database for PII and PCI Records"
gethomepage.dev/group: "Security" gethomepage.dev/group: "Security"
gethomepage.dev/icon: "adminer" gethomepage.dev/icon: "double-take"
gethomepage.dev/href: "https://databunker.forteapps.net" gethomepage.dev/href: "https://databunker.forteapps.net"

View File

@@ -13,3 +13,53 @@ ingress:
- secretName: homepage-tls - secretName: homepage-tls
hosts: hosts:
- start.forteapps.net - start.forteapps.net
config:
settings:
title: "Forte Platform"
headerStyle: clean
layout:
Apps:
style: row
columns: 2
Security:
style: row
columns: 3
Tools:
style: row
header: false
columns: 2
DevOps:
style: column
rows: 2
Monitoring:
style: column
rows: 1
# Top-of-page cluster overview widget
widgets:
- kubernetes:
cluster:
show: true
cpu: true
memory: true
showLabel: true
label: "Cluster"
nodes:
show: true
cpu: true
memory: true
showLabel: true
# In-cluster entries come from K8s service annotations.
# External (out-of-cluster) services are listed here statically.
bookmarks: []
services:
- Apps:
- Forte Benken:
href: https://benken.hackathon.forteapps.net
description: Teknisk kompetanse fra offentlige anbud
icon: forte
- Forte Feedback:
href: https://feedback.forteapps.net
description: Fortes internal feedback app
icon: forte

View File

@@ -0,0 +1,49 @@
database:
type: postgresql
existingSecret: prod-db-creds
existingSecretUserKey: pgusername
existingSecretPasswordKey: pgpassword
ingress:
enabled: true
class: "traefik"
tls: true
tlsSecret: vaultwarden-tls
hostname: bitwarden.forteapps.net
additionalAnnotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
replicas: 1
# Multi-Attach error for volume "pvc-102ec9a4-dccd-4cba-bb4b-650f7d934c81" Volume is already used by pod(s) vaultwarden-7f568875c7-m9cgs
service:
sessionAffinity: ClientIP
sessionAffinityConfig:
clientIP:
timeoutSeconds: 10800
smtp:
host: smtp.office365.com
from: no-reply@forteapps.net
fromName: "Forte Bitwarden Administrator"
existingSecret: prod-db-creds
username:
existingSecretKey: SMTP_USERNAME
password:
existingSecretKey: SMTP_PASSWORD
storage:
data:
name: "vaultwarden-data"
size: "5Gi"
class: ""
path: "/data"
keepPvc: true
accessMode: "ReadWriteOnce"
attachments:
name: "vaultwarden-files"
size: "5Gi"
class: ""
path: /files
keepPvc: true
accessMode: "ReadWriteOnce"