Secrets Management Service (SMS)¶
The Secrets Management Service (SMS) acts as a broker between the DataRobot platform and a client-managed secret storage backend, ensuring the following:
- Stores only secret metadata (identifiers and schema references) in DataRobot's database.
- Routes all secret values, such as credentials, API keys, and secure configurations, to and from the client's own secret storage.
- Ensures sensitive data is never stored in the DataRobot platform.
The Secrets Management Service is available starting with DataRobot 11.9. SMS supports the following secret storage backends:
- HashiCorp Vault (OSS or Enterprise)
- Azure Key Vault (DataRobot v11.11 and later)
You configure exactly one backend per deployment.
Requirements¶
Before enabling the Secrets Management Service, you must fulfill the following requirements:
- A supported secret storage backend is deployed and reachable over HTTPS from the DataRobot cluster.
- Credentials or an authentication method for the backend are provisioned for DataRobot.
For backend-specific requirements, see the sections below
HashiCorp Vault¶
If you are using HashiCorp Vault as your backend service, you must meet the following requirements:
- A HashiCorp Vault (OSS or Enterprise) instance is deployed and accessible over HTTPS from the DataRobot cluster.
- The KV v2 secrets engine is enabled.
-
An authentication method is configured for DataRobot:
- For AppRole authentication, the auth method is enabled in Vault, and a Role ID and Secret ID are provisioned.
- For Kubernetes or JWT authentication, the auth method must be enabled in Vault before use.
-
A base path is allocated in Vault for DataRobot secrets.
- (Optional) If Vault uses a private CA, the CA certificate is available in PEM format.
- (Optional) If using Vault Enterprise, the target namespace is identified. If not set, this defaults to the Vault root namespace.
Vault policy¶
HashiCorp Vault operates on a deny-by-default model, so you must attach a policy that grants the following permissions to the Vault role configured for SMS (or the token, if using token authentication):
| Path | Required capabilities |
|---|---|
<kv-base-path>/* |
create, read, update, delete, list |
auth/token/lookup-self |
read |
auth/token/renew-self |
update |
If you plan to enable scoped token support, also grant:
| Path | Required capabilities |
|---|---|
auth/token/create |
create, update |
The following HCL policy satisfies these requirements. Replace <kv-base-path> with the mount path allocated for DataRobot secrets:
path "<kv-base-path>/*" {
capabilities = ["create", "read", "update", "delete", "list"]
}
path "auth/token/lookup-self" {
capabilities = ["read"]
}
path "auth/token/renew-self" {
capabilities = ["update"]
}
Attach this policy to your auth method role (AppRole, Kubernetes, or JWT) or directly to the token before proceeding with enablement.
Azure Key Vault¶
If you are using Azure Key Vault as your backend service, you must meet the following requirements:
- An Azure Key Vault instance is deployed and reachable over HTTPS from the DataRobot cluster. Note its vault URI (for example,
https://<vault-name>.vault.azure.net/). - An Azure (Microsoft Entra ID) application registration or managed identity is provisioned for DataRobot, and you have its tenant ID and client (application) ID.
- The application is granted permission to manage secrets in the Key Vault (see Key Vault permissions).
-
An authentication method is selected and its credentials are provisioned:
- For client secret authentication, a client secret (password) is generated for the application registration.
- For client certificate authentication, a certificate is registered on the application, and the PEM bundle (certificate and private key) is available.
- For workload identity authentication, the cluster has an OIDC issuer enabled and the Azure Workload Identity webhook installed. A federated identity credential must also link from the Kubernetes service account in DataRobot to the application registration.
-
A secret name prefix is chosen for DataRobot's secrets. A prefix is required for Azure Key Vault: it must start with a letter and contain only letters, digits, and hyphens, with a maximum of 80 characters.
Key Vault permissions¶
SMS creates, reads, and deletes secrets in the Key Vault. Using Azure RBAC, assign the built-in Key Vault Secrets Officer role to the application registration (or managed identity) in DataRobot, scoped to the target Key Vault. This role grants all of the secret operations SMS requires:
| Operation | Purpose |
|---|---|
| Get | Read secret values requested by DataRobot. |
| Set | Create and update secrets. |
| Delete | Soft-delete secrets that DataRobot removes. |
| Purge | Permanently remove soft-deleted secrets during best-effort background cleanup. |
If your Key Vault uses access policies instead of Azure RBAC, grant the equivalent secret permissions (Get, Set, Delete, and Purge).
Note
Azure Key Vault soft-deletes a secret before purging it. After deleting a secret, SMS attempts a best-effort purge in the background. If purge protection is enabled on the vault, or the purge does not succeed, the secret remains recoverable until the vault's retention window (7–90 days) expires, after which Azure purges it automatically.
Enablement¶
SMS is disabled by default. To enable it, set global.secret-mgmt-service.enabled: true, then configure one of the supported storage backends, as described in the following sections:
global:
secret-mgmt-service:
enabled: true
Only one backend can be configured at a time. SMS selects the backend based on which configuration block you populate under storage and fails to start if more than one—or none—are configured.
When SMS is enabled, the chart automatically sets ENABLE_SECRET_MGMT_SERVICE_INTEGRATION: true on the core service, which causes DataRobot to route all credentials, API keys, and other sensitive configuration through SMS for storage in the configured backend. If you need to keep the SMS service running without activating this routing—for example, to retain access to secrets already stored in a backend—you can explicitly disable the integration:
core:
config_env_vars:
ENABLE_SECRET_MGMT_SERVICE_INTEGRATION: false
HashiCorp Vault¶
Configure the Vault connection under storage.vault:
secret-mgmt-service:
storage:
vault:
addr: "https://<vault-address>:<vault-port>"
auth_method: <auth-method> # approle | k8s | jwt | token
mount_path: "<kv-base-path>/"
# namespace: "<vault-enterprise-namespace>" # optional: Vault Enterprise only
| Field | Description |
|---|---|
addr |
The HTTPS address of your Vault instance. |
auth_method |
The authentication method: approle, k8s, jwt, or token. |
mount_path |
KV v2 base path allocated for DataRobot secrets. |
namespace |
(Optional) The Vault Enterprise namespace. If not set, this defaults to the root namespace. |
If Vault uses a private CA, provide the CA certificate via a Kubernetes Secret; see Custom CA certificate.
Then add the auth-method-specific configuration described in the following sections.
AppRole authentication¶
Add the approle block under storage.vault:
secret-mgmt-service:
storage:
vault:
approle:
role_id: "<role-id>"
mount_path: "approle/"
token_wrapping: "false"
The AppRole Secret ID is sensitive credential material. The recommended approach is to provide it via a Kubernetes Secret, referencing it under app.secrets as the VAULT_APPROLE_SECRET_ID environment variable:
secret-mgmt-service:
app:
secrets:
- name: VAULT_APPROLE_SECRET_ID
valueFrom:
secretKeyRef:
name: <approle-credentials-secret>
key: secret-id
Alternatively, you can set it directly in your values file:
secret-mgmt-service:
storage:
vault:
approle:
secret_id: "<secret-id>"
Kubernetes authentication¶
SMS presents its Kubernetes service account token; Vault verifies it by calling the Kubernetes API server directly. This authentication method is recommended for Kubernetes-native Vault deployments.
Add the k8s block under storage.vault:
secret-mgmt-service:
storage:
vault:
k8s:
mount_path: "kubernetes/"
role: "<vault-role-name>"
JWT authentication¶
SMS presents its Kubernetes service account token; Vault verifies it independently using public keys from the Kubernetes OIDC discovery endpoint without a live call to the Kubernetes API server per request.
Add the jwt block under storage.vault:
secret-mgmt-service:
storage:
vault:
jwt:
mount_path: "jwt/"
role: "<vault-role-name>"
Token authentication¶
Provide a static Vault token via a Kubernetes Secret, referencing it under app.secrets as the VAULT_TOKEN environment variable:
secret-mgmt-service:
app:
secrets:
- name: VAULT_TOKEN
valueFrom:
secretKeyRef:
name: <vault-credentials-secret>
key: token
Alternatively, you can set it directly in your values file:
secret-mgmt-service:
storage:
vault:
token: "<vault-token>"
Custom CA certificate¶
If your Vault instance uses TLS signed by a private CA, provide the PEM-encoded CA certificate via a Kubernetes Secret, referencing it under app.secrets as the VAULT_CA_CERT environment variable:
secret-mgmt-service:
app:
secrets:
- name: VAULT_CA_CERT
valueFrom:
secretKeyRef:
name: <vault-ca-cert-secret>
key: ca-cert
Alternatively, you can set it directly in your values file as a single-line PEM string with \n-escaped newlines:
secret-mgmt-service:
storage:
vault:
ca_cert: "-----BEGIN CERTIFICATE-----\n<base64-encoded-certificate>\n-----END CERTIFICATE-----"
Scoped token support¶
By default, SMS authenticates to Vault once and reuses the resulting token for all secret operations. Enabling scoped token support changes this behavior: SMS creates a short-lived child token with a limited TTL and only the policies required for each individual operation, discarding it immediately after use. This limits the blast radius if a token is ever compromised, but increases load on the Vault token API because a new token is created and revoked for every secret operation.
Enable this option only if your security requirements justify the additional Vault overhead.
To enable scoped tokens, ensure the Vault policy includes auth/token/create permissions, then add the following to your values override:
secret-mgmt-service:
storage:
vault:
scoped_token_enabled: true
scoped_token_policies:
- "<policy-name>" # policy to attach to each scoped token
Azure Key Vault¶
Configure the Key Vault connection under storage.azure, along with the required secret name prefix:
secret-mgmt-service:
storage:
secret_name_prefix: "<prefix>" # required for Azure Key Vault
azure:
addr: "https://<vault-name>.vault.azure.net/"
tenantId: "<azure-tenant-id>"
authMethod: <auth-method> # client_secret | client_certificate | workload_identity
clientId: "<azure-application-client-id>"
| Field | Description |
|---|---|
secret_name_prefix |
Prefix for every secret name stored in the Key Vault. Required for Azure Key Vault. Must start with a letter, contain only letters, digits, and hyphens, and be at most 80 characters. This field is a sibling of azure under storage, not nested inside it. |
addr |
The Key Vault URI, for example https://<vault-name>.vault.azure.net/. Must be an HTTPS URL. |
tenantId |
The Azure (Microsoft Entra ID) tenant ID. |
authMethod |
The authentication method: client_secret, client_certificate, or workload_identity. |
clientId |
The application (client) ID of the application registration or managed identity. Required for all authentication methods. |
Then add the auth-method-specific configuration described in the following sections.
Client secret authentication¶
Add the servicePrincipal block under storage.azure:
secret-mgmt-service:
storage:
azure:
authMethod: client_secret
servicePrincipal:
clientSecret: "<client-secret>"
The client secret is sensitive credential material. The recommended approach is to provide it via a Kubernetes Secret, referencing it under app.secrets as the AKV_SP_CLIENT_SECRET environment variable:
secret-mgmt-service:
app:
secrets:
- name: AKV_SP_CLIENT_SECRET
valueFrom:
secretKeyRef:
name: <akv-credentials-secret>
key: client-secret
When you supply the client secret via app.secrets, omit servicePrincipal.clientSecret from your values file.
Client certificate authentication¶
Provide a certificate registered on the application registration. The PEM bundle—the certificate and its private key—is sensitive credential material. The recommended approach is to provide it via a Kubernetes Secret, referencing it under app.secrets as the AKV_CLIENT_CERTIFICATE_PEM environment variable:
secret-mgmt-service:
storage:
azure:
authMethod: client_certificate
app:
secrets:
- name: AKV_CLIENT_CERTIFICATE_PEM
valueFrom:
secretKeyRef:
name: <cert-secret-name>
key: <cert-secret-key>
For example, create the secret from a local bundle file:
kubectl create secret generic <cert-secret-name> \
--from-file=bundle.pem=<path-to-bundle.pem> \
--namespace datarobot
In this example, set name to <cert-secret-name> and key to bundle.pem.
Workload identity authentication¶
Workload identity is recommended for production Kubernetes deployments. SMS authenticates using an Azure federated identity credential bound to its Kubernetes service account, so no client secret or certificate is stored in the cluster.
This method requires that the cluster has an OIDC issuer enabled, the Azure Workload Identity mutating admission webhook installed, and a federated identity credential that links SMS's Kubernetes service account to the application registration. The webhook is what injects the projected service account token and AZURE_* environment variables into the SMS pod; without it, the annotations the chart applies (below) have no effect.
Workload identity requires no values beyond the common ones described above (set authMethod to workload_identity and provide clientId).
When authMethod is workload_identity and the chart creates the service account (serviceAccount.create: true, the default), it automatically annotates the service account with azure.workload.identity/client-id and labels the pod with azure.workload.identity/use: "true". If you use an existing service account (serviceAccount.create: false), you must add the azure.workload.identity/client-id: <clientId> annotation to that service account yourself.
Apply the configuration¶
After updating your values override file, perform a Helm upgrade:
helm upgrade datarobot datarobot/datarobot-prime \
-f your-values-override.yaml \
--namespace datarobot
Verification¶
After the upgrade completes, verify that the SMS pod is running:
kubectl get pods -n datarobot -l role=secret-mgmt-service-app
Confirm the pod has passed its readiness probe:
kubectl get pod -n datarobot -l role=secret-mgmt-service-app -o jsonpath='{.items[0].status.conditions[?(@.type=="Ready")].status}'
The output should be True. If the pod is not ready, check the logs for backend connectivity or authentication errors:
kubectl logs -n datarobot -l role=secret-mgmt-service-app
Post-enablement¶
Once the service is running, DataRobot routes all secret operations through SMS:
- New secrets created in DataRobot are automatically stored in the configured backend.
-
DataRobot performs a "lazy migration" of pre-existing secrets to the backend lazily on first access. No manual migration is required and consuming services observe no change in behavior. The migration follows these steps:
- DataRobot reads the secret from its previous internal store.
- The secret is written to the backend via SMS.
- The internal reference is updated to point to the backend.
- The secret is removed from legacy storage.