실습

Authentication - EKS

  1. kubeconfig 파일 리뷰

    kubectl config view
  2. kubeconfig에 명시된 users 확인 - https://kubernetes.io/docs/reference/access-authn-authz/authentication/#client-go-credential-plugins

    kubectl config view | yq e '.users' -
  3. user에 명시된 명령어 실행

    $(kubectl config view \
    -o=jsonpath='{.users[0].user.exec.command} {.users[0].user.exec.args[*]}')
  4. 토큰값을 환경변수로 지정 - Base64로 인코딩된 부분만 캡쳐

    {
        export TOKEN=$($(kubectl config view \
        -o=jsonpath='{.users[0].user.exec.command} {.users[0].user.exec.args[*]}') \
        | jq -r '.status.token' | grep -oP '(?<=k8s-aws-v1.).*')
        echo $TOKEN
    }
  5. Base64URL 유틸리티 설치

    npm install -g base64-url-cli
  6. 토큰값을 디코딩해서 환경변수로 지정

    {
        export DECODED_URL=$(base64url decode $TOKEN)
        echo $DECODED_URL 
    }
  7. Node에 부여된 Label을 통해서 EKS 클러스터 이름 확인하고 환경변수로 저장

    {
        export CLUSTER_NAME=$(kubectl get node \
        -o=jsonpath='{.items[0].metadata.labels.alpha\.eksctl\.io\/cluster-name}')
        echo $CLUSTER_NAME
    }
  8. 디코딩한 URL 호출

    curl -H "x-k8s-aws-id: $CLUSTER_NAME" $DECODED_URL
  9. 현재 설정된 AWS 자격증명을 확인

    aws sts get-caller-identity
  10. API 서버 주소를 확인하고 환경변수로 지정

    {
        export K8S_SERVER=$(kubectl config view \
        -o=jsonpath='{.clusters[*].cluster.server}')
        echo $K8S_SERVER
    }
  11. Node 목록을 보는 API 호출

    curl -k -X GET \
    -H "Authorization: Bearer $TOKEN" \
    -H "Content-Type: application/json" \
    $K8S_SERVER/api/v1/nodes
  12. 토큰값을 환경변수로 지정

    {
        export TOKEN=$($(kubectl config view \
        -o=jsonpath='{.users[0].user.exec.command} {.users[0].user.exec.args[*]}') \
        | jq -r '.status.token')
        
        echo $TOKEN
    }
  13. Node 목록을 보는 API 호출

    curl -k -X GET \
    -H "Authorization: Bearer $TOKEN" \
    -H "Content-Type: application/json" \
    $K8S_SERVER/api/v1/nodes
  14. IAM 유저 생성

    aws iam create-user --user-name john
  15. 위에서 생성한 IAM 유저의 Access Key 생성

    aws iam create-access-key --user-name john > key.txt
  16. Access Key가 정상적으로 생성되었는지 확인

    cat key.txt
  17. AWS CLI 자격증명 파일 및 설정 파일 백업

    {
        cp ~/.aws/credentials ~/.aws/credentials_backup
        cp ~/.aws/config ~/.aws/config_backup
    }
  18. 위에서 생성한 Access Key를 AWS CLI 자격증명 파일에 반영

    {
    cat <<EOF >> ~/.aws/credentials
    
    [john]
    aws_access_key_id=$(cat key.txt | jq -r '.AccessKey.AccessKeyId')
    aws_secret_access_key=$(cat key.txt | jq -r '.AccessKey.SecretAccessKey')
    EOF
    
    cat <<EOF >> ~/.aws/config
    
    [profile john]
    region = ap-northeast-2
    EOF
    }
  19. 위에서 명시한 프로필을 통해서 AWS API 호출

    aws sts get-caller-identity --profile john
  20. kubeconfig 파일 삭제

    rm -rf ~/.kube/config
  21. 쿠버네티스 API 호출 시도

    kubectl get pod -A
  22. 새로 생성한 IAM 유저의 자격증명으로 AWS CLI를 이용해서 kubeconfig 파일 생성

    aws eks update-kubeconfig --name $CLUSTER_NAME --profile john
  23. IAM 유저에서 eks:DescribeCluster 권한 부여

    aws iam put-user-policy --user-name john --policy-name eks-admin --policy-document \
    '{
        "Version": "2012-10-17",
        "Statement": [
            {
                "Action": [
                    "eks:DescribeCluster"
                ],
                "Resource": "*",
                "Effect": "Allow"
            }
        ]
    }'
  24. IAM 정책이 부여되었는지 확인

    {
        aws iam list-user-policies --user-name john
        aws iam get-user-policy --user-name john --policy-name eks-admin
    }
  25. 새로 생성한 IAM 유저의 자격증명으로 AWS CLI를 이용해서 kubeconfig 파일 생성 - 정책 적용까지 시간이 걸릴수 있음

    aws eks update-kubeconfig --name $CLUSTER_NAME --profile john
  26. 새로 생성된 kubeconfig 파일 리뷰

    kubectl config view
  27. 쿠버네티스 API 호출 시도

    kubectl get pod -A
  28. user에 명시된 명령어 실행

    {
        export $(kubectl config view -o=jsonpath='{.users[0].user.exec.env[0].name}={.users[0].user.exec.env[0].value}')
        $(kubectl config view \
        -o=jsonpath='{.users[0].user.exec.command} {.users[0].user.exec.args[*]}')
    }
  29. 토큰값을 환경변수로 지정 - Base64로 인코딩된 부분만 캡쳐

    {
        export TOKEN=$($(kubectl config view \
        -o=jsonpath='{.users[0].user.exec.command} {.users[0].user.exec.args[*]}') \
        | jq -r '.status.token' | grep -oP '(?<=k8s-aws-v1.).*')
        echo $TOKEN
    }
  30. 토큰값을 디코딩해서 환경변수로 지정

    {
        export DECODED_URL=$(base64url decode $TOKEN)
        echo $DECODED_URL 
    }
  31. 디코딩한 URL 호출

    curl -H "x-k8s-aws-id: $CLUSTER_NAME" $DECODED_URL
  32. 어드민 IAM 유저의 자격증명으로 AWS CLI를 이용해서 kubeconfig 파일 업데이트

    {
        rm -rf ~/.kube/config
        unset AWS_PROFILE
        aws eks update-kubeconfig --name $CLUSTER_NAME
    }

