コンテナプラットフォーム(kubernetes)環境におけるセキュリティ対策について

エンタープライズ企業が本番環境でコンテナプラットフォームの採用を検討する際、昨今グルーバルでデファクトスタンダートとなっているコンテナオーケストレーションツールであるkubernetesの採用が進んでいく事が予想される。kubernetesをベースとしたコンテナプラットフォーム環境を運用していくにあたりエンタープライズ企業が考慮すべきセキュリティ対策について考えてみる。

エンタープライズ企業がプロダクション環境でkubernetes互換のコンテナプラットフォームを動かす際の選択肢について

kubernetes互換のコンテナプラットフォーム導入には、いくつかの選択肢がある。物理・仮想サーバからkubernetesを初期インストールしkubernetesクラスタをセットアップする方法か、あるいはAWS EKSやAzure AKSなどのパブリッククラウドベンダーが提供するkubernetes互換のマネージドサービスを利用する、といった方法がある。前者の場合、利用者でkubernetesクラスタのセットアップや運用管理における一定の知識や経験が必要ではあるが、利用者側で任意にkubernetes本体のバージョンアップやセキュリティパッチ適用、コントロールプレーンのカスタマイズやコントロールが出来るといったメリットがある。また、物理・仮想サーバからkubernetesクラスタをセットアップするにしても、kubernetesをラッピングしたOpenShift(Redhat社)やPivotal(VMware社)などのクラスタ環境一式の導入・運用パッケージコンポーネントを利用する方法もある。この場合、ベンダーサポートの恩恵を受けられるメリットもある。後者の場合、パブリッククラウドベンダーが提供するkubernetesバージョンの制約の範囲内で利用する事になるが、コントロールプレーン(マスターノード)の運用管理をパブリッククラウドベンダーに任せる事が出来るなどのメリットがある。

AWSなどのパブリッククラウドでコンテナプラットフォーム環境を導入し運用する際に考慮すべきセキュリティ対策について

仮にAWSが提供するkubernetes互換のマネージドサービス(AWS EKSなど)を利用する場合でも、AWSが提唱する「責任共有モデル」は従来通り当てはまる。責任共有モデルとは、物理サーバやOS、ストレージやネットワークなどの各レイヤやコンポーネントに応じて、パブリッククラウドベンダーとクラウド利用者の双方でセキュリティとコンプライアンスの責務を共有する、という概念である。

引用サイト) https://aws.amazon.com/jp/compliance/shared-responsibility-model/

この概念はAWSに限らず各社パブリッククラウドベンダーが提唱している概念である。AWSでコンテナプラットフォーム環境を導入し運用する場合、この責任共有モデルを、いくつかの選択肢とマッピングすると以下の通りとなる。 背景が橙色の部分がAWS、白色の部分がクラウド利用者の責務の範囲となる。

kubernetesのコンテナプラットフォーム環境におけるセキュリティ対策について

セキュリティ対策と一口に言っても考慮すべき視点は多岐に辺り、どこから検討していけばよいか悩む。セキュリティ脅威の一例を記す。

  • kubernetesクラスタのコントロールプレーンのセキュリティホール(欠陥)を狙った外部からの攻撃
  • コンテナやノードのセキュリティホール(欠陥)を狙った攻撃
  • 管理者用クレデンシャルの情報漏洩を狙った攻撃
  • 権限設定のミスを狙った攻撃など

kubernetesなどのCloud Nativeなシステムのセキュリティ対策は多くの技術要素が組み合わさっている為、とても複雑である。また、kubernetes本体の各種デフォルト設定値のままで導入・運用する事はセキュリティ対策が不十分であるのが定説となっている。弊社では、考慮すべきセキュリティ対策を「セキュリティカテゴリ」と「セキュリティ境界」の2つの軸で整理した。

