OCI KubernetesとOCI VaultでExternal Secrets Operatorを使用 (2022/06/01)

OCI KubernetesとOCI VaultでExternal Secrets Operatorを使用 (2022/06/01)

https://medium.com/oracledevs/using-the-external-secrets-operator-with-oci-kubernetes-and-oci-vault-6865f2e1fe35

投稿者:Ali Mukadam


最近、お客様からExternal Secrets Operator (ESO)プロジェクトを紹介され、すでにOCI Vault統合されていることを知り、嬉しく思いました。この記事では、ESOを試してみて、OKEでどのように使用できるかを見ていきます。



OKEへのExternal Secrets Operatorのインストール


まず、OCIコンソールのクイック作成か、https://github.com/oracle-terraform-modules/terraform-oci-oke を使って、OKEクラスタを作成します。これでCloud Shellやterraform-oci-okeモジュールのoperator hostを使って、kubectlやhelmコマンドを実行できるようになります。


helm チャートで ESO をインストールしてみましょう。

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


OCI Vaultで使用するためのESOの設定


instance_principalを使用しない場合、秘密鍵とFingerprintを保持するためにyamlファイルにKubernetes secretを作成します。

apiVersion: v1
kind: Secret
metadata:
name: pk-fp
labels:
type: oracle
type: Opaque
stringData:
privateKey: |
-----BEGIN RSA PRIVATE KEY-----
abcdefg1234567890/+-
-----END RSA PRIVATE KEY-----
fingerprint: ab:cd:ef:gh:12:34


シークレットの作成

kubectl create -f pk-fp.yaml


これでSecretStoreを作成することができます。

apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
name: alivault
spec:
provider:
oracle:
vault: # The vault OCID
region: # The vault region
auth:
user: # A user OCID
tenancy: # A user's tenancy
secretRef:
privatekey:
name: pk-fp
key: privateKey
fingerprint:
name: pk-fp
key: fingerprint


N.B. instance_principalsを使う場合は、authから最後までを削除してください。また、動的グループを作成し、ワーカー・ノードを追加する必要があります。最後に、OCI Vaultで作成するキーを動的グループに使用させるためのポリシーも作成する必要があります。

kubectl create -f oci-secret-store.yaml



ExternalSecret の作成


では、ESO を使って ExternalSecret を作成してみましょう。

apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: oci-secret
spec:
refreshInterval: 0.03m
secretStoreRef:
kind: SecretStore
name: alivault # Must match SecretStore on the cluster
target:
name: my-oke-secret # Name for the secret on the cluster
creationPolicy: Owner
data:
- secretKey: key
remoteRef:
key: my-eso-secret


my-eso-secretは、Vault内のOCIシークレットの名前です。



この場合、単にプレーンな内容("aSecretInSiV")を持つだけなので、上記のようにデータを使用すれば、ExternalSecretを作成することができます。

kubectl create -f ext-secret.yaml


ExternalSecretの入手

kubectl get es
NAME STORE REFRESH INTERVAL STATUS
oci-secret alivault 0.03m SecretSynced


シークレットが同期されたことが確認できます。このネームスペースのシークレットを一覧にしてみましょう。

kubectl get secrets
NAME TYPE DATA AGE
default-token-mnpsm kubernetes.io/service-account-token 3 41m
my-oke-secret Opaque 1 108s
pk-fp Opaque 2 10m


my-oke-secretが作成されたことが確認できます。それでは、シークレットの中を覗いてみましょう。

kubectl get secret my-oke-secret -o yaml
apiVersion: v1
data:
key: YVNlY3JldEluU2lW
immutable: false
kind: Secret
metadata:
annotations:
reconcile.external-secrets.io/data-hash: cff53a4bddfc2d04ea50e6d0da2c2868
creationTimestamp: "2022-06-01T02:11:43Z"
name: my-oke-secret
namespace: default
ownerReferences:
- apiVersion: external-secrets.io/v1beta1
blockOwnerDeletion: true
controller: true
kind: ExternalSecret
name: oci-secret
uid: 0039c7ab-91c2-4e15-acc7-f8de87ba1254
resourceVersion: "9117"
uid: 3074d172-078f-4214-9f21-a6bc69aae182
type: Opaque


キーが作成されたことが確認できます。これを抽出して、OCI Secretで作成したものと一致するかどうか確認してみましょう。

