본문 바로가기
  • 오늘처럼
소프트웨어 아키텍처/Kubernetes

Kubernetes 와 Seccomp

by bluefriday 2022. 9. 23.
반응형

Kubernetes 에서의 seccomp

docker 와 마찬가지로, kubernetes 또한 어플리케이션이 모든 시스템 함수에 대한 권한을 갖는 걸 막기 위하여, seccomp 필터를 사용할 수 있다. 여기서는 docker 와 비교되는 kubernetes 의 seccomp 사용에 대해 확인해본다.

먼저 docker 가 default seccomp profile 을 이용하여 시스템 함수를 필터링 하는 결과를 확인해 보기 위해 다음의 오픈소스를 이용한다.

컨테이너에 대한 인스펙션 툴로 아래와 같이 사용할 수 있다.

# docker run --rm -it r.j3ss.co/amicontained amicontained

Container Runtime: not-found
Has Namespaces:
        pid: true
        user: false
AppArmor Profile: docker-default (enforce)
Capabilities:
        BOUNDING -> chown dac_override fowner fsetid kill setgid setuid 
        setpcap net_bind_service net_raw sys_chroot mknod audit_write setfcap
Seccomp: filtering
Blocked Syscalls (61):
        PTRACE SYSLOG SETPGID SETSID USELIB USTAT SYSFS VHANGUP PIVOT_ROOT _SYSCTL ACCT 
        SETTIMEOFDAY MOUNT UMOUNT2 SWAPON SWAPOFF REBOOT SETHOSTNAME SETDOMAINNAME IOPL 
        IOPERM CREATE_MODULE INIT_MODULE DELETE_MODULE GET_KERNEL_SYMS QUERY_MODULE QUOTACTL 
        NFSSERVCTL GETPMSG PUTPMSG AFS_SYSCALL TUXCALL SECURITY LOOKUP_DCOOKIE CLOCK_SETTIME 
        VSERVER MBIND SET_MEMPOLICY GET_MEMPOLICY KEXEC_LOAD ADD_KEY REQUEST_KEY KEYCTL 
        MIGRATE_PAGES UNSHARE MOVE_PAGES PERF_EVENT_OPEN FANOTIFY_INIT NAME_TO_HANDLE_AT 
        OPEN_BY_HANDLE_AT SETNS PROCESS_VM_READV PROCESS_VM_WRITEV KCMP FINIT_MODULE 
        KEXEC_FILE_LOAD BPF USERFAULTFD PKEY_MPROTECT PKEY_ALLOC PKEY_FREE
Looking for Docker.sock
#

꼭 위 인스펙션 툴을 사용할 필요는 없다. 여기서는 kubernetes 와의 차이를 보기 위함이다. 위 결과를 보면 seccomp 항목이 'filtering' 상태로 되어 있으며 약 61개의 syscall 이 거부(blocked) 되어 있음을 확인할 수 있다.

이번에는 동일한 이미지를 kubernetes 클러스터의 파드로 배포해본다.

$ kubectl run amicontained --image r.j3ss.co/amicontained amicontained -- amicontained
pod/amicontained created
$
$ kubectl logs amicontained
Container Runtime: kube
Has Namespaces:
        pid: true
        user: false
AppArmor Profile: cri-containerd.apparmor.d (enforce)
Capabilities:
        BOUNDING -> chown dac_override fowner fsetid kill setgid setuid setpcap 
        net_bind_service net_raw sys_chroot mknod audit_write setfcap
Seccomp: disabled
Blocked Syscalls (20):
        SYSLOG SETPGID SETSID VHANGUP PIVOT_ROOT ACCT SETTIMEOFDAY SWAPON SWAPOFF 
        REBOOT SETHOSTNAME SETDOMAINNAME INIT_MODULE DELETE_MODULE LOOKUP_DCOOKIE 
        FANOTIFY_INIT OPEN_BY_HANDLE_AT FINIT_MODULE KEXEC_FILE_LOAD BPF
Looking for Docker.sock
$

배포 결과를 보면 docker와는 조금 다른 부분을 확인할 수 있다. 기본적으로 seccomp 항목의 값이 'disable'로 seccomp 이 비활성화 되어 있으며, 거부되는 시스템콜 함수의 수도 상대적으로 훨씬 적다. 현재 버전 v1.22.12 (2022.09.23) kubernetes 에서는 기본적으로 seccomp 을 구현하지 않고 있다. 

