k8s 보안

ImOk·2023년 4월 9일
0
post-thumbnail

Cloudnet@에서 진행하는 쿠버네티스 실무 실습 스터디를 진행하면서 작성한 글입니다.
스터디에서 사용하는 교재는 24단계 실습으로 정복하는 쿠버네티스 입니다.

Cloudnet@
24단계 실습으로 정복하는 쿠버네티스


실습 환경 배포

# CloudFormation 스택 배포
aws cloudformation deploy \
--template-file kops-oneclick-f1.yaml \
--stack-name mykops \
--parameter-overrides KeyName=kops-key \
SgIngressSshCidr=$(curl -s ipinfo.io/ip)/32 \
MyIamUserAccessKeyID=AKI... \
MyIamUserSecretAccessKey='o4H...' \
ClusterBaseName='imokapp.net' \
S3StateStore='imok-k8s-study' \
MasterNodeInstanceType=t3.medium \
WorkerNodeInstanceType=c5d.large \
--region ap-northeast-2

# 13분 후 작업 SSH 접속
ssh -i kops-key.pem \
ec2-user@$(aws cloudformation describe-stacks \
--stack-name mykops \
--query 'Stacks[*].Outputs[0].OutputValue' \
--output text)

kops validate cluster --wait 10m

# EC2 instance profiles 에 IAM Policy 추가(attach)
aws iam attach-role-policy --policy-arn arn:aws:iam::$ACCOUNT_ID:policy/AWSLoadBalancerControllerIAMPolicy --role-name masters.$KOPS_CLUSTER_NAME
aws iam attach-role-policy --policy-arn arn:aws:iam::$ACCOUNT_ID:policy/AWSLoadBalancerControllerIAMPolicy --role-name nodes.$KOPS_CLUSTER_NAME

kubectl ns default

EC2 메타데이터 호출 실습

IMDS(Instance Metadata Service)를 사용하여 실행 중인 인스턴스에서 인스턴스 메타데이터에 액세스할 수 있습니다.

AWS 인스턴스 메타데이터 검색

워커 노드 1대 EC2 메타데이터(IMDSv2) 보안 제거 및 호출 확인

kops 클러스터로 배포되는 워커 노드의 인스턴스 그룹 2개 중, 첫 번째의 인스턴스 메타데이터 설정을 삭제합니다.

메타데이터 관련 보안 정책을 제거한 후 보안에 취약해집니다.

#
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

각각의 워커 노드에 접속해 메타데이터 사용이 가능한지 확인해 봅니다.

# 워커 노드 Public IP 확인
aws ec2 describe-instances --query "Reservations[*].Instances[*].{PublicIPAdd:PublicIpAddress,InstanceName:Tags[?Key=='Name']|[0].Value}" --filters Name=instance-state-name,Values=running --output table

# 워커 노드 Public IP 변수 지정
W1PIP=<워커 노드 1 Public IP>
W2PIP=<워커 노드 2 Public IP>

# 워커 노드 SSH 접속
ssh -i ~/.ssh/id_rsa ubuntu@$W1PIP
ssh -i ~/.ssh/id_rsa ubuntu@$W2PIP

curl -v http://169.254.169.254/latest

kops 클러스터 기본 설정으로는 워커노드 2c는 다음과 같이 메타데이터를 호출할 수 없습니다.

보안을 제거한 워커노드 2a는 메타데이터를 호출할 수 있습니다.

POD에서 메타데이터 호출 확인

인스턴스 메타데이터 API 노드 설정은 pod까지 영향이 갑니다.

# netshoot-pod 생성
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
        command: ["tail"]
        args: ["-f", "/dev/null"]
      terminationGracePeriodSeconds: 0
EOF

# 파드 이름 변수 지정
PODNAME1=$(kubectl get pod -l app=netshoot-pod -o jsonpath={.items[0].metadata.name})
PODNAME2=$(kubectl get pod -l app=netshoot-pod -o jsonpath={.items[1].metadata.name})

# EC2 메타데이터 정보 확인
kubectl exec -it $PODNAME1 -- curl 169.254.169.254 ;echo
kubectl exec -it $PODNAME2 -- curl 169.254.169.254 ;echo

Pod 2번에서는 다음과 같이 호출해도 아무것도 보이지 않습니다.

pod 1번에서는 다음과 같이 메타데이터를 호출할 수 있습니다.

또한 security-credentials 정보도 쉽게 출력할 수 있습니다.

kubectl exec -it $PODNAME1 -- curl 169.254.169.254/latest/meta-data/iam/security-credentials/nodes.$KOPS_CLUSTER_NAME | jq

🚨 이처럼 Pod가 IMDS API를 사용 가능하게 된다면, 많은 보안상 위험에 노출됩니다.
pod를 해킹해 IMDS API를 사용해서 credentials 정보를 탈취해, AWS 리소스를 생성할 수도 있습니다.


쿠버네티스 보안 도구 활용

클러스터 내부에 실행 중인 모든 파드는 기본 설정으로 클러스터 내 다른 모든 파드와 통신이 가능합니다.
따라서 특정 파드가 외부 공격자에 노출되면, 같은 노드 내 다른 파드는 물론 통신 가능한 클러스터 전체의 다른 노드에서 실행 중인 모든 파드까지 영향을 끼칩니다.

쿠버네티스 보안 적용 대상 4C

각 계층 마다 각각 적절한 보안 설정을 적용해 전체적으로 안전한 시스템을 만들 필요가 있습니다.

  1. 클라우드(Cloud)
  2. 클러스터(Cluster)
  3. 컨테이너(Container)
  4. 코드(Code)