「セキュリティカテゴリ」とは、kubernetesへのAPIアクセス認証・認可、ネットワーク通信の制御を行うファイアウォール、企業やシステムの要件に合わせて何をどこまで守るべきなのかを明確にする為のガバナンス/コンプライアンス対策など、いくつかの考慮すべき代表的なセキュリティ項目をカテゴライズしたものである。「セキュリティ境界」とは、kubernetesクラスタやコンテナレイヤで抽象化された各コンポーネント間における境界の事である。AWSなどのパブリッククラウド上にkubernetesクラスタを導入していると仮定する。kubernetesクラスタは物理的にMaster NodeとWorker Nodeで構成されており、更にNamespaceやpodなどの論的なコンポーネントで多層的に構成されている。一般的なセキュリティ戦略の原則として、一ヶ所だけ対策を取れば良いという訳では無く、多段階の多層防御をとる事が重要である。その理由は、仮に特定のNodeやContainerのいずれかの脆弱性を突かれ外部からの悪意ある侵入をされたとしても多層防御を講じておけば被害範囲を最小限に抑え込める可能性が高くなる。このセキュリティ戦略は、オペレーションミスやハードウェア障害などのインシデントに対する備えにも有効に働く。kubernetesやコンテナ向けのセキュリティ対策製品を開発しているベンダ各社は、この手の対策を講じる事を「爆風半径の最小化」と説明している事が多い。各セキュリティ境界における考慮すべきセキュリティ対策例を記す。

セキュリティ境界 対策例
Public Cloud IAMなどの認証・認可や、Firewallなどのネットワーク通信制限など
kubernetes Cluster クラスタレベルのリソースへのアクセス制限など
Master / Worker Node コンテナワークロードの分離や、ステートフルなストアデータの暗号化など
Namespace 名前空間レベルでのリソースへのアクセス制限や、CPU/MEMリソース使用量の制限など
Pod ネットワークやボリュームの分離や制限など
Container ハードウェアやカーネル資源の分離や制限など
Application ソースコードやライブラリのバグや脆弱性対策など

セキュリティカテゴリ毎の対策詳細について

ここからはセキュリティカテゴリ毎に具体的な施策について説明していく。まずは、kubernetes へのAPIアクセスにおいて、誰に対して何に対する何の操作を許可、あるいは拒否するのか、認証・認可について説明する。

1.認証

kubernetesのAPIアクセス認証・認可・Admission Controlの概要図(AWS例)

認証機構について

  • kubernetesクラスタへのAPIアクセスの主体に対しての認可ポリシーは大きく分類すると2種類ある。人、またはkubernetesクラスタ外部システムからのAPIアクセス認証用途のUserAccount(Groupで束ねる事も出来る)と、kubernetesクラスタ内部のPodからのAPIアクセス認証用途としてServiceAccountがある。例えばX509クライアント証明書を使った認証方式の場合、UserAccount自体はkubernetesクラスタ外部で証明書を発行し管理する。この証明書のCommon Nameがユーザ名、Organizationがグループ名としてkubernetesクラスタ内部で認識される。ServiceAccountの場合は、kubernetesクラスタ内部でオブジェクトリソースを作成し管理する。認証方式は、Token(Static Token File、Service Account Tokens、OpenID Connect Tokensなど)、Basic認証(Static Password File)、クライアント証明書(X.509 Client Certs)、X-Remoteヘッダ(Authenticating Proxy)などの選択肢がある。

