> ## Documentation Index
> Fetch the complete documentation index at: https://docs.abbyy.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Secrets and Key Vault

> How Vantage 3.0 self-hosted reads secrets and certificates: from Azure Key Vault via the Secrets Store CSI driver, or from pre-existing Kubernetes Secret resources.

Vantage 3.0 self-hosted reads every database connection string, API key, and TLS certificate from a secrets provider at pod startup; none of these values are stored in `values.yaml` files. Two providers are supported; exactly one is configured per install via `vantage.secrets`.

## Supported providers

| Provider               | Helm value                   | Description                                                                                                                                                                      |
| ---------------------- | ---------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Azure Key Vault**    | `vantage.secrets.azure`      | Uses the Secrets Store CSI Driver with the Azure Key Vault provider. The operator provisions a `SecretProviderClass` per chart and the driver mounts secrets into pods as files. |
| **Kubernetes Secrets** | `vantage.secrets.kubernetes` | Uses pre-existing Kubernetes `Secret` resources directly. No external secrets infrastructure required.                                                                           |

The two providers share the same **secret alias** contract. Vantage workloads look up secrets by alias regardless of where the values come from. Use the [alias inventory](#secret-aliases) below to plan provisioning.

## Azure Key Vault provider

```yaml theme={null}
vantage:
  secrets:
    azure:
      keyVaultName: mykeyvault
      tenantId: 00000000-0000-0000-0000-000000000000
      clientId: 00000000-0000-0000-0000-000000000000  # client ID of the UAMI with Key Vault read access
      identityMode: workloadIdentity                   # workloadIdentity (default) | podIdentity | vmManagedIdentity
```

### Identity modes

| Mode                         | How the CSI driver authenticates                                                                                                                                                                                                                 |
| ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `workloadIdentity` (default) | Azure Workload Identity. Each chart's ServiceAccount is federated to a user-assigned managed identity (UAMI) whose `clientId` is provided here. That UAMI must have read access to the Key Vault objects backing the aliases used by that chart. |
| `podIdentity`                | Legacy AAD Pod Identity binding. This mode is not a tested scenario; contact your ABBYY account team before relying on it.                                                                                                                       |
| `vmManagedIdentity`          | A VM-assigned managed identity. The UAMI's client ID is supplied via `vantage.secrets.azure.userAssignedIdentityID`. That identity must have read access to the Key Vault.                                                                       |

### How it works

Vantage uses the Secrets Store CSI Driver with the Azure Key Vault provider. Each chart's `SecretProviderClass` is mounted as a CSI volume in the consuming pod, and that mount triggers the driver to sync the values into a per-chart Kubernetes `Secret` (the SPC's `secretObjects` feature), which the pod consumes via `envFrom` and volume mounts. The chain is:

```
┌──────────────────────┐
│  Azure Key Vault     │  Customer-provisioned secret/certificate objects
└──────────┬───────────┘
           │ ① read via configured identity
           ▼
┌──────────────────────────────────────────────────┐
│  SecretProviderClass  (one per chart)            │  Created by the operator
│  alias → Key Vault objectName                    │
│  alias → key in the per-chart Kubernetes Secret  │
└──────────┬───────────────────────────────────────┘
           │ ② Secrets Store CSI driver populates
           ▼
┌──────────────────────────────────────────────────┐
│  Kubernetes Secret  (one per chart)              │  e.g. mail-helm-secrets
└──────────┬───────────────────────────────────────┘
           │ ③ envFrom (env vars) and/or volumeMounts (files)
           ▼
┌──────────────────────────────────────────────────┐
│  Vantage pod                                     │
└──────────────────────────────────────────────────┘
```

1. The operator generates a `SecretProviderClass` (SPC) per chart, declaring which Key Vault aliases that chart needs and how each maps to a key in a per-chart Kubernetes `Secret`.
2. When a pod mounts the SPC's volume, the Secrets Store CSI driver authenticates as the identity selected by `identityMode`, fetches the named objects from Key Vault, and synchronizes them into a per-chart Kubernetes `Secret` via the SPC's `secretObjects` feature.
3. The chart's pod consumes the per-chart `Secret`:
   * **Most secrets** are loaded as environment variables via `envFrom`.
   * **Certificates** (`authSigningTlsCrt`, etc.) are also mounted as files via `volumeMounts` (typically under `/var/run/certs/`).

