UbuntuでのAppArmorのメモ

背景

containerdをrootlessで動かそうとしたところAppArmorに引っかかってしまった

(私の場合、/mnt配下の追加ディスク上にコンテナイメージを置きたい、という背景があったため引っかかったと思われる)

標準的なディレクトリ以外で動作させようとした場合に問題になりそう。

下記のエラーが出た

Mar  6 00:39:00 marie-ms7817 systemd[1055]: Started libcontainer container d1b514a134af96a15f5062afe042fd8654d91b2be4bef27f9af5865e29d2cad7.
Mar  6 00:40:30 marie-ms7817 kernel: [ 7375.140738] audit: type=1400 audit(1709653230.078:103): apparmor="DENIED" operation="change_onexec" class="file" info="label not found" error=-2 profile="unconfined" name="nerdctl-default" pid=54813 comm="aa-exec"

apparmor=“DENIED operation=“change_onexec” このメッセージは、AppArmor(Linuxのセキュリティモジュールの一つ)が、実行時の権限変更を拒否したことを示している。 特に、name=“nerdctl-default"に関連する操作が拒否されており、これはコンテナのセキュリティポリシーに関連する問題を示唆している。 label not foundという部分から、特定のセキュリティラベルが見つからない、または適切に設定されていない可能性がある。

既存の設定前の確認

nerdctl-defaultに関連する設定があるか確認。 下記コマンドで現在のAppArmorの設定のリストを出力し設定があるか確認(無かった)

sudo aa-status

ポリシーファイルの作成

/etc/apparmor.d ディレクトリに nerdctl-default という名前の新しい AppArmor ポリシーファイルを作成する。

/etc/apparmor.d/nerdctl-default とした。

#include <tunables/global>

profile nerdctl-default flags=(attach_disconnected,mediate_deleted) {
    / r,
    /dev/tty rw,
    /dev/pts/** w,
    /dev/null rw,
    /etc/.ro*/ld.so.cache r,
    /etc/ld.so.cache r,
    /etc/locale.alias r,
    /etc/nsswitch.conf r,
    /etc/passwd r,
    /mnt/append-disk/containerd/** rwk,
    /proc/ r,
    /proc/** r,
    /sys/devices/system/** r,
    /sys/kernel/mm/transparent_hugepage/hpage_pmd_size r,
    /usr/bin/** rix,
    /usr/lib/locale/locale-archive r,
    /usr/lib/x86_64-linux-gnu/** rm,
    /usr/lib/locale/** r,
    /usr/share/terminfo/** r,
    /var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/** rwk,
    /var/lib/containerd/** rwk,
    owner /** rwix,
    network,
    ptrace (read, readby) peer=nerdctl-default,
    signal (receive) peer=nerdctl-default,
    signal (receive) peer=unconfined,
    signal (send) peer=nerdctl-default,
    signal (send) set=kill peer=unconfined,
}

それぞれの意味。

  • #include <tunables/global>
    • AppArmor のグローバルな設定(共通の定義や変数など)をこのプロファイルにインクルードします。これにより、一貫性のあるセキュリティ設定がプロファイル間で共有されます。
  • profile nerdctl-default flags=(attach_disconnected,mediate_deleted)
    • nerdctl-default という名前のプロファイルを定義します。
      • フラグ attach_disconnected は、プロセスが名前空間やIPCから切断された状態で起動される場合に関連します。mediate_deleted は、削除されたファイルへのアクセスを制御します。
  • /usr/bin/nerdctl rmix
    • /usr/bin/nerdctl に対して、読み取り(r)、マッピング(m)、実行(ix)のアクセスを許可します。ix は、実行可能ファイルがプロファイルの制約内で実行されることを意味します。
  • /var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/** rwk
    • /var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/ 以下の全てのファイルとディレクトリに対して、読み取り(r)、書き込み(w)、ロック(k)のアクセスを許可します。これは、コンテナのスナップショットやオーバーレイファイルシステムに関連する操作を可能にします。
  • /var/lib/containerd/** rwk
    • /var/lib/containerd/ 以下の全てのファイルとディレクトリに対して、同様に読み取り(r)、書き込み(w)、ロック(k)のアクセスを許可します。これは、コンテナランタイムのデータやメタデータに広範なアクセスを可能にします。
  • network
    • ネットワークへのアクセスを許可します。
  • /mnt/append-disk/containerd/** rwk
    • 追加されたディスク上の /mnt/append-disk/containerd/ 以下の全てのファイルとディレクトリに対して、読み取り(r)、書き込み(w)、ロック(k)のアクセスを許可します。これは、特定のストレージパスへのアクセスが必要な場合に有用。
  • /etc/** r
    • /etc/ ディレクトリ以下の全てのファイルに対して読み取り(r)のアクセスを許可します。これにより、システムの設定ファイルへの読み取りアクセスが可能になる(ただし範囲は狭めたい)
  • /usr/lib/x86_64-linux-gnu/libc.so.6 rm,
    • 標準Cライブラリ /usr/lib/x86_64-linux-gnu/libc.so.6 に対して、読み取り(r)とメモリマッピング(m)のアクセスを許可します。これは、ほとんどのプログラムが依存する基本的なライブラリへのアクセスを必要とするためです。

実行権限(x)について

実行権限(x)を付与する際には、特定の実行修飾子(ix、px、cx、または ux)を使用する必要がある。 これらの修飾子は、プロセスが新しいプログラムをどのように実行するかを制御し、プロセスのセキュリティコンテキストの扱いを定義する。

  • ix(継承実行): 新しいプログラムが現在のプロファイルのセキュリティコンテキストを継承します。
  • px(プロファイル実行): 新しいプログラムが指定されたプロファイル(またはそのプログラムのデフォルトプロファイル)で実行されます。
  • cx(子プロファイル実行): 新しいプログラムが動的に生成されたプロファイルで実行されます。
  • ux(非制限実行): 新しいプログラムがAppArmorの制御なしで実行されます。

ポリシーのロード

sudo apparmor_parser -r /etc/apparmor.d/プロファイル名

私は下記のようにロードした。

sudo apparmor_parser -r /etc/apparmor.d/nerdctl-default

ポリシーのデバッグ

/var/log/syslogを見つつ試行錯誤が結構ある。 下記のワンライナーを使いつつ徐々にAppArmorの設定を行った。

tac /var/log/syslog | grep apparmor | less && vi /etc/apparmor.d/nerdctl-default && apparmor_parser -r /etc/apparmor.d/nerdctl-default

参考