An Interest In:
Web News this Week
- March 21, 2024
- March 20, 2024
- March 19, 2024
- March 18, 2024
- March 17, 2024
- March 16, 2024
- March 15, 2024
Using Lambda to Automate OIDC and IAM role for Service Account in EKS
You can automate the OIDC and IAM roles creation when you provision EKS cluster by Terraform or CloudFormatio but what if you want to automate the creation of OIDC and IAM roles when creating the EKS cluster by Rancher!
What if you want to use a crossplane to create AWS resources from a new EKS cluster, how does crossplane get access to the cluster, now we are facing a chicken-egg problem.
In this article, I am going to show you how to Automate the process once the EKS cluster is created.
We need OIDC and IAM roles to use service accounts in Kubernetes to get access to AWS resources like S3, SQS,SNS ..etc
AWS is recommended to use service accounts rather than using
static ACCESS KEY and SECRET KEY inside your pods.
In the architecture diagram when a new EKS cluster is created then it will send an event to the event bridge and then we added a rule to invoke lambda only when the event name is CreateNodegroup or DeleteCluster.
You will ask why the event name is not CreateCluster because we are interested in values after the cluster is created, the creation of the cluster takes around 8 minutes.
Steps:
1- Go to lambda service -> Create function -> Add "eks-iam" in the Function name -> Author from scratch -> choose Runtime Python 3.8 -> Create a new role with basic Lambda permissions -> Create function
2- Create IAM a policy eks-iam-policy and add the below policy
{ "Version": "2012-10-17", "Statement": [ { "Sid": "VisualEditor0", "Effect": "Allow", "Action": [ "iam:UntagRole", "iam:TagRole", "iam:CreateRole", "iam:DeleteRole", "iam:AttachRolePolicy", "iam:CreateOpenIDConnectProvider", "iam:DetachRolePolicy", "iam:ListAttachedRolePolicies", "eks:DescribeCluster", "iam:UntagOpenIDConnectProvider", "eks:ListClusters", "iam:DeleteOpenIDConnectProvider", "iam:TagOpenIDConnectProvider" ], "Resource": "*" } ]}
3- Attach the policy to the lambda Execution role, go to lambda eks-iam function -> Configuration -> Permissions -> Execution role -> click on Role name eks-iam-role-XXXX -> attach policy eks-iam-policy
4- Add the below code to eks-iam lambda function
import jsonimport boto3# in which namespace that used by the service accountnamespace = 'default'# iam policiespolicies = ['arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess']iam = boto3.client('iam')def create_role(roleName,policy): response = iam.create_role( RoleName=roleName, AssumeRolePolicyDocument=json.dumps(policy), Description='Lambda invoked by Rancher event to Create this Role', MaxSessionDuration=3600, Tags=[ { 'Key': 'Created-By', 'Value': 'Lambda' }, ] ) return responsedef lambda_handler(event, context): if event['detail']['eventName'] == "CreateNodegroup": clusterName = event['detail']['responseElements']['nodegroup']['clusterName'] eks = boto3.client('eks') eksResponse = eks.describe_cluster(name=clusterName) oidc = eksResponse['cluster']['identity']['oidc']['issuer'] # create oidc provider oidcResponse = iam.create_open_id_connect_provider(Url=oidc, ClientIDList=['sts.amazonaws.com',], ThumbprintList=['9e99a48a9960b14926bb7f3b02e22da2b0ab7280',], Tags=[{ 'Key': 'Created-By', 'Value': 'Lambda' }, ]) arn = oidcResponse['OpenIDConnectProviderArn'] policy = { "Version": "2012-10-17","Statement": [ {"Sid": "", "Effect": "Allow", "Principal": { "Federated": arn}, "Action": "sts:AssumeRoleWithWebIdentity", "Condition": { "StringEquals": { arn.split('oidc-provider/')[1] +":sub": "system:serviceaccount:" + namespace + ":" + clusterName }}}]} # create iam role createResponse = create_role (clusterName, policy) print(createResponse) # attach policies to the role for i in range(len(policies)): iam.attach_role_policy( RoleName=clusterName, PolicyArn= policies[i] ) return oidcResponse elif event['detail']['eventName'] == "DeleteCluster": clusterName = event['detail']['responseElements']['cluster']['name'] oidc = event['detail']['responseElements']['cluster']['identity']['oidc']['issuer'] accountId = event['detail']['userIdentity']['accountId'] arn = "arn:aws:iam::" + accountId + ":oidc-provider/" + oidc.split('https://')[1] # remove oidc provider oidcResponse = iam.delete_open_id_connect_provider( OpenIDConnectProviderArn=arn ) # get all policies attached to the role policyResponse = iam.list_attached_role_policies( RoleName=clusterName ) # detach all policies from the role for i in range(len(policyResponse['AttachedPolicies'])): iam.detach_role_policy( RoleName=clusterName, PolicyArn=policyResponse['AttachedPolicies'][i]['PolicyArn'] ) # remove the iam role roleResponse = iam.delete_role( RoleName=clusterName ) return oidcResponse
5- Go to EventBridge -> Rules -> Create Rule -> Rule with an event pattern -> In the Event pattern, choose Custom patterns (JSON editor) and add the following:
{ "source": ["aws.eks"], "detail-type": ["AWS API Call via CloudTrail"], "detail": { "eventSource": ["eks.amazonaws.com"], "eventName": ["CreateNodegroup", "DeleteCluster"] }}
Choose target -> AWS service -> Select a target -> Lambda function -> Function -> eks-iam
6- Create a service account in your EKS cluster, now we can know the arn of our IAM role because you only change the EKS-CLUSTER-NAME.
Hint: I assumed you have a unique name for EKS clusters
---apiVersion: v1kind: ServiceAccountmetadata: name: list-s3 namespace: default annotations: eks.amazonaws.com/role-arn: arn:aws:iam::AWS-ACCOUNT-NUMBER:role/EKS-CLUSTER-NAME
7- Create a deployment and define the service account name like the example below
---apiVersion: apps/v1kind: Deploymentmetadata: name: aws-cli namespace: defaultspec: selector: matchLabels: app: aws-cli replicas: 1 template: metadata: labels: app: aws-cli spec: serviceAccountName: list-s3 containers: - name: aws-cli image: amazon/aws-cli command: [ "/bin/bash", "-c", "--" ] args: [ "while true; do sleep 30; done;" ]
now you can access your pod and test it by:
aws s3 ls
In the end, you can have a default policy that is attached for each EKS cluster and then use tools like crossplane to create a specific IAM policies and roles.
Original Link: https://dev.to/aws-builders/using-lambda-to-automate-oidc-and-iam-role-for-service-account-in-eks-c0e
Dev To
An online community for sharing and discovering great ideas, having debates, and making friendsMore About this Source Visit Dev To