#스터디 시작
EKS Security는 EKS 플랫폼에서 컨테이너화된 애플리케이션을 배포하고 관리하는 보안 측면을 이해하기 위한 구조화된 접근 방식이 필요합니다. 여기에는 Kubernetes 기본 사항 숙지, EKS의 특정 보안 기능 및 모범 사례 살펴보기, 액세스 제어를 위한 IAM 숙달, 네트워크 보안, 데이터 암호화, 포드 보안 정책 학습, 로깅, 모니터링, 패치 및 업데이트 업데이트 유지, 탐색이 수반됩니다. 여러 보안 도구를 사용하고 보안 모범 사례를 지속적으로 준수하여 EKS 클러스터에 대한 보안을 강화할 수 있도록 공부할 것입니다.
#사전준비
- Amazon EKS (myeks) 윈클릭 배포 (bastion ec2 2대) & 기본 설정
# YAML 파일 다운로드
curl -O https://s3.ap-northeast-2.amazonaws.com/cloudformation.cloudneta.net/K8S/eks-oneclick5.yaml
# CloudFormation 스택 배포
예시) aws cloudformation deploy --template-file eks-oneclick5.yaml --stack-name myeks --parameter-overrides KeyName=kp-gasida SgIngressSshCidr=$(curl -s ipinfo.io/ip)/32 MyIamUserAccessKeyID=AKIA5... MyIamUserSecretAccessKey='CVNa2...' ClusterBaseName=myeks --region ap-northeast-2
# CloudFormation 스택 배포 완료 후 작업용 EC2 IP 출력
aws cloudformation describe-stacks --stack-name myeks --query 'Stacks[*].Outputs[0].OutputValue' --output text
# 작업용 EC2 SSH 접속
ssh -i ~/.ssh/kp-gasida.pem ec2-user@$(aws cloudformation describe-stacks --stack-name myeks --query 'Stacks[*].Outputs[0].OutputValue' --output text)
or
ssh -i ~/.ssh/kp-gasida.pem root@$(aws cloudformation describe-stacks --stack-name myeks --query 'Stacks[*].Outputs[0].OutputValue' --output text)
- 기본 설정
# default 네임스페이스 적용
kubectl ns default
# 노드 정보 확인 : t3.medium
kubectl get node --label-columns=node.kubernetes.io/instance-type,eks.amazonaws.com/capacityType,topology.kubernetes.io/zone
# ExternalDNS
MyDomain=<자신의 도메인>
echo "export MyDomain=<자신의 도메인>" >> /etc/profile
MyDomain=gasida.link
echo "export MyDomain=gasida.link" >> /etc/profile
MyDnzHostedZoneId=$(aws route53 list-hosted-zones-by-name --dns-name "${MyDomain}." --query "HostedZones[0].Id" --output text)
echo $MyDomain, $MyDnzHostedZoneId
curl -s -O https://raw.githubusercontent.com/gasida/PKOS/main/aews/externaldns.yaml
MyDomain=$MyDomain MyDnzHostedZoneId=$MyDnzHostedZoneId envsubst < externaldns.yaml | kubectl apply -f -
# kube-ops-view
helm repo add geek-cookbook https://geek-cookbook.github.io/charts/
helm install kube-ops-view geek-cookbook/kube-ops-view --version 1.2.2 --set env.TZ="Asia/Seoul" --namespace kube-system
kubectl patch svc -n kube-system kube-ops-view -p '{"spec":{"type":"LoadBalancer"}}'
kubectl annotate service kube-ops-view -n kube-system "external-dns.alpha.kubernetes.io/hostname=kubeopsview.$MyDomain"
echo -e "Kube Ops View URL = http://kubeopsview.$MyDomain:8080/#scale=1.5"
# AWS LB Controller
helm repo add eks https://aws.github.io/eks-charts
helm repo update
helm install aws-load-balancer-controller eks/aws-load-balancer-controller -n kube-system --set clusterName=$CLUSTER_NAME \
--set serviceAccount.create=false --set serviceAccount.name=aws-load-balancer-controller
# gp3 스토리지 클래스 생성
kubectl apply -f https://raw.githubusercontent.com/gasida/PKOS/main/aews/gp3-sc.yaml
# 노드 IP 확인 및 PrivateIP 변수 지정
N1=$(kubectl get node --label-columns=topology.kubernetes.io/zone --selector=topology.kubernetes.io/zone=ap-northeast-2a -o jsonpath={.items[0].status.addresses[0].address})
N2=$(kubectl get node --label-columns=topology.kubernetes.io/zone --selector=topology.kubernetes.io/zone=ap-northeast-2b -o jsonpath={.items[0].status.addresses[0].address})
N3=$(kubectl get node --label-columns=topology.kubernetes.io/zone --selector=topology.kubernetes.io/zone=ap-northeast-2c -o jsonpath={.items[0].status.addresses[0].address})
echo "export N1=$N1" >> /etc/profile
echo "export N2=$N2" >> /etc/profile
echo "export N3=$N3" >> /etc/profile
echo $N1, $N2, $N3
# 노드 보안그룹 ID 확인
NGSGID=$(aws ec2 describe-security-groups --filters Name=group-name,Values=*ng1* --query "SecurityGroups[*].[GroupId]" --output text)
aws ec2 authorize-security-group-ingress --group-id $NGSGID --protocol '-1' --cidr 192.168.1.100/32
aws ec2 authorize-security-group-ingress --group-id $NGSGID --protocol '-1' --cidr 192.168.1.200/32
# 워커 노드 SSH 접속
for node in $N1 $N2 $N3; do ssh -o StrictHostKeyChecking=no ec2-user@$node hostname; done
for node in $N1 $N2 $N3; do ssh ec2-user@$node hostname; done

