全部產品
Search
文件中心

Alibaba Cloud Service Mesh:使用Coraza Wasm外掛程式在ASM網關上實現WAF能力

更新時間:Jul 10, 2024

ASM通過VirtualService API提供豐富的路由能力和請求操縱能力,通過AuthorizationPolicy API提供豐富的安全能力,但是在一些特定情境下,這些API可能仍然不能滿足需求。您可以通過編寫自訂的Wasm Filter並添加到ASM網關或Sidecar來實現複雜情境的自訂行為。本文介紹如何通過WasmPlugin API為ASM網關啟用Coraza WAF。

前提條件

步驟一:製作Wasm Plugin OCI鏡像並推送至阿里雲Container Registry

Wasm Plugin有以下三種載入方式。本文以第二種方式為例,製作Wasm Plugin的OCI鏡像,並將其推送到阿里雲Container Registry。

  • 將Wasm擴充儲存至configmap,並Mount至容器,ASM網格代理或ASM網關從本地檔案系統載入。

  • 將Wasm擴充製作成OCI鏡像上傳至鏡像倉庫,ASM網格代理或ASM網關從鏡像倉庫拉取。

  • 將Wasm擴充上傳至雲端儲存或其他支援HTTP協議下載的服務,ASM網格代理或網關通過網路下載。

  1. 下載Coraza Wasm外掛程式並構建鏡像。

    1. 執行以下命令,下載Coraza Wasm外掛程式至本地,並解壓縮。

      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. 執行以下命令,為Coraza Wasm外掛程式重新命名。

      上一步解壓完成後,會得到coraza-proxy-wasm.wasm檔案。ASM要求Wasm外掛程式必須命名為plugin.wasm,因此需要重新命名。

      mv coraza-proxy-wasm.wasm plugin.wasm
    3. 在目前的目錄下建立Dockerfile檔案,內容如下:

      FROM scratch
      ADD ./plugin.wasm ./plugin.wasm
    4. 執行如下命令構建鏡像:

      docker build -t coraza-proxy-wasm:latest . 
  2. 推送鏡像到ACR企業版執行個體。

    1. 建立命名空間。

      1. 登入Container Registry控制台,在左側導覽列,單擊執行個體列表

      2. 執行個體列表頁面,單擊目標企業版執行個體。

      3. 在左側導覽列,單擊倉庫管理 > 命名空間,然後單擊建立命名空間,配置相關資訊,然後單擊確定

        本樣本配置命名空間名稱為wasm

    2. 在左側導覽列,單擊倉庫管理 > 存取控制,單擊公網頁簽,開啟訪問入口開關,按需添加公網白名單。

      如果不需要白名單控制,請刪除預設的白名單。

      說明

      本文採用公網地址作為示範。在實際應用中,您可以配置專用網路訪問以實現更高的私密性和更好的網路效能。更多資訊,請參見配置專用網路的存取控制

    3. 執行以下命令,登入ACR企業版執行個體,輸入密碼。

      docker login --username=登入使用者名稱 enterprise-registry.cn-hangzhou.cr.aliyuncs.com
    4. 執行以下命令,將鏡像推送到鏡像倉庫。

      docker tag ${ImageId} enterprise-registry.cn-hangzhou.cr.aliyuncs.com/wasm/coraza-proxy-wasm:latest
      docker push enterprise-registry.cn-hangzhou.cr.aliyuncs.com/wasm/coraza-proxy-wasm:latest
    5. 驗證鏡像是否推送成功。

      1. 登入Container Registry控制台,在左側導覽列,單擊執行個體列表

      2. 執行個體列表頁面,單擊目標企業版執行個體。

      3. 在左側導覽列,單擊倉庫管理 > 鏡像倉庫,單擊coraza-proxy-wasm,然後在左側導覽列,單擊鏡像版本

        若顯示剛推送的標籤為latest的鏡像,表明鏡像推送成功。

步驟二:配置鏡像拉取許可權

建立私人倉庫後,您需要使用Container Registry配置的口令建立Secret。ASM網格代理或ASM網關將使用Secret中的授權資訊在拉取鏡像時進行認證。

  1. 執行以下命令,建立Secret。

    kubectl create secret docker-registry -n istio-system coraza-wasm-proxy --docker-server=enterprise-registry.cn-hangzhou.cr.aliyuncs.com --docker-username=使用者名稱 --docker-password=密碼

    Secret需要保持與Wasm Plugin處於同一命名空間。本文的Wasm Plugin命名空間為istio-system,因此對應的Secret在istio-system命名空間。在實際使用中,請您根據實際情況調整以上命令中-n參數後的命名空間名稱。

  2. 執行以下命令,檢查Secret是否建立成功。

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

步驟三:應用WasmPlugin API到ASM

WasmPlugin API用於聲明在目標網關或網格代理上使用的外掛程式及相關配置。

  1. 使用以下內容,建立wasm-plugin.yaml。

    apiVersion: extensions.istio.io/v1alpha1
    kind: WasmPlugin
    metadata:
      name: coraza-proxy-wasm
      namespace: istio-system
    spec:
      imagePullPolicy: IfNotPresent
      imagePullSecret: coraza-wasm-proxy
      selector:
        matchLabels:
          istio: ingressgateway
      url: oci://enterprise-registry.cn-hangzhou.cr.aliyuncs.com/wasm/coraza-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

    欄位

    說明

    spec.url

    指定OCI鏡像的地址和Tag。

    spec.imagePullSecret

    指定用於進行鏡像倉庫鑒權的Secret。

    spec.selector

    指定生效的工作負載。

    spec.phase

    指定外掛程式生效的階段。

    sepc.pluginConfig

    指定外掛程式配置。

    • directives_map:定義名為defaultdirective,其中規則指定當請求攜帶x-user-type Header,且值為baned時,拒絕該請求。

    • default_directives:指定預設的directivedefault

  2. 在ASM執行個體對應的KubeConfig環境下,執行以下命令,將WasmPlugin應用到ASM執行個體。

    kubectl apply -f wasm-plugin.yaml

步驟四:驗證WasmPlugin API是否生效

  1. 執行以下命令,訪問httpbin應用。

    請將http://120.27.XXX.XX/替換為實際的網關地址。關於如何擷取網關地址,請參見擷取入口網關地址

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

    預期輸出:

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

    可以看到請求返回200 OK,符合預期。

  2. 執行以下命令,為請求添加header:x-user-type: baned,再次訪問httpbin應用。

    請將http://120.27.XXX.XX/替換為實際的網關地址。

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

    預期輸出:

    *   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

    可以看到請求返回403 Forbidden,被網關拒絕,符合預期。