Secret values appear in the per-chart Kubernetes `Secret` and in the pod's environment at runtime, so they're not invisible to `kubectl get secret`. But they never appear in `values.yaml`, ArgoCD diffs, or Git, because the CSI driver populates them at pod-start time.

The Secrets Store CSI driver and the [Azure Key Vault provider plugin](https://azure.github.io/secrets-store-csi-driver-provider-azure) must be installed in the cluster before Vantage. See [Prerequisites](/vantage/self-hosted/v3.0/prerequisites).

### Per-chart resources

Each Vantage chart that consumes secrets gets its own set of resources:

| Resource              | Name pattern                                                                      | Purpose                                                                                              |
| --------------------- | --------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- |
| `SecretProviderClass` | `{chart}-secret-provider` (and `{chart}-migr-secret-provider` for migration jobs) | Lists the Key Vault aliases the chart needs and how they map into the per-chart Kubernetes `Secret`. |
| `Secret`              | `{chart}-secrets` (and `{chart}-migr-secrets`)                                    | Populated by the CSI driver; mounted into the chart's pod via `envFrom`.                             |
| Volume `Secret`s      | `{chart}-secrets-volume-N`                                                        | Additional per-chart `Secret`s for material that must be mounted as files (e.g. certificates).       |

This per-chart split keeps Key Vault access least-privileged: a chart's SPC references only the aliases that chart actually needs.

### Service accounts and identity scope

The operator does **not** create or annotate `ServiceAccount` resources. Each chart brings its own SA through standard Helm values; the customer is responsible for federating the per-chart ServiceAccounts that mount the SPCs to the user-assigned managed identity (UAMI) whose `clientId` is provided in `vantage.secrets.azure.clientId`. That identity must have read access to the Key Vault objects backing the charts' aliases.

<Note>
  Key Vault access and image pull access are separate concerns that can land on the same ServiceAccounts. UAMI federation (this page) grants secret reads; it does not authenticate image pulls. For pulls, add a registry pull secret to the `imagePullSecrets` of the ServiceAccount named by `vantage.serviceAccountName`, or grant `AcrPull` to the AKS kubelet identity instead. See [Image pull access](/vantage/self-hosted/v3.0/providers/azure#image-pull-access).
</Note>

## Kubernetes Secrets provider

```yaml theme={null}
vantage:
  secrets:
    kubernetes:
      # objects:                           # optional: override default secret names
      #   sendgridApiKey:
      #     secretName: my-sendgrid-secret
```

Pre-create the `Secret` resources in the install namespace before running the chart. If `objects` is not defined, the default secret names are used; supply an `objects` mapping (`secretName` per alias) to point at Secrets with different names.

This provider requires no Secrets Store CSI driver and no cloud key vault. Values are read directly from in-cluster `Secret` objects.

During preflight, the operator validates the secrets configuration. The matched operator and Vantage charts install a Secret-reader ClusterRole and bind it to the operator ServiceAccount only in the Vantage release namespace. If you restrict Secret access by `resourceNames`, include every default and overridden Secret name.

An external secret-management system can remain your source of truth. For example, External Secrets Operator can materialize Kubernetes Secrets from HashiCorp Vault. Vantage consumes only the resulting Kubernetes Secrets and does not connect to External Secrets or Vault directly.

### PostgreSQL and per-service Secrets

Set `vantage.databaseProvider: PostgreSQL` to use PostgreSQL. Every service must receive a connection string that names a distinct logical database; sharing one database causes the services' migration state to collide.

Some workloads read uniquely named connection-string keys and can share a Secret. Other workloads read the generic key `Database__ConnectionString`; create a separate Secret for each of those services and map its alias through `vantage.secrets.kubernetes.objects`:

```yaml theme={null}
vantage:
  databaseProvider: PostgreSQL
  reportingEnabled: false
  secrets:
    kubernetes:
      objects:
        subscriptionDatabaseConnectionString:
          secretName: vantage-db-subscriptions
        workspaceDatabaseConnectionString:
          secretName: vantage-db-workspace
```

Each mapped Secret contains the same key but a different database connection string:

```yaml theme={null}
apiVersion: v1
kind: Secret
metadata:
  name: vantage-db-subscriptions
  namespace: <install-namespace>
type: Opaque
stringData:
  Database__ConnectionString: "Host=<host>;Port=5432;Database=subscriptions;Username=<user>;Password=<password>;Ssl Mode=Require"
```

Use your secret-management system to create these Secrets without committing credentials to source control. Connection strings must be a single line without leading, trailing, or embedded newline characters.

Reporting is SQL Server-only. Leave `reportingEnabled: false` when using PostgreSQL.

## Secret aliases

The following aliases are the contract between Vantage workloads and your secrets provider. With the Azure provider, the simplest setup is to name your Key Vault secrets to match the alias. With either provider, you can remap names through an `objects` mapping in your secrets configuration.

### Platform

| Alias                          | Description                                                                                                         |
| ------------------------------ | ------------------------------------------------------------------------------------------------------------------- |
| `sendgridApiKey`†              | API key for SendGrid. Required unless you configure `spec.smtp`.                                                    |
| `redisConnectionString`        | Connection string for Redis.                                                                                        |
| `redisCacheConnectionString`   | Connection string for Redis cache / locks / client cache. May reuse `redisConnectionString`.                        |
| `secretStorageUserKeyVaultUri` | URI to the Azure Key Vault used for secret storage. May be the same vault or a separate one (separate recommended). |

### Storage

Required only when using the default Azure Blob storage backend. When `spec.storage.custom` is configured for a Kubernetes-`StorageClass`-backed backend (for example, NFS), these aliases are not used. Each alias is a storage account connection string; defer to the base Vantage system docs for what each storage type is used for.

| Alias                                    | Description                                            |
| ---------------------------------------- | ------------------------------------------------------ |
| `storageArchiveConnectionString`         | Storage account connection string ("archive").         |
| `storageLegacyTemporaryConnectionString` | Storage account connection string ("temporary (old)"). |
| `storageTemporaryConnectionString`       | Storage account connection string ("temporary").       |
| `storagePermanentConnectionString`       | Storage account connection string ("permanent").       |
| `storageStandardConnectionString`        | Storage account connection string ("standard").        |

### Databases

Connection strings, one per distinct database. The database names are illustrative; any name your provisioning process produces is fine, as long as the connection string points to the right database.

| Alias                                        | Database                                         |
| -------------------------------------------- | ------------------------------------------------ |
| `apiRegistryDatabaseConnectionString`        | `apiregistry`                                    |
| `auth2DatabaseConnectionString`              | `auth`                                           |
| `authIdentityDatabaseConnectionString`       | `auth-identity`                                  |
| `cronServiceDatabaseConnectionString`        | `cron`                                           |
| `documentSetStorageDatabaseConnectionString` | `documentset`                                    |
| `mailDatabaseConnectionString`               | `mail`                                           |
| `securityAuditDatabaseConnectionString`      | `security-audit`                                 |
| `storageDatabaseConnectionString`            | `storage`                                        |
| `workflowDatabaseConnectionString`           | `workflows`                                      |
| `catalogStorageDatabaseConnectionString`     | `catalogstorage`                                 |
| `folderImportDatabaseConnectionString`       | `folderimport`                                   |
| `interactiveJobsDatabaseConnectionString`    | `interactive-jobs`                               |
| `mailImportDatabaseConnectionString`         | `mailimport`                                     |
| `permissionsDatabaseConnectionString`        | `permissions`                                    |
| `reportingDatabaseConnectionString`          | `reporting` (must support Columnstore Indexing). |
| `secretStorageDatabaseConnectionString`      | `secretstorage`                                  |
| `skillInfoDatabaseConnectionString`          | `skillinfo`                                      |
| `skillMonitorDatabaseConnectionString`       | `skillmonitor`                                   |
| `subscriptionDatabaseConnectionString`       | `subscriptions`                                  |
| `tokenManagementDatabaseConnectionString`    | `tokenmanagement`                                |
| `transactionsDatabaseConnectionString`       | `transactions`                                   |
| `urlShortenerDatabaseConnectionString`       | `urlshortener`                                   |
| `workspaceDatabaseConnectionString`          | `workspace`                                      |

### OAuth

| Alias                        | Description                    |
| ---------------------------- | ------------------------------ |
| `oAuthGoogleClientId`        | OAuth Google client ID.        |
| `oAuthGoogleClientSecret`    | OAuth Google client secret.    |
| `oAuthMicrosoftClientId`     | OAuth Microsoft client ID.     |
| `oAuthMicrosoftClientSecret` | OAuth Microsoft client secret. |

† `sendgridApiKey` is required only when not using SMTP. See [Known Limitations](/vantage/self-hosted/v3.0/known-limitations#smtp-supports-basic-auth-only).

## Certificate aliases

Four PEM-encoded TLS materials are required, surfaced as two pairs of secret aliases (certificate + private key). With the Azure provider, store them as Key Vault **secrets**, not Key Vault certificate objects:

| Alias                   | Description                                                                                              |
| ----------------------- | -------------------------------------------------------------------------------------------------------- |
| `authSigningTlsCrt`     | PEM-encoded certificate for auth signing (from the `auth-signing` Key Vault certificate).                |
| `authSigningTlsKey`     | PEM-encoded private key for auth signing.                                                                |
| `authDeactivatedTlsCrt` | PEM-encoded certificate for auth deactivated tokens (from the `auth-deactivated` Key Vault certificate). |
| `authDeactivatedTlsKey` | PEM-encoded private key for auth deactivated tokens.                                                     |

With the Azure provider, the simplest approach is to create two self-signed certificates in Key Vault named `auth-signing` and `auth-deactivated` (Common Name = your Vantage `dnsRecord` value), then create four Key Vault secrets named to match the aliases above. With the Kubernetes provider, pre-create the `Secret` resources containing the PEM material. The default data keys are `auth-signing-tls-crt`, `auth-signing-tls-key`, `auth-deactivated-tls-crt`, and `auth-deactivated-tls-key`. Use an `objects` mapping to remap Secret names.

## Naming and remapping

**With the Azure provider, aliases not listed in the `objects` mapping fall back to using the alias itself as the Key Vault object name** (fetched as type `secret`). If your Key Vault objects are already named to match the aliases, no `objects` mapping is required. With the Kubernetes provider, the default secret names are used when `objects` is not defined.

If your provisioning process uses different names, provide an `objects` mapping in your secrets configuration:

```yaml theme={null}
vantage:
  secrets:
    azure:
      # ...
      objects:
        sendgridApiKey:
          objectName: my-sendgrid-key            # Azure Key Vault object name
        reportingDatabaseConnectionString:
          objectName: vantage-reporting-conn
```

```yaml theme={null}
vantage:
  secrets:
    kubernetes:
      objects:
        sendgridApiKey:
          secretName: my-sendgrid-secret         # Kubernetes Secret name
        reportingDatabaseConnectionString:
          secretName: my-reporting-secret
```

The alias is the API contract; the object name is yours to choose.

## Required permissions

With the **Azure Key Vault provider**, the identity used by the Secrets Store CSI driver must have **read** access to every secret and certificate listed above:

* `workloadIdentity` (default): the user-assigned managed identity whose `clientId` is provided in `vantage.secrets.azure.clientId`.
* `vmManagedIdentity`: the identity whose client ID is provided in `vantage.secrets.azure.userAssignedIdentityID`.
* `podIdentity`: not a tested scenario; contact your ABBYY account team before relying on it.

With the **Kubernetes Secrets provider**, no Key Vault or cloud identity permissions are involved. Pre-create the `Secret` resources in the install namespace; Vantage consumes them directly.

<Note>
  Workload identity for the **CSI driver** (here) is distinct from workload identity used by other workloads in your cluster (for example, an in-mesh Prometheus you deploy for monitoring; the Vantage installer does not deploy Prometheus). They can use the same UAMI or different UAMIs.
</Note>

## What's next

<CardGroup cols={2}>
  <Card title="Prerequisites" icon="list-check" href="/vantage/self-hosted/v3.0/prerequisites">
    Cluster-level and external-service requirements for any install.
  </Card>

  <Card title="Install on Azure" icon="cloud" href="/vantage/self-hosted/v3.0/providers/azure">
    Azure Key Vault inventory and the step-by-step install.
  </Card>

  <Card title="Self-Managed Kubernetes" icon="server" href="/vantage/self-hosted/v3.0/providers/self-managed">
    Native Kubernetes Secrets and PostgreSQL configuration.
  </Card>
</CardGroup>
