AppArmor는 표준 리눅스 사용자와 그룹 기반의 권한을 보완하여, 한정된 리소스 집합으로 프로그램을 제한하는 리눅스 커널 보안 모듈이다. AppArmor는 임의의 애플리케이션에 대해서 잠재적인 공격 범위를 줄이고 더욱 심층적인 방어를 제공하도록 구성할 수 있다. 이 기능은 특정 프로그램이나 컨테이너에서 필요한 리눅스 기능, 네트워크 사용, 파일 권한 등에 대한 접근을 허용하는 프로파일로 구성한다. 각 프로파일은 허용하지 않은 리소스 접근을 차단하는 강제(enforcing) 모드 또는 위반만을 보고하는 불평(complain) 모드로 실행할 수 있다.
AppArmor를 쿠버네티스에서 사용하려면 다음 조건을 만족해야 한다.
예를 들어 한시간동안 sleep을 하는 파드를 생성한다고 가정해보자.
apiVersion: v1
kind: Pod
metadata:
name: ubuntu-sleeper
spec:
containers:
- name: hello
image: busybox
command: ["sh", "-c", "echo 'Sleeping for an hour!' && sleep 1h"]
이 파드는 sleep만 하면 되기 때문에, 파일시스템에 대해 쓰기 권한을 가질 필요가 없다.
이 파드가 파일시스템에 쓰기 작업을 하지 못하도록 노드에 다음과 같은 프로파일을 생성한다.
profile apparmor-deny-write flags=(attach_disconnected) {
file,
# Deny all file writes.
deny /** w,
}
프로파일이 작성되었다면, apparmor_parser 명령어를 사용하여 프로파일을 로드하고, aa-status 명령어를 사용하여 프로파일이 잘 로드되었는지 확인한다.
$ apparmor_parser -q ./apparmor-deny-write
$ aa-status
pparmor module is loaded.
57 profiles are loaded.
20 profiles are in enforce mode.
...
apparmor-deny-write
...
AppArmor 프로파일은 컨테이너 별로 적용이 가능하다.
아직은 베타 버전이기 때문에, 컨테이너에 AppArmor 프로파일을 적용하기 위해서는 Annotation을 사용한다.
apiVersion: v1
kind: Pod
metadata:
name: ubuntu-sleeper
annotations:
container.apparmor.security.beta.kubernetes.io/ubuntu-sleeper: localhost/apparmor-deny-write
spec:
containers:
- name: hello
image: busybox
command: ["sh", "-c", "echo 'Sleeping for an hour!' && sleep 1h"]
이제 파드를 실행시켜서 프로파일이 잘 적용되었는지 확인한다.
$ k apply -f ubuntu-sleeper.yaml
pod/ubuntu-sleeper created
$ k logs ubuntu-sleeper
sleeping for an hour
$ k exec -it ubuntu-sleeper -- touch /tmp/test
touch: cannot touch '/tmp/test/': Permission denied
command terminated with exit code 1
touch를 사용해서 파일을 생성하려고 했지만, 의도한 것처럼 실패한 것을 볼 수 있다.
컨테이너의 root 프로세스에 올바른 프로파일이 적용되어 있는지는 proc attr을 확인하여 검증할 수 있다.
$ k exec ubuntu-sleeper cat /proc/1/attr/current