Vault-Wazuh Secrets Integration

Status: Stub - Research complete, implementation pending

Origin: Post-incident action from CR-2026-02-25 Wazuh Credential Rotation

Overview

Evaluate options for managing Wazuh credentials via HashiCorp Vault instead of static Kubernetes secrets.

This is NOT a simple Vault Agent Injector use case.

OpenSearch (Wazuh indexer) stores password hashes in an internal security index (.opendistro_security). Simply injecting credentials to a file does NOT work - you must also update the internal user database via securityadmin.sh.

Current State

Component Secret Source Credential Storage Rotation

wazuh-indexer

indexer-cred (k8s)

Internal security index

Manual (requires securityadmin.sh)

wazuh-dashboard

dashboard-cred (k8s)

opensearch_dashboards.yml

Manual (restart required)

wazuh-manager

wazuh-api-cred (k8s)

Internal config

Manual

Why Vault Agent Injector Won’t Work

Standard Vault Agent Injector pattern:

Vault KV → Agent Sidecar → /vault/secrets/file → Application reads file

Problem with OpenSearch/Wazuh:

Vault KV → Agent Sidecar → /vault/secrets/file → ???
                                                   ↓
                                    OpenSearch ignores file!
                                    Uses internal .opendistro_security index

OpenSearch security plugin stores credentials as bcrypt hashes in a dedicated index. Changing the K8s secret alone does NOT change the password - you must:

  1. Generate bcrypt hash of new password

  2. Update internal_users.yml

  3. Run securityadmin.sh to push to security index

  4. Restart dependent services

Integration Options

Difficulty: Medium

┌──────────┐     ┌─────────────────────┐     ┌──────────────┐
│ Vault KV │────▶│ External Secrets    │────▶│ K8s Secret   │
│          │     │ Operator (ESO)      │     │ indexer-cred │
└──────────┘     └─────────────────────┘     └──────────────┘
                                                    │
                                                    ▼
                                          ┌─────────────────┐
                                          │ CronJob runs    │
                                          │ securityadmin.sh│
                                          └─────────────────┘

Pros: - ESO is well-supported, widely used - Secrets stay in Vault (source of truth) - K8s secrets auto-sync on Vault changes

Cons: - Still need CronJob/Job to run securityadmin.sh after sync - Two moving parts (ESO + password sync job)

Implementation:

# ExternalSecret resource
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: wazuh-indexer-cred
  namespace: wazuh
spec:
  refreshInterval: 1h
  secretStoreRef:
    name: vault-backend
    kind: ClusterSecretStore
  target:
    name: indexer-cred
  data:
    - secretKey: username
      remoteRef:
        key: kv/data/domus/applications/wazuh/indexer
        property: username
    - secretKey: password
      remoteRef:
        key: kv/data/domus/applications/wazuh/indexer
        property: password

Option B: Vault + Password Sync CronJob

Difficulty: Medium-High

Custom CronJob that: 1. Reads password from Vault 2. Generates bcrypt hash 3. Updates internal_users.yml 4. Runs securityadmin.sh 5. Restarts affected pods

Pros: - Full automation - No ESO dependency

Cons: - Custom code to maintain - Must handle securityadmin.sh failures - Complex error handling

Option C: OpenSearch Kubernetes Operator

Difficulty: High (migration required)

The official OpenSearch K8s Operator handles password hashing automatically:

You no longer need to provide password hashes for the admin or kibanaserver users. The operator will automatically generate password hashes from the credentials secrets.

Pros: - Native secret handling - Automatic hash generation - Production-grade operator

Cons: - Requires migrating from Wazuh deployment to OpenSearch operator - May lose Wazuh-specific customizations - Data migration complexity

Option D: Manual Rotation (Current)

Difficulty: Low

Use CR-2026-02-25 process.

Pros: - Simple, well-documented - No additional infrastructure - Full control

Cons: - Manual process - Human error risk - No automatic rotation

Recommendation

Timeframe Approach Rationale

Now

Manual rotation (Option D)

CR process is solid, low risk

Q2 2026

External Secrets Operator (Option A)

Moderate effort, good ROI

Future

Evaluate OpenSearch Operator (Option C)

If Wazuh adds native support

Prerequisites for Option A (ESO)

  • Install External Secrets Operator in k3s

  • Configure ClusterSecretStore for Vault

  • Create password sync Job/CronJob

  • Test in non-prod first