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角色功能具有以下優點:
- 最低特權 (Least privilege) -通過使用IAM角色提供服務帳戶功能,您不再需要為工作節點IAM角色提供擴展權限,以便該節點上的Pod可以調用AWS API。 您可以將IAM權限限定在服務帳戶上,只有使用該服務帳戶的Pod才能訪問這些權限。 此功能還消除了對諸如
kiam
或kube2iam
之類的第三方解決方案的需求。 - 憑證隔離 (Credential isolation ) - 容器只能檢索與其所屬的服務帳戶關聯的IAM角色的憑據。 容器永遠無法訪問用於屬於另一個容器的另一個容器的憑據。
- 可審核性 ( Auditability ) - 可通過CloudTrail獲得訪問和事件日誌,以幫助確保進行追溯審核。
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:
- Java (Version 2) — 2.10.11
- Java — 1.11.704
- Go — 1.23.13
- Python (Boto3) — 1.9.220
- Python (botocore) — 1.12.200
- AWS CLI — 1.16.232
- Node — 2.521.0
- Ruby — 2.11.345
- C++ — 1.7.174
- .NET — 3.3.659.1
- PHP — 3.110.7
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
- The IAM roles for service accounts feature is available on new Amazon EKS Kubernetes version 1.14 clusters, and clusters that were updated to versions 1.14 or 1.13 on or after September 3rd, 2019.
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
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
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
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