Authorization

  1. ClusterRole 목록 확인

    kubectl get clusterrole
  2. cluster-admin ClusterRole 리뷰

    kubectl get clusterrole cluster-admin -o yaml
  3. ClusterRoleBinding 목록 확인

    kubectl get clusterrolebinding
  4. cluster-admin ClusterRoleBinding 리뷰

    kubectl get clusterrolebinding cluster-admin -o yaml
  5. 현재 kubeconfig에 설정된 유저의 자격증명으로 수행할수 있는 API 목록 확인

    kubectl auth can-i --list
  6. aws-auth ConfigMap에 명시된 MapRoles 내용 확인 - https://kubernetes.io/docs/reference/access-authn-authz/node/

    kubectl -n kube-system get configmap aws-auth -o yaml | yq e '.data' -
  7. 한개의 Node의 인스턴스 ID를 확인하고 환경변수로 지정

    {
        export INSTANCE_ID=$(kubectl get node -o jsonpath='{.items[0].spec.providerID}' \
        | grep -oE "i-[a-z0-9]+")
        echo $INSTANCE_ID
    }
  8. Node에 부여된 IAM 인스턴스 프로필을 확인하고 환경변수로 지정

    {
        export INSTANCE_PROFILE=$(aws ec2 describe-instances --instance-ids $INSTANCE_ID \
        --query 'Reservations[0].Instances[0].IamInstanceProfile.Arn' \
        --output text | grep -oE "[a-z0-9-]+$")
        echo $INSTANCE_PROFILE
    }
  9. 위에서 확인한 인스턴스 프로필에 연동된 IAM 역할 확인

    aws iam get-instance-profile --instance-profile-name $INSTANCE_PROFILE \
    --query 'InstanceProfile.Roles[0].Arn' --output text
  10. view ClusterRole 리뷰

    kubectl get clusterrole view -o yaml
  11. ClusterRoleBinding 생성

    cat <<EOF | kubectl apply -f -
    kind: ClusterRoleBinding
    apiVersion: rbac.authorization.k8s.io/v1
    metadata:
      name: readonly
    subjects:
    - kind: Group
      name: readonly
      apiGroup: rbac.authorization.k8s.io
    roleRef:
      kind: ClusterRole
      name: view
      apiGroup: rbac.authorization.k8s.io
    EOF
  12. Node에 부여된 Label을 통해서 EKS 클러스터 이름을 확인하고 환경변수로 저장

    {
        export CLUSTER_NAME=$(kubectl get node \
        -o=jsonpath='{.items[0].metadata.labels.alpha\.eksctl\.io\/cluster-name}')
        echo $CLUSTER_NAME
    }
  13. EKS 클러스터가 생성되어 있는 AWS 계정번호 확인하고 환경변수로 저장

    {
        export ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
        echo $ACCOUNT_ID
    }
  14. aws-auth ConfigMap에 규칙 추가

    eksctl create iamidentitymapping --cluster $CLUSTER_NAME \
    --arn arn:aws:iam::$ACCOUNT_ID:user/john \
    --username arn:aws:iam::$ACCOUNT_ID:user/john \
    --group readonly
  15. aws-auth ConfigMap 변경분 확인

    kubectl -n kube-system get configmap aws-auth -o yaml
  16. john IAM 유저의 자격증명으로 AWS CLI를 이용해서 kubeconfig 파일 업데이트

    {
        rm -rf ~/.kube/config
        aws eks update-kubeconfig --name $CLUSTER_NAME --profile john
    }
  17. 현재 kubeconfig에 설정된 유저의 자격증명으로 수행할수 있는 API 목록 확인

    kubectl auth can-i --list
  18. 클러스터에 생성된 Pod 목록 확인

    kubectl get pod -A 
  19. Pod 생성 시도

    kubectl run nginx --image=nginx
  20. IAM 역할 생성

    {
    cat > trust-policy.json <<EOF
    {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Effect": "Allow",
                "Principal": {
                    "AWS": [
                        "arn:aws:iam::$ACCOUNT_ID:root"
                    ]
                },
                "Action": "sts:AssumeRole"
            }
        ]
    }
    EOF
    aws iam create-role --role-name eks-admin-role \
    --assume-role-policy-document file://trust-policy.json
    }
  21. aws-auth ConfigMap에 규칙 추가

    eksctl create iamidentitymapping --cluster $CLUSTER_NAME \
    --arn arn:aws:iam::$ACCOUNT_ID:role/eks-admin-role \
    --username devops \
    --group system:masters
  22. aws-auth ConfigMap 변경분 확인

    kubectl -n kube-system get configmap aws-auth -o yaml
  23. john IAM 유저의 자격증명으로 위에서 생성한 IAM 역할 전환하는 설정 추가해서 kubeconfig 파일 업데이트

    {
        rm -rf ~/.kube/config
        aws eks update-kubeconfig --name $CLUSTER_NAME --profile john \
        --role-arn arn:aws:iam::$ACCOUNT_ID:role/eks-admin-role
    }
  24. 새로 생성된 kubeconfig 파일 리뷰

    kubectl config view
  25. 쿠버네티스 API 호출 시도

    kubectl get pod -A
  26. john IAM 유저에서 sts:AssumeRole 권한 부여

    aws iam put-user-policy --user-name john --policy-name assume-role --policy-document \
    '{
        "Version": "2012-10-17",
        "Statement": [
            {
                "Action": [
                    "sts:AssumeRole"
                ],
                "Resource": "*",
                "Effect": "Allow"
            }
        ]
    }'
  27. IAM 정책이 부여되었는지 확인

    {
        aws iam list-user-policies --user-name john
        aws iam get-user-policy --user-name john --policy-name assume-role
    }
  28. 쿠버네티스 API 호출 시도 - 정책 적용까지 시간이 걸릴수 있음

    kubectl get pod -A
  29. user에 명시된 명령어 실행

    {
        export $(kubectl config view -o=jsonpath='{.users[0].user.exec.env[0].name}={.users[0].user.exec.env[0].value}')
        $(kubectl config view \
        -o=jsonpath='{.users[0].user.exec.command} {.users[0].user.exec.args[*]}')
    }
  30. 토큰값을 환경변수로 지정 - Base64로 인코딩된 부분만 캡쳐

    {
        export TOKEN=$($(kubectl config view \
        -o=jsonpath='{.users[0].user.exec.command} {.users[0].user.exec.args[*]}') \
        | jq -r '.status.token' | grep -oP '(?<=k8s-aws-v1.).*')
        echo $TOKEN
    }
  31. 토큰값을 디코딩해서 환경변수로 지정

    {
        export DECODED_URL=$(base64url decode $TOKEN)
        echo $DECODED_URL 
    }
  32. 디코딩한 URL 호출

    curl -H "x-k8s-aws-id: $CLUSTER_NAME" $DECODED_URL
  33. 어드민 IAM 유저의 자격증명으로 AWS CLI를 이용해서 kubeconfig 파일 업데이트

    {
        rm -rf ~/.kube/config
        unset AWS_PROFILE
        aws eks update-kubeconfig --name $CLUSTER_NAME
    }
  34. 리소스 삭제

    {
        aws iam delete-access-key --user-name john --access-key-id $(cat key.txt | jq -r '.AccessKey.AccessKeyId')
        aws iam delete-user-policy --user-name john --policy-name eks-admin
        aws iam delete-user-policy --user-name john --policy-name assume-role
        aws iam delete-user --user-name john
        kubectl delete clusterrolebinding readonly
        aws iam delete-role --role-name eks-admin-role
        eksctl delete iamidentitymapping --cluster $CLUSTER_NAME --arn arn:aws:iam::$ACCOUNT_ID:role/eks-admin-role
        eksctl delete iamidentitymapping --cluster $CLUSTER_NAME --arn arn:aws:iam::$ACCOUNT_ID:user/john
        mv ~/.aws/credentials_backup ~/.aws/credentials
        mv ~/.aws/config_backup ~/.aws/config
        rm key.txt trust-policy.json
    }

