Platform secrets
Third-party services read their credentials from Kubernetes Secrets created by External Secrets (deploy/external-secrets/secrets, Argo CD component platform-secrets). No value is committed.
Bootstrap order
- cert-manager creates the internal root CA (
cert-manager/eai-root-ca,deploy/cert-manager/cluster-issuers.yaml); the OpenBao TLS certificate is issued by that CA. - OpenBao is initialised and unsealed (
bao operator init,bao operator unseal), thendeploy/openbao/bootstrap.shenables KV v2 (kv), transit, kubernetes auth and the policies. - The operator writes every entry of the table below:
bao kv put kv/eai/platform/<namespace>/<secret> <property>=<value> .... - Argo CD applies
platform-secrets: the ClusterSecretStoreopenbao(deploy/openbao/k8s/clustersecretstore.yaml) syncs the ExternalSecrets (refresh 1h,creationPolicy: Owner,deletionPolicy: Retain). - The Secret
kyverno/cosign-public-key(keycosign.pub) comes from the Terraform moduleplatform-bootstrap(variablecosign_public_key), because admission needs it before anything else.
OpenBao entries
| OpenBao path (kv) | Properties | Consumer | How to generate |
|---|---|---|---|
eai/platform/apisix/redis-acl-apisix | apisix-password | apisix/redis-acl-apisix: APISIX (limit-count Redis) | openssl rand -base64 32; its sha256 goes into user.acl (user apisix) |
eai/platform/eai-data/nats-users | control-plane, multimodal, worker | eai-data/nats-users: NATS (bcrypt hashes) | bcrypt of openssl rand -base64 32: nats server passwd -p <password> |
eai/platform/eai-data/redis-acl | user.acl | eai-data/redis-acl: Redis (whole ACL file, deploy/data/redis/values.yaml) | the ACL file with #<sha256> per user: printf %s <password> | sha256sum |
eai/platform/eai-data/redis-password | password | eai-data/redis-password: Redis default user (operator and replication only) | openssl rand -base64 32 |
eai/platform/eai-data/redis-opik-acl | user.acl | eai-data/redis-opik-acl: Redis dedicated to Opik (ACL file, deploy/data/redis-opik/values.yaml) | the ACL file with #<sha256> per user: printf %s <password> | sha256sum |
eai/platform/eai-data/redis-opik-password | password | eai-data/redis-opik-password: Redis dedicated to Opik, default user (operator and replication only) | openssl rand -base64 32 |
eai/platform/eai-data/cnpg-s3 | ACCESS_KEY_ID, SECRET_ACCESS_KEY | eai-data/cnpg-s3: CloudNativePG backups (bucket eai-backups, prefix cnpg) | keys of an S3 user limited to the eai-backups bucket |
eai/platform/velero/velero-s3 | cloud | velero/velero-s3: Velero (AWS credentials file format) | [default] section with aws_access_key_id and aws_secret_access_key of an S3 user limited to the Velero bucket |
eai/platform/eai-data/qdrant-api-key | api-key, read-only-api-key | eai-data/qdrant-api-key: Qdrant (control plane, workers) | openssl rand -base64 32 each |
eai/platform/eai-data/temporal-db-credentials | username, password | eai-data/temporal-db-credentials: Temporal (Postgres role temporal) | username temporal; openssl rand -base64 32, same as the CloudNativePG role |
eai/platform/eai-data/livekit-keys | api-key, api-secret | eai-data/livekit-keys: LiveKit, same pair as EAI_LIVEKIT_API_KEY / EAI_LIVEKIT_API_SECRET of the control plane | api-key: openssl rand -hex 8; api-secret: openssl rand -base64 48 (at least 32 bytes) |
eai/platform/eai-data/livekit-redis | password | eai-data/livekit-redis: LiveKit (Redis ACL user livekit) | openssl rand -base64 32; its sha256 goes into user.acl |
eai/platform/eai-security/keycloak-bootstrap-admin | username, password | eai-security/keycloak-bootstrap-admin: Keycloak (temporary admin) | openssl rand -base64 32 |
eai/platform/eai-security/keycloak-db | username, password | eai-security/keycloak-db: Keycloak (Postgres role keycloak) | openssl rand -base64 32 |
eai/platform/eai-security/openfga-db | uri | eai-security/openfga-db: OpenFGA | postgres://openfga:<password>@eai-postgres-rw.eai-data.svc:5432/openfga?sslmode=verify-full&sslrootcert=/etc/openfga/db-ca/ca.crt |
eai/platform/eai-security/openfga-preshared | keys | eai-security/openfga-preshared: OpenFGA (also EAI_OPENFGA_API_TOKEN) | openssl rand -base64 32, comma separated |
eai/platform/observability/clickhouse-operator-access | username, password | observability/clickhouse-operator-access: ClickHouse operator (metrics, schema) | username clickhouse_operator; openssl rand -base64 32 |
eai/platform/observability/clickhouse-users | eai-reader, eai-writer, opik | observability/clickhouse-users: ClickHouse (sha256 hex digests) | printf %s <password> | sha256sum (the plain password of opik goes to clickhouse-credentials and opik-backend-credentials) |
eai/platform/observability/otel-opensearch | password | observability/otel-opensearch: OpenTelemetry Collector (OpenSearch user otel-writer, logs) | openssl rand -base64 32 |
eai/platform/observability/opensearch-internal-users | internal_users.yml | observability/opensearch-internal-users: OpenSearch (security plugin users, bcrypt hashes) | plugins/opensearch-security/tools/hash.sh -p <password> for each user |
eai/platform/observability/opensearch-bootstrap | password | observability/opensearch-bootstrap: opensearch-bootstrap Job (index templates, ISM, Security Analytics) | openssl rand -base64 32 |
eai/platform/observability/jaeger-opensearch | password, ca.crt | observability/jaeger-opensearch: Jaeger (OpenSearch user jaeger, span storage) | openssl rand -base64 32; ca.crt of eai-root-ca |
eai/platform/observability/opik-backend-credentials | STATE_DB_PASS, ANALYTICS_DB_PASS, ANALYTICS_DB_MIGRATIONS_PASS, REDIS_URL, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY | observability/opik-backend-credentials: Opik (client provided MySQL, ClickHouse opik, redis-opik, S3 bucket opik) | MySQL password of the client; plain password of opik; rediss://opik:<password>@redis-opik-master.eai-data.svc.cluster.local:6379/0; S3 user of the object store |
eai/platform/observability/clickhouse-credentials | password | observability/clickhouse-credentials: Opik (adminUser of ClickHouseInstallation opik-clickhouse) | plain password of opik |
eai/platform/observability/otel-clickhouse | password | observability/otel-clickhouse: OpenTelemetry Collector (ClickHouse otel) | openssl rand -base64 32 |
eai/platform/observability/alertmanager-webhooks | default-url, oncall-url, finops-url, security-url | observability/alertmanager-webhooks: Alertmanager receivers | webhook URLs of the on-call tools |
eai/platform/spire-server/spire-server-db | password | spire-server/spire-server-db: SPIRE server (Postgres role spire) | openssl rand -base64 32 |
CA copies
Public certificates (key ca.crt only, never tls.key) are copied by the External Secrets kubernetes provider (deploy/external-secrets/secrets/ca-stores.yaml): eai-root-ca to apisix, observability and eai-data (eai-internal-ca) and to spire-server (openbao-ca); the CloudNativePG CA eai-data/eai-postgres-ca to eai-security and spire-server. Each store has its own ServiceAccount and a Role limited to get on the source Secret.