kubectl get secret my-oke-secret -o json | jq -r ."data.key" | base64 -d
aSecretInSiV


素晴らしい これは一致します!



シークレットを更新


では、更新を扱えるかどうか見てみましょう。OCI Secretで、新しいバージョンを作ってみましょう。



バージョン2がアクティブになり、現在の状態になるのを待って、もう一度上記のコマンドを実行し、シークレットを抽出します。

kubectl get secret my-oke-secret -o json | jq -r ."data.key" | base64 -d
SecretVersion2


Kubernetes Secret の値が更新されました。



クラスタ内の他のアプリケーションでESOを使用


ESO を使って、クラスタ内で動作している他のアプリケーションにシークレットを注入する方法を見てみましょう。今回は、Grafanaにパスワードを注入してみます。


Grafanaのhelmレポを追加します。

helm repo add grafana https://grafana.github.io/helm-charts
helm show values grafana/grafana > grafana.yaml


grafana.yamlを編集し、Administrator credentialsセクションを見つけます。

admin:

  ## Name of the secret. Can be templated.
existingSecret: "grafana-in-eso"
userKey: admin-user
passwordKey: admin-password

既存のSecretを上記のように変更します(または、任意の値に変更します)。


次に、OCI Vaultで以下のようにシークレットを作成します。



以上でExternalSecretを作成することができました。

apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: oci-secret
spec:
refreshInterval: 0.03m
secretStoreRef:
kind: SecretStore
name: alivault
target:
name: grafana-in-eso
creationPolicy: Owner
dataFrom:
- extract:
key: grafana


それでは、Grafanaをデプロイしてみましょう。

helm install grafana grafana/grafana -f grafana.yaml


Grafanaポッドにポートフォワード

export POD_NAME=$(kubectl get pods --namespace default -l "app.kubernetes.io/name=grafana,app.kubernetes.io/instance=grafana" -o jsonpath="{.items[0].metadata.name}")
kubectl --namespace default port-forward $POD_NAME 3000


OCI Vaultで作成した値が代わりに使用されていることに注意してください。ログインできるようになりました。


ここで、管理者のユーザー名とパスワードを変更したいとします。OCI Secretで新しいバージョンを作成します。



アクティブになったら、再度ログインしてください。



これは失敗します。理由は、Grafanaのポッドを作成する際に、シークレットを読み込んで、シークレットからadmin-usernameとadmin-passwordの値を使用し、設定ファイルに保存しているからです。そのため、今はまだOCI SecretとKubernetes secretの値が変更されていても、Grafanaはそのことを認識していないのです。


新しい値を使用するためには、このファイルを更新する必要があります。GrafanaのREST APIを使うこともできますが、Grafanaにシークレットの変更を監視するリスニングメカニズムがあるかどうかはわかりません(将来的に調査する必要があります)。今のところ、ユーザー名とパスワードの再読み込みを強制する最も簡単な方法は、Grafanaポッドを削除してKubernetesによる再作成を強制することです。

kubectl delete pod $POD_NAME


新しいポッドが作成されているのがわかると思います。

kubectl get pods
NAME READY STATUS RESTARTS AGE
grafana-788976bc4c-q2swm 0/1 ContainerCreating 0 8s


READYになるのを待って、バージョン2のシークレットで使用した値でポートフォワードしてください。これで、Grafanaにログインできるようになります。


注意:これはGrafanaのユーザー名とパスワードの更新方法として推奨されるものではありません。この例のポイントは、アプリケーションでESOを介してOCI Vaultからシークレットを再読み込みすることを示すことです。



まとめ


External Secrets Operatorは、OCI OKEをOCI Vaultと統合して使用するための優れた方法です。OKEとOKEで動作するアプリケーションの両方が、ESOを使用してOCI Vaultから機密データを取得することができます。


この投稿がお役に立てれば幸いです。


議論したいですか?私たちの公開Slackチャンネルに参加してください。


コメント

このブログの人気の投稿

Oracle RACによるメンテナンスのためのドレインとアプリケーション・コンティニュイティの仕組み (2023/11/01)

Oracle APEXのInteractive Gridで、Oracle Formsと比較して、重複行の検証を制御/通過させる方法 (2022/07/21)

Oracle APEX 24.1の一般提供の発表 (2024/06/17)