- 프로메테우스 & 그라파나(admin / prom-operator) 설치 : 대시보드 추천 15757 17900 15172
# 사용 리전의 인증서 ARN 확인
CERT_ARN=`aws acm list-certificates --query 'CertificateSummaryList[].CertificateArn[]' --output text`
echo $CERT_ARN
# repo 추가
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
# 파라미터 파일 생성 : PV/PVC(AWS EBS) 삭제에 불편하니, 4주차 실습과 다르게 PV/PVC 미사용
cat <<EOT > monitor-values.yaml
prometheus:
prometheusSpec:
podMonitorSelectorNilUsesHelmValues: false
serviceMonitorSelectorNilUsesHelmValues: false
retention: 5d
retentionSize: "10GiB"
ingress:
enabled: true
ingressClassName: alb
hosts:
- prometheus.$MyDomain
paths:
- /*
annotations:
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/target-type: ip
alb.ingress.kubernetes.io/listen-ports: '[{"HTTPS":443}, {"HTTP":80}]'
alb.ingress.kubernetes.io/certificate-arn: $CERT_ARN
alb.ingress.kubernetes.io/success-codes: 200-399
alb.ingress.kubernetes.io/load-balancer-name: myeks-ingress-alb
alb.ingress.kubernetes.io/group.name: study
alb.ingress.kubernetes.io/ssl-redirect: '443'
grafana:
defaultDashboardsTimezone: Asia/Seoul
adminPassword: prom-operator
defaultDashboardsEnabled: false
ingress:
enabled: true
ingressClassName: alb
hosts:
- grafana.$MyDomain
paths:
- /*
annotations:
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/target-type: ip
alb.ingress.kubernetes.io/listen-ports: '[{"HTTPS":443}, {"HTTP":80}]'
alb.ingress.kubernetes.io/certificate-arn: $CERT_ARN
alb.ingress.kubernetes.io/success-codes: 200-399
alb.ingress.kubernetes.io/load-balancer-name: myeks-ingress-alb
alb.ingress.kubernetes.io/group.name: study
alb.ingress.kubernetes.io/ssl-redirect: '443'
alertmanager:
enabled: false
EOT
cat monitor-values.yaml | yh
# 배포
kubectl create ns monitoring
helm install kube-prometheus-stack prometheus-community/kube-prometheus-stack --version 57.2.0 \
--set prometheus.prometheusSpec.scrapeInterval='15s' --set prometheus.prometheusSpec.evaluationInterval='15s' \
-f monitor-values.yaml --namespace monitoring
# Metrics-server 배포
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
# 프로메테우스 ingress 도메인으로 웹 접속
echo -e "Prometheus Web URL = https://prometheus.$MyDomain"
# 그라파나 웹 접속 : 기본 계정 - admin / prom-operator
echo -e "Grafana Web URL = https://grafana.$MyDomain"




- grafana 콘솔 화면 (+dashboard)



# EKS Security 개념 및 특징

EKS Security는 제어 플레인이나 노드를 설정, 관리 또는 유지 관리할 필요 없이 Amazon 웹 서비스에서 Kubernetes를 실행할 수 있게 해주는 관리형 서비스입니다 . Kubernetes 는 컨테이너화된 애플리케이션 배포, 확장 및 관리를 자동화하기 위한 오픈 소스 프레임워크입니다.
- AWS 가용 영역.
- 제어 영역 인스턴스는 로드 기준에 따라 자동으로 크기가 조정됩니다. 비정상이거나 결함이 있는 컨트롤 플레인 인스턴스를 관찰, 감지 및 교체하고 패치 적용 및 자동화된 버전 업그레이드가 수행됩니다.
- 다음 기능을 포함하여 애플리케이션의 확장성을 제공하기 위해 다양한 다른 서비스에 통합될 수 있습니다.
- Amazon ECR 의 컨테이너 이미지 .
- 탄력적 로드 밸런싱을 통한 로드 분산.
- 인증에는 IAM이 사용됩니다.
- VPC를 사용한 격리.
- 오픈 소스 Kubernetes 소프트웨어의 최신 버전을 실행하여 커뮤니티의 현재 플러그인과 도구를 활용할 수 있습니다. EKS의 앱은 온프레미스 데이터 센터든 퍼블릭 클라우드든 모든 표준 Kubernetes 환경에서 실행되는 애플리케이션과 완벽하게 호환됩니다. 코드 변경 없이 일반적인 Kubernetes 애플리케이션 을 마이그레이션할 수 있습니다.

클라우드 컴퓨팅이 부상하면서 Amazon EKS는 Kubernetes 컨테이너 애플리케이션을 실행하는 데 필수적인 도구입니다. Kubernetes 리소스를 자동화하는 데 도움이 될 수 있는 강력한 리소스입니다. 그러나 자동화는 더 나은 보안을 제공하지 않습니다. 보안을 수동으로 구현해야 합니다. 프라이빗 서브넷에 작업자 노드를 배포하고, AWS KMS를 사용하여 비밀, 지속적인 모니터링, 데이터 암호화 등을 관리할 수 있습니다.
# EKS Security 실습
- 네임스페이스와 서비스 어카운트 생성 후 확인
- 파드 기동 시 서비스 어카운트 한 개가 할당되며, 서비스 어카운트 기반 인증/인가를 함, 미지정 시 기본 서비스 어카운트가 할당
- 서비스 어카운트에 자동 생성된 시크릿에 저장된 토큰으로 쿠버네티스 API에 대한 인증 정보로 사용 할 수 있다 ← 1.23 이전 버전의 경우에만 해당
# 네임스페이스(Namespace, NS) 생성 및 확인
kubectl create namespace dev-team
kubectl create ns infra-team
# 네임스페이스 확인
kubectl get ns
# 네임스페이스에 각각 서비스 어카운트 생성 : serviceaccounts 약자(=sa)
kubectl create sa dev-k8s -n dev-team
kubectl create sa infra-k8s -n infra-team
# 서비스 어카운트 정보 확인
kubectl get sa -n dev-team
kubectl get sa dev-k8s -n dev-team -o yaml | yh
kubectl get sa -n infra-team
kubectl get sa infra-k8s -n infra-team -o yaml | yh

# 각각 네임스피이스에 kubectl 파드 생성 - 컨테이너이미지
# docker run --rm --name kubectl -v /path/to/your/kube/config:/.kube/config bitnami/kubectl:latest
cat <<EOF | kubectl create -f -
apiVersion: v1
kind: Pod
metadata:
name: dev-kubectl
namespace: dev-team
spec:
serviceAccountName: dev-k8s
containers:
- name: kubectl-pod
image: bitnami/kubectl:1.28.5
command: ["tail"]
args: ["-f", "/dev/null"]
terminationGracePeriodSeconds: 0
EOF
cat <<EOF | kubectl create -f -
apiVersion: v1
kind: Pod
metadata:
name: infra-kubectl
namespace: infra-team
spec:
serviceAccountName: infra-k8s
containers:
- name: kubectl-pod
image: bitnami/kubectl:1.28.5
command: ["tail"]
args: ["-f", "/dev/null"]
terminationGracePeriodSeconds: 0
EOF
# 확인
kubectl get pod -A
kubectl get pod -o dev-kubectl -n dev-team -o yaml
serviceAccount: dev-k8s
...
kubectl get pod -o infra-kubectl -n infra-team -o yaml
serviceAccount: infra-k8s
...
# 파드에 기본 적용되는 서비스 어카운트(토큰) 정보 확인
kubectl exec -it dev-kubectl -n dev-team -- ls /run/secrets/kubernetes.io/serviceaccount
kubectl exec -it dev-kubectl -n dev-team -- cat /run/secrets/kubernetes.io/serviceaccount/token
kubectl exec -it dev-kubectl -n dev-team -- cat /run/secrets/kubernetes.io/serviceaccount/namespace
kubectl exec -it dev-kubectl -n dev-team -- cat /run/secrets/kubernetes.io/serviceaccount/ca.crt
# 각각 파드로 Shell 접속하여 정보 확인 : 단축 명령어(alias) 사용
alias k1='kubectl exec -it dev-kubectl -n dev-team -- kubectl'
alias k2='kubectl exec -it infra-kubectl -n infra-team -- kubectl'
# 권한 테스트
k1 get pods # kubectl exec -it dev-kubectl -n dev-team -- kubectl get pods 와 동일한 실행 명령이다!
k1 run nginx --image nginx:1.20-alpine
k1 get pods -n kube-system
k2 get pods # kubectl exec -it infra-kubectl -n infra-team -- kubectl get pods 와 동일한 실행 명령이다!
k2 run nginx --image nginx:1.20-alpine
k2 get pods -n kube-system
# (옵션) kubectl auth can-i 로 kubectl 실행 사용자가 특정 권한을 가졌는지 확인
k1 auth can-i get pods
no


- 각각 네임스페이스에 롤(Role)를 생성 후 서비스 어카운트 바인딩
- 롤(Role) : apiGroups 와 resources 로 지정된 리소스에 대해 verbs 권한을 인가
- 실행 가능한 조작(verbs) : *(모두 처리), create(생성), delete(삭제), get(조회), list(목록조회), patch(일부업데이트), update(업데이트), watch(변경감시)
# 각각 네임스페이스내의 모든 권한에 대한 롤 생성
cat <<EOF | kubectl create -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: role-dev-team
namespace: dev-team
rules:
- apiGroups: ["*"]
resources: ["*"]
verbs: ["*"]
EOF
cat <<EOF | kubectl create -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: role-infra-team
namespace: infra-team
rules:
- apiGroups: ["*"]
resources: ["*"]
verbs: ["*"]
EOF
# 롤 확인
kubectl get roles -n dev-team
kubectl get roles -n infra-team
kubectl get roles -n dev-team -o yaml
kubectl describe roles role-dev-team -n dev-team
...
PolicyRule:
Resources Non-Resource URLs Resource Names Verbs
--------- ----------------- -------------- -----
*.* [] [] [*]
# 롤바인딩 생성 : '서비스어카운트 <-> 롤' 간 서로 연동
cat <<EOF | kubectl create -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: roleB-dev-team
namespace: dev-team
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: role-dev-team
subjects:
- kind: ServiceAccount
name: dev-k8s
namespace: dev-team
EOF
cat <<EOF | kubectl create -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: roleB-infra-team
namespace: infra-team
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: role-infra-team
subjects:
- kind: ServiceAccount
name: infra-k8s
namespace: infra-team
EOF
# 롤바인딩 확인
kubectl get rolebindings -n dev-team
kubectl get rolebindings -n infra-team
kubectl get rolebindings -n dev-team -o yaml
kubectl describe rolebindings roleB-dev-team -n dev-team
...
Role:
Kind: Role
Name: role-dev-team
Subjects:
Kind Name Namespace
---- ---- ---------
ServiceAccount dev-k8s dev-team

- 서비스 어카운트를 지정하여 생성한 파드에서 다시 권한 테스트
# 각각 파드로 Shell 접속하여 정보 확인 : 단축 명령어(alias) 사용
alias k1='kubectl exec -it dev-kubectl -n dev-team -- kubectl'
alias k2='kubectl exec -it infra-kubectl -n infra-team -- kubectl'
# 권한 테스트
k1 get pods
k1 run nginx --image nginx:1.20-alpine
k1 get pods
k1 delete pods nginx
k1 get pods -n kube-system
k1 get nodes
k2 get pods
k2 run nginx --image nginx:1.20-alpine
k2 get pods
k2 delete pods nginx
k2 get pods -n kube-system
k2 get nodes
# (옵션) kubectl auth can-i 로 kubectl 실행 사용자가 특정 권한을 가졌는지 확인
k1 auth can-i get pods
yes

- 리소스 삭제 : kubectl delete ns dev-team infra-team

- RBAC 관련 krew 플러그인
# 설치
kubectl krew install access-matrix rbac-tool rbac-view rolesum whoami
# k8s 인증된 주체 확인
kubectl whoami
arn:aws:iam::9112...:user/admin
# Show an RBAC access matrix for server resources
kubectl access-matrix # Review access to cluster-scoped resources
kubectl access-matrix --namespace default # Review access to namespaced resources in 'default'
# RBAC Lookup by subject (user/group/serviceaccount) name
kubectl rbac-tool lookup
kubectl rbac-tool lookup system:masters
SUBJECT | SUBJECT TYPE | SCOPE | NAMESPACE | ROLE
+----------------+--------------+-------------+-----------+---------------+
system:masters | Group | ClusterRole | | cluster-admin
kubectl rbac-tool lookup system:nodes # eks:node-bootstrapper
kubectl rbac-tool lookup system:bootstrappers # eks:node-bootstrapper
kubectl describe ClusterRole eks:node-bootstrapper
# RBAC List Policy Rules For subject (user/group/serviceaccount) name
kubectl rbac-tool policy-rules
kubectl rbac-tool policy-rules -e '^system:.*'
kubectl rbac-tool policy-rules -e '^system:authenticated'
# Generate ClusterRole with all available permissions from the target cluster
kubectl rbac-tool show
# Shows the subject for the current context with which one authenticates with the cluster
kubectl rbac-tool whoami
{Username: "arn:aws:iam::911283...:user/admin", <<-- 과거 "kubernetes-admin"에서 변경됨
UID: "aws-iam-authenticator:911283.:AIDA5ILF2FJI...",
Groups: ["system:authenticated"], <<-- 과거 "system:master"는 안보임
Extra: {accessKeyId: ["AKIA5ILF2FJI....."],
arn: ["arn:aws:iam::9112834...:user/admin"],
canonicalArn: ["arn:aws:iam::9112834...:user/admin"],
principalId: ["AIDA5ILF2FJI...."],
sessionName: [""]}}
# Summarize RBAC roles for subjects : ServiceAccount(default), User, Group
kubectl rolesum -h
kubectl rolesum aws-node -n kube-system
kubectl rolesum -k User system:kube-proxy
kubectl rolesum -k Group system:masters
kubectl rolesum -k Group system:authenticated
Policies:
• [CRB] */system:basic-user ⟶ [CR] */system:basic-user
Resource Name Exclude Verbs G L W C U P D DC
selfsubjectaccessreviews.authorization.k8s.io [*] [-] [-] ✖ ✖ ✖ ✔ ✖ ✖ ✖ ✖
selfsubjectreviews.authentication.k8s.io [*] [-] [-] ✖ ✖ ✖ ✔ ✖ ✖ ✖ ✖
selfsubjectrulesreviews.authorization.k8s.io [*] [-] [-] ✖ ✖ ✖ ✔ ✖ ✖ ✖ ✖
• [CRB] */system:discovery ⟶ [CR] */system:discovery
• [CRB] */system:public-info-viewer ⟶ [CR] */system:public-info-viewer
# [터미널1] A tool to visualize your RBAC permissions
kubectl rbac-view
INFO[0000] Getting K8s client
INFO[0000] serving RBAC View and http://localhost:8800
## 이후 해당 작업용PC 공인 IP:8800 웹 접속 : 최초 접속 후 정보 가져오는데 다시 시간 걸림 (2~3분 정도 후 화면 출력됨)
echo -e "RBAC View Web http://$(curl -s ipinfo.io/ip):8800"


