Kubernetes Generic Dynamic Secrets

You can use Akeyless dynamic secrets to generate tokens for Kubernetes service accounts that are used to authenticate to a Kubernetes cluster as an external resource.

Kubernetes service accounts are designed to be used by processes for specific tasks, following the principle of least privilege. Each service account has an associated JWT token, which can be generated by the dynamic secret. The service account and token are authenticated by the Kubernetes API server.

Once you have created a Kubernetes generic dynamic secret using the Akeyless CLI or the Akeyless Gateway, you can use the token in a kubeconfig file. If the Akeyless CLI is installed on the same host as the kubectl, this can be done automatically. Alternatively, you can get the token from the Akeyless Console, and manually update the kubeconfig file.

Prerequisites

To create a Kubernetes generic dynamic secret you need the following two Kubernetes service accounts:

  • A service account with permission to run the Kubernetes API RequestToken command to generate JWT tokens for other service accounts.
  • A service account with the permissions that should be given to clients on a specific Kubernetes namespace.

In the following example, you can see a cluster role with permission to create and get tokens:

apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
  name: tokenrequest
rules:
- apiGroups: [""]
  resources:
  - "serviceaccounts/token"
  - "serviceaccounts"
  verbs:
  - "create"
  - "get"

📘

Note

When using kubeadm, please make sure to enable the following api flags on kubeadm-config.yaml

apiServer:
  extraArgs:
    service-account-signing-key-file: /etc/kubernetes/pki/sa.key
    service-account-key-file: /etc/kubernetes/pki/sa.pub
    service-account-issuer: api
    service-account-api-audiences: api,vault,factors

Create a Kubernetes Generic Dynamic Secret from the CLI

Let’s create a Kubernetes generic dynamic secret using the Akeyless CLI. If you’d prefer, see how to do this from the Akeyless Gateway instead.

The CLI command to create a Kubernetes generic dynamic secret is:

$ akeyless gateway-create-producer-k8s \ 
--name <secret name> \
--k8s-cluster-endpoint <cluster DNS/IP address> \
--k8s-cluster-ca-cert <base 64 encoded cluster certificate> \
--k8s-namespace <namespace> \
--k8s-service-account <service account> \
--k8s-cluster-token ${TOKEN}

where:

  • name: A unique name for the dynamic secret. The name can include the path to the virtual folder in which you want to create the new secret, using slash / separators. If the folder does not exist, it will be created together with the secret.
  • k8s-cluster-endpoint: The DNS or IP address of the cluster, in https:// format.
  • k8s-cluster-ca-cert: The Base-64 encoded cluster certificate.
  • k8s-namespace: The Kubernetes namespace for which the service account is defined.
  • k8s-service-account: The Kubernetes service account from which to extract the token.
  • k8s-cluster-token: A JWT authentication token authorized to create service account tokens.

Options

The full list of options for this command is:

