はじめに
OCIのContainer Engine for Kubernetes (OKE)において、Secretを安全に管理するためのツールとしてExternal Secret Operatorの設定方法を確認します。
External Secret Operatorは、外部プロバイダーに保存された情報からKubernetesのSecretを作成するためのCRDです。
OCIの場合は、Vaultサービスを使用します。
使用したクラスタです。
$ kubectl get node
NAME STATUS ROLES AGE VERSION
10.0.10.75 Ready node 39h v1.23.4
設定方法
以下を参考にしました。
キーとシークレットの作成
Vaultにキーとシークレットを作成します。Vaultはあらかじめ作成済みです。
なお、OCI Vaultのシークレットはカタカナ、KubernetesリソースのSecretはアルファベットで記載します。
作成したキーを指定して、シークレットを以下のように作成します。
External Secret Operatorのデプロイ
以下を参考にHelmを使用してデプロイします。
$ helm repo add external-secrets https://charts.external-secrets.io
"external-secrets" has been added to your repositories
$ helm repo list
NAME URL
external-secrets https://charts.external-secrets.io
$ helm install external-secrets \
> external-secrets/external-secrets \
> -n external-secrets \
> --create-namespace
NAME: external-secrets
LAST DEPLOYED: Tue May 31 07:27:26 2022
NAMESPACE: external-secrets
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
external-secrets has been deployed successfully!
In order to begin using ExternalSecrets, you will need to set up a SecretStore
or ClusterSecretStore resource (for example, by creating a 'vault' SecretStore).
More information on the different types of SecretStores and how to configure them
can be found in our Github: https://github.com/external-secrets/external-secrets
デプロイされたリソースを確認します。
$ kubectl get all -n external-secrets
NAME READY STATUS RESTARTS AGE
pod/external-secrets-7bc8757d6-7wb2r 1/1 Running 0 2m27s
pod/external-secrets-cert-controller-55754f89fb-mqrxb 1/1 Running 0 2m27s
pod/external-secrets-webhook-67965bb887-rpvtw 1/1 Running 0 2m27s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/external-secrets-webhook ClusterIP 10.96.204.196 <none> 443/TCP 2m27s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/external-secrets 1/1 1 1 2m28s
deployment.apps/external-secrets-cert-controller 1/1 1 1 2m28s
deployment.apps/external-secrets-webhook 1/1 1 1 2m28s
NAME DESIRED CURRENT READY AGE
replicaset.apps/external-secrets-7bc8757d6 1 1 1 2m28s
replicaset.apps/external-secrets-cert-controller-55754f89fb 1 1 1 2m28s
replicaset.apps/external-secrets-webhook-67965bb887 1 1 1 2m28s
ポリシーの作成
External Secret Operatorはインスタンスプリンシパルを使用して認証しますので、動的グループに以下のポリシーを設定します。
KubernetesのServiceAccountでも認証できるようですが、未確認です。
Secretの作成
VaultにAPIアクセスするために、APIキーの秘密キーとフィンガープリントを取得し、Secretを作成します。
以下のマニフェストファイルを作成して、Secretを作成します。
apiVersion: v1
kind: Secret
metadata:
name: oracle-secret
labels:
type: oracle
type: Opaque
stringData:
privateKey: |-
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDR/ahwU01vyJZH
#### insert you PEM certificate ####
-----END PRIVATE KEY-----
fingerprint: 03:06:00:00:00:00:00:00:00:00:00:00:00:00:00:00
$ kubectl apply -f oracle-secret.yaml
secret/oracle-secret created
$ kubectl describe secret oracle-secret
Name: oracle-secret
Namespace: default
Labels: type=oracle
Annotations: <none>
Type: Opaque
Data
====
fingerprint: 47 bytes
privateKey: 1703 bytes
Secret Storeの作成
外部プロバイダーに認証するためのSecret Storeを作成します。
apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
name: secretstore-auth
spec:
provider:
oracle:
vault: ocid1.vault.oc1.uk-london-1.xxxxxxxxxxxxxxxxxxxxx # vault OCID
region: uk-london-1 # vault region
auth:
user: ocid1.user.oc1..xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx # user OCID
tenancy: ocid1.tenancy.oc1..xxxxxxxxxxxxxxxxxxxxxxxxxxx # tenancy OCID
secretRef:
privatekey:
name: oracle-secret
key: privateKey
fingerprint:
name: oracle-secret
key: fingerprint
$ kubectl apply -f authSecretStore.yaml
secretstore.external-secrets.io/secretstore-auth created
$ kubectl get ss
NAME AGE STATUS
secretstore-auth 22s Valid
External Secretの作成
Secretを作成するためのExternal Secretを作成します。
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: ocisecret
namespace: default
spec:
refreshInterval: 0.03m # 外部プロバイダーに対してSecretを更新する頻度
secretStoreRef:
kind: SecretStore
name: secretstore-auth # Secret Store名
target:
name: k8s-secret # External Secretによって作成されるSecret名
creationPolicy: Owner
data:
- secretKey: oci-secret # secretのKey-Valueの「Key」
remoteRef:
key: oke-secret01 # OCI Vaultのシークレット名
$ kubectl apply -f externalSecret.yaml
externalsecret.external-secrets.io/ocisecret created
$ kubectl get es
NAME STORE REFRESH INTERVAL STATUS
ocisecret example-instance-principal 0.03m SecretSynced
External SecretによってSecretが作成されています。
$ kubectl get secret
NAME TYPE DATA AGE
default-token-zftfg kubernetes.io/service-account-token 3 23h
k8s-secret Opaque 1 77s
oracle-secret Opaque 2 5m28s
$ kubectl describe secret k8s-secret
Name: k8s-secret
Namespace: default
Labels: <none>
Annotations: reconcile.external-secrets.io/data-hash: 8b6c7979477db7cffa9a66740dc10ca4
Type: Opaque
Data
====
oci-secret: 8 bytes
Secretの値をデコードして確認します。
$ kubectl get secret k8s-secret -o jsonpath='{.data.oci-secret}'| base64 -d
aabbccdd
OCI Vaultのコンソール画面でシークレットの値を更新します。
再度、Secretの値をデコードして確認します。
$ kubectl get secret k8s-secret -o jsonpath='{.data.oci-secret}'| base64 -d
xxyyzz
Vaultのシークレットに合わせてSecretの値が更新されていることが確認できます。