Enable HTTPS on an ASM gateway

更新时间:
复制 MD 格式

You can enable HTTPS on an ASM gateway to provide encrypted access for external clients. ASM gateways support dynamic certificate loading, which allows you to configure private keys, server certificates, and root certificates in real time. This method avoids restarting the gateway or relying on Secret volume mounts, reducing operational complexity and eliminating the risk of service interruptions. ASM gateways can monitor and manage multiple certificate and private key pairs, providing flexible and secure communication for different hosts and enhancing data transmission security.

Prerequisites

Background information

Istio supports dynamic certificate loading. The private key, server certificate, and root certificate required for Transport Layer Security (TLS) can be configured dynamically without restarting the gateway. An ASM gateway monitors Secrets in its namespace and dynamically loads them via the Gateway custom resource (CR). Using HTTPS on an ASM gateway provides the following benefits:

  • The ingress gateway can dynamically add, delete, or update the required certificates, private keys, or corresponding root certificates without a restart.

  • Secret volume mounts are not required. After you create a Kubernetes Secret, the ASM gateway detects it and sends its certificate, private key, or root certificate to the ingress gateway.

  • An ASM gateway can monitor multiple pairs of certificates and private keys. You only need to create Secrets for multiple hosts and update the Gateway configuration.

Step 1: Prepare certificates and private keys

When using a domain name, you may need an Internet Content Provider (ICP) filing to ensure it is publicly accessible. This topic uses aliyun.com as an example to generate a certificate and a private key, and then save them as a Secret.

If you already have a certificate and private key for aliyun.com, rename the key to aliyun.com.key and the certificate to aliyun.com.crt. If not, use openssl to generate a certificate and a key.

  1. Run the following command to create a root certificate and a private key.

    openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -subj '/O=myexample Inc./CN=aliyun.com' -keyout aliyun.root.key -out aliyun.root.crt 
  2. Run the following commands to generate a server certificate and a private key for aliyun.com.

    openssl req -out aliyun.com.csr -newkey rsa:2048 -nodes -keyout aliyun.com.key -subj "/CN=aliyun.com/O=myexample organization"
    openssl x509 -req -days 365 -CA aliyun.root.crt -CAkey aliyun.root.key -set_serial 0 -in aliyun.com.csr -out aliyun.com.crt
  3. Create a Secret or certificate based on the version of your ASM instance.

    • For ASM instances earlier than v1.17

      Using the kubeconfig for the ingress gateway's cluster, run the following command to create a Secret containing the certificate and private key in the istio-system namespace.

      kubectl create -n istio-system secret tls myexample-credential --key=aliyun.com.key --cert=aliyun.com.crt
      Important

      The Secret name must not start with istio or prometheus and cannot contain the token field.

    • For ASM instances v1.17 and later

      1. Log on to the ASM console. In the left-side navigation pane, choose Service Mesh > Mesh Management.

      2. On the Mesh Management page, click the name of the target ASM instance. In the left-side navigation pane, choose ASM Gateways > Certificate Management.

      3. On the Certificate Management page, click Create. In the Certificate Information panel, set the following parameters and click OK.

        Parameter

        Description

        Name

        Enter a name for the certificate. In this example, myexample-credential is used.

        Public Key Certificate

        The content of the aliyun.com.crt file generated in sub-step 2.

        Private Key

        The content of the aliyun.com.key file generated in sub-step 2.

Step 2: Define backend service for a.aliyun.com

The backend service in this example uses NGINX. For the a.aliyun.com backend service, requests to the /hello path return the string Welcome to a.aliyun.com! with a status code of 200. The following is the content of the myexample-nginx.conf file.

