Automatic Certificate Management Environment (ACME) is a protocol for automating issuance of X.509 certificates. With the ACME protocol, a certificate authority (CA) automatically verifies that a certificate applicant has ownership of a domain and then issues a certificate for the applicant. Let's Encrypt is a non-profit public CA that uses the ACME protocol to issue certificates that are trusted by most browsers. This topic describes how to use cert-manager together with Let's Encrypt to issue a browser-trusted HTTPS certificate for a Service Mesh (ASM) ingress gateway.
Prerequisites
A Container Service for Kubernetes (ACK) cluster is added to an ASM instance of V1.16 or later. For more information, see Add a cluster to an ASM instance and Update an ASM instance.
An ingress gateway is deployed and ports 80 and 443 are exposed. For more information, see Create an ingress gateway.
An HTTPBin application is deployed in the ACK cluster that is added to the ASM instance. For more information, see Deploy the HTTPBin application.
cert-manager is installed. For more information, see Install cert-manager in your cluster.
Ingress API access is enabled for the ASM ingress gateway. For more information, see Step 1: Enable Ingress on the ASM gateway.
ACME in cert-manager
When you use cert-manager, an ACME Issuer registers accounts with CA servers that support the ACME protocol. When you create an ACME Issuer resource, cert-manager will generate a private key for you. This private key is used for secure communication with ACME CA servers. Certificates issued by public CAs such as Let's Encrypt are typically trusted by web browsers on clients. This means that when users visit your website through browsers, their browsers automatically trust the Secure Sockets Layer (SSL) and Transport Layer Security (TLS) certificates of your website. The primary purpose of a certificate issued by a public CA is to prove to a browser that the current server is a legitimate service provider for the domain. For this reason, the public CA needs to verify that the server applying for a certificate actually owns the domain before it issues the certificate. For more information about the ACME protocol, see Automatic Certificate Management Environment.
Solve challenges
Challenges are a key mechanism used by the ACME protocol to validate that a certificate applicant owns the domain in a certificate. In the process of applying for a certificate, the ACME CA server requires that the client (certificate applicant) complete specific challenges to ensure that only the legitimate owner of the domain can successfully apply for the corresponding certificate. This improves network security and prevents the risk of impersonation of the domain. cert-manager supports the following main challenge types: HTTP-01 challenges and DNS-01 challenges.
HTTP-01 challenges are completed by presenting a computed key. The key is present at an HTTP URL endpoint and is routable over the Internet. This URL uses the domain requested for the certificate. After the ACME server can get this key from this URL over the Internet, the ACME server can validate that the applicant is the owner of this domain. When an HTTP-01 challenge is created, cert-manager automatically configures your cluster ingress to route traffic for this URL to a small web server that presents this key. The small web server responds to the challenge validation requests initiated by the ACME server by returning this key.
DNS-01 challenges are completed by providing a computed key that is present in a Domain Name System (DNS) TXT record. After this TXT record has been propagated across the Internet, the ACME server can successfully retrieve this key via a DNS lookup and can validate that the applicant owns the domain for the requested certificate. With appropriate permissions, cert-manager automatically presents this TXT record for the DNS provider.
In real-world use scenarios, you need to check whether your current CA supports the ACME protocol. If your CA supports the ACME protocol, your ASM ingress gateway can use cert-manager to automatically obtain a certificate from the CA. For example, Sectigo supports the ACME protocol. The way how Sectigo works is similar to that described in this topic. For more information, see Overview.
Step 1: Prepare a public domain
To use Let's Encrypt to issue a certificate for a domain, you must have a public domain and point the public domain to the ASM ingress gateway that you want to use. For more information, see the documentation of your DNS provider. If you are using Alibaba Cloud DNS, see Add a DNS record. For more information about Let's Encrypt, see Getting Started.
Step 2: Create an Issuer resource to connect cert-manager to Let's Encrypt
Use the kubeconfig file of the ACK cluster on the data plane that you added to the ASM instance and then create the resource shown in the following code block:
apiVersion: cert-manager.io/v1 kind: Issuer metadata: name: letsencrypt-prod-issuer namespace: istio-system spec: acme: email: 'te**@mail.com' # This field is optional but we recommend that you specify this field. The ACME server may send you important certificate-related notifications through this email. privateKeySecretRef: name: letsencrypt-prod server: https://acme-v02.api.letsencrypt.org/directory solvers: - http01: ingress: ingressClassName: istio
The preceding Issuer resource specifies a Solver of the
http01
type. Ingress API access is enabled and the value of theingressClassName
field isistio
. The following steps explain how this Solver takes effect.Notecert-manager supports two types of Solvers: Ingress API and Gateway API. ASM also supports these two APIs. In this example, the Ingress API is used.
Wait until the Issuer resource is ready. Run the following command to check the status of the Issuer resource:
kubectl -n istio-system get issuer letsencrypt-prod-issuer
Expected output:
NAME READY AGE letsencrypt-prod-issuer True 8m3s
Step 3: Issue a certificate for the ASM ingress gateway
Use the kubeconfig file of the ACK cluster on the data plane that you added to the ASM instance and then create the resource shown in the following code block:
apiVersion: cert-manager.io/v1 kind: Certificate metadata: name: istio-ingressgateway-certs namespace: istio-system spec: dnsNames: - ${Test domain} # test.com issuerRef: group: cert-manager.io kind: Issuer name: letsencrypt-prod-issuer secretName: istio-ingressgateway-certs
Wait until the Certificate resource is ready. Run the following command to check the status of the Certificate resource:
kubectl -n istio-system get certificate istio-ingressgateway-certs
Expected output:
NAME READY SECRET AGE istio-ingressgateway-certs True istio-ingressgateway-certs 59m
Certificate issuing process
After you create a Certificate resource, cert-manager uses the created Issuer resource to issue a certificate for the domain you specified in the Certificate resource. During this process, the configured Solver takes effect.
Let's Encrypt initiates an HTTP-01 challenge to validate that the current server is the owner of the domain you specified in the certificate. To do this, Let's Encrypt sends an HTTP request to this domain. It must obtain a valid response before it can validate the ownership of the domain. In this example, only the HTTPBin routing rules are configured on the ASM ingress gateway. No challenge-related configurations are configured for the ASM ingress gateway. Did Let's Encrypt send a challenge validation request? How is the request responded to?
You can run the following command to view the access logs of the ASM ingress gateway. Then, you can determine whether Let's Encrypt sends a challenge validation request to the ASM ingress gateway:
kubectl -n istio-system logs ${Name of the ASM ingress gateway pod} | grep letsencrypt | tail -1
The output indicates that Let's Encrypt sent a challenge validation request to the ASM ingress gateway and the request was successfully responded to. In the Issuer resource, the ingressClassName
field is set to istio
. Therefore, cert-manager automatically creates an Ingress resource whose ingressClassName
is istio
and forwards the challenge validation request to the Solver of cert-manager to complete the domain ownership validation.
After the Certificate resource is ready, you cannot view the related Ingress resource by running the kubectl -n istio-system get ingress
command. The reason is that after the certificate is issued, cert-manager automatically deletes the Solver-related resources, such as the Ingress, Service, and Deployment resources.
Step 4: Verify the certificate issued by Let's Encrypt
Create an Istio gateway shown in the following code block. Configure the certificate generated in Step 3 on port 443 of the ASM ingress gateway. For more information, see Manage Istio gateways.
apiVersion: networking.istio.io/v1beta1 kind: Gateway metadata: name: httpbin-https namespace: default spec: selector: istio: ingressgateway servers: - hosts: - ${Test domain} port: name: https number: 443 protocol: HTTPS tls: credentialName: istio-ingressgateway-certs mode: SIMPLE
Modify the original httpbin-vs virtual service to the content shown in the following code block. For more information, see Manage virtual services.
apiVersion: networking.istio.io/v1beta1 kind: VirtualService metadata: name: httpbin-vs namespace: default spec: gateways: - httpbin -httpbin-https # Add this line. hosts: - '*' http: - name: test route: - destination: host: httpbin.default.svc.cluster.local port: number: 8000
Enter
https://${Test domain}
in the address bar of your browser.The address bar of your browser is similar to that in the following figure. Click the icon. Connection is secure is displayed, indicating that the browser has trusted your certificate.