Neil Kuan
April 22, 2020

Least privilege ?! IAM Role For Service Account (IRSA)

Posted on April 22, 2020  •  5 minutes  • 1064 words

使用Amazon EKS集群上服務帳戶的IAM角色,您可以將IAM角色與Kubernetes服務帳戶關聯。 然後,該服務帳戶可以向使用該服務帳戶的任何 pod 中的 container 提供AWS權限。 使用此功能,您不再需要為工作節點( worker nodes ) IAM角色提供擴展權限,以便該節點上的Pod可以調用AWS API。

應用程序必須使用AWS憑證簽署其AWS API請求。 此功能提供了一種用於管理應用程序憑證的策略,類似於Amazon EC2實例配置文件向Amazon EC2實例提供憑證的方式。 您可以將IAM角色與Kubernetes服務帳戶相關聯,而不必創建AWS憑證並將其分發到容器或使用Amazon EC2實例的角色。 然後,容器容器中的應用程序可以使用AWS SDK或AWS CLI向授權的AWS服務發出API請求。

服務帳戶的IAM角色功能具有以下優點:

2014年,AWS Identity and Access Management添加了對使用OpenID Connect(OIDC)的聯合身份的支持。通過此功能,您可以使用受支持的身份提供者對AWS API調用進行身份驗證,並接收有效的OIDC JSON Web令牌(JWT)。您可以將此令牌傳遞給AWS STS AssumeRoleWithWebIdentity API操作,並接收IAM臨時角色憑證。您可以使用這些憑證與任何AWS服務(例如Amazon S3和DynamoDB)進行交互。

Kubernetes長期以來一直將服務帳戶用作其內部身份系統。 Pods可以使用僅Kubernetes API服務器可以驗證的自動安裝的令牌(非OIDC JWT)向Kubernetes API服務器進行身份驗證。這些舊版服務帳戶令牌不會過期,並且旋轉簽名密鑰是一個困難的過程。在Kubernetes版本1.12中,添加了對新ProjectedServiceAccountToken功能的支持,該功能是OIDC JSON Web令牌,它還包含服務帳戶標識,並支持可配置的受眾。

Amazon EKS現在在每個集群上託管一個公共OIDC發現終端節點,其中包含ProjectedServiceAccountToken JSON Web令牌的簽名密鑰,因此外部系統(例如IAM)可以驗證和接受Kubernetes發行的OIDC令牌。

Using a supported AWS SDK The containers in your pods must use an AWS SDK version that supports assuming an IAM role via an OIDC web identity token file. AWS SDKs that are included in Linux distribution package managers may not be new enough to support this feature. Be sure to use at least the minimum SDK versions listed below:

Many popular Kubernetes add-ons, such as the Cluster Autoscaler and the ALB Ingress Controller support IAM roles for service accounts. The Amazon VPC CNI plugin for Kubernetes has been updated with a supported version of the AWS SDK for Go, and you can use the IAM roles for service accounts feature to provide the required permissions for the CNI to work.

PREPARATION

Enabling IAM Roles for Service Accounts on your Cluster

Need tools in your workspaces

# You must use at least version 1.18.15 of the AWS CLI to receive the proper output from this command:

-- aws cli version 1.18.15

-- eksctl version []  version.Info{BuiltAt:"", GitCommit:"", GitTag:"0.5.3"}

# The IAM roles for service accounts feature is available on new Amazon EKS Kubernetes # version 1.14 clusters, and clusters that were updatedtversions 1.14 or 1.13 on or# after September 3rd, 2019.
-- kubectl version --short >= 1.13.*

CREATE AN OIDC IDENTITY PROVIDER

To create an IAM OIDC identity provider for your cluster with eksctl To use IAM roles for service accounts in your cluster, you must create an OIDC identity provider in the IAM console Check your eksctl version that your eksctl version is at least 0.5.1

$EKS_CLUSTER_NAME is your EKS cluster name like pic1

pic1

Create your OIDC identity provider for your cluster

$ eksctl utils associate-iam-oidc-provider --cluster $EKS_CLUSTER_NAME --approve
---output
[]  using region {AWS_REGION}
[]  will create IAM Open ID Connect provider for cluster "$EKS_CLUSTER_NAME" in "{AWS_REGION}"
[]  created IAM Open ID Connect provider for cluster "$EKS_CLUSTER_NAME" in "{AWS_REGION}"

If you go to the Identity Providers in IAM Console , you will see OIDC provider has created for your cluster

OIDC Identity Provider

CREATING AN IAM ROLE FOR SERVICE ACCOUNT

To create an IAM role for your service accounts with eksctl You must create an IAM policy that specifies the permissions that you would like the containers in your pods to have. In this workshop we will use AWS managed policy named “AmazonS3ReadOnlyAccess” which allow get and list for all S3 resources. You must also create a role for your service accounts to use before you associate it with a service account. Then you can then attach a specific IAM policy to the role that gives the containers in your pods the permissions you desire. Get ARN for AmazonS3ReadOnlyAccess:

# Get aws manged policy
$ aws iam list-policies --query 'Policies[?PolicyName==`AmazonS3ReadOnlyAccess`].Arn'
--- output
"arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess"

# This policy like this pic2

pic 2

