🛡️
【GCP/GKE】kubernetesのセキュリティ対策ですべきこと
kubernrtesを標的とするマルウェアが登場したという記事を見かけました。
上の記事で紹介されているマルウェアはGKEで運用されているkubernetesを攻撃対象にできなさそうではありますが、今一度セキュリティー対策を見直しておこうと思いまとめました。
Googleはセキュリティー対策できる機能を次々とリリースしてくれるので、定期的に見直しておくことをお勧めします。
この記事は、2020年2月現在の以下の公式ドキュメントに書いてある内容の要約になります。
詳しい情報、正確な情報、最新の情報については公式ドキュメントを参考にしてください。
クラスタとそのノードプールを常にアップグレードする
- セキュリティを向上させる最も簡単な方法の 1 つ
- 2019/11/11から、デフォルトで自動アップグレードする設定になっている
- 自動アップグレードする設定だと、Googleが勝手にクラスタのバージョンもノードプールのバージョンをアップデートしてくれる
コントロール プレーンとノードへのネットワークアクセスを制限する
- コントロールプレーンへのネットワークアクセスを制限するには、enable_private_endpointかenable_master_authorized_networksを設定します
- ノードへのネットワークアクセスを制限するには、限定公開クラスタを使います
- 詳しくは、こちらの記事に書きました
グループ認証を有効にする(ベータ版)
- 個別のユーザー管理だと大変だから、Googleグループ作って、GoogleグループにRABC使って権限与えましょうよという話だと思います
- https://cloud.google.com/kubernetes-engine/docs/how-to/role-based-access-control?&_ga=2.263240078.-389644922.1539007199#google-groups-for-gke
- 同じ権限を持つユーザーを簡単に管理でき、ID 管理者は、ユーザーの一貫した一元管理ができるようにな
- 逆に個別で管理できないのはデメリット
- GoogleGroupの管理はGoogleのWEBのGUIからしかできないので、terraformとかで管理できなくなってしまう
コンテナノードによりセキュアなものを使う
- シールドされた GKE ノードを使う
- セキュアブートも有効にする
- クラスタ作成時に
--shielded-secure-boot
オプションをつける - https://cloud.google.com/kubernetes-engine/docs/how-to/hardening-your-cluster?hl=ja#shielded_nodes
- クラスタ作成時に
- containerd ランタイムで強化されたノードイメージを使う
- クラスタ作成時に
--image-type=cos_containerd
オプションをつける - コンテナを実行するためにカスタムビルドされ、最適化され、強化されていることから cos_containerd は GKE の推奨イメージとなっています
- https://cloud.google.com/kubernetes-engine/docs/how-to/hardening-your-cluster?hl=ja#containerd
- クラスタ作成時に
Workload Identity を有効にする
- WorkloadIdentityを使うことで、ノードのサービス アカウントを使わない、かつ、サービス アカウントのキーを Secret にエクスポートしなくてすむので、細かな権限設定をより低いリスクで行えます
GKE Sandbox によるワークロード分離の強化
- Pod 内のコンテナで、不明なコードや信頼できないコードが実行されたときに、ノードのホストカーネルを保護してくれます
- たとえば、マルチテナントクラスタでユーザーから送信された不明なコードが実行される場合など
- GKE SandboxはオープンソースプロジェクトのgVisorが使われます
最小限の権限の Google サービス アカウントを使用する
- 特にGCEのデフォルトサービスアカウントを使用しないようにしましょう
- 最小限の権限のみを持つサービスアカウントを作成して、GKEクラスタを実行するときに使用しましょう
- ワークロードに権限を付与するには Workload Identityを使いましょう
- 最低でも
monitoring.viewer
、monitoring.metricWriter
、logging.logWriter
は必須です
NamespaceとRBACを使用してクラスタリソースへのアクセスを制限する
- 与える権限は最小限にしましょう
- ユーザーに付与するロールは
roles/container.clusterViewer
だけにしておくことで、kubernetesのRoleやClusterRoleリソースでアクセスするサービスアカウントやユーザーの権限をコントロールすることができます。 - サービスアカウントで
roles/container.developer
のようなロールを付与すると、kubernetesのsecretなど全てのリソースにアクセスできてしまいます。 - 以下の記事を参考になると思います
ポッド間のトラフィックをネットワーク ポリシーで制限する
- デフォルトでは、クラスタ内のすべてのポッドが相互通信できてしまいます。
- ポッド間通信は、ワークロードのニーズに応じて制御すべきです。
- トラフィックを制御する 2つの推奨方法は以下になります
- Istioを使用する
- Kubernetesネットワークポリシーを使用する
-
--enable-network-policy
オプションを有効すればOK - NetworkPolicyのリソースを作成します
-
Secretの管理
- secretリソースのyamlファイルは、機密情報の文字列をbase64でエンコードしただけのものなのでデコード可能です。ソースコードに書き込むのはやめましょう
- kubecrlコマンドでsecretリソースにアクセスできるユーザーやサービスアカウントはしっかりと管理しましょう
- GKEのVMは、etcd を含むストレージレイヤをデフォルトで暗号化してくれていますが、secretをよりセキュアに管理したい場合は、下のような方法も検討しましょう
- KMSを用いたアプリケーション レイヤでのシークレットの暗号化を行う
- HashiCorpVaultなどのシークレットマネージャーを利用する
ポッドセキュリティーポリシーでポッドの機能を制限する
- Podやコンテナの定義によっては、特権コンテナと呼ばれる、ホストと同等の権限を持ったコンテナを実行することができるが、攻撃の踏み台とされた場合にはネットワークスタックやデバイス等、広範囲に渡ってアクセスを許してしまいます
-
--enable-pod-security-policy
オプションを有効し、必要な機能だけに制限するようにPodSecurityPolicyを定義しましょう
クラスタ構成を監視する
- 実際のクラスタ構成と、定義した設定に矛盾がないか監査しましょう
ノードのメタデータを保護する(デフォルトは 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 以降)
- 静的パスワードを使用する基本認証が無効になっていること
- クライアント証明書を使用する認証が無効になっていること
- GKEをOAuthと統合する前は、1回限りのx509証明書または静的パスワードが唯一の認証方法だったが、OAuthと統合してから非推奨となりました
- https://cloud.google.com/kubernetes-engine/docs/how-to/hardening-your-cluster?hl=ja#harden_workload_isolation_with_sandbox
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ログを有効にする
- ノードのオペレーティング システムログには、エラー メッセージ、ログイン試行、バイナリ実行など、クラスタとワークロードの状態に関する重要な情報されます
- リソースを結構必要とするらしいです
- https://cloud.google.com/kubernetes-engine/docs/how-to/linux-auditd-logging?hl=ja
Confidential GKE Node の使用
- VM の使用中のメモリの内容を暗号化してくれます
- 通常のノードよりも利用料金が高くなります
- https://cloud.google.com/kubernetes-engine/docs/how-to/confidential-gke-nodes?hl=ja
セキュリティ インシデントが発生した場合の緩和策
- できれば脆弱性を修正してください
- 重大度の高い順に次を行いましょう
- 1, ホスト VM のディスクのスナップショットを作成する
- 2, ワークロードの稼働中に VM を検査する
- 3, コンテナを再デプロイする
- 4, ワークロードを削除する
- https://cloud.google.com/kubernetes-engine/docs/how-to/security-mitigations?hl=ja
最後に
攻撃者も進化をとめませんし、Gooleはセキュリティ対策の新しい機能はどんどん追加してるので、改めてしっかりと最新のセキュリティ対策機能に追従していかないとなと思いました!
また、GKEのバージョンが古いのはかなり致命的なので、こちらは常に最新版にし続けないといけませんし、逆に言うと最新版にしておけばそれなりに安心というところもあります。しかし、後から非推奨になった機能について、アップデートした場合には自分で無効にしなければ使い続けれてしまう、という場合もありますので気をつけないといけません。
GKEの載せ替えや構成変更は非常に大変ですが、terraformなどを使いクラウドサービスのリソースをコードで管理し、GitOpsを行うことでかなり楽になったので、まだ導入されてない現場ではぜひ試していただきたいなと思いました!
Discussion