サービスメッシュ(ASM)は、VirtualService API を使用して豊富なルーティング機能とリクエスト操作機能を提供し、AuthorizationPolicy API を使用して豊富なセキュリティ機能を提供します。ただし、これらの API は、特定のシナリオでは要件を満たせない場合があります。WebAssembly(Wasm)フィルターをカスタマイズし、ASM ゲートウェイまたはサイドカープロキシに追加して、複雑なシナリオでカスタム動作を実装できます。このトピックでは、WasmPlugin API を使用して ASM ゲートウェイの Coraza Web アプリケーションファイアウォール(WAF)を有効にする方法について説明します。
前提条件
バージョン 1.18 以降の ASM インスタンスにコンテナサービス Kubernetes 版(ACK)クラスターが追加されています。詳細については、「ASM インスタンスへのクラスターの追加」をご参照ください。
自動サイドカープロキシインジェクションが有効になっています。詳細については、「グローバル名前空間の管理」をご参照ください。
HTTPBin アプリケーションがデプロイされ、アクセス可能です。詳細については、「HTTPBin アプリケーションのデプロイ」をご参照ください。
コンテナレジストリ Enterprise Edition インスタンスが作成されています。コンテナレジストリ Enterprise Edition インスタンスは、Open Container Initiative(OCI)イメージをサポートしています。詳細については、「コンテナレジストリ Enterprise Edition インスタンスの作成」をご参照ください。
Docker がインストールされています。詳細については、「Get Docker」を参照してください。
手順 1:Wasm プラグインの OCI イメージを作成し、コンテナレジストリ Enterprise Edition インスタンスにプッシュする
Wasm プラグインは、次の 3 つの方法でロードできます。次の例では、2 番目の方法を使用します。この例では、Wasm プラグインの OCI イメージを作成し、コンテナレジストリ Enterprise Edition インスタンスにプッシュします。
Wasm プラグインは ConfigMap に保存され、コンテナーにマウントされます。ASM サイドカープロキシまたは ASM ゲートウェイは、ローカルファイルシステムから Wasm プラグインをロードします。
Wasm プラグインの OCI イメージが作成され、イメージリポジトリにアップロードされます。ASM サイドカープロキシまたは ASM ゲートウェイは、イメージリポジトリからイメージをプルします。
Wasm プラグインは、クラウドストレージ、または HTTP 経由のダウンロードをサポートするその他のサービスにアップロードされます。ASM サイドカープロキシまたは ASM ゲートウェイは、ネットワーク経由で Wasm プラグインをダウンロードします。
Coraza Wasm プラグインをダウンロードし、イメージを作成します。
次のコマンドを実行して、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次のコマンドを実行して、Coraza Wasm プラグインの名前を変更します。
前の手順でファイルを解凍すると、coraza-proxy-wasm.wasm ファイルが取得されます。ASM では、Wasm プラグインの名前を plugin.wasm にする必要があるため、名前を変更する必要があります。
mv coraza-proxy-wasm.wasm plugin.wasm次のコンテンツを使用して、現在のディレクトリに Dockerfile ファイルを作成します。
FROM scratch ADD ./plugin.wasm ./plugin.wasm次のコマンドを実行して、イメージを作成します。
docker build -t coraza-proxy-wasm:latest .
イメージをコンテナレジストリ Enterprise Edition インスタンスにプッシュします。
名前空間を作成します。
コンテナレジストリコンソール にログインします。左側のナビゲーションペインで、[インスタンス] をクリックします。
[インスタンス] ページで、目的のコンテナレジストリ Enterprise Edition インスタンスのカードをクリックします。
左側のナビゲーションペインで、 を選択します。表示されるページで、[名前空間の作成] をクリックします。表示されるダイアログボックスで、関連情報を設定し、[OK] をクリックします。
この例では、[名前空間] を wasm に設定します。
左側のナビゲーションペインで、 を選択します。次に、[インターネット] タブをクリックし、[インターネット経由のアクセスを有効にする] をオンにして、ビジネス要件に基づいてインターネットホワイトリストを追加します。
ホワイトリストベースの制御が不要な場合は、デフォルトのホワイトリストを削除します。
説明パブリックエンドポイントを例として使用しています。実際の使用では、セキュリティとネットワークパフォーマンスを向上させるために、仮想プライベートクラウド(VPC)アクセスを設定できます。詳細については、「VPC ACL の設定」をご参照ください。
次のコマンドを実行し、パスワードを入力してコンテナレジストリ Enterprise Edition インスタンスにログインします。
docker login --username=ログオンユーザー名 enterprise-registry.cn-hangzhou.cr.aliyuncs.com次のコマンドを実行して、イメージをイメージリポジトリにプッシュします。
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イメージがプッシュされたかどうかを確認します。
コンテナレジストリコンソール にログインします。左側のナビゲーションペインで、[インスタンス] をクリックします。
[インスタンス] ページで、目的のコンテナレジストリ Enterprise Edition インスタンスのカードをクリックします。
左側のナビゲーションペインで、 を選択します。表示されるページで、[coraza-proxy-wasm] をクリックします。左側のナビゲーションペインで、[タグ] をクリックします。
latestタグが付いたイメージが表示されている場合、イメージは正常にプッシュされています。
手順 2:イメージをプルするための権限を設定する
プライベートリポジトリを作成した後、コンテナレジストリ Enterprise Edition インスタンスに設定されているパスワードを使用して Secret を作成する必要があります。ASM サイドカープロキシまたは ASM ゲートウェイは、イメージをプルするときに、認証のために Secret 内の認証情報を使用します。
次のコマンドを実行して、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 プラグインと同じ名前空間に存在する必要があります。この例では、Wasm プラグインの名前空間は istio-system です。したがって、Secret は istio-system 名前空間に存在する必要があります。実際の使用では、前のコマンドの
-nパラメーターに続く名前空間名をビジネス要件に基づいて変更します。次のコマンドを実行して、Secret が作成されたかどうかを確認します。
kubectl -n istio-system get secret coraza-wasm-proxy
手順 3:WasmPlugin API を ASM インスタンスに適用する
WasmPlugin API は、宛先ゲートウェイまたはサイドカープロキシに適用されるプラグインと関連設定を宣言するために使用されます。
次のコンテンツを含む 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.urlOCI イメージのアドレスとタグを指定します。
spec.imagePullSecretイメージリポジトリを認証するために使用される Secret を指定します。
spec.selectorこのプラグイン設定が適用されるワークロードを指定します。
spec.phaseプラグインを挿入する場所を指定します。
sepc.pluginConfigプラグイン設定を指定します。
directives_map:defaultという名前のdirectiveを定義します。デフォルトでは、リクエストに値がbanedのx-user-typeヘッダーが含まれている場合、リクエストは拒否されます。default_directives:デフォルトのdirectiveがdefaultであることを指定します。
kubectl を使用して、kubeconfig ファイルの情報に基づいて ASM インスタンスに接続します。次に、次のコマンドを実行して、Coraza Wasm プラグインを ASM インスタンスに適用します。
kubectl apply -f wasm-plugin.yaml
手順 4:Coraza Wasm プラグインが有効になっているかどうかを確認する
次のコマンドを実行して、HTTPBin アプリケーションにアクセスします。
http://120.27.XXX.XX/をイングレスゲートウェイの IP アドレスに置き換えます。ゲートウェイの IP アドレスを取得する方法の詳細については、「イングレスゲートウェイの IP アドレスの取得」をご参照ください。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が想定どおりに返されたことを示しています。x-user-type: banedヘッダーを含むリクエストを送信して、HTTPBin アプリケーションに再度アクセスします。http://120.27.XXX.XX/をゲートウェイの実際の IP アドレスに置き換えます。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が返されたことを示しています。これは、リクエストが想定どおりにゲートウェイによって拒否されたことを意味します。