6주차 - EKS Security - EKS 인증/인가(2)

728x90

EKS 인증/인가

 

AWS EKS의 경우 사용자 인증은 AWS IAM / 인가는 K8S의 RBAC을 사용

etc-image-0



  • EKS 인증 모드: API / ConfigMap
    • ConfigMap의 경우 Deprecation 예정

etc-image-1

 

 

 EKS 사용자 인증 /인가

 

  1. IAM 인증을 위한 Token 요청(eks get token)
  2. 발급받은 Token을 통하여 Pre-Signed URL을 Bearer Token으로 EKS API Cluster Endpoint로 요청
  3. EKS API는 Token Review 를 Webhook token authenticator에 요청 ⇒ (STS GetCallerIdentity 호출) AWS IAM 해당 호출 인증 완료 후 User/Role에 대한 ARN 반환
  4. ConfigMap에서 반환된 Role ARN과 맵핑 정보를 확인(엑세스 인증)
  5. Kubernetes RBAC을 통하여 맵핑된 정보(권한)확인 후 EKS 인가 허가(RBAC을 통한 인가 검토)

 

  • kubeconifg 확인 시 일반 config파일에서는 키와 인증서가 확인되지만, EKS의 경우 Token 발급을 위한 설정이 되어 있음
    • kubectl 명령 → aws eks get-tokenSTS토큰 요청 ⇒ 응답값 디코드
    • STS Security Token Service : AWS 리소스에 대한 액세스를 제어할 수 있는 임시 보안 자격 증명(STS)을 생성하여 신뢰받는 사용자에게 제공
    • AWS CLI 버전 1.16.156 이상에서는 별도 aws-iam-authenticator 설치 없이 aws eks get-token으로 사용 가능
# sts caller id의 ARN 확인
aws sts get-caller-identity --query Arn
"arn:aws:iam::<자신의 Account ID>:user/admin"

# kubeconfig 정보 확인
cat ~/.kube/config
...
- 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

# 임시 보안 자격 증명(토큰)을 요청 : expirationTimestamp 시간경과 시 토큰 재발급됨
aws eks get-token --cluster-name $CLUSTER_NAME | jq
aws eks get-token --cluster-name $CLUSTER_NAME | jq -r '.status.token'
aws eks get-token --cluster-name $CLUSTER_NAME --debug | jq

etc-image-2

# tokenreviews api 리소스 확인 
kubectl api-resources | grep authentication
tokenreviews                                   authentication.k8s.io/v1               false        TokenReview

# List the fields for supported resources.
kubectl explain tokenreviews
...
DESCRIPTION:
     TokenReview attempts to authenticate a token to a known user. Note:
     TokenReview requests may be cached by the webhook token authenticator
     plugin in the kube-apiserver.

 

 

 실습 - 신규 사용자 EKS 인증/인가

  • 신규 IAM 생성
# burst 사용자 생성
aws iam create-user --user-name burst

# 사용자에게 프로그래밍 방식 액세스 권한 부여(Access Key 발급)
aws iam create-access-key --user-name burst

# burst 사용자에 정책을 추가
aws iam attach-user-policy --policy-arn arn:aws:iam::aws:policy/AdministratorAccess --user-name burst

 

etc-image-3etc-image-4
etc-image-5

 

etc-image-6

  • burst 자격증명 설정(operator-host-2에서 진행)
# 아래 실습 진행을 위해, kind(k8s) 삭제
kind delete cluster --name myk8s
mv ~/.kube/config ~/.kube/config.old

# burst 자격증명 설정
aws configure

# get-caller-identity 확인
aws sts get-caller-identity --query Arn

# kubectl 시도 >> testuser도 AdministratorAccess 권한을 가지고 있는데, 실패 이유는?
kubectl get node -v6
ls ~/.kube

etc-image-7
etc-image-8

  • burst에 system:masters 그룹 부여로 EKS 관리자 수준 권한 설정
# 방안1 : eksctl 사용 >> iamidentitymapping 실행 시 aws-auth 컨피그맵 작성해줌
# Creates a mapping from IAM role or user to Kubernetes user and groups
eksctl get iamidentitymapping --cluster $CLUSTER_NAME
ARN											USERNAME				GROUPS					ACCOUNT
arn:aws:iam::890742582773:role/eksctl-myeks-nodegroup-ng1-NodeInstanceRole-CPeuWkY6c6v1	system:node:{{EC2PrivateDNSName}}	system:bootstrappers,system:nodes	

