「Oracle Cloud Hangout Cafe (OCHaCafe)」ダイジェスト 4

System Hardening

System Hardening

ここでは、システムの強化という観点から、Kubernetesクラスタを支えるノード(ホスト)とKubernetesのセキュリティについて学びます。ノード(ホスト)のOSにおいて、カーネルのセキュリティモジュールであるAppArmorとseccompを利用してKubernetesのセキュリティを強化することを理解します。

AppArmor

AppArmorはLinuxカーネルのセキュリティモジュールです。プロファイルを作成して読み取り、書き込み、プログラムの実行やファイルシステムのマウントなどシステム機能を制御できます。例えば、コンテナからノード(ホスト)のディレクトリをbind-mountした場合に、ディレクトリ全体ではなく個別のファイルやディレクトリに権限を設定できます。

AppArmor

AppArmorとKubernetesクラスタとのセキュリティを理解するために、AppArmorの制御プロファイルを作成し、Kubernetesクラスタ上のPodからファイルの書き込みができない環境を構築します。

AppArmorの使用例

1. AppArmorの有効確認
最初にノード(ホスト)のOSにログインし、AppArmorが有効であるかを確認します。「Y」と表示されれば有効です。

$ cat /sys/module/apparmor/parameters/enable

Y

2. AppArmorプロファイルの作成
次に、AppArmorプロファイルを「/etc/apparmor.d/k8s-apparmor-example-deny-write」として作成します。

$ vim /etc/apparmor.d/k8s-apparmor-example-deny-write

#include <tunables/global>

profile k8s-apparmor-example-deny-write flags=(attach_disconnected) {
  #include <abstractions/base>

  file,

  # Deny all file writes.
  deny /** w,
}

3. AppArmorプロファイルの登録
apparmor_parserコマンドを実行して、AppArmorプロファイルを作成します。

$ apparmor_parser -q /etc/apparmor.d/k8s-apparmor-example-deny-write

登録できたことを確認します。

$ aa-status | grep k8s-apparmor-example-deny-write

k8s-apparmor-example-deny-write
/usr/bin/sleep (92896) k8s-apparmor-example-deny-write

以上で、ノード(ホスト)側での作業は完了です。

4. AppArmorプロファイルを定義したマニフェストの作成
登録したAppArmorプロファイルをannotationsに定義したPodのマニフェストを作成します。

【マニフェスト:hello-apparmor.yaml】
apiVersion: v1
kind: Pod
metadata:
  name: hello-apparmor
  annotations:
    # Tell Kubernetes to apply the AppArmor profile "k8s-apparmor-example-deny-write".
    # Note that this is ignored if the Kubernetes node is not running version 1.4 or greater.
    container.apparmor.security.beta.kubernetes.io/hello: localhost/k8s-apparmor-example-deny-write
spec:
  containers:
  - name: hello
    image: busybox
    command: [ "sh", "-c", "echo 'Hello AppArmor!' && sleep 1h" ]

5. マニフェストの適用と確認

$ kubectl apply -f hello-apparmor.yaml

pod/hello-apparmor created

Pod(hello-apparmor)がRunningであるかを確認します。

$ kubectl get pods

NAME                      READY   STATUS      RESTARTS   AGE
hello-apparmor            1/1     Running     0          26s

hello-apparmorに接続し、定義したAppArmorプロファイルで実行されていることを確認します。

$ kubectl exec hello-apparmor -- cat /proc/1/attr/current

k8s-apparmor-example-deny-write (enforce)

「k8s-apparmor-example-deny-write(enforce)」と表示されれば問題ありません。

6. ファイル書き込みによる動作確認
hello-apparmorに接続し、touchコマンドを実行してファイル作成を試みます。

$ kubectl exec hello-apparmor -- touch /tmp/test

touch: /tmp/file: Permission denied
command terminated with exit code 1

Permission deniedとなり、ファイルを作成できません。

seccomp

seccompもLinuxカーネルのセキュリティモジュールです。プロファイルを作成して、コンテナが呼び出せるシステムコール(プロセス)を制御できます。不要なシステムコールを制限することで、カーネルの脆弱性を狙った攻撃を防ぎます。

例えば、chmodに関連するシステムコールを拒否するプロファイルを作成して、「$ docker run」コマンド実行時にオプションとしてプロファイル名を指定します。起動したコンテナ内でchmodコマンドを実行するとエラーとなり、権限設定ができません。

seccomp

seccompとKubernetesクラスタとのセキュリティを理解するために、seccompの制御プロファイルを作成し、Kubernetesクラスタ上のPodからmkdirコマンドを実行してもディレクトリを作成できない環境を構築します。

seccompの使用例

1. seccompの有効確認
最初にノード(ホスト)のOSにログインし、seccompが有効であるかを確認します。「CONFIG_SECCOMP=y」と表示されれば有効です。

$ grep CONFIG_SECCOMP= /boot/config-$(uname -r)

CONFIG_SECCOMP=y

2. seccompプロファイルの作成
次に、専用ディレクトリを作成してからプロファイルを作成します。

$ mkdir -p /var/lib/kubelet/seccomp/profiles

$ vim /var/lib/kubelet/seccomp/profiles/prohibit-mkdir.json
{
  "defaultAction": "SCMP_ACT_ALLOW",
  "syscalls": [
    {
      "names": ["mkdir","mkdirat"],
      "action": "SCMP_ACT_ERRNO"
    }
  ]
}

以上で、ノード(ホスト)側での作業は完了です。

3. seccompプロファイルを定義したマニフェストの作成と適用
作成したseccompプロファイルを定義したPodのマニフェストを作成します。

【マニフェスト:prohibit-mkdir.yaml】
apiVersion: v1
apiVersion: v1
kind: Pod
metadata:
  name: prohibit-mkdir
spec:
  securityContext:
    seccompProfile:
      type: Localhost
      localhostProfile: profiles/prohibit-mkdir.json
  containers:
    - name: ubuntu
      image: ubuntu:21.10
      command:
        - sleep
        - infinity

「spec.securityContext.seccompProfile」では、以下を定義できます。

  • localhostProfile:ノード(ホスト)上の「/var/lib/kubelet/seccomp」ディレクトリ内のファイルをProfileとして指定
    ※Kubernetes 1.19以前はannotationで指定、1.19以降はsecurityContextで指定
  • RuntimeDefault:CRIランタイムのデフォルトプロファイル指定
  • unconfined:seccomp不使用(デフォルト)

seccompにおいて、ホワイトリストでプロファイルをカスタマイズして作成することはセキュリティを高められますが、運用の煩雑さにつながるところもあります。場合によっては、ある程度コンテナアプリケーションで利用しないsyscallを制限したProfile(RuntimeDefault)の利用を検討する余地もあります。

マニフェストを適用します。

$ kubectl apply -f prohibit-mkdir.yaml

pod/prohibit-mkdir created

Pod(prohibit-mkdir)がRunningであるかを確認します。

$ kubectl get pods

NAME                      READY   STATUS      RESTARTS   AGE
prohibit-mkdir            1/1     Running     0          16s

4. 動作確認
prohibit-mkdirに接続して、ディレクトリ作成ができないことを確認します。

$ kubectl exec -it prohibit-mkdir -- mkdir test

mkdir: cannot create directory 'test': Operation not permitted
command terminated with exit code 1

Kubernetes v1.25からSeccompDefaultという機能が追加され、Podのspecでprofileを指定しなかった場合にRuntimeDefaultでコンテナを動かすことができます。

この記事のキーワード

この記事をシェアしてください

人気記事トップ10

人気記事ランキングをもっと見る