- 데브옵스 신입 사원을 위한 myeks-bastion-2에 설정 해보기
1. [myeks-bastion] testuser 사용자 생성
# testuser 사용자 생성
aws iam create-user --user-name testuser
# 사용자에게 프로그래밍 방식 액세스 권한 부여
aws iam create-access-key --user-name testuser
{
"AccessKey": {
"UserName": "testuser",
"AccessKeyId": "AKIA5ILF2##",
"Status": "Active",
"SecretAccessKey": "TxhhwsU8##",
"CreateDate": "2023-05-23T07:40:09+00:00"
}
}
# testuser 사용자에 정책을 추가
aws iam attach-user-policy --policy-arn arn:aws:iam::aws:policy/AdministratorAccess --user-name testuser
# get-caller-identity 확인
aws sts get-caller-identity --query Arn
"arn:aws:iam::911283464785:user/admin"
kubectl whoami
# EC2 IP 확인 : myeks-bastion-EC2-2 PublicIPAdd 확인
aws ec2 describe-instances --query "Reservations[*].Instances[*].{PublicIPAdd:PublicIpAddress,PrivateIPAdd:PrivateIpAddress,InstanceName:Tags[?Key=='Name']|[0].Value,Status:State.Name}" --filters Name=instance-state-name,Values=running --output table

2.[myeks-bastion-2] testuser 자격증명 설정 및 확인
# get-caller-identity 확인 >> 왜 안될까요?
aws sts get-caller-identity --query Arn
# testuser 자격증명 설정
aws configure
AWS Access Key ID [None]: AKIA5ILF2F...
AWS Secret Access Key [None]: ePpXdhA3cP....
Default region name [None]: ap-northeast-2
# get-caller-identity 확인
aws sts get-caller-identity --query Arn
"arn:aws:iam::911283464785:user/testuser"
# kubectl 시도 >> testuser도 AdministratorAccess 권한을 가지고 있는데, 실패 이유는?
kubectl get node -v6
ls ~/.kube

3. [myeks-bastion] testuser에 system:masters 그룹 부여로 EKS 관리자 수준 권한 설정

4.[myeks-bastion-2] testuser kubeconfig 생성 및 kubectl 사용 확인

5. [myeks-bastion] testuser 의 Group 변경(system:masters → system:authenticated)으로 RBAC 동작 확인


6.[myeks-bastion-2] testuser kubectl 사용 확인

7. [myeks-bastion]에서 testuser IAM 맵핑 삭제

8. [myeks-bastion-2] testuser kubectl 사용 확인

- EC2 Instance Profile(IAM Role)에 맵핑된 k8s rbac 확인 해보기
1.노드 mapRoles 확인 - 링크

