[Yandex Cloud documentation](../../index.md) > [Tutorials](../index.md) > [Security](index.md) > Integrations of workload identity federations > Custom installation Kubernetes

# Getting the Yandex Lockbox secret value on the custom Kubernetes installation side

[Workload identity federations](../../iam/concepts/workload-identity.md) allow you to configure a link between external systems and Yandex Cloud via the [OpenID Connect](https://openid.net/developers/how-connect-works/) (OIDC) protocol. This allows external systems to perform actions with Yandex Cloud resources under IAM [service accounts](../../iam/concepts/users/service-accounts.md) without using [authorized keys](../../iam/concepts/authorization/key.md). This is a more secure method that minimizes the risk of credential leakage and the possibility of unauthorized access.

This tutorial shows you as an example how to get the [Yandex Lockbox](../../lockbox/index.md) [secret](../../lockbox/concepts/secret.md) value from the Kubernetes side under a Yandex Cloud service account. Similarly, you can perform any action via the Yandex Cloud [CLI](../../cli/quickstart.md), [API](../../api-design-guide/index.md), or [Terraform](../../terraform/index.md).

{% note info %}

This tutorial demonstrates an example of integrating a custom Kubernetes installation with a workload identity federation. See the Managed Service for Kubernetes integration guide in [Accessing the Yandex Cloud API from a Managed Service for Kubernetes cluster using an Identity and Access Management workload identity federation](wlif-managed-k8s-integration.md).

{% endnote %}

To get the Yandex Lockbox secret value under a Kubernetes account:

1. [Prepare the Kubernetes cluster](#prepare-k8s-cluster).
1. [Get your cloud ready](#prepare-cloud).
1. [Configure a scenario in Kubernetes](#k8s-workflow).

If you no longer need the resources you created, [delete them](#clear-out).

## Prepare the Kubernetes cluster {#prepare-k8s-cluster}

1. Create a new Kubernetes cluster or use an existing one.

   Make sure your cluster meets the following requirements:

   * You are using Kubernetes 1.20 or higher.
      Earlier Kubernetes versions use a different `ServiceAccount` token format incompatible with the instructions provided here.
   * You have configured `kube-apiserver` to [support projection of `ServiceAccount` tokens](https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#serviceaccount-token-volume-projection).

   {% note info %}

   This tutorial applies to both public and private Kubernetes clusters.

   {% endnote %}

1. Create a manifest named `service-account.yaml` with the following contents:

   ```yaml
   apiVersion: v1
   kind: ServiceAccount
   metadata:
     name: wlif
   ```

1. Apply the manifest:

   ```bash
   kubectl apply -f service-account.yaml
   ```

1. To check the `ServiceAccount` resource you created, run this command:

   ```bash
   kubectl describe serviceaccount wlif
   ```

   Result:
   ```
   Name:                wlif
   Namespace:           default
   ```

   You will need the `Name` and `Namespace` field values to further configure integration on the Yandex Cloud side.

1. Create a manifest named `pod.yaml` with the following contents:

   ```yaml
   apiVersion: v1
   kind: Pod
   metadata:
     name: test-wlif
   spec:
     containers:
     - image: nginx
       name: nginx
       volumeMounts:
       - mountPath: /var/run/secrets/tokens
         name: sa-token
     serviceAccountName: wlif
     volumes:
     - name: sa-token
       projected:
         sources:
         - serviceAccountToken:
             path: sa-token
             expirationSeconds: 7200
             audience: ycaud
   ```

   In the `audience` field, specify the token recipient, e.g., `ycaud`.

1. Apply the manifest:

   ```bash
   kubectl apply -f pod.yaml
   ```

1. Make sure the pod you created has the `RUNNING` status:

   ```bash
   kubectl get pod test-wlif
   ```

   Result:

   ```
   NAME        READY   STATUS    RESTARTS   AGE
   test-wlif   1/1     Running   0          1m
   ```

1. Get `URL Issuer` for your Kubernetes cluster:

   ```bash
   kubectl get --raw /.well-known/openid-configuration | jq -r .issuer
   ```

1. Create a file with a public key set (JWKS):
   
   ```bash
   kubectl get --raw /openid/v1/jwks > cluster-jwks.json
   ```

## Get your cloud ready {#prepare-cloud}

Sign up for Yandex Cloud and create a [billing account](../../billing/concepts/billing-account.md):
1. Navigate to the [management console](https://console.yandex.cloud) and log in to Yandex Cloud or create a new account.
1. On the **[Yandex Cloud Billing](https://center.yandex.cloud/billing/accounts)** page, make sure you have a billing account linked and it has the `ACTIVE` or `TRIAL_ACTIVE` [status](../../billing/concepts/billing-account-statuses.md). If you do not have a billing account, [create one](../../billing/quickstart/index.md) and [link](../../billing/operations/pin-cloud.md) a cloud to it.

If you have an active billing account, you can create or select a [folder](../../resource-manager/concepts/resources-hierarchy.md#folder) for your infrastructure on the [cloud page](https://console.yandex.cloud/cloud).

[Learn more about clouds and folders here](../../resource-manager/concepts/resources-hierarchy.md).

### Required paid resources {#paid-resources}

The infrastructure support cost includes:
1. Fee for storing the [secret](../../lockbox/concepts/secret.md) and requests to the secret (see [Yandex Lockbox pricing](../../lockbox/pricing.md)).
1. Fee for bucket data storage and bucket operations (see [Object Storage pricing](../../storage/pricing.md)).

### Upload a file with a public key set to a public bucket

1. Create a public bucket:

   {% list tabs group=instructions %}

   - Management console {#console}

      1. In the [management console](https://console.yandex.cloud), select the folder where you want to create a bucket.
      1. Navigate to **Object Storage**.
      1. In the top panel, click **Create bucket**.
      1. On the `create bucket` page:
         1. Specify a bucket name that meets [these naming conventions](../../storage/concepts/bucket.md#naming).
         
         1. In the **Read objects** field, select `For all`.

         1. Click **Create bucket** to complete the operation.

   {% endlist %}

1. Upload the `cluster-jwks.json` file you created earlier into the bucket:

   {% list tabs group=instructions %}

   - Management console {#console}

      1. Go to the new bucket.
      1. In the left-hand panel, select ![image](../../_assets/console-icons/folder-tree.svg) **Objects**.
      1. Click **Upload objects**.
      1. In the top panel, click ![image](../../_assets/console-icons/arrow-up-from-line.svg) **Upload**.
      1. In the window that opens, select the `cluster-jwks.json` file and click **Open**.
      1. Click **Upload**.
      1. Refresh the page.

   {% endlist %}

1. Get a link to the uploaded file:

   {% list tabs group=instructions %}

   - Management console {#console}

      1. Click the file name.
      1. Click ![link](../../_assets/storage/link.svg) **Get link** in the top-right corner.
      1. Copy the link.

   {% endlist %}

### Create a workload identity federation {#federation-iam-accounts}

{% list tabs group=instructions %}

- Management console {#console}

   1. In the [management console](https://console.yandex.cloud), select the folder where you want to create a workload identity federation.
   1. Navigate to **Identity and Access Management**.
   1. In the left-hand panel, select ![cpus](../../_assets/console-icons/cpus.svg) **Workload identity federations**.
   1. Click **Create federation**.
   1. In the **Issuer value (iss)** field, enter `URL Issuer` for your Kubernetes cluster, which you got earlier, e.g., `https://kubernetes.default.svc.cluster.local`.
   1. In the **Acceptable Audience values (AUD)** field, enter the token recipient you specified when creating the pod, e.g., `ycaud`.
   1. In the **JWKS address** field, enter a link to the `cluster-jwks.json` file in the bucket.
   1. In the **Name** field, enter a name for the federation, e.g., `test-iam-federation`.
   1. Click **Create**.

{% endlist %}

### Create a custom secret

{% list tabs group=instructions %}

- Management console {#console}

   1. In the [management console](https://console.yandex.cloud), select the folder where you want to create your secret.
   1. Navigate to **Lockbox**.
   1. Click **Create secret**.
   1. In the **Name** field, enter a name for the secret: `MY_SECRET`.
   1. Select **Secret type** `Custom`.
   1. In the **Key** field, enter a non-secret ID, e.g., `secret`.
   1. In the **Value** field, enter the confidential data you want to store.
   1. Click **Create**.

{% endlist %}

### Create a service account.

1. Create a service account:

   {% list tabs group=instructions %}

   - Management console {#console}

      1. In the [management console](https://console.yandex.cloud), select the folder where you want to create a service account.
      1. Navigate to **Identity and Access Management**.
      1. Click **Create service account**.
      1. Enter a name for the service account, e.g., `sa-lockbox`.
      1. Click **Create**.

   {% endlist %}

1. Assign the `lockbox.payloadViewer` [role](../../iam/concepts/access-control/roles.md) for the folder to the service account: 

   {% list tabs group=instructions %}

   - Management console {#console}

      1. On the management console [home page](https://console.yandex.cloud), select a folder.
      1. Navigate to the **Access bindings** tab.
      1. Find the `sa-lockbox` account in the list and click ![image](../../_assets/console-icons/ellipsis.svg).
      1. Click **Edit roles**.
      1. In the dialog that opens, click ![image](../../_assets/console-icons/plus.svg) **Add role** and select the `lockbox.payloadViewer` role.

   {% endlist %}

### Link the service account to the Federation

{% list tabs group=instructions %}

- Management console {#console}

   1. In the [management console](https://console.yandex.cloud), select the folder the service account was created in.
   1. Navigate to **Identity and Access Management**.
   1. In the list of service accounts, select `sa-lockbox`.
   1. In the top panel, click ![image](../../_assets/console-icons/cpus.svg) **Link to federation**.
   1. In the **Workload identity federation** field, select the federation you created earlier.
   1. In the **Subject value (sub)** field, specify the external account ID: `system:serviceaccount:<namespace>:<account_name>`.
   
      Where:
      * `namespace`: The `Namespace` field value in the output of the `kubectl describe serviceaccount <account_name>` command, e.g., `default`.
      * `account_name`: Name of the account you created, e.g., `wlif`.

   1. Click **Link**.

{% endlist %}

## Configure a scenario in Kubernetes {#k8s-workflow}

1. Fill in the variables:

   ```bash
   SA_ID="<service_account_ID>"
   SECRET_ID="<secret_ID>"
   ```

   Where:
   * `SA_ID`: Service account ID.
   * `SECRET_ID`: Custom secret ID.

1. Get the Kubernetes service account token:

   ```bash
   SA_TOKEN=`kubectl exec -it test-wlif -- cat /var/run/secrets/tokens/sa-token`
   ```

1. Exchange the Kubernetes service account token for the IAM token of the Yandex Cloud service account:
   
   ```bash
   IAMTOKEN=$(curl -sH "Content-Type: application/x-www-form-urlencoded" -d "grant_type=urn:ietf:params:oauth:grant-type:token-exchange&requested_token_type=urn:ietf:params:oauth:token-type:access_token&audience=$SA_ID&subject_token=$SA_TOKEN&subject_token_type=urn:ietf:params:oauth:token-type:id_token" -X POST https://auth.yandex.cloud/oauth/token | jq -r '.access_token')
   ```

1. Request the secret via the API using the Yandex Cloud IAM token:

   ```bash
   SECRET_DATA=$(curl -sH "Authorization: Bearer ${IAMTOKEN}" https://payload.lockbox.api.cloud.yandex.net/lockbox/v1/secrets/$SECRET_ID/payload)
   echo ${SECRET_DATA}
   ```

   Result:

   ```json
   { "entries": [ { "key": "secret", "textValue": "67cH2£?pO********" } ], "versionId": "e6q8isknpcp7********" }
   ```

## Delete the resources you created {#clear-out}

Some resources are not free of charge. Delete the resources you no longer need to avoid paying for them:

* [Yandex Lockbox secret](../../lockbox/operations/secret-delete.md) 
* [Object Storage bucket](../../storage/operations/buckets/delete.md)
* [Service account](../../iam/operations/sa/delete.md)

## Useful links {#see-also}

* [Workload identity federations](../../iam/concepts/workload-identity.md)
* [Accessing the Yandex Cloud API from a Managed Service for Kubernetes cluster using an Identity and Access Management workload identity federation](wlif-managed-k8s-integration.md)
* [Getting Yandex Lockbox secret value on the GitLab side](wlif-gitlab-integration.md)
* [Getting Yandex Lockbox secret value on the GitHub side](wlif-github-integration.md)