【GCP/GKE】kubernetesのセキュリティ対策ですべきこと

公開:2021/02/14
更新:2021/02/14
8 min読了の目安(約7400字TECH技術記事

kubernrtesを標的とするマルウェアが登場したという記事を見かけました。
上の記事で紹介されているマルウェアはGKEで運用されているkubernetesを攻撃対象にできなさそうではありますが、今一度セキュリティー対策を見直しておこうと思いまとめました。

Googleはセキュリティー対策できる機能を次々とリリースしてくれるので、定期的に見直しておくことをお勧めします。
この記事は、2020年2月現在の以下の公式ドキュメントに書いてある内容の要約になります。
詳しい情報、正確な情報、最新の情報については公式ドキュメントを参考にしてください。

https://cloud.google.com/kubernetes-engine/docs/how-to/hardening-your-cluster?hl=ja

クラスタとそのノードプールを常にアップグレードする

コントロール プレーンとノードへのネットワークアクセスを制限する

  • コントロールプレーンへのネットワークアクセスを制限するには、enable_private_endpointかenable_master_authorized_networksを設定します
  • ノードへのネットワークアクセスを制限するには、限定公開クラスタを使います
  • 詳しくは、こちらの記事に書きました

グループ認証を有効にする(ベータ版)

コンテナノードによりセキュアなものを使う

Workload Identity を有効にする

GKE Sandbox によるワークロード分離の強化

最小限の権限の Google サービス アカウントを使用する

  • 特にGCEのデフォルトサービスアカウントを使用しないようにしましょう
  • 最小限の権限のみを持つサービスアカウントを作成して、GKEクラスタを実行するときに使用しましょう
  • ワークロードに権限を付与するには Workload Identityを使いましょう
  • 最低でもmonitoring.viewermonitoring.metricWriterlogging.logWriterは必須です

NamespaceとRBACを使用してクラスタリソースへのアクセスを制限する

  • 与える権限は最小限にしましょう
  • ユーザーに付与するロールは roles/container.clusterViewer だけにしておくことで、kubernetesのRoleやClusterRoleリソースでアクセスするサービスアカウントやユーザーの権限をコントロールすることができます。
  • サービスアカウントで roles/container.developer のようなロールを付与すると、kubernetesのsecretなど全てのリソースにアクセスできてしまいます。
  • 以下の記事を参考になると思います

ポッド間のトラフィックをネットワーク ポリシーで制限する

  • デフォルトでは、クラスタ内のすべてのポッドが相互通信できてしまいます。
  • ポッド間通信は、ワークロードのニーズに応じて制御すべきです。
  • トラフィックを制御する 2つの推奨方法は以下になります

Secretの管理

ポッドセキュリティーポリシーでポッドの機能を制限する

クラスタ構成を監視する

  • 実際のクラスタ構成と、定義した設定に矛盾がないか監査しましょう

ノードのメタデータを保護する(デフォルトは 1.12 以降)

  • 従来の Compute Engine インスタンスのメタデータ API を無効にする
    • VMインスタンスのメタデータサーバーが公開する以前の v0.1 と v1beta1 エンドポイントは、メタデータクエリヘッダーを適用しないため、攻撃者はインスタンス メタデータを取得することがより簡単になります
  • Kubernetesに対する攻撃の中には、VMインスタンスのメタデータサーバーへのアクセスを使用して認証情報を抽出するものもあります
  • GKEメタデータサーバーを有効にする
  • https://cloud.google.com/kubernetes-engine/docs/how-to/hardening-your-cluster?hl=ja#protect_node_metadata_default_for_112

以前のクライアント認証方式を無効にする(デフォルト: 1.12 以降)

Cloud Logging を有効のままにする(デフォルト)

  • Stackdriver Kubernetes のロギングとモニタリングは有効のままにしておきましょう
  • すべてのGKEクラスタではデフォルトでKubernetes監査ロギングが有効になっています
    • kubernetes API サーバーに対する呼び出しの記録が時系列で保持されている
    • ログは不審な API リクエストの調査、統計情報の収集、不要な API 呼び出しに対するモニタリング アラートの作成に使えます

KubernetesウェブUI(ダッシュボード)を無効のままにする(1.10 以降デフォルト)

  • KubernetesウェブUI(ダッシュボード)は、高い特権を持つ Kubernetes サービス アカウントと関連付けられているので、結構危険
  • GPCコンソールにほぼ同等の機能があるので、 KubernetesウェブUIを使う必要はない

ABAC を無効のままにする(デフォルトは 1.8 以降)

  • ABACは使わずに、RBACを使いましょう
  • RBACには重要なセキュリティ上の利点があり、現在Kubernetesで安定しているので推奨されています

IAMとRBACを使って適切な権限を付与する

  • IAMかRBACのどちらかで権限を与えると、与えられた権限の範囲で実行可能になります
    • Namespaceごとに権限を管理したい場合は、IAMで権限を付与せずにRBACで権限を付与します
    • 全てのNamespaceのsecretへのアクセス権限など、Namespaceごとでない場合は、IAMかRBACのどちらかで権限を付与します
  • https://cloud.google.com/kubernetes-engine/docs/how-to/role-based-access-control?hl=ja

クラスタ認証情報のローテーション

  • gcloud container clusters get-credentials ... で取得するクラスタの認証情報をローテションできます
  • 認証情報の有効期間を短縮することでGKEクラスタの保護を強化できます
  • コントロールプレーンのIPのローテーションも実施されます
  • 自動的にはローテーションされませんので、定期的に実行してください

GKEノード上でLinuxのauditdログを有効にする

Confidential GKE Node の使用

セキュリティ インシデントが発生した場合の緩和策

最後に

攻撃者も進化をとめませんし、Gooleはセキュリティ対策の新しい機能はどんどん追加してるので、改めてしっかりと最新のセキュリティ対策機能に追従していかないとなと思いました!
また、GKEのバージョンが古いのはかなり致命的なので、こちらは常に最新版にし続けないといけませんし、逆に言うと最新版にしておけばそれなりに安心というところもあります。しかし、後から非推奨になった機能について、アップデートした場合には自分で無効にしなければ使い続けれてしまう、という場合もありますので気をつけないといけません。

GKEの載せ替えや構成変更は非常に大変ですが、terraformなどを使いクラウドサービスのリソースをコードで管理し、GitOpsを行うことでかなり楽になったので、まだ導入されてない現場ではぜひ試していただきたいなと思いました!