The 4C's of Cloud Native security


kubescape

미국 NSA에서 발행한 쿠버네티스 보안 체크리스트를 기준으로 현재 클러스터의 취약점을 점검하고 이를 대시보드 형태로 리포트합니다.

kubescape github

NSA/CISA 의 쿠버네티스 클러스터 보안 가이드

  1. 컨테이너의 root 사용자 권한 제거
  2. 컨테이너 내부 파일 시스템 쓰기 권한 제거
  3. 컨테이너의 불필요한 추가 특권 제거
  4. 리소스 제한 설정
  5. 불필요한 외부 접속 제한을 위한 네트워크 정책 적용
  6. 호스트 노드 보안 강화(SELinux 등 사용)

📝 실습 내용
1. kubescape를 설치 및 실행
2. NSA/CISA 보안 권고 사항 대비 현재 클러스터의 보안 취약점 확인


kubesacpe 설치

# 설치
curl -s https://raw.githubusercontent.com/kubescape/kubescape/master/install.sh | /bin/bash

kubescape version
Your current version is: v2.2.6 [git enabled in build: true]

제공하는 보안 프레임워크들을 확인해 봅니다.

# Download all artifacts and save them in the default path (~/.kubescape)
kubescape download artifacts
tree ~/.kubescape/
cat ~/.kubescape/attack-tracks.json | jq

# 제공하는 보안 프레임워크 확인
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

kubesacpe를 사용해서 보안 취약점을 확인해 보겠습니다.

kubescape scan --enable-host-scan --verbose
kubescape scan framework nsa -e kubesys-tem,kube-public

클러스터 보안 점검 결과 많은 보안 취약점이 발견된 것을 볼 수 있습니다. 😭

kubescape web

kubescape에서 제공하는 web을 통해 보안 취약점을 확인해 봅시다.
회원가입 후 10개의 worker노드까지 무료로 사용할 수 있습니다.
https://cloud.armosec.io/

회원 가입 후 들어가면 다음과 같이 설치 명령어가 나옵니다.

Compliance

클러스터의 보안과 규정 준수를 유지하기 위해 보안 위험을 신속하게 발견, 평가 및 해결합니다.

다음과 같이 보안이 필요한 항목에 대해 확인할 수 있습니다.

Vulnerabilities

모든 클러스터에서 알려진 취약점 또는 새로운 취약점을 감지합니다.

RBAC Visualizer

RBAC 구성 상태를 시각화합니다.


polaris

보안 체크리스트 뿐만 아니라 가용성, 안정성 측면에서 모범 사례 대비 현재 매니페스트 yaml 파일의 부족한 점을 파악할 수 있습니다. 해결 방법도 다른 도구에 비해 좀 더 직관적 입니다.
polaris github

📝 실습 내용
1. 헬름 차트를 이용해 redis 설치 Polaris 헬름 차트
2. 보안 점검도구 polaris를 이용해 레디스 파드의 취약점을 확인하고 이를 수정

redis 설치

인메모리 기반 데이터베이스인 레디스를 헬름 기반으로 설치합니다.

# redis 헬름 차트 설치
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo update
helm pull bitnami/redis
tar xvfz redis-17.9.3.tgz
cd redis/
cp values.yaml my-values.yaml

# 배포
k create ns redis
k ns redis
helm install redis bitnami/redis --namespace redis -f my-values.yaml

# pod 확인
k get pod

polaris 설치 및 redis 보안 취약점 확인

폴라리스를 설치해 보안 취약점을 확인합니다.

# polaris 헬름 차트 설치
helm repo add fairwinds-stable https://charts.fairwinds.com/stable
helm repo update
helm pull fairwinds-stable/polaris
tar xvfz polaris-5.7.3.tgz
cd polaris/
cp values.yaml my-values.yaml

LoadBalancer로 변경

k create ns polaris
k ns polaris

# 배포
helm install polaris fairwinds-stable/polaris --namespace polaris --version 5.7.3 -f my-values.yaml
# CLB에 ExternanDNS 로 도메인 연결
kubectl annotate service polaris-dashboard "external-dns.alpha.kubernetes.io/hostname=polaris.$KOPS_CLUSTER_NAME" -n polaris
# 웹 접속 주소 확인 및 접속
echo -e "Polaris Web URL = http://polaris.$KOPS_CLUSTER_NAME"

# pod 확인
k get pod
# 웹 서비스 포트 확인
k get svc
# 노드 ip 주소 확인
k get node -o wide

앞에서 설치한 redis 애플리케이션의 상세한 권고 사항을 확인할 수 있습니다.

❓ 버튼을 클릭하면, 해당 사항에 대하 자세한 설명을 확인할 수 있습니다.

polaris pod의 매니페스트 yaml 파일은 모범 사례로 구성돼 있기 때문에 해당 yaml 파일을 참고해서 다른 애플리케이션을 수정해 적용할 수 있습니다.
구체적인 설정을 확인하기 위해 실행 중인 polaris pod 설정을 확인해 봅니다.
k get pod polaris-dashboard-78 -o yaml > polaris-dashboard-pod.yaml

해당 파일을 참고해서 redis 헬름 차트의 yaml 파일에 securityContext.allowPrivilegeEscalation 설정을 추가해봅니다.

# redis 재설치
helm upgrade redis bitnami/redis --namespace redis -f my-values.yaml

polaris 웹에서 변경 사항을 확인합니다.

profile
ImOk👌

0개의 댓글