External Secrets Operator

External Secrets Operator is a Kubernetes operator that integrates with external secret management systems like Akeyless. The operator reads information from Akeyless APIs and automatically injects the values into a Kubernetes Secret. More information can be found under Akeyless official provider.

1920

The goal of External Secrets Operator is to synchronize secrets from Akeyless into Kubernetes. ESO is a collection of custom API resources - ExternalSecret, SecretStore, and ClusterSecretStore that provide a user-friendly abstraction for the external API that stores and manages the lifecycle of the secrets for you.

Getting started:

External secrets run within your Kubernetes cluster as a deployment resource. It utilizes CustomResourceDefinitions to configure access to secret providers through SecretStore resources and manages Kubernetes secret resources with ExternalSecret resources.

📘

Note:

The minimum supported version of Kubernetes is 1.16.0. Users still running Kubernetes v1.15 or below should upgrade to a supported version before installing external-secrets.

Installing with Helm

External Secrets Official Git: https://github.com/external-secrets/external-secrets

helm repo add external-secrets https://charts.external-secrets.io
helm install external-secrets external-secrets/external-secrets # -n external-secrets --create-namespace

SecretStore

The idea behind the SecretStore resource is to separate concerns of authentication/access and the actual Secret and configuration needed for workloads. The ExternalSecret specifies what to fetch, the SecretStore specifies how to access it. This resource is namespaced.

Authentication methods:

Akeyless providers require an access-id, access-type and access-Type-param
To set your SecretStore with an authentication method from Akeyless, create a secret item on your cluster that contains the following settings:

apiVersion: v1
kind: Secret
metadata:
  name: akeyless-secret-creds
type: Opaque
stringData:
  accessId: "p-XXXX"
  accessType:  # k8s/aws_iam/gcp/azure_ad/api_key
  accessTypeParam:  # replace by the appropriate value for: <k8s-conf-name>/<gcp-audience>/<azure-obj-id>/<access-key>

📘

Note:

  • Ensure that an Access Role is defined in Akeyless for the credentials you specify and that the Access Role is associated with an Authentication Method that allows access to the required secret.

  • If you define the value of accessType as api_key, define the value of accessTypeParam as your access key.

Create the secret item for authentication:

kubectl apply -f akeylesscreds.yaml

Alternatively, you can explicitly specify the secret details as described in the K8sSecretStore example below:

Create the Akeyless Secret Store Provider:

apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
  name: akeyless-secret-store
spec:
  provider:
    akeyless:
      # URL of your akeyless API
      akeylessGWApiURL: "https://api.akeyless.io"
      authSecretRef:
        secretRef:
          accessID:
            name: akeyless-secret-creds
            key: accessId
          accessType:
            name: akeyless-secret-creds
            key: accessType
          accessTypeParam:
            name: akeyless-secret-creds
            key: accessTypeParam
apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
  name: akeyless-secret-store
spec:
  provider:
    akeyless:
      # URL of your akeyless API
      akeylessGWApiURL: "https://api.akeyless.io"
      authSecretRef:
        kubernetesAuth:
          accessID: "p-XXXXXX"
          k8sConfName: "my-conf-name"
          # Optional service account field containing the name
          # of a kubernetes ServiceAccount
          serviceAccountRef:
            name: "my-sa"
          # Optional secret field containing a Kubernetes ServiceAccount JWT
          # used for authenticating with Akeyless
          #secretRef:
           # name: "my-secret"
            #key: "token"

📘

Note:

  • Make sure the Akeyless provider is listed in the Kind=SecretStore.

  • If you use a customer fragment, define the value of akeylessGWApiURL as the URL of your Akeyless Gateway in the following format: https://your.akeyless.gw:8080/v2.

Create the Secret Store:

kubectl apply -f secretstore.yaml

Creating an External Secret:

To fetch a secret from Akeyless and store it as a Kubernetes secret on your cluster, a Kind=ExternalSecret is required.

apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: akeyless-external-secret-example
spec:
  refreshInterval: 1h

  secretStoreRef:
    kind: SecretStore
    name: akeyless-secret-store # Must match SecretStore on the cluster

  target:
    name: akeyless-secret-to-create # Name for the secret to be created on the cluster
    creationPolicy: Owner

  data:
    - secretKey: secretKey # Key given to the secret to be created on the cluster
      remoteRef:
        key: /path/to/your/secret # Full path of the secret on Akeyless

Create the External Secret item:

kubectl apply -f externalsecret.yaml

Getting the Kubernetes secret:

kubectl get secret akeyless-secret-to-create -o jsonpath='{.data.secretKey}' | base64 -d

Using DataFrom:

DataFrom can be used to get a secret as a JSON string and attempt to parse it.

apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: akeyless-external-secret-example-json
spec:
  refreshInterval: 1h

  secretStoreRef:
    kind: SecretStore
    name: akeyless-secret-store # Must match SecretStore on the cluster

  target:
    name: akeyless-secret-to-create-json # Name for the secret to be created on the cluster
    creationPolicy: Owner

  # for json formatted secrets: each key in the json will be used as the secret key in the SECRET k8s target object
  dataFrom:
  - extract:
      key: /path/to/your/secret/keyname # Full path of the secret on Akeyless

Getting the Kubernetes secret:

kubectl get secret akeyless-secret-to-create-json -o jsonpath='{.data}'