All Products
Search
Document Center

Alibaba Cloud Service Mesh:Use the Coraza Wasm plug-in to implement WAF capabilities on an ASM gateway

Last Updated:Dec 01, 2023

Service Mesh (ASM) provides rich routing and request manipulation capabilities by using the VirtualService API, and provides rich security capabilities by using the AuthorizationPolicy API. However, these APIs may still fail to meet your requirements in some specific scenarios. You can customize WebAssembly (Wasm) filters and add them to ASM gateways or sidecar proxies to implement custom behavior in complex scenarios. This topic describes how to use the WasmPlugin API to enable Coraza Web Application Firewall (WAF) for an ASM gateway.

Prerequisites

Step 1: Deploy the HTTPBin application and configure an Isito gateway and a virtual service

  1. Deploy the HTTPBin application.

    1. Create an httpbin.yaml file that contains the following content:

      Expand to view the httpbin.yaml file

      apiVersion: v1
      kind: ServiceAccount
      metadata:
        name: httpbin
      ---
      apiVersion: v1
      kind: Service
      metadata:
        name: httpbin
        labels:
          app: httpbin
          service: httpbin
      spec:
        ports:
        - name: http
          port: 8000
          targetPort: 80
        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:
            serviceAccountName: httpbin
            containers:
            - image: docker.io/kong/httpbin
              imagePullPolicy: IfNotPresent
              name: httpbin
              ports:
              - containerPort: 80
    2. Use kubectl to connect to the ACK cluster based on the information in the kubeconfig file, and then run the following command to deploy the HTTPBin application in the cluster:

      kubectl apply -f httpbin.yaml
  2. Create an Istio gateway.

    1. Create an ingressgateway.yaml file that contains the following content:

      apiVersion: networking.istio.io/v1beta1
      kind: Gateway
      metadata:
        name: ingressgateway
        namespace: istio-system
      spec:
        selector:
          istio: ingressgateway
        servers:
        - hosts:
          - '*'
          port:
            name: http
            number: 80
            protocol: HTTP
    2. Use kubectl to connect to the ASM instance based on the information in the kubeconfig file. Then, run the following command to configure an Istio gateway for the ingress gateway and expose port 80:

      kubectl apply -f ingressgateway.yaml
  3. Create a virtual service.

    1. Create an ingressgateway-vs.yaml file that contains the following content:

      apiVersion: networking.istio.io/v1beta1
      kind: VirtualService
      metadata:
        name: ingressgateway
        namespace: istio-system
      spec:
        gateways:
        - ingressgateway
        hosts:
        - '*'
        http:
        - match:
          - uri:
              prefix: /
          name: httpbin
          route:
          - destination:
              host: httpbin.default.svc.cluster.local
    2. Use kubectl to connect to the ASM instance based on the information in the kubeconfig file. Then, run the following command to configure a route to the HTTPBin application on the ingress gateway:

      kubectl apply -f ingressgateway-vs.yaml

Step 2: Create an OCI image of the Wasm plug-in and push it to the Container Registry Enterprise Edition instance

A Wasm plug-in can be loaded in the following three ways. The following example uses the second method. In the example, an OCI image of the Wasm plug-in is created and pushed to the Container Registry Enterprise Edition instance.

  • The Wasm plug-in is stored in a ConfigMap and mounted to a container. An ASM sidecar proxy or ASM gateway loads the Wasm plug-in from the local file system.

  • An OCI image of the Wasm plug-in is created and uploaded to the image repository. An ASM sidecar proxy or ASM gateway pulls the image from the image repository.

  • The Wasm plug-in is uploaded to cloud storage or other services that support download over HTTP. An ASM sidecar proxy or ASM gateway downloads the Wasm plug-in over the network.

  1. Download the Coraza Wasm plug-in.

    1. Run the following commands to download the Coraza Wasm plug-in to your computer and decompress it:

      wget https://github.com/corazawaf/coraza-proxy-wasm/releases/download/0.3.0/coraza-proxy-wasm-0.3.0.zip
      unzip coraza-proxy-wasm-0.3.0.zip
    2. Run the following command to rename the Coraza Wasm plug-in.

      After you decompress the file in the previous step, you obtain the coraza-proxy-wasm.wasm file. ASM requires that a Wasm plug-in must be named plugin.wasm, and therefore you must rename it.

      mv coraza-proxy-wasm.wasm plugin.wasm
  2. Create an image and push it to the Container Registry Enterprise Edition instance.

    1. Create a namespace.

      1. Log on to the Container Registry console. In the left-side navigation pane, click Instances.

      2. On the Instances page, click the card of the desired Container Registry Enterprise Edition instance.

      3. In the left-side navigation pane, choose Repository > Namespace. On the page that appears, click Create Namespace. In the dialog box that appears, configure the relevant information, and then click OK.

        For this example, set Namespace to wasm.

    2. In the left-side navigation pane, choose Repository > Access Control. Then, click the Internet tab, turn on Enable Access over Internet, and add Internet whitelists based on your business requirements.

      If you do not need whitelist-based control, delete the default whitelist.

      Note

      The public endpoint is used as an example. During actual use, you can configure virtual private cloud (VPC) access for greater security and better network performance. For more information, see Configure a VPC ACL.

    3. Run the following command and enter the password to log on to the Container Registry Enterprise Edition instance:

      buildah login --username=Logon user name enterprise-registry.cn-hangzhou.cr.aliyuncs.com
    4. Run the following commands to create an image named coroza-proxy-wasm and copy the plugin.wasm file obtained in Step 1 to the image:

      buildah --name coroza-proxy-wasm from scratch
      buildah copy coroza-proxy-wasm plugin.wasm ./
    5. Run the following command to push the image to the image repository:

      buildah commit coroza-proxy-wasm docker://enterprise-registry.cn-hangzhou.cr.aliyuncs.com/wasm/coroza-proxy-wasm:latest
    6. Check whether the image is pushed.

      1. Log on to the Container Registry console. In the left-side navigation pane, click Instances.

      2. On the Instances page, click the card of the desired Container Registry Enterprise Edition instance.

      3. In the left-side navigation pane, choose Repository > Repositories. On the page that appears, click coroza-proxy-wasm. In the left-side navigation pane, click Tags.

        If the image with the latest tag is displayed, the image is pushed successfully.

        镜像推送验证.png

