TT Lab
はじめる
学ぶ 学習パス コース

CKS — Kubernetesセキュリティスペシャリスト

Pod Security AdmissionとsecurityContext

TT Labで続きを見る

目標

ネームスペースのラベルだけでワークロードのセキュリティの下限を決める方法を身に付け、restrictedプロファイルを実際に通過するPodスペックを手で完成させます。

なぜ重要なのか

PodSecurityPolicyは1.25で削除されました。使うにはServiceAccountに「このPSPをuseする権限」を与える必要があり、その構造そのものが権限昇格の経路でしたし、複数のPSPのうちどれが適用されるかを予測するのも困難だったためです。代替のPSAは、ネームスペースのラベル数行で済み、enforce・audit・warnの3つのモードを別々に有効にできるため、段階的な導入が可能です。既存のクラスターにいきなりenforceを設定するとワークロードが大量にブロックされるので、warnとauditを先に有効にして観察するのが標準的な手順です。

restrictedプロファイルが要求する4つ(runAsNonRoot、allowPrivilegeEscalation false、capabilities drop ALL、seccompProfile)は、CKSで最もよく出る組み合わせです。暗記するよりも、自分で1つずつ外してみて、どんなエラーが出るかを確認したほうが長く記憶に残ります。

この環境のAPIサーバーではPodSecurityアドミッションが有効になっているため、違反したPodは実際に拒否されます。

ステップ

  1. ネームスペースcks-psaを作成し、ラベルpod-security.kubernetes.io/enforce=baselineを付けてください。
  2. ネームスペースcks-psa-strictを作成し、enforce・audit・warnの3つのラベルをすべてrestrictedにし、さらにenforce-version・audit-version・warn-versionの3つのラベルをすべてlatestにして付けてください。
  3. cks-psa-strictにPodhardened(コンテナ名app、イメージnginx:1.27-alpine)を作成してください。restrictedを通過する必要があるため、PodレベルにrunAsNonRoot: trueとseccompProfile.type: RuntimeDefault、コンテナレベルにallowPrivilegeEscalation: falseとcapabilities.drop: [ALL]が必要です。
  4. cks-psa-strictに、privileged: trueのコンテナを持つPodbad-podをapplyしてみてください。その出力(標準エラー出力を含む)を/root/cks-securitycontext/denied.txtに保存します。Podが作成されてはいけません。
  5. cks-psaにPodnonroot-app(コンテナ名app)を作成してください。PodレベルのsecurityContextにrunAsNonRoot: true、runAsUser: 10001、runAsGroup: 10001、fsGroup: 20001を入れます。
  6. cks-psa-strictにPoddropped(コンテナ名app)を作成してください。PodレベルのseccompProfile.typeはRuntimeDefault、runAsNonRootはtrueとし、コンテナレベルにallowPrivilegeEscalation: false、capabilities.drop: [ALL]、readOnlyRootFilesystem: trueを入れます。
  7. RuntimeClasscks-sandboxを作成してください。handlerはrunsc、overhead.podFixedはメモリ160MiとCPU250mです。
  8. cks-psa-strictにDeploymentpaymentsを作成してください。replicasは2、セレクターとPodラベルはapp=payments、PodスペックのruntimeClassNameはcks-sandboxとし、Podテンプレートは、restrictedを通過するようにステップ3と同じ4つの条件をすべて備えます。

参考

baselineプロファイルを適用する

ネームスペースcks-psaを作成し、ラベルpod-security.kubernetes.io/enforce=baselineを付けてください。

PSAはネームスペースのラベルで動作します。ラベルのキーはpod-security.kubernetes.io/で始まります。

3つのモードとバージョンラベルをすべて設定する

ネームスペースcks-psa-strictを作成し、enforce・audit・warnの3つのラベルをすべてrestrictedにし、さらにenforce-version・audit-version・warn-versionの3つのラベルをすべてlatestにして付けてください。

enforce・audit・warnのそれぞれに対応する-versionラベルが別にあります。バージョンを固定すると、クラスターのアップグレードがそのままポリシーの強化につながることがありません。

restrictedを通過するPod

cks-psa-strictにPodhardened(コンテナ名app、イメージnginx:1.27-alpine)を作成してください。restrictedを通過する必要があるため、PodレベルにrunAsNonRoot: trueとseccompProfile.type: RuntimeDefault、コンテナレベルにallowPrivilegeEscalation: falseとcapabilities.drop: [ALL]が必要です。

restrictedは4つを必須として要求します。1つでも欠けると拒否され、エラーメッセージがどのフィールドが引っかかったかを教えてくれます。

もう1つ知っておいてください。runAsNonRoot: trueはUIDを指定しません。「rootで動かすな」と言っているだけなので、イメージがUIDを指定していないと、本物のノードではkubeletがPodを起動できず、CreateContainerConfigErrorが出ます。実際のクラスターでは、runAsUserを一緒に指定するか、非rootで作られたイメージを使ってください。このラボ環境はPodを実際には実行しないため、その違いは現れません。

違反したPodが拒否されることを確認する

cks-psa-strictに、privileged: trueのコンテナを持つPodbad-podをapplyしてみてください。その出力(標準エラー出力を含む)を/root/cks-securitycontext/denied.txtに保存します。Podが作成されてはいけません。

applyの標準出力と標準エラー出力を、一緒にファイルに残す必要があります。2>&1 | teeを使ってください。Podが作成されたなら、ポリシーが効いていないということです。

実行ユーザーとグループを指定する

cks-psaにPodnonroot-app(コンテナ名app)を作成してください。PodレベルのsecurityContextにrunAsNonRoot: true、runAsUser: 10001、runAsGroup: 10001、fsGroup: 20001を入れます。

runAsUser/runAsGroup/fsGroupはPodレベルのsecurityContextに、runAsNonRootは両方に書けます。fsGroupは、ボリューム内のファイルのグループ所有権を変更します。

seccompとcapabilityの組み合わせ

cks-psa-strictにPoddropped(コンテナ名app)を作成してください。PodレベルのseccompProfile.typeはRuntimeDefault、runAsNonRootはtrueとし、コンテナレベルにallowPrivilegeEscalation: false、capabilities.drop: [ALL]、readOnlyRootFilesystem: trueを入れます。

restrictedのネームスペースなので、このPodも4つの必須条件をすべて満たさないと作成されません。

RuntimeClassオブジェクト

RuntimeClasscks-sandboxを作成してください。handlerはrunsc、overhead.podFixedはメモリ160MiとCPU250mです。

RuntimeClassはクラスタースコープのリソースです。handlerの値は、ノードのコンテナランタイムの設定にあるランタイム名と、一文字ずつ同じでなければなりません。

総合: サンドボックスランタイムでデプロイする

cks-psa-strictにDeploymentpaymentsを作成してください。replicasは2、セレクターとPodラベルはapp=payments、PodスペックのruntimeClassNameはcks-sandboxとし、Podテンプレートは、restrictedを通過するようにステップ3と同じ4つの条件をすべて備えます。

DeploymentのPodテンプレートもPSAの検査を受けます。先に作成したRuntimeClassの名前を、PodスペックのruntimeClassNameに書きます。