eksctl create iamidentitymapping --cluster $CLUSTER_NAME --username burst --group system:masters --arn arn:aws:iam::$ACCOUNT_ID:user/burst
2025-03-16 00:34:18 [ℹ]  checking arn arn:aws:iam:::user/burst against entries in the auth ConfigMap
2025-03-16 00:34:18 [ℹ]  adding identity "arn:aws:iam:::user/burst" to auth ConfigMap

# 확인
kubectl get cm -n kube-system aws-auth -o yaml
...

# 확인 : 기존에 있는 role/eksctl-myeks-nodegroup-ng1-NodeInstanceRole-YYYYY 는 어떤 역할/동작을 하는 걸까요?
eksctl get iamidentitymapping --cluster $CLUSTER_NAME
ARN											USERNAME				GROUPS					ACCOUNT
arn:aws:iam::890742582773:role/eksctl-myeks-nodegroup-ng1-NodeInstanceRole-CPeuWkY6c6v1	system:node:{{EC2PrivateDNSName}}	system:bootstrappers,system:nodes	
arn:aws:iam:::user/burst								burst					system:masters						testuser				system:masters

etc-image-9
etc-image-10

  • burst사용자 kubeconfig 생성 및 kubectl 사용 확인(operator-host-2에서 진행)
# burst kubeconfig 생성 >> aws eks update-kubeconfig 실행이 가능한 이유는?, 3번 설정 후 약간의 적용 시간 필요
CLUSTER_NAME=myeks
aws eks update-kubeconfig --name $CLUSTER_NAME --user-alias burst

# 운영서버의 config와 비교해보자
cat ~/.kube/config

# kubectl 사용 확인
kubectl ns default
kubectl get node -v6

# rbac-tool 후 확인 >> 기존 계정과 비교해보자
kubectl rbac-tool whoami

etc-image-11
etc-image-12
etc-image-13

 

  • burst 의 Group 변경(system:masters → system:authenticated)으로 RBAC 동작 확인
    • aws-auth 컨피그맵을 잘못 수정 시 장애 발생할 수 있기 때문에 Deprecation 예정
# 방안2 : 아래 edit로 mapUsers 내용 직접 수정 system:authenticated
kubectl edit cm -n kube-system aws-auth
...

# 확인
eksctl get iamidentitymapping --cluster $CLUSTER_NAME

etc-image-14
etc-image-15

 

 

EKS 신규기능 access management 

etc-image-16
etc-image-17

  • aws-auth configmap 잘못 수정 시 Node전체에 장애가 발생 할 수 있음
  • 이를 보안하기 위해 신규 기능인 access management controls 기능이 추가
  • 기존 복잡하고 configmap을 통한 사용자 관리를 보다 쉽게 제어 및 컨트롤 할 수 있는 장점이 있음

etc-image-18

  • 기본 인증모드는 EKS API 및 ConfigMap으로 설정되어 있으며, 정책 중복 시 EKS API가 우선되며, ConfigMap은 무시

etc-image-19

 

  • 기본 인증모드는 EKS API 및 ConfigMap으로 설정되어 있으나 정책 중복 시 EKS API가 우선되며, ConfigMap은 무시됨

etc-image-20

  • EKS 설치 시, 설치한 IAM계정에 대해서 기본적으로 권한이 설정(AmazonEKSClusterAdminPolicy)

 

1. EKS 인증방식을 EKS API모드로 변경

# EKS API 액세스모드로 변경
aws eks update-cluster-config --name $CLUSTER_NAME --access-config authenticationMode=API

# List all access policies : 클러스터 액세스 관리를 위해 지원되는 액세스 정책
# https://docs.aws.amazon.com/eks/latest/userguide/access-policy-permissions.html
## AmazonEKSClusterAdminPolicy – 클러스터 관리자
## AmazonEKSAdminPolicy – 관리자
## AmazonEKSEditPolicy – 편집
## AmazonEKSViewPolicy – 보기

aws eks list-access-policies | jq

