All Products
Search
Document Center

Alibaba Cloud Service Mesh:Issue certificates for an ASM gateway with ACME

Last Updated:Jun 24, 2026

The Automatic Certificate Management Environment (ACME) protocol automates the process of obtaining and renewing X.509 digital certificates. By using the ACME protocol, a certificate authority (CA) can automatically verify an applicant's ownership of a domain before issuing a certificate. Let's Encrypt is a non-profit public CA that supports the ACME protocol and issues certificates that are trusted by most web browsers. This topic explains how to use cert-manager with Let's Encrypt to issue a browser-trusted HTTPS certificate for a Service Mesh (ASM) ingress gateway.

Prerequisites

How ACME works in cert-manager

When you use cert-manager, the ACME Issuer component registers user accounts with CA servers that support the ACME protocol. When you create an ACME Issuer, cert-manager generates a private key for secure communication with the ACME CA server. Certificates from public CAs like Let's Encrypt are generally trusted by most web browsers, allowing users to access your website without security warnings. The primary role of a public CA is to prove to the browser that the server is the legitimate owner of the domain. To do this, the public CA must verify that the applicant controls the domain before issuing the certificate. For more details about the ACME protocol, see the Automatic Certificate Management Environment RFC.

Challenges

A challenge is a key mechanism in the ACME protocol used to verify that a certificate applicant owns a domain. During the certificate application process, the ACME CA server requires the client (the applicant) to complete a specific challenge. This ensures that only the legitimate domain owner can obtain a certificate, which improves security and prevents domain impersonation. cert-manager supports two primary challenge types: the HTTP-01 challenge and the DNS-01 challenge.

  • The HTTP-01 challenge requires the server to expose a validation key at a specific, publicly accessible HTTP URL. This URL uses the domain requesting the certificate. When the ACME CA server successfully retrieves this key, it considers the applicant to have control over the domain. To simplify this process, cert-manager automatically modifies the cluster's Ingress resource when an HTTP-01 challenge is configured. It directs requests for the validation URL to a temporary web service that holds the required key and responds to the ACME server's challenge.

  • The DNS-01 challenge works by publishing a specific key as a TXT record in the DNS system. After this TXT record propagates, the ACME CA server can retrieve the key through a standard DNS query to confirm domain ownership. With the proper permissions, cert-manager automatically creates and submits the required TXT record to your DNS provider to fulfill the DNS-01 challenge.

Note

In a production environment, you must confirm whether your certificate authority (CA) supports the ACME protocol. If it does, the ASM ingress gateway can automatically obtain certificates from the CA using cert-manager. For example, Sectigo supports the ACME protocol, and its process is similar to that described in this topic.

Step 1: Prepare a public domain

To use Let's Encrypt to issue a certificate, you need a public domain. You must also point this domain to the ASM ingress gateway that you plan to use. For specific instructions, refer to the documentation from your DNS provider. If you use Alibaba Cloud DNS, see Add a DNS record. For more information about Let's Encrypt, see its Getting Started guide.

Step 2: Create an Issuer for Let's Encrypt

  1. Use the KubeConfig for your data plane cluster to create the following resource.

    apiVersion: cert-manager.io/v1
    kind: Issuer
    metadata:
      name: letsencrypt-prod-issuer
      namespace: istio-system
    spec:
      acme:
        email: 'your-email@example.com'    # This field is optional but recommended. The ACME server may use this email to send you important notices about your certificate.
        privateKeySecretRef:
          name: letsencrypt-prod
        server: https://acme-v02.api.letsencrypt.org/directory
        solvers:
        - http01:
            ingress:
              ingressClassName: istio

    The Issuer resource above specifies an http01 solver, which uses the Ingress API with an ingressClassName of istio.

    Note

    cert-manager supports solvers for both the Ingress API and the Gateway API. ASM also supports both APIs. This example uses the Ingress API.

  2. Wait for the Issuer to become ready. Run the following command to check its status.

    kubectl -n istio-system get issuer letsencrypt-prod-issuer

    Expected output:

    NAME                      READY   AGE
    letsencrypt-prod-issuer   True    8m3s

Step 3: Issue an ASM gateway certificate

  1. Use the KubeConfig for your data plane cluster to create the following resource.

    apiVersion: cert-manager.io/v1
    kind: Certificate
    metadata:
      name: istio-ingressgateway-certs
      namespace: istio-system
    spec:
      dnsNames:
      - ${YOUR_DOMAIN}    # test.com
      issuerRef:
        group: cert-manager.io
        kind: Issuer
        name: letsencrypt-prod-issuer
      secretName: istio-ingressgateway-certs
  2. Wait for the Certificate to become ready. Run the following command to check its status.

    kubectl -n istio-system get certificate istio-ingressgateway-certs

    Expected output:

    NAME                         READY   SECRET                       AGE
    istio-ingressgateway-certs   True    istio-ingressgateway-certs   59m

How certificate issuance works

After you create the Certificate resource, cert-manager uses the specified Issuer to issue a certificate for the domain. During this process, the configured solver becomes active.

Let's Encrypt uses an HTTP-01 challenge to confirm that the server owns the domain. It sends an HTTP request to the domain and must receive a valid response to complete the verification. In this example, the ingress gateway only has routing rules for the httpbin application, with no explicit configuration for the challenge. Did Let's Encrypt actually send a challenge request? And how did the gateway answer it?

You can run the following command to check the gateway logs and determine if Let's Encrypt sent a challenge request.

kubectl -n istio-system logs ${GATEWAY_POD_NAME} | grep letsencrypt | tail -1

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 logs show that the gateway received and successfully handled a request from Let's Encrypt. Because the Issuer is configured with an ingressClassName of istio, cert-manager automatically creates an Ingress resource with the same ingressClassName. This resource forwards the challenge request to the corresponding cert-manager solver, which completes the verification.

You will not see this Ingress resource if you run kubectl -n istio-system get ingress after the certificate is ready. This is because cert-manager automatically cleans up solver-related resources, such as Ingress, Service, and Deployment resources, once cert-manager successfully issues the certificate.

Step 4: Verify the certificate

  1. Create the following gateway rule to apply the certificate generated in Step 3 to port 443 of the gateway. For more information, see Manage gateway rules.

    apiVersion: networking.istio.io/v1beta1
    kind: Gateway
    metadata:
      name: httpbin-https
      namespace: default
    spec:
      selector:
        istio: ingressgateway
      servers:
      - hosts:
        - ${YOUR_DOMAIN}
        port:
          name: https
          number: 443
          protocol: HTTPS
        tls:
          credentialName: istio-ingressgateway-certs
          mode: SIMPLE
  2. Update the existing httpbin-vs virtual service with the following content. 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. In your web browser, navigate to https://${YOUR_DOMAIN}.

    The browser's address bar displays a lock icon. Click the icon (image). The message Connection is secure appears. This indicates that the browser trusts your certificate.