events {
}
http {
  log_format main '$remote_addr - $remote_user [$time_local]  $status '
  '"$request" $body_bytes_sent "$http_referer" '
  '"$http_user_agent" "$http_x_forwarded_for"';
  access_log /var/log/nginx/access.log main;
  error_log  /var/log/nginx/error.log;
  server {
    listen 80;
    location /hello {
        return 200 'Welcome to a.aliyun.com!';
        add_header Content-Type text/plain;
    }
  }
}
  1. Using the kubeconfig for the ingress gateway's cluster, run the following command to create a Kubernetes ConfigMap for the NGINX server configuration.

    kubectl create configmap myexample-nginx-configmap --from-file=nginx.conf=./myexample-nginx.conf
  2. Enable automatic sidecar proxy injection for the default namespace. For more information, see Enable automatic sidecar proxy injection.

  3. Create a file named myexampleapp.yaml with the following content. Then, run the kubectl apply -f myexampleapp.yaml command to create the backend service for the a.aliyun.com domain name.

    View YAML

    apiVersion: v1
    kind: Service
    metadata:
      name: myexampleapp
      labels:
        app: myexampleapp
    spec:
      ports:
      - port: 80
        protocol: TCP
      selector:
        app: myexampleapp
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: myexampleapp
    spec:
      selector:
        matchLabels:
          app: myexampleapp
      replicas: 1
      template:
        metadata:
          labels:
            app: myexampleapp
        spec:
          containers:
          - name: nginx
            image: nginx
            ports:
            - containerPort: 80
            volumeMounts:
            - name: nginx-config
              mountPath: /etc/nginx
              readOnly: true
          volumes:
          - name: nginx-config
            configMap:
              name: myexample-nginx-configmap

Step 3: Define backend service for b.aliyun.com

This example's backend service uses httpbin.

  1. Create a file named httpbin.example.yaml and copy the following content into it.

    View YAML

    apiVersion: v1
    kind: Service
    metadata:
      name: httpbin
      labels:
        app: httpbin
    spec:
      ports:
      - name: http
        port: 8000
      selector:
        app: httpbin
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: httpbin
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: httpbin
          version: v1
      template:
        metadata:
          labels:
            app: httpbin
            version: v1
        spec:
          containers:
          - image: docker.io/citizenstig/httpbin
            imagePullPolicy: IfNotPresent
            name: httpbin
            ports:
            - containerPort: 80
  2. Using the kubeconfig for the cluster where the ingress gateway pod resides, run the following command to create the backend service for the b.aliyun.com domain name.

    kubectl apply -f httpbin.example.yaml

Step 4: Create a Gateway resource

  1. Log on to the ASM console. In the left-side navigation pane, choose Service Mesh > Mesh Management.

  2. On the Mesh Management page, click the name of the ASM instance. In the left-side navigation pane, choose ASM Gateways > Gateway. On the page that appears, click Create from YAML.

  3. On the Create page, select the target namespace (in this example, default) and any Scenario Template. Then, enter the following YAML and click Create.

    View YAML

    apiVersion: networking.istio.io/v1alpha3
    kind: Gateway
    metadata:
      name: mysdsgateway
    spec:
      selector:
        istio: ingressgateway # use istio default ingress gateway
      servers:
      - port:
          number: 443
          name: https
          protocol: HTTPS
        tls:
          mode: SIMPLE
          credentialName: myexample-credential # must be the same as secret
        hosts:
        - '*.aliyun.com'
                                    

    After the resource is created, the new gateway appears on the Gateway page.

Step 5: Create VirtualServices

  1. Log on to the ASM console. In the left-side navigation pane, choose Service Mesh > Mesh Management.

  2. On the Mesh Management page, click the name of the ASM instance. In the left-side navigation pane, choose Traffic Management Center > VirtualService. On the page that appears, click Create from YAML.

  3. On the Create page, select the target Namespaces and any Scenario Template. Then, enter the following YAML and click Create.

    View YAML

    apiVersion: networking.istio.io/v1alpha3
    kind: VirtualService
    metadata:
      name: mysdsgateway-myexamplevs
    spec:
      hosts:
      - "a.aliyun.com"
      gateways:
      - mysdsgateway
      http:
      - match:
        - uri:
            exact: /hello
        route:
        - destination:
            host: myexampleapp.default.svc.cluster.local
            port:
              number: 80      

    Repeat this step to create a VirtualService for b.aliyun.com.

    View YAML

    apiVersion: networking.istio.io/v1alpha3
    kind: VirtualService
    metadata:
      name: mysdsgateway-httpbinvs
    spec:
      hosts:
      - "b.aliyun.com"
      gateways:
      - mysdsgateway
      http:
      - match:
        - uri:
            prefix: /status
        - uri:
            prefix: /delay
        route:
        - destination:
            port:
              number: 8000
            host: httpbin.default.svc.cluster.local        

    After the virtual services are created, they appear on the VirtualService page.

Verify the results

Get the ingress gateway service address

  • Method 1: View the address in the ASM console. Log on to the ASM console, select the target Service Mesh instance, and then choose ASM Gateways > Ingress Gateway in the left-side navigation pane. On the Ingress Gateway page, view the required information.

  • Method 2: View the address in the ACK console. For more information, see View the service information about an ingress gateway.

