Container Service for Kubernetesでは、複数の方法を使用して、攻撃者がコンテナーのホストにアクセスできるコンテナーエスケープを防ぐことができます。 たとえば、コンテナーの特権モードでの実行を禁止したり、アプリケーションポッドを非rootユーザーとして実行したり、ServiceAccountトークンの自動マウントを無効にしたりできます。 このトピックでは、ポッドのセキュリティポリシーを設定してACKクラスターのセキュリティを強化し、攻撃者からACKクラスターを保護する方法について説明します。
攻撃者が特権をエスカレートできるコンテナエスケープを防止する
Kubernetesの開発者とO&M管理者は、プロセスがコンテナから逃げるのを防ぐ方法に集中する必要があります。 コンテナエスケープを使用すると、攻撃者はコンテナのホストを制御する特権をエスカレートできます。 コンテナのエスケープを防ぐことは、次の理由から重要です。
デフォルトでは、コンテナ内のプロセスはLinuxのrootユーザーのコンテキストで実行されます。
root
ユーザーが実行できる操作は、Dockerによってコンテナーに割り当てられたLinux機能
によって制限されます。 ただし、攻撃者はデフォルトの機能を悪用して特権をエスカレートしたり、ホスト上の機密情報 (Secrets
やConfigMaps
など) にアクセスしたりする可能性があります。 次のリストは、Dockerコンテナに割り当てられるデフォルトの機能
を示しています。 詳細については、「capabilities (7) Linux manual page」をご参照ください。cap_chown、cap_dac_override、cap_fowner、cap_fsetid、cap_kill、cap_setgid、cap_setuid、cap_setpcap、cap_net_bind_service、cap_net_raw、cap_sys_chroot、cap_mknod、cap_audit_write、cap_setfcap
特権コンテナーにはrootユーザーのすべてのLinux
機能
が割り当てられるため、コンテナーのエスケープを防ぐには、Dockerコンテナーを特権
モードで実行しないようにする必要があります。すべてのKubernetesワーカーノードは、特別な権限付与モードであるノードオーソライザを使用します。 ノード承認者は、kubeletによって送信されるすべてのAPIリクエストを承認するために使用されます。 ノード承認者は、ノードが次の操作を実行できるようにもします。
読み取り操作:
サービス
エンドポイント
ノード
ポッド
kubeletが実行されているノードにデプロイされているポッドのSecrets、ConfigMaps、永続ボリューム (PV) 、および永続ボリュームクレーム (PVC)
書き込み操作:
ノードとノードのステータス。 NodeRestrictionアドミッションコントローラーを有効にして、kubeletが実行されているノードのみを変更できるようにすることができます。
ポッドとポッドのステータス。 NodeRestrictionアドミッションコントローラーを有効にして、kubeletが実行されているノードにバインドされているポッドのみをkubeletが変更できるようにすることができます。
Events
認証関連の操作:
トランスポート層セキュリティ (TLS) ブートストラップ用の
CertificateSigningRequest (CSR)
APIの読み取りおよび書き込み権限委任されたID認証と承認を確認するために
TokenReview
とSubjectAccessReview
を作成する権限
デフォルトでは、ACKクラスターはNodeRestrictionアドミッションコントローラーを使用します。 NodeRestrictionアドミッションコントローラーを使用すると、kubeletはノードにバインドされているノード属性とポッドオブジェクトの限られたセットのみを変更できます。 ただし、承認コントローラーは、攻撃者がKubernetes APIを使用してクラスター環境に関する機密情報を収集するのを防ぐことはできません。 詳細については、「NodeRestriction」をご参照ください。
ポッドのセキュリティに関する提案
コンテナーの特権モードでの実行を禁止
特権コンテナは、同じホスト上のrootユーザーのすべてのLinux機能を継承します。 ほとんどのシナリオでは、コンテナーはワークロードを処理するためにこれらの機能を必要としません。 ポッドを特権モードで実行することを禁止するポッドセキュリティポリシーを作成できます。 ポッドセキュリティポリシーは、ポッドを作成する前にポッドが満たす必要がある制約のグループです。 ACKを使用すると、Open Policy Agent (OPA) とGatekeeperに基づいてポッドセキュリティポリシーを設定できます。 ポリシーは、設定したセキュリティルールに基づいて、クラスター内のポッドの作成と更新の要求を検証するために使用されます。 ポッドを作成または更新する要求が設定されたルールを満たさない場合、要求は拒否され、エラーが返されます。 ACKPSPBrivilegedContainerセキュリティポリシーを使用して、クラスターの指定された名前空間内での特権コンテナのデプロイを禁止することもできます。
ポッドを非rootユーザーとして実行する
デフォルトでは、すべてのコンテナーはrootユーザーとして実行されます。 攻撃者は、アプリケーションの脆弱性を悪用し、実行中のコンテナのシェルにアクセスできます。 そのため、セキュリティ上のリスクが発生します。 複数の方法を使用してリスクを軽減できます。 コンテナイメージからシェルを削除できます。 DockerfileにUSER命令を追加したり、非rootユーザーとしてコンテナーを実行したりすることもできます。 podSpecの
spec.securityContext
属性には、runAsUser
フィールドとrunAsGroup
フィールドが含まれます。 2つのフィールドは、コンテナーを実行するユーザーとユーザーグループを指定します。 ACKPSPAllowedUsersポリシーを作成して、指定されたユーザーとユーザーグループのみがコンテナーを実行できるようにすることができます。ユーザーがDocker-in-Dockerモードでコンテナを実行したり、Docker.sockをコンテナにマウントしたりすることを禁止
Docker-in-Dockerメソッドを使用するか、Docker.sockをコンテナーにマウントすることで、Dockerコンテナー内にコンテナーイメージを効率的にビルドまたはデプロイできます。 ただし、そうすることで、コンテナ内で実行されているプロセスにノードの制御が許可されます。 Kubernetesでコンテナイメージを構築する方法の詳細については、「container Registry Enterprise Editionインスタンスを使用してイメージを構築する」、「kaniko」、および「img」をご参照ください。
hostPathボリュームの使用を制限するか、プレフィックスを指定したディレクトリへのhostPathボリュームのマウントのみを許可し、ボリュームを読み取り専用に設定します
hostPath
ボリュームは、ホストからポッドにディレクトリをマウントします。 ほとんどの場合、ポッドはhostPathボリュームを必要としません。 hostPathボリュームを使用する必要がある場合は、必ずリスクを理解してください。 デフォルトでは、root権限で実行されるポッドには、hostPath
ボリュームを使用して公開されるファイルシステムに対する書き込み権限があります。 攻撃者は、kubelet
設定を変更し、hostPath
ボリュームによって直接公開されないディレクトリまたはファイルへのシンボリックリンクを作成できます。 たとえば、攻撃者は/etc/shadow
へのアクセス、SSHキーのインストール、ホストにマウントされているSecretsの読み取り、その他の悪意のあるアクティビティを実行できます。hostPath
ボリュームから発生するリスクを軽減するには、spec.containers.volumeMounts
を読み取り専用に設定します。 サンプルコード:volumeMounts: - name: hostPath-volume readOnly: true mountPath: /host-path
また、ACKPSPHostFlesystemポリシーを展開して、hostPathボリュームを使用して、クラスターの指定された名前空間内のポッドにマウントできるホストディレクトリを制限することもできます。
リソースの競合を防ぎ、DoS攻撃から保護するために、各コンテナにリソース要求と制限を設定します
リソース要求または制限がないポッドは、ホスト上のすべてのリソースを消費する可能性があります。 追加のポッドがノードにスケジュールされている場合、ノードのCPUまたはメモリリソースが不十分になる可能性があります。 その結果、
kubelet
がクラッシュしたり、ポッドがノードから追い出されたりする可能性があります。 この問題は避けられません。 ただし、リソース要求と制限を設定して、リソースの競合を最小限に抑え、不適切にプログラムされたアプリケーションが過剰なリソースを消費するリスクを減らすことができます。podSpecでCPUおよびメモリリソースのリクエストと制限を指定できます。 名前空間にリソースクォータまたは制限範囲を設定して、リクエストとリソースの使用を強制的に制限できます。 リソースクォータは、CPUリソースやメモリリソースなど、名前空間に割り当てられるリソースの合計量を指定します。 名前空間にリソースクォータを適用すると、その名前空間にデプロイされたすべてのコンテナのリクエストと制限を強制的に指定します。 制限範囲を使用して、割り当てられるリソースに対してきめ細かい制御を実施することができる。 制限範囲を設定して、名前空間内の各ポッドまたはコンテナーが使用できるCPUおよびメモリリソースの最大量と最小量を指定できます。 制限範囲を使用して、デフォルトのリクエスト値を設定したり、デフォルト値が指定されていない場合は制限値を設定したりできます。 詳細については、「コンテナーのリソースの管理」をご参照ください。
ACKContainerLimitsポリシーをデプロイして、クラスターの指定された名前空間のポッドにリソース制限を適用することもできます。
特権エスカレーションの禁止
特権エスカレーションは、プロセスが実行するセキュリティコンテキストを変更することを可能にする。 たとえば、
sudo
ファイルは、SUID
またはSGID
ビットを持つバイナリファイルです。 特権エスカレーションは、ユーザーが別のユーザーまたはユーザーグループの権限を持つファイルを実行するために使用できるメソッドです。 特権エスカレーションを防止するには、allowPriviledgedEscalation
パラメーターをfalse
に設定するpod
セキュリティポリシーを使用するか、podSpec
でsecurityContext.allowPrivilegedEscalation
を指定します。ACKPSPAllowPrivilegeEscalationContainerポリシーをデプロイして、クラスターの指定された名前空間のポッドに対してallowPrivilegeEscalationパラメーターの設定を強制することもできます。
ServiceAccountトークンの自動マウントを無効にする
Kubernetes APIにアクセスする必要がないポッドの場合は、特定のポッドの
podSpec
でServiceAccount
トークンの自動マウントを無効にするか、特定のServiceAccount
を使用するすべてのポッドでこの機能を無効にできます。apiVersion: v1 kind: Pod metadata: name: pod-no-automount spec: automountServiceAccountToken: false
ポッドの
ServiceAccount
トークンの自動マウントを無効にした後も、ポッドはKubernetes APIにアクセスできます。 ポッドがKubernetes APIにアクセスしないようにするには、ACKクラスターのエンドポイント
のアクセス制御を規制し、ポッドをブロックするようにネットワークポリシーを設定する必要があります。 詳細については、「ACKクラスターでのネットワークポリシーの使用」をご参照ください。apiVersion: v1 kind: ServiceAccount metadata: name: sa-no-automount automountServiceAccountToken: false
ACKBlockAutomountTokenポリシーをデプロイして、アプリケーションポッドの
automountServiceAccountToken: false
フィールドの設定を強制し、ServiceAccountトークンの自動マウントを防止することもできます。サービス検出の無効化
ポッドがクラスターサービスを検索したり呼び出したりする必要がない場合は、ポッドに提供される情報量を減らすことができます。 ポッドのドメインネームシステム (DNS) ポリシーを設定して、CoreDNSを使用せず、ポッドの名前空間の環境変数としてサービスを公開しないようにすることができます。 詳しくは、『Environment variables』をご参照ください。
デフォルトでは、ポッドのDNSポリシーは
ClusterFirst
に設定されているため、ポッドはクラスター内DNSサービスを使用する必要があります。 DNSポリシーがデフォルト
に設定されている場合、ポッドは基になるノードからDNS解決設定を使用する必要があります。 詳細については、「ポッドのDNSポリシー」をご参照ください。サービスリンクを無効にしてポッドのDNSポリシーを変更しても、ポッドは引き続きクラスター内DNSサービスにアクセスできます。 攻撃者は、クラスター内DNSサービスにアクセスすることで、ACKクラスター内のサービスを列挙できます。 たとえば、攻撃者は
dig SRV *.*.svc.cluster.local @$CLUSTER_DNS_IP
コマンドを実行して、クラスター内のサービスを検出できます。 クラスターでのサービス検出を防止する方法の詳細については、「ACKクラスターでのネットワークポリシーの使用」をご参照ください。apiVersion: v1 kind: Pod metadata: name: pod-no-service-info spec: dnsPolicy: Default # The value Default does not indicate the default setting of a DNS policy. enableServiceLinks: false
読み取り専用ファイルシステムを使用するようにコンテナイメージを構成する
読み取り専用ファイルシステムを使用するようにコンテナイメージを構成して、アプリケーションで使用されるファイルシステム内のファイルを攻撃者が上書きしないようにすることができます。 アプリケーションがファイルシステムにデータを書き込む必要がある場合は、一時ディレクトリに書き込むか、ボリュームをアプリケーションにマウントするようにアプリケーションを設定できます。 次のポッドSecurityContextを設定することで、読み取り専用ファイルシステムを使用するようにコンテナイメージを構成できます。
... securityContext: readOnlyRootFilesystem: true ...
ACKPSPReadOnlyRootFilesystemポリシーをデプロイして、クラスターの指定された名前空間内のポッドに対して読み取り専用のルートファイルシステムの使用を強制することもできます。