認証の考慮事項

  • 信頼されたユーザやアプリケーションからのAPIアクセスかどうか一意に識別し正当性の確認を怠ると意図しない不正な操作を許容してしまうリスクがある。その為、UserAccountやServiceAccount対象の用途が異なる場合、共用せず個別にUserAccountやServiceAccountを作成し運用管理するのが望ましい。また、未使用なUserAccoutやServiceAccountは削除する事が望ましい。KubernetesにはデフォルトのServiceAccountが存在する。スケジューリングされたPodがこのデフォルトのServiceAccountを自動マウントする仕様である為、各Podの用途毎にServiceAccountを作成し管理する事が望ましい。パブリッククラウドが提供するkubernetes互換のマネージドサービスやkubernetes本体のバージョンによっては、既に考慮された設定になっている場合もある。kubernetesクラスタの認証に関連した考慮すべき設定例をいくつか記す。
    対策例 関連する設定項目
    匿名ユーザからのAPIアクセスを無効化する kubelet起動引数に「-anonymous-auth=false」を追加する
    kubelet操作範囲を制限する API ServerのAdmission Controlの設定で「-admission-control=NodeRestriction,***」を追加する
    kubernetes dashboardの公開範囲を制限する 特定のプライベートネットワーク経由からのみアクセス制限するなど
    Read onlyポートを無効化する kubelet起動引数「-read-only-port=0」を追加する
    cAdvisorメトリックポートを無効化する kubelet起動引数「-cadvisor-port=0」を追加する
    kubeletへのAPIアクセス認証用に作成した証明書の定期的なローテーションを行う。(デフォルトの有効期間は1年間) api-serverの起動引数に「-kubelet-client-certificate」、「-kubelet-client-key」を指定し更新した証明書を指定する

2.認可及びAdmission Control

認可機構について

  • kubernetesクラスタやオブジェクトリソースに対する何の操作を許可、または拒否するのかの操作範囲の制御を行う。例えばdeploymentやConfigMapなどのkubernetesオブジェクトリソースに対して、WatchやWriteといた操作権限を定義する。一般的なセキュリティ戦略の原則として必要最小限の権限である事が望ましい。kubernetesでは下記の様な認可モジュールが選択提供されている。
    認可モジュール名 機能概要
    Node Podがスケジュールされたkubeletのみにリクエストを許可する
    ABAC 属性ベースのアクセス制御でポリシーファイルを起動フラグで静的に設定する。現在は非推奨である
    RBAC ロールベースのアクセス制御。API経由で動的に制御する
    Webhook Webhookに対してHTTP POSTメッセージで認可を委任。外部認可サービスと連携する
    AlwaysDeny テスト用。全てのアクセスを拒否する
    AlwaysAllow テスト用。認可を実施しない全てのアクセスを許可する
  • 本番環境では、RBAC、またはWebhookの方式が推奨されている。RBACでは、kubernetesクラスタスコープで定義(ClusterRole)、または、Namespaceスコープで定義(Role)する。この定義を上述のUser、またはServiceAccountにバインディングする事で、APIアクセス時の操作範囲を制御する。RBACにはkubernetesがデフォルトで用意している以下の様な汎用ロールがある。
    名前 概要
    cluster-admin クラスタの全リソースの操作権限をもつ
    Admin ほとんどのリソースに対する読み書き権限をもつ。ResourceQuota、所属Namespaceの書込み権限はない
    Edit ほとんどのリソースに対する読み書き権限をもつ。Role、RoleBindingの書き込み権限はない
    View ほとんどのリソースに対する読み取り権限をもつ。Role、RoleBinding、Secretの読み取り権限はない
  • 更にAdmission ControlというAPI Serverのリクエスト制御機構がある。Admission Controlは、APIリクエストに対しての認証・認可を行った後のフェーズで、APIリクエスト内容の検証やポリシーに応じたリクエスト内容の書き換えを行う。これはkubernetesクラスタやkubernetesオブジェクトリソースを安全に保つ為のガードレールの役割を果たす。例えば特定のNamespace内のコンテナが確保出来るCPU/MEMリソースの合計上限の制限(ResouceQuota)をかける事で、特定のNamespaceのコンテナ群でkubernetesクラスタノードの全CPU/MEMリソースを消費させない様にする事が出来る。admission controllerプラグイン例を記す。
    名前 概要
    Pod Security Policy 予め定義したセキュリティポリシーに応じてPodやContainerリソースを検証・変更する
    LimitRanger NamespaceのLimitRangeで指定されたPodのCPUやMemory Resource範囲の制限を行う
    ResouceQuota NamespaceのCPUやMemory Resouceの合計使用量の制限を行う
    MutatingAdmissionWebhook 独自ポリシーの呼び出し。Open Policy Agentなどに委譲する
    ValidatingAdmissionWebhook 独自バリデーションの呼び出しを行う
    AlwaysPullImages PodのimagePullPolicyをAlwaysに強制的に変更する
    EventRateLimit API Serverへのリクエスト高負荷を抑制する為、Namespace、UserAccount、ourceAndObjectなどの単位で制限する