2. awscli 파드를 추가하고, 해당 노드(EC2)의 IMDS 정보 확인 : AWS CLI v2 파드 생성 - 링크 공식이미지링크



3.awscli 파드에 kubeconfig (mapRoles) 정보 생성 및 확인

3. EKS IRSA & Pod Identitty
실습1 - 링크

실습2 - Kubernetes Service Accounts : https://jwt.io/



JWT.IO
JSON Web Tokens are an open, industry standard RFC 7519 method for representing claims securely between two parties.
jwt.io
실습3 : This webhook is for mutating pods that will require AWS IAM acces
- iam 서비스 계정 만들기 - Kubernetes 서비스 계정에 바인딩된 AWS IAM 역할

- 신규 파드 생성

- s3는 되고 decribe는 안됨

- api 리소스 확인

- AWS_WEB_IDENTITY_TOKEN_FILE 확인

- 아래와 같이 JWT(JSON Web Token) 확인에 사용되는 공개 키를 포함하는 키 세트를 포함하는 jwks(JSON Web Key set) 필드 확인

-cloudtail 확인

- AWS_WEB_IDENTITY_TOKEN_FILE 토큰 값 변수 및 ROLE ARN 확인 후 변수 직접 지정

- 실습 확인 후 파드 삭제 및 IRSA 제거

