보안 체크리스트
보안 체크리스트 (Security Checklist)
이 체크리스트는 각 주제에 대한 더 포괄적인 문서로 연결되는 기본 지침 목록을 제공하는 것을 목표로 해요. 완전하다고 주장하지 않으며 진화할 의도가 있어요.
이 문서를 읽고 사용하는 방법:
- 주제의 순서는 우선순위를 반영하지 않아요.
- 일부 체크리스트 항목은 각 섹션의 목록 아래 문단에서 자세히 설명돼요.
주의:
출처: 문서
본문
인증과 인가 (Authentication & Authorization)
system:masters그룹은 부트스트래핑 후 사용자 또는 컴포넌트 인증에 사용되지 않아요.- kube-controller-manager가
--use-service-account-credentials를 활성화한 채 실행 중이에요. - 루트 인증서가 보호돼요(오프라인 CA 또는 효과적인 접근 제어가 있는 관리형 온라인 CA).
- 중간(intermediate) 및 리프(leaf) 인증서의 만료일이 3년 이내예요.
- 주기적 접근 검토 프로세스가 존재하며, 검토는 24개월 이내에 수행돼요.
- 인증과 인가에 대한 지침은 역할 기반 접근 제어 모범 사례를 따르고 있어요.
부트스트래핑 후에는 사용자나 컴포넌트 모두 system:masters 로 쿠버네티스 API에 인증하지 않아야 해요. 마찬가지로 kube-controller-manager 전체를 system:masters 로 실행하는 것도 피해야 해요. 사실 system:masters 는 관리자 사용자가 아닌 브레이크-글래스(break-glass) 메커니즘으로만 사용해야 해요.
네트워크 보안 (Network security)
- 사용 중인 CNI 플러그인이 네트워크 정책을 지원해요.
- 인그레스·이그레스 네트워크 정책이 클러스터의 모든 워크로드에 적용돼 있어요.
- 각 네임스페이스에 모든 파드를 선택하고 모든 것을 거부하는 기본 네트워크 정책이 있어요.
- 적절하다면 서비스 메시가 클러스터 내부의 모든 통신을 암호화하는 데 사용돼요.
- 쿠버네티스 API, kubelet API, etcd가 인터넷에 공개적으로 노출되지 않아요.
- 워크로드에서 클라우드 메타데이터 API로의 접근이 필터링돼 있어요.
- LoadBalancer와 ExternalIP 사용이 제한돼 있어요.
다양한 Container Network Interface (CNI) 플러그인 플러그인이 파드가 통신할 수 있는 네트워크 리소스를 제한하는 기능을 제공해요. 이것은 가장 일반적으로 규칙을 정의하는 네임스페이스 리소스를 제공하는 Network Policies를 통해 이루어져요. 각 네임스페이스에서 모든 파드를 선택하고 모든 이그레스·인그레스를 차단하는 기본 네트워크 정책은 어떤 워크로드도 빠뜨리지 않도록 허용 목록 접근 방식을 채택하는 데 유용할 수 있어요.
모든 CNI 플러그인이 전송 중 암호화를 제공하는 것은 아니에요. 선택한 플러그인에 이 기능이 없다면, 대안 솔루션으로 서비스 메시를 사용해 그 기능을 제공할 수 있어요.
제어 플레인의 etcd 데이터 저장소는 접근을 제한하는 제어가 있어야 하고 인터넷에 공개적으로 노출되지 않아야 해요. 또한 그것과 안전하게 통신하기 위해 상호 TLS(mTLS)를 사용해야 해요. 이를 위한 인증 기관은 etcd 고유의 것이어야 해요.
쿠버네티스 API 서버에 대한 외부 인터넷 접근은 API를 공개적으로 노출하지 않도록 제한해야 해요. 많은 관리형 쿠버네티스 배포가 기본적으로 API 서버를 공개적으로 노출하고 있으므로 주의해요. 그러면 배스천 호스트를 사용해 서버에 접근할 수 있어요.
kubelet API 접근은 제한되고 공개적으로 노출되지 않아야 해요. --config 플래그로 구성 파일을 지정하지 않았을 때의 기본 인증·인가 설정은 지나치게 허용적이에요.
쿠버네티스를 호스팅하는 데 클라우드 제공자를 사용한다면, 파드에서 클라우드 메타데이터 API 169.254.169.254 로의 접근도 정보를 누출할 수 있으므로 필요하지 않다면 제한하거나 차단해야 해요.
제한된 LoadBalancer·ExternalIP 사용에 대해서는 CVE-2020-8554: LoadBalancer 또는 ExternalIP를 사용한 중간자 공격과 DenyServiceExternalIPs admission 컨트롤러를 참고해요.
파드 보안 (Pod security)
- 워크로드에 대한
create,update,patch,deleteRBAC 권한은 필요할 때만 부여돼요. - 모든 네임스페이스에 적절한 Pod Security Standards 정책이 적용되고 강제돼요.
- 요청과 같거나 낮은 한도의 메모리 한도가 워크로드에 설정돼 있어요.
- 민감한 워크로드에는 CPU 한도가 설정될 수 있어요.
- 지원하는 노드에서 프로그램에 적절한 syscalls 프로필로 Seccomp가 활성화돼 있어요.
- 지원하는 노드에서 프로그램에 적절한 프로필로 AppArmor 또는 SELinux가 활성화돼 있어요.
RBAC 인가는 중요하지만 Pods 리소스(또는 파드를 관리하는 어떤 리소스)에 대한 인가를 가질 만큼 세밀할 수 없어요. 유일한 세부성은 리소스 자체의 API 동사, 예를 들어 Pods에 대한 create 예요. 추가 admission 없이 이러한 리소스를 만드는 인가는 클러스터의 스케줄링 가능한 노드에 대한 직접·무제한 접근을 허용해요.
Pod Security Standards는 PodSpec 에서 보안 관련 필드가 어떻게 설정될 수 있는지 제한하는 privileged, baseline, restricted 세 가지 정책을 정의해요. 이 표준은 기본으로 활성화된 새 Pod Security admission이나 서드파티 admission webhook으로 네임스페이스 수준에서 강제될 수 있어요. 그것이 대체하는 제거된 PodSecurityPolicy admission과 달리 Pod Security admission은 admission webhook와 외부 서비스를 쉽게 결합할 수 있다는 점을 주목하세요.
Pod Security admission restricted 정책은 Pod Security Standards 집합 중 가장 제한적인 정책이며, 보안 모범 사례에 따라 가장 적절한 security context를 점진적으로 적용하기 위해 warn, audit 또는 enforce 여러 모드로 동작할 수 있어요. 그럼에도 파드의 security context는 특정 사용 사례에 대해 사전 정의된 보안 표준 위에 파드가 가질 수 있는 권한과 접근을 제한하기 위해 별도로 조사해야 해요.
Pod Security에 대한 실습 튜토리얼은 블로그 게시물 Kubernetes 1.23: Pod Security Graduates to Beta를 참고해요.
메모리와 CPU 한도는 파드가 노드에서 소비할 수 있는 메모리·CPU 리소스를 제한하고 따라서 악의적이거나 침해된 워크로드의 잠재적 DoS 공격을 방지하기 위해 설정해야 해요. 그러한 정책은 admission 컨트롤러로 강제될 수 있어요. CPU 한도는 사용량을 스로틀링하므로 자동 확장 기능이나 효율성에 의도치 않은 영향을 줄 수 있다는 점(즉 사용 가능한 CPU 리소스로 베스트 에포트 실행)을 주의하세요.
주의:
Seccomp 활성화하기
Seccomp는 secure computing mode를 뜻하며 Linux 커널 버전 2.6.12부터 있었던 기능이에요. 프로세스의 권한을 샌드박스화해 사용자 공간에서 커널로 만들 수 있는 호출을 제한하는 데 사용할 수 있어요. 쿠버네티스는 노드에 로드된 seccomp 프로필을 파드와 컨테이너에 자동으로 적용하게 해줘요.
Seccomp는 컨테이너 안에서 사용할 수 있는 Linux 커널 syscall 공격 표면을 줄여 워크로드의 보안을 개선할 수 있어요. seccomp 필터 모드는 BPF를 활용해 명명된 프로필인 특정 syscall의 허용 또는 거부 목록을 만들어요.
쿠버네티스 1.27부터 모든 워크로드에 대한 기본 seccomp 프로필로 RuntimeDefault 의 사용을 활성화할 수 있어요. 이 주제에 대한 보안 튜토리얼을 사용할 수 있어요. 추가로 Kubernetes Security Profiles Operator는 클러스터에서 seccomp의 관리와 사용을 용이하게 하는 프로젝트예요.
참고:
AppArmor 또는 SELinux 활성화하기
AppArmor
AppArmor은 Mandatory Access Control (MAC)과 시스템 로그를 통한 더 나은 감사를 쉽게 구현하는 방법을 제공할 수 있는 Linux 커널 보안 모듈이에요. 지원하는 노드에서 기본 AppArmor 프로필이 강제되거나 커스텀 프로필을 구성할 수 있어요. seccomp처럼 AppArmor도 프로필로 구성되며, 각 프로필은 금지된 리소스에 대한 접근을 차단하는 enforcing 모드 또는 위반만 보고하는 complain 모드 중 하나로 실행돼요. AppArmor 프로필은 애노테이션과 함께 컨테이너별로 강제되어 프로세스가 정확히 필요한 권한만 얻을 수 있게 해줘요.
참고:
SELinux
SELinux는 Mandatory Access Control (MAC)을 포함한 접근 제어 보안 정책을 지원하는 메커니즘을 제공할 수 있는 Linux 커널 보안 모듈이기도 해요. SELinux 라벨은 securityContext 섹션을 통해 컨테이너나 파드에 할당될 수 있어요.
참고:
로그와 감사 (Logs and auditing)
- 감사 로그가 활성화돼 있다면 일반 접근으로부터 보호돼 있어요.
파드 배치 (Pod placement)
- 파드 배치는 애플리케이션의 민감도 단계에 따라 이루어져요.
- 민감한 애플리케이션이 노드에 격리되거나 특정 샌드박스 런타임으로 실행되고 있어요.
애플리케이션 파드와 쿠버네티스 API 서버처럼 서로 다른 민감도 단계의 파드는 별도 노드에 배포되어야 해요. 노드 격리의 목적은 애플리케이션 컨테이너 탈출이 더 높은 민감도의 애플리케이션에 대한 직접 접근을 제공해 클러스터 안에서 쉽게 피벗하지 못하게 하는 것이에요. 이 분리는 파드가 우발적으로 같은 노드에 배포되는 것을 방지하도록 강제되어야 해요. 이는 다음 기능으로 강제할 수 있어요:
Secret
- ConfigMap이 기밀 데이터를 담는 데 사용되지 않아요.
- Secret API에 저장 시 암호화가 구성돼 있어요.
- 적절하다면 서드파티 저장소에 저장된 Secret을 주입하는 메커니즘이 배포되고 사용 가능해요.
- 필요하지 않은 파드에 서비스 어카운트 토큰이 마운트되지 않아요.
- 만료되지 않는 토큰 대신 바인딩된 서비스 어카운트 토큰 볼륨이 사용 중이에요.
파드에 필요한 Secret은 ConfigMap 같은 대안 대신 쿠버네티스 Secret 안에 저장해야 해요. etcd 안에 저장된 Secret 리소스는 저장 시 암호화되어야 해요.
Secret이 필요한 파드는 emptyDir.medium 옵션처럼 바람직하게는 메모리에 저장되는 볼륨을 통해 자동으로 마운트되어야 해요. Secrets Store CSI Driver처럼 서드파티 저장소에서 Secret을 볼륨으로 주입하는 메커니즘을 사용할 수도 있어요. 이것은 파드에 서비스 어카운트 RBAC 접근을 제공하는 것보다 우선적으로 수행되어야 해요. 이렇게 하면 Secret을 환경 변수나 파일로 파드에 추가할 수 있어요. 환경 변수 방식은 Linux에서 환경 변수의 비기밀적 특성과 로그의 크래시 덤프 때문에 파일의 권한 메커니즘과 달리 누출에 더 취약할 수 있음을 주목하세요.
서비스 어카운트 토큰은 필요하지 않은 파드에 마운트되지 않아야 해요. 이는 서비스 어카운트 내에서 네임스페이스 전체에 적용하거나 파드에 특정하게 automountServiceAccountToken 을 false 로 설정해 구성할 수 있어요. 쿠버네티스 v1.22 이상에서는 시간이 제한된 서비스 어카운트 자격 증명에 Bound Service Accounts를 사용해요.
이미지 (Images)
- 컨테이너 이미지의 불필요한 내용이 최소화돼 있어요.
- 컨테이너 이미지가 권한 없는 사용자로 실행되도록 구성돼 있어요.
- 컨테이너 이미지에 대한 참조가 sha256 다이제스트(tags 대신)로 이루어지거나, 이미지의 디지털 서명을 배포 시점에 admission control을 통해 검증해 이미지의 출처가 검증돼요.
- 컨테이너 이미지가 생성과 배포 중 정기적으로 스캔되고, 알려진 취약한 소프트웨어가 패치돼 있어요.
컨테이너 이미지는 패키징하는 프로그램을 실행하는 데 필요한 최소한만 포함해야 해요. 바람직하게는 가능한 최소 베이스에서 이미지를 빌드해 프로그램과 그 종속성만 포함해야 해요. 특히 프로덕션에서 사용되는 이미지는 셸이나 디버깅 유틸리티를 포함하지 않아야 해요. 임시 디버그 컨테이너를 문제 해결에 사용할 수 있기 때문이에요.
Dockerfile의 USER 지시어를 사용해 이미지를 권한 없는 사용자로 직접 시작하도록 빌드해요. Security Context를 사용하면 이미지 매니페스트에 지정되지 않았더라도 runAsUser 와 runAsGroup 으로 컨테이너 이미지를 특정 사용자·그룹으로 시작할 수 있어요. 하지만 이미지 레이어의 파일 권한 때문에 이미지 수정 없이 새 권한 없는 사용자로 프로세스를 시작하는 것이 불가능할 수도 있어요.
이미지 태그(특히 latest 태그)를 사용해 이미지를 참조하는 것을 피해요. 태그 뒤의 이미지는 레지스트리에서 쉽게 수정될 수 있어요. 이미지 매니페스트에 고유한 완전한 sha256 다이제스트 사용을 선호해요. 이 정책은 ImagePolicyWebhook으로 강제될 수 있어요. 이미지 서명은 배포 시점에 admission 컨트롤러로 자동 검증되어 그 진위와 무결성을 검증할 수도 있어요.
컨테이너 이미지 스캔은 심각한 취약점이 컨테이너 이미지와 함께 클러스터에 배포되는 것을 방지할 수 있어요. 이미지 스캔은 컨테이너 이미지를 클러스터에 배포하기 전에 완료되어야 하며 보통 CI/CD 파이프라인의 배포 프로세스의 일부로 수행돼요. 이미지 스캔의 목적은 Common Vulnerability Scoring System (CVSS) 점수 같은 컨테이너 이미지의 가능한 취약점과 그 예방에 대한 정보를 얻는 것이에요. 이미지 스캔 결과를 파이프라인 준수 규칙과 결합하면 제대로 패치된 컨테이너 이미지만 Production에 들어가게 돼요.
Admission 컨트롤러
- 적절한 admission 컨트롤러 선택이 활성화돼 있어요.
- Pod 보안 정책이 Pod Security Admission 및/또는 webhook admission 컨트롤러로 강제되고 있어요.
- admission 체인 플러그인과 webhook가 안전하게 구성돼 있어요.
Admission 컨트롤러는 클러스터의 보안을 개선하는 데 도움을 줄 수 있어요. 하지만 API 서버를 확장하므로 자체적으로 위험을 제시할 수 있으며 적절히 보호되어야 해요.
다음 목록은 클러스터와 애플리케이션의 보안 자세를 강화하기 위해 고려할 수 있는 여러 admission 컨트롤러를 제시해요. 이 문서의 다른 부분에서 참조될 수 있는 컨트롤러를 포함해요.
이 첫 번째 admission 컨트롤러 그룹은 기본으로 활성화된 플러그인을 포함하며, 무엇을 하는지 알지 못한다면 활성화된 상태로 두는 것을 고려해요:
두 번째 그룹은 기본으로 활성화되지 않지만 일반적으로 사용 가능하며 보안 자세를 개선하기 위해 권장되는 플러그인을 포함해요:
세 번째 그룹은 기본으로 활성화되지 않지만 특정 사용 사례에 고려될 수 있는 플러그인을 포함해요:
더 알아보기 (Learn more)
- Pod 생성을 통한 권한 승격 은 특정 접근 제어 위험에 대해 경고하며, 해당 위협을 어떻게 관리하는지 확인해요.
- 우발적이거나 악의적인 접근으로부터 클러스터를 보호하는 정보는 클러스터 보안 문서를 참고해요.
- 멀티 테넌시에 대한 구성 옵션 권장 사항과 모범 사례는 클러스터 멀티 테넌시 가이드를 참고해요.
- 쿠버네티스 클러스터를 강화하는 보완 리소스는 블로그 게시물 "NSA/CISA Kubernetes Hardening Guidance 자세히 보기" 를 참고해요.