Skip to content

OVHcloud

Secrets Manager

External Secrets Operator integrates with OVHcloud KMS.

This guide demonstrates: - how to set up a ClusterSecretStore/SecretStore with the OVH provider. - ExternalSecret use cases with examples. - PushSecret use cases with examples.

This guide assumes: - External Secrets Operator is already installed - You have access to OVHcloud Secret Manager - Required credentials are already created

SecretStore

OVH provider supports both token and mTLS authentication.

Token authentication:

apiVersion: external-secrets.io/v1 
kind: SecretStore
metadata:
  name: secret-store-ovh
  namespace: default
spec:
  provider:
    ovh:
      server: <kms-endpoint>
      okmsid: <okms-id>
      auth:
        token:
          tokenSecretRef:
            name: ovh-token
            key: token
---
apiVersion: v1
kind: Secret
metadata:
  name: ovh-token
data:
  token: BASE64-TOKEN-VALUE-PLACEHOLDER
mTLS authentication:
apiVersion: external-secrets.io/v1
kind: SecretStore
metadata:
  name: secret-store-ovh
  namespace: default
spec:
  provider:
    ovh:
      server: "https://eu-west-rbx.okms.ovh.net"
      okmsid: "734b9b45-8b1a-469c-b140-b10bd6540017"
      auth:
        mtls:
          certSecretRef:
            name: ovh-mtls
            key: tls.crt
          keySecretRef:
            name: ovh-mtls
            key: tls.key
---
apiVersion: v1
kind: Secret
metadata:
  name: ovh-mtls
  namespace: default
type: kubernetes.io/tls
data:
  tls.crt: BASE64_CERT_PLACEHOLDER # "client certificate value"
  tls.key: BASE64_KEY_PLACEHOLDER  # "client key value"

Note

A ClusterSecretStore configuration is the same except you must provide the namespace for tokenSecretRef, certSecretRef and keySecretRef according to your chosen authentication method.

ExternalSecret

For these examples, we will assume you have the following secret in your Secret Manager:

{
  "path": "creds",
  "data": {
    "type": "credential",
    "users": {
      "kevin": {
        "token": "kevin token value"
      },
      "laura": {
        "token": "laura token value"
      }
    }
  }
}
path refers to the secret's path in OVH Secret Manager.

apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
  name: external-secret-ovh
  namespace: default
spec:
  secretStoreRef:
    name: secret-store-ovh
    kind: SecretStore
  target:
    name: secret-example
  data:
    - secretKey: foo
      remoteRef:
        key: creds
        version: version
        property: property
Field Description Required
version Secret version to retrieve No
property Specific key or nested key in the secret No
secretKey The key inside the Kubernetes Secret that will hold the secret's value Yes

Fetch the whole secret

  • Using spec.data
    apiVersion: external-secrets.io/v1
    kind: ExternalSecret
    metadata:
      name: external-secret-ovh
      namespace: default
    spec:
      secretStoreRef:
        name: secret-store-ovh
        kind: SecretStore
      target:
        name: secret-example
      data:
        - secretKey: foo
          remoteRef:
            key: creds
    
    Resulting Kubernetes Secret data:
    {
      "foo": {
        "type": "credential",
        "users": {
          "kevin": {
            "token": "kevin token value"
          },
          "laura": {
            "token": "laura token value"
          }
        }
      }
    }
    
  • Using spec.dataFrom.extract
    apiVersion: external-secrets.io/v1
    kind: ExternalSecret
    metadata:
      name: external-secret-ovh
      namespace: default
    spec:
      secretStoreRef:
        name: secret-store-ovh
        kind: SecretStore
      target:
        name: secret-example
      dataFrom:
      - extract:
          key: creds
    
    Resulting Kubernetes Secret data:
    {
      "type": "credential",
      "users": {
        "kevin": {
          "token": "kevin token value"
        },
        "laura": {
          "token": "laura token value"
        }
      }
    }
    

Fetch scalar/nested values

  • Scalar value using data
    apiVersion: external-secrets.io/v1
    kind: ExternalSecret
    metadata:
      name: external-secret-ovh
      namespace: default
    spec:
      secretStoreRef:
        name: secret-store-ovh
        kind: SecretStore
      target:
        name: secret-example
      data:
        - secretKey: type
          remoteRef:
            key: creds
            property: type
    
    Resulting Kubernetes Secret data:
    {
      "type": "credential"
    }
    
  • Nested value using data
    apiVersion: external-secrets.io/v1
    kind: ExternalSecret
    metadata:
      name: external-secret-ovh
      namespace: default
    spec:
      secretStoreRef:
        name: secret-store-ovh
        kind: SecretStore
      target:
        name: secret-example
      data:
        - secretKey: kevin-token
          remoteRef:
            key: creds
            property: users.kevin.token
    
    Resulting Kubernetes Secret data:
    {
      "kevin-token": "kevin token value"
    }
    
  • Nested value using dataFrom.extract
    apiVersion: external-secrets.io/v1
    kind: ExternalSecret
    metadata:
      name: external-secret-ovh
      namespace: default
    spec:
      secretStoreRef:
        name: secret-store-ovh
        kind: SecretStore
      target:
        name: secret-example
      dataFrom:
      - extract:
          key: creds
          property: users
    
    Resulting Kubernetes Secret data:
    {
      "kevin": {
        "token": "kevin token value"
      },
      "laura": {
        "token": "laura token value"
      }
    }
    

