메타데이터
EC2 메타데이터 탈취하기
# 워커 노드 1대 EC2 메타데이터를 제거한다
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
# 테스트용 파드 생성(netshoot)
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
# 파드1에서 EC2 메타데이터 정보 확인
kubectl exec -it $PODNAME1 -- curl 169.254.169.254/latest ;echo
kubectl exec -it $PODNAME1 -- curl 169.254.169.254/latest/meta-data/iam/security-credentials/ ;echo
kubectl exec -it $PODNAME1 -- curl 169.254.169.254/latest/meta-data/iam/security-credentials/**nodes**.$KOPS_CLUSTER_NAME | jq
# 파드2에서 EC2 메타데이터 정보 확인
kubectl exec -it $PODNAME2 -- curl 169.254.169.254/latest ;echo
kubectl exec -it $PODNAME2 -- curl 169.254.169.254/latest/meta-data/iam/security-credentials/ ;echo
kubectl exec -it $PODNAME2 -- curl 169.254.169.254/latest/meta-data/iam/security-credentials/**nodes**.$KOPS_CLUSTER_NAME | jq

파드에 접속해서 명령어를 날리면 액세스 키를 볼 수 있다!
파드 탈취 후 EC2 메타데이터의 IAM Role 토큰 정보로 AWS 서비스 강제 사용 – boto3
- Boto란? Python용 AWS SDK
# boto3 파드 생성
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
# 파드 이름 변수 지정
PODNAME1=$(kubectl get pod -l app=boto3 -o jsonpath={.items[0].metadata.name})
PODNAME2=$(kubectl get pod -l app=boto3 -o jsonpath={.items[1].metadata.name})
# 파드에 접속(1이나 2 중 선택)
kubectl exec -it $PODNAME1 -- sh
# AWS 리소스에 대한 접근 및 명령 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** # aws ec2 describe-vpcs
# 실습 완료 후 삭제
kubectl delete deploy boto3-pod

- boto3으로 EC2에 접근하여 정보를 탈취할 수 있다
과제1)Boto3으로 다른 실습 진행하기
cat <<EOF> ec22.py
import boto3
ec2 = boto3.client('ec2', region_name='ap-northeast-2')
response = ec2.describe_regions()
print('Regions:', response['Regions'])
EOF

Kubescape
kubescape란?
IDE, CI/CD 파이프라인 및 클러스터를 위한 오픈소스 Kubernetes 보안 플랫폼
- NSA/CISA 에서 발표한 보안 규정 권고 사항 대비 얼마나 보안이 지켜지고 있는지 확인하는 오픈소스 도구
ARMO
kubescrape를 웹에서 간편하게 사용할 수 있는 웹 포탈
# ARMO를 통해 쿠버네티스 클러스터 검사하기
# kubescrape 설치
curl -s <https://raw.githubusercontent.com/kubescape/kubescape/master/install.sh> | /bin/bash
# 웹 포털에서 주어지는 명령어를 입력하면 아래와 같은 내용이 뜬다
>>
helm upgrade --install kubescape kubescape/kubescape-cloud-operator -n kubescape --create-namespace --set account=022f6a1c-8239-4567-b08c-0b510b9d47de --set clusterName=`kubectl config current-context`
Release "kubescape" does not exist. Installing it now.
NAME: kubescape
LAST DEPLOYED: Mon Feb 27 22:43:47 2023
NAMESPACE: kubescape
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
Thank you for installing kubescape-cloud-operator version 1.9.16.
In a few minutes your scan results will be available in the following link:
<https://cloud.armosec.io/compliance/play-board-net>
You can see and change the values of your's recurring configurations daily scan in the following link:
<https://cloud.armosec.io/settings/assets/clusters/scheduled-scans?cluster=play-board-net>
> kubectl -n kubescape get cj kubescape-scheduler -o=jsonpath='{.metadata.name}{"\\t"}{.spec.schedule}{"\\n"}'
You can see and change the values of your's recurring images daily scan in the following link:
<https://cloud.armosec.io/settings/assets/images>
> kubectl -n kubescape get cj kubevuln-scheduler -o=jsonpath='{.metadata.name}{"\\t"}{.spec.schedule}{"\\n"}'
See you!!!
과제2) ARMO 실습


Polaris
Polaris란?
Kubernetes 클러스터의 자동 감사를 수행하는 오픈 소스 도구
# 폴라리스 설치를 위한 네임스페이스 생성
kubectl create ns polaris
#
cat <<EOT > polaris-values.yaml
dashboard:
replicas: 1
service:
type: LoadBalancer
EOT
# 배포
helm repo add fairwinds-stable <https://charts.fairwinds.com/stable>
helm install polaris fairwinds-stable/polaris --namespace polaris --version 5.7.2 -f polaris-values.yaml
# CLB에 ExternanDNS 로 도메인 연결
kubectl annotate service polaris-dashboard "external-dns.alpha.kubernetes.io/hostname=polaris.$KOPS_CLUSTER_NAME" -n polaris
# 아래 주소로 접속
<http://polaris.play-board.net>
과제3) 폴라리스 실습


앞서 만든 netshoot-pod의 테스트 결과를 참조하여 보안 문제를 수정한다
# 기존 netshoot-pod 삭제
kubectl delete deploy 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:v0.9 # 이미지 버전 확인
command: ["tail"]
args: ["-f", "/dev/null"]
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
#

- netshoot-pod에 대한 주요 보안 이슈가 대부분 해결된 것을 확인할 수 있다.
Kubernetes의 인증 및 인가

https://happycloud-lee.tistory.com/259
인증(Authentication)
- CA crt(발급 기관 인증서), Client crt(클라이언트 인증서), Client key(클라이언트 개인키) 를 통해 사용자가 맞는지 인증을 진행한다
인가(Authorization)
- 인증이 성공하면, 해당 사용자가 특정 명령을 수행할 수 있는 권한이 있는지를 확인한다
실습

각각 다른 권한을 가진 SA를 생성한 뒤 권한을 테스트한다
# 네임스페이스 생성 및 서비스 어카운트 생성
kubectl create namespace dev-team
kubectl create ns infra-team
kubectl create sa dev-k8s -n dev-team
kubectl create sa infra-k8s -n infra-team
# 각각 네임스피이스에 kubectl 파드 생성
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.24.10
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.24.10
command: ["tail"]
args: ["-f", "/dev/null"]
terminationGracePeriodSeconds: 0
EOF
# 각각 파드로 접근하여 명령어가 먹히는지 확인한다
kubectl exec -it dev-kubectl -n dev-team -- kubectl get pods
>>
Error from server (Forbidden): pods is forbidden: User "system:serviceaccount:dev-team:dev-k8s" cannot list resource "pods" in API group "" in the namespace "dev-team"
command terminated with exit code 1
# 권한이 없어서 pod 목록을 가져올 수 없다

# 모든 권한에 대한 롤 생성
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
# 롤바인딩 생성
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 exec -it dev-kubectl -n dev-team -- kubectl get pods
>>
NAME READY STATUS RESTARTS AGE
dev-kubectl 1/1 Running 0 9m52s
#정상적으로 파드 리스트가 츨력되는 것을 확인한다

과제4) 읽기 전용 권한 생성
# 네임스페이스 생성
kubectl create ns read-only
# 서비스 어카운트 생성
kubectl create sa readonly -n read-only
# 파드 생성
cat <<EOF | kubectl create -f -
apiVersion: v1
kind: Pod
metadata:
name: readonly-pod
namespace: default
spec:
serviceAccountName: readonly
containers:
- name: kubectl-pod
image: bitnami/kubectl:1.24.10
command: ["tail"]
args: ["-f", "/dev/null"]
terminationGracePeriodSeconds: 0
EOF
# 롤 생성
cat <<EOF | kubectl create -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: readonly-role
namespace: default
rules:
- apiGroups: ["*"]
resources: ["*"]
verbs: ["get","watch","list"]
EOF
# 롤바인딩 생성
cat <<EOF | kubectl create -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: readonly-role-binding
namespace: default
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: readonly-role
subjects:
- kind: ServiceAccount
name: readonly
EOF

댓글을 달려면 로그인해야 합니다.