Step 3: Configure permissions to pull images

After you create a private repository, you must use the password configured for the Container Registry Enterprise Edition instance to create a Secret. An ASM sidecar proxy or ASM gateway uses the authorization information in the Secret for authentication when it pulls images.

  1. Run the following command to create a Secret:

    kubectl create secret docker-registry -n istio-system coroza-wasm-proxy --docker-server=enterprise-registry.cn-hangzhou.cr.aliyuncs.com --docker-username=Username -- docker-password=Password

    The Secret must be in the same namespace as the workload where the Coraza Wasm plug-in is located. In this example, the Coraza Wasm plug-in applies to an ASM gateway. Therefore, the Secret is created in the istio-system namespace. In actual use, change the namespace name after the -n parameter in the preceding command to the name of the namespace where the workload resides.

  2. Run the following command to check whether the Secret is created:

    kubectl -n isito-system get secret coroza-wasm-proxy 

Step 4: Apply the WasmPlugin API to the ASM instance

The WasmPlugin API is used to declare the plug-ins that apply to the destination gateway or sidecar proxy and the related configurations.

  1. Create a wasm-plugin.yaml file that contains the following content:

    apiVersion: extensions.istio.io/v1alpha1
    kind: WasmPlugin
    metadata:
      name: coroza-proxy-wasm
      namespace: istio-system
    spec:
      imagePullPolicy: IfNotPresent
      imagePullSecret: coroza-wasm-proxy
      selector:
        matchLabels:
          istio: ingressgateway
      url: oci://enterprise-registry.cn-hangzhou.cr.aliyuncs.com/wasm/coroza-proxy-wasm:latest
      phase: AUTHN
      pluginConfig:
        directives_map:
          default:
            - "SecDebugLogLevel 9"
            - "SecRuleEngine On"
            - "SecRule REQUEST_HEADERS:x-user-type \"@streq baned\" \"id:101,phase:1,t:lowercase,deny,msg:'denied by header'\""
        default_directives: default

    Parameter

    Description

    spec.url

    Specifies the address and tags of the OCI image.

    spec.imagePullSecret

    Specifies the Secret that is used to authenticate the image repository.

    spec.selector

    Specifies the workload on which this plug-in configuration is applied.

    spec.phase

    Specifies where to insert the plug-in.

    sepc.pluginConfig

    The plug-in configurations.

    • directives_map: defines a directive named default. By default, the rule specifies that a request is rejected if the request carries the x-user-type header with a value of baned.

    • default_directives: specifies that the default directive is default.

  2. Use kubectl to connect to the ASM instance based on the information in the kubeconfig file. Then, run the following command to apply the Coraza Wasm plug-in to the ASM instance:

    kubectl apply -f wasm-plugin.yaml

Step 5: Check whether the Coraza Wasm plug-in takes effect

  1. Run the following command to access the HTTPBin application.

    Replace http://120.27.XXX.XX/ with the IP address of the ingress gateway. For more information about how to obtain the IP address of the gateway, see Obtain the IP address of the ingress gateway.

    curl -v http://120.27.XXX.XX/

    Expected output:

    *   Trying 120.27.XXX.XX:80...
    * Connected to 120.27.XXX.XX (120.27.XXX.XX) port 80 (#0)
    > GET / HTTP/1.1
    > Host: 120.27.XXX.XX
    > User-Agent: curl/7.86.0
    > Accept: */*
    >
    * Mark bundle as not supporting multiuse
    < HTTP/1.1 200 OK
    < server: istio-envoy
    < date: Fri, 27 Oct 2023 03:21:19 GMT
    < content-type: text/html; charset=utf-8
    < content-length: 9593
    < access-control-allow-origin: *
    < access-control-allow-credentials: true
    < x-envoy-upstream-service-time: 2
    ......

    You can see that 200 OK is returned for the request as expected.

  2. Run the following command to send a request with the x-user-type: baned header to access the HTTPBin application again.

    Replace http://120.27.XXX.XX/ with the actual IP address of the gateway.

    curl -v -H 'x-user-type: baned' http://120.27.XXX.XX/

    Expected output:

    *   Trying 120.27.XXX.XX:80...
    * Connected to 120.27.XXX.XX (120.27.XXX.XX) port 80 (#0)
    > GET / HTTP/1.1
    > Host: 120.27.XXX.XX
    > User-Agent: curl/7.86.0
    > Accept: */*
    > x-user-type: baned
    >
    * Mark bundle as not supporting multiuse
    < HTTP/1.1 403 Forbidden
    < date: Fri, 27 Oct 2023 03:22:19 GMT
    < server: istio-envoy
    < content-length: 0
    <
    * Connection #0 to host 120.27.XXX.XX left intact

    You can see that 403 Forbidden is returned for the request, which is rejected by the gateway as expected.