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
출력에는 다음과 유사한 'Permission Denied' 오류가 있어야 합니다.
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
을 검사하면 기본 Docker 보안 프로필로 프로세스(pid 1927
)가 실행되었음을 나타내는 다음과 같은 출력을 볼 수 있습니다.
# cat /proc/1927/attr/current
docker-default (enforce)
/proc/2001/attr/current
을 검사하면 보안 프로필을 사용하지 않고(즉 apparmor=unconfined
옵션을 사용하여) 프로세스(pid 2001
)가 실행되었음을 나타내는 다음 결과가 표시됩니다.
# cat /proc/2001/attr/current
unconfined
커스텀 보안 프로필 만들기
docker-default
와 상이한 보안 프로필이 프로세스에 필요한 경우 고유한 커스텀 프로필을 만들 수 있습니다. 커스텀 프로필을 사용하려면 프로필을 만든 다음 해당 파일을 AppArmor에 로드해야 합니다.
예를 들어 모든 원시 네트워크 트래픽을 허용하지 않는 보안 프로필이 필요하다고 가정해 보겠습니다. 다음 스크립트는 /etc/apparmor.d/no_raw_net
에 no-ping
이라는 보안 프로필의 파일을 만듭니다.
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
에 프로필을 설치할 수 있습니다. 이를 위해 user-data
키 값으로 인스턴스 메타데이터에 cloud-config
스크립트를 추가합니다.
다음 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 프로필로 제한된 컨테이너를 실행할 수 있습니다.