# 맵핑 클러스터롤 정보 확인
kubectl get clusterroles -l 'kubernetes.io/bootstrapping=rbac-defaults' | grep -v 'system:'
NAME                                                                   CREATED AT
admin                                                                  2025-03-15T05:15:27Z
cluster-admin                                                          2025-03-15T05:15:27Z
edit                                                                   2025-03-15T05:15:27Z
view                                                                   2025-03-15T05:15:27Z

kubectl describe clusterroles admin
kubectl describe clusterroles cluster-admin
kubectl describe clusterroles edit
kubectl describe clusterroles view

aws eks list-access-entries --cluster-name $CLUSTER_NAME | jq
{
  "accessEntries": [
    "arn:aws:iam::890742582773:role/aws-service-role/eks.amazonaws.com/AWSServiceRoleForAmazonEKS",
    "arn:aws:iam::890742582773:role/eksctl-myeks-nodegroup-ng1-NodeInstanceRole-CPeuWkY6c6v1",
    "arn:aws:iam::890742582773:user/yjsong2"
  ]
}

# 확인 : macOS - 뒤에 admin 은 자신의 IAM User로 변경해서 실행 할 것!
export ACCOUNT_ID=$(aws sts get-caller-identity --query 'Account' --output text)
aws eks list-associated-access-policies --cluster-name $CLUSTER_NAME --principal-arn arn:aws:iam::$ACCOUNT_ID\:user/yjsong2 | jq # macOS

# 확인 : Linux (운영서버, WSL2 등) - 뒤에 admin 은 자신의 IAM User로 변경해서 실행 할 것!
export ACCOUNT_ID=$(aws sts get-caller-identity --query 'Account' --output text)
aws eks list-associated-access-policies --cluster-name $CLUSTER_NAME --principal-arn arn:aws:iam::$ACCOUNT_ID:user/yjsong2 | jq # Linux

{
  "associatedAccessPolicies": [
    {
      "policyArn": "arn:aws:eks::aws:cluster-access-policy/AmazonEKSClusterAdminPolicy",
      "accessScope": {
        "type": "cluster",
        "namespaces": []
      },
      "associatedAt": "2025-03-15T14:10:41.146000+09:00",
      "modifiedAt": "2025-03-15T14:10:41.146000+09:00"
    }
  ],
  "clusterName": "myeks",
  "principalArn": "arn:aws:iam::890742582773:user/yjsong2"
}


# 위에서 출력된 nodegroup IAM Role ARN 을 아래 입력 해서 실행 할 것!
aws eks list-associated-access-policies --cluster-name $CLUSTER_NAME --principal-arn arn:aws:iam::$ACCOUNT_ID\:role/eksctl-myeks-nodegroup-ng1-NodeInstanceRole-CPeuWkY6c6v1 | jq
aws eks list-associated-access-policies --cluster-name $CLUSTER_NAME --principal-arn arn:aws:iam::$ACCOUNT_ID:role/eksctl-myeks-nodegroup-ng1-NodeInstanceRole-CPeuWkY6c6v1 | jq
{
  "associatedAccessPolicies": [],
  "clusterName": "myeks",
  "principalArn": "arn:aws:iam::890742582773:role/eksctl-myeks-nodegroup-ng1-NodeInstanceRole-CPeuWkY6c6v1"
}
#
aws eks describe-access-entry --cluster-name $CLUSTER_NAME --principal-arn arn:aws:iam::$ACCOUNT_ID\:user/yjsong2 | jq
aws eks describe-access-entry --cluster-name $CLUSTER_NAME --principal-arn arn:aws:iam::$ACCOUNT_ID:user/yjsong2 | jq
{
  "accessEntry": {
    "clusterName": "myeks",
    "principalArn": "arn:aws:iam::890742582773:user/yjsong2",
    "kubernetesGroups": [],
    "accessEntryArn": "arn:aws:eks:ap-northeast-2:890742582773:access-entry/myeks/user/890742582773/yjsong2/b2cacc1b-1439-4a7f-13c0-77e7cbbb0311",
    "createdAt": "2025-03-15T14:10:41.076000+09:00",
    "modifiedAt": "2025-03-15T14:10:41.076000+09:00",
    "tags": {},
    "username": "arn:aws:iam::890742582773:user/yjsong2",
    "type": "STANDARD"
  }
}
aws eks describe-access-entry --cluster-name $CLUSTER_NAME --principal-arn arn:aws:iam::$ACCOUNT_ID\:role/eksctl-myeks-nodegroup-ng1-NodeInstanceRole-CPeuWkY6c6v1 | jq
aws eks describe-access-entry --cluster-name $CLUSTER_NAME --principal-arn arn:aws:iam::$ACCOUNT_ID:role/eksctl-myeks-nodegroup-ng1-NodeInstanceRole-CPeuWkY6c6v1 | jq
{
  "accessEntry": {
    "clusterName": "myeks",
    "principalArn": "arn:aws:iam::890742582773:role/eksctl-myeks-nodegroup-ng1-NodeInstanceRole-CPeuWkY6c6v1",
    "kubernetesGroups": [
      "system:nodes"
    ],
    "accessEntryArn": "arn:aws:eks:ap-northeast-2:890742582773:access-entry/myeks/role/890742582773/eksctl-myeks-nodegroup-ng1-NodeInstanceRole-CPeuWkY6c6v1/90cacc21-65bd-83cb-014c-2cfc5b829539",
    "createdAt": "2025-03-15T14:24:29.248000+09:00",
    "modifiedAt": "2025-03-15T14:24:29.248000+09:00",
    "tags": {},
    "username": "system:node:{{EC2PrivateDNSName}}",
    "type": "EC2_LINUX"
  }
}

