EKS Kubernetes 環境変数のセキュリティ考察

前回の続きで、環境変数を取り扱う時のセキュリティについて考察していきます。

あくまで考察であって、正解ではないです。セキュリティなんてものは環境によって必要な内容が変わるので、こんな風に考えて、こんな感じが正着の1つちゃうん・・・くらいなテイストでお願いしますだ。



はじめに

環境変数を扱うにあたって、セキュリティについて考える必要があるわけですが、そもそも本当に考える必要があるのか?どこまでやれば十分なのか?はサービスによって異なるので、ある程度の条件を想定して考察していきます。

似たような考察はこちらでもされているので、ぜひ。
  • なぜ、Kubernetesを使う際にSecretを暗号化するのか? | DevelopersIO

  • 最も環境変数の利用としてありがちなのは、アプリケーション・サーバーがデータベースへ接続するための、接続先・ユーザー・パスワード といった情報でしょう。その中で特に、パスワードはおいそれと人の手に渡らないようにする、という要件で丁寧に考えます。


    データの保管方法

    保存される箇所を把握する

    前回まとめた環境変数の設定方法から、どのような箇所に保存される可能性があるかというと、

  • Terraformコード local/remote(平文)
  • Kubernetes ConfigMap(平文)
  • Kubernetes Secret(base64 = 平文に等しい)
  • Kubernetes Pod(環境変数に登録)
  • AWS SSM Parameter Store(IAM権限があれば閲覧可能)
  • Excel パスワードまとめ的な(平文)
  • PCモニタの付箋(平文)

  • 最後の方はまぁ ほぼ ジョークですけど、、可能性としては色んな所に散らばると考えるべきですよね。

    暗号化する・しない

    暗号化といえばSSL証明書あたりが最も身近なものだと思いますが、アレは通信の秘密を守るために重要なのであって、今回のような設定値だと暗号化それ自体にはそこまで意味があるわけではない、と考えます。(なんかセキュリティ警察に怒られそうな言い方でgkbrですが)

    なぜなら、プライベートな環境限定で扱うデータだからです。暗号化したデータそのものを盗られても、復号化できなければ大丈夫── という以前に、まず扱う経路的に盗られる可能性が限りなくゼロ。万が一、パスワードを入手されたとしても、特定のネットワーク内でしか効果ない── など、ポシティブに大丈夫な理由を考えれば、いろいろあるものです。

    あるとすれば、Terraformコードを、グローバル・ネットワークを通して、パブリックにあるGitサービスへ送るとかでしょうか。それでも、HTTPSで通信しているでしょうから、その送信時は問題なく、結局はGit上のコードを想定外の人物にアクセスされた場合に、暗号化されていれば鍵がなければ大丈夫。という流れなどが考えられるでしょう。

    つまるところ、じゃあ何を考えるかというと、アクセス権です。データへのアクセス、鍵へのアクセス、ネットワーク経路。暗号化はそれらが通過されたあとの話なので、したらより安全には近づくけど、したから安全というものではないと思うべきでしょう。

    アクセス権を管理する

    ではアクセス権をちゃんと管理しましょう、となったので、上記保存場所でそれぞれ何を制御することになるのかを整理していきます。

    Terraformコードの場合、Git に保管するので、レポジトリへのアクセス権で制御することになります。

    Kubernetes ConfigMap / Secret の場合、Role や ClusterRole で管理することになるでしょう。そのへんについては、以下を参考にしてください。
  • Kubernetesの管理が簡単なロールベースアクセス制御(RBAC)について知っておくべきこと – クリエーションライン株式会社

  • Pod へのアクセスができてしまうと、環境変数はこんな感じでゴッソリ見えてしまいますので、やはり Role のお世話になるでしょう。

    Pod に sshd がいると、また話は別になりますが、コンテナにSSHは通常入れないのでスルーな方向です。

    SSM Parameter Store は KMS と合わせてIAM管理下にあります。

    Excel は……置くとしたらどこかの共有ファイルサーバーだとして、ディレクトリやファイルの閲覧権限、Excel そのもののパスワードとかが考えられます。が半分ジョークです。

    付箋は……ジャパニーズ・ジョークです。やめましょう。


    データを何から守るか

    こういう内部用のデータって、いったい何故、何から守らなくてはいけないかを考えてみると、外部公開に関わる場合と異なってすごくシンプルだったりします。

    手元の開発環境などから、一瞬は Git や AWS へ送信するタイミングはあれど、それ以外は基本的にプライベート環境内のいずこかに保存して内部で使用するため、外部からの驚異に晒されることはほぼありません。では、そのプライベートなデータを何から守るかというと、、、

    社員 から守ります。
    社員を守る ではなく 社員から なのが切ないですねぇ。

    インフラは、サービスひいては担当社員に提供することが歓びであるはずが、社員を疑うことも必要になります。例えば、

    これから退職予定の社員、
     入社したてで信用が確立していない社員、
      力量不足で信頼が薄い社員、
       スパイとして入社してきた社員、

    色々あるし、その色々に対して対策も様々ありますが、
    セキュリティの重要事項として確たるモノに、

     余計なデータを、余計なところに開放しない = 最小限に開放する

    という考えがあります。ただ、それをパーフェクトに実現しようとすると、非常に運用しづらかったり、苦労の割に効果が薄かったりするので、その程度を考えて設計するのがミソというか、腕の見せどころでもあります。ていうか、そもそもパーフェクトとかないし?みたいな?

    アクセス制限が必要な箇所をできるだけ少なくし、アクセス制限の方法ができるだけシンプルで扱いやすい、そんな仕組みが望まれます。

    それによって、悪い言い方をすれば、

    退職前の社員がデータをぶっこ抜いていくのを阻止し、
     退職後の元社員がデータをもぎ取りにくる可能性を排除し、
      力量不足の社員がデータ破壊を起こすのを防止し、
       スパイは・・・ちょっと別の話になっちゃいそうですが・・・

    というようなことが、そもそも起こらないし、
    そもそも疑う必要すらない、ような環境を整えることが目的となります。

    まぁ可能性をあげていけば、クラウドのアカウント情報が漏れて~とか、脆弱性をゼロデイ攻撃により~とか、いくらでもあるわけなんですが、最も簡単で危ないのは何っていえば、内側からお漏らしポロリ なのが世知辛い世の中でござんすねぇ。


    イマイチっぽい例

    次の良さそうな例をマシに見せるために、あえて超普通にど真ん中直球な構成にしてみると、こういうのはどうでしょう。

  • Terraform の ConfigMap で平文の環境変数を設定する
  • Terraform の Secret で暗号化の環境変数を設定する
  • Pod で復号化処理

  • これだけみたら非常にシンプルですが、気を使うべきところが結構多くなります。

  • Secret 用の値を事前に暗号化
  • 暗号化用の鍵の管理
  • Terraform 用 Git レポジトリのアクセス権限
  • Kubernetes への IAM アクセス権限
  • Secret へのアクセス権限
  • Pod での復号化処理
  • Pod へのアクセス権限

  • 暗号化は kubesec とか、他にもなんとでもなりそうではありますが、Terraform と連携してうまくできるかは疑問ですねぇ。一応、運用できなくはなさそうですが、全体的にあまりスタイリッシュとはいえなさそうです。


    良さそうな例

    というわけで、こんな設計ではどうでしょう。

  • Terraform の env で SSM のパスに必要な値を設定(ENV=production 等)
  • SSM Parameter Store に平文は String, String List で、暗号化用は Secure String でキーのパス規則を決めて登録
  • Pod で平文・暗号化ともに取得

  • 全部、SSM に置いてしまう構成です。この場合、気にするべきところは、

  • SSM / KMS への IAM アクセス権限
  • Kubernetes への IAM アクセス権限
  • Pod へのアクセス権限

  • くらいになりそうです。Secure String はコンソールで手動作成することで、そこ以外にデータが存在するのは、Pod 内の export された環境変数そのもののみ、ということになります。もし確認したければ、SSM / KMS 権限のあるユーザーで閲覧/編集し、一般的なコンソール用ユーザーにはその権限を与えないようにします。

    場合によっては、平文でよい接続先情報などは、Parameter Store を Terraform で設定してしまってもよさそうです。その方が、aws_*** の作成済みリソースから、FQDN や URL などの情報をコードで登録できるので、よりシステマチックです。


    セキュリティも頑張るぞいっ

    昔ながらのシステム構成だと、アプリケーション・コードに普通にDBパスワードを直書きしていたわけですが、コンテナを扱い、コンテナの正しい使い方、その利便性を享受しようと思えば、自然とその悪習慣から切り離され、設計を再考する機会が設けられるのはとても良いことだと思います。

    インフラの、稼働して当然、落ちてマイナス評価 のイメージのように、
    セキュリティも、抜かれないのが当然、事件が起きたら間抜け なところがあり、

    逆に言えば、何も起きなければ大正義、どれだけ強固でも何も起きなければ同効果。
    その、何かが起きる度合い ってのは環境やサービスによって異なり、定量化できない。

    となれば、緩む とまでは言わないまでも、後回し気味になるのは否めません。

    既存のイマイチと心の中でわかっている環境を、矜持だけで強化しても、見えない効果はあれど自身としても他人からの評価としても、あまりグッとくるものがないかもですが、

    ガラッと新環境にすることがあれば、この辺をキリッと引き締め、それがさも当然のように振る舞えば、システムもニッコリ、企業文化醸成もパッチリ、お給料もドッサリ



    するといいですねぇ。みなさん、頑張りましょう:-)