All Products
Search
Document Center

Alibaba Cloud Service Mesh:Issue a certificate for an ASM ingress gateway

Last Updated:Jun 21, 2026

The Automatic Certificate Management Environment (ACME) protocol automates the process of obtaining and renewing X.509 certificates. The ACME protocol allows a certificate authority (CA) to automatically verify that you own a domain and issue a certificate for it. Let's Encrypt is a non-profit public CA that uses the ACME protocol to issue certificates that are trusted by most web browsers. This topic describes how to use cert-manager with Let's Encrypt to issue a browser-trusted HTTPS certificate for an ASM ingress gateway.

Prerequisites

ACME in cert-manager

When you use cert-manager, the ACME Issuer component registers a user account with a CA server that supports the ACME protocol. When you create an ACME Issuer, cert-manager generates a private key that is used to securely communicate with the ACME server. Certificates from public CAs like Let's Encrypt are trusted by default in most web browsers. This means that when a user visits your website, their browser automatically trusts the site's SSL/TLS certificate. The primary purpose of a public CA is to prove to the browser that the server is the legitimate owner of the domain. To do this, the CA must verify that the applicant actually controls the domain before issuing a certificate. For more information about the ACME protocol, see Automatic Certificate Management Environment.

Solving challenges

A challenge is how the ACME protocol verifies your domain ownership. During the certificate issuance process, the ACME server requires the client to complete a specific challenge. This ensures that only the legitimate owner of a domain can obtain a certificate for it, which prevents domain spoofing and enhances security. cert-manager supports two main types of challenges: HTTP-01 and DNS-01.

  • The HTTP-01 challenge requires you to prove ownership by placing a file with a validation key at a specific URL on your server. This URL must be publicly accessible and include the domain for which you are requesting the certificate. When the ACME server successfully retrieves the key from this path, it considers the domain validated. To simplify this, cert-manager automates the process. When you configure an HTTP-01 challenge, cert-manager temporarily adjusts your cluster's Ingress resources to route validation requests to a small web service. This service presents the required validation key to the ACME server.

  • The DNS-01 challenge requires you to prove ownership by creating a specific DNS TXT record that contains a validation key. After the record propagates through the DNS system, the ACME server can verify your domain ownership by performing a DNS lookup. If granted the necessary permissions, cert-manager can automatically create and submit the required TXT record to your DNS provider to solve the DNS-01 challenge.

Note

In a production environment, you must confirm whether your certificate authority supports the ACME protocol. If it does, the ASM ingress gateway can automatically obtain a certificate from the CA through cert-manager. For example, Sectigo supports the ACME protocol, which works on a similar principle.

Step 1: Prepare a public domain

To use Let's Encrypt to issue a certificate, you need a public domain that points to the ASM ingress gateway. For specific instructions, refer to the documentation from your DNS provider. If you use Alibaba Cloud DNS, see Add DNS records. For more information about Let's Encrypt, see Getting Started.

Step 2: Create a Let's Encrypt Issuer resource

  1. Use the KubeConfig of 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: 'te**@mail.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 preceding Issuer resource specifies an http01 solver that uses the Ingress API with an ingressClassName of istio. The following steps explain how this solver works.

    Note

    cert-manager supports both Ingress API and Gateway API solvers. 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 a certificate

  1. Use the KubeConfig of 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}    # For example, 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

Certificate issuance process

After creating the Certificate resource, cert-manager uses the specified Issuer to issue a certificate for the domain. During this process, the configured solver is activated.

Let's Encrypt uses an HTTP-01 challenge to confirm that the server requesting the certificate owns the domain. To do this, Let's Encrypt sends an HTTP request to the domain and expects to receive a valid response to complete the verification. In this example, the ingress gateway only has routing rules for the httpbin application, with no specific configuration for the challenge. Does Let's Encrypt actually send a challenge request? And how is it answered?

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

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

After the Certificate resource is ready, you cannot see the temporary Ingress resource by running kubectl -n istio-system get ingress. This is because cert-manager automatically deletes solver-related resources, such as the Ingress, Service, and Deployment, after the certificate is successfully issued.

Step 4: Verify the certificate

  1. Create the following Gateway resource to configure the certificate generated in Step 3 on port 443 of the 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:
        - ${YOUR_DOMAIN}
        port:
          name: https
          number: 443
          protocol: HTTPS
        tls:
          credentialName: istio-ingressgateway-certs
          mode: SIMPLE
  2. Modify the existing httpbin-vs virtual service as follows. 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 browser, navigate to https://${YOUR_DOMAIN}.

    In the browser's address bar, click the lock image icon. The message Connection is secure appears, indicating that your browser trusts the certificate.