etc-image-21

 

2. burst 유저 설정

  • access-entry 생성 / associate-access-policy 연동
    • 간단하고 직관적으로 EKS 사용자를 관리 할 수 있음
# burst 의 access entry 생성
aws eks create-access-entry --cluster-name $CLUSTER_NAME --principal-arn arn:aws:iam::$ACCOUNT_ID:user/burst
aws eks list-access-entries --cluster-name $CLUSTER_NAME | jq -r .accessEntries[]
{
    "accessEntry": {
        "clusterName": "myeks",
        "principalArn": "arn:aws:iam::890742582773:user/burst",
        "kubernetesGroups": [],
        "accessEntryArn": "arn:aws:eks:ap-northeast-2:890742582773:access-entry/myeks/user/890742582773/burst/7ecacd69-bf89-6b1c-03c3-20342863d56d",
        "createdAt": "2025-03-16T02:21:46.832000+09:00",
        "modifiedAt": "2025-03-16T02:21:46.832000+09:00",
        "tags": {},
        "username": "arn:aws:iam::890742582773:user/burst",
        "type": "STANDARD"
    }
}

# burst에 AmazonEKSClusterAdminPolicy 연동
aws eks associate-access-policy --cluster-name $CLUSTER_NAME --principal-arn arn:aws:iam::$ACCOUNT_ID:user/burst \
  --policy-arn arn:aws:eks::aws:cluster-access-policy/AmazonEKSClusterAdminPolicy --access-scope type=cluster

#
aws eks list-associated-access-policies --cluster-name $CLUSTER_NAME --principal-arn arn:aws:iam::$ACCOUNT_ID:user/burst | jq
aws eks describe-access-entry --cluster-name $CLUSTER_NAME --principal-arn arn:aws:iam::$ACCOUNT_ID:user/burst | jq

 

etc-image-22
etc-image-23

 

3. burst 유저 확인(operator-host-2에서 진행)

# burst 정보 확인
aws sts get-caller-identity --query Arn
kubectl whoami

# kubectl 시도
kubectl get node -v6
kubectl api-resources -v5
kubectl rbac-tool whoami
kubectl auth can-i delete pods --all-namespaces
kubectl get cm -n kube-system aws-auth -o yaml
eksctl get iamidentitymapping --cluster $CLUSTER_NAME

etc-image-24

 

4. 직접 생성한 Cluster-role 사용(Access entries and Kubernetes groups)

# 기존 testuser access entry 제거
aws eks delete-access-entry --cluster-name $CLUSTER_NAME --principal-arn arn:aws:iam::$ACCOUNT_ID:user/burst
aws eks list-access-entries --cluster-name $CLUSTER_NAME | jq -r .accessEntries[]

#
cat <<EoF> ~/pod-viewer-role.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: pod-viewer-role
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["list", "get", "watch"]
EoF

cat <<EoF> ~/pod-admin-role.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: pod-admin-role
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["*"]
EoF

