brunch

You can make anything
by writing

C.S.Lewis

by Master Seo May 30. 2023

EKS 8탄-12. EKS 보안1-인증, 인가

EKS 8탄 - 6주차

본 내용은 CloudNet 주말 스터디 내용을 참고로 작성되었습니다.

https://gasidaseo.notion.site/gasidaseo/CloudNet-Blog-c9dfa44a27ff431dafdd2edacc8a1863  

계속 테스트하며  내용과 설명이 업데이트됩니다.



목표

EKS  인증과 인가를 누가 하는지 알아보자.

실습을 통해 이해하자 - 새로운 개발자가 EKS사용하도록 제공하는 법




이론 1시간

실습 1시간

이론부터 1시간 설명후 바로 실습 진행합니다.


미리 노드를 설치해 두자

k get nodes해 확인해 두자.






<1> EKS 생성과 ExternalDNS,AWS LB Controller 설치(필수)

<2> 프로메테우스 & 그라파나 설치(선택)

<3> EKS 인증/인가 기본 지식

<4> EKS 인증/인가

<5> Amazon EKS 인증 인가 순서

<6> kubectl 명령 → aws eks get-token  과정 보기 (선택)

<7> 예제 - 새로 입사한 개발자가 사용하도록 제공하자

<8> 노드에 매핑될 롤 확인과 의미

<9> 샘플 테스트

<10> 개인 정리 





<1> EKS 생성과 ExternalDNS,AWS LB Controller 설치(필수)


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





<2> 프로메테우스 & 그라파나 설치(선택)


// 여기서는 사용하지 않는다. 설치 안해도 된다.


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





<3>  EKS 인증/인가 기본 지식


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




<4>  EKS 인증/인가


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






<5>  Amazon EKS 인증 인가 순서        


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 (인가)





<6> kubectl 명령 → aws eks get-token  과정 보기 (선택)





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 부분 확인하자.

https://jwt.io/



5

payload 부분을 디코드하면 ?

https://url-decode.com/


내용 ?

action  = GetcallerIdentity  등이 있다.



6

EKS API에게 전달 한다.

사용자에 대한 인증처리를 webhook 으로 요청한다.

kubectl api-resources | grep authentication


Token Reviews ?

사용자에 대한 인증을 처리할수 있다.


Webhook token authenticator 은  aws-iam-authenticator 를 사용 한다.


Cloudtrail 가면 GetCallerIdentity 사용 확인 가능.

https://ap-northeast-2.console.aws.amazon.com/cloudtrail/home?region=ap-northeast-2#/events?EventName=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





<7> 예제 - 새로 입사한 개발자가 사용하도록 제공하자



1

[myeks-bastion] 


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번 서버에 로그온 하자 ~


[myeks-bastion-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에서 권한을 추가해준다.


[myeks-bastion] 


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가 사용해야 하는 파일이다.


[myeks-bastion-2] 


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

[myeks-bastion-2]  


에서 신규 개발자가 확인 


# 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

퇴사 했을 경우 ?


[myeks-bastion]에서


# 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

[myeks-bastion-2] 


testuser kubectl 사용 확인


# 시도

kubectl get node -v6

kubectl api-resources -v5


둘다 안됨.



13

config 샘플

https://docs.aws.amazon.com/eks/latest/userguide/add-user-role.html







<8> 노드에 매핑될 롤 확인과 의미



노드가 사용하는 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 자격증명을 가진 사용자가  쿠버네티스의 리소스를 쓸때 매핑되는 것이다.





<9> 샘플 테스트


파드에서도 된다 !

노드에 권한이 부여 되어 있어서 가능한것이다.



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 취약점은 노드의 정책 권한을 파드도 다 사용할수 있게 되어 취약해진다.





<10> 개인 정리 


1

사용자/애플리케이션 에서 k8s 사용 시 

인증은 AWS IAM 사용  (쿠버네티스것  사용하지 않음)

인가는 K8S RBAC 사용


2

IMDS 취약점은 노드의 정책 권한을 파드도 다 사용할수 있게 되어 취약해진다.



다음 보기

https://brunch.co.kr/@topasvga/3302



전체 보기

https://brunch.co.kr/@topasvga/3217

감사합니다.




매거진의 이전글 EKS 8탄-11. EKS  Karpenter 실습
브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari