Skip to content

Secrets management

The DataQI Helm chart uses a “Pre-requisite Day 2” secret model. Helm does not generate any credentials or certificates on deployment. All credentials must be provisioned into the cluster as standard Kubernetes Secret resources before running helm upgrade --install.

The chart expects these secrets to follow a canonical dataqi-<component> naming scheme by default. If you use other tools, such as External Secrets Operator, you can map custom secret names in the chart’s values.yaml under the secrets: block.


These secrets are essential for the primary dataqi deployment.

  • Type: kubernetes.io/dockerconfigjson.
  • Purpose: Provides authentication credentials to pull DataQI container images from a private registry. Not required when pulling from an unauthenticated registry (for example if you are mirroring the images to a local registry). In that case, set secrets.registry: "" in your values file to skip imagePullSecrets entirely.
  • Required keys:
    • .dockerconfigjson: A JSON payload containing the registry credentials.
      • Example payload before Base64 encoding: {"auths":{"acrdataqi-ayguf2ahfghaenfn.azurecr.io":{"username":"<YOUR_USER>","password":"<YOUR_PASSWORD>","auth":"<BASE64_USER_PASS>"}}}.

Tip: You can easily generate this secret using the following kubectl command:

Terminal window
kubectl create secret docker-registry dataqi-image-registry \
--docker-server=<registry-url> \
--docker-username=<username> \
--docker-password=<password>
  • Type: Opaque.
  • Purpose: Mounted into the NATS message broker pod as an auth.conf configuration file to enforce client authentication.
  • Important: The password must be alphanumeric only (NATS rejects special characters in its config file) and exactly match the password in dataqi-nats-connection.
  • Required keys:
    • auth.conf: authorization { user: "nats-user", password: "<randomly-generated-password>" }.
  • Type: Opaque.
  • Purpose: Stores the connection string that allows the API and asynchronous workers to connect to the NATS message broker securely.
  • Required keys:
    • connection-string: nats://nats-user:<randomly-generated-password>@nats:4222.
  • Type: Opaque.
  • Purpose: Configures the Valkey (Redis-compatible) server password and the API client connection used for distributed caching and coordination.
  • Required keys:
    • password: <randomly-generated-password>.
    • connection-string: valkey:6379,password=<randomly-generated-password>,abortConnect=false.
  • Type: Opaque.
  • Purpose: Provides the endpoint and ingestion key used by the OpenTelemetry (OTel) Collector to export traces and metrics. The presence of this secret activates telemetry exporting. If omitted, the collector will still deploy and process traffic but will drop the payloads instead of exporting them.
  • Required keys:
    • endpoint: https://telemetry.dataqi.somewhere:4317.
    • bearer-token: <telemetry-bearer-token>.
  • Type: Opaque.
  • Purpose: Contains a PFX certificate and its password. This is used by the API to securely encrypt and decrypt credentials that are used for connecting to external systems. For instructions on generating this certificate, see the Data protection certificate guide.
  • Required keys:
    • dataprotection.pfx: <binary-certificate-data> (Must be properly Base64 encoded if passing via YAML data: block).
    • certificate-password: <certificate-password>.

Warning: Beware of double encoding

Do not use kubectl create secret ... --from-literal=dataprotection.pfx="<base64>" to inject a Base64-encoded string from the command line or CI/CD pipelines. This causes Kubernetes to Base64 encode the string again, resulting in a corrupted certificate when the pod mounts the file.

Correct approach: Always create this secret directly from the binary file:

Terminal window
kubectl create secret generic dataqi-api-data-protection \
--from-file=dataprotection.pfx=./dataprotection.pfx \
--from-literal=certificate-password="<password>"

Warning: Do not auto-rotate this certificate

Auto-rotating the Data Protection PFX certificate in your secrets manager will instantly destroy the decryption keys running in the cluster. This will immediately prevent the application from decrypting user secret values rendering them permanently un-decryptable and breaking user functionality.

Note: This certificate is used for encrypting user credentials that are stored in the database. It does not need to be signed by a trusted Certificate Authority because there is no trust relationship between the certificate and any external systems.

dataqi-keycloak-initial-admin (Auto-generated)

Section titled “dataqi-keycloak-initial-admin (Auto-generated)”
  • Type: basic-auth.
  • Purpose: Contains the initial admin credentials for the Keycloak management console. This secret is automatically created by the Keycloak Operator when Keycloak starts for the first time — you do not need to create it yourself.
  • Keys:
    • username: The admin username.
    • password: The auto-generated admin password.

Tip: Retrieve the auto-generated admin credentials after installation:

Terminal window
kubectl get secret dataqi-keycloak-initial-admin -o jsonpath='{.data.username}' | base64 -d
kubectl get secret dataqi-keycloak-initial-admin -o jsonpath='{.data.password}' | base64 -d

Store these securely so that you can log in and administer the DataQI login server post-installation.

  • Type: Opaque.
  • Purpose: Automatically provisions an upstream Microsoft identity provider in Keycloak. Omitting this secret leaves Keycloak configured for local authentication only.
  • Required keys:
    • clientId: <client-id>.
    • clientSecret: <client-secret>.
    • tenantId: <tenant-id>.
  • Type: Opaque.
  • Purpose: Provides the bind credentials for Keycloak to connect to an external LDAP directory (e.g., Active Directory). The name of this secret must be explicitly provided in your values file under infra.keycloak.ldap.bindCredentialSecretName.
  • Required keys:
    • password: <ldap-bind-password>.
  • Type: Opaque.
  • Purpose: Inject the API key required for outbound LLM service communication (e.g., Azure OpenAI, OpenRouter).
  • Important: If your LLM endpoints are unsecured or use keyless identity, omit this secret completely.
  • Required keys:
    • default-api-key: <llm-api-key>.
  • Type: Opaque.
  • Purpose: Provides the API key used to authenticate external systems calling the workflow trigger endpoint. Each deployment instance should use a unique key.
  • Required keys:
    • api-key: <randomly-generated-api-key>.

Tip: Generate a strong random key and create the secret:

Terminal window
kubectl create secret generic dataqi-api-key-auth \
--from-literal=api-key="$(openssl rand -base64 32)"

DataQI supports two ways to supply a custom Certificate Authority (CA) bundle to outbound-facing pods, so they trust internal corporate PKI or self-signed certificates that are not present in standard Linux root stores. Choose whichever approach fits your environment — both are supported across both charts:

  • dataqi chart: covers the API, telemetry ingress, Extractor, and MCP Sandbox pods. Required when Keycloak, your AI model gateway, or another endpoint uses an internal CA.
  • dataqi-aiops chart: covers all enabled MCP server pods (Intersight, vROps, Virtana, ServiceNow). Required when any of those target systems use an internal CA.

Option A — Kubernetes Secret (secrets.customCaBundle)

Section titled “Option A — Kubernetes Secret (secrets.customCaBundle)”

Create a standard Opaque Secret whose ca-bundle.crt key holds a PEM-encoded certificate bundle, then reference it by name in your values file.

  • Type: Opaque.
  • Required keys:
    • ca-bundle.crt: A PEM-encoded certificate bundle. Multiple CA certificates can be concatenated into a single file.

Tip: Create this secret from a PEM file. You can concatenate multiple certificates into one file before creating the secret:

Terminal window
# Single CA
kubectl create secret generic dataqi-custom-ca-bundle \
--from-file=ca-bundle.crt=./corporate-ca.crt
# Multiple CAs concatenated into a bundle
cat root-ca.crt issuing-ca.crt > ca-bundle.crt
kubectl create secret generic dataqi-custom-ca-bundle \
--from-file=ca-bundle.crt=./ca-bundle.crt

Tip: On enterprise Windows machines enrolled in a corporate PKI, you can export the relevant root CAs directly from the Windows certificate store. Run the following in PowerShell on any domain-joined machine that already trusts the corporate PKI, replacing COMPANYNAME with the common name identifier used in your organisation’s CA subject:

Terminal window
$bundlePath = ".\ca-bundle.crt"
Get-ChildItem Cert:\LocalMachine\Root |
Where-Object { $_.Subject -like "*COMPANYNAME*" } |
ForEach-Object {
"-----BEGIN CERTIFICATE-----"
[Convert]::ToBase64String($_.RawData, 'InsertLineBreaks')
"-----END CERTIFICATE-----"
""
} | Set-Content -Path $bundlePath -Encoding ascii

This exports every matching root certificate from the machine trust store into a single PEM bundle. You can then create the Kubernetes secret directly from that file:

Terminal window
kubectl create secret generic dataqi-custom-ca-bundle \
--from-file=ca-bundle.crt=./ca-bundle.crt

Activate the Secret in each chart’s values file:

# In your dataqi values override
secrets:
# Set to "" if using Option B (ConfigMap) instead
customCaBundle: "dataqi-custom-ca-bundle"
# In your dataqi-aiops values override
secrets:
# Set to "" if using Option B (ConfigMap) instead
customCaBundle: "dataqi-custom-ca-bundle"

The same Secret can be referenced by both charts — create it once in the namespace.

Option B — ConfigMap (networking.caBundleConfigMap)

Section titled “Option B — ConfigMap (networking.caBundleConfigMap)”

If your platform already manages CA certificates via a ConfigMap (for example, OpenShift’s cluster CA injection or a custom operator), point the chart at that ConfigMap instead of creating a Secret.

The ConfigMap must contain a ca-bundle.crt key holding a PEM-encoded certificate bundle. On OpenShift, create an empty ConfigMap with the injection label and the cluster operator will populate it automatically:

kind: ConfigMap
apiVersion: v1
metadata:
name: ca-bundle
labels:
config.openshift.io/inject-trusted-cabundle: 'true'
data: {}

For other platforms, create the ConfigMap manually:

Terminal window
kubectl create configmap ca-bundle \
--from-file=ca-bundle.crt=./corporate-ca.crt

Then set the ConfigMap name in each chart’s values file:

# In your dataqi values override
networking:
caBundleConfigMap: "ca-bundle"
# In your dataqi-aiops values override
networking:
caBundleConfigMap: "ca-bundle"

Leave secrets.customCaBundle: "" when using this option. If both are set, the ConfigMap takes precedence.

By default, DataQI preserves existing OS trust. When networking.caBundleMergeImage.enabled is true (the default), an init container merges the supplied PEM file with the OS CA roots before the application starts. The merge image is configured under networking.caBundleMergeImage. In private-registry environments, override networking.caBundleMergeImage.repository and networking.caBundleMergeImage.tag to point to a mirrored, shell-capable image that is already approved for your cluster.

Note: Leaving networking.caBundleMergeImage.registry empty ("") causes the chart to fall back to global.imageRegistry. If the merge image lives in a different registry (for example the default mcr.microsoft.com while your app images use an internal mirror), set registry explicitly.

Only set networking.caBundleMergeImage.enabled: false when your bundle is a complete replacement that already contains both public roots and your private roots — this disables the merge init container entirely and mounts the source directly.


These secrets are required when deploying the dataqi-aiops chart, which runs various Model Context Protocol (MCP) integrations connecting the assistant to enterprise infrastructure. Since each MCP server is optional, you only need to provide the secrets for the MCP servers you intend to deploy. Note that each MCP server is disabled by default and must be explicitly enabled in the values file.

Important: Base URL Configuration

All MCP servers (Intersight, vROps, Virtana, ServiceNow) manage their own internal API path routing automatically. When configuring the baseUrl or instanceUrl for any of these services (whether in values.yaml or a secret), you MUST provide the domain root only, with no trailing slashes or path segments.

  • Correct: https://vrops.example.com
  • Incorrect: https://vrops.example.com/suite-api
  • Incorrect: https://intersight.com/api/v1/

The dataqi-aiops chart uses the same dataqi-image-registry secret as the core chart. No separate registry secret is required. Ensure dataqi-image-registry is provisioned in the same namespace before deploying either chart.

The dataqi-aiops chart supports the same CA bundle options as the core chart — either a Kubernetes Secret via secrets.customCaBundle or a ConfigMap via networking.caBundleConfigMap. See Custom CA bundle above for full setup instructions.

  • Type: Opaque.
  • Purpose: Automates interactions with Cisco Intersight through the Intersight MCP tool.
  • Required keys:
    • apiKeyId: <api-key-id>.
    • secretKey: <secret-key> (multiline PEM).
  • Type: Opaque.
  • Purpose: Provides VMware Aria Operations / vROps service-account credentials so the MCP server can acquire short-lived runtime tokens.
  • Required keys:
    • username: Service-account username.
    • password: Service-account password.
  • Optional keys:
    • authSource: Authentication source name for non-default providers (LDAP, AD, vIDM, etc.).
  • Example:
Terminal window
kubectl create secret generic mcp-vrops-credentials \
--from-literal=username="<service-account-username>" \
--from-literal=password="<service-account-password>" \
--from-literal=authSource="<optional-auth-source>"

Do not store short-lived acquired vROps tokens in this Secret; the MCP server acquires, caches, and refreshes tokens at runtime.

  • Type: Opaque.
  • Purpose: Authorises the Virtana MCP tool to query infrastructure performance metrics and capacity planning data.
  • Required keys:
    • bearerToken: <bearer-token>.
  • Type: Opaque.
  • Purpose: Authenticates the ServiceNow MCP tool for querying incidents, requests, and CI data.
  • Required keys:
    • instanceUrl: <instance-url> (e.g. https://dev12345.service-now.com).
    • username: <service-account-username>.
    • password: <service-account-password>.
    • token: <optional-token> (if applicable).