All Products
Search
Document Center

Alibaba Cloud Service Mesh:Use ACME CA to issue certificates for ASM ingress gateways

Last Updated:May 13, 2024

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

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.

Note

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

  1. 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 the ingressClassName field is istio. The following steps explain how this Solver takes effect.

    Note

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

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

  1. 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
  2. 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

Show the expected output

{

    "authority_for": "xxxxxxx",

    "bytes_received": "0",

    "bytes_sent": "87",

    "downstream_local_address": "xx.xx.xx.xx:80",

    "downstream_remote_address": "xx.xx.xx.xx:57101",

    "duration": "0",

    "istio_policy_status": "-",

    "method": "GET",

    "path": "/.well-known/acme-challenge/JfKvfdSNmkR7UqmCQU0OSkJC3EsnP4ZUiCc28OLLLxA",

    "protocol": "HTTP/1.1",

    "request_id": "e6806d08-0469-4383-be8e-4d7506b39ec5",

    "requested_server_name": "-",

    "response_code": "200",

    "response_flags": "-",

    "route_name": "-",

    "start_time": "2024-04-08T12:04:06.153Z",

    "trace_id": "-",

    "upstream_cluster": "outbound|8089||cm-acme-http-solver-c4ch9.istio-system.svc.cluster.local",

    "upstream_host": "xx.xx.xx.xx:8089",

    "upstream_local_address": "xx.xx.xx.xx:55886",

    "upstream_response_time": "0",

    "upstream_service_time": "0",

    "upstream_transport_failure_reason": "-",

    "user_agent": "Mozilla/5.0 (compatible; Let's Encrypt validation server; +https://www.letsencrypt.org)",

    "x_forwarded_for": "xx.xx.xx.xx"

}

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

  1. 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
  2. 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
  3. 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 image icon. Connection is secure is displayed, indicating that the browser has trusted your certificate.

    image