3 minutes
Kubernetes: Cert Manager using IRSA
Creating an IAM OIDC provider for your cluster
- Requirements
- AWS CLI version Version 2.9.1 or later (version 2)
Determine whether you have an existing IAM OIDC provider for your cluster.
- Retrieve your cluster’s OIDC provider ID and store it in a variable.
oidc_id=$(aws eks describe-cluster --name my-cluster --query "cluster.identity.oidc.issuer" --output text | cut -d '/' -f 5)
- Determine whether an IAM OIDC provider with your cluster’s ID is already in your account.
aws iam list-open-id-connect-providers | grep $oidc_id
If output is returned from the previous command, then you already have a provider for your cluster and you can skip the next step. If no output is returned, then you must create an IAM OIDC provider for your cluster.
- Create an IAM OIDC identity provider for your cluster with the following command. Replace my-cluster with your own value.
eksctl utils associate-iam-oidc-provider --cluster my-cluster --approve
CERT-MANAGER INSTALLATION AND CONFIGURATION
- Create a role and attach the following policy
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "route53:GetChange",
"Resource": "arn:aws:route53:::change/*"
},
{
"Effect": "Allow",
"Action": [
"route53:ChangeResourceRecordSets",
"route53:ListResourceRecordSets"
],
"Resource": "arn:aws:route53:::hostedzone/*"
},
{
"Effect": "Allow",
"Action": "route53:ListHostedZonesByName",
"Resource": "*"
}
]
}
Config the trust policy in the role (Created in the previous step), go to “Trust relationships” tab and set the policy.
<aws-account-id>
with the AWS account ID of the EKS cluster.<aws-region>
with the region where the EKS cluster is located.<eks-hash>
runaws eks describe-cluster --name liberty-c62d9cc --query "cluster.identity.oidc.issuer" --output text | cut -d '/' -f 5
to get it<namespace>
with the namespace where cert-manager is running.<service-account-name>
with the name of theServiceAccount
object created by cert-manager.
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "sts:AssumeRoleWithWebIdentity", "Principal": { "Federated": "arn:aws:iam::<aws-account-id>:oidc-provider/oidc.eks.<aws-region>.amazonaws.com/id/<eks-hash>" }, "Condition": { "StringEquals": { "oidc.eks.<aws-region>.amazonaws.com/id/<eks-hash>:sub": "system:serviceaccount:<namespace>:<service-account-name>", "oidc.eks.<aws-region>.amazonaws.com/id/<eks-hash>:aud": "sts.amazonaws.com" } } } ] }
example:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Federated": "arn:aws:iam::123456789:oidc-provider/oidc.eks.us-east-1.amazonaws.com/id/45DABD88EEE3A227AF0FA468BE4EF0B5" }, "Action": "sts:AssumeRoleWithWebIdentity", "Condition": { "StringEquals": { "oidc.eks.us-east-1.amazonaws.com/id/45DABD88EEE3A227AF0FA468BE4EF0B5:sub": "system:serviceaccount:cert-manager:cert-manager", "oidc.eks.us-east-1.amazonaws.com/id/45DABD88EEE3A227AF0FA468BE4EF0B5:aud": "sts.amazonaws.com" } } } ] }
Install Cert Manager
- Create
cert-manager-values.yml
- Create
#cert-manager-values.yml
serviceAccount:
create: true
# this is very important, it has to be the same name as <service-account-name> value in trust relationship policy
name: cert-manager
annotations:
# role created in the step before
eks.amazonaws.com/role-arn: arn:aws:iam::168476488911:role/cert-manager
installCRDs: true
# the securityContext is required, so the pod can access files required to assume the IAM role
securityContext:
fsGroup: 1001
- Install it using helm
helm repo add jetstack https://charts.jetstack.io
helm upgrade cert-manager jetstack/cert-manager \
--install \
--namespace cert-manager \
--create-namespace \
--values "cert-manager-values.yml" \
--wait
- Define and apply
ClusterIssuer
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt
spec:
acme:
email: EXAMPLE@EXAMPLE.com
server: https://acme-v02.api.letsencrypt.org/directory
privateKeySecretRef:
name: letsencrypt
solvers:
- selector:
dnsZones:
# your hosted zone from route53
- "EXAMPLE.COM"
dns01:
route53:
region: us-east-1
- TESTING (Optional)
At this point you have to be able to generate certificates with status Ready
in True
(kubectl get certificate
pointing to the ns
where the resource is running). Create the following Ingress
to test if cert manager is working. - cert-manager.io/cluster-issuer
: the name of the ClusterIssuer
. - host
: the domain to certificate
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
# add an annotation indicating the issuer to use.
cert-manager.io/cluster-issuer: letsencrypt
name: test-ingress
namespace: default
spec:
rules:
- host: test.aaa.bbb.com
http:
paths:
- pathType: Prefix
path: /
backend:
service:
name: test-service
port:
number: 80
tls: # < placing a host in the TLS config will determine what ends up in the cert's subjectAltNames
- hosts:
- test.aaa.bbb.com
secretName: test-ingress
- References
- https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html
- https://docs.aws.amazon.com/eks/latest/userguide/enable-iam-roles-for-service-accounts.html
- https://cert-manager.io/docs/configuration/acme/dns01/route53/#eks-iam-role-for-service-accounts-irsa