How-To: Configure Azure AD as an OIDC Identity Provider for EKS
Problem statement
The problem statement for this piece of work was as follows:
As a platform engineer
I want our to provide other engineers with EKS access securely
So that we can easily audit usage and simplify off-boarding
Glossary
Before we go any further I think its important to have a glossary of terms to aid understanding, so here we go …
- OIDC — OpenID Connect, for more information see here.
- Azure AD — Azure Active Directory, for more information see here.
aad
— An abbreviation for Azure Active Directory.
Implementation
The following section lists the steps required to implement this configuration, the order is important!
1. Azure configuration
We firstly need to configure the Azure side of the house, this is honestly where the majority of the configuration happens and the order of these steps is extremely important.
1.1 Enterprise Application to be used as the OIDC identity provider
- Login to Azure AD portal as user that has sufficient permission to create Azure AD application and manage permission and select Azure Active Directory from Azure Services.
- From the sidebar click on Enterprise Application
- From the top click on New Application> Create your own application
This will open a wizard to create an Azure AD Application, provide a name for your application and click create.
1.2 Registered Application (#1)
Secondly, we now need to configure the application registration that is automatically created when we created the Enterprise Application above.
Navigate back to Azure Active Directory
From the sidebar click on “App registrations”
Select the name of the application you configured in part 1.1
Click authentication on the left hand sub navigation menu
Under Redirect URIs simply add http://localhost (see below)
Make sure ID tokens is checked (see below)
Make sure Allow public client flows is set to yes (see below)
Click Save
From the sidecar click on “Token configuration”
From the top click on “Add group claims”
Make sure the following are selected
From the sidecar click on “API permissions”
Click on “Add new permission”
Click on “APIs my organization uses”
Search for AWS-EKS-SSO
and add the permission, you should now see your Enterprise application added (see example below).
From the sidecar click on “Certificates & secrets”
Click on “New client secret”
Name the secret AWS-EKS-SSO
give it an expiry of 24 months.
🚨Make a note of the secret value, we are going to need it later 🚨
1.3 Registered Application (#2)
Finally, we need to configure a brand new application to act as our client when interacting with kubectl
.
Login to Azure AD portal as user that has sufficient permission to create Azure AD application and manage permission and select Azure Active Directory from Azure Services.
From the sidebar click on App registrations
From the top click on New registration
Give it a name of AWS-EKS-KUBECTL
Click authentication on the left hand sub navigation menu
Under Redirect URIs simply add http://localhost (see below)
Make sure ID tokens is checked (see below)
Make sure Allow public client flows is set to yes (see below)
Click Save
2. EKS configuration (via Terraform)
I am used to leveraging Terraform to configure AWS infrastructure to the steps below detail the Terraform configuration required to implement OIDC on our EKS cluster.
variable "oidc_configuration" {
description = "The configuration for the OIDC provider."
type = object({
client_id = string
groups_claim = string
groups_prefix = string
issuer_url = string
provider = string
username_claim = string
username_prefix = string
}) default = {
client_id = "XXX-XXX-XXX-XXX-XXX" # AWS-EKS-SSO app id
groups_claim = "groups"
groups_prefix = "aad:"
issuer_url = "https://sts.windows.net/<tenant_id>/"
provider = "AzureAD"
username_claim = "upn"
username_prefix = "aad:"
}
}
The client_id
above is the application ID of our AWS-EKS-SSO
registered application configured as part of our Azure setup above.
The tenant_id
above is your organisations tenant ID within Azure, see Directory (tenant) id
on either of the registered applications configured as part of our Azure setup above.
The
/
at the end ofissuer_url
is extremely important it needs to be there!
We now need to add the identity provider resource (see below)
resource "aws_eks_identity_provider_config" "eks_identity_provider" {
cluster_name = aws_eks_cluster.eks.name
oidc {
client_id = var.oidc_configuration["client_id"]
groups_claim = var.oidc_configuration["groups_claim"]
groups_prefix = var.oidc_configuration["groups_prefix"]
identity_provider_config_name = var.oidc_configuration["provider"]
issuer_url = var.oidc_configuration["issuer_url"]
username_claim = var.oidc_configuration["username_claim"]
username_prefix = var.oidc_configuration["username_prefix"]
}
timeouts {
create = "2h"
delete = "2h"
}
}
The timeouts
here were important because the defaults didn’t seem long enough for me to get the configuration to complete successfully.
3. ClusterRole/Role bindings
We now need to add ClusterRoleBindings or RoleBindings to the cluster so that once we authenticate we have access to interact with the cluster, an example of this can be seen below.
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: sso-platform-engineering-admin
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: Group
name: aad:<group id> # aws-pe-admins group ID in Azure
The group name needs to be prefixed with aad:
here to match the prefix we added as part of the EKS configuration in section 2 of this implementation.
I advise prefixing any ClusterRole/Role bindings with sso-
to make it firstly bunch all bindings together when listing them as well as making it explicitly obvious you have to be using SSO to leverage these.
4. Configuring kubectl
In order to authenticate I used https://github.com/int128/kubelogin.
Firstly you need to install the plugin, I just krew and executed:
kubectl krew install oidc-login
Secondly, you need to authenticate using the following command:
kubectl oidc-login setup \
--oidc-issuer-url https://sts.windows.net/<tenant_id>/ \
--oidc-client-id YOUR_CLIENT_ID \
--oidc-client-secret YOUR_CLIENT_SECRET
Note: The secret is the value from section 1.2 of this blog post
The above command outputs your JWT token to validate you’ve successfully authenticated with Azure. Next you need to add the following to your kubeconfig file located at ~/.kube/config
users:
- name: oidc
user:
exec:
apiVersion: client.authentication.k8s.io/v1beta1
command: kubectl
args:
- oidc-login
- get-token
- --oidc-issuer-url=https://sts.windows.net/<tenant_id>/
- --oidc-client-id=YOUR_CLIENT_ID
- --oidc-client-secret=YOUR_CLIENT_SECRET
Note: The secret is the value from section 1.2 of this blog post
You can increase the log level by adding a -v1
argument above.
You should now be able to interact with EKS using the following …
kubectl --user=oidc <commands>
For example
kubectl --user=oidc get nodes
Summary
This blog post hopefully captures the steps required to configure Azure Active Directory as an OIDC identity provider to our EKS cluster(s).
Please feel free to add comments/suggestions for improving the kubectl configuration if you have them as this configuration is completely new to me. In the past I used Dex and Gangway to obtain a kubeconfig file.