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 と組み合わせる案もある.詳しくは以下の記事にまとめてある!