AppArmor (Application Armor) とは Linux Security Modules の1つで,プログラムに対して「ファイル操作」や「マウント操作」などを制限する.詳しくは以下のドキュメントに載っている.
コンテナワークロードのセキュリティ対策として,AppArmor を Kubernetes でも多層防御として使える.今まで試したことがなく,今回は以下の検証環境を使って「Kubernetes と AppArmor」を組み合わせた基本的な制限を試していく!
- Kubernetes v1.23.0
- ワーカーノード : Ubuntu 20.04.3 LTS
AppArmor プロファイル
AppArmor では「AppArmor プロファイル」を作って読み込ませる必要がある.今回は Kubernetes ドキュメントに載っている以下のサンプルを使う.構文は少し複雑に見えるけど w = write
を deny
なので「全てのディレクトリでファイル操作(書き込み)を制限するプロファイル」と言える.
#include <tunables/global> profile k8s-apparmor-example-deny-write flags=(attach_disconnected) { #include <abstractions/base> file, # Deny all file writes. deny /** w, }
準備 : AppArmor 適用前
AppArmor を適用する前に通常の動作確認をする.以下のマニフェストを使って Ubuntu Pod を起動する.
apiVersion: v1 kind: Pod metadata: name: ubuntu spec: containers: - name: ubuntu image: ubuntu:21.10 command: - sleep - infinity
Ubuntu Pod に接続をしてファイル操作(書き込み)を試す.期待通りに書き込めた.
/hello.txt
: OK/tmp/hello.txt
: OK
$ kubectl apply -f ubuntu.yaml $ kubectl exec -it ubuntu -- /bin/sh # echo 'hello' > hello.txt # cat hello.txt hello # echo 'hello' > /tmp/hello.txt # cat /tmp/hello.txt hello
検証 : 全てのディレクトリでファイル操作(書き込み)を制限する
さっそく AppArmor を適用する.まず,ワーカーノードに「AppArmor プロファイル」を読み込ませる.さっき紹介したプロファイルを k8s-apparmor-example-deny-write
として保存して,apparmor_parser
コマンドを使って読み込ませる.読み込ませたら aa-status
コマンドを使って確認できる.
- Ubuntu Manpage: apparmor_parser - loads AppArmor profiles into the kernel
- Ubuntu Manpage: aa-status - display various information about the current AppArmor policy.
$ sudo apparmor_parser k8s-apparmor-example-deny-write $ sudo aa-status | egrep 'profiles|k8s-apparmor-example-deny-write' 38 profiles are loaded. 36 profiles are in enforce mode. k8s-apparmor-example-deny-write 2 profiles are in complain mode. 5 processes have profiles defined.
次にマニフェストを更新して Ubuntu Pod を起動し直す.Pod に AppArmor プロファイルを適用する場合は annotations
を追加する.今回は container.apparmor.security.beta.kubernetes.io/ubuntu: localhost/k8s-apparmor-example-deny-write
とした.ubuntu
はコンテナ名で localhost/k8s-apparmor-example-deny-write
は AppArmor プロファイル名を意味している.
apiVersion: v1 kind: Pod metadata: name: ubuntu annotations: container.apparmor.security.beta.kubernetes.io/ubuntu: localhost/k8s-apparmor-example-deny-write spec: containers: - name: ubuntu image: ubuntu:21.10 command: - sleep - infinity
もう一度 Ubuntu Pod に接続をしてファイル操作(書き込み)を試す.今度は AppArmor によって制限されているため失敗した.エラー内容としては Permission denied
になった.
/hello.txt
: NG/tmp/hello.txt
: NG
$ kubectl apply -f ubuntu.yaml $ kubectl exec -it ubuntu -- /bin/sh # echo 'hello' > hello.txt /bin/sh: 1: cannot create hello.txt: Permission denied # echo 'hello' > /tmp/hello.txt /bin/sh: 3: cannot create /tmp/hello.txt: Permission denied
検証 : /tmp でファイル操作(書き込み)を制限する
今度は AppArmor プロファイルを更新して,/tmp
に限定してファイル操作(書き込み)を制限する.更新箇所は deny /** w,
から deny /tmp/** w,
とした.
#include <tunables/global> profile k8s-apparmor-example-deny-write flags=(attach_disconnected) { #include <abstractions/base> file, # Deny all file writes. deny /tmp/** w, }
改めてワーカーノードで「AppArmor プロファイル」を読み込ませる.同じく apparmor_parser
コマンドを使うけど,更新するときは apparmor_parser -r
コマンドを使う.
$ sudo apparmor_parser -r k8s-apparmor-example-deny-write
もう一度 Ubuntu Pod に接続をしてファイル操作(書き込み)を試す.今度は AppArmor によって制限されているため /tmp
のみ失敗した.
/hello.txt
: OK/tmp/hello.txt
: NG
$ kubectl apply -f ubuntu.yaml $ kubectl exec -it ubuntu -- /bin/sh # echo 'hello' > hello.txt # cat hello.txt hello # echo 'hello' > /tmp/hello.txt /bin/sh: 5: cannot create /tmp/hello.txt: Permission denied
参考 : AppArmor プロファイルを生成する
今回は Kubernetes ドキュメントに載っているサンプルを使ったけど,ファイル操作以外も制限できる.AppArmor の apparmor-easyprof
コマンド(簡易的な雛形のみ)や aa-genprof
コマンド(プロファイリングもする)を使うと「AppArmor プロファイル」を生成できる.
aa-genprof
コマンドを使うと自動的に /etc/apparmor.d/
に AppArmor プロファイルが生成されるので,例えば /usr/bin/curl
を制限する場合は /etc/apparmor.d/usr.bin.curl
というプロファイルになる.今回は w
以外に m = memory map executable
と r = read
が追加されている.
- Ubuntu Manpage: aa-easyprof - AppArmor profile generation made easy.
- Ubuntu Manpage: aa-genprof - profile generation utility for AppArmor
$ sudo apt install -y apparmor-utils $ sudo apt install -y apparmor-easyprof $ sudo aa-easyprof /usr/bin/curl # vim:syntax=apparmor # AppArmor policy for curl # ###AUTHOR### # ###COPYRIGHT### # ###COMMENT### #include <tunables/global> # No template variables specified "/usr/bin/curl" { #include <abstractions/base> # No abstractions specified # No policy groups specified # No read paths specified # No write paths specified } $ sudo aa-genprof /usr/bin/curl (中略) [(S)can system log for AppArmor events] / (F)inish (中略) Finished generating profile for /usr/bin/curl. $ cat /etc/apparmor.d/usr.bin.curl # Last Modified: Fri Apr 8 04:20:37 2022 #include <tunables/global> /usr/bin/curl { #include <abstractions/base> /usr/bin/curl mr, }
まとめ
コンテナワークロードのセキュリティ対策として,AppArmor と Kubernetes の組み合わせを試した.実際にファイル操作を制限した Pod を起動できた!
関連記事
システムコールを制限するなら seccomp と組み合わせる案もある.詳しくは以下の記事にまとめてある!