kubectl apply -f ~/pod-viewer-role.yaml
kubectl apply -f ~/pod-admin-role.yaml

#
kubectl create clusterrolebinding viewer-role-binding --clusterrole=pod-viewer-role --group=pod-viewer
kubectl create clusterrolebinding admin-role-binding --clusterrole=pod-admin-role --group=pod-admin

#
aws eks create-access-entry --cluster-name $CLUSTER_NAME --principal-arn arn:aws:iam::$ACCOUNT_ID:user/burst --kubernetes-group pod-viewer
{
    "accessEntry": {
        "clusterName": "myeks",
        "principalArn": "arn:aws:iam::890742582773:user/burst",
        "kubernetesGroups": [
            "pod-viewer"
        ],
        "accessEntryArn": "arn:aws:eks:ap-northeast-2:890742582773:access-entry/myeks/user/890742582773/burst/0ecacd6f-e8e4-78a8-a9a6-52a9f000a277",
        "createdAt": "2025-03-16T02:35:14.460000+09:00",
        "modifiedAt": "2025-03-16T02:35:14.460000+09:00",
        "tags": {},
        "username": "arn:aws:iam::890742582773:user/burst",
        "type": "STANDARD"
    }
}

#
aws eks list-associated-access-policies --cluster-name $CLUSTER_NAME --principal-arn arn:aws:iam::$ACCOUNT_ID:user/burst
aws eks describe-access-entry --cluster-name $CLUSTER_NAME --principal-arn arn:aws:iam::$ACCOUNT_ID:user/burst | jq
{
  "accessEntry": {
    "clusterName": "myeks",
    "principalArn": "arn:aws:iam::890742582773:user/burst",
    "kubernetesGroups": [
      "pod-viewer"
    ],
    "accessEntryArn": "arn:aws:eks:ap-northeast-2:890742582773:access-entry/myeks/user/890742582773/burst/0ecacd6f-e8e4-78a8-a9a6-52a9f000a277",
    "createdAt": "2025-03-16T02:35:14.460000+09:00",
    "modifiedAt": "2025-03-16T02:35:14.460000+09:00",
    "tags": {},
    "username": "arn:aws:iam::890742582773:user/burst",
    "type": "STANDARD"
  }
}
  • pod-viewer  그룹 설정 시, pod확인은 가능하나 delete 권한은 없음

etc-image-25
etc-image-26

 

5. 직접 생성한 Cluster-role 사용(kubernetesGroups 업데이트 적용)

#
aws eks update-access-entry --cluster-name $CLUSTER_NAME --principal-arn arn:aws:iam::$ACCOUNT_ID:user/burst --kubernetes-group pod-admin | jq -r .accessEntry
{
  "clusterName": "myeks",
  "principalArn": "arn:aws:iam::890742582773:user/burst",
  "kubernetesGroups": [
    "pod-admin"
  ],
  "accessEntryArn": "arn:aws:eks:ap-northeast-2:890742582773:access-entry/myeks/user/890742582773/burst/0ecacd6f-e8e4-78a8-a9a6-52a9f000a277",
  "createdAt": "2025-03-16T02:35:14.460000+09:00",
  "modifiedAt": "2025-03-16T02:45:01.924000+09:00",
  "tags": {},
  "username": "arn:aws:iam::890742582773:user/burst",
  "type": "STANDARD"
}

aws eks describe-access-entry --cluster-name $CLUSTER_NAME --principal-arn arn:aws:iam::$ACCOUNT_ID:user/burst | jq
{
  "accessEntry": {
    "clusterName": "myeks",
    "principalArn": "arn:aws:iam::890742582773:user/burst",
    "kubernetesGroups": [
      "pod-admin"
    ],
    "accessEntryArn": "arn:aws:eks:ap-northeast-2:890742582773:access-entry/myeks/user/890742582773/burst/0ecacd6f-e8e4-78a8-a9a6-52a9f000a277",
    "createdAt": "2025-03-16T02:35:14.460000+09:00",
    "modifiedAt": "2025-03-16T02:45:01.924000+09:00",
    "tags": {},
    "username": "arn:aws:iam::890742582773:user/burst",
    "type": "STANDARD"
  }
}
  • pod-admin  그룹 설정 시, pod 확인 및 delete 권한 확인 

etc-image-27
etc-image-28

 

728x90