*본 게시글의 내용은 개인 학습내용과 더불어 가시다님의 노션 페이지와 스터디 자료인 '24단계 실습으로 정복하는 쿠버네티스 도서' 를 기반으로 작성하였습니다.
Polaris
쿠버네티스 클러스터의 구성과 보안 상태를 분석하여 보안 취약점과 성능 이슈에 대한 식별 및 평가하는 오픈소스
도구이다. 다양한 룰셋을 지원하며, 룰셋을 커스터마이징 하여 평가 항목에 추가하는 방식도 가능하다. 분석한 보안 상태와 성능 이슈를 시각화한 자료를 함께 제공하기 때문에 관리자가 보완이 필요한 부분을 가시적으로 확인하는데 도움을 주는 툴이다.
폴라리스는 3가지 모드로 실행 가능하다.
- Dashboard : 코드로 정의한 정책(policy as code)을 따라 쿠버네티스 리소스의 유효성을
검증
하고, 어떤 보완 작업이 필요한지 보여준다. - Admission Controller : 정책을 위반하는 워크로드는 강제로
수정하거나 생성을 막는다
. - CLI Tool : 코드화 한 정책(policy as code)을
CI/CD 파이프라인에 추가
하여 yaml파일을 테스트한다. 통과하지 못한 yaml파일은 반영되지 않는다.
평가 기준 및 조치방법
Polaris의 공식 도큐먼트가 사용자에게 있어 꽤나 친절하다는 느낌을 받은 부분이다.
보안, 성능효율, 사이트 안정성에 대하여 3개 카테고리로 분류한 기준을 설명하고 있으며, 분석 항목에 대한 danger/warning 기준과, Admission Controller의 차단 기준을 표에서 설명한다.
페이지 하단에서는 이러한 차단 기준이 어떤 배경에 의해 설정되었는지 소개하고 있다.
다만 각 매니페스트에 대한 예시를 제공하지 않는 점이 아쉬웠는데
나는 Polaris로 분석한 결과를 아래 표를 기준으로 먼저 살펴보고, 실제 조치 과정에서는 아래 세 개의 레퍼런스를 가장 많이 참조했다.
1. 쿠버네티스 공식문서
2. bridgecrew의 kubernetes policy
3. polaris github의 check/*.yaml 파일 내용들
Security
Efficiency
Reliability
Dashboard 모드
설치 및 사용
- helm으로 배포
helm repo add fairwinds-stable https://charts.fairwinds.com/stable
helm upgrade --install polaris fairwinds-stable/polaris --namespace polaris --create-namespace
kubectl port-forward --namespace polaris svc/polaris-dashboard 8080:80
- 로컬에 docker로 배포
docker run -d -p8080:8080 -v ~/.kube/config:/opt/app/config:ro quay.io/fairwinds/polaris:1.2 polaris dashboard --kubeconfig /opt/app/config
대시보드는 반드시 쿠버네티스 클러스터가 아닌, 로컬에 구성하여 kubeconfig 파일을 기반으로 클러스터에 연결할 수도 있다.
실제로 쿠버네티스 밖의 환경에서 별도로 대시보드를 실행할 수 있는지 궁금하기도 해서 일부러 쿠버네티스 클러스터와 완전히 분리된 로컬 환경에서 docker로 실행해보았다.
kOps로 구성한 실습 환경인데, 아직 아무런 사용하지 않은 설치 직후의 최초 분석 결과는 위와 같다. 분석 결과는 분석에 사용된 룰셋에 따라 달라지기 떄문에 조직 내에서 분석 대상에 대한 리스트업과 평가 기준을 세워 사용하는 편이 좋을 것 같다.
네임스페이스별로 배포된 각 리소스에 대한 세밀한 분석결과도 제공한다.
aws-node(vpc cni)의 분석 결과를 보면, 심각도에 따라 조치가 필요한 항목을 보여준다. 하나의 파드가 여러 컨테이너를 품고 있는 단위인 만큼, 각 컨테이너별로 분석이 이루어지며 컨테이너 레벨의 분석 결과와 파드 레벨의 분석 결과를 분리해서 확인할 수 있다.
기본적으로 30개 이상의 미리 세팅된 룰셋들이 존재하며, 평가된 항목들을 보면 쿠버네티스 리소스 생성시 안정적인 서비스 운영을 위해 적용을 권장하는 항목들이 주를 이루고 있기 때문에 필수 항목만 체크하려고 한다면 사전 정의된 룰셋만으로도 충분한 효과를 볼 수 있을 것 같다.
- 호스트 네트워크대역 공유
- 컨테이너에 부여된 권한
- CPU/Mem limit&request
- Readiness , Liveness Prove 설정
- 이미지 태그 명시
물론 호스트 네트워크 대역의 사용이나, 운영상의 목적으로 CPU/Memory 자원에 대한 limit & request를 설정하지 않는 경우도 있기 때문에 모든 항목을 맹목적으로 따를 필요는 없어 보인다.
이 중 CPU limits should be set
항목 옆의 ?
버튼을 클릭하면 세부 조치 항목과 이 항목이 조치되어야 하는 이유를 함께 가이드하고 있는데, 이러한 배경이 함께 제공된다는 점은 매우 매력적이다.
조치
테스트로 nginx파드와 argocd를 추가로 배포하고 확인해보았다. 대시보드를 새로고침하면 새로이 배포한 리소스들이 바로 반영되고, 분석이 이루어진다.
nginx 파드의 분석 결과에서 조치가 필요한 항목 중 일부 항목에 대한 조치를 해보고, 어떻게 반영되는지 확인해보겠다.
기존 배포는 아래와 같이 했다.
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
조치 후의 매니페스트는 아래와 같다.
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
imagePullPolicy: Always
ports:
- containerPort: 80
securityContext:
readOnlyRootFilesystem: true
runAsNonRoot: true
resources:
requests:
cpu: 100m
memory: 100Mi
limits:
cpu: 100m
memory: 100Mi
readinessProbe:
exec:
command: ["ls", "/usr/share/nginx/html/index.html"]
livenessProbe:
exec:
command: ["ls", "/usr/share/nginx/html/index.html"]
initialDelaySeconds: 5
periodSeconds: 3
failureThreshold: 3
아래의 항목들을 조치하여 매니페스트에 반영하였다.
- image 태그 반영 :
image: nginx:1.14.2
- cpu limit :
limits.cpu : 100m
- cpu request :
request.cpu : 100m
- mem limit :
limits.memory : 100Mi
- mem request
reqeust.memory : 100Mi
- livenessprove :
command: ["ls", "/usr/share/nginx/html/index.html"]
- image pull policy를 Always로 적용 :
imagePullPolicy: Always
- 컨테이너를 루트로 실행하지 않도록 함 :
runAsNonRoot: true
- 파일시스템 리드온리로 변경 :
readOnlyRootFilesystem: true
조치 결과
대시보드는 룰셋의 평가 기준에 벗어난다고 해서 쿠버네티스 리소스의 생성을 차단하거나, 강제로 수정시키는 등의 동작은 하지 않고, 평가 결과와 조치 내용에 대한 View만 제공한다.
Admission Controller 모드
Polarlist Admission Controller 모드는 Admission Controller로 Built-In PodSecurity Admission Controller가 아닌 Polarlis를 사용하여 개발자 또는 관리자가 새로운 워크로드를 쿠버네티스 클러스터에 배포하려고 할 때, 분석 항목을 만족하는지 확인하고 만족하지 않는 경우 배포를 차단하는 방식으로 동작한다.
설치
helm upgrade --install polaris fairwinds-stable/polaris --namespace demo --create-namespace --set webhook.enable=true --set dashboard.enable=false
Admission Contrller를 활성화하고, 대시보드를 비활성화 한다. 설치에 성공하면 아래와 같은 메세지가 표시된다.
NAME: polaris
LAST DEPLOYED: Sat Apr 8 14:48:54 2023
NAMESPACE: demo
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
** Please be patient while the chart is being deployed **
Enjoy Polaris and smooth sailing!
The webhook is now running. Any resources that violate Polaris policy will be rejected
테스트를 위해 nginx 파드를 조치 전 기준으로 재배포해보았더니, Polaris 에 의해 배포가 차단되고 조치가 필요한 항목이 출력되었다.
Error from server (
Polaris prevented this deployment due to configuration problems:
- Container nginx: Privilege escalation should not be allowed
- Container nginx: Should not be allowed to run as root
- Container nginx: Image tag should be specified
): error when creating "pod.yaml": admission webhook "polaris.fairwinds.com" denied the request:
Polaris prevented this deployment due to configuration problems:
- Container nginx: Privilege escalation should not be allowed
- Container nginx: Should not be allowed to run as root
- Container nginx: Image tag should be specified
이번에는 앞서 조치를 완료했던 매니페스트로 nginx를 배포해보았는데, 이번에도 배포가 실패하고 에러가 출력되었다.
Dashboard에서는 분명 모든 조치가 완료된 것으로 표시되었는데, Dashboard의 평가 기준과 Admission Controller 모드의 평가 기준이 다른 듯 보인다.
Error from server (
Polaris prevented this deployment due to configuration problems:
- Container nginx: Privilege escalation should not be allowed
): error when creating "pod.yaml": admission webhook "polaris.fairwinds.com" denied the request:
Polaris prevented this deployment due to configuration problems:
- Container nginx: Privilege escalation should not be allowed
아래와 같이 Security Context를 추가하여 조치하였고, 파드 생성에 성공했다.
...
securityContext:
readOnlyRootFilesystem: true
runAsNonRoot: true
allowPrivilegeEscalation: false
privileged: false
...
$kubectl apply -f pod.yaml
pod/nginx created
폴라리스 공식 문서에 따르면, 아직까지는 부적절한 워크로드의 생성 자체를 reject 시킬수만 있고, 대시보드처럼 단순 경고는 불가능하다고 한다.
심각도 분류는 danger와 Warning, success(ignore)으로 나누어지는데, Warning인 항목은 Admission Controller에 의한 검사를 통과하며, danger일 때만 차단이 발생한다.
Polaris CLI
폴라리스의 마지막 동작 모드로 CLI를 사용하는 방법이 있다. 로컬에서 작업한 yaml파일을 polaris cli를 이용하여 분석하는 방법이다. 커맨드라인으로 동작하기 때문에 CI/CD 파이프라인에 녹여서 사용이 가능한 것으로 소개하고 있다.
다만 이번에 사용해본 바로는 조치 결과를 출력해주는 것 외에, 배포를 차단하여 수정을 강제하는 효과를 볼 수 있을지는 모르겠다. 오히려 Admission Controller 모드를 사용하고 알림을 설정해서 받아보는 편이 더 좋을 수 있겠다는 생각이 들었다.
설치
curl -L "https://github.com/FairwindsOps/polaris/releases/download/7.4.1/polaris_linux_amd64.tar.gz" > polaris.tar.gz
tar -xvf polaris.tar.gz
sudo mv polaris /usr/local/bin/
중간에 7.4.1이 현 시점 최신 버전이고, 내 로컬은 리눅스 환경이기 때문에 linux_amd64 로 설치하였다. 업데이트 현황과 로컬 환경에 따라 수정하여 설치할 수 있으며, polaris github에서 릴리즈 버전과 환경별 바이너리 다운로드가 가능하다.
다시 pod의 매니페스트 파일을 조치 전 기준으로 변경하고, polaris cli를 사용해보았다. 현재 pod.yaml 파일은 ~/polaris_test/ 경로에 있어 path를 지정하였다.
polaris audit --audit-path ./polaris_test/ --format=pretty
Polaris audited Path ./polaris_test/ at 2023-04-08T15:19:24+09:00
Nodes: 0 | Namespaces: 0 | Controllers: 1
Final score: 45
Pod nginx
hostIPCSet 🎉 Success
Security - Host IPC is not configured
hostNetworkSet 🎉 Success
Security - Host network is not configured
hostPIDSet 🎉 Success
Security - Host PID is not configured
topologySpreadConstraint 😬 Warning
Reliability - Pod should be configured with a valid topology spread constraint
Container nginx
readinessProbeMissing 😬 Warning
Reliability - Readiness probe should be configured
cpuLimitsMissing 😬 Warning
Efficiency - CPU limits should be set
dangerousCapabilities 🎉 Success
Security - Container does not have any dangerous capabilities
hostPortSet 🎉 Success
Security - Host port is not configured
linuxHardening 😬 Warning
Security - Use one of AppArmor, Seccomp, SELinux, or dropping Linux Capabilities to restrict containers using unwanted privileges
memoryLimitsMissing 😬 Warning
Efficiency - Memory limits should be set
pullPolicyNotAlways 😬 Warning
Reliability - Image pull policy should be "Always"
privilegeEscalationAllowed ❌ Danger
Security - Privilege escalation should not be allowed
runAsPrivileged 🎉 Success
Security - Not running as privileged
cpuRequestsMissing 😬 Warning
Efficiency - CPU requests should be set
insecureCapabilities 😬 Warning
Security - Container should not have insecure capabilities
livenessProbeMissing 😬 Warning
Reliability - Liveness probe should be configured
memoryRequestsMissing 😬 Warning
Efficiency - Memory requests should be set
notReadOnlyRootFilesystem 😬 Warning
Security - Filesystem should be read only
runAsRootAllowed ❌ Danger
Security - Should not be allowed to run as root
sensitiveContainerEnvVar 🎉 Success
Security - The container does not set potentially sensitive environment variables
tagNotSpecified ❌ Danger
Reliability - Image tag should be specified
Want more? Automate Polaris for free with Fairwinds Insights!
🚀 https://fairwinds.com/insights-signup/polaris 🚀
마찬가지로 조치 후 다시 검사를 실행.
polaris audit --audit-path ./polaris_test/ --format=pretty --only-show-failed-tests
Polaris audited Path ./polaris_test/ at 2023-04-08T16:40:17+09:00
Nodes: 0 | Namespaces: 0 | Controllers: 1
Final score: 89
Pod nginx
topologySpreadConstraint 😬 Warning
Reliability - Pod should be configured with a valid topology spread constraint
Container nginx
insecureCapabilities 😬 Warning
Security - Container should not have insecure capabilities
linuxHardening 😬 Warning
Security - Use one of AppArmor, Seccomp, SELinux, or dropping Linux Capabilities to restrict containers using unwanted privileges
hostPortSet 😬 Warning
Security - Host port should not be configure
danger 항목은 모두 조치되었고, warning 항목에서 몇 가지 경고를 보여준다.
위와 같이 단일 디렉토리나, 매니페스트 파일에 대하여 검사를 수행할 수도 있지만 클러스터 전체애 대한 수행도 가능하다. 이미 실행중인 워크로드에 대해서도 분석이 이루어지며, kubeconfig 파일에 설정된 클러스터를 기준으로 동작한다.
polaris audit --format=pretty
커맨드를 실행하면 먼저 기존 워크로드를 읽어들인다.
polaris audit --format=pretty
INFO[0000] Loading nodes
INFO[0000] Loading namespaces
INFO[0000] Loading pods
INFO[0000] Setting up restmapper
INFO[0000] Loading networking.k8s.io/Ingress
INFO[0000] Loading rbac.authorization.k8s.io/RoleBinding
INFO[0000] Loading rbac.authorization.k8s.io/ClusterRole
INFO[0000] Loading /ConfigMap
INFO[0000] Loading policy/PodDisruptionBudget
INFO[0000] Loading rbac.authorization.k8s.io/Role
INFO[0000] Loading ServiceAccount
INFO[0000] Loading networking.k8s.io/NetworkPolicy
INFO[0000] Loading rbac.authorization.k8s.io/ClusterRoleBinding
INFO[0000] Loading controllers
INFO[0000] Done loading Kubernetes resource
그리고 아래와 같이 네임스페이스별, 워크로드별로 분석한 결과를 보여주는데, 클러스터 내의 모든 워크로드를 분석한 결과를 출력하다보니 내용이 꽤 길기 때문에 output을 파일로 써서 천천히 살펴보는 편이 좋았다.
$ polaris audit --format=pretty > result.txt
$ head result.txt -n 30
---
Polaris audited Cluster https://api.ilikebigmac.link at 2023-04-08T15:25:54+09:00
Nodes: 3 | Namespaces: 7 | Controllers: 26
Final score: 83
Role system::leader-locking-kube-controller-manager in namespace kube-system
rolePodExecAttach 🎉 Success
Security - The Role does not allow pods/exec or pods/attach
Role cert-manager-cainjector:leaderelection in namespace kube-system
rolePodExecAttach 🎉 Success
Security - The Role does not allow pods/exec or pods/attach
...
--only-show-failed-tests
옵션을 추가하면 실패한 항목만 출력할 수 있는데, 어떤 항목에 대한 평가가 이루어졌는지보다는 실패한 항목만을 찾아 조치하고자 하는 경우에 사용하면 좋을 것 같다. 내용을 거의 다 날려버려서 사용자에게 폴라리스가 분석한 결과와 평가 항목에 대한 내용을 전달하고자 하는 경우에는 쓰지 않는게 좋을 것 같음.
$ polaris audit --audit-path ./polaris_test/ --format=pretty -c config.yaml --only-show-failed-tests
Polaris audited Path ./polaris_test/ at 2023-04-08T16:24:12+09:00
Nodes: 0 | Namespaces: 0 | Controllers: 1
Final score: 88
Pod nginx
topologySpreadConstraint 😬 Warning
Reliability - Pod should be configured with a valid topology spread constraint
Container nginx
hostPortSet 😬 Warning
Security - Host port should not be configured
linuxHardening 😬 Warning
Security - Use one of AppArmor, Seccomp, SELinux, or dropping Linux Capabilities to restrict containers using unwanted privileges
insecureCapabilities 😬 Warning
Security - Container should not have insecure capabilities
Want more? Automate Polaris for free with Fairwinds Insights!
🚀 https://fairwinds.com/insights-signup/polaris 🚀
Customizing
기본적으로 설정된 Polaris의 룰셋들은 미리 설정된 config.yaml 파일 내에 정의되어 있다.
사용자는 이 config.yaml 을 변경하여 아래와 같이 폴라리스를 커스텀 할 수 있다.
- check를 켜고 끌 수 있음
- 각 평가 항목에 대한 심각도 수준 조정(danger/warning)
- 새로운 custom check 추가
- 특정 룰에서 특정 워크로드에 대한 예외 추가
테스트에서는 privilegeEscalationAllowed의 심각도 수준을 변경해보려고 한다.
config.yaml의 아래 privilegeEscalationAllowed: danger
를 privilegeEscalationAllowed: warning
으로 변경한 뒤, pod.yaml의 내용에서 privilegeEscalationAllowed
설정을 제거해보았다.
- 기존
privilegeEscalationAllowed ❌ Danger Security - Privilege escalation should not be allowed
- 변경 후
privilegeEscalationAllowed 😬 Warning Security - Privilege escalation should not be allowed ...
- ignore 적용 후
Polaris audited Path ./polaris_test/ at 2023-04-08T16:46:32+09:00
Nodes: 0 | Namespaces: 0 | Controllers: 1
Final score: 88
Pod nginx
topologySpreadConstraint 😬 Warning
Reliability - Pod should be configured with a valid topology spread constraint
Container nginx
linuxHardening 😬 Warning
Security - Use one of AppArmor, Seccomp, SELinux, or dropping Linux Capabilities to restrict containers using unwanted privileges
insecureCapabilities 😬 Warning
Security - Container should not have insecure capabilities
hostPortSet 😬 Warning
Security - Host port should not be configured
Want more? Automate Polaris for free with Fairwinds Insights!
🚀 https://fairwinds.com/insights-signup/polaris 🚀
warning에서 ignore로 변경했더니, 아예 평가 항목에서 사라져버렸다. Success로 표기되는 개념이 아닌 평가 항목에서의 완전 배제를 ignore로 설정할 수 있는 것으로 보인다.
마치며
쿠버네티스 클러스터와 워크로드에 대한 보안/성능 분석 툴의 사용은 이번 스터디 주제로 다루면서 처음 경험해보았다.
사용 전에는 이러한 툴의 적용으로 인해서 개발 및 배포 프로세스가 지연될 가능성에 대한 고려가 필요해 보였고, 때문에 속도를 중시하면서 어느정도의 유연한 운영을 원하는 경우 사용이 어렵지 않을까 하는 생각이었는데 지금까지 핸즈온 해본 바로는 최초 설정시에 기준만 잘 잡아둔다면 오히려 안정성 있는 워크로드 구성을 가속화 할 수 있겠다는 느낌을 받았다.
다만 이 역시 초기 적용시에는 클러스터를 관리하는 인원간에 각 분석 항목에 대한 합의와 함께 개발 조직과 협업하여 일정 기간 베타테스트가 선행된다면 좋을 것 같다.
최근에 타 팀에서 아직 쿠버네티스와 인프라 레벨의 AWS 설정에 대한 도메인이 부족한 상태에서, 모 플랫폼을 PoC하기 위하여 production 데이터를 끌어다 EKS 기반으로 워크로드를 올렸다가 일부 데이터와 함께 플랫폼의 admin 정보가 노출되었던 사례가 있었다. 다행히 조치가 빠르게 이루어져서 보안 사고로 이어지지는 않았지만.
쿠버네티스의 운영도 결국 사람이 한다. Polaris 의 도입과 함께 추가로 check 룰셋을 조직의 환경에 맞게 커스터마이징 해서 사용한다면, 미처 놓칠 수 있는 보안 취약점이나 서비스 안정성을 위해 반드시 추가되어야 하는 설정값들이 빠져 서비스 장애가 발생할 수 있는 경우의 수를 현저히 낮출 수 있을 것으로 기대한다.
Ref
- https://github.com/FairwindsOps/polaris
- https://polaris.docs.fairwinds.com/checks/security/
- https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/
- https://coffeewhale.com/kubernetes/admission-control/2021/04/28/opa1/
- https://docs.bridgecrew.io/docs/kubernetes-policy-index
- https://www.fairwinds.com/blog
'Kubernetes > PKOS' 카테고리의 다른 글
[5주차-2] EC2 Instance Metadata와 IRSA (0) | 2023.04.09 |
---|---|
[보완] 쿠버네티스 스토리지와 CSI Driver (0) | 2023.04.08 |
[보완] kubernetes 워커노드를 spot instance로 구성하기(Node Termination Handler) (1) | 2023.04.02 |
[4주차] 쿠버네티스 모니터링 (0) | 2023.04.02 |
[3주차] GitOps와 ArgoCD (0) | 2023.03.26 |