DNS Challenge on Route53

Configure cert-manager with Route53 dns-01 challenge for Let's Encrypt certs

If your cluster isn't publicly accessible, you can use DNS validation with Let's Encrypt.
This documentation is based on https://cert-manager.io/docs/configuration/acme/dns01/route53/.

Use these instructions for a Hydrolix deployment running k8s cert-manager to acquire a certificate from Let's Encrypt using the DNS challenge when authoritative DNS is hosted on AWS Route53.

Prerequisites

  • A Hydrolix cluster running k8s cert-manager deployed on AWS
  • A Route53 managed DNS zone for the Hydrolix cluster hostname
  • AWS CLI installed on your local machine

Create the Policy

Create a new policy, named ${HDX_KUBERNETES_NAMESPACE}-route53, which allows route53 record changes:

{
  "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": "*"
    }
  ]
}

Run the following command to create the policy with the AWS CLI:

aws iam create-policy --policy-name "${HDX_KUBERNETES_NAMESPACE}-route53" --policy-document ${HDX_KUBERNETES_NAMESPACE}-route53

Attach that policy to the service account used by the Hydrolix cluster:

aws iam attach-role-policy --role-name "${HDX_KUBERNETES_NAMESPACE}-bucket" \
    --policy-arn="arn:aws:iam::${AWS_ACCOUNT_ID}:policy/${HDX_KUBERNETES_NAMESPACE}-route53"

Create an Issuer CRD

In TLS ecosystem, an issuer is an entity capable of issuing certificates, more commonly, a Certification Authority (CA). The cert-manager software uses an Issuer Custom Resource Definition (CRD)to configure how to interact with any CA.

Create an Issuer CRD describing the Let's Encrypt production CA with the following required elements:

  • name - display name of the issuer or CA
  • server - the ACME server URL of the CA
  • email - email presented to the ACME API
  • solvers - preferred configuration for responding to the ACME challeng

Each solver has slightly different configuration. See configuration examples.

For further detail, see Issuer Configuration.

The following configuration example generates a certificate using Let's Encrypt to validate the domain ownership using DNS and manages the creation of the proof via route53:

apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
  name: letsencrypt-production-route53
  namespace: ${HDX_KUBERNETES_NAMESPACE}
spec:
  acme:
    server: https://acme-v02.api.letsencrypt.org/directory
    email: ${HDX_ADMIN_EMAIL}
    privateKeySecretRef:
      name: letsencrypt-production-route53
    solvers:
    - selector:
        dnsZones:
          - "${MANAGED_DNS_ZONE_NAME_AT_ROUTE53}"
      dns01:
        route53:
          region: ${MANAGED_DNS_ROUTE53_REGION_NAME}
          hostedZoneID: ${MANAGED_DNS_ROUTE53_ZONE_ID}

Store the configuration in the file issuer-prod-lets-enc-route53.yaml. Use the following command to deploy it to your cluster:

kubectl apply -f issuer-prod-lets-enc-route53.yaml

Create a Certificate CRD

After deploying your certificate Issuer, create a new Certificate which manages the lifetime of certificate contents, secrets, and related status information when interacting with the CA.

The Certificate CRD contains the information required to generate and send a Certificate Signing Request (CSR), and will also store a successfully acquired TLS certificate and its private key in the configured secret.

  • metadata.name and metadata.namespace - the Kubernetes namespace in which the Hydrolix cluster runs
  • spec.issuerRef.name - the name of the Issuer CRD to use for acquiring this certificate
  • commonName - the primary name on the certificate
  • dnsNames - a list of Subject Alternate Names (SANs) to include on the certificate, should always include at least the commonName
  • spec.secretName - where to store the certificate and corresponding TLS private key

Hydrolix requires the certificate to be stored into the secretName: traefik-tls. This is the default location used by the reverse proxy when loading a certificate.

Here's a configuration example:

apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: ${HDX_KUBERNETES_NAMESPACE}
  namespace: ${HDX_KUBERNETES_NAMESPACE}
spec:
  secretName: traefik-tls
  issuerRef:
    name: letsencrypt-production-route53
  commonName: ${myhost}.hydrolix.live
  dnsNames:
  - ${myhost}.hydrolix.live

After creating this Certificate CRD in yaml file cert-req.yaml, deploy to your cluster:

kubectl apply -f cert-req.yaml

Check the certificate status

Once applied, you can check the certificate status with the following command:

kubectl describe certificate ${HDX_KUBERNETES_NAMESPACE}

If the CA can validate ownership, you can should see the following:

Normal  Issuing    12s   cert-manager-certificates-issuing          The certificate has been successfully issued

Enable TLS

Once the certificate is deployed, enable TLS for network services by changing the protocol in the hydrolix_url in your Hydrolix spec from http to https:

hydrolix_url: https://${myhost}.hydrolix.live

After changing the protocol, traefik should restart and use the new certificate.

See also Enable TLS.