Configuring EKS for IAM (OIDC) using CloudFormation
Creating and applying an OIDC provider to an EKS cluster using a CloudFormation template
Posted by Harry Lascelles on March 5, 2020
The state of play
With the introduction of IAM roles for Service Accounts
AWS has made it easy to assign IAM roles to individual pods using the eks.amazonaws.com/role-arn
annotation to pod service accounts. However to make this work, the cluster first needs to have an
OpenID Connect (OIDC) Provider configured. This configuration could be done manually using the
console or via SDK/CLI scripts, but then operational audit, resource ownership, and
environment teardown semantics are lost. We want config as code.
This blog post will show you how to configure an OIDC provider for an existing EKS cluster using a
single CloudFormation template. It will roll up the multiple command line steps from the AWS guide
into CustomResources
that will do the configuration for you, and return the URL required to
apply to the role.
Other guides exist to show you how this can be done with Terraform and eksctl, so if you are using those tools to manage your infrastructure, you may want to start there.
The repository for the finished template, and the testing resources can be found here: https://github.com/bambooengineering/example-eks-oidc-iam-cloudformation.
Template overview
You can find the full template to download and use in the repo here. It has the following high level structure.
---
Parameters:
EKSClusterName:
... The name of the cluster to configure (not the full arn).
Resources:
ClusterOIDCURL:
... The CustomResource that manages the queries to the cluster for its OIDC URL by using the ClusterOIDCURLFunction.
We need this URL to configure the OIDC provider and apply it to namespace constraints in the
IAM role.
ClusterOIDCURLFunction:
... The lambda that will query the cluster for the URL.
ClusterOIDCProvider:
... The CustomResource that will invoke the ClusterOIDCProviderFunction to create the provider.
ClusterOIDCProviderFunction:
... The lambda that actually creates and deletes the provider.
ClusterOIDCLambdaExecutionRole:
... The role that gives the stack sufficient permissions to create the OIDC provider.
It is only used during lifecycle operations of this stack.
Outputs:
ClusterOIDCURL:
... The OpenID Connect URL (without protocol). This must be used later in the pod IAM roles.
Prerequisites
Before you apply the template:
- You will need a running EKS cluster to apply the template to. If you do not have one, you can create
one for testing using eksctl with
eksctl create cluster
. - Your cluster must be 1.14 or above, and have been upgraded / created after September 2019.
- You absolutely must ensure the
aws-cli
oraws-sdk
version used inside your business logic pods is high enough. See here for a list of versions supported. This is one of the main reasons your pod may simply (and silently) fail to obtain credentials.
The show comes to town
Once you have downloaded the template oidc-provider.yaml, you can configure your cluster with one command:
# Assign your cluster name to an ENV here (the short name, not the full ARN).
# Note, this cluster must already exist. You can create one to test with by using
# `eksctl create cluster`
# => "curious-badger-1585558460" or similar.
CLUSTER_NAME=<NAME>
# Create the OIDC stack. Make sure the stack and the cluster are in the same region.
aws cloudformation create-stack \
--capabilities CAPABILITY_NAMED_IAM \
--stack-name ${CLUSTER_NAME}-oidc \
--parameters ParameterKey=EKSClusterName,ParameterValue=${CLUSTER_NAME} \
--template-body file://oidc-provider.yaml
After a few seconds that stack will create the required resource: an OIDC Provider. You will be able to see it in your AWS console in the IAM section here.
It will also add the cluster
OIDC URL to the Outputs
of the stack without the "https://" prefix, which makes it easy for
applying to any roles you want to then create. You can then wait for it to finish and view the
output thus:
# View the OIDC URL:
OIDC_URL=$(aws cloudformation describe-stacks --stack-name ${CLUSTER_NAME}-oidc \
--query "Stacks[0].Outputs[?OutputKey=='ClusterOIDCURL'].OutputValue" \
--output text)
echo "OIDC_URL is ${OIDC_URL}"
That's it! Your cluster is now configured. You deserve a beer.
CloudFormation all the way
This guide allows you to configure your EKS clusters to use OIDC, and thus IAM roles, using a single CloudFormation template.
In my next post I will show how pod IAM roles can (and should) be constrained by namespace and service account, again using CloudFormation.
See part 2: Creating EKS IAM roles using CloudFormation.
Good luck on your Kubernetes journey!