ヤフー社内のKubernetes環境における、シークレットデータの扱いに関して紹介します。
ヤフーでは、Secrets Store CSI Driver(以下、SSCD)というプロジェクトを、社内のKubernetesプラットフォーム向けにエコシステムとして導入しました。なぜ私たちがSSCDをエコシステムとして導入する必要があったのかを説明します。
社内データ保護の一環として、ヤフーでは自社開発のSecrets Managerを運用しています。各シークレットデータの保護に加え、RevokeやバージョンコントロールなどパブリッククラウドにあるSecrets Managerと同様の機能を有しています。ストアしているシークレットデータは、データベースのパスワードやAPIキー、暗号化キーなど多岐にわたり、それらをSecrets Managerで一元管理しています。
社内にはPaaS、FaaSといったものから、Kubernetesベースの自社開発プラットフォームなども存在し、開発者はサービスの要件や規模に応じて自由に構成を決定できます。そのため、大量のアプリケーションからリクエストされることを想定し、大規模にSecrets Managerを展開しています。認証認可については、AthenzというOSSと連携することで適切なアクセスコントロールを実現しています。
最近では、ヤフー社内でもKubernetesでの開発が主流となりつつあるため、Kubernetes内におけるシークレットデータの扱いに関してもアップデートする必要がありました。しかし、Secrets ManagerとKubernetes環境との連携が十分でなく、より利便性と安全を両立したプラットフォームが求められていました。またプラットフォームによっては開発者のニーズがさまざまであるため、それらをカバーできるようなシークレット管理のサービスを提供することが必要でした。
開発者は、開発時にも任意のタイミングでSecrets Managerからデータを取り出しますが、何かしらのサポートや仕組みがないとアプリケーションで利用するまでの間のセキュリティ担保は開発者の責任になってしまい、セキュリティリスクを背負った状態でデータを扱う必要があります。数多くの利用者がいるため、利用者自身で行っている全てのシークレット管理の把握は不可能ですが、シークレットデータの安全性を担保し開発者の責任をなるべく減らすことも責務です。
エコシステムができる前は、社内の開発者は大別して3つの方法でシークレットデータを取り扱っていました。
1つ目がKubernetesのSecret Resourceを使う方法。2つ目、3つ目にヤフー特有の方法として、sidecarを使う方法と、client libraryを使う方法です。これらの3つの方法に共通した課題は、開発者側に責任を負わせてしまっており、生産性が低くなってしまっていることでした。
社内プライベートクラウドにおけるシークレットデータの扱い
ここからは上述した3つの方法における問題点を挙げていきます。
1つ目は、Secrets Resourceを使ったシークレットデータの管理について。あるアプリケーションがシークレットデータを必要としたとき、それをSecrets Resourceとして作成し、対象のPodはそのリソースを環境変数だったり、ボリュームマウントをしたりして扱います。
どこからシークレットデータを持ってくるかはいろいろなシチュエーションが考えられますが、多くはCI/CD上でシークレットデータをマニフェストに埋め込んで作成したり、開発者自身でマニフェストを管理したりしている場合も想定されます。作成されたシークレットデータは、Kubernetes Secretsの完全性と機密性を担保する唯一のデータストアであるetcd内に保存されます。
一方で、Secrets Resourceにはいくつかの欠点があります。その中で代表的なものがetcdの暗号化です。通常では平文でデータをストアするので、機密性の担保のためetcdの暗号化を有効にする必要がありますが、クラスタ管理者が暗号化鍵の管理をすることになります。ヤフーでは多くのクラスタが存在するため、クラスタ管理者にかなりの負担と責任を負わせてしまいます。
また、Secrets Managerからシークレットデータを取得する際にはマニフェストファイルに埋め込むなどのステップが発生するため、Secrets Resourceとして使えるようになるには一手間加える必要があります。CI/CD上でシークレットデータを加工する際は、そのデータがログに出ないようにする必要があることから、開発者側の裁量によるところが大きいのも課題と言えます。
ローカルでシークレットデータを管理しているケースでは、安全性により配慮しなければなりません。この場合は、開発者自身で機密性を担保する必要があり、これを怠るとデータの漏えいにつながりかねません。加えて、Podを作成できる権限を持つ開発者はその内容を自由に見ることができるため、開発者の認証情報に関しても気を配る必要があります。
2つ目にsidecarを使う方法についての問題点を紹介します。sidecarはSecrets Managerと連携させるためのものであり、Pod内でsidecarと通信を行うことで、シークレットデータを扱うことができます。sidecarが代わりにデータを取得することで、開発者をシークレット管理の責務から解放できます。
なお、Secrets ManagerにはAthenzによるアクセスコントロールが伴うため、認証情報をSecrets Resourceとして置く必要があります。このことから、sidecarを使う方法では、根本的な問題が解決されていないのです。
また、sidecarがシークレットデータを取得するまで処理を待たなくてはならず、開発者自身で命令的な処理をどこかに追加する必要が出てきます。さらに、Pod数が増えるにつれてsidecarも増えるので、その分クラスタのリソースを浪費します。
3つ目はClient Libraryを使う方法です。アプリケーション自身が直接Secrets Managerからデータ取得を行うアプローチです。Client Libraryの仕様に従って実装すれば、簡単にSecrets Managerと連携でき、開発者側で直接シークレットデータを扱うことなく運用できます。
問題点としては、Client Libraryを使うための学習コストが挙げられます。ライブラリの仕様を満たすように実装しなければならないため、その分のコストもかかります。また、シークレットデータが取得できなかった場合に備えて、エラーハンドリングやネットワークエラーなどをアプリケーション内に実装する必要も出てきます。Client Libraryのバージョン管理とアップデート管理も必要です。
シークレットデータの管理を効率化し、開発に注力
エコシステムが導入される以前の環境では、それぞれのシークレットデータの扱い方が開発者依存になっていたり、プロセスが人によって異なっていたりしました。また、開発者側で一手間をかけないと安全が担保できずにいるのも問題でした。そのため、自動化をするか、何らかの仕組みを入れるといったサポートが必要であると考えました。
シークレット管理の負担を減らし、特別なsidecarやライブラリ、モジュールを必要としない環境を構築することで、開発者はアプリケーション開発に注力できる環境が理想です。
この実現のため、社内環境やセキュリティ施策、導入コストなどを加味しプライベートクラウドへのエコシステム導入を検討しました。さまざまなエコシステムを比較検討した結果、構成のシンプルさ、社内プラットフォームとの連携のしやすさを高く評価し、SSCDを採用することになりました。
開発者とクラスタ管理者の両者にメリットをもたらすSSCD
SSCDとは何かについて説明するまえに、CSI(Container Storage Interface)について触れておこうと思います。
CSIとは、コンテナ用ストレージを制御するAPI仕様です。この仕様に従って実装されたCSI Driverは、ストレージ内のデータが使えるよう、コンテナにストレージボリュームを接続します。ストレージベンダがCSI Driverを開発することで、対象ストレージとの連携が実現します。
CSIを満たしていればMesosやNomadといった異なるコンテナオーケストレーションでも、Kubernetesと同様の処理を実現することが可能です。CSI Driverのうち、外部のSecrets Managerからシークレットデータを取ってきて、コンテナにストレージボリュームとしてマウントするものがSSCDです。
SSCDは、CSI Driver本体と、別途実装が必要なProviderで構成されます。SSCDを使う際には、外部のSecrets Managerに対応したProviderが必要です。AWSやGCP、AzureなどのパブリッククラウドはそれぞれSecrets Managerを持っていますが、そのそれぞれに対応したProviderが存在するため、すぐにSSCDを使うことができます。
SSCDではCSI Driver本体の開発をする必要がなく、Providerの実装を行うだけで処理を実現できます。Provider自体の実装もシンプルで、提示されているインタフェースは2つのみとなっており、Secrets Managerとの連携がメインなため素早い実装が可能です。このように柔軟な構成になっているため、オンプレミスのSecrets Managerにも対応できます。
下図は、SSCD、Providerの動作を表したイメージ図です。SSCDとProviderはDaemonSetとしてデプロイされるため、各Worker Nodesに必ずセットで存在します。マウントが要求された際には、SSCDからProviderへリクエストがされ、シークレットデータを取得し対象のPodに取得データをマウントします。
ノードごとにSSCDとProviderが存在するため、Podは同じノード内のProviderによって、シークレットデータがマウントされます。Client Libraryやsidecarのように、Pod内でアクティブにシークレットデータを取得するのに対し、SSCDは開発者に見えないところでシークレットデータを取得します。つまり、プラットフォームレベルでシークレットデータの取得がサポートされるため、運用面での優位性はもちろん、セキュリティ担保のための仕組みを実装する手間もありません。
シークレットデータのマウントについてもう少し踏み込んで説明します。コンテナ起動前にSSCDがあらかじめtmpfs領域を作成し、シークレットデータの取得後、ファイルとしてそこに書き出します。これにより、ファイルを読み出すことで、シークレットデータを扱えます。Podが消えるとそのファイルは消えるため、使いまわすことはできず、データ漏えいリスクの面からも安心です。
SSCDの動作は、Secret Resourceと同じようなセキュリティ特性を持ちます。シークレットデータがtmpfs領域に配置されるため、ディスクストレージに書き込まれません。Secret Resourceでは、Kubernetes APIにアクセスできる権限があると読み出せる一方、SSCDはコンテナ内に閉じているため、機密性が高いといえます。
もう1つの利点として、クラスタ管理者の負担軽減が挙げられます。etcdに保存されないため、暗号鍵の管理から解放されるのです。開発者、クラスタ管理者の両者にメリットがあるのも特徴の1つです。
ここで、開発者側の利用例を紹介します。SSCDにはSecretProviderClassというCustom Resource Definitionがあり、これにSecrets Managerから取得したいシークレットデータの情報を記載します。このように、直接シークレットデータをマニフェストとして宣言する必要がないため、開発・運用の段階から安全性を担保できます。
一方で、マウントされたシークレットデータは自動的に更新されません。もし更新を反映したい場合には、Podをリスタートさせる必要があります。この制限は、マウントする動作がコンテナの起動前にのみ行われることに起因します。この挙動は、べき等性の担保という意味では正しい動作ですが、シークレットデータを自動的に更新したいというニーズには対応できません。
SSCDの社内エコシステムへの組み込みで利便性と機密性を両立
次に、SSCDをヤフー社内のエコシステムとしてどのように組み込んだのか説明します。
まずは、社内の各種プラットフォームとの連携についてです。Secrets Managerや認証プラットフォーム、Kubernetesプラットフォームは互いに協調し動作しているため、各プラットフォームにゆがみが生まれないように導入する必要がありました。とはいえ、Providerは柔軟な構成になっているため、連携に関しては問題がありませんでした。また、対象としているコンピューティングプラットフォームはベースがKubernetesなので、CSI Driverとしては特に大きな影響はありませんでした。
一方で、Secrets Managerとの連携には認証プラットフォームであるAthenzとの連携も必要です。Athenzとの連携では初めに認証情報を取得する必要があり、次にその認証情報を使い、対象のシークレットデータを取得し、最後にそのデータをボリュームに書き出します。社内のほとんどのコンピューティングプラットフォームがAthenzと連携しており、サービス単位で認証情報(X.509証明書)の払い出しが可能となっています。Kubernetes環境においては、Service Account単位に対応した認証情報が発行されるイメージです。
エコシステムは、この認証情報の発行の仕組みを踏襲しています。Providerがマウント対象のPodに対する認証情報を取得し、これを使ってSecrets Managerにリクエストを行います。つまり、アクセスコントロールはPod単位で行われます。
マウントがコンテナの起動前のみ行われるため、Podごとに認証情報とシークレットデータを都度リクエストする仕様となっています。認証情報については使いまわしをせず、認証情報とシークレットデータのやりとりがProvider内で、しかも開発者に見えないところで完結するため、より安全で機密性の高い仕組みと言えます。
ヤフー社内には、Kubernetes as a Serviceとして開発者にクラスタを与えるものもあれば、中央管理しているマルチクラスタをアプリケーション実行基盤とするものもあるなど、大小さまざまなクラスタが多数存在します。
これでもなお、SSCDの構成のシンプルさと、Providerが外部との連携を吸収していることから、プラットフォームの違いを気にせずエコシステムを導入することができました。この導入により、各コンピューティングプラットフォームでのシークレットデータの取得が、プラットフォームからサポートできるようになったので、開発者側はセキュリティを気にすることがなくなり、開発に集中できるようになりました。
社内に啓蒙活動を行いSSCDの拡大を目指す
エコシステム自体は一部のプラットフォームで本番環境として適用されていますが、社内での認知度はまだまだ低いため、今後もメリットを広く周知していきます。さらに、導入していないプラットフォームによっては、現状のエコシステムの形を保ったまま導入できるかどうかを検討しています。
SSCDは、シークレットデータをファイルにしてコンテナにボリュームマウントする特性上、環境変数として扱うことが不得意です。これに対し、SSCDには追加機能の一つにマウントしたシークレットデータをSecret Resourceとして作成する「Sync as Kubernetes Secret」があります。
Sync as Kubernetes Secretは、マウントするシークレットを従来通りのSecret Resourceとして扱えるため、環境変数への適用も容易にできます。しかし、マウントしたシークレットデータは、外部のリソースが変わったとしても自動更新されないため、更新する際にはそのSecret Resourceを消すなどの対処が必要です。こういった開発者の一手間は事故の原因になりかねないため、現在解決策を検討中です。
まとめ
最後に今回の話をまとめます。SSCDをエコシステムとしてプライベートクラウドに組み込むことで、開発者はシークレットデータの管理を意識することなく、より安全に実施できます。認証処理からシークレットデータ処理までをSSCDで一貫して行うことで、開発の段階からセキュアな状態が保たれます。それにより、アプリケーションの開発にリソースを回せるようになるため、生産性の向上も期待できます。
エコシステムとしてKubernetesプラットフォームに導入したことで、ヤフーの開発環境はより安全で、より利便性の高いものになりつつあります。同じ課題に悩みを持つ方は、ぜひSSCDを検討してみてください。
アーカイブ動画
こちらの記事のご感想を聞かせください。
- 学びがある
- わかりやすい
- 新しい視点
ご感想ありがとうございました
- 山口 勝也
- ソフトウェアエンジニア
- 社内のデータ保護領域を担当するチームに所属。業務では主にGo言語を使用。