AppArmor によるコンテナの保護

AppArmor は、ホスト オペレーティング システム上で実行されているプロセスの機能を制限するのに使用できる Linux カーネル セキュリティ モジュールです。各プロセスには独自のセキュリティ プロファイルを含めることができます。セキュリティ プロファイルは、ネットワーク アクセスやファイルの読み取り / 書き込み / 実行の権限などの特定の機能を許可または禁止します。

Container-Optimized OS インスタンスで実行される Docker コンテナで AppArmor を使用できます。任意のコンテナに対して、Docker に付属するデフォルトの AppArmor セキュリティ プロファイルか、提供されるカスタム セキュリティ プロファイルのいずれかを適用できます。

デフォルトの Docker AppArmor セキュリティ プロファイルの使用

Container-Optimized OS インスタンスでコンテナを起動すると、システムは自動的に docker-default AppArmor セキュリティ プロファイルを適用します。次のコマンド例は、docker-default セキュリティ プロファイルでコンテナを実行します。

docker run --rm -it debian:jessie bash -i

docker-default セキュリティ プロファイルをテストするには、次のように cat コマンドを使用して /proc/sysrq-trigger ファイルを次のように読み取ります。

root@88cef496c1a5:/# cat /proc/sysrq-trigger

出力には、次のような「アクセスが拒否されました」というエラーが含まれているはずです。

cat: /proc/sysrq-trigger: Permission denied

カスタム セキュリティ プロファイルの適用

別のセキュリティ プロファイルを適用するには、コンテナを実行するときに apparmor=<profile-name> コマンドライン オプションを使用します。次のコマンド例は、no-ping というセキュリティ プロファイルでコンテナを実行します。

docker run --rm -i --security-opt apparmor=no-ping debian:jessie bash -i

この例で指定する no-ping プロファイルの作成方法について詳しくは、このトピックのカスタム セキュリティ プロファイルの作成をご覧ください。

次の例のように、apparmor オプションに unconfined を指定し、コンテナをセキュリティ プロファイルなしで実行するように示すこともできます。

docker run --rm -it --security-opt apparmor=unconfined debian:jessie bash -i

アクティブな AppArmor セキュリティ プロファイルの表示

/proc/<pid>/attr/current ファイルを調べることによって、Container-Optimized OS インスタンスのプロセスに AppArmor プロファイルが適用されているかどうかを確認できます。<pid> はプロセス ID です。

インスタンス上で次のプロセスが実行されているとします(ps -ef | grep '[b]ash -i' コマンドで表示される)。

root      1903  1897  0 21:58 pts/3    00:00:00 docker run --rm -it debian:jessie bash -i
root      1927  1913  0 21:58 pts/4    00:00:00 bash -i
root      1978  1001  0 22:01 pts/0    00:00:00 docker run --rm -it --security-opt apparmor=unconfined debian:jessie bash -i
root      2001  1988  0 22:01 pts/2    00:00:00 bash -i

/proc/1927/attr/current を調べると、プロセス(pid 1927)がデフォルトの Docker セキュリティ プロファイルを使用して実行されたことを示す次の出力が表示されます。

# cat /proc/1927/attr/current
docker-default (enforce)

/proc/2001/attr/current を調べると、プロセス(pid 2001)がセキュリティ プロファイルなしで(つまり、オプション apparmor=unconfined を指定して)実行されたことを示す次の出力が表示されます。

# cat /proc/2001/attr/current
unconfined

カスタム セキュリティ プロファイルの作成

プロセスに docker-default とは異なるセキュリティ プロファイルが必要な場合は、独自のカスタム プロファイルを作成できます。カスタム プロファイルを使用するには、プロファイル ファイルを作成し、そのファイルを AppArmor にロードする必要があります。

たとえば、すべての未処理のネットワーク トラフィックを許可しないセキュリティ プロファイルが必要だとします。次のスクリプトは、no-ping というセキュリティ プロファイルのファイルを /etc/apparmor.d/no_raw_net に作成します。

cat > /etc/apparmor.d/no_raw_net <<EOF
#include <tunables/global>

profile no-ping flags=(attach_disconnected,mediate_deleted) {
  #include <abstractions/base>

  network inet tcp,
  network inet udp,
  network inet icmp,

  deny network raw,
  deny network packet,
  file,
  mount,
}
EOF

セキュリティ プロファイル ファイルを作成したら、apparmor_parser を使用して AppArmor にプロファイルを読み込むことができます。

/sbin/apparmor_parser --replace --write-cache /etc/apparmor.d/no_raw_net

読み込まれたら、次のように no-ping プロファイルをテストできます。

$ docker run --rm -i --security-opt apparmor=no-ping debian:jessie ping -c3 8.8.8.8

このコマンドは、no-ping セキュリティ プロファイルを持つコンテナを作成し、コンテナ内から ping を実行しようとします。セキュリティ プロファイルはトラフィックを許可しません。その結果、次のようなエラーが発生します。

ping: Lacking privilege for raw socket.

Container-Optimized OS インスタンスが起動し、再起動しても存続する場合に、カスタム セキュリティ プロファイルが必ず存在するようにするには、cloud-init を使用してプロファイルを /etc/apparmor.d にインストールします。これを行うには、インスタンスのメタデータに cloud-config スクリプトを user-data キーの値として追加します。

次の cloud-config スクリプトは、no-ping プロファイルを /etc/apparmor.dに追加します。

#cloud-configs

write_files:
- path: /etc/apparmor.d/no_raw_net
  permissions: 0644
  owner: root
  content: |
    #include <tunables/global>

    profile no-ping flags=(attach_disconnected,mediate_deleted) {
      #include <abstractions/base>

      network inet tcp,
      network inet udp,
      network inet icmp,

      deny network raw,
      deny network packet,
      file,
      mount,
    }

サービス ファイルがカスタム プロファイルを AppArmor に読み込んで Docker に使用させるようにするには、インスタンス上で次のコマンドを実行します。

ExecStartPre=/sbin/apparmor_parser -r -W /etc/apparmor.d/no_raw_net
ExecStart=/usr/bin/docker run --security-opt apparmor=no-ping ...

コマンドを実行した後、インスタンスを再起動すると、カスタム AppArmor プロファイルによって限定されたコンテナを実行できます。