5. OWASP Kubernetes Top Ten
- Kubelet 미흡한 인증/인가 설정 시 위험 + kubeletct 툴
# 노드의 kubelet API 인증과 인가 관련 정보 확인
ssh ec2-user@$N1 cat /etc/kubernetes/kubelet/kubelet-config.json | jq
ssh ec2-user@$N1 cat /var/lib/kubelet/kubeconfig | yh
# 노드의 kubelet 사용 포트 확인
ssh ec2-user@$N1 sudo ss -tnlp | grep kubelet
LISTEN 0 4096 127.0.0.1:10248 0.0.0.0:* users:(("kubelet",pid=2940,fd=20))
LISTEN 0 4096 *:10250 *:* users:(("kubelet",pid=2940,fd=21))
# 데모를 위해 awscli 파드 생성
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: myawscli
spec:
#serviceAccountName: my-sa
containers:
- name: my-aws-cli
image: amazon/aws-cli:latest
command: ['sleep', '36000']
restartPolicy: Never
terminationGracePeriodSeconds: 0
EOF
# 파드 사용
kubectl exec -it myawscli -- aws sts get-caller-identity --query Arn
kubectl exec -it myawscli -- aws s3 ls
kubectl exec -it myawscli -- aws ec2 describe-instances --region ap-northeast-2 --output table --no-cli-pager
kubectl exec -it myawscli -- aws ec2 describe-vpcs --region ap-northeast-2 --output table --no-cli-pager



