In this blog post we will take a look of a native-AWS way to attach an IAM role into the Kubernetes POD, without third party software, such as kube2iam and kiam. This is possible thanks to the integration between AWS IAM and Kubernetes ServiceAccount, following the approach of IAM Roles for Service Accounts (IRSA).
There are many benefits of using IRSA with Kubernetes PODs
- Granular restriction (per cluster, per namespace, etc.)
It’s also possible to not use it - More flexible than the other tools
- One less point of failure (maybe a few lesser)
- Lesser resources consumption
- Implementing best practice, there are more pods per worker node
- Latency may reduce by ~50ms
Especially for the first request - Prevent issues with caching the credentials
This software takes a few minutes to update its cache. - Better auditing
Instead of checking the logs of kube2iam/kiam pods, you can check AWS CloudTrails - Easier to set up
- AWS provides full support
There are a few pre-requirements that are needed to use the IAM role in a POD.
- An IAM OpenID Connect provider pointing to the AWS EKS OpenID Connect provider URL
- AWS EKS cluster 1.13 or above
- A trust relationship between your IAM Role and the OpenID Provider
To illustrate all of these items and to follow security best practices, an Amazon Elastic Kubernetes Service cluster was created by the following cluster.yaml file:
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig
metadata:
name: demo-k8s
region: us-east-1
version: "1.28"
vpc:
id: vpc-xxxxxxxx
cidr: "172.31.0.0/16"
subnets:
private:
us-east-1a:
id: "subnet-xxxxxxxx"
cidr: "172.31.48.0/20"
us-east-1b:
id: "subnet-xxxxxxxx"
cidr: "172.31.0.0/20"
us-east-1c:
id: "subnet-xxxxxxxx"
cidr: "172.31.16.0/20"
nodeGroups:
- name: linux-node
instanceType: t2.micro
desiredCapacity: 2
volumeSize: 8
ssh:
allow: true
privateNetworking: true
availabilityZones: ["us-east-1a", "us-east-1b", "us-east-1c"]
eksctl create cluster -f cluster.yaml
Furthermore, we will follow these steps:
- Create an AWS OpenID Connect provider
- Link the OIDC provider to the EKS OIDC URL
- Create an IAM Role
- Create an IAM Policy (only via terraform)
- Attach the IAM Policy to the IAM Role
- Set up the Trust Relationship, adhering to security best practices, between the IAM Role and the OpenID Connect provider in the Amazon Elastic Kubernetes Service
- Create a Kubernetes ServiceAccount
Amazon AWS EKS Security Best Practices and Tools
The tools that are going to be used are AWS cli, eksctl, kubectl and AWS console.
With this command aws eks describe-cluster –name demo-k8s –query “cluster.identity.oidc.issuer” we are going to check the existing EKS cluster OIDC URL.
The output is https://oidc.eks.us-east-1.amazonaws.com/id/<OIDC_ID>
After that, with command aws iam list-open-id-connect-providers we are listing the existing IAM OIDC providers. If <OIDC_ID> from the previous command is not included, we will associate it with this command: eksctl utils associate-iam-oidc-provider –region=us-east-1 –cluster=demo-k8s –approve.
Furthermore, from AWS console we are creating an IAM policy with minimal permissions on EKS cluster, i.e. list and read.
Then, the IAM role will be created by the eksctl and attach the pre-existing policy <POLICY_NAME> into it.
eksctl create iamserviceaccount ^
--cluster=demo-k8s ^
--role-name=pod-creator ^
--namespace=default ^
--name=svc-test ^
--attach-policy-arn=arn:aws:iam::xxxxxxxx:policy/test-k8s-read-policy ^
--approve
After this, we have created an IAM ServiceAccount, default/svc-test for the default namespace and use it in a pod creation yaml.
Also, from AWS console can be checked the existence of an IAM role.
This is a very simple example for a pod definition:
apiVersion: v1
kind: Pod
metadata:
name: amazonlinux
namespace: default
spec:
serviceAccountName: svc-test
containers:
- name: amazonlinux
image: amazonlinux
command: [ "sh", "-c", "sleep 8h" ]
kubectl apply -f pod.yaml
pod/amazonlinux created in the Kubernetes cluster.
With the command, kubectl get pods/amazonlinux-o yaml a serviceAccount name can be checked, in our case svc-test.
Why an IAM Role for EKS?
For several reasons, creating an IAM (Identity and Access Management) role for Amazon EKS (Elastic Kubernetes Service) is important. It primarily conforms to the principle of least privilege and follows security best practices, which enhances the overall security of your Amazon Elastic Kubernetes Service infrastructure. You reduce potential risks and vulnerabilities by granting only the necessary permissions.
Furthermore, the integration of IAM Roles with EKS is effortless and robust, especially considering its compatibility with other AWS services. This collaboration under the shared responsibility model ensures AWS is responsible for a consistent and comprehensive security framework across your entire cloud environment, specifically your Amazon Elastic Kubernetes Service.
One of the primary benefits is the ability to customize permissions for your EKS nodes. This customization allows you to precisely customize access rights to the needs of your application, giving you granular control. The whole process can be automated with the Infrastructure as a Code tools, like Terraform.
Conclusion
Conclusively, IAM Roles following the security best practices are the first and most important step in securing our Kubernetes deployment on the Amazon Elastic Kubernetes Service. They follow the principle of least privilege, providing a fundamental level of protection against potential threats. Additionally, their adaptability enables us to adapt security measures to the specific needs of our environment. However, in best practice, it is critical to understand that, while IAM Roles are an important starting point in the shared responsibility model, ongoing customization is essential. This adaptability ensures that our security strategy remains dynamic and effective in dealing with a constantly changing landscape of potential threats. In essence, IAM Roles are the foundation upon which we continuously build and refine our Kubernetes security framework.