기본적으로 seccomp 를 구현하지 않고 있지만, 사용자 지정에 의해 파드에 seccomp 를 부여할 수 있다.

apiVersion: v1
kind: Pod
metadata:
  labels:
    run: amicontained
  name: amicontained
spec:
  securityContext:
      seccompProfile:
        type: RuntimeDefault
  containers:
  - args:
    - amicontained
    image: r.j3ss.co/amicontained
    name: amicontained
    securityContext:
      allowPrivilegeEscalation: false

이번에는 pod 명세를 통하여 위와 같이 securityContext 필드를 추가하였다. securityContext 필드가 파드의 명세 이외에 containers 필드 하위에도 부여되어 있는데, 'allowPrivilegeEscalation: false' 의 경우, 컨테이너 내에서 실행되는 프로세스의 권한이 파드로 에스컬레이션 되지 않기 위함이다.

spe 하위의 securityContext 필드에는 seccomp profile 을 RuntimeDefault 로 지정해준다. 이 yaml 을 이용하여 insepction tool image(amicontaind)를 다시 배포해보면 결과는 다음과 같다.

$ kubectl apply -f amicontained.yaml
pod/amicontained created
$
$ kubectl logs amicontained
Container Runtime: kube
Has Namespaces:
        pid: true
        user: false
AppArmor Profile: cri-containerd.apparmor.d (enforce)
Capabilities:
        BOUNDING -> chown dac_override fowner fsetid kill setgid setuid 
        setpcap net_bind_service net_raw sys_chroot mknod audit_write setfcap
Seccomp: filtering
Blocked Syscalls (61):
        PTRACE SYSLOG SETPGID SETSID USELIB USTAT SYSFS VHANGUP PIVOT_ROOT _SYSCTL ACCT 
        SETTIMEOFDAY MOUNT UMOUNT2 SWAPON SWAPOFF REBOOT SETHOSTNAME SETDOMAINNAME IOPL 
        IOPERM CREATE_MODULE INIT_MODULE DELETE_MODULE GET_KERNEL_SYMS QUERY_MODULE QUOTACTL 
        NFSSERVCTL GETPMSG PUTPMSG AFS_SYSCALL TUXCALL SECURITY LOOKUP_DCOOKIE CLOCK_SETTIME 
        VSERVER MBIND SET_MEMPOLICY GET_MEMPOLICY KEXEC_LOAD ADD_KEY REQUEST_KEY KEYCTL 
        MIGRATE_PAGES UNSHARE MOVE_PAGES PERF_EVENT_OPEN FANOTIFY_INIT NAME_TO_HANDLE_AT 
        OPEN_BY_HANDLE_AT SETNS PROCESS_VM_READV PROCESS_VM_WRITEV KCMP FINIT_MODULE 
        KEXEC_FILE_LOAD BPF USERFAULTFD PKEY_MPROTECT PKEY_ALLOC PKEY_FREE
Looking for Docker.sock

이제 seccomp 필터가 적용되어 거부 되는 시스템콜 함수의 수가 늘어난 것을 볼 수 있다.

...
  securityContext:
      seccompProfile:
	    type: Unconfined
...

위 소스 처럼, type 의 값을 'Unconfined'로 바꿀 경우에는, Docker 옵션과 마찬가지로 모든 시스템콜 함수에 접근할 수 있다.


사용자 정의 seccomp profile 

apiVersion: v1
kind: Pod
metadata:
  name: systemcall-test
spec:
  securityContext:
    seccompProfile:
      type: Localhost
      localhostProfile: <사용자정의 profile의 경로> #상대경로에 주의
  containers:
  - command: ["bash", "-c", "echo 'Test Log!!!' && sleep 100"]
  image: ubuntu
  name: ubuntu
  securityContext:
    allowPrivilegeEscalation: false

이번에는  .spec.securityContext.seccompProfile 하위에 localhost 타입을 지정하여 사용자가 정의한 custom seccomp profile 을 사용할 수도 있다. 이 경우 경로에 주의하여야 하는데, '상대경로' 만을 사용하여야 하며 여기서의 상대 경로는

  • custom seccomp profile 의 기준 경로 : /var/lib/kubelet/seccomp

이다. 따라서 위 경로 하위에 디렉토리나 파일을 생성한 후에, 경로를 지정해줘야 한다. 만약 /var/lib/kubelet/seccomp/profiles/test.json 로 파일을 준비한 경우 localhostProfile 의 값은 'profiles/test.json' 이 된다.

댓글