Service Account

  1. Pod 생성

    kubectl run nginx --image=nginx
  2. Pod 생성 확인

    kubectl get pod nginx
  3. Pod에 부여된 ServiceAccount 확인

    kubectl get pod nginx -o=jsonpath='{.spec.serviceAccountName}{"\n"}'
  4. default 네임스페이스에 존재하는 ServiceAccount 목록 확인

    kubectl get sa
  5. ServiceAccount 생성

    kubectl create sa kubectl-access
  6. Pod 생성

    cat <<EOF | kubectl apply -f -
    apiVersion: v1
    kind: Pod
    metadata:
      name: kubectl
    spec:
      serviceAccountName: kubectl-access
      containers:
      - image: bitnami/kubectl
        name: kubectl
        command: ["sleep", "3600"]
    EOF
  7. 생성된 Pod 안에서 포함된 kubectl을 통해서 kube-system 네임스페이스에 있는 Pod 목록 확인

    kubectl exec kubectl -- kubectl get pod -n kube-system
  8. 위에서 생성한 ServiceAccount에 부여된 권한 확인

    kubectl auth can-i --list --as system:serviceaccount:default:kubectl-access
  9. ClusterRole 생성

    cat <<EOF | kubectl apply -f -
    kind: ClusterRole
    apiVersion: rbac.authorization.k8s.io/v1
    metadata:
      name: pod-access
    rules:
    - apiGroups: [""]
      resources: ["pods"]
      verbs: ["get", "list", "watch"]
    EOF
  10. RoleBinding 생성

    cat <<EOF | kubectl apply -f -
    kind: RoleBinding
    apiVersion: rbac.authorization.k8s.io/v1
    metadata:
      name: pod-access
      namespace: kube-system
    subjects:
    - kind: ServiceAccount
      name: kubectl-access
      namespace: default
    roleRef:
      kind: ClusterRole
      name: pod-access
      apiGroup: rbac.authorization.k8s.io
    EOF
  11. 생성된 Pod 안에서 포함된 kubectl을 통해서 kube-system 네임스페이스에 있는 Pod 목록 확인

    kubectl exec kubectl -- kubectl get pod -n kube-system
  12. 생성된 Pod 안에서 포함된 kubectl을 통해서 default 네임스페이스에 있는 Pod 목록 확인

    kubectl exec kubectl -- kubectl get pod
  13. 위에서 생성한 ServiceAccount에 부여된 권한 확인

    kubectl auth can-i --list --as system:serviceaccount:default:kubectl-access
  14. 위에서 생성한 ServiceAccount에 kube-system 네임스페이스에 대해서 부여된 권한 확인

    kubectl auth can-i --list -n kube-system \
    --as system:serviceaccount:default:kubectl-access
  15. 리소스 삭제

    {
        kubectl delete pod kubectl nginx
        kubectl delete rolebinding pod-access -n kube-system
        kubectl delete clusterrole pod-access
        kubectl delete sa kubectl-access
    }