- [myeks-bastion-2] kubeletct 설치 및 사용


- [myeks-bastion] → 노드1 접속 : kubelet-config.json 수정


- [myeks-bastion-2] kubeletct 사용



6. Kyverno

Kyverno는 Kubernetes를 위한 다재다능하고 사용자 친화적인 정책 엔진이 되는 다양한 기능을 제공합니다.
1. Kubernetes 리소스로서의 정책: Kyverno는 Kubernetes 리소스 자체를 활용하므로 새로운 정책별 언어를 배울 필요가 없습니다.
2. 검증, 변형, 생성 또는 정리: 승인 제어 중에 Kubernetes 리소스를 검증, 변형, 생성 또는 정리할 수 있습니다.
3. 컨테이너 이미지 확인: Kyverno는 컨테이너 이미지 메타데이터를 검사하여 소프트웨어 공급망 보안을 지원합니다.
4. 레이블 선택기와 와일드카드를 사용하여 리소스 일치: 레이블과 와일드카드를 사용하여 특정 리소스를 대상으로 하는 정책을 작성할 수 있습니다.
5. 오버레이를 사용한 검증 및 변형: Kyverno는 검증 및 변형을 위해 Kustomize와 유사한 오버레이 스타일 구문을 지원합니다.
6. 네임스페이스 간 구성 동기화: Kyverno를 사용하면 여러 네임스페이스에서 구성을 동기화할 수 있습니다.
7. 비준수 리소스 차단: 허용 제어를 사용하여 비준수 리소스를 차단하거나 정책 위반을 보고할 수 있습니다.
8. 셀프 서비스 보고서 및 정책 예외: Kyverno는 더 나은 가시성과 관리를 위해 셀프 서비스 보고서 및 정책 예외를 제공합니다.
9. 정책 테스트 및 리소스 검증: Kyverno CLI를 사용하면 정책을 클러스터에 적용하기 전에 CI/CD 파이프라인에서 정책을 테스트하고 리소스를 검증할 수 있습니다.
10. 코드로 정책 관리: Git 및 Kustomize와 같은 친숙한 도구를 사용하여 정책을 코드로 관리할 수 있으므로 버전 제어 및 협업이 단순화됩니다.

