On this page

Overview

This guide walks you through the complete process of securing your Kubernetes Ingress using cert-manager with GlobalSign’s Atlas-ACME server and the DNS-01 challenge type. At the completion of this article, you'll learn how to: 

  • Set up a Kubernetes cluster with Kops and AWS 
  • Install and configure cert-manager 
  • Set up NGINX Ingress Controller 
  • Configure GlobalSign Atlas Issuer and Certificate using DNS-01
  • Secure an Ingress resource with a trusted TLS certificate 

What is Ingress?

Ingress exposes HTTP and HTTPS routes from outside the cluster to services within the cluster. Traffic routing is controlled by rules defined on the Ingress resource.

Here is a simple example where an Ingress sends all its traffic to one service:                 

cert-manager-http-1                        

Guidelines

  1. AWS Ubuntu EC2 Instance - Use the AWS documentation for creating Ubuntu Instance

  2. Create A User in IAM
    a. Go to IAM Console and select Users
    b. Click on create user
    c. Give a name to the user
    d. Fill the checkbox of "Provide user Access to the AWS Management Console"
        1. Select "I want to create an IAM user "
        2. In Console Password, choose "Autogenerate Password" or "Custom Password" based on your choice.
        3. Click "Next" in the bottom right corner.
    e. In Set Permissions, choose
       1. Select "Add User to a group" in case if you already have defined policies for a particular user group, otherwise choose "Attach Policies directly".
       2. In Permission Policies, provide the following permissions to the user(Note:- You can provide permissions based on your own requirements as this is just for the example purposes.)
          a. VPCFullAccess
          b. EC2FullAcces
          c. S3FullAccess
          d. Route53FullAccess
          e. IAMFullAccess
          f. Click "Next" in the bottom-right corner

Prerequisites

Ensure the following tools are installed and configured on your system: 

Install Unzip

sudo apt install unzip

Install AWS CLI

curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install

Install Helm

     curl -fsSL -o
get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3
     chmod 700 get_helm.sh
     ./get_helm.sh

There are few policies required to run the cluster successfully which should be assigned to a user and a role for the cluster:

IAM URL: https://console.aws.amazon.com/iamv2/home#/home

Create a user for k8s cluster and assign the below policies:

  1. Go to Users
  2. Add users
  3. Give a name to user
  4. Select Access key - Programmatic access
  5. Permissions
  6. Select Attach existing policies directly and select the below policies for this user.

              a.) VPC full access

              b.) EC2 full access

              c.) S3 full access

              d.) Route53 full access

              e.) IAM full access

Create a role for k8s cluster and assign the below policies:

  1. Go to IAM dashboard https://console.aws.amazon.com/iamv2/home#/home
  2. Roles
  3. Create role
  4. Form common use case select EC2 and go to next screen for permissions
  5. Select the below permissions for this user

              a.) VPC full access

              b.) EC2 full access

              c.) S3 full access

              d.) Route53 full access

              e.) IAM full access

Launch an Ec2-Instance and assign this role to the instance.

Install kubectl

# kubectl
curl -LO "https://dl.k8s.io/release/$(curl -L -
s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"

#make the downloaded file executable
chmod +x kubectl
#Move the executable to the /usr/local/bin
sudo mv kubectl /usr/local/bin 

Install kops

curl -LO https://github.com/kubernetes/kops/releases/download/$(curl -
s https://api.github.com/repos/kubernetes/kops/releases/latest | grep tag_name | cut -d '"' -
f 4)/kops-linux-amd64

#Make the binary executable
chmod +x kops-linux-amd64
#Move the executable to /usr/local/bin
sudo mv kops-linux-amd64 /usr/local/bin/kops 

In order to work further need to login with the above created programmatic user:

aws configure

#enter the Access key ID and Secret access key.

#Provide the region details i.e., us-east-1 or any other

#Give output format as "json".

#Create a S3 bucket through S3 bucket console: https://s3.console.aws.amazon.com/s3/home?region=us-east-1

#Create a private hosted zone from Route53 console: https://console.aws.amazon.com/route53/v2/home#Dashboard

#Generate public and private keys

ssh-keygen


Set Up Kubernetes Cluster 

export KOPS_STATE_STORE="s3://your-s3-bucket-name"
export MASTER_SIZE=${MASTER_SIZE:-m4.large}
export NODE_SIZE=${NODE_SIZE:-m4.large}
export ZONES="us-east-1a,us-east-1b,us-east-1c"

