今日覚えて帰ること
AppArmorの概要
- 実行ファイルごとに詳細なアクセス制御を設定するためことを目的とした、Linuxカーネルのセキュリティモジュールのこと
- aa-statusでプロファイルのステータスが確認できる
- apparmor_parsor -r <path> でプロファイルを読み込める
AppArmor
Check existing AppArmor profiles
You’re asked to verify if the following AppArmor profiles are available on
node01
:docker-default snap.lxd.lxc ftpd /usr/sbin/tcpdump
Create file
/root/profiles.txt
on nodecontrolplane
. It should contain only these profile names that are available onnode01
.
node01で有効化されているAppArmor profileを確認し、有効であるプロファイル名をcontrolplaneの
/root/profiles.txtに書き込めというお題です。
sshでnode01にログインし、apparmor_statusコマンドを実行して有効になっているプロファイルを確認します。
controlplane $ ssh node01
Last login: Mon Jul 29 12:40:31 2024 from 10.244.5.178
node01 $ apparmor_status
apparmor module is loaded.
30 profiles are loaded.
30 profiles are in enforce mode.
/snap/snapd/21759/usr/lib/snapd/snap-confine
/snap/snapd/21759/usr/lib/snapd/snap-confine//mount-namespace-capture-helper
/usr/bin/man
/usr/lib/NetworkManager/nm-dhcp-client.action
/usr/lib/NetworkManager/nm-dhcp-helper
/usr/lib/connman/scripts/dhclient-script
/usr/lib/snapd/snap-confine
/usr/lib/snapd/snap-confine//mount-namespace-capture-helper
/usr/sbin/tcpdump
/{,usr/}sbin/dhclient
cri-containerd.apparmor.d
docker-default
lsb_release
man_filter
man_groff
nvidia_modprobe
nvidia_modprobe//kmod
snap-update-ns.lxd
snap.lxd.activate
snap.lxd.benchmark
snap.lxd.buginfo
snap.lxd.check-kernel
snap.lxd.daemon
snap.lxd.hook.configure
snap.lxd.hook.install
snap.lxd.hook.remove
snap.lxd.lxc
snap.lxd.lxc-to-lxd
snap.lxd.lxd
snap.lxd.migrate
0 profiles are in complain mode.
5 processes have profiles defined.
5 processes are in enforce mode.
/usr/sbin/dhclient (656) /{,usr/}sbin/dhclient
/usr/sbin/dhclient (769) /{,usr/}sbin/dhclient
/usr/sbin/dhclient (1017) /{,usr/}sbin/dhclient
/coredns (2232) cri-containerd.apparmor.d
/coredns (2399) cri-containerd.apparmor.d
0 processes are in complain mode.
0 processes are unconfined but have a profile defined.
node01 $
問題文に記載されているprofileのうち、node01で有効化されているプロファイルは以下の3つです。
docker-default
snap.lxd.lxc
/usr/sbin/tcpdump
これをcontrolplaneの /root/profiles.txt に書き込めばOKです。
この設問はこれでOKですが、そもそもAppArmorとは何なのでしょうか?
AppArmor
AppArmorとは、実行ファイルごとに詳細なアクセス制御を設定するためことを目的とした、Linuxカーネルのセキュリティモジュールです。
CKSの試験対策記事を見てみると、一からプロファイルを設定できる必要はなさそうで、
- プロファイルをAppArmorへ登録すること
- プロファイルをPod上のコンテナへ適用すること
この2点を抑えておけばよさそうです。
apparmor-utilsをインストールすることで使えるようになる便利なコマンドがいくつかあります。
CKSで使用するエミュレータには最初からapparmor-utilsはインストールされています。
- aa-status(ファイルやプロセスのプロファイルへの適用状態を確認できる)
- apparmor-parser(AppArmorプロファイルを読み込み、解析し、カーネルにロードする)
- -a <path> (<path>プロファイルを追加する。add。)
- -r <path> (既存の<path>プロファイルを上書きする。replace。)
- -p <path> (<path>プロファイルの前処理(プリプロセス)行う。preprocess。)
などなど。
困ったときは我らが -h コマンドでヘルプを求めることが出来ます。
Fix Deployment with wrong AppArmor config
There is an existing Deployment named
spacecow
in Namespacemoon
.It should be configured to use AppArmor profile
docker-default
, but something seems wrong.Fix it.
Developmentに対してAppArmorのプロファイルを使って権限の制御を行え、という問題です。
どこかに設定ミスがあるようです。
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
container.apparmor.security.beta.kubernetes.io/httpd: localhost/docker-default
deployment.kubernetes.io/revision: "2"
creationTimestamp: "2024-07-29T15:05:03Z"
generation: 2
name: spacecow
///
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
dnsPolicy: ClusterFirst
restartPolicy: Always
schedulerName: default-scheduler
securityContext:
appArmorProfile:
localhostProfile: docker
type: Localhost
長くなるので間は省略しています。
公式ページを読むと、PodでAppArmorを使用したいならannotationを設定する必要があると書いています。
しかし、このシナリオではsecurityContextを編集するだけで良かったみたいです。
(解答にそう書いていた。)
アノテーションがあっても正解だったので、そちらで指定しても問題ないのかもしれないですね。
→ Kubernetes v1.30からアノテーションは廃止になったみたいです。やはり英語版を読むべきですね。
修正出来たら、そのpodが実際に稼働しているワーカーノード(今回はnode01)にsshでログインして、そのpodに本当にapparmorが適用されているか確認します。
以下のようにすればよいです。
controlplane $ ssh node01
Last login: Sun Nov 13 17:27:09 2022 from 10.48.0.33
node01 $ crictl ps
CONTAINER IMAGE CREATED STATE NAME ATTEMPT POD ID POD
e0e4bc7cf61b1 294cecd6c7790 39 seconds ago Running httpd 0 111bd5424d3c8 spacecow-c4b49d8cc-7vrrl
///
c1d532ed0f305 a0bf559e280cf 6 minutes ago Running kube-proxy 1 35f4ec0c9bf66 kube-proxy-nhmtq
node01 $ crictl inspect e0e4bc7cf61b1 | grep apparmor
"apparmor": {
"apparmor_profile": "localhost/docker-default"
"apparmorProfile": "docker-default",
node01 $
k logs でチェックしようと思いましたが、大したログは出てきませんでした。
controlplane $ k logs -n moon spacecow-c4b49d8cc-7vrrl
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 192.168.1.9. Set the 'ServerName' directive globally to suppress this message
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 192.168.1.9. Set the 'ServerName' directive globally to suppress this message
[Mon Jul 29 16:06:02.014348 2024] [mpm_event:notice] [pid 1:tid 140677577182024] AH00489: Apache/2.4.52 (Unix) configured -- resuming normal operations
[Mon Jul 29 16:06:02.014526 2024] [core:notice] [pid 1:tid 140677577182024] AH00094: Command line: 'httpd -D FOREGROUND'
回答に記載されてる確認方法は
- podが動いているnodeにログイン(今回はnode01)
- crictl psでcontainerIDを検索
- crictl logsでログを確認
という手順でしたが、k logsと同じログが出ただけでした。
公式サイトではk execで入り込んで cat /proc/1/attr/current をすれば確認できるとのことでした。
実際にやってみたらドンピシャで確認できました。
controlplane $ k exec -n moon spacecow-c4b49d8cc-9xcmn -- cat /proc/1/attr/current
docker-default (enforce)
Install AppArmor profile on nodes
There is an AppArmor profile at
/root/profile
.It should be referenced by name
docker-nginx-custom
, change the profile if needed.Install it on nodes
controlplane
andnode01
.
プロファイルの名前を変更し、各ノードにインストールせよ、という問題ですね。
まずはプロファイルの中身を確認します。
controlplane $ cat /root/profile
#include <tunables/global>
profile docker-nginx flags=(attach_disconnected,mediate_deleted) {
#include <abstractions/base>
network inet tcp,
///
deny /sys/firmware/** rwklx,
deny /sys/kernel/security/** rwklx,
}
controlplane $
先頭の #include <tunables/global> はいわゆるおまじないで、/etc/apparmor.d/tunables/globalに記述されている環境変数などをインクルード(読み込み)します。
プロファイルの名前がdocker-nginxとなっているので、docker-nginx-customに変更します。
controlplane $ cat /root/profile
#include <tunables/global>
profile docker-nginx-custom flags=(attach_disconnected,mediate_deleted) {
#include <abstractions/base>
network inet tcp,
///
deny /sys/firmware/** rwklx,
deny /sys/kernel/security/** rwklx,
}
controlplane $
変更後は apparmor_parsarコマンド を使ってプロファイルを読み込みなおします。
-r オプションは本来 repalce を意味し、既存のプロファイルを読み込みなおすために使用します。
しかし、新規ファイルを読み込むこともできるのでとりあえず -r オプションを使うのが良いと思います。
controlplane $ apparmor_parser -r /root/profile
aa-statusでプロファイルの状況を確認します。
controlplane $ aa-status
apparmor module is loaded.
38 profiles are loaded.
38 profiles are in enforce mode.
/snap/snapd/21759/usr/lib/snapd/snap-confine
///
/{,usr/}sbin/dhclient
cri-containerd.apparmor.d
docker-default
docker-nginx-custom
///
/usr/bin/local-path-provisioner (4179) cri-containerd.apparmor.d
0 processes are in complain mode.
0 processes are unconfined but have a profile defined.
読み込まれています。
プロファイルの読み込みは node 毎に行う必要があるので node01 でもプロファイルを読み込みます。
scpでcontrolplaneからnode01にファイルをコピーします。
controlplane $ scp /root/profile node01:/root/profile
先ほどと同様のコマンドを実行します。
controlplane $ ssh node01
Last login: Tue Jul 30 10:47:08 2024 from 10.244.6.33
node01 $ apparmor_parser -r /root/profile
node01 $ aa-status
apparmor module is loaded.
31 profiles are loaded.
31 profiles are in enforce mode.
/snap/snapd/21759/usr/lib/snapd/snap-confine
/snap/snapd/21759/usr/lib/snapd/snap-confine//mount-namespace-capture-helper
///
/{,usr/}sbin/dhclient
cri-containerd.apparmor.d
docker-default
docker-nginx-custom
///
/usr/local/apache2/bin/httpd (4465) docker-default
0 processes are in complain mode.
0 processes are unconfined but have a profile defined.
node01 $
Kubernetes 1.30 には、AppArmor プロファイルをノードにロードするための組み込みメカニズムは用意されていないので、実運用の際には何らかの仕組みで全てのノードにプロファイルをロードする仕組みが必要です。