Tenant Helm Chart Audit
Audit methodology: this document captures the expected classification based on chart inspection. Actual
helm templateruns and diff-vs-classification are required in pre-release validation. Any object found in a real render that isn't listed here becomes a review gate.
Scope of audit
Charts to audit:
| Upstream | Upstream source | Target version |
|---|---|---|
| Wazuh | wazuh/wazuh-kubernetes Helm chart (community) or official OCI chart | Latest stable 4.x supporting single-manager HA |
| TheHive | StrangeBee/thehive4 Helm chart or community | 5.x |
| Cortex | TheHive-Project/Cortex Helm chart or community | 3.x |
| MISP | deferred a future release |
For each chart we vendor the manifest templates (with patches if needed) as subchart dependencies of charts/soctalk-tenant/: Version pinning is strict. Chart.yaml uses exact semver with digest (OCI) where available.
Classification rules
For every rendered object, classify as:
- NS-OK: namespace-scoped object that lives inside
tenant-<slug>. Safe, expected. - CLUSTER-PREREQ: cluster-scoped object that must be installed once by the
soctalk-systemchart or documented as MSSP cluster-admin responsibility. Tenant chart must not re-install these per tenant. - FORBIDDEN: object type or capability we refuse to allow in a tenant chart even when upstream declares it (e.g., cluster-wide
ClusterRoleBindinggiving Wazuh privileged access). Must be patched out. - PATCH: keep the object but modify it (e.g., drop
hostPathvolumes, remove privilegedsecurityContext, reduce default resource requests).
Expected classification per upstream chart
Wazuh
Wazuh charts typically render:
| Object | Expected class | Notes |
|---|---|---|
Deployment / StatefulSet (manager, indexer, dashboard) | NS-OK | Core stack pods |
Service (manager API, indexer, dashboard, agent ingress 1514/1515) | NS-OK | |
ConfigMap (ossec.conf, indexer.yml, dashboard.yml) | NS-OK | |
Secret (admin pw, mutual TLS certs) | NS-OK | Seeded per-tenant at provisioning |
PersistentVolumeClaim (indexer data, manager data) | NS-OK | Size set via tenant values |
ServiceAccount | NS-OK | Per-tenant SA |
Role + RoleBinding (for leader election if used) | NS-OK | Namespace-scoped only |
NetworkPolicy (chart-provided) | PATCH | Replace with SocTalk-rendered NP for consistent posture; don't allow upstream defaults to override default-deny |
StorageClass references | CLUSTER-PREREQ | MSSP must provide a dynamic provisioner; storageClassName is a values input |
Ingress | PATCH or disable | Wazuh's agent protocol on 1514 is not standard TLS, so HTTP/HTTPS Ingress is not appropriate. Strip any Ingress resources. For the agent-ingress Service, the chart should render the variant matching tenant.wazuhIngress.mode: a LoadBalancer Service for per-tenant LB IPs (default) or a ClusterIP Service when the install uses the in-cluster HAProxy fallback. See Wazuh Ingress. |
PodSecurityPolicy / SecurityContextConstraints | CLUSTER-PREREQ if present; forbidden otherwise | PSP is deprecated; if present, remove. OpenShift SCC is not in scope for this release |
CustomResourceDefinition | FORBIDDEN in tenant chart | If the chart tries to install a CRD, move to soctalk-system chart or document as prerequisite |
ClusterRole / ClusterRoleBinding | FORBIDDEN in tenant chart | Never install cluster-wide RBAC from a tenant namespace |
| Privileged/host-network/hostPath pods | FORBIDDEN; patch out | Wazuh manager doesn't require these for standard operation; indexer doesn't either. If a subchart demands hostPath for logs, patch to emptyDir + PVC |
PodDisruptionBudget | NS-OK | Optional; depends on Wazuh HA mode. Single-manager topology may skip |
Expected patches:
- Remove any
ClusterRole/ClusterRoleBindingfrom rendered output. - Remove any cluster-scoped resources (
ValidatingWebhookConfiguration, etc.). - Render the agent-ingress
Serviceto matchtenant.wazuhIngress.mode(LoadBalancerfor per-tenant LB IPs,ClusterIPfor the in-cluster HAProxy fallback). - Strip
Ingressresources. Wazuh dashboards are exposed via a separate SocTalk-managed path; the agent protocol on 1514 is not HTTP, so K8sIngressdoes not apply. - Ensure all pods have
securityContext: { runAsNonRoot: true, allowPrivilegeEscalation: false }; patch if upstream sets otherwise. - Pin images to digests, not
latest.
TheHive
| Object | Expected class | Notes |
|---|---|---|
Deployment (TheHive app) | NS-OK | |
StatefulSet (Cassandra or external-DB-backed variants) | NS-OK | uses embedded Cassandra; external Cassandra is a future release option |
Service (TheHive web + API on 9000) | NS-OK | |
ConfigMap (application.conf) | NS-OK | Per-tenant config rendered by SocTalk |
Secret (admin credentials, Cortex API key for this tenant's Cortex) | NS-OK | |
PersistentVolumeClaim (Cassandra data, index data) | NS-OK | |
ServiceAccount | NS-OK | |
Ingress | PATCH or disable | Same as Wazuh: dashboard exposure via MSSP-side proxy with tenant routing, not per-namespace Ingress |
Job (bootstrap / init) | NS-OK | OK for first-run cert generation / DB init |
CustomResourceDefinition | FORBIDDEN: must be in soctalk-system chart if present | |
ClusterRole / ClusterRoleBinding | FORBIDDEN in tenant chart |
Expected patches:
- Strip Ingress; use ClusterIP Services only.
- Pin Cassandra to digest; set resource limits matching sizing sizing.
- Ensure init Job is idempotent (re-runs harmless).
- No CRD dependencies.
Cortex
| Object | Expected class | Notes |
|---|---|---|
Deployment (Cortex app) | NS-OK | |
StatefulSet (Elasticsearch or compatible index) | NS-OK | embedded ES; external ES is a future release |
Service (Cortex API on 9001) | NS-OK | |
ConfigMap (application.conf, analyzer lists) | NS-OK | |
Secret (admin, inter-service tokens) | NS-OK | |
PersistentVolumeClaim | NS-OK | |
ServiceAccount | NS-OK | |
Job (analyzer registration) | NS-OK if idempotent | |
Ingress | PATCH or disable | |
PrivilegedContainer (Docker-in-Docker for analyzer sandboxing, if upstream uses this pattern) | FORBIDDEN: patch | Cortex analyzers that require Docker sandboxing are out of scope for this release. Use only analyzers that run in-process or call out to sandboxed external services |
Known risk: Cortex historically runs some analyzers as subprocesses or Docker containers. This release limits to "pure-code" analyzers that don't require privileged host access. Analyzer list is pinned in values; analyzers requiring Docker-in-Docker are rejected at provisioning time.
Cluster prerequisites list (rolled into install guide + soctalk-system chart prereq check)
Following the audit, these are out-of-scope for the tenant chart and must exist in the cluster before soctalk-tenant is applied to any namespace:
| Prerequisite | Why | source |
|---|---|---|
| K3s 1.30+ (or compatible K8s 1.30+) | Baseline plus ValidatingAdmissionPolicy v1 | MSSP responsibility |
| NP-enforcing CNI (Cilium primary, Calico alternate) | Isolation enforcement | MSSP responsibility |
| cert-manager | TLS for Ingress, per-tenant Wazuh cert issuance | MSSP responsibility; install guide provides helm install recipe |
| Ingress controller (Traefik default in K3s, ingress-nginx common) | MSSP UI + Customer UI + per-tenant WebUI routing | MSSP responsibility |
Dynamic StorageClass (local-path, longhorn, cloud-provider CSI, etc.) | PVC provisioning | MSSP responsibility |
VolumeSnapshotClass if using CSI snapshots | Backup/restore runbook (docs only) | Optional |
The soctalk-system chart includes a pre-install hook (helm.sh/hook: pre-install) that verifies:
- NP-enforcing CNI active (probes for Cilium or Calico markers)
- cert-manager CRDs present
- Default
StorageClassset
Hook fails fast with actionable error message if any are missing.
Patching strategy
Two paths:
- Values-driven overrides: prefer upstream chart values that disable the unwanted object (e.g.,
ingress.enabled: false,networkPolicy.enabled: falseif upstream's is looser than ours,rbac.create: truescoped to namespace only). - Kustomize-style overlay (Helm's
kustomizeintegration or post-render hook) for objects that can't be disabled via values: stripClusterRoles, removehostPathvolumes, setsecurityContext.
We vendor upstream charts as pinned subchart dependencies in charts/soctalk-tenant/charts/, not as helm repo references. This lets us:
- Pin to exact versions (no upstream surprise updates)
- Apply patches as needed without depending on upstream PR acceptance
- Sign our bundle as a single artifact (a future release when cosign lands)
If upstream doesn't meet our needs after patches, the fallback is to write SocTalk-native templates that call the same container images with our own manifests. pre-release validation decides this per chart.
Known unknowns (pre-release validation resolves)
Items that require actual helm template runs + inspection to confirm:
- [ ] Wazuh: does the chosen chart version require CRDs for operator-driven deployment? If yes, move CRDs to
soctalk-systemchart. - [ ] TheHive: does Cassandra require
StorageClasswith specific features (e.g., RWO only, minimum IOPS)? Document in sizing sizing. - [ ] Cortex: what analyzers are enabled by default, and do any require Docker-in-Docker? Produce an allowlist of-safe analyzers.
- [ ] All charts: any
JoborCronJobthat runs withServiceAccountbeyond the namespace? Patch to ns-local SA. - [ ] All charts: any
initContainerwithprivileged: trueorhostPathmounts? Patch or replace. - [ ] All charts: default
resources.requestsandlimits: Compare to sizing sizing profile; override in values where needed.
Each open item becomes a pre-release validation checklist entry. The spike's output is a filled-in classification table and the patched chart ready for charts/soctalk-tenant/charts/.
Output artifact (produced before shipping)
The spike produces:
- Classified object inventory (filling in section 3 tables with actual rendered objects).
- Patched chart bundles checked into
charts/soctalk-tenant/charts/wazuh/,thehive/,cortex/with pinned versions. - Cluster prerequisites list merged into install guide.
- Analyzer allowlist for Cortex (safe-only set).
- Values schema fragment for each subchart (inputs SocTalk will provide per-tenant).
The spike's completion is a prerequisite for Helm chart implementation.