Warning

Scalar values cannot be retrieved using dataFrom.extract because no Kubernetes secret key can be specified, which would imply storing a value without a corresponding key.

Fetch multiple secrets

Extract multiple secrets, with filtering support.
You can filter either by path or/and regular expression. Path filtering occurs first if you use both.

For these examples, we will assume you have the following secrets in your Secret Manager: path/to/secret/secret1, path/to/secret/secret2, path/to/config/config2, path/to/config/config3, secret-example2. - Path filtering

apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
  name: external-secret-ovh
  namespace: default
spec:
  secretStoreRef:
    name: secret-store-ovh
    kind: SecretStore
  target:
    name: secret-example
  dataFrom:
  - find:
      path: "path/to/secret"
Resulting Kubernetes Secret data:
{
  "path/to/secret/secret1": "secret1 value",
  "path/to/secret/secret2": "secret2 value"
}

Note

If path is left empty or is "/", every secret will be retrieved from your Secret Manager.

  • Regular expression filtering
    apiVersion: external-secrets.io/v1
    kind: ExternalSecret
    metadata:
      name: external-secret-ovh
      namespace: default
    spec:
      secretStoreRef:
        name: secret-store-ovh
        kind: SecretStore
      target:
        name: secret-example
      dataFrom:
      - find:
          name:
            regexp: "[2-3]"
    
    Resulting Kubernetes Secret data:
    {
      "path/to/secret/secret2": "secret2 value",
      "path/to/config/config2": "config2 value",
      "path/to/config/config3": "config3 value",
      "secret-example2": "secret-example2 value"
    }
    

Note

If name.regexp is left empty, every secret will be retrieved from your Secret Manager.

  • Combination of both
    apiVersion: external-secrets.io/v1
    kind: ExternalSecret
    metadata:
      name: external-secret-ovh
      namespace: default
    spec:
      secretStoreRef:
        name: secret-store-ovh
        kind: SecretStore
      target:
        name: secret-example
      dataFrom:
      - find:
          path: "path/to"
          name:
            regexp: "2$"
    
    Resulting Kubernetes Secret data:
    {
      "path/to/secret/secret2": "secret2 value",
      "path/to/config/config2": "config2 value"
    }
    

Note

When both are combined, path filtering occurs first.

PushSecret

Check-And-Set

Check-And-Set can be enabled/disabled (default: disabled), in the Secret Store configuration:

apiVersion: external-secrets.io/v1
kind: SecretStore
metadata:
  name: secret-store-ovh
  namespace: default
spec:
  provider:
    ovh:
      server: <kms-endpoint>
      okmsid: <okms-id>
      auth:
        token:
          tokenSecretRef:
            name: ovh-token
            key: token
      casRequired: true
---
apiVersion: v1
kind: Secret
metadata:
  name: ovh-token
data:
  token: BASE64_TOKEN_PLACEHOLDER # "token value"

Secret Rotation

apiVersion: generators.external-secrets.io/v1alpha1
kind: Password
metadata:
  name: my-password-generator
spec:
  length: 32
  digits: 5
  symbols: 5
  symbolCharacters: "-_^$%*รน/;:,?"
  noUpper: false
  allowRepeat: true
---
apiVersion: external-secrets.io/v1alpha1
kind: PushSecret
metadata:
  name: push-secret-ovh
spec:
  refreshInterval: 6h0m0s
  secretStoreRefs:
    - name: secret-store-ovh
      kind: SecretStore
  selector:
    generatorRef:
      apiVersion: generators.external-secrets.io/v1alpha1
      kind: Password
      name: my-password-generator
  data:
    - match:
        secretKey: password # property in the generator output
        remoteRef:
          remoteKey: prod/mysql/password

With this configuration, the secret is automatically rotated every 6 hours in the OVH Secret Manager.

Secret migration

apiVersion: external-secrets.io/v1
kind: SecretStore
metadata:
  name: secret-store-vault
  namespace: default
spec:
  provider:
    vault:
      server: "https://my.vault.server:8200"
      path: "secret"
      version: "v2"
      auth:
        tokenSecretRef:
          name: vault-token
          key: token
---
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
  name: external-secret-vault
  namespace: default
spec:
  secretStoreRef:
    name: secret-store-vault
    kind: SecretStore
  refreshPolicy: Periodic
  refreshInterval: "10s"
  target:
    name: creds-secret-vault
  dataFrom:
    - extract:
        key: example
---
apiVersion: external-secrets.io/v1
kind: SecretStore
metadata:
  name: secret-store-ovh
  namespace: default
spec:
  provider:
    ovh:
      server: <kms-endpoint>
      okmsid: <okms-id>
      auth:
        token:
          tokenSecretRef:
            name: ovh-token
            key: token
---
apiVersion: external-secrets.io/v1alpha1
kind: PushSecret
metadata:
  name: push-secret-ovh
spec:
  secretStoreRefs:
    - name: secret-store-ovh
      kind: SecretStore
  selector:
    secret:
      name: creds-secret-vault
  refreshInterval: 10s
  data:
    - match:
        secretKey: "secretKey"
        remoteRef:
          remoteKey: "creds-secret-migrated"

This example demonstrates how to fetch a secret from a HashiCorp Vault KV secrets engine and sync it into OVH Secret Manager.