Skip to main content
This page records the chart’s pod-hardening baseline and the platform-team responsibilities it does not cover.

What the chart enforces

Pod-level hardening is rendered into every workload the chart installs. The defaults come from the chart’s templates and values.yaml. Chart-managed selector labels and component labels are silently dropped from per-engine podLabels and similar user surfaces so user input cannot detach selectors. Security contexts can still be overridden through the documented value surfaces. Treat the table below as the install-time baseline, not as an immutable contract.
Podfirebolt/componentUID / GIDrunAsNonRootCapabilitiesSeccompRead-only root FS
Engineengine3473 / 3473truedrop ALLnot set (defer to platform default)true on the engine container
Metadata Servicemetadata-service1111 / 1111truedrop ALLRuntimeDefaulttrue (emptyDir for tmp)
Bundled PostgreSQLmetadata-pg70 / 70truedrop ALLRuntimeDefaulttrue (PGDATA lives on the PVC)
Gateway (Envoy)gateway101 / unsettruedrop ALLnot set (defer to platform default)true
The engine pod additionally sets fsGroup: 3473 (with fsGroupChangePolicy: OnRootMismatch) so the data PVC’s group ownership matches the engine UID.

Memlock-setup sidecar

When engineSpec.memlockSetup: true and podSecurityContext.runAsNonRoot: true, the chart injects a memlock-setup sidecar container that raises the engine pod’s memlock limit. The sidecar runs as UID 0 because it issues a prlimit(2) against the engine container. The pod enables shareProcessNamespace: true so the sidecar can see the engine’s PID. It drops all capabilities except SYS_RESOURCE. When your node hosts already provide a memlock limit of at least 8 GiB, disable it with memlockSetup: false and configure the nodes yourself. See Engine node requirements.

Install-time validation

The chart ships helm/values.schema.json. helm install and helm upgrade reject wrong types and pattern violations on selected known fields, including postgresql.host, postgresql.database, postgresql.schema, customEngineConfig.instance.id, and the engine name. The schema is intentionally permissive, so unknown value paths are not rejected. This is install-time validation, not an admission webhook. It runs only when the chart is being applied, not on subsequent edits to the rendered objects.

What the chart does not enforce

Network isolation between pods

The firebolt-instance Helm chart emits no NetworkPolicy objects. All pod-to-pod and pod-to-external traffic is governed by whatever the cluster’s CNI and NetworkPolicy controller already enforce. In a default Kubernetes install with no NetworkPolicy controller, every pod can reach every other pod on every port. This is a deliberate scoping decision. NetworkPolicy semantics depend on the CNI plugin (Calico, Cilium, Antrea, etc.), the cluster’s default-allow vs. default-deny posture, and the chart-vs-platform ownership boundary for security primitives. Encoding any of those assumptions into chart-emitted NetworkPolicy objects would either be a no-op with no controller installed or actively wrong for the deployment target. Platform teams should apply NetworkPolicy objects covering at least the allowed flows below. Recommended selectors:
Pod kindSelector
Engine podsfirebolt/component=engine, optionally with firebolt/engine=<name> to scope to one engine
Gateway podsfirebolt/component=gateway
Metadata Service podsfirebolt/component=metadata-service
Bundled PostgreSQL podsfirebolt/component=metadata-pg
Release scopingapp.kubernetes.io/instance=<release-name>

Allowed flows

FromToPortPurpose
External clientsGateway8080 (container) / 80 (Service)Query traffic over HTTP
GatewayEngine pods3473Query forwarding
Engine replicas of the same engineEach other5678, 16000, 1717, 3434Distributed query execution and internal coordination between replicas of the same engine. The chart’s engine config lists per-replica FQDNs on the headless Service.
Engine podsMetadata Service7000Metadata gRPC
Metadata ServicePostgreSQL (bundled or external)5432Metadata catalog reads and writes
Engine podsExternal object storage443 / 80Managed-storage reads and writes
PrometheusEngine and gateway pods9090Metrics scraping
Cross-engine traffic (replicas of different engines), gateway-to-metadata, and gateway-to-PostgreSQL are not required by any chart-emitted control flow and should be denied.

Namespace-level resource ceilings

A ResourceQuota capping the aggregate of requests.cpu, requests.memory, pod count, and PVC size across all engines in a namespace is a platform concern. The chart applies per-engine resources.requests and resources.limits from your values, but does not emit a ResourceQuota and does not validate the per-engine resources block against a Helm-side maximum. The per-namespace budget is a deployment-target decision (test cluster vs. multi-tenant production).

Image provenance and supply-chain attestation

The chart pulls whatever image you supply via engineSpec.image.repository, metadata.image.repository, and the equivalent tag values. The chart does not validate signatures, attestations, or SBOMs. If image-policy enforcement is required, use a cluster-level admission controller such as Kyverno or Sigstore Policy Controller.

Admission-time enforcement

The chart has no controller and no admission webhook. Once helm install has rendered the manifests, subsequent edits to the resulting objects (engine StatefulSet pod template, metadata Deployment, gateway Deployment) are not reconciled back to the chart-rendered state. Platform teams that need drift correction should treat the firebolt-instance install as input to GitOps (Argo CD, Flux) and rely on the GitOps controller for drift.
The Firebolt Kubernetes Operator provides continuous reconciliation and admission-time validation natively. When drift correction or admission-time guardrails are a primary requirement, see the operator upgrade path.

Secrets handling

Bundled PostgreSQL

When postgresql.credentials.existingSecret is empty, the chart generates a Secret named <release>-metadata-postgres-creds on first helm install:
  • The Secret holds three base64-encoded keys: username, password, and database.
  • The password is sourced (in order): an explicit postgresql.password value, the existing Secret’s password key on a helm upgrade, or a freshly generated 24-character alphanumeric value (randAlphaNum 24) on a clean install.
  • The chart never rotates the password.
  • The Metadata Service Deployment loads the credentials by mounting the Secret at postgresql.credentials.mountPath.
  • When postgresql.local_enabled: true, the bundled PostgreSQL StatefulSet also reads this generated Secret.
To use a Secret you create yourself, use an external PostgreSQL database and set postgresql.local_enabled: false with postgresql.credentials.existingSecret.

External PostgreSQL

For external databases, use postgresql.credentials.existingSecret. See External PostgreSQL. Inline postgresql.password also works but leaks the password into helm get values.

External object storage

Object-storage credentials for engines are not represented as Helm values. The chart passes customEngineConfig.storage into the engine config and relies on the engine pod’s workload identity for cloud credentials: The chart never sees those cloud provider credentials. For S3-compatible endpoints that use the minio storage type, the endpoint must accept the credentials expected by the engine mode documented in Amazon S3.

TLS to PostgreSQL is not exposed

The chart does not currently expose sslmode or a CA-bundle mount for the Metadata Service’s PostgreSQL connection. Encrypt the PostgreSQL connection at the network layer (VPC peering, sidecar TLS proxy, or service-mesh mTLS) until the chart grows native support.

See also

  • Monitoring: metrics surface and Prometheus Operator integration.
  • Operator upgrade path: when continuous admission, drift correction, and CR-status surfaces are required.
  • SECURITY.md: vulnerability reporting policy for this repository.