Keeper Security
Keeper Security
External Secrets Operator integrates with Keeper Security for secret management by using Keeper Secrets Manager.
Authentication
Secrets Manager Configuration (SMC)
KSM can authenticate using One Time Access Token or Secret Manager Configuration. In order to work with External Secret Operator we need to configure a Secret Manager Configuration.
Creating Secrets Manager Configuration
You can find the documentation for the Secret Manager Configuration creation here. Make sure you add the proper permissions to your device in order to be able to read and write secrets
Once you have created your SMC, you will get a config.json file or a base64 json encoded string containing the following keys:
- hostname
- clientId
- privateKey
- serverPublicKeyId
- appKey
- appOwnerPublicKey
This base64 encoded jsong string will be required to create your secretStores
Important note about this documentation
The KepeerSecurity calls the entries in vaults 'Records'. These docs use the same term.
Update secret store
Be sure the keepersecurity provider is listed in the Kind=SecretStore
---
apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
  name: keeper
spec:
  provider:
    keepersecurity:
      authRef: # Refer to a kubernetes secret which holds the base64 encoded json string for the configuration
        name: keeper-configuration
        key:  auth
      folderID: 1qdsiewFW-U # Folder ID where the secrets can be pushed. It requires write permissions
NOTE 1: folderID target the folder ID where the secrets should be pushed to. It requires write permissions within the folder
NOTE 2: In case of a ClusterSecretStore, Be sure to provide namespace for SecretAccessKeyRef with the namespace of the secret that we just created.
External Secrets
Behavior
- How a Record is equated to an ExternalSecret:- remoteRef.keyis equated to a Record's ID
- remoteRef.propertyis equated to one of the following options:- Fields: Record's field's Type
- CustomFields: Record's field's Label
- Files: Record's file's Name
- If empty, defaults to the complete Record in JSON format
 
- remoteRef.versionis currently not supported.
 
- dataFrom:- find.pathis currently not supported.
- find.name.regexpis equated to one of the following options:- Fields: Record's field's Type
- CustomFields: Record's field's Label
- Files: Record's file's Name
 
- find.tagsare not supported at this time.
 
Creating external secret
To create a kubernetes secret from the GCP Secret Manager secret a Kind=ExternalSecret is needed.
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: example
spec:
  refreshInterval: 1h           # rate SecretManager pulls KeeperSrucity
  secretStoreRef:
    kind: SecretStore
    name: example               # name of the SecretStore (or kind specified)
  target:
    name: secret-to-be-created  # name of the k8s Secret to be created
    creationPolicy: Owner
  dataFrom:
    - extract:
        key: OqPt3Vd37My7G8rTb-8Q  # ID of the Keeper Record
---
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: regcred
  namespace: external-secrets
spec:
  refreshInterval: 1m
  secretStoreRef:
    name: keeper
    kind: ClusterSecretStore
  target:
    name: regcred
    creationPolicy: Owner
    template:
      engineVersion: v2
      type: kubernetes.io/dockerconfigjson
      data:
        .dockerconfigjson: "{\"auths\":{\"registry.example.com\":{\"username\":\"{{ .username }}\",\"password\":\"{{ .password }}\",\"auth\":\"{{(printf \"%s:%s\" .username .password) | b64enc }}\"}}}"
  data:
    - secretKey: username
      remoteRef:
        key: OqPt3Vd37My7G8rTb-8Q
        property: login
    - secretKey: password
      remoteRef:
        key: OqPt3Vd37My7G8rTb-8Q
        property: password
---
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: config
  namespace: external-secrets
spec:
  refreshInterval: 1m
  secretStoreRef:
    name: keeper
    kind: ClusterSecretStore
  target:
    name: credentials
    creationPolicy: Owner
    template:
      engineVersion: v2
      data:
        username: "{{ .login }}"
        password: "{{ .password }}"
  data:
    - secretKey: login
      remoteRef:
        key: OqPt3Vd37My7G8rTb-8Q
        property: login
    - secretKey: password
      remoteRef:
        key: OqPt3Vd37My7G8rTb-8Q
        property: password
The operator will fetch the Keeper Secret Manager secret and inject it as a Kind=Secret
kubectl get secret secret-to-be-created -n <namespace> | -o jsonpath='{.data.dev-secret-test}' | base64 -d
Limitations
There are some limitations using this provider.
- Keeper Secret Manager does not work with GeneralRecords types nor legacy non-typed records
- Using tags find.tagsis not supported by KSM
- Using path find.pathis not supported at the moment
Push Secrets
Push Secret will only work with a custom KeeperSecurity Record type ExternalSecret
Behavior
- selector:
- secret.name: name of the kubernetes secret to be pushed
- data.match:
- secretKey: key on the selected secret to be pushed
- remoteRef.remoteKey: Secret and key to be created on the remote provider- Format: SecretName/SecretKey
 
Creating push secret
To create a Keeper Security record from kubernetes a Kind=PushSecret is needed.
apiVersion: external-secrets.io/v1alpha1
kind: PushSecret
metadata:
  name: example
spec:
  secretStoreRefs:
    - name: keeper
      kind: SecretStore
  refreshInterval: "1h"
  deletionPolicy: Delete
  selector:
    secret:
      name: secret-name # k8s secret to be pushed
  data:
    - match:
        secretKey: secret-key # k8s key within the secret to be pushed
        remoteRef:
          remoteKey: remote-secret-name/remote-secret-key # This will create a record called "remote-secret-name" with a key "remote-secret-key"
Limitations
- Only possible to push one key per secret at the moment
- If the record with the selected name exists but the key does not exists the record can not be updated. See Ability to add custom fields to existing secret #17