Pod Security Policy (이하 PSP) 란?
k8s에는 SecurityContext라는 기능이 존재한다. SecurityContext는 Container의 보안 기능을 정의하는 것인데, 개인적으로 PSP는 이 SecurityContext의 확장판이라고 생각한다.
PSP(포드 보안 정책)은 포드 사양의 보안 관련 측면을 제어하는 클러스터 수준 리소스이다. PSP 객체는 관련 필드에 대한 기본값 뿐만 아니라 시스템에 적용하기 위해 포드가 실행해야 하는 조건 세트를 정의한다. 관리자는 다음을 제어 할 수 있다.
제어 목록 | 필드명 |
Container의 실행 권한 | privileged |
호스트 네임 스페이스의 사용 | hostPID, hostIPC |
호스트 네트워킹 및 포트의 사용 | hostNetwork, hostPorts |
볼륨 유형의 사용법 | volumes |
호스트 파일 시스템의 사용 | allowedHostPaths |
FlexVolume 드라이버의 화이트리스트 | allowedFlexVolumes |
포드의 볼륨을 소유 FSGroup 할당 | fsGroup |
읽기 전용 루트 파일 시스템의 사용을 요구하는 | readOnlyRootFilesystem |
Container의 사용자와 그룹 ID | runAsUser, runAsGroup, supplementalGroups |
루트 권한을 제한 에스컬레이션 | allowPrivilegeEscalation, defaultAllowPrivilegeEscalation |
리눅스 기능 | defaultAddCapabilities, requiredDropCapabilities, allowedCapabilities |
Container의 SE 리눅스 문맥 | seLinux |
컨테이너에 대한 허용 PROC 마운트 타입 | allowedProcMountTypes |
Container에서 사용되는 AppArmor의 프로파일 | annotations |
Container에서 사용되는 프로파일 기는 seccomp | annotations |
Container에서 사용되는 프로파일의 sysctl | forbiddenSysctls,allowedUnsafeSysctls |
즉 PSP는 여러 제어 기능으로 컨테이너가 불필요하게 과도한 권한을 가지는 것을 정책적으로 제어하는 것이 목적이라고 할 수 있겠다.
PSP 적용 - 클러스터 내 ROOT 권한 컨테이너 기동 제한
여러가지 PSP의 제어 기능 중, ROOT 권한으로 컨테이너를 기동하는 것을 막는 기능을 직접 설정해보고 테스트 해 볼 것이다.
환경 - 필자는 Gcloud나 AWS Cloud와 같은 퍼블릭 클라우드 환경이 아닌 물리 서버에 직접 k8s를 구축하였기 때문에 퍼블릭 클라우드 환경에서의 PSP 활성화 방식과 다르다. (퍼블릭 클라우드는 버튼 하나면 PSP 기능을 활성화 할 수 있다.)
Step 1. NonRoot PSP 정의
$ vi 1.nonroot-psp.yaml
apiVersion: extensions/v1beta1
kind: PodSecurityPolicy
metadata:
name: nonroot-psp
spec:
seLinux:
rule: RunAsAny
supplementalGroups:
rule: RunAsAny
runAsUser:
rule: MustRunAsNonRoot
# rule: RunAsAny
fsGroup:
rule: RunAsAny
volumes:
- '*'
Step 2. 서비스 계정 생성
$ 2.nonroot-sa.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: nonroot-sa
Step 3. ClusterRole 생성
$ 3.nonroot-clusterrole.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: nonroot-clusterrole
rules:
- apiGroups:
- policy
resources:
- podsecuritypolicies
resourceNames:
- nonroot-psp
verbs:
- use
Step 4. ClusterRoleBinding 생성
$ 4.nonroot-clusterrolebinding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: nonroot-clusterrole-bindings
subjects:
- kind: ServiceAccount
name: nonroot-sa
namespace: default
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: nonroot-clusterrole
Step 5. k8s PSP with RBAC 설정 적용
$ kubectl apply -f default-psp-with-rbac.yaml
$ kubectl create -f nonroot-sa.yaml
$ kubectl apply -f nonroot-clusterrole.yaml
$ kubectl apply -f nonroot-clusterrolebinding.yaml
# PSP,RBAC 및 서비스 계정 기동 확인
$ kubectl get psp
$ kubectl get sa
$ kubectl get clusterrole
$ kubectl get clusterrolebinding
Step 6. Admission Controller 활성화
k8s apiserver를 수정해줘야 한다.
$ vi /etc/kubernetes/manifests/kube-apiserver.yaml
$ kubectl apply -f kube-apiserver.yaml
$ kubectl get pods -n kube-system
Step 7. PSP 적용 Deployment 생성
$ vi 1.hello-deployment.yaml
apiVersion: apps/v1beta2
kind: Deployment
metadata:
name: hello-deployment
spec:
replicas: 3
minReadySeconds: 5
selector:
matchLabels:
app: hello-deployment
template:
metadata:
name: hello-deployment-pod
labels:
app: hello-deployment
spec:
serviceAccountName: nonroot-sa
securityContext:
runAsUser: 1000
fsGroup: 1000
containers:
- name: hello-deployment
image: 192.168.10.7:5000/pss/hello:v1
imagePullPolicy: Always
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: hello-deployment-svc
spec:
selector:
app: hello-deployment
ports:
- name: http
port: 80
protocol: TCP
targetPort: 8080
type: LoadBalancer
※ 중요
NonRoot로 기동할 것이기 때문에 서비스 계정(serviceAccountName)뿐만 아니라 securityContext에서 기동할 User를 반드시 명시해줘야 한다.
Step 8. 기동 테스트
# 기동
$ kubectl create -f 1.hello-deployment.yaml
# 확인
$ kubectl get pods
# 컨테이너 진입
$ kubectl exec -it nonroot-deploy-56d47694df-8hnjh /bin/bash
=> 생성된 파일들이 root가 아닌 appuser라는 것을 확인
( 사용자 pid 1000을 사용했다면 node가 사용자 계정이 될 것이다. 여기서 appuser는 docker 이미지 빌드시 필자가 지정해준 사용자이다. )
-끝-
============================================================================
만약 Step 6. 에서 Admission Controller가 활성화 되지 않고 kube-apiserver pod가 pending이나 error상태라면 아래 default PSP를 먼저 생성해주고 다시 Admission Controller를 적용해봐라.
default PSP 정의
$ vi 0.default-psp-with-rbac.yaml
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
annotations:
apparmor.security.beta.kubernetes.io/allowedProfileNames: 'runtime/default'
apparmor.security.beta.kubernetes.io/defaultProfileName: 'runtime/default'
seccomp.security.alpha.kubernetes.io/allowedProfileNames: 'docker/default'
seccomp.security.alpha.kubernetes.io/defaultProfileName: 'docker/default'
name: default
spec:
allowedCapabilities: [] # default set of capabilities are implicitly allowed
allowPrivilegeEscalation: false
fsGroup:
rule: 'MustRunAs'
ranges:
# Forbid adding the root group.
- min: 1
max: 65535
hostIPC: false
hostNetwork: false
hostPID: false
privileged: false
readOnlyRootFilesystem: false
runAsUser:
rule: 'MustRunAsNonRoot'
seLinux:
rule: 'RunAsNonRoot'
supplementalGroups:
rule: 'RunAsNonRoot'
ranges:
# Forbid adding the root group.
- min: 1
max: 65535
volumes:
- 'configMap'
- 'downwardAPI'
- 'emptyDir'
- 'persistentVolumeClaim'
- 'projected'
- 'secret'
hostNetwork: false
runAsUser:
rule: 'RunAsAny'
seLinux:
rule: 'RunAsAny'
supplementalGroups:
rule: 'RunAsAny'
fsGroup:
rule: 'RunAsAny'
---
# Cluster role which grants access to the default pod security policy
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: default-psp
rules:
- apiGroups:
- policy
resourceNames:
- default
resources:
- podsecuritypolicies
verbs:
- use
---
# Cluster role binding for default pod security policy granting all authenticated users access
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: default-psp
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: default-psp
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: Group
name: system:authenticated
$ kubectl create -f 0.default-psp-with-rbac.yaml
'Cloud > Kubernates' 카테고리의 다른 글
# k8s 유용한 명령어 (0) | 2019.10.31 |
---|---|
# k8s Horizontal Pod Autoscaler (HPA) 실습 - 2 (0) | 2019.10.31 |
# k8s Horizontal Pod Autoscaler (HPA) 실습 - 1 (0) | 2019.10.23 |
# k8s Pod Autoscaler 개념 (2) | 2019.10.23 |
# docker + k8s + tensorflow-gpu 구성 (0) | 2019.09.26 |