本記事は 虎の穴ラボ Advent Calendar 2023 14日目の記事です。
- 本記事のテーマは「HashiCorp Vault でのシークレット管理」です!
- 前回はY.N.さんによる「モダンなshell 「Nushell」 を触ってみる」でした。
- 次回はgodanさんによる「Akihabara入門 at akihabara」です。ご期待ください!
はじめに
こんにちは。虎の穴ラボ株式会社のかなざわです。
KubernetesのSecretリソースで管理される秘密情報は、マニフェスト記載のままだとbase64でエンコードされているのみのため、簡単に復号できてしまいます。そのような情報をGitなどのVCSへコミットして管理する場合は、第三者が復号できないように気をつける必要があります。
個人で構築し利用しているKubernetesでも、GitでSecretを管理する場合はSealedしたものをコミットするようにしていました。第三者が復号できないという観点ではこの方法でもよいのですが、他の管理方法として HashiCorp Vaultを使用する方法もよさそうでしたので、今回試してみました。
HashiCorp Vault とは
HashiCorp VaultはHashiCorp社で開発されているシークレット管理ソリューションです。2023年12月現在、以下の形で利用できるものとなっています。
- 無償版 (Vault OSS)
- 商用版 (Hashicrop Vault Enterprise)
- マネージド版 (HCP Vault)
以下のようなことが機能として存在しています。ユーザーもしくはアプリケーションに対して必要とされるシークレットをアクセス制御に基づき提供する機能と理解しています。
- 秘密情報の集中管理
- 秘密情報を暗号化して保存
- 秘密情報へのアクセスを制御(認証認可)
- 秘密情報のローテーション
アクセス手段
GUIが提供されます。ブラウザからアクセスして、秘密情報やアクセスする権限を設定できます。
また、CLIも提供されています。vault
コマンドを利用してコマンドラインからVaultを操作することが可能です。APIも提供されているため、例えばアプリケーションから秘密情報の取得や登録・暗号化といったことが可能になります。
環境情報
今回はKubernetesにVault(Vault OSS)をデプロイし内容を見ていきます。KubernetesとVault OSSの環境情報は以下となります。公式ページにサポートされているKubernetesバージョンの記載があるのでそちらも参考にします。
- Kubernetes
HW: Raspberry Pi4 Model B x3 (ControlNode x1, WorkerNode x2) Version: v1.25.4
- Vault OSS
Version: 1.15.2
Kubernetes へのデプロイ
Vault OSSをKubernetesへデプロイします。今回はHelmを利用してデプロイを進めていきます。Helmのページを参考にして行います。Helmを利用してデプロイが進められるように、事前にHelmのインストールを実施しておきます。
Helmのリポジトリリストに今回のリポジトリを加えます。リポジトリを加えた後にアップデートを行い、最新化しておきます。
❯ helm repo add hashicorp https://helm.releases.hashicorp.com "hashicorp" has been added to your repositories ❯ helm repo update Hang tight while we grab the latest from your chart repositories... ...Successfully got an update from the "hashicorp" chart repository Update Complete. ⎈Happy Helming!⎈
早速デプロイを行います。-n vault --create-namespace
の引数を付け、今回用のnamespaceであるvault
も同時に作成しています。
❯ helm install vault hashicorp/vault -n vault --create-namespace NAME: vault LAST DEPLOYED: Sat Dec 2 15:50:07 2023 NAMESPACE: vault STATUS: deployed REVISION: 1 NOTES: Thank you for installing HashiCorp Vault! Now that you have deployed Vault, you should look over the docs on using Vault with Kubernetes available here: https://developer.hashicorp.com/vault/docs Your release is named vault. To learn more about the release, try: $ helm status vault $ helm get manifest vault
デプロイされたようです。Podがデプロイされたかどうかを確認します。
❯ kubectl get pod -n vault NAME READY STATUS RESTARTS AGE vault-0 0/1 Pending 0 11m vault-agent-injector-dc89c4549-crdql 1/1 Running 0 11m
vault-0
がPending
となっており、正常にデプロイされていませんでした。ログを確認します。
- PersistenceVolumeClaimログ
Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal FailedBinding 27s (x922 over 3h50m) persistentvolume-controller no persistent volumes available for this claimand no storage class is set
PVCのログから、StorageClassとPersistenceVolumeを作成していないことが原因のように見えました。一度、今回のデプロイをhelm uninstall
で削除したあとに、上記2つのリソースを作成した上で、helm install
を行います。--set
でstorageClassの名前を指定し、作成したリソースを参照させるようにしました。
❯ helm install vault hashicorp/vault --set "server.dataStorage.storageClass=vault-storage" -n vault --create-namespace
再びPodステータスを確認すると、STATUS
がRunning
となりました。vault-0
のREADY
が0/1
となっていることは問題ありません。
❯ kubectl get pod -n vault NAME READY STATUS RESTARTS AGE vault-0 0/1 Running 0 35s vault-agent-injector-dc89c4549-t5wkr 1/1 Running 0 35s
Vaultの初期化とUnseal
Vaultの起動直後はSealedという状態となっており使用することができません。使用できるようにするには、初期化時に払い出されるUnsealキーを渡します。
Vaultは秘密情報を登録するときに暗号化して保存されます。暗号化に用いるキーも、別のキー(ルートキー)によって暗号化されています。そして、このルートキーもまた別のキー(シェアリングキー)で暗号化されています。このシェアリングキーがUnsealキーとなり、Unsealキーの提供でルートキーが復号できる(データの暗号化・復号化が可能になった)ようになることを、Unsealingと呼び実施しています。公式ではこちらのページで説明されています。
初期化および必要な認証情報を生成するために、pod 内でvault operator init
のコマンドを実施し処理を進めます。
❯ kubectl exec -it vault-0 -n vault -- vault operator init Unseal Key 1: WEpA+0/QSBZi78aXRFnaUDMGrD+2ttUwRjm3pIwiD9SH Unseal Key 2: xmcGOmd4Xum7j6E1qhCOs+rpxJoE1NWFJu7pzs5Gnnlx Unseal Key 3: 147ibpMgnjTxQQeXP+uZZCetKoiiWOT+gvp2uR2aZJpR Unseal Key 4: sc67bm1+xGUwfS7TxJmCoWWqms7dznJHr/YMck9kkyNF Unseal Key 5: 7pOwuFatKykqbiU4VHQbB6odtFpcGqnhYJ7izYwzVnrX Initial Root Token: hvs.1IoD1jqLjsQTNmPGhUl1RA1B Vault initialized with 5 key shares and a key threshold of 3. Please securely distribute the key shares printed above. When the Vault is re-sealed, restarted, or stopped, you must supply at least 3 of these keys to unseal it before it can start servicing requests. (略)
払い出されたUnsealキーを使用してUnsealingを行います。基本的に3回行う(Unsealキーを3つ使用する)ことでVaultが使用できるようになります。下記のように、Sealed
の値がfalse
となったことを確認します。
❯ kubectl exec -it vault-0 -n vault -- vault operator unseal ❯ kubectl exec -it vault-0 -n vault -- vault operator unseal ❯ kubectl exec -it vault-0 -n vault -- vault operator unseal Unseal Key (will be hidden): Key Value --- ----- Seal Type shamir Initialized true Sealed false Total Shares 5 Threshold 3 Version 1.15.2 Build Date 2023-11-06T11:33:28Z Storage Type file Cluster Name vault-cluster-c65d5f88 Cluster ID ffebfd89-df37-7323-47bc-c8496cd5aa0a HA Enabled false
ここで再びPodステータスを確認すると、vault-0
のREADY
が1/1
となりました。
❯ kubectl get pod -n vault NAME READY STATUS RESTARTS AGE vault-0 1/1 Running 0 10m vault-agent-injector-dc89c4549-t5wkr 1/1 Running 0 10m
Vaultへの秘密情報の登録
Vaultへの認証
Vaultの使用準備が整いましたので、Vaultへ秘密情報を登録していきます。
登録方法は、Vaultが動作しているPodへシェルログインのほかに、Kubernetesの外からvault
コマンドを使用する方法があります。vault
コマンドを使用してアクセスする場合はvault
コマンドのインストールおよび、以下のようにServiceリソースのポートフォワードなどを行い、遠隔からアクセスできるようにしてあげる必要があります。
$ kubectl port-forward service/vault -n vault 8200:8200
今回はブラウザからアクセスし設定を行います。上記の設定を施した状態で、http://127.0.0.1:8200
とアクセスすると、Vault UIにアクセスできます。Vaultの初期化時に払い出されたRootTokenを入力してログインします。
Vault への秘密情報の登録
秘密情報の形式を指定して登録できるように有効化したあと、秘密情報を登録します。Vaultでは、こちらのページに記載されているようなさまざまな秘密情報の形式に対応しています。
今回はKeyVaule形式の秘密情報を有効化します。メニューの「Secret Engines」から「Enable new engine」と進み、秘密情報の形式をkvを選択して「Next」をクリックします。「Path」をkv-secret
として「Enable Engine」を選択します。
秘密情報を登録します。先程作成された「secret」をクリックし「Create Secret」と進み、
- Path for this secret:
info
- Secret data:
SECRET_KEY
とSECRET_VALUE
を入力して、「Save」をクリックします。なおPath
は空欄で設定できません。
Kubernetesから秘密情報を参照する
Vaultに秘密情報を登録したので、Kubernetesリソース(Pod)から秘密情報が参照できることを確認します。
Kubernetes Auth Method のリソースを作成する
まずは、KubernetesからVaultにアクセスするための準備を行います。Kubernetesに認証用のサービスアカウントを作成します。
❯ kubectl create sa app -n default serviceaccount/app created
続いてVaultへ認証方法を設定します。Vaultには認証方法が複数用意されておりその中のKubernetesを有効化します。あわせて秘密情報に対する権限も設定します。
メニューの「Access」から「Authentication Methods」と進み、「Enable new method」をクリックします。そこで「Kubernetes」を選択して「Next」をクリックします。Pathを「kubernetes」として、「Enable Method」を選択します。Configuration画面で、Kubernetes hostの情報を入力して「Save」をクリックします。
続いて、KubernetesからVaultにアクセスする際の権限をポリシーで作成します。メニューの「Policies」から、「Create ACL policy」と進み、
- Name:
allow-secret-access
- Policy: 以下参照
を入力し、「Create policy」をクリックします。
path "kv-secret/data/info" { capabilities = ["read"] }
最後にこのポリシーを先程の認証情報に適用します。「Authentication Methods」の「Kubernetes」を選択し、「Create role」をクリックします。
- Name: kubernetes-role
- Bound service account names: app
- Bound service account namespaces: default
- Generated Token's Policies: allow-secret-access
- Generated Token's Initial TTL: 86400
- Generated Token's Type: default
を入力して「Save」をクリックします。Tokensをクリックすると、追加設定項目があるため忘れずに設定します。
Kubernetesのリソースから秘密情報を参照する
それではKubernetesリソースから秘密情報を参照してみます。Podをデプロイし意図した秘密情報が設定されていることを確認します。
Podのマニフェストはこちらを使用します。Agent Sidecar Injector を使用しており、具体的な設定はこちらを参考に実施しています。
Podデプロイ後に、Podにシェルログインを行います。/vault/secrets/info.txt
を閲覧すると秘密情報が記載されていることが確認できました。
❯ kubectl apply -f vault-test-pod.yaml pod/vault-test-pod created ❯ kubectl exec -it vault-test-pod -c app -- /bin/bash root@vault-test-pod:/# cat /vault/secrets/info.txt SECRET_KEY: SECRET_VALUE
まとめ
KubernetesにおけるSecretの管理方法として、Vaultを使用する方法を見てきました。
Vaultに秘密情報を管理するようにしたため、秘密情報を記載したマニフェストファイルは無くなり漏洩や第三者による復号の可能性が減少したことがわかりました。
オンプレやコンテナによるVaultの運用を考えると、別途トークンやポリシー管理などを考慮する必要があります。VaultにはHashiCorp社が運用するマネージドサービスであるHCP Vaultも存在しているため、Vault利用検討時における一つの選択肢となります。
今後見たい箇所
今回は書ききれなかった箇所も含めた、今後見ていきたい内容を記載します。
- Vaultへのログイン方法
今回はRootTokenによるトークンログインを実施しましたが、Vaultは外部IdPとの連携によるログインが可能です。
- 秘密情報のローテーション
Vaultには秘密情報を暗号化し管理する機能の他に、秘密情報をローテーションする機能が存在します。
- 秘密情報を更新した場合の反映
Podをデプロイ後にVault GUIなどから秘密情報が更新された場合、今回の方法ですとPod内の秘密情報は置き換わりません。しかしながら、HashiCorp社からリリースされたVault Secrets Operatorを用いることで可能となります。
今回はKubernetesとVault間の秘密情報の共有中心の内容となりましたが、こちらの内容も引き続き見ていきたいと思います。
採用情報
虎の穴では一緒に働く仲間を募集中です!
この記事を読んで、興味を持っていただけた方はぜひ弊社の採用情報をご覧下さい。
カジュアル面談やエンジニア向けイベントも随時開催中です。ぜひチェックしてみてください。 toranoana-lab.co.jp