Seccomp와 AppArmor — 커널 레벨 보안 프로파일

Seccomp로 syscall을 제한하고 AppArmor로 파일/네트워크 접근을 제어하는 방법, RuntimeDefault 프로파일, 커스텀 프로파일 개발, Pod 설정 방법을 설명합니다.

· 6 min read · PALDYN Team

지난 글에서 Security Context로 파드 프로세스 권한을 설정하는 방법을 알아봤다. 이번에는 한 단계 더 깊이 들어가 커널 레벨 보안 메커니즘인 Seccomp와 AppArmor를 다룬다. Security Context의 capabilities가 “어떤 권한 그룹을 가질 수 있는가”를 제어한다면, Seccomp는 “어떤 시스템 콜을 호출할 수 있는가”를, AppArmor는 “어떤 파일과 네트워크에 접근할 수 있는가”를 제어한다. 이 둘은 심층 방어(Defense in Depth)를 완성하는 마지막 레이어다.

Seccomp 개요

Seccomp(Secure Computing Mode)는 Linux 커널 기능으로, 프로세스가 호출할 수 있는 시스템 콜(syscall)을 필터링한다. 컨테이너화된 앱이 kexec_load(커널 교체), mount(파일시스템 마운트) 같은 위험한 syscall을 호출하는 것을 원천 차단한다.

Seccomp vs AppArmor — 커널 레벨 보안

RuntimeDefault 프로파일 적용

가장 쉽고 효과적인 첫 단계는 RuntimeDefault를 사용하는 것이다. containerd/Docker의 기본 seccomp 프로파일로, 약 300개의 위험 syscall을 차단하면서 대부분의 앱이 정상 동작한다.

apiVersion: v1
kind: Pod
metadata:
  name: secure-pod
spec:
  securityContext:
    seccompProfile:
      type: RuntimeDefault   # containerd/Docker 기본 프로파일
  containers:
    - name: app
      image: my-app:latest
# RuntimeDefault 적용 확인
kubectl get pod secure-pod -o jsonpath=\
  '{.spec.securityContext.seccompProfile}'
# {"type":"RuntimeDefault"}

# 컨테이너 내에서 차단된 syscall 시도 (예: reboot)
kubectl exec secure-pod -- reboot
# Operation not permitted

Audit 모드로 필요한 Syscall 파악

커스텀 프로파일을 개발할 때는 먼저 Audit 모드로 필요한 syscall을 파악한다.

{
  "defaultAction": "SCMP_ACT_LOG",
  "syscalls": []
}

SCMP_ACT_LOG는 모든 syscall을 허용하되 커널 로그(dmesg)에 기록한다. 앱을 실제로 실행하면서 어떤 syscall이 호출되는지 확인할 수 있다.

# Audit 모드 실행 후 syscall 확인
dmesg | grep "type=SECCOMP" | awk '{print $NF}' | sort -u
# syscall=0  (read)
# syscall=1  (write)
# syscall=2  (open)
# ...

# syscall 번호를 이름으로 변환
ausyscall --dump | grep "^0\|^1\|^2"

Localhost 커스텀 프로파일

파악한 syscall로 화이트리스트 프로파일을 만들어 노드에 배포한다.

Seccomp 커스텀 프로파일 구조

# 프로파일을 모든 노드의 /var/lib/kubelet/seccomp/profiles/에 배포
# DaemonSet으로 배포하는 것이 권장됨

# 단일 노드 테스트
sudo mkdir -p /var/lib/kubelet/seccomp/profiles
sudo cp my-app.json /var/lib/kubelet/seccomp/profiles/
# Localhost 프로파일 사용
spec:
  securityContext:
    seccompProfile:
      type: Localhost
      localhostProfile: profiles/my-app.json

AppArmor 개요와 적용

AppArmor는 Ubuntu/Debian 배포판에 기본 탑재된 Mandatory Access Control 시스템이다. 파일 경로, 네트워크 소켓, 리소스 사용을 프로파일로 제한한다.

# 노드에서 AppArmor 지원 확인
cat /sys/module/apparmor/parameters/enabled
# Y

# 기본 Docker 프로파일 확인
sudo aa-status | grep docker
# docker-default (enforce)

# 커스텀 프로파일 생성 (기본 구조)
cat /etc/apparmor.d/k8s-my-app-profile
#include <tunables/global>

profile k8s-my-app flags=(attach_disconnected) {
  #include <abstractions/base>

  network inet tcp,              # TCP 연결 허용
  network inet udp,

  /app/my-app mr,                # 앱 바이너리 실행 허용 (r=read, m=memory map)
  /tmp/** rw,                    # /tmp 읽기/쓰기
  /var/log/** w,                 # 로그 디렉터리 쓰기
  deny /etc/shadow r,            # shadow 파일 읽기 금지
  deny /proc/sys/kernel/core_pattern w,  # core dump 경로 변경 금지
}
# AppArmor 프로파일 로드
sudo apparmor_parser -r -W /etc/apparmor.d/k8s-my-app-profile

# 프로파일 상태 확인
sudo aa-status | grep k8s-my-app
# k8s-my-app-profile (enforce)
# Pod에 AppArmor 프로파일 적용 (K8s 1.30+ securityContext 방식)
spec:
  securityContext:
    appArmorProfile:
      type: Localhost
      localhostProfile: k8s-my-app-profile
# K8s 1.30 미만에서는 어노테이션 방식
metadata:
  annotations:
    container.apparmor.security.beta.kubernetes.io/app: localhost/k8s-my-app-profile

complain 모드로 프로파일 개발

# complain 모드로 프로파일 로드 (차단 없이 로그만)
sudo aa-complain /etc/apparmor.d/k8s-my-app-profile

# 앱 실행 후 로그 확인
sudo journalctl -f | grep apparmor

# 로그 기반으로 프로파일 자동 업데이트
sudo aa-logprof
# 대화형으로 새로운 접근 패턴을 프로파일에 추가

Seccomp + AppArmor + Security Context 조합

가장 강력한 파드 하드닝은 세 가지를 함께 사용하는 것이다.

apiVersion: v1
kind: Pod
metadata:
  name: hardened-pod
spec:
  securityContext:
    runAsNonRoot: true
    runAsUser: 1000
    seccompProfile:
      type: RuntimeDefault        # Seccomp
    appArmorProfile:
      type: Localhost
      localhostProfile: k8s-my-app-profile  # AppArmor
  containers:
    - name: app
      image: my-app:latest
      securityContext:
        allowPrivilegeEscalation: false
        readOnlyRootFilesystem: true
        capabilities:
          drop: [ALL]             # Capabilities

Pod Security Standards와의 관계

프로파일Seccomp 요구사항
Privileged제한 없음
BaselineUnconfined만 차단
RestrictedRuntimeDefault 또는 Localhost 강제

Restricted 프로파일은 seccomp를 강제하므로, Restricted 정책을 사용하면 자동으로 최소한의 Seccomp 보호가 적용된다.


지난 글: 쿠버네티스 Security Context — 파드 보안 설정


읽어주셔서 감사합니다. 😊