認可の考慮事項

  • RBACは複数用途で共用せず用途毎に独自ロールを作成する事が望ましい。更に、未使用(不要)なロールは削除する事が望ましい。但し、APIアクセス元の用途毎に応じて全て独自にRBACを作成・管理するのは現実的に運用が高負荷になり、結果的に野良RBACがセキュリティホールになるリスクも懸念される。その為、APIアクセス元が外部システムなどのプログラムなのか、開発やオペレータ要員なのによって独自にRBACを作成するのか、または汎用で用意されているRBACを利用するのかを検討し、適材適所で使い分けするのが現実解だと考えている。

3.ファイアウォール

外部からの悪意あるアタックや、内部からの意図しない情報漏洩のリスクを低減する為、クライアントからkubernetesクラスタへのAPIリクエストや、kubernetesクラスタ内部のServiceやPod間のネットワーク通信の制御を行う。kubernetesクラスタを物理的に構成するMaster NodeとWorker Nodeレイヤの観点で考慮すべきネットワーク通信制御の例を記す。

  • master nodeは、kubernetesクラスタへのAPI操作コンポーネントであるAPI Serverへのアクセスを、特定のプライベートネットワークセグメントやIPアドレスからのみの通信に制限する。AWSやGCPなどのパブリッククラウドベンダーが提供するkubernetes互換のマネージドサービスでは、master nodeへのAPIアクセスを特定のプライベートネットワークからのみに制限する機能も提供されている。
  • worker nodeは、master nodeからのアクセスやworker node間のアクセスなどの必要最低限のネットワーク通信に制限する。worker node本体をプライベートネットワークセグメントに配置する事も有効である。worker node上で稼働するpod(コンテナ)のサービスを外部インターネットに公開する場合は、IngressやLoad Balancer経由で公開する。

コンテナレジストリへのネットワーク通信制御の考慮も重要である。kubernetesクラスタでpod(コンテナ)をスケジュールする際、コンテナレジストリからコンテナイメージをプルする。その為、kubernetesクラスタが稼働するネットワークセグメントからのみコンテナレジストリへの通信制限を行う。例えばAWSなどのパブリッククラウドベンダーが提供するコンテナレジストリでは、特定のプライベートネットワークセグメントからのみに通信を制限する様なプライベートレジストリやVPCエンドポイントといった機能が提供されている。

kubernetesクラスタ内部のserviceやpod間通信はデフォルトで全て許可されている為、必要最小限の通信に制限する事が望ましい。kubernetesでは、特定のワークロードやロール毎に操作権限やネットワーク通信を論理的に分離可能なNamespaceを有効活用するとよい。ワークロードの用途毎にNamespaceを作成する事でNamespace毎にネットワーク通信のインバウンド/アウトバンドの制御が出来る。defaultのNamespaceに複数ワークロードをデプロイし集約していたとすると、特定コンテナに侵入された際に被害範囲の拡大を軽減出来ない可能性が高い為、defaultのNamespaceの利用を避けるのが無難である。特定のNamespaceやPod間のL3/L4レイヤの通信制御を行う為の機構としてkubernetesでは、CalicoやFlannelといったContainer Network Interface(CNI)プラグインを利用しNetwork policyが定義できる。更に、L7レイヤの通信制御を行いたい場合、Envoyなどのサービスメッシュ機構を持つツールを利用する事で、L7レイヤでの認証や、mTLS、サーキットブレーカー、ヘルスチェックなどを行う事が出来る。

引き続き 全編版のダウンロード用PDFをご覧ください。

本コラムはいかがでしたでしょうか。
全編版PDFでは同様の形式で全10セキュリティカテゴリをセキュリティ境界の図を用いて詳細に解説しています。