스터디에서 진행하는 이론 및 실습은 PKOS 스터디 자료 및 이정훈 님의 "24단계 실습으로 정복하는 쿠버네티스" 서적의 내용을 기반으로 합니다.
24단계 실습으로 정복하는 쿠버네티스 | 위키북스 | 이정훈 | 링크
들어가며
이번 주 스터디에서는 kOps Cluster (Kubernetes Cluster)의 보안 구성에 대한 내용을 배웠다.
회사에서 개발하는 서비스를 오픈하기 전에 반드시 신경 써야 할 부분이 보안이다. CKA, CKAD 과정에서 RBAC (Role, RoleBinding)에 대해 배웠었지만 실제 우리 부서 클러스터에는 적용한 적이 없었다. 이번 스터디에서 배운 내용은 단순한 외부 보안뿐 아니라, 사내 전체의 클러스터를 운영하기 위해 활용할 수 있을 것 같다고 생각했다.
실습 환경 구성
이번 실습 환경은 t3.small 1식 & t3.xlarge 서버 3식으로 클러스터를 구성했다. (Bastion, Leader Node, Follow Node)
기존에 사용하던 kOps Cluster 구축 스크립트를 스터디장께서 업그레이드 해주셔서 certManager, awsLoadBalancerController, externalDns, metricsServer, kubeProxy addon을 자동으로 추가되었다.
마지막으로 Deployment를 kOps Cluster 외부로 노출시킬 수 있도록 클러스터 환경에서 IAM Policy에 AWSLoadBalancerControllerIAMPolicy와 AllowExternalDNSUpdates를 추가했다.
Boto3을 이용한 Kubernetes Pod 탈취 시나리오
Follow Node의 메타데이터 보안 제거를 한 후 Pod에서 EC2 권한을 탈취하는 실습을 진행했다. AWS EC2 인스턴스의 IAM Role을 사용하여 클러스터에 접근할 수 있다. 만약 Follow Node의 컨테이너가 탈취된다면, EC2 인스턴스를 통해 각종 정보를 탈취할 수 있다. 그래서 각 Pod에 IAM Role 권한을 부여해서 EC2 인스턴스에 접근할 수 없도록 한다.
메타데이터 보안 제거를 하는 방법은 다음과 같다.
ap-northeast-2a, ap-northeast-2c 중에서 하나의 인스턴스 보안을 제거한다.
kops edit ig nodes-ap-northeast-2a
---
# 아래 3줄 제거
spec:
instanceMetadata:
httpPutResponseHopLimit: 1
httpTokens: required
---
# 업데이트 적용 : 노드1대 롤링업데이트
kops update cluster --yes && echo && sleep 3 && kops rolling-update cluster --yes
Pod 안에서 boto3을 이용하여 EC2 메타데이터를 탈취한다.
# boto3 를 사용할 수 있는 Pod 생성
cat <<EOF | kubectl create -f -
apiVersion: apps/v1
kind: Deployment
metadata:
name: boto3-pod
spec:
replicas: 2
selector:
matchLabels:
app: boto3
template:
metadata:
labels:
app: boto3
spec:
containers:
- name: boto3
image: jpbarto/boto3
command: ["tail"]
args: ["-f", "/dev/null"]
terminationGracePeriodSeconds: 0
EOF
# Pod에 접속
kubectl exec -it (kubectl get pod -l app=boto3 -o jsonpath={.items[0].metadata.name}) -- sh
Pod에 접속하고나면, boto3 SDK를 이용해서 EC2 정보를 탈취할 수 있다.
# 인스턴스 정보를 모두 확인할 수 있는 ec2.py
cat <<EOF> ec2.py
import boto3
ec2 = boto3.client('ec2', region_name = 'ap-northeast-2')
response = ec2.describe_instances()
print(response)
EOF
#스크립트 실행
python ec2.py
하지만 httpToken이 적용되어 있는 환경이라면 다음과 같이 정보를 탈취할 수 없다.
Kubescape (취약점 점검 툴)
Kubescape는 DevOps를 위한 kubernetes용 보안 플랫폼이다.
NSA/CISA의 ‘쿠버네티스 보안강화 지침(Kubernetest hadrdening Guidance)’ 가이드에 맞게 안전하게 배포되었는지 테스트하는 도구로써 단일 yaml 파일부터 클러스터 단위의 테스트를 수행한다.
OPA의 활용사례 - kubescape | Devocean | sungil | 링크
Kubescape Architecture | Github | 링크
Kubescape 를 통해 다음과 같이 클러스터의 취약점을 스캔할 수 있다.
# 설치
curl -s https://raw.githubusercontent.com/kubescape/kubescape/master/install.sh | /bin/bash
kubescape download artifacts
# 제공하는 보안 프레임웍 확인
kubescape list frameworks --format json | jq '.[]'
"AllControls"
"ArmoBest"
"DevOpsBest"
"MITRE"
"NSA"
"cis-eks-t1.2.0"
"cis-v1.23-t1.0.1"
# 통제 정책 확인
kubescape list controls
# 취약점 스캔
kubescape scan --enable-host-scan --verbose
취약점 스캔을 통해 보안 단계에 대한 조치 권고를 확인할 수 있다.
Polaris
Polaris는 Kubescape와 같은 오픈소스 보안 점검 도구로써, Kubernetes 리소스를 검증하고 수정하여 구성 모범사례를 따르도록 한다.
Polaris는 IaC 단계 및 쿠버네티스 Admission Control와 Kubernetes Resource 생성 단계에서 보안 점검을 통해 현재 상황을 대시보드 형태로 확인하거나, 리소스 생성을 제한할 수 있다.
다음의 점검 항목들 중에서 “image tag should be specified”를 확인할 수 있는데, image 태그가 정해져 있지 않아서 생기는 문제다. 이미지의 최신 버전에 바이러스를 심어 공격할 수도 있기 때문에, image tag의 버전을 명시하는 것을 권고한다고 한다.
다음과 같이 이미지에 버전명을 명시한다.
cat <<EOF | kubectl create -f -
apiVersion: apps/v1
kind: Deployment
metadata:
name: netshoot-pod
spec:
replicas: 2
...
template:
metadata:
labels:
app: netshoot-pod
spec:
containers:
- name: netshoot-pod
image: nicolaka/netshoot:v0.9
...
EOF
수정하면 다음과 같이 이미지 태그에 대한 보안사항이 해결된다.
? 를 클릭하면 다음과 같이 권고사항에 대한 상세 내용을 확인할 수 있어서 유용하다.
만약에 웹훅을 이용하게 된다면 다음과 같이 보안 권고사항을 지켜야 한다고 알려주고 배포할 수 없게 만들 수 있다.
다음과 같이 IaC 단계에서도 보안 점검이 가능하다.
polaris audit --audit-path ~/pkos/1/mario.yaml --format=pretty
K8S 인증/인가 & RBAC
Kubernetes RBAC(Role, RoleBinding)을 이용해서 namespace/cluster 별로 권한을 줄 수 있다.
실습을 위해 dev-team, infra-team 두개의 네임스페이스를 만드는데 이는 개발팀과 인프라팀이 사용할 수 있는 환경을 만든 것이다.
Role과 Role Binding을 이용해서 권한설정을 하게 되면 팀별로 접근할 수 있는 자원을 제한할 수 있다.
7주 차 과제
과제 1
파드에서 EC2 메타데이터의 IAM Role 토큰 정보를 활용하여(boto3), 스터디에서 소개한 것 이외의 다른 AWS 서비스(혹은 Action)를 사용 후 코드나 스샷을 올려주세요
시큐리티 그룹 생성 - Create a security group and rules - 링크
시큐리티 그룹 생성을 위해 NetworkAdminstrator 권한 할당
import boto3
from botocore.exceptions import ClientError
ec2 = boto3.client('ec2', region_name = 'ap-northeast-2')
response = ec2.describe_vpcs()
vpc_id = response.get('Vpcs', [{}])[0].get('VpcId', '')
try:
response = ec2.create_security_group(GroupName='SECURITY_GROUP_NAME',
Description='DESCRIPTION',
VpcId=vpc_id)
security_group_id = response['GroupId']
print('Security Group Created %s in vpc %s.' % (security_group_id, vpc_id))
data = ec2.authorize_security_group_ingress(
GroupId=security_group_id,
IpPermissions=[
{'IpProtocol': 'tcp',
'FromPort': 80,
'ToPort': 80,
'IpRanges': [{'CidrIp': '0.0.0.0/0'}]},
{'IpProtocol': 'tcp',
'FromPort': 22,
'ToPort': 22,
'IpRanges': [{'CidrIp': '0.0.0.0/0'}]}
])
print('Ingress Successfully Set %s' % data)
except ClientError as e:
print(e)
과제 2
책 398~400페이지 - kubescape armo 웹 사용 후 관련 스샷을 올려주세요
helm repo add kubescape https://kubescape.github.io/helm-charts/
helm repo update
helm upgrade --install kubescape kubescape/kubescape-cloud-operator -n kubescape --create-namespace --set account=928cf7c5-0826-4d0f-9978-b9dbaf2908cb --set clusterName=`kubectl config current-context`
과제 3
polaris 관련 실습(아무거나) 후 관련 스샷을 올려주세요
Liveness probe should be configured
cat <<EOF | kubectl create -f -
apiVersion: apps/v1
kind: Deployment
metadata:
name: netshoot-pod
spec:
replicas: 2
selector:
matchLabels:
app: netshoot-pod
template:
metadata:
labels:
app: netshoot-pod
spec:
containers:
- name: netshoot-pod
image: nicolaka/netshoot:v0.9
command: ["tail"]
args: ["-f", "/dev/null"]
livenessProbe:
exec:
command:
- cat
- /tmp/healthy
initialDelaySeconds: 5
periodSeconds: 5
imagePullPolicy: Always
resources:
limits:
cpu: 150m
memory: 512Mi
requests:
cpu: 100m
memory: 128Mi
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
privileged: false
readOnlyRootFilesystem: true
#runAsNonRoot: true
terminationGracePeriodSeconds: 0
EOF
과제 4
신규 서비스 어카운트(SA) 생성 후 '클러스터 수준(모든 네임스페이스 포함)에서 읽기 전용'의 권한을 주고 테스트 후 코드나 스샷을 올려주세요
#1 신규 어카운트 전용 네임스페이스 생성
kubectl create ns devlos-lab
#2 신규 어카운트 생성
kubectl create sa k8s-mighty -n devlos-lab
#3 클러스터 접속이 가능한 환경 생성
cat <<EOF | kubectl create -f -
apiVersion: v1
kind: Pod
metadata:
name: lab-kubectl
namespace: devlos-lab
spec:
serviceAccountName: k8s-mighty
containers:
- name: kubectl-pod
image: bitnami/kubectl:1.24.10
command: ["tail"]
args: ["-f", "/dev/null"]
terminationGracePeriodSeconds: 0
EOF
#4 Role 생성
cat <<EOF | kubectl create -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: role-mighty
namespace: devlos-lab
rules:
- apiGroups: ["*"]
resources: ["*"]
verbs: ["get", "watch", "list"]
EOF
#5 Role Binding
cat <<EOF | kubectl create -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: role-binding-cluster
namespace: devlos-lab
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: role-mighty
subjects:
- kind: ServiceAccount
name: k8s-mighty
namespace: devlos-lab
EOF
#SA용 단축 키워드 지정
alias k-all='kubectl exec -it lab-kubectl -n devlos-lab -- kubectl'
Pod를 볼 수는 있지만,
생성할 수는 없다.
마치며
스터디를 통해 kubernetes cluster의 보안환경 구축에 대한 실무 노하우를 알 수 있었다. 특히 클러스터의 보안 상태를 점검해 볼 수 있는 kubescape, polaris와 같은 툴을 알게 되어 보안 방향성과 개선 필요 사항들에 대해 확인할 수 있다는 것은 정말 소중한 정보였다. 이러한 툴들을 적극 활용하여 더욱더 안전한 시스템을 개선할 수 있을 것이다. 또한 단순 보안뿐 아니라 네임스페이스를 통해 부서별로 리소스의 권한을 관리할 수 있다는 점도 다시 한번 상기할 수 있었다.
이렇게 오랜 시간동안 스터디를 처음 진행해 봐서 얼마나 힘든 것인지도 잘 몰랐다. 과제를 하면서 ‘내가 끝까지 스터디를 마칠 수 있을까?..’ 하는 생각이 든 적이 많았다. 하지만 다행스럽게도 풀리지 않던 문제들을 포기하지 않고 하나둘씩 해결해 나갔고 무사히 스터디를 마칠 수 있었다. 개인적으로도 많은 도움이 되었지만, 내가 속한 조직에 적용하고 비즈니스적 가치를 이끌어 낼 수 있는 수많은 지식을 단 7주 만에 얻을 수 있어서 행운이었다.
스터디에 참여한 많은 개발자 분들은 훨씬 더 많은 경험을 가지고 있을 것이다. 스터디의 정보를 이용하여 필자도 좀더 공부해서 다른 개발자들에게 도움이 되는 정보를 제공할 수 있도록 노력해야겠다.
누군가는 필자의 블로그를 통해 7주간의 스터디 정보를 접할 수 있을것이다.
필자가 정리한 글들은 스터디 내용보다 많이 미흡하지만, 부디 그 분들에게 조금이나마 도움이 되는 정보였길 바란다.
(그럼 이제.. 스터디 뒷풀이 참석 고고)
'클라우드 컴퓨팅 & NoSQL > [PKOS] 쿠버네티스 실무 실습 스터디' 카테고리의 다른 글
[6주차] PKOS 쿠버네티스 실무 실습 스터디 (23.02.19) (1) | 2023.02.26 |
---|---|
[5주차] PKOS 쿠버네티스 실무 실습 스터디 (23.02.12) (0) | 2023.02.18 |
[4주차] PKOS 쿠버네티스 실무 실습 스터디 (23.02.04) (0) | 2023.02.11 |
[3주차] PKOS 쿠버네티스 실무 실습 스터디 (23.01.29) (0) | 2023.02.04 |
[2주차] PKOS 쿠버네티스 실무 실습 스터디 (23.01.15) (0) | 2023.01.29 |