Kyverno는 Kubernetes 클러스터 내에서 동적 승인 컨트롤러 역할을 합니다. Kubernetes API 서버로부터 승인 웹후크 콜백 검증 및 변경을 수신하고 일치하는 정책을 적용하여 승인 정책을 시행하거나 요청을 거부합니다.
Kyverno 정책은 종류, 이름, 라벨 선택기 등을 기준으로 리소스를 일치시킬 수 있습니다. 변형 정책은 오버레이 또는 RFC 6902 JSON 패치로 작성할 수 있습니다. 정책 검증에서는 패턴 일치 및 조건부 처리를 지원하는 오버레이 스타일 구문을 사용합니다.
정책 시행은 Kubernetes 이벤트를 사용하여 캡처되며 Kyverno는 허용된 리소스에 대한 정책 결정 결과를 표시하기 위해 클러스터에 정책 보고서를 생성합니다.
- 설치

- 확인

- step-cli 설치

- 그라파나 대시보드 : 15987, 15804

- Validation


- Mutation

- team=bravo 가 적용

- 삭제 후, team=bravo 가 적용안됨

- Generation : We will use a Kyverno generate policy to generate an image pull secret in a new Namespace. - Link

-확인

7. 파드/컨테이너 보안 컨텍스트
* 컨테이너 보안 컨텍스트 SecurityContext
- 파드생성
readOnlyRootFilesystem : root 파일 시스템을 읽기 전용으로 사용

- 기존 파일 수정 시도

- 특정 파티션, 파일의 ro/rw 확인

- Linux Capabilities 확인 및 노드 Linux Capabilities 확인


- 파드의 Linux Capabilities 기본 확인

- 샘플 파드 생성2

- 파드에서 시간 변경 시도

- 파드에 Linux Capabilities 부여 및 삭제

8. 실습 완료 후 리소스 삭제
7-1) EKS 클러스터 삭제
eksctl delete cluster --name $CLUSTER_NAME && aws cloudformation delete-stack --stack-name $CLUSTER_NAME
7-2) testuser IAM User는 AWS 웹 관리콘솔에서 삭제
7-3) 삭제 안되는 리소스는 스택에서 삭제
삭제 소요시간은 대략 30분정도 걸리며, 아래와 같이 삭제된 것을 확인가능함.


#스터디 후기
EKS Security 스터디를 통해 EKS 클러스터 보안의 복잡성과 중요성에 깨달았습니다. 특히 IAM 지식, 네트워크 보안 과제, 암호화 지속적인 모니터링, 모범 사례 등이 중요 포인트였습니다. 또한, 취약점과 여러 공격 시나리오, 보안 강화 및 모니터링 방안 등을 체계적으로 이해할 수 있었습니다. 나아가 EKS 클러스터를 효과적으로 보호하기 위해 AWS 서비스에 대한 깊은 이해와 사전 모니터링 및 보안 모범 사례 준수가 필요하다고 생각합니다.
'EKS Study' 카테고리의 다른 글
| 8주차 - EKS IaC (0) | 2024.04.21 |
|---|---|
| 7주차 - EKS CI/CD (0) | 2024.04.14 |
| 5주차 - EKS Autoscaling (0) | 2024.04.07 |
| 4주차 - EKS Observability (1) | 2024.03.24 |
| 3주차 - EKS Storage & Nodegroup (1) | 2024.03.17 |