ちょっと話題の記事

なぜ、Kubernetesを使う際にSecretを暗号化するのか?

2019.06.21

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

おはようございます、加藤です。
Kubernetesには、Secretリソースという物が存在しDBの認証情報など秘匿する必要があるデータを格納するのに使用されます。
しかし、このSecretリソースはBase64エンコードが行われているだけなので、Secretリソースへ読み込み権限があれば誰でもデコードして平文データを取得できてしまいます。
また、Secretリソースを作成する為のマニフェストファイルにも、記述されているので、これに対して読み込み権限があれば同様に平文データの取得が可能です。

Secretの暗号化はどの様に行うか

Secretの暗号化には、下記の様なツールを使う事が多いと認識しています。

sealed-secretsについては、概要程度の知識しかなく、触ったことが無い為、今回は触れません。導入する際は、ぜひ両方試して頂き検討頂くと良いと思います。

Vault Agent with Kubernetes | Vault - HashiCorp Learn

HashiCorp Vaultを使った方法もあるようですが、こちらは概要も把握できていないので、触れることができていませんm(_ _)m

上記の理由で、kubesecを例に上げて説明します。kubesecは、Secretリソースのマニフェストに対して、データ部分を暗号化/復号化が行えるツールです。

  • AWS Key Management Service
  • Google Cloud KMS
  • GnuPG

上記を使って暗号化/復号化が行えます。
利用フローを図に起こしてみました。

管理者(Secretを閲覧許可された人)が、このフローに従いk8sにSecretをデプロイします。
利用者(Secretを閲覧禁止された開発者)はGitHubへはアクセスができるが、Secretは暗号化されているので閲覧できないという環境が手に入ります。
認証・認可は、AWS Key Management Service(KMS)を使う場合だと、AWS Identity and Access Management (IAM)によって行われます。KMSへの権限があれば、復号化が可能といった制御が可能です。これは個別のキーを作成し権限を設定する事でグループ管理も可能です。(チームAはチームA管轄の暗号化/復号化のみできるなど) k8sのSecretリソースは、平文(正確にはBase64エンコード済)で保存されています。よって、k8sクラスタに対して少なくとも、Secretリソースへの読み取りは禁止する必要があります。

本当に暗号化する必要があるのか?

プロダクトで使用するマニフェストファイルは、そもそもパブリック公開せずプライベート設定で公開されているはずです。なぜ暗号化する必要があるのか個人的に考察してみました。

最初に、Secretが何処に所属するのかを明確にする必要があります。言葉だけでは厳しいので図に起こします。

なぜ情シスが図に出てくる理由は後で説明するので一旦スルーしてください。
あるプロダクトが存在し、その中には複数のサービスが存在しているという状況を想定します。この想定では2パターンのSecretが存在します。

  • サービス固有
    • Secret A, Secret B
  • プロダクト固有
    • Common Secret

サービス固有はサービスチームだけが、プロダクト固有はプロダクトチームだけが見れるのが、範囲を最小化できていて理想ですね。後は現実と、どう折り合いをつけるかです。

例えば、会社のメンバーからは全員に見えても良いと判断するならば、そもそも暗号化を行う必要はありません。リポジトリをプロダクトチームにしか公開していないなら、プロダクトチーム内には見えるけど、会社には見えないと当初は考えていました。
しかし、GitHubの契約や最上位の権限を持っているのは情シスというパターンが多いと気づいて、考えを修正しました。
よって、全社(正確には。プロダクトチーム & 情シス)に見えても良いなら暗号化を行わないというのが1つの結論です。
逆にこれを許容できないのであれば暗号化は必須となります。セキュリティーポリシーは会社・プロダクト毎に異なると思うので、随時検討して判断するのが良いです。

社内よりフィードバックがあり追記

この際には、本当に他から見えると不味いのか、セキュリティーポリシー自体の検討も行いましょう。また、認証情報にもRDBのパスワードの様にそもそもローカルネットワークからしかアクセスできない物やSaaSのAPIキーの様なグローバルからアクセスできてしまう物と危険度にランクが存在します。こういった内容にも、しっかりと注意して検討すると良いです。

kubesec + AWS KMS という形は、監査にも有効です。AWS KMSは、復号化などのアクションが発生した際に、誰がいつ行ったかが、CloudTrailから確認できます。
こういった事を求めて、kubesecを利用するのもありです。

AWS CloudTrail で AWS KMS を使用する方法 - AWS Key Management Service

まとめ

私は、GitOps・Kubernetes・AWSという文脈で、暗号化に以下のようなメリットがあると捉えています。

  • 権限管理
    • 必要な人にだけ秘匿情報を開示する
  • 監査ログ取得
    • いつ誰が秘匿情報にアクセスしたか記録する

やや乱暴ですが、全社で見れても良いなら、暗号化は不要と言うのが自分の中では結論です。
しかし、暗号化を行う事はものすごくコストがかかる行為では無く、一度手法を確立すれば他のプロダクトにも流用が効くので実際どうするの?と聞かれれば暗号化をするつもりです。
自分が情シスの立場だったらと考えると、見る必要の無い秘匿情報は見たくないという気持ちもあります。

あとがき

具体的な技術を掘り下げたり手順を書くのではなく、なぜにフォーカスしてブログを書いてみました。
考慮が抜けているポイントがあれば、コメント頂けるとありがたいです。