kops create cluster pki.atlasqa.co.uk --node-count 3 --zones $ZONES --node-size $NODE_SIZE --master-size $MASTER_SIZE --master-zones $ZONES --dns public --dns-zone pki.atlasqa.co.uk --cloud aws 

#It will describe everything that it will create within the cluster in next step kops will update the cluster and resources would be created

kops update cluster --name pki.atlasqa.co.uk --yes --admin 

#It will take around 20min to get all the resources ready within the cluster.
#Check the cluster status after 20min with below command

kops validate cluster --name pki.atlasqa.co.uk 

cert-manager-dns-1.png

The cluster is setup, there are 3 node machines running in us-east-1 region and 3 master running in us-east-1 as per the availability zones.

Install cert-manager 

kubectl create namespace cert-manager
helm install  cert-manager jetstack/cert-manager --namespace cert-manager --create-namespace  --set installCRDs=true --set 'extraArgs={--dns01-recursive-nameservers-only,--dns01-recursive-nameservers=8.8.8.8:53}'

Add the jetstack repo to helm

helm repo add jetstack https://charts.jetstack.io
helm repo update

Install Nginx-ingress-controller in namespace cert-manager and create A record to your DNS Zone

helm upgrade --install ingress-nginx ingress-nginx --repo https://kubernetes.github.io/ingress-nginx --namespace cert-manager 

Add an A record to your DNS zone

kubectl get svc -n cert-manager

The ingress-nginx controller would have the external IP, Add that IP as A record in DNS host.


 

cert-manager-dns-2.png


Configure GlobalSign Atlas-ACME Issuer 

Step 1: Set Up account binding key as a secret within Kubernetes

kubectl create secret generic eab-secret --from-literal secret=HMAC_key -n cert-manager

Step 2: Set up the GlobalSign as issuer/ClusterIssuer 

kubectl apply -f issuer.yml -n cert-manager

issuer.yml

apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
  name: issuer-gs
  namespace: cert-manager
spec:
  acme:
    server: https://*******/directory
    email: *********
    externalAccountBinding:
      keyID: ************
      keySecretRef:
        name: eab-secret
        key: secret
      keyAlgorithm: HS256
    privateKeySecretRef:
      name: account-private-key-secret
    solvers:
      - dns01:
          route53:
            accessKeyID: AKIA3UZDDYFT7EMKGS2R
            region: us-east-1
            secretAccessKeySecretRef:
              key: secret
              name: dns-secret

 

cert-manager-dns-3.png

Step 3. Create certificate resource

kubectl apply -f cert.yml -n cert-manager

cert.yml


apiVersion: cert-manager.io/v1

kind: Certificate

metadata:

  name: eab-cert

  annotations:

#    cert-manager.io/issue-temporary-certificate: "true"

#    acme.cert-manager.io/http01-edit-in-place: "true"

  namespace: cert-manager

spec:

  secretName: acme-account-secret

  duration: 2160h

  renewBefore: 360h

  commonName: pki.atlasqa.co.uk

  dnsNames:

  - pki.atlasqa.co.uk

  issuerRef:

#    name: aeg-eab

#    name: acme-issuer

    name: issuer-gs

#    kind: ClusterIssuer

    kind: Issuer

   

cert-manager-dns-4.png

Step 4. Securing ingress resource

kubectl apply -f ingress.yml -n cert-manager

ingress.yml

apiVersion: networking.k8s.io/v1

kind: Ingress

metadata:

  name: nc-s

  namespace: cert-manager

  annotations:

    cert-manager.io/issuer: issuer-gs

    kubernetes.io/ingress.class: nginx

    cert-manager.io/acme-challenge-type: dns01

#    acme.cert-manager.io/http01-edit-in-place: "true"

spec:

  rules:

#  - host: nc-s.default.svc.pki.atlasqa.co.uk

  - host: pki.atlasqa.co.uk

    http:

      paths:

      - pathType: Prefix

        path: /

        backend:

          service:

#            name: nc-s

#            port:

#              number: 16000

            name: nginx

            port:

              number: 80

  tls:

  - hosts:

#    - nc-s.default.svc.pki.atlasqa.co.uk

    - pki.atlasqa.co.uk

    secretName: eab-secret

 

cert-manager-dns-6.png

Video Demo: https://asciinema.org/a/cAbCNQskDaKkEKUOjbm2UpKY8

If all steps are followed correctly, access your domain over browser you would get your domain accessible over https protocol with GS cert.