-u, --gateway-url[=http://localhost:8000]   Akeyless Gateway URL (Configuration Management port)
  -n, --name                                 *Producer name
  -e, --k8s-cluster-endpoint                 *K8S Cluster endpoint. https:// , <DNS / IP> of the cluster.
  -c, --k8s-cluster-ca-cert                  *K8S Cluster certificate. Base 64 encoded certificate.
  -t, --k8s-cluster-token                    *K8S Cluster authentication token.
  -s, --k8s-service-account                  *K8S ServiceAccount to extract token from.
      --k8s-namespace[=default]               K8S Namespace where the ServiceAccount exists.
      --producer-encryption-key-name          Encrypt producer with following key
      --user-ttl[=60m]                        User TTL
      --profile                               Use a specific profile from your akeyless/profiles/ folder
      --username                              Optional username for various authentication flows
      --password                              Optional password for various authentication flows
      --uid-token                             The universal identity token, Required only for universal_identity authentication
  -h, --help                                  display help information
      --json[=false]                          Set output format to JSON
      --no-creds-cleanup[=false]              Do not clean local temporary expired creds

👍

For details about these options, see the CLI Command Reference.

Create a Kubernetes Generic Dynamic Secret from the Akeyless Gateway

Let’s create a Kubernetes generic dynamic secret using the Akeyless Gateway. If you’d prefer, see how to do this from the Akeyless CLI instead.

  1. Log in to the Akeyless Gateway and go to Dynamic Secrets > New > Kubernetes Producer > Generic.

  2. Define a Name for the dynamic secret, and specify the Location as a path to the virtual folder in which you want to create the new secret, using slash / separators. If the folder does not exist, it will be created together with the secret.

  3. Do one of the following:

    • Select Choose Target, then select an existing Kubernetes target from the Target name dropdown list.
    • Select Built-in Target, and define the following information for the Kubernetes target:
      • Target Name: Enter a unique name for the target.
      • K8S Cluster URL Endpoint: Enter the DNS or IP address of the cluster, in https:// format.
      • K8S Cluster CA Certificate: Enter the Base-64 encoded cluster certificate.
      • K8S Token (bearer): Enter a JWT authentication token authorized to create service account tokens.
  4. In the Permission Profile area, define the parameters as follows:

    • K8S Service Account: Enter the Kubernetes service account from which to extract the token.
    • K8S Namespace: Enter the Kubernetes namespace for which the service account is defined.
    • User TTL: Enter the length of time for which the credentials generated by the dynamic secret are valid, by default 60 (minutes).
    • Time Unit: Select the time unit for the TTL, by default, minutes.
  5. From the Encrypt Dynamic Producer with the following Key dropdown list, select the encryption key with which to encrypt the dynamic secret (if your system includes multiple encryption keys). Otherwise, select Default.

  6. Select Save.

Use a Kubernetes Generic Dynamic Secret with the Akeyless CLI

If the Akeyless CLI is installed on the same host as the kubectl, you can define a kubeconfig file to automatically run the get-dynamic-secret-value command and fetch new access tokens as required.

👍

If the Akeyless CLI is not installed on the same host as the kubectl, you can get the token and manually update the kubeconfig file with the token value.

Create the following kubeconfig file to run the get-dynamic-secret-value command and fetch new access tokens:

apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: <base 64 encoding of the cluster certificate>
    server: <cluster DNS/IP address>
  name: <cluster name>
contexts:
- context:
    cluster: <cluster name>
    user: <user name>
  name: <cluster context name>
current-context: <cluster context name>
kind: Config
preferences: {}
users:
- name: <user name>
  user:
    exec:
      apiVersion: client.authentication.k8s.io/v1beta1
      args:
        - get-dynamic-secret-value
        - --name
        - <dynamic secret item name>
        - --profile
        - <some profile> 
      command: /usr/local/bin/akeyless

Use a Kubernetes Generic Dynamic Secret without the Akeyless CLI

You can get a service account token from Akeyless and then manually update the kubeconfig file that uses the token.

📘

If the Akeyless CLI is installed on the same host as the kubectl, you can define the kubeconfig file to automatically fetch new access tokens as required.

  1. Create the following kubeconfig file:
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: <base 64 encoding of the cluster certificate>
    server: <cluster DNS/IP address>
  name: <cluster name>
contexts:
- context:
    cluster: <cluster name>
    user: <user name>
  name: <cluster context name>
current-context: <cluster context name>
kind: Config
preferences: {}
users:
- name: <some user name>
  user:
    token: < Dynamic Secret Value response goes here >
  1. Log in to the Akeyless Console, go to Secrets & Keys, and select the Kubernetes generic dynamic secret.

  2. Select Get Dynamic Secret, and copy the token value.

  3. In the kubeconfig file, replace < Dynamic Secret Value response goes here > with the token value.

Example: Kubernetes Dashboard

Let's see an example of how you could use Kubernetes generic dynamic secrets to get a token for the Kubernetes Dashboard.

In this example, the token-request-sa service account has permission to create tokens for existing service accounts on the kubernetes-dashboard namespace:

apiVersion: v1
kind: ServiceAccount
metadata:
  name: token-request-sa
  namespace: kubernetes-dashboard
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
  name: tokenrequest-dash
rules:
- apiGroups: [""]
  resources:
  - "serviceaccounts/token"
  - "serviceaccounts"
  verbs:
  - "create"
  - "get"
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
  name: tokenrequest-dash
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: tokenrequest-dash
subjects:
- kind: ServiceAccount
  name: token-request-sa
  namespace: kubernetes-dashboard
  1. Extract the service account token (secret) name by running:
TOKENNAME=`kubectl -n kubernetes-dashboard get serviceaccount/token-request-sa -o jsonpath='{.secrets[0].name}'`
  1. Extract the service account token by running:
TOKEN=`kubectl -n kubernetes-dashboard get secret $TOKENNAME -o jsonpath='{.data.token}'| base64 --decode`
  1. Create a Kubernetes generic dynamic secret called k8s-dashboard-producer by running:
$ akeyless gateway-create-producer-k8s -n k8s-dashboard-producer \
--k8s-cluster-endpoint <cluster DNS/IP address> \
--k8s-cluster-ca-cert <base 64 encoding of the cluster certificate> \
--k8s-namespace kubernetes-dashboard \
--k8s-service-account kubernetes-dashboard \
--k8s-cluster-token ${TOKEN}
  1. Get the k8s-dashboard-producer dynamic secret value by running:
$ akeyless get-dynamic-secret-value -n k8s-dashboard-producer | jq .

The output is:

{
  "apiVersion": "client.authentication.k8s.io/v1beta1",
  "clusterCACertificate": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJkekNDQVIyZ0F3SUJBZ0lCQURBS0JnZ3Foa2pPUFFRREFqQWpNU0V3SHdZRFZRUUREQmhyTTNNdGMyVnkKZG1WeUxXTmhRREUyTWpNek1UZzBPRFV3SGhjTk1qRXdOakV3TURrME9EQTFXaGNOTXpFd05qQTRNRGswT0RBMQpXakFqTVNFd0h3WURWUVFEREJock0zTXRjMlZ5ZG1WeUxXTmhRREUyTWpNek1UZzBPRFV3V1RBVEJnY3Foa2pPClBRSUJCZ2dxaGtqT1BRTUJCd05DQUFUTEZqVXZIRFg0YmhzMm9TS0Vkb1Y1R2dsQVRPUkpYVDBzYmhCVSs2VzEKUm52dEFwWVZlVDlQa1crUnJXL0VKcS9lZEpNYUFzZGFIcEtxM2FHZTFNbGJvMEl3UURBT0JnTlZIUThCQWY4RQpCQU1DQXFRd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBZEJnTlZIUTRFRmdRVWhXTGwzU1N5UGVHVlRRVlh6UkszClV5RnF4S0l3Q2dZSUtvWkl6ajBFQXdJRFNBQXdSUUloQUkwd2MwcUUwck9YZVN2VzN5d1RFc1BHWVUrVHZkVTIKbVFEYUtIN3BvSGJVQWlCbWtoQTNZejZhQkpmTmU0c09Eb1RKK2lGTElwSndvb3FPZjhGZWYvdnJSdz09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K",
  "clusterEndpoint": "https://0.0.0.0:56155",
  "clusterName": "k8s-native-cluster",
  "clusterUsername": "k8s-native-cluster",
  "kind": "ExecCredential",
  "status": {
    "token": "eyJhbGciOiJSUzI1NiIsImtpZCI6InNmMmZhbXgyRC1KT1pzUTBSVll0RFMzQjk1dGJXV19sRnd0b3FhYnBBRTgifQ.eyJhdWQiOlsiaHR0cHM6Ly9rdWJlcm5ldGVzLmRlZmF1bHQuc3ZjLmNsdXN0ZXIubG9jYWwiLCJrM3MiXSwiZXhwIjoxNjI0MTg4MTY5LCJpYXQiOjE2MjQxODQ1NjksImlzcyI6Imh0dHBzOi8va3ViZXJuZXRlcy5kZWZhdWx0LnN2Yy5jbHVzdGVyLmxvY2FsIiwia3ViZXJuZXRlcy5pbyI6eyJuYW1lc3BhY2UiOiJrdWJlcm5ldGVzLWRhc2hib2FyZCIsInNlcnZpY2VhY2NvdW50Ijp7Im5hbWUiOiJrdWJlcm5ldGVzLWRhc2hib2FyZCIsInVpZCI6IjI5MGU4M2IwLTc1MTItNDZiOC1hYWIxLWViN2IxOTIxNmY2NyJ9fSwibmJmIjoxNjI0MTg0NTY5LCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6a3ViZXJuZXRlcy1kYXNoYm9hcmQ6a3ViZXJuZXRlcy1kYXNoYm9hcmQifQ.oflUcXwzFF2Kcyi45_SNrdGmAk_2abqAz0nE7AyUU_-W2-l7ZxPovtM2pfcfHm_dmW9wCDxM3zK4Zh39ruWnvjqIB_uxWQGAtQnU3TBlHSY2knQdZ7lNop-ylvQMdh4rTNf07BM_zKoKVh1w1__nE-esghwOe6mtRuKIy3Xj5Ijk2aamx3DFbFcyizHyZVst_PSbm1fdxdSLFzBy0vXmI8-Lx-KbJsUM5yO2MGmEk-oX28YCG0hgF0NkPbyjyEtIPBrRKbbdyo8lM_dGQ5Hk7D1P5Vo56f14oKUHRJDdzyd-jFSH_dtxD0FxazuNPlmuE9lRdJzeSgvuGp6S-MsksQ"
  }
}
  1. Copy the token value, and use it for the Kubernetes Dashboard.

Did this page help you?