EKS 8탄 - 6주차
본 내용은 CloudNet 주말 스터디 내용을 참고로 작성되었습니다.
https://gasidaseo.notion.site/gasidaseo/CloudNet-Blog-c9dfa44a27ff431dafdd2edacc8a1863
계속 테스트하며 내용과 설명이 업데이트됩니다.
EKS 인증과 인가를 누가 하는지 알아보자.
실습을 통해 이해하자 - 새로운 개발자가 EKS사용하도록 제공하는 법
이론 1시간
실습 1시간
이론부터 1시간 설명후 바로 실습 진행합니다.
미리 노드를 설치해 두자
k get nodes해 확인해 두자.
1
준비
ec2 keypair
access-key/secret-key
(15분 걸림)
현재 20분이면
35분 완료
https://vclock.kr/timer/#countdown=00:02:00&enabled=0&seconds=0&sound=xylophone&loop=1
2
bastion-ec2 에 로그온해서 master, node 서버들이 만들어지는지 모니터링 하자.
# EC2 인스턴스 모니터링
while true; do aws ec2 describe-instances --query "Reservations[*].Instances[*].{PublicIPAdd:PublicIpAddress,InstanceName:Tags[?Key=='Name']|[0].Value,Status:State.Name}" --output text | sort; echo "------------------------------" ;date; sleep 3; done
(노드 서버 생성 2분후 노드로 kubectl 명령어로 조회가 가능하다.)
while true ; do kubectl get nodes ;echo "-----------";date; sleep 2 ;done
콘솔에서 생성 확인
ec2 생성확인
노드 서버 생성 3분후에 노드로 kubectl 명령어로 조회가 가능하다.
3
(선택) CLI로 구축하기
# 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
4
CloudFormation 내용은?
bastion ec2 2대를 만든다.
1대는 관리자용
1대는 신규 입사자용
6
기본설정
# default 네임스페이스 적용
kubectl ns default
7
# ExternalDNS
MyDomain=<자신의 도메인>
echo "export MyDomain=<자신의 도메인>" >> /etc/profile
MyDomain=masterseo1.link
echo "export MyDomain=masterseo1.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 -
8
# 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
9
# 노드 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.0/24
# 워커 노드 SSH 접속
for node in $N1 $N2 $N3; do ssh ec2-user@$node hostname; done
ssh ec2-user@$node $N1
ssh ec2-user@$node $N2
ssh ec2-user@$node $N3
// 여기서는 사용하지 않는다. 설치 안해도 된다.
admin / prom-operator
1
대시보드 추천 15757 17900 15172
2
보안관련해 모니터링 시 사용 - 이번 실습에는 사용하지 않음.
# 사용 리전의 인증서 ARN 확인
CERT_ARN=`aws acm list-certificates --query 'CertificateSummaryList[].CertificateArn[]' --output text`
echo $CERT_ARN
3
# repo 추가
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
4
# 파라미터 파일 생성
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
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'
defaultRules:
create: false
kubeControllerManager:
enabled: false
kubeEtcd:
enabled: false
kubeScheduler:
enabled: false
alertmanager:
enabled: false
EOT
# 배포
kubectl create ns monitoring
helm install kube-prometheus-stack prometheus-community/kube-prometheus-stack --version 45.27.2 --set prometheus.prometheusSpec.scrapeInterval='15s' --set prometheus.prometheusSpec.evaluationInterval='15s' -f monitor-values.yaml --namespace monitoring
5
# Metrics-server 배포
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
6
k get ingress -A
(admin@myeks:default) [root@myeks-bastion ~]# k get ingress -A
NAMESPACE NAME CLASS HOSTS ADDRESS PORTS AGE
monitoring kube-prometheus-stack-grafana alb grafana.masterseo1.link myeks-ingress-alb-879031103.ap-northeast-2.elb.amazonaws.com 80 15m
monitoring kube-prometheus-stack-prometheus alb prometheus.masterseo1.link myeks-ingress-alb-879031103.ap-northeast-2.elb.amazonaws.com 80 15m
7
https://grafana.masterseo1.link/dashboards
1
.kube/config 내용
clusters : kubectl 이 사용할 쿠버네티스 API 서버의 접속 정보 목록. 원격의 쿠버네티스 API 서버의 주소를 추가해 사용 가능
users : 쿠버네티스의 API 서버에 접속하기 위한 사용자 인증 정보 목록. (서비스 어카운트의 토큰, 혹은 인증서의 데이터 등)
contexts : cluster 항목과 users 항목에 정의된 값을 조합해 최종적으로 사용할 쿠버네티스 클러스터의 정보(콘텍스트)를 설정.
예를 들어 clusters 항목에 클러스터 A, B 가 정의돼 있고, users 항목에 사용자 a, b 가 정의돼 있다면 cluster A + user a를 조합해, 'cluster A에 user a로 인증해 쿠버네티스를 사용한다'라는 새로운 콘텍스트를 정의할 수 있습니다.
kubectl을 사용하려면 여러 개의 콘텍스트 중 하나를 선택.
인증 관련 내용이 들어가 있다.
cat .kube/config
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: LS0tLS1CRUtLS0tCg==
server: https://192.168.100.10:6443
name: kubernetes
contexts:
- context:
cluster: kubernetes
namespace: default
user: kubernetes-admin
name: admin@k8s
current-context: admin@k8s
kind: Config
preferences: {}
users:
- name: kubernetes-admin
user:
client-certificate-data:
Ka1gvQnZmaXc9PQ0FURS0tLS0tCg==
client-key-data: LS0tLS1CRUdJTiBSQkFBS0NBUUVBbnZ5=
2
기본은 알아야 한다.
롤, 롤바인딩등 이해하자.
https://brunch.co.kr/@topasvga/1877
https://brunch.co.kr/@topasvga/1878
1
사용자/애플리케이션 -> k8s 사용 시 ?
인증은 AWS IAM 사용 (쿠버네티스것은 사용하지 않음)
인가는 K8S RBAC 사용한다.
// RBAC(Role-Based Access Control)란?
RBAC는 역할에 따라 해당 역할이 할수 있는 권한을 제공하는것이다.
2
krew로 rbac관련 툴 설치하자.
# 설치
kubectl krew install access-matrix rbac-tool rbac-view rolesum
# 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
# system:masters에 대해 알아보기
정보를 볼수 있는 명령어.
cluster-admin role을 볼수 있다고 나온다.
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:.*'
# 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: "kubernetes-admin",
UID: "aws-iam-authenticator:911283.....:AIDA5ILF2FJ......",
Groups: ["system:masters",
"system:authenticated"],
Extra: {accessKeyId: ["AKIA5ILF2FJ....."],
arn: ["arn:aws:iam::911283....:user/admin"],
canonicalArn: ["arn:aws:iam::911283....:user/admin"],
principalId: ["AIDA5ILF2FJ....."],
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
(admin@myeks:default) [root@myeks-bastion ~]# kubectl rolesum -k Group system:masters
--------------------------------------------------
Group: system:masters
Policies:
• [CRB] */cluster-admin ⟶ [CR] */cluster-admin
Resource Name Exclude Verbs G L W C U P D DC
*.* [*] [-] [-] ✔ ✔ ✔ ✔ ✔ ✔ ✔ ✔
# [터미널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 웹 접속
echo -e "RBAC View Web http://$(curl -s ipinfo.io/ip):8800"
RBAC View Web http://43.201.29.88:8800
https://youtu.be/bksogA-WXv8?t=669
https://youtu.be/bksogA-WXv8?t=669
순서 ?
1
kubectl 명령을 내리면 ?
k get nodes
2
사용자가 EKS클러스터에 접근해 놓은 설정
즉, 사용자의 Kubeconfig설정 정보에 정의된 AWS Get-Tocken명령을 통해 AWS EKS Endpoint로 요청을 하게 된다.
응답으로 토큰 값이 전달 된다.
EKS get-tocken = EKS Service endpoint(STS)에 토큰 요청 한다.
3
Pre-Signed URL 을 Bearer Tocken으로 컨트롤 플레인 API Server에 날린다.
Bearer Tocken = 인증 타입으로 JWT 혹은 OAuth에 대한 토큰을 사용한다. (RFC 6750)
basic인증 타입은 사용자 아이디와 암호를 base64 인코딩한 값을 토큰으로 사용한다.
4
API를 통해 Token Review 를 통해 Webhook 으로 전달 되고, AWS IAM 인증으로 처리한다.
aws-iam-authenticator server
EKS에서 '사용자 인증을 통합'하기위해 IAM인증으로 처리한다.
sts GetCallerIdentity 요청 한다. 응답은 허락 한다.
IAM은 인증만 있다.
5
인가는 쿠버네티스의 RBAC에서 처리해야 한다.
IAM user나 Role을 쿠버네티스의 User나 Group으로 매핑하는 Config MAP인
'AWS Auth Config'에서 처리한다.
그룹을 봐서 처리한다.
6
IAM role과 매핑된 IAM-admin이라는 username과 System:master라고 하는 그룹을 리턴한다.
K8S RBAC으로 인가를 처리한다.
Authorization (인가)
1
kubectl 명령 → aws eks get-token -> EKS Service endpoint(STS)에 토큰 요청
2
AWS CLI 버전 1.16.156 이상에서는 별도 aws-iam-authenticator 설치 없이 aws eks get-token으로 사용 가능
https://docs.aws.amazon.com/eks/latest/userguide/install-aws-iam-authenticator.html
3
# sts caller id의 ARN 확인
aws sts get-caller-identity --query Arn
"arn:aws:iam::<자신의 Account ID>:user/admin"
4
# kubeconfig 정보 확인
cat ~/.kube/config | yh
...
- name: admin@myeks.ap-northeast-2.eksctl.io
user:
exec:
apiVersion: client.authentication.k8s.io/v1beta1
args:
- eks
- get-token
- --output
- json
- --cluster-name
- myeks
- --region
- ap-northeast-2
command: aws
env:
- name: AWS_STS_REGIONAL_ENDPOINTS
value: regional
interactiveMode: IfAvailable
provideClusterInfo: false
# Get a token for authentication with an Amazon EKS cluster. 토큰을 요청한다.
# This can be used as an alternative to the aws-iam-authenticator. 예전 버전 사용시 방법.
aws eks get-token help
5
STS (Security Token Service) 토근을 받아온다!!
임시 보관이다.
장기 보관이 아니다.
cloudtail에 로그가 남는다.
# 임시 보안 자격 증명(토큰)을 요청 : expirationTimestamp 시간경과 시 토큰 재발급됨
aws eks get-token --cluster-name $CLUSTER_NAME | jq
aws eks get-token --cluster-name $CLUSTER_NAME | jq -r '.status.token'
6
토큰 내용을 확인 가능하다.
pre-signed URL이라고 하는데 디버그 사이트에서 내용 확인 가능하다.
토큰을 넣어서 payload 부분 확인하자.
5
payload 부분을 디코드하면 ?
내용 ?
action = GetcallerIdentity 등이 있다.
6
EKS API에게 전달 한다.
사용자에 대한 인증처리를 webhook 으로 요청한다.
kubectl api-resources | grep authentication
Token Reviews ?
사용자에 대한 인증을 처리할수 있다.
Webhook token authenticator 은 aws-iam-authenticator 를 사용 한다.
Cloudtrail 가면 GetCallerIdentity 사용 확인 가능.
7
AWS STS 가 AWS IAM 서비스 이다.
사용자 유저가 맞는지 문의한다.
맞다고 응답을 한다.
인증 완료.
User/role에 대한 ARN반환을 한다.
8
이제 인가 처리를 해야 한다.
aws-auth컨피그맵에서 IAM사용자, 역할ARN, K8S오브젝트 권한 확인한후 K8S 인가 허가를 하면 동작한다.
# Webhook api 리소스 확인
kubectl api-resources | grep Webhook
mutatingwebhookconfigurations admissionregistration.k8s.io/v1 false MutatingWebhookConfiguration
validatingwebhookconfigurations admissionregistration.k8s.io/v1 false ValidatingWebhookConfiguration
// validatingwebhookconfigurations 에서 통과를 한다.
9
# validatingwebhookconfigurations 리소스 확인
kubectl get validatingwebhookconfigurations
NAME WEBHOOKS AGE
eks-aws-auth-configmap-validation-webhook 1 50m
vpc-resource-validating-webhook 2 50m
aws-load-balancer-webhook 3 8m27s
// eks-aws-auth-configmap-validation-webhook 이 있다.
10
// aws-auth-configmap 안에 내용이
kubectl get validatingwebhookconfigurations eks-aws-auth-configmap-validation-webhook -o yaml | kubectl neat | yh
# aws-auth 컨피그맵 확인
kubectl get cm -n kube-system aws-auth -o yaml | kubectl neat | yh
apiVersion: v1
kind: ConfigMap
metadata:
name: aws-auth
namespace: kube-system
data:
mapRoles: |
- groups:
- system:bootstrappers
- system:nodes
rolearn: arn:aws:iam::91128.....:role/eksctl-myeks-nodegroup-ng1-NodeInstanceRole-1OS1WSTV0YB9X
username: system:node:{{EC2PrivateDNSName}}
11
# 아래 생략(추정), ARN은 EKS를 설치한 IAM User
만약 있을경우 실수로 삭제 시 복구 불가능하여 생략 됨.
mapUsers: |
- groups:
- system:masters
userarn: arn:aws:iam::111122223333:user/admin
username: kubernetes-admin
12
# EKS 설치한 IAM User 정보 >> system:authenticated는 어떤 방식으로 추가가 되었는지 궁금???
kubectl rbac-tool whoami
그룹의 권한을 확인한다!!
{Username: "kubernetes-admin",
UID: "aws-iam-authenticator:9112834...:AIDA5ILF2FJIR2.....",
Groups: ["system:masters",
"system:authenticated"],
...
13
# system:masters , system:authenticated 그룹의 정보 확인
kubectl rbac-tool lookup system:masters
kubectl rbac-tool lookup system:authenticated
kubectl rolesum -k Group system:masters
kubectl rolesum -k Group system:authenticated
14
# system:masters 그룹이 사용 가능한 클러스터 롤 확인 : cluster-admin
kubectl describe clusterrolebindings.rbac.authorization.k8s.io cluster-admin
Name: cluster-admin
Labels: kubernetes.io/bootstrapping=rbac-defaults
Annotations: rbac.authorization.kubernetes.io/autoupdate: true
Role:
Kind: ClusterRole
Name: cluster-admin
Subjects:
Kind Name Namespace
---- ---- ---------
Group system:masters
15
# cluster-admin 의 PolicyRule 확인 : 모든 리소스 사용 가능!
kubectl describe clusterrole cluster-admin
Name: cluster-admin
Labels: kubernetes.io/bootstrapping=rbac-defaults
Annotations: rbac.authorization.kubernetes.io/autoupdate: true
PolicyRule:
Resources Non-Resource URLs Resource Names Verbs
--------- ----------------- -------------- -----
*.* [] [] [*]
[*] [] [*]
16
# system:authenticated 그룹이 사용 가능한 클러스터 롤 확인
kubectl describe ClusterRole system:discovery
kubectl describe ClusterRole system:public-info-viewer
kubectl describe ClusterRole system:basic-user
kubectl describe ClusterRole eks:podsecuritypolicy:privileged
1
testuser 사용자 생성
aws iam create-user --user-name testuser
2
# 사용자에게 프로그래밍 방식 액세스 권한 부여
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"
}
}
// accesskey 와 secret key를 메모 한다.
3
# testuser 사용자에 정책을 추가 - admin 권한 추가한다.
aws iam attach-user-policy --policy-arn arn:aws:iam::aws:policy/AdministratorAccess --user-name testuser
4
확인
# get-caller-identity 확인
aws sts get-caller-identity --query Arn
"arn:aws:iam::476286675138:user/admin"
5
# 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
----------------------------------------------------------------------
| DescribeInstances |
+---------------------+-----------------+-----------------+----------+
| InstanceName | PrivateIPAdd | PublicIPAdd | Status |
+---------------------+-----------------+-----------------+----------+
| myeks-ng1-Node | 192.168.3.249 | 52.79.228.63 | running |
| myeks-ng1-Node | 192.168.2.164 | 15.164.240.22 | running |
| myeks-bastion-EC2 | 192.168.1.100 | 43.201.29.88 | running |
| myeks-bastion-EC2-2| 192.168.1.200 | 43.201.147.2 | running |
| myeks-ng1-Node | 192.168.1.121 | 3.36.73.51 | running |
+---------------------+-----------------+-----------------+----------+
6
2번 서버에 로그온 하자 ~
testuser 자격증명 설정 및 확인
# get-caller-identity 확인 >> 왜 안될까요?
aws sts get-caller-identity --query Arn
7
# 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::476286675138:user/testuser"
8
# kubectl 시도 >> testuser도 AdministratorAccess 권한을 가지고 있는데, 실패 이유는?
kubectl get node -v6
ls ~/.kube
인증 정보가 없다.
4
test user를 그룹으로 매핑해야 한다!!!
클러스터 롤을 사용할수 있도록 하는 것이다.
5
1번 EC2에서 권한을 추가해준다.
testuser에 system:masters 그룹 부여로 EKS 관리자 수준 권한 설정
# 방안1 : eksctl 사용 >> iamidentitymapping 실행 시 aws-auth 컨피그맵 작성해줌
# Creates a mapping from IAM role or user to Kubernetes user and groups.
# 그룹을 매핑한다. aws-auth 설정을 해야 한다.
eksctl create iamidentitymapping --cluster $CLUSTER_NAME --username testuser --group system:masters --arn arn:aws:iam::$ACCOUNT_ID:user/testuser
// testuser를 쿠버네티스의 group system:masters 와 매핑하라~ arn은 위와 같다.
6
잘 설정 되었는지 configmap 확인해보자~
여기에 설정된 role을 사용할수 있다.
kubectl get cm -n kube-system aws-auth -o yaml | kubectl neat | yh
admin@myeks:default) [root@myeks-bastion ~]# kubectl get cm -n kube-system aws-auth -o yaml | kubectl neat | yh
apiVersion: v1
data:
mapRoles: |
- groups:
- system:bootstrappers
- system:nodes
rolearn: arn:aws:iam::476286675138:role/eksctl-myeks-nodegroup-ng1-NodeInstanceRole-1GEQ51CT063N2
username: system:node:{{EC2PrivateDNSName}}
mapUsers: |
- groups:
- system:masters
userarn: arn:aws:iam::476286675138:user/testuser
username: testuser
kind: ConfigMap
metadata:
name: aws-auth
namespace: kube-system
(선택)
# 방안2 : 아래 edit로 mapUsers 내용 직접 추가!
kubectl edit cm -n kube-system aws-auth
---
apiVersion: v1
data:
mapRoles: |
- groups:
- system:bootstrappers
- system:nodes
rolearn: arn:aws:iam::911283464785:role/eksctl-myeks-nodegroup-ng1-NodeInstanceRole-LHQ7DWHQQRZJ
username: system:node:{{EC2PrivateDNSName}}
mapUsers: |
- groups:
- system:masters
userarn: arn:aws:iam::911283464785:user/testuser
username: testuser
...
# 확인 : 기존에 있는 role/eksctl-myeks-nodegroup-ng1-NodeInstanceRole-YYYYY 는 어떤 역할/동작을 하는 걸까요?
eksctl get iamidentitymapping --cluster $CLUSTER_NAME
ARN USERNAME GROUPS ACCOUNT
arn:aws:iam::911283464785:role/eksctl-myeks-nodegroup-ng1-NodeInstanceRole-LHQ7DWHQQRZJ system:node:{{EC2PrivateDNSName}} system:bootstrappers,system:nodes
arn:aws:iam::911283464785:user/testuser testuser system:masters
7
2번 서버에서 업데이트 해서 파일을 만든다.
testuser가 사용해야 하는 파일이다.
testuser kubeconfig 생성 및 kubectl 사용 확인
# testuser kubeconfig 생성 >> aws eks update-kubeconfig 실행이 가능한 이유는?
설정 후 약간의 적용 시간 필요
aws eks update-kubeconfig --name $CLUSTER_NAME --user-alias testuser
-------------------------------------------
Added new context testuser to /home/ec2-user/.kube/config
// 혹 아래와 같은 에러가 뜨면 aws configure가 제대로 안된것이다.
설정 파일을 지우고 다시 설정하자.
에러 내용
Unable to parse config file: /root/.aws/credentials
rm -rf /root/.aws/credentials
aws configure
6
# 첫번째 bastic ec2의 config와 비교해보자
cat ~/.kube/config | yh
- context:
cluster: arn:aws:eks:ap-northeast-2:476286675138:cluster/myeks
user: testuser
name: testuser
current-context: testuser
kind: Config
preferences: {}
users:
- name: testuser
user:
exec:
apiVersion: client.authentication.k8s.io/v1beta1
args:
- --region
- ap-northeast-2
- eks
- get-token
- --cluster-name
- myeks
- --output
- json
command: aws
7
에서 신규 개발자가 확인
# kubectl 사용 확인
kubectl ns default
kubectl get node -v6
--------------------------------------------------------------------------
NAME STATUS ROLES AGE VERSION
ip-192-168-1-121.ap-northeast-2.compute.internal Ready <none> 131m v1.24.13-eks-0a21954
ip-192-168-2-164.ap-northeast-2.compute.internal Ready <none> 131m v1.24.13-eks-0a21954
ip-192-168-3-249.ap-northeast-2.compute.internal Ready <none> 131m v1.24.13-eks-0a21954
잘 된다.
8
(기타)
# rbac-tool 후 확인?
>> 기존 계정과 비교해보자 >> system:authenticated 는 system:masters 설정 시 따라온다.
kubectl krew install rbac-tool && kubectl rbac-tool whoami
{Username: "testuser",
UID: "aws-iam-authenticator:911283464785:AIDA5ILF2FJIV65KG6RBM",
Groups: ["system:masters",
"system:authenticated"],
Extra: {accessKeyId: ["AKIA5ILF2FJIZJUZSG4D"],
arn: ["arn:aws:iam::911283464785:user/testuser"],
canonicalArn: ["arn:aws:iam::911283464785:user/testuser"],
...
9
(선택)
권한 조정해 테스트해볼까?
[myeks-bastion]
testuser 의 Group 변경(system:masters → system:authenticated)으로 RBAC 동작 확인
10
(선택)
# 방안2 : 아래 edit로 mapUsers 내용 직접 수정 system:authenticated
kubectl edit cm -n kube-system aws-auth
...
# 확인
eksctl get iamidentitymapping --cluster $CLUSTER_NAME
// system:authenticated 로 변경됨.
[myeks-bastion-2] testuser kubectl 사용 확인
# 시도
kubectl get node -v6
안됨.
api 리소스를 볼수 있는 권한은 있다.
kubectl api-resources -v5
이건 됨.
// IAM의 인증은 처리 되었지만, RBAC에서 차단된것이다.
11
퇴사 했을 경우 ?
# testuser IAM 맵핑 삭제
eksctl delete iamidentitymapping --cluster $CLUSTER_NAME --arn arn:aws:iam::$ACCOUNT_ID:user/testuser
# Get IAM identity mapping(s)
eksctl get iamidentitymapping --cluster $CLUSTER_NAME
kubectl get cm -n kube-system aws-auth -o yaml | yh
EKS 설치하는 사용자는 기본으로 권한이 들어간다.
auth 설정에서는 보안상
12
testuser kubectl 사용 확인
# 시도
kubectl get node -v6
kubectl api-resources -v5
둘다 안됨.
13
config 샘플
https://docs.aws.amazon.com/eks/latest/userguide/add-user-role.html
노드가 사용하는 EC2 인스턴스 프로파일이 매핑되어져 있어 되는 것이다.
1
# 노드에 호스트이름 확인
for node in $N1 $N2 $N3; do ssh ec2-user@$node hostname; done
2
# 노드에 STS ARN 정보 확인 : Role 뒤에 인스턴스 ID!
노드에서 자격 증명이 된다 !!!
왜?
노드가 사용하는 EC2 인스턴스 프로파일이 매핑되어져 있어 되는 것이다.
for node in $N1 $N2 $N3; do ssh ec2-user@$node aws sts get-caller-identity --query Arn; done
"arn:aws:sts::911283464785:assumed-role/eksctl-myeks-nodegroup-ng1-NodeInstanceRole-LHQ7DWHQQRZJ/i-07c9162ed08d23e6f"
"arn:aws:sts::911283464785:assumed-role/eksctl-myeks-nodegroup-ng1-NodeInstanceRole-LHQ7DWHQQRZJ/i-00d9d24c0af0d6815"
"arn:aws:sts::911283464785:assumed-role/eksctl-myeks-nodegroup-ng1-NodeInstanceRole-LHQ7DWHQQRZJ/i-031e672f89572abe8"
3
# aws-auth 컨피그맵 확인 >> system:nodes 와 system:bootstrappers 의 권한은 어떤게 있는지 찾아보세요!
# username 확인! 인스턴스 ID? EC2PrivateDNSName?
kubectl describe configmap -n kube-system aws-auth
...
mapRoles:
----
- groups:
- system:nodes
- system:bootstrappers
rolearn: arn:aws:iam::911283464785:role/eksctl-myeks-nodegroup-ng-f6c38e4-NodeInstanceRole-1OU85W3LXHPB2
username: system:node:{{EC2PrivateDNSName}}
...
# Get IAM identity mapping(s)
eksctl get iamidentitymapping --cluster $CLUSTER_NAME
ARN USERNAME GROUPS ACCOUNT
arn:aws:iam::911283464785:role/eksctl-myeks-nodegroup-ng1-NodeInstanceRole-1OS1WSTV0YB9X system:node:{{EC2PrivateDNSName}} system:bootstrappers,system:nodes
...
AWS자격 증명을 가진 사용자가, 쿠버네티스 리소스를 사용할떄 사용하는 것이다.
4
별도의 자격 증명 없이도 노드에서 사용 가능하다.
iamidentitymapping ?
AWS 자격증명을 가진 사용자가 쿠버네티스의 리소스를 쓸때 매핑되는 것이다.
파드에서도 된다 !
노드에 권한이 부여 되어 있어서 가능한것이다.
https://docs.aws.amazon.com/ko_kr/cli/latest/userguide/getting-started-docker.html
https://hub.docker.com/r/amazon/aws-cli
1
pod 2개 생성
pod에서 자격증명 안했는데 되는 이유?
2
# awscli 파드 생성
cat <<EOF | kubectl create -f -
apiVersion: apps/v1
kind: Deployment
metadata:
name: awscli-pod
spec:
replicas: 2
selector:
matchLabels:
app: awscli-pod
template:
metadata:
labels:
app: awscli-pod
spec:
containers:
- name: awscli-pod
image: amazon/aws-cli
command: ["tail"]
args: ["-f", "/dev/null"]
terminationGracePeriodSeconds: 0
EOF
# 파드 생성 확인
kubectl get pod -owide
3
# 파드 이름 변수 지정
APODNAME1=$(kubectl get pod -l app=awscli-pod -o jsonpath={.items[0].metadata.name})
APODNAME2=$(kubectl get pod -l app=awscli-pod -o jsonpath={.items[1].metadata.name})
echo $APODNAME1, $APODNAME2
4
# awscli 파드에서 EC2 InstanceProfile(IAM Role)의 ARN 정보 확인
kubectl exec -it $APODNAME1 -- aws sts get-caller-identity --query Arn
kubectl exec -it $APODNAME2 -- aws sts get-caller-identity --query Arn
5
# awscli 파드에서 EC2 InstanceProfile(IAM Role)을 사용하여 AWS 서비스 정보 확인 ???
>>
별도 IAM 자격 증명이 없는데 어떻게 가능한 것일까요?
노드에 권한이 부여 되어 있어서 가능한것이다.
# > 최소권한부여 필요!!! >>> 보안이 허술한 아무 컨테이너나 탈취 시, IMDS로 해당 노드의 IAM Role 사용 가능!
pod에서 된다.
pod에 자격증명을 안했는데 된다.
kubectl exec -it $APODNAME1 -- aws ec2 describe-instances --region ap-northeast-2 --output table --no-cli-pager
kubectl exec -it $APODNAME2 -- aws ec2 describe-vpcs --region ap-northeast-2 --output table --no-cli-pager
6
# EC2 메타데이터 확인 : IDMSv1은 Disable, IDMSv2 활성화 상태, IAM Role - 링크
kubectl exec -it $APODNAME1 -- bash
7
-----------------------------------
아래부터는 파드에 bash shell 에서 실행
curl -s http://169.254.169.254/ -v
...
8
# Token 요청
curl -s -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600" ; echo
curl -s -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600" ; echo
# Token을 이용한 IMDSv2 사용
TOKEN=$(curl -s -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600")
echo $TOKEN
curl -s -H "X-aws-ec2-metadata-token: $TOKEN" –v http://169.254.169.254/ ; echo
curl -s -H "X-aws-ec2-metadata-token: $TOKEN" –v http://169.254.169.254/latest/ ; echo
curl -s -H "X-aws-ec2-metadata-token: $TOKEN" –v http://169.254.169.254/latest/meta-data/iam/security-credentials/ ; echo
9
# 위에서 출력된 IAM Role을 아래 입력 후 확인
curl -s -H "X-aws-ec2-metadata-token: $TOKEN" –v http://169.254.169.254/latest/meta-data/iam/security-credentials/eksctl-myeks-nodegroup-ng1-NodeInstanceRole-1DC6Y2GRDAJHK
{
"Code" : "Success",
"LastUpdated" : "2023-05-27T05:08:07Z",
"Type" : "AWS-HMAC",
"AccessKeyId" : "ASIA52IYJHP",
"SecretAccessKey" : "rkeeMrjCpiB4h+9XJ",
"Token" : "IQoJb3JB2AOL4iA3TTuK+U2o+pHWEHRQOVh3p4=",
"Expiration" : "2023-05-27T11:09:07Z"
}
## 출력된 정보는 AWS API를 사용할 수 있는 어느곳에서든지 Expiration 되기전까지 사용 가능
10
해당 정책(권한)을 사용하게 된다!!
보안에 주의.
access , secret가 노출 됨.
POD가 노드에 있는 역할을 다 쓸수 있다.
11
# 파드에서 나오기
exit
12
콘솔에서 확인
노드에 있는 역할울 파드에서 사용할수 있게 된다.
IMDS 취약점은 노드의 정책 권한을 파드도 다 사용할수 있게 되어 취약해진다.
1
사용자/애플리케이션 에서 k8s 사용 시
인증은 AWS IAM 사용 (쿠버네티스것 사용하지 않음)
인가는 K8S RBAC 사용
2
IMDS 취약점은 노드의 정책 권한을 파드도 다 사용할수 있게 되어 취약해진다.
다음 보기
https://brunch.co.kr/@topasvga/3302
전체 보기
https://brunch.co.kr/@topasvga/3217
감사합니다.