IAM roles for service accounts

  1. Pod 생성

    kubectl run aws-cli --image=amazon/aws-cli --command -- sleep 3600
  2. Pod 생성 확인

    kubectl get pod aws-cli
  3. 생성된 Pod에 부여된 AWS 자격증명 확인

    kubectl exec aws-cli -- aws sts get-caller-identity
  4. Pod가 배포된 Node 확인

    kubectl get pod aws-cli -o wide
  5. Pod가 배포된 Node의 인스턴스 ID를 확인하고 환경변수로 지정

    {
        export INSTANCE_ID=$(kubectl get node $(kubectl get pod aws-cli -o=jsonpath='{.spec.nodeName}') \
        -o jsonpath='{.spec.providerID}{"\n"}' | grep -oE "i-[a-z0-9]+")
        echo $INSTANCE_ID
    }
  6. Node에 부여된 IAM 인스턴스 프로필을 확인하고 환경변수로 지정

    {
        export INSTANCE_PROFILE=$(aws ec2 describe-instances --instance-ids $INSTANCE_ID \
        --query 'Reservations[0].Instances[0].IamInstanceProfile.Arn' \
        --output text | grep -oE "[a-z0-9-]+$")
        echo $INSTANCE_PROFILE
    }
  7. 위에서 확인한 인스턴스 프로필에 연동된 IAM 역할 확인

    aws iam get-instance-profile --instance-profile-name $INSTANCE_PROFILE \
    --query 'InstanceProfile.Roles[0].Arn' --output text
  8. Pod에 부여된 AWS 자격증명 확인

    kubectl exec aws-cli -- aws sts get-caller-identity
  9. Pod에서 EC2 인스턴스 메타데이터를 통해서 상속받는 자격증명 확인

    kubectl exec aws-cli -- \
    curl -s -w "\n" http://169.254.169.254/latest/meta-data/iam/security-credentials
  10. 위에서 확인한 자격증명에 부여된 Access Key 확인

    kubectl exec aws-cli -- bash -c \
    'curl -s -w "\n" http://169.254.169.254/latest/meta-data/iam/security-credentials/$(curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials)'
  11. AWS CLI가 자격증명을 불러오는 순서 확인

    kubectl exec aws-cli -- aws sts get-caller-identity --debug
  12. Node에 부여된 Label을 통해서 EKS 클러스터 이름을 확인하고 환경변수로 저장

    {
        export CLUSTER_NAME=$(kubectl get node \
        -o=jsonpath='{.items[0].metadata.labels.alpha\.eksctl\.io\/cluster-name}')
        echo $CLUSTER_NAME
    }
  13. ServiceAccount 생성

    eksctl create iamserviceaccount \
    --cluster=$CLUSTER_NAME \
    --namespace=default \
    --name=aws-cli \
    --attach-policy-arn=arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess \
    --override-existing-serviceaccounts \
    --approve
  14. 생성된 ServiceAccount 확인

    kubectl get sa aws-cli
  15. ServiceAccount에 명시된 IAM 역할 이을 확인하고 환경변수로 지정

    {
       IAM_ROLE_NAME=$(kubectl get sa aws-cli \
       -o=jsonpath='{.metadata.annotations.eks\.amazonaws\.com\/role-arn}' \
       | grep -oP '(?<=role.).*')
       echo $IAM_ROLE_NAME
    }
  16. ServiceAccount와 연동된 IAM 역할에 부여된 IAM 정책 확인

    aws iam list-attached-role-policies --role-name $IAM_ROLE_NAME
  17. ServiceAccount와 연동된 IAM 역할에 부여된 신뢰관계 정책 확인

    aws iam get-role --role-name $IAM_ROLE_NAME
  18. EKS 클러스터에 연동된 OIDC 제공자 확인

    aws eks describe-cluster --name $CLUSTER_NAME \
    --query "cluster.identity.oidc.issuer" --output text
  19. Pod를 재생성하고 위에서 생성한 ServiceAccount 부여

    cat <<EOF | kubectl replace --force -f -
    apiVersion: v1
    kind: Pod
    metadata:
      name: aws-cli
    spec:
      serviceAccountName: aws-cli
      containers:
      - name: aws-cli
        image: amazon/aws-cli
        command: ["sleep", "3600"]
    EOF
  20. Pod에 부여된 AWS 자격증명 확인

    kubectl exec aws-cli -- aws sts get-caller-identity
  21. Pod에서 EC2 인스턴스 메타데이터를 통해서 상속받는 자격증명 확인

    kubectl exec aws-cli -- \
    curl -s -w "\n" http://169.254.169.254/latest/meta-data/iam/security-credentials
  22. AWS CLI가 자격증명을 불러오는 순서 확인

    kubectl exec aws-cli -- aws sts get-caller-identity --debug
  23. Pod에 지정된 환경변수 확인

    kubectl exec aws-cli -- printenv
  24. Pod에 생성된 AWS 임시토큰 파일 내용 확인

    kubectl exec aws-cli -- bash -c 'cat $AWS_WEB_IDENTITY_TOKEN_FILE'
  25. 위에서 확인한 토큰 내용 확인

    jq -R 'split(".") | .[0],.[1] | @base64d | fromjson' <<<\
    $(kubectl exec aws-cli -- bash -c 'cat $AWS_WEB_IDENTITY_TOKEN_FILE')
  26. ServiceAccount와 연동된 IAM 역할에 부여된 신뢰관계 정책 확인

    aws iam get-role --role-name $IAM_ROLE_NAME
  27. Pod에서 AWS CLI를 통해서 S3 버킷 목록 확인

    kubectl exec aws-cli -- aws s3 ls
  28. 리소스 삭제

    {
        eksctl delete iamserviceaccount --cluster $CLUSTER_NAME --name aws-cli
        kubectl delete pod aws-cli
    }

Last updated