Access the ingress gateway via command line

  • Run the following command to access the a.aliyun.com service over HTTPS.

    curl -k -H Host:a.aliyun.com --resolve a.aliyun.com:443:{REPLACE_WITH_THE_INGRESS_GATEWAY_IP_ADDRESS}  https://a.aliyun.com/hello

    Expected output:

    Welcome to a.aliyun.com!
  • Run the following command to access the b.aliyun.com service over HTTPS.

    curl -k -H Host:b.aliyun.com --resolve b.aliyun.com:443:{REPLACE_WITH_THE_INGRESS_GATEWAY_IP_ADDRESS}  https://b.aliyun.com/status/418  

    Expected output:

        -=[ teapot ]=-
           _...._
         .'  _ _ `.
        | ."` ^ `". _,
        \_;`"---"`|//
          |       ;/
          \_     _/
            `"""`

Related operations

Update the gateway certificate

To update the certificate mounted to a gateway, create a new Secret in the data plane and then change the value of the credentialName field in the Gateway resource to the name of the new Secret. The gateway automatically mounts the new Secret. This example shows how to create a Secret named new-istio-ingressgateway-certs for the example.com server.

  1. Create a certificate whose issuer is myexample.

    1. In the OpenSSL tool, run the following command to create a root certificate and a private key.

      openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -subj '/O=myexample Inc./CN=example.com' -keyout example.root.key -out example.root.crt
    2. Run the following commands to generate a server certificate and a private key for the example.com server.

      openssl req -out example.com.csr -newkey rsa:2048 -nodes -keyout example.com.key -subj "/CN=example.com/O=myexample organization"
      openssl x509 -req -days 365 -CA example.root.crt -CAkey example.root.key -set_serial 0 -in example.com.csr -out example.com.crt
    3. Obtain the kubeconfig file of the cluster and use kubectl to connect to the cluster.

    4. Run the following command to create a Secret named new-istio-ingressgateway-certs.

      kubectl create -n istio-system secret tls new-istio-ingressgateway-certs --key example.com.key --cert example.com.crt
  2. Run the following command in the cluster to delete the old certificate Secret.

    kubectl delete secret  istio-ingressgateway-certs -n istio-system
  3. Update the Gateway resource.

    1. Log on to the ASM console. In the left-side navigation pane, choose Service Mesh > Mesh Management.

    2. On the Mesh Management page, click the name of the ASM instance. In the left-side navigation pane, choose ASM Gateways > Gateway.

    3. On the Gateway page, find the target Gateway resource and click View YAML in the Actions column.

    4. In the edit dialog box, change the value of credentialName to the new certificate Secret name, new-istio-ingressgateway-certs, and then click OK.

  4. Verify that the gateway certificate is updated.

    1. Run the following command to view the current certificate information in the cluster.

      kubectl exec istio-ingressgateway-xxxx -n istio-system -- curl localhost:15000/config_dump  > ingressgateway_dump.yaml
    2. Run the following command to print and search for the new-istio-ingressgateway-certs certificate.

      cat ingressgateway_dump.yaml | grep new-istio-ingressgateway-certs -A 3

      Expected output:

      "name": "kubernetes://new-istio-ingressgateway-certs",
          "tls_certificate": {
            "certificate_chain": {
              "inline_bytes": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0t..."
            }
          }

      Copy the content after the inline_bytes parameter to obtain the Base64-encoded certificate.

    3. Run the following command in your local command-line tool to Base64-decode the certificate.

      echo <Base64-encoded-certificate-content> | base64 --decode
    4. Save the decoded content as a test.com.crt file.

    5. Run the following command in the OpenSSL tool to view the organization of the certificate.

      openssl x509 -in test.com.crt -text -noout

      Expected output:

      Certificate:
          Data:
              Version: 1 (0x0)
              Serial Number: 0 (0x0)
              Signature Algorithm: sha256WithRSAEncryption
              Issuer: O = myexample Inc., CN = example.com
              Validity
                  Not Before: Mar 17 03:20:27 2022 GMT
                  Not After : Mar 17 03:20:27 2023 GMT
              Subject: CN = example.com, O = myexample organization

      You can see that the organization is successfully changed to myexample, which means the gateway certificate was updated successfully.