On this page

Overview

This guide walks you through the complete process of securing an AWS EKS Kubernetes Ingress resource with a trusted TLS certificate from GlobalSign using Cert-Manager and the GlobalSign Atlas Issuer plugin.  At the completion of this article, you'll learn how to: 

  • Set up IAM roles and permissions
  • Create and configure an EKS cluster
  • Install and configure cert-manager with Atlas plugin
  • Set up NGINX Ingress Controller
  • Configure GlobalSign Issuer and Certificate
  • Secure an Ingress resource with a 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.png

Prerequisites

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

  • AWS Account

  • Nginx Ingress

  • One Valid Domain Name

  • Kubectl

  • Helm Package Manager

  • Cert-manager & its CRDs

  • Cert-manager-Atlas Plugin

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".

        i. Select I want to create an IAM user.

        ii. In Console Password, choose Autogenerate Password or Custom Password based on your preference.

        iii. Click Next in the bottom right corner.

    e. In Set Permissions, choose:

       i. Select Add User to a group in case if you already have defined policies for a particular user group, otherwise choose Attach Policies directly.

       ii. 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.

         - AdministratorAccess

         - AmazonEC2FullAccess

         - AmazonEKSClusterPolicy

         - AmazonEKSServicePolicy

         - AmazonEventBridgeFullAccess

         - AmazonRoute53FullAccess

         - AmazonVPCFullAccess

         - AWSCloudFormationFullAccess

         - IAMFullAccess

    iii. Click Next in the bottom-right corner.

    iv. Review your User Permissions and Policies.

    v. Retrieve Login URL and Password.

  3. Provide programmatic access to your user. 

    a. Go to IAM, then users.

    b. Select your created user.

    c. Select Security Credentials.

    d. Go to Access Keys in your Security Credentials and choose Create Access Key.

    e. Go to the Use Case and select AWS CLI.

    f. Click Next, then Create Access Key.

    g. You will get your Programmatic Access Keys from here.
  4. Connect to your AWS ec2  instance which you have created in the Step 1.
  5. Once you are logged in to your instance, install the following tools:

    a. Install Unzip.

    sudo apt install unzip

    b. Configure AWS CLI.

    curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
    unzip awscliv2.zip
    sudo ./aws/install
  6. Configure AWS CLI with the following commands and the programmatic access keys created in Step 3. 

    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".
    #Generate public and private keys
    ssh-keygen
  7. 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
  8. Install kubectl and eksctl (tools to manage and interact with the kubernetes cluster).

    a. Install the latest version of kubectl:

    curl -LO"https://dl.k8s.io/release/$(curl -L -shttps://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


    b. Install the latest version of eksctl:

    #for ARM systems, set ARCH to: arm64, armv6 or armv7
    ARCH=amd64
    PLATFORM=$(uname -s)_$ARCH
    curl -sLO "https://github.com/eksctl-io/eksctl/releases/latest/download/eksctl_$PLATFORM.tar.gz"
    #(Optional) Verify checksum
    curl -sL "https://github.com/eksctl-io/eksctl/releases/latest/download/eksctl_checksums.txt" | grep $PLATFORM | sha256sum --check
    tar -xzf eksctl_$PLATFORM.tar.gz -C /tmp && rm eksctl_$PLATFORM.tar.gz
    sudo mv /tmp/eksctl /usr/local/bin
  9. Create the cluster with 3 worker node and 1 master node with the below command.

    eksctl create cluster --name test-cluster --version 1.29 --region eu-west-1 --nodegroup-name linux-nodes --node-type m4.large --nodes 3

    cert-manager-atlas-issuer1.png


    It will take around 10 to 15 mins for cluster to be ready to use. After the said time, you can check the status of the cluster by running the below command:

    eksctl get cluster --region eu-west-1

    cert-manager-atlas-issuer2.png


    When the cluster is ready with 3 node machines running in eu-west-1 region and 1 master running in eu-west-1 as per the availability zones.
  10.  Install Cert-manager and its CRDs.

    a. Add and update the Jetstack Helm repository.

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

    b. Install the Cert-manager and it’s CRDs using the following command:

    kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.15.1/cert-manager.yaml

    c. Install the GlobalSign's Certmanager-Atlas CRD. Once installed, then it is ready to handle Atlas Certificate requests.

    kubectl apply -f https://github.com/globalsign/atlas-cert-manager/releases/download/v0.0.1/install.yaml
  11.  Label the cert-manager namespace to disable resource validation

    kubectl label namespace cert-manager certmanager.k8s.io/disable-validation=true
  12.  Install Nginx-ingress-controller in namespace cert-manager. 

    helm upgrade --install ingress-nginx ingress-nginx --repo https://kubernetes.github.io/ingress-nginx --namespace cert-manager
    kubectl get svc -n cert-manager
  13.  Create A record in your Route 53 to the Hosted Zone for the below created Load Balancer IP. Note: The cluster IP is 10.100.96.178.

    cert-manager-atlas-issuer3.png
  14.  As soon as the ingress-nginx-controller get the EXTERNAL-IP value with extension *.eu-west-1.elb.amazonaws.com, add this value as A record into hosted zone. It would be in the sync within 60sec. Note: Before creating the hosted zone kindly make sure you have the valid domain.
  15.  Creating A record over AWS Route53

    a. Go to https://us-east-1.console.aws.amazon.com/route53/v2/home?region=eu-west-1#Dashboard and click on Hosted zones

    b. Click on Create hosted zone.

    c. Enter the name followed by your actual domain name and make sure the Public hosted zone should be selected.

    d. After creating the hosted zone, get NS record along with SOA record. Then, add the NS records into your domain registrar.

    e. After adding the NS into domain registrar, your hosted zone is now ready to accept traffic. You can now create the A record into the hosted zone:

       i. Into your hosted zone, click on Create record.

       ii. In the next screen, make sure that Record Type is "A" and Alias are selected. Also, make sure that Route traffic to, Alias to Application and Classic Load Balancer are selected. After selecting the required fields, click Create records.

    iii. The record would be created and it would take around 60sec to get in the sync.
  16.  Create GlobalSign Issuer to issue a TLS certificate for your Ingress with the following steps.

    a. Create a secret to store the GlobalSign's ATLAS account api_key, secrets along with mTLS and private key. Note: You can get these API credentials from GlobalSign Team.

    kubectl create secret generic issuer-credentials --from-literal=apikey=$API_KEY --from-literal=apisecret=$API_SECRET --from-literal=cert="$(cat mTLS.pem)" --from-literal=certkey="$(cat privatekey.pem)" -n cert-manager

    b. Create an Issuer of GlobalSign.

    cat < apiVersion: hvca.globalsign.com/v1alpha1
    kind: Issuer
    metadata:
      name: gs-issuer
      namespace: cert-manager
    spec:
      authSecretName: "issuer-credentials"
      url: "https://emea.api.hvca.globalsign.com:8443/v2"
    EOF


    c. Create Certificate Resource with the following configuration:

    cat < apiVersion: cert-manager.io/v1
    kind: Certificate
    metadata:
      name: pki.atlasqa.co.uk
      namespace: cert-manager
    spec:
      # Secret names are always required.
      secretName: www.atlasqa.co.uk
     
      duration: 2160h # 90d
      renewBefore: 360h # 15d
      subject:
      #  organizations:
      #    - jetstack
      # The use of the common name field has been deprecated since 2000 and is
      # discouraged from being used.
      commonName: pki.atlasqa.co.uk
      isCA: false
      privateKey:
        algorithm: RSA
        encoding: PKCS1
        size: 2048
      usages:
        - server auth
        #- client auth
      # At least one of a DNS Name, URI, or IP address is required.
    #  dnsNames:
    #    -
    #www.atlasqa.co.uk
      # Issuer references are always required.
      issuerRef:
        name: gs-issuer
        # We can reference ClusterIssuers by changing the kind here.
        # The default value is Issuer (i.e. a locally namespaced Issuer)
        kind: Issuer
        # This is optional since cert-manager will default to this value however
        # if you are using an external issuer, change this to that issuer group.
        group: hvca.globalsign.com
    EOF


    d. At times the certificate object can take couple of seconds to become ready.

    cert-manager-atlas-issuer4.png
  17.  Secure nginx ingress resource using the below configuration:

    cat < apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: nginx
      namespace: cert-manager
      annotations:
        cert-manager.io/issuer: GS-issuer
        kubernetes.io/ingress.class: nginx
    spec:
      tls:
        - hosts:
            - pki.atlasqa.co.uk
          secretName: www.atlasqa.co.uk
      rules:
        - host: pki.atlasqa.co.uk
          http:
            paths:
              - path: /
                pathType: Prefix
                backend:
                  service:
                    name: example-service
                    port:
                      number: 80
    EOF
  18.  The ingress resource that has been created could take up to 1min to get the load balancer URL as ADDRESS.

    cert-manager-atlas-issuer5.png