From 3efe1b68ef4d186c95e0ab87eec946c211d7a4fb Mon Sep 17 00:00:00 2001 From: Danijel Simeunovic Date: Thu, 23 Apr 2026 10:05:15 +0200 Subject: [PATCH 01/12] auth doc --- docs/DEVELOPER-GUIDE.md | 40 ++++++++++++++++++++++++++++++++++++++++ docs/REFERENCE.md | 18 +++++++++++++++++- 2 files changed, 57 insertions(+), 1 deletion(-) diff --git a/docs/DEVELOPER-GUIDE.md b/docs/DEVELOPER-GUIDE.md index 8f4402f..7ec2605 100644 --- a/docs/DEVELOPER-GUIDE.md +++ b/docs/DEVELOPER-GUIDE.md @@ -962,6 +962,46 @@ User sees application (authenticated) --- +### Accessing Authenticated User Information + +The auth sidecar handles all authentication before requests reach your application. Your app never sees unauthenticated traffic — the sidecar returns 401 or redirects to the IdP first. + +After successful authentication, the sidecar forwards the request to your application with user identity injected as HTTP headers: + +| Header | Description | Available in | +|--------|-------------|-------------| +| `X-Auth-User` | Username or display name | Token, OIDC, MCP | +| `X-Auth-Email` | User email address | OIDC | +| `X-Auth-Subject` | OIDC `sub` claim (stable user ID) | OIDC, MCP | +| `X-Auth-Groups` | Comma-separated group memberships | OIDC (if scope includes `groups`) | +| `X-Auth-Token` | The validated access token | All modes | + +**Your application reads these headers — no auth library needed:** + +```javascript +// Express.js example +app.get('/profile', (req, res) => { + const user = req.headers['x-auth-user']; + const email = req.headers['x-auth-email']; + res.json({ user, email }); +}); +``` + +```python +# Flask example +@app.route('/profile') +def profile(): + user = request.headers.get('X-Auth-User') + email = request.headers.get('X-Auth-Email') + return jsonify(user=user, email=email) +``` + +**Why this is safe**: The Kyverno-generated NetworkPolicy restricts ingress to the sidecar port only. Traffic cannot bypass the sidecar to reach the application port directly, so the `X-Auth-*` headers can be trusted unconditionally. + +**Key principle**: Your application is zero-trust-unaware by design. It reads headers and renders UI. All authentication complexity lives in the sidecar and Kyverno policy. + +--- + ### Authentication Configuration Reference #### Helm Values Schema diff --git a/docs/REFERENCE.md b/docs/REFERENCE.md index 0ba2013..3bf62dd 100644 --- a/docs/REFERENCE.md +++ b/docs/REFERENCE.md @@ -1516,7 +1516,23 @@ Forward to Application (localhost:3000) Application processes request ``` -**See**: [Developer Guide - Enabling Authentication](DEVELOPER-GUIDE.md#enabling-authentication-for-applications) for usage examples. +#### Forwarded Headers + +After successful authentication, the sidecar injects user identity as HTTP headers before forwarding the request to the application container: + +| Header | Description | Auth Modes | +|--------|-------------|------------| +| `X-Auth-User` | Username or display name | Token, OIDC, MCP | +| `X-Auth-Email` | User email address | OIDC | +| `X-Auth-Subject` | OIDC `sub` claim (stable user ID) | OIDC, MCP | +| `X-Auth-Groups` | Comma-separated group memberships | OIDC (if `groups` scope) | +| `X-Auth-Token` | The validated access token | All modes | + +These headers are trustworthy because the auto-generated `NetworkPolicy` restricts pod ingress to the sidecar port only — external traffic cannot reach the application container directly, so headers cannot be spoofed. + +Applications should read these headers to obtain authenticated user information (e.g. for display, authorisation decisions, or audit logging) instead of implementing their own authentication. + +**See**: [Developer Guide - Accessing Authenticated User Information](DEVELOPER-GUIDE.md#accessing-authenticated-user-information) for code examples. --- From 2fb276a62c5ad6e261876224670b8c36a0832fc5 Mon Sep 17 00:00:00 2001 From: Danijel Simeunovic Date: Thu, 23 Apr 2026 13:02:00 +0200 Subject: [PATCH 02/12] ts-mcp --- apps/base/ts-mcp.yaml | 57 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 apps/base/ts-mcp.yaml diff --git a/apps/base/ts-mcp.yaml b/apps/base/ts-mcp.yaml new file mode 100644 index 0000000..5d310e4 --- /dev/null +++ b/apps/base/ts-mcp.yaml @@ -0,0 +1,57 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: ts-mcp + namespace: ts-mcp + annotations: + argocd.argoproj.io/sync-wave: "11" + notifications.argoproj.io/subscribe.on-sync-succeeded.slack: "" + notifications.argoproj.io/subscribe.on-sync-failed.slack: "" + notifications.argoproj.io/subscribe.on-degraded.slack: "" + labels: + app.kubernetes.io/name: ts-mcp + 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/ts-mcp/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: ts-mcp + + syncPolicy: + automated: + prune: true + selfHeal: true + allowEmpty: false + + syncOptions: + - CreateNamespace=true + - Validate=true + - ServerSideApply=false + - Replace=false + retry: + limit: 5 + backoff: + duration: 5s + factor: 2 + maxDuration: 3m + + ignoreDifferences: + - group: apps + kind: Deployment + jsonPointers: + - /spec/replicas From 6b1115ec28b5a2a01908e260686fea20e7178870 Mon Sep 17 00:00:00 2001 From: Danijel Simeunovic Date: Thu, 23 Apr 2026 13:09:02 +0200 Subject: [PATCH 03/12] argocd disable submodule --- docs/REFERENCE.md | 9 +++++++++ infra/values/base/argocd-values.yaml | 3 +++ 2 files changed, 12 insertions(+) diff --git a/docs/REFERENCE.md b/docs/REFERENCE.md index 3bf62dd..d026c47 100644 --- a/docs/REFERENCE.md +++ b/docs/REFERENCE.md @@ -602,6 +602,15 @@ retry: 4. 40 seconds 5. 80 seconds (capped at 3 minutes) +### Global Settings (`argocd-cm`) + +| Setting | Value | Purpose | +|---------|-------|---------| +| `application.resourceTrackingMethod` | `annotation` | Track resources via annotations | +| `timeout.reconciliation` | `60s` | Reconciliation interval | +| `admin.enabled` | `true` | Enable admin account | +| `git.submodule.enabled` | `false` | Disable git submodule checkout — submodules are not needed for manifest generation | + --- ## Infrastructure Components diff --git a/infra/values/base/argocd-values.yaml b/infra/values/base/argocd-values.yaml index 83dc1b3..1dd85c9 100644 --- a/infra/values/base/argocd-values.yaml +++ b/infra/values/base/argocd-values.yaml @@ -6,6 +6,9 @@ configs: application.resourceTrackingMethod: annotation timeout.reconciliation: 60s admin.enabled: "true" + # Disable git submodule checkout - submodules (e.g. shared-prompts) + # are not needed for K8s manifest generation + git.submodule.enabled: "false" params: "server.insecure": true server: From 9c905355e37671a6afa8b63b06bb52dd65293506 Mon Sep 17 00:00:00 2001 From: Danijel Simeunovic Date: Thu, 23 Apr 2026 13:28:34 +0200 Subject: [PATCH 04/12] argocd known host --- infra/values/base/argocd-values.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/infra/values/base/argocd-values.yaml b/infra/values/base/argocd-values.yaml index 1dd85c9..5e0478a 100644 --- a/infra/values/base/argocd-values.yaml +++ b/infra/values/base/argocd-values.yaml @@ -2,6 +2,9 @@ configs: secret: createSecret: true argocdServerAdminPassword: "$2b$12$Tmb1jH7ADvwWoUoNPXXsfOf6JqEluqhq8mL06a8DGT2AP1GzbNsCm" + ssh: + knownHosts: | + [git.forteapps.net]:2222 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDTwi40de8yTGUuRT0i/XGicQ672BLhYR6D/lDquJrp/tdrWoZhVVPy0wxSkWsq1V92iiAUuQnXagOGsLBGZT9uDLWKvEmNDnCfjzTMq3J1iA3vk2rQ8WBlCzhvmeCV/r0ufl6vsgfwxSRomLZeqa2UkLHx69gy2Njb1S2/aZK1Q53f466hCUfDULZrTn2Nn5Sj8cEbJ8EyvVN2YG9HYBxQdzKRPZEmS1vyzmn8YrYIkZseIRQElabzWGh86owuaaqnwJhTJj1j2sEUeIet04sGKJcnxx2UL4H90N66LKMldmMiuli+ve/CjJmMwDl0zGkjIniT3XR8CyEXYHli7B1hR8Z+dbK6DBgjz+28lFgMIRY70KkZJNsJcBNZLZ5fHwCI13a9U3Uhg3Pu/6s0zlosM4CrAQNQCRe95ZPtCpdFhlGrOl4m1rdSK2meL6rND0TBBuZbaFF6Py7TawLCAiO2KRaVqhu9OFVjwJ/nifgLzFGwWj+WcYmpuR+DwozrF/Hl7QYsz1x4GO1SONY07KbIFkUCHOMAh0AELY5YE4eGI4mtG6SecdPaAdLREGZYK4IcyP5i1QW9g0wmfRSsV9jy+r0ivBxixxh4yJiNpkg6NXak40gQtGIme9EJ+DxrRLruNsfDILWcdSuH/wvuorv56NpQFGB0FzB6LXMloSYptQ== cm: application.resourceTrackingMethod: annotation timeout.reconciliation: 60s From 1fa070b041d33c89e68219841169220dded88f7b Mon Sep 17 00:00:00 2001 From: Danijel Simeunovic Date: Thu, 23 Apr 2026 13:35:42 +0200 Subject: [PATCH 05/12] argo --- infra/values/base/argocd-values.yaml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/infra/values/base/argocd-values.yaml b/infra/values/base/argocd-values.yaml index 5e0478a..4bfa6df 100644 --- a/infra/values/base/argocd-values.yaml +++ b/infra/values/base/argocd-values.yaml @@ -9,11 +9,14 @@ configs: application.resourceTrackingMethod: annotation timeout.reconciliation: 60s admin.enabled: "true" - # Disable git submodule checkout - submodules (e.g. shared-prompts) - # are not needed for K8s manifest generation - git.submodule.enabled: "false" params: "server.insecure": true +repoServer: + env: + # Disable git submodule checkout - submodules (e.g. shared-prompts) + # are not needed for K8s manifest generation + - name: ARGOCD_GIT_MODULES_ENABLED + value: "false" server: ingress: enabled: false From c4e586a7be299e6c769dc9fd35656a0abeda75ec Mon Sep 17 00:00:00 2001 From: Danijel Simeunovic Date: Thu, 23 Apr 2026 13:38:47 +0200 Subject: [PATCH 06/12] ts-mcp --- apps/base/kustomization.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/base/kustomization.yaml b/apps/base/kustomization.yaml index 25ead86..5029cf7 100644 --- a/apps/base/kustomization.yaml +++ b/apps/base/kustomization.yaml @@ -4,4 +4,5 @@ resources: - dot-ai-stack.yaml - mcp10x.yaml - musicman.yaml +- ts-mcp.yaml - argo-mcp.yaml From 5394b2c714b6038c38a9ff1ba1e77bfa3e7a2356 Mon Sep 17 00:00:00 2001 From: Danijel Simeunovic Date: Thu, 23 Apr 2026 13:40:33 +0200 Subject: [PATCH 07/12] ts-mcp --- apps/base/ts-mcp.yaml | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/apps/base/ts-mcp.yaml b/apps/base/ts-mcp.yaml index 5d310e4..2612370 100644 --- a/apps/base/ts-mcp.yaml +++ b/apps/base/ts-mcp.yaml @@ -36,22 +36,5 @@ spec: automated: prune: true selfHeal: true - allowEmpty: false - syncOptions: - CreateNamespace=true - - Validate=true - - ServerSideApply=false - - Replace=false - retry: - limit: 5 - backoff: - duration: 5s - factor: 2 - maxDuration: 3m - - ignoreDifferences: - - group: apps - kind: Deployment - jsonPointers: - - /spec/replicas From 84f4bebc08bb59fdba18b9e98f34822148a4f029 Mon Sep 17 00:00:00 2001 From: Danijel Simeunovic Date: Thu, 23 Apr 2026 13:41:51 +0200 Subject: [PATCH 08/12] ts-mcp --- apps/base/ts-mcp.yaml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/apps/base/ts-mcp.yaml b/apps/base/ts-mcp.yaml index 2612370..ff131bf 100644 --- a/apps/base/ts-mcp.yaml +++ b/apps/base/ts-mcp.yaml @@ -1,3 +1,11 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: ts-mcp + annotations: + argocd.argoproj.io/sync-wave: "-1" +--- + apiVersion: argoproj.io/v1alpha1 kind: Application metadata: From 4c65035485c66633ef33b3da1b2a67ec643c9666 Mon Sep 17 00:00:00 2001 From: Danijel Simeunovic Date: Thu, 23 Apr 2026 14:11:45 +0200 Subject: [PATCH 09/12] ns --- apps/base/ts-mcp.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/base/ts-mcp.yaml b/apps/base/ts-mcp.yaml index ff131bf..821c51b 100644 --- a/apps/base/ts-mcp.yaml +++ b/apps/base/ts-mcp.yaml @@ -10,7 +10,7 @@ apiVersion: argoproj.io/v1alpha1 kind: Application metadata: name: ts-mcp - namespace: ts-mcp + namespace: argocd annotations: argocd.argoproj.io/sync-wave: "11" notifications.argoproj.io/subscribe.on-sync-succeeded.slack: "" From 06522b2f191ef4a1201a0e957c0ef43b883166f6 Mon Sep 17 00:00:00 2001 From: Danijel Simeunovic Date: Thu, 23 Apr 2026 14:44:33 +0200 Subject: [PATCH 10/12] ts-mcp --- apps/base/ts-mcp.yaml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/apps/base/ts-mcp.yaml b/apps/base/ts-mcp.yaml index 821c51b..70752ff 100644 --- a/apps/base/ts-mcp.yaml +++ b/apps/base/ts-mcp.yaml @@ -1,11 +1,3 @@ -apiVersion: v1 -kind: Namespace -metadata: - name: ts-mcp - annotations: - argocd.argoproj.io/sync-wave: "-1" ---- - apiVersion: argoproj.io/v1alpha1 kind: Application metadata: From 3f0f70699bb01079431cde91da7ccfef5c48eb10 Mon Sep 17 00:00:00 2001 From: Danijel Simeunovic Date: Fri, 24 Apr 2026 09:43:16 +0200 Subject: [PATCH 11/12] karpor --- docs/REFERENCE.md | 27 +++++++++++++++++ infra/base/karpor.yaml | 42 ++++++++++++++++++++++++++ infra/base/kustomization.yaml | 1 + infra/values/base/karpor-values.yaml | 44 ++++++++++++++++++++++++++++ 4 files changed, 114 insertions(+) create mode 100644 infra/base/karpor.yaml create mode 100644 infra/values/base/karpor-values.yaml diff --git a/docs/REFERENCE.md b/docs/REFERENCE.md index d026c47..7788e4f 100644 --- a/docs/REFERENCE.md +++ b/docs/REFERENCE.md @@ -1078,6 +1078,33 @@ kubectl get secret keycloak-client- -n keycloak -o jsonpath='{.metadata.ann **See**: [Developer Guide - Adding a New Keycloak Client](DEVELOPER-GUIDE.md#adding-a-new-keycloak-client) +### Karpor + +**Chart**: `karpor` from `https://kusionstack.github.io/charts` +**Version**: 0.7.6 (app v0.6.4) +**Namespace**: `karpor` +**Sync Wave**: 1 + +**Purpose**: Kubernetes visualization and intelligence tool. Provides cross-cluster resource search, compliance checking, and topology visualization. Gives platform engineers a unified view of all cluster resources and their relationships. + +**Architecture** (4 components): +- **Server** — main Karpor API/UI (port 7443) +- **Syncer** — syncs cluster state into the search index +- **ElasticSearch** — search backend for resource indexing +- **etcd** — persistent key-value store (10Gi PVC) + +**Configuration** (`infra/values/base/karpor-values.yaml`): +- `namespaceEnabled: false` — ArgoCD manages namespace creation +- Default resource limits tuned for small clusters +- ElasticSearch: 2 CPU / 4Gi memory (the heaviest component) +- AI features available but not enabled (requires `server.ai.authToken` + backend config) + +**Access**: Port-forward to reach the UI: +```bash +kubectl port-forward svc/karpor-release-server -n karpor 7443:7443 +# Open https://localhost:7443 +``` + ### Renovate **Chart**: `renovate` (OCI: `ghcr.io/renovatebot/charts`) diff --git a/infra/base/karpor.yaml b/infra/base/karpor.yaml new file mode 100644 index 0000000..0bd6a25 --- /dev/null +++ b/infra/base/karpor.yaml @@ -0,0 +1,42 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: karpor + namespace: argocd + annotations: + argocd.argoproj.io/sync-wave: "1" + labels: + app.kubernetes.io/name: karpor + app.kubernetes.io/part-of: developer-portal + app.kubernetes.io/managed-by: argocd + finalizers: + - resources-finalizer.argocd.argoproj.io +spec: + project: default + + sources: + - repoURL: https://kusionstack.github.io/charts + chart: karpor + targetRevision: "0.7.6" + helm: + releaseName: karpor + valueFiles: + - $values/infra/values/base/karpor-values.yaml + + - repoURL: ssh://git@git.forteapps.net:2222/Forte/launchpad.git + targetRevision: HEAD + ref: values + + destination: + server: https://kubernetes.default.svc + namespace: karpor + + syncPolicy: + automated: + prune: true + selfHeal: true + allowEmpty: false + syncOptions: + - CreateNamespace=true + - Validate=true + - ServerSideApply=true diff --git a/infra/base/kustomization.yaml b/infra/base/kustomization.yaml index 5c1beb1..a88000f 100644 --- a/infra/base/kustomization.yaml +++ b/infra/base/kustomization.yaml @@ -22,3 +22,4 @@ resources: - tempo.yaml - grafana-dashboards.yaml - network-policies-application.yaml +- karpor.yaml diff --git a/infra/values/base/karpor-values.yaml b/infra/values/base/karpor-values.yaml new file mode 100644 index 0000000..3f67b15 --- /dev/null +++ b/infra/values/base/karpor-values.yaml @@ -0,0 +1,44 @@ +# Karpor - Kubernetes Visualization & Intelligence Tool +# Helm chart: https://github.com/KusionStack/charts/tree/master/charts/karpor + +# Let the ArgoCD Application manage the namespace +namespaceEnabled: false + +server: + replicas: 1 + port: 7443 + resources: + requests: + cpu: 250m + memory: 256Mi + limits: + cpu: 500m + memory: 1Gi + +syncer: + replicas: 1 + port: 7443 + resources: + requests: + cpu: 250m + memory: 256Mi + limits: + cpu: 500m + memory: 1Gi + +elasticsearch: + replicas: 1 + port: 9200 + resources: + requests: + cpu: 500m + memory: 2Gi + limits: + cpu: "2" + memory: 4Gi + +etcd: + replicas: 1 + port: 2379 + persistence: + size: 5Gi From 65598c929793f35e7ca37bb5ba8c68310c2987f2 Mon Sep 17 00:00:00 2001 From: Danijel Simeunovic Date: Fri, 24 Apr 2026 09:47:52 +0200 Subject: [PATCH 12/12] karpor diffs --- infra/base/karpor.yaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/infra/base/karpor.yaml b/infra/base/karpor.yaml index 0bd6a25..dc15e59 100644 --- a/infra/base/karpor.yaml +++ b/infra/base/karpor.yaml @@ -40,3 +40,9 @@ spec: - CreateNamespace=true - Validate=true - ServerSideApply=true + + ignoreDifferences: + - group: apps + kind: StatefulSet + jsonPointers: + - /spec/volumeClaimTemplates