OKEでoci-secrets-store-csi-driver-providerを使ってみよう

# はじめに
先日、OKEでoci-secrets-store-csi-driver-providerが[サポート](https://docs.oracle.com/en-us/iaas/releasenotes/changes/6dfc3529-8e66-4cf0-8b36-ef5c696f1182/)されました。
これは、Oracle Cloud InfrastructureのKey Management ServiceであるOCI Vaultというサービスを利用してOKE上のアプリのSecretを管理する仕組みです。

これを試してみたいと思います。 

# OKEの環境構築

OKEの構築は[こちら](https://oracle-japan.github.io/ocitutorials/cloud-native/oke-for-commons/)を参考に行なってください。

# [OCI Secrets Store CSI Driver Provider](https://github.com/oracle-samples/oci-secrets-store-csi-driver-provider)のインストール

ここではOCI Secrets Store CSI Driver Providerのインストールを行います。
これは、Kubernetes Secrets Store CSI Driverの仕組みを利用して、OCI Vaultに保存されているSecretを取得し、CSIドライバーでPodにマウントできるものです。

OCI Secrets Store CSI Driver Providerは、[GCR(GitHub Container Registry)にコンテナイメージがアップロード](https://github.com/oracle-samples/oci-secrets-store-csi-driver-provider)されています。

この記事では、このイメージを利用してインストールを行います。（別途自前でビルドすることも可能です）

## Helmレポジトリの追加

```sh
helm repo add oci-provider https://oracle-samples.github.io/oci-secrets-store-csi-driver-provider/charts
```

## インストール

以下のコマンドでoci-secrets-store-csi-driver-providerをインストールします。

```sh
helm install oci-provider oci-provider/oci-secrets-store-csi-driver-provider --namespace kube-system
```

以下のように表示されればOKです。

```sh
Release "oci-provider" has been upgraded. Happy Helming!
NAME: oci-provider
LAST DEPLOYED: Mon Feb  6 07:16:23 2023
NAMESPACE: kube-system
STATUS: deployed
REVISION: 2
TEST SUITE: None
NOTES:
The Secrets Store CSI Driver and the provider are getting deployed to your cluster.

Verify DaemonSets readiness:
  kubectl get daemonset \
      --namespace kube-system \
      --selector='app.kubernetes.io/name in (oci-secrets-store-csi-driver-provider, secrets-store-csi-driver)'
```

表示された`Verify DaemonSets readiness`のコマンドを実行し、Podの状態を確認します。

```sh
kubectl get daemonset \
      --namespace kube-system \
      --selector='app.kubernetes.io/name in (oci-secrets-store-csi-driver-provider, secrets-store-csi-driver)'
```

以下のように`Running`状態になっていれば問題ありません。

```sh
NAME                                    DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR            AGE
oci-provider-secrets-store-csi-driver   1         1         1       1            1           kubernetes.io/os=linux   3m20s
oci-secrets-store-csi-driver-provider   1         1         1       1            1           <none>                   3m20s
```

これでoci-secrets-store-csi-driver-providerのインストールは完了です。

# インスタンス・プリンシパルの設定

OKE上のoci-secrets-store-csi-driver-providerからOCI Vaultのクレデンシャルが参照可能になるように権限を追加する必要があります。

この記事では、インスタンス・プリンシパルという仕組みを利用して、Worker NodeからOCI Vaultのクレデンシャルが参照できるように設定します。
結果的にはPodからOCI Vaultを参照できるようになります。

インスタンス・プリンシパルの仕組みや設定の際のスクリーンショットは今回は割愛しますが、詳細は[ドキュメント](https://docs.oracle.com/ja-jp/iaas/Content/Identity/Tasks/callingservicesfrominstances.htm)や[こちらの手順](https://oracle-japan.github.io/ocitutorials/cloud-native/oke-for-advances/#5-1-%E5%8B%95%E7%9A%84%E3%82%B0%E3%83%AB%E3%83%BC%E3%83%97%E3%81%A8%E3%83%9D%E3%83%AA%E3%82%B7%E3%83%BC%E3%81%AE%E8%A8%AD%E5%AE%9A)を参考にしてください。

今回設定する動的グループとポリシーは以下の通りです。

|  項目  |  値  | 説明
| ---- | ---- | ----|
|  動的グループ  | Any {instance.compartment.id = \<compartment-ocid>} | コンパートメント内のすべてのコンピュートを対象。本来はもっとスコープを狭くしますが、今回は全てを対象にします
|  ポリシー | allow dynamic-group \<dynamic-group-name> to use secret-family in compartment <compartment-name> | 動的グループに含まれるコンピュートがVaultを利用可能にするポリシー

これでインスタンス・プリンシパルの設定は完了です。

# OCI VaultでのSecretの作成

ここでは、アプリケーションで参照させるためのSecretをOCI Vaultに登録します。  

OCIコンソールから以下のようにクリックしていきます。

![スクリーンショット 2023-02-06 16.42.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/40392/f6cfd953-8a12-4b5d-edb0-6b81e16a247d.png)

`ボールトの作成`をクリックします。

名前を入力し、(ikanogazoudeha`oke`)`ボールトの作成`をクリックします。  

![スクリーンショット 2023-02-06 16.43.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/40392/f54f31b9-e57e-467b-ca97-b375977652aa.png)

作成したOCI VaultのOCIDは後ほど利用するので、コピーしてメモ帳などに記録しておいてください。

![スクリーンショット 2023-02-06 16.59.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/40392/c8f79c8d-03d2-8ca4-541e-489bd6e59421.png)



`キーの作成`をクリックします。  

名前を入力し、(以下の画像では`oke`)`キーの作成`をクリックします。 

![スクリーンショット 2023-02-06 16.49.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/40392/66e17158-117f-06cc-892c-fa9f087564a0.png)

画面左側にある`シークレット`をクリックします。

![スクリーンショット 2023-02-06 16.50.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/40392/02976270-7cb8-4fd2-5bbe-2d8eadf5d843.png)

`シークレットの作成`をクリックします。  

以下のパラメータを入力し、`シークレットの作成`をクリックします。

|  項目  |  値  | 
| ---- | ---- | 
|  名前  | oke
|  暗号化キー | oke
|シークレット・コンテンツ| 任意の値(この値をPodから参照します) 

![スクリーンショット 2023-02-06 16.51.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/40392/34f87b70-14dd-416d-dd6b-ab4fff468113.png)

以上で、Secretの作成は完了です。

# 動作確認

ここまでで、oci-secrets-store-csi-driver-providerが利用可能になっているため、実際に動作確認をしていきます。  

まずは、Podから参照するためのSecret Providerの設定を行います。
今回はレポジトリ内のサンプルManifestを利用します。

`deploy/example/secret-provider-class.yaml`を以下のように編集します。

```yaml:secret-provider-class.yaml
#
# OCI Secrets Store CSI Driver Provider
#
# Copyright (c) 2022 Oracle America, Inc. and its affiliates.
# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/
#

# SecretProviderClass is a custom resource to provide driver configurations and
# provider-specific parameters to the CSI driver.
#
# On pod start and restart, the driver will communicate with the provider to retrieve the secret content
# from the external Secrets Store you have specified in the SecretProviderClass resource.
#
# For more information check: https://secrets-store-csi-driver.sigs.k8s.io/getting-started/usage.html
#
# This SecretProviderClass is used as a reference example of how to configure the OCI Vault provider.
# Each SecretProviderClass enumerates secrets to mount into the pod.
# So, multiple SecretProviderClass resources could exist in a single Kubernetes cluster.

apiVersion: secrets-store.csi.x-k8s.io/v1
kind: SecretProviderClass
metadata:
  name: test-oci-provider-class # SecretProviderClass name is referenced from pod definition
spec:
  provider: oci # `provider` value is used as the provider socket name, must be constant
  parameters:
    # Each secret could be identified with `name` and either `stage` or `versionNumber`.
    # If both `stage` and `versionNumber` are omitted, default stage CURRENT is used.
    # Secret names could not be duplicated, since `name` field is used as a file name during the mounting.
    secrets: |
      - name: oke # OCI Vaultに登録したシークレット名
    vaultId: <前手順でメモしたOCI VaultのOCID>
    authType: instance 
```

このManifestを適用します。

```sh
kubectl apply -f deploy/example/secret-provider-class.yaml
```

次にサンプルのPodをデプロイします。今回はnginxを利用します。
特に変更する箇所はありません。

```yaml:app.deployment.yaml
#
# OCI Secrets Store CSI Driver Provider
# 
# Copyright (c) 2022 Oracle America, Inc. and its affiliates.
# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/
#

# This Deployment is used as a reference example of how to mount secrets into the pod
# via Secrets Store CSI Driver and OCI Vault Provider.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx:1.21.4-alpine
          ports:
            - containerPort: 80
          resources:
            limits:
              memory: 128Mi
              cpu: 200m
          volumeMounts:
            - name: 'some-creds'
              mountPath: '/mnt/secrets-store'  # => Podのマウントパス
              readOnly: true
      volumes:
        - name: some-creds
          csi:
            driver: 'secrets-store.csi.k8s.io'
            readOnly: true
            volumeAttributes:
              secretProviderClass: 'test-oci-provider-class'  # => 先ほど作成したSecretProviderClassの名前
```

```sh
kubectl apply -f deploy/example/app.deployment.yaml
```

これでデプロイは完了です。

実際にPodからOCI Vaultに格納したシークレットが参照できているかどうかを確認します。

Podの名前を取得します。 

```sh
[opc@user]$ kubectl get pods
NAME                     READY   STATUS    RESTARTS   AGE
nginx-5fd7f7876d-dqpf8   1/1     Running   0          10s
```

Pod内にSSHします。

```sh
[opc@user]$ kubectl exec -it nginx-5fd7f7876d-dqpf8 -- bin/sh
```

マウントしたパスを確認します。  

```sh
/ $ cd /mnt/secrets-store
```

中身を確認します。

```sh
/mnt/secrets-store $ cat oke
aaaa
```

先ほど登録したSecretの内容が登録されていますね！！

# まとめ

このようにoci-secrets-store-csi-driver-providerを利用するとOKE上のアプリケーションから簡単にOCI Vaultで管理しているSecretを参照することができます。
これによって、セキュアにアプリケーションのクレデンシャルが管理できますね！！

# 参考資料

https://github.com/oracle-samples/oci-secrets-store-csi-driver-provider

https://docs.oracle.com/ja-jp/iaas/Content/ContEng/Tasks/contengmanagingsecrets.htm

https://kubernetes-csi.github.io/docs/

https://github.com/kubernetes-sigs/secrets-store-csi-driver