Create an IAM role for your service accounts:

# $SA_NAME is your k8s service account name .
# $NAMESPACE is your service account in which namespaces .
# $POLICY_ARN is your want to give your service account that role can do .
# $EKS_CLUSTER_NAME is your EKS Cluster Name .
# eksctl create iamserviceaccount --name $SA_NAME --namespace $NAMESPACE --cluster $EKS_CLUSTER_NAME --attach-policy-arn $POLICY_ARN --approv--override-existing-serviceaccounts

# Now , I create a iam role have AmazonS3ReadOnlyAccess policy ,
eksctl create iamserviceaccount --name iam-test --namespace default --cluster $EKS_CLUSTER_NAME --attach-policy-arn arn:aws:iam::aws:policAmazonS3ReadOnlyAccess --approve --override-existing-serviceaccounts

--- output
[]  using region {AWS_REGION}
[]  1 iamserviceaccount (default/iam-test) was included (based on the include/exclude rules)
[!]  metadata of serviceaccounts that exist in Kubernetes will be updated, as --override-existing-serviceaccounts was set
[]  1 task: { 2 sequential sub-tasks: { create IAM role for serviceaccount "default/iam-test", create serviceaccount "default/iam-test" } }
[]  building iamserviceaccount stack "eksctl-eksworkshop-eksctl-addon-iamserviceaccount-default-iam-test"
[]  deploying stack "eksctl-eksworkshop-eksctl-addon-iamserviceaccount-default-iam-test"
[]  created serviceaccount "default/iam-test"

SPECIFYING AN IAM ROLE FOR SERVICE ACCOUNT

Specifying an IAM Role for your Service Account

In the previous step, we created the IAM role that associated with a service account named iam-test in the cluster and this has already been done for you with the service account you specified when creating the role. Be sure your service account iam-test is exist:

$ kubectl get sa
NAME               SECRETS   AGE
default            1         25h
iam-test           1         24m

Make sure your service account with the ARN of the IAM role is annotated:

$ kubectl describe sa iam-test
--- output
Name:                iam-test
Namespace:           default
Labels:              <none>
Annotations:         eks.amazonaws.com/role-arn: arn:aws:iam::${AWS_ACCOUNT_ID}:roleksctl-$EKS_CLUSTER_NAME-addon-iamserviceac-Role1-2UJ4A3H87Z59M
Image pull secrets:  <none>
Mountable secrets:   iam-test-token-5n9cb
Tokens:              iam-test-token-5n9cb
Events:              <none>

DEPLOY SAMPLE POD

Now that we have completed all the necessary configuration to run a Pod with IAM role. We will deploy sample Pod to the cluster, and run a test command to see whether it works correctly or not.

$ curl -LO https://eksworkshop.com/beginner/110_irsa/deploy.files/iam-pod.yaml
--- inside
apiVersion: apps/v1
kind: Deployment
metadata:
  name: eks-iam-test
spec:
  replicas: 1
  selector:
    matchLabels:
      app: eks-iam-test
  template:
    metadata:
      labels:
        app: eks-iam-test
    spec:
      serviceAccountName: iam-test   <-- this is we need to change in the future
      containers:
        - name: eks-iam-test
          image: sdscello/awscli:latest
          ports:
            - containerPort: 80

$ kubectl apply -f iam-pod.yaml

Exec to pod check iam role from service account

$ kubectl get pods
NAME                        READY   STATUS    RESTARTS   AGE
iam-test-xxxxxxxxxxx  1/1     Running   0          4m44s

$ kubectl exec -it  iam-test-xxxxxxxxxxx bash

root@iam-test-5f46bfb788-9fhcr:/# aws sts get-caller-identity
{
    "Arn": "arn:aws:sts::${AWS_ACCOUNT_ID}/assumed-role/eksctl-$EKS_CLUSTER_NAME-addon-iamserviceac-Role1-2UJ4A3H87Z59M",
    "Account": "${AWS_ACCOUNT_ID}",
    "UserId": "AROAUJP5OVXBK6S5OZSWR:botocore-session-1587545083"
}

##########  Default in ENV VARS #############
# AWS_WEB_IDENTITY_TOKEN_FILE=/var/run/secrets/eks.amazonaws.com/serviceaccount/token
# AWS_ROLE_ARN=arn:aws:iam::xxxxxxxxxxxx:role/XXXXXXXXXX-ROLE-XXXXXX
# you can cat 
root@iam-test-5f46bfb788-9fhcr:/# cat /var/run/secrets/eks.amazonaws.com/serviceaccount/token 

root@iam-test-5f46bfb788-9fhcr:/# aws s3 cp s3://your-bucket-name/hello.txt

To remove sample application

$ kubectl delete -f iam-pod.yaml

To remove IAM role and Service Account stack from cloudformation

$ eksctl delete iamserviceaccount --name iam-test --namespace default --cluster $EKS_CLUSTER_NAME

總結:我們知道如何不使用 worker node IAM role 的權限,限制我們的服務(pod)給與相對應的權限,也代表著 IAM policy 設計的重要性,可以給予最剛好的權限到我們的服務中。

source: https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html , https://eksworkshop.com/beginner/110_irsa/

2020年4月22日 Neil Kuan

Follow me

Here's where I hang out in social media