Kubernetesで機密情報を管理する際、external-secretsというオペレータを使用することで、AWS Secrets Managerなどの外部シークレットプロバイダーと連携できます。
一般的な使用方法では、AWS Secrets Managerに保存された機密情報をKubernetesのSecretとして同期します。一方で、今回紹介するPushSecret
を使うと、逆方向の同期、つまりKubernetesのSecretをAWS Secrets Managerに同期することができます。
この記事では、PushSecret
の基本的な使い方を紹介します。
前提条件
external-secretsのインストール
まず、external-secretsをHelmを使用してインストールします:
helm repo add external-secrets https://charts.external-secrets.io
helm install external-secrets \
external-secrets/external-secrets \
-n external-secrets \
--create-namespace
AWS認証情報の設定
AWSの認証情報を環境変数に設定し、正しく設定されているか確認します:
export AWS_ACCESS_KEY_ID=xxxx
export AWS_SECRET_ACCESS_KEY=xxxx
export AWS_REGION=ap-northeast-1
# 認証情報の確認
aws sts get-caller-identity
次に、この認証情報をKubernetesのSecretとして保存します:
kubectl create secret generic aws-credentials \
--from-literal=access-key-id=${AWS_ACCESS_KEY_ID} \
--from-literal=secret-access-key=${AWS_SECRET_ACCESS_KEY}
SecretStoreの設定
AWS Secrets Managerに接続するためのSecretStore
を作成します:
apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
name: aws-secretsmanager
namespace: default
spec:
provider:
aws:
service: SecretsManager
region: ap-northeast-1
auth:
secretRef:
accessKeyIDSecretRef:
name: aws-credentials
key: access-key-id
secretAccessKeySecretRef:
name: aws-credentials
key: secret-access-key
kubectl apply -f secret-store.yaml
PushSecretの設定
KubernetesのSecretをAWS Secrets Managerに同期するためのPushSecret
を作成します:
apiVersion: external-secrets.io/v1alpha1
kind: PushSecret
metadata:
name: pushsecret-example
namespace: default
spec:
# 同期時にプロバイダーの既存のシークレットを上書き
updatePolicy: Replace
# PushSecret削除時にプロバイダーのシークレットも削除
deletionPolicy: Delete
# 再同期の間隔
refreshInterval: 10s
# シークレットをプッシュするSecretStore
secretStoreRefs:
- name: aws-secretsmanager
kind: SecretStore
# 同期対象のSecret
selector:
secret:
name: my-secret
# 同期するキーの設定
data:
- match:
secretKey: foo # Secretのキー
remoteRef:
remoteKey: my-secret-foo # AWS Secrets Managerのシークレット名
metadata:
secretPushFormat: string
kubectl apply -f push-secret.yaml
動作確認
1. Secretの作成
まず、同期対象のSecretを作成します:
kubectl create secret generic my-secret \
--from-literal=foo=bar
AWS Secrets Managerに同期されたことを確認します:
aws secretsmanager get-secret-value \
--secret-id my-secret-foo
次のようなレスポンスが返ってくれば成功です:
{
"ARN": "arn:aws:secretsmanager:ap-northeast-1:000000000000:secret:my-secret-foo-rUBCkr",
"Name": "my-secret-foo",
"VersionId": "00000000-0000-0000-0000-000000000001",
"SecretString": "bar",
"VersionStages": [
"AWSCURRENT"
],
"CreatedDate": "2024-11-14T09:50:34.787000+09:00"
}
2. Secretの更新
Secretの値を更新してみます:
kubectl create secret generic my-secret \
--from-literal=foo=baz \
--dry-run=client -o yaml | kubectl apply -f -
AWS Secrets Managerで値が更新されたことを確認します:
aws secretsmanager get-secret-value \
--secret-id my-secret-foo
SecretString
がbar
からbaz
に変更されていることが確認できます:
{
"ARN": "arn:aws:secretsmanager:ap-northeast-1:000000000000:secret:my-secret-foo-rUBCkr",
"Name": "my-secret-foo",
"VersionId": "00000000-0000-0000-0000-000000000002",
"SecretString": "baz",
"VersionStages": [
"AWSCURRENT"
],
"CreatedDate": "2024-11-14T10:03:41.913000+09:00"
}
3. 削除時の動作確認
Secretを削除してみます:
kubectl delete secret my-secret
この時点では、AWS Secrets Managerのシークレットは削除されません。
次に、PushSecretを削除します:
kubectl delete pushsecret pushsecret-example
この操作により、AWS Secrets Managerのシークレットも削除されます:
aws secretsmanager list-secrets
{
"SecretList": []
}
クリーンアップ
external-secretsのPushSecret
を削除しただけでは、my-secret-foo
はAWS Secrets Managerに「削除予定」として残っているので、AWS Secrets Managerのシークレットの即時削除を実施します:
aws secretsmanager delete-secret \
--secret-id my-secret-foo \
--force-delete-without-recovery
external-secretsの削除:
helm uninstall external-secrets -n external-secrets
AWS認証情報の削除:
kubectl delete secret aws-credentials
まとめ
external-secretsのPushSecret
を使うことで、KubernetesのSecretをAWS Secrets Managerに同期できることを見てきました。この機能は以下のような用途に活用できると思います。
- Kubernetes上で管理している機密情報を、他のAWSサービスと共有する
- AWS Secrets Manager経由によるKubernetesクラスター間でのSecret共有
- KubernetesのSecretのバックアップをAWS Secrets Managerに保存する
今回は、external-secrets × AWS Secrets Managerの組み合わせでやってみましたが、他にも様々なプロバイダーをSecretStoreを提供しています。プロバイダーの中にはKubernetesもあって、個人的に特に気になっているところです。Kubernetesクラスター間のSecretの直接的な同期ができるのか試してみて、また記事にしてみようと思います。