イングレスゲートウェイが外部トラフィックを受信すると、きめ細かなアクセス制御には単純な許可/拒否ルールだけでは不十分な場合が多くあります。Open Policy Agent (OPA) を使用すると、Rego 言語でカスタムの権限付与ポリシーを作成し、アプリケーションコードを変更することなく、ゲートウェイレベルでそのポリシーを適用できます。
本トピックでは、Service Mesh (ASM) のイングレスゲートウェイと並列して OPA エンジンをデプロイし、Envoy の外部権限付与メカニズムを介して両者を接続したうえで、HTTPBin アプリケーションを用いて設定を検証する手順について説明します。
仕組み
ASM イングレスゲートウェイは、データプレーンプロキシとして Envoy を使用します。Envoy は、外部権限付与フィルター (ext_authz) をサポートしており、このフィルターにより、権限付与の判断を外部サービスに委譲できます。
OPA が外部権限付与サービスとして統合される場合:
リクエストがイングレスゲートウェイに到着します。
Envoy が、リクエストのメタデータ(HTTP メソッド、パス、ヘッダー)を gRPC 経由で OPA エンジンに送信します。
OPA が、ロード済みの Rego ポリシーに基づいてリクエストを評価します。
OPA が「許可」または「拒否」の判定結果を返します。Envoy は、許可された場合はリクエストをアップストリームに転送し、拒否された場合は
403 Forbidden応答を返します。
OPA はクラスター内に独立した Pod として実行されるため、ポリシー評価はローカルで行われ、外部ネットワークホップを必要としません。また、OPA の HTTP API を使用することで、ワークロードの再デプロイを伴わず、ランタイム中にポリシーを更新できます。
前提条件
開始する前に、以下の条件を満たしていることを確認してください。
ASM インスタンス(v1.15.3.25 以降)で、Kubernetes マネージドクラスターが追加済みであること。詳細については、「ASM インスタンスにクラスターを追加する」および「ASM インスタンスを更新する」をご参照ください。
イングレスゲートウェイ経由でデプロイされ、アクセス可能な HTTPBin アプリケーション。詳細については、「HTTPBin アプリケーションをデプロイする」をご参照ください。
自動サイドカープロキシ注入が
default名前空間に対して有効になっています。詳細については、「サイドカープロキシ注入ポリシーの設定」をご参照ください。
ステップ 1:OPA エンジンのデプロイ
以下の内容で asm-opa.yaml というファイルを作成します。このマニフェストでは、3 つの Kubernetes リソースが定義されています。
| リソース | 目的 |
|---|---|
| サービス | 9191 ポート(gRPC)および 8181 ポート(HTTP)で OPA エンジンを公開します |
| デプロイメント | Envoy 外部権限付与 gRPC プラグインを有効化した状態で OPA コンテナを実行します |
| シークレット | OPA が起動時に読み込むデフォルトの Rego ポリシーを格納します |
コンテナイメージのパスに含まれるリージョン ID cn-hangzhou を、ご利用のクラスターがデプロイされているリージョンに置き換えてください。たとえば、クラスターが中国 (上海) リージョンにある場合は、registry-vpc.cn-shanghai.aliyuncs.com/acs/opa:0.46.1-istio-3-static を使用します。
主な構成フィールド
デプロイメントの args は、OPA エンジンの動作を制御するパラメーターを指定します。
| フィールド | 値 | 説明 |
|---|---|---|
--addr | 0.0.0.0:8181 | ポリシー管理およびヘルスチェック用の HTTP API リスニングアドレスです。 |
--diagnostic-addr | 0.0.0.0:8282 | readiness プローブおよび liveness プローブ用の診断エンドポイントです。 |
plugins.envoy_ext_authz_grpc.addr | :9191 | Envoy 外部権限付与プラグインの gRPC リスニングアドレスです。サービスのポートと一致させる必要があります。 |
plugins.envoy_ext_authz_grpc.path | asm/authz/allow | Rego ポリシーの判定パスです。OPA は各リクエストに対して data.asm.authz.allow を評価します。 |
decision_logs.console | true | デバッグ用に、判定ログを stdout に出力します。 |
デフォルトのポリシールール
シークレットに格納された Rego ポリシーでは、3 つの権限付与ルールが定義されています。リクエストは、**いずれかのルール**が true と評価された場合に許可されます。
| ルール | 条件 | 例 |
|---|---|---|
| ヘルスチェックのバイパス | リクエストパスが health | GET /health |
| HEAD メソッドのバイパス | HTTP メソッドが HEAD | HEAD /any-path |
| ユーザーの権限付与 | Authorization ヘッダー内のユーザー名が alice | Authorization: Basic YWxpY2U6dGVzdHBhc3N3b3Jk(alice:testpassword、Base64 エンコード) |
上記以外のすべてのリクエストは拒否されます(default allow := false)。
デプロイ
以下のコマンドを実行して、OPA を Container Service for Kubernetes (ACK) クラスターにデプロイします。
kubectl apply -f asm-opa.yamlステップ 2:イングレスゲートウェイから OPA を利用するよう構成
ASM コンソールを使用して、OPA エンジンをカスタム権限付与サービスとしてイングレスゲートウェイに接続します。
ASM コンソールにログインします。左側のナビゲーションウィンドウで、 を選択します。
Mesh Management ページで、対象の ASM インスタンスの名前をクリックします。左側のナビゲーションウィンドウで、 を選択します。
Ingress Gateway ページで、構成対象のイングレスゲートウェイの横にある Gateway security をクリックします。
左側のナビゲーションウィンドウで、 を選択します。
Custom Authorization Service Configuration ステップで、イングレスゲートウェイのカスタム権限付与サービスとして OPA エンジンを構成し、Next をクリックします。

Matching Rules ステップで、OPA 権限付与を適用するリクエストを指定し、Submit をクリックします。

構成が保存されると、カスタム権限付与サービスがページ上に表示されます。

ステップ 3:OPA 権限付与の検証
HTTPBin アプリケーションをイングレスゲートウェイ経由で呼び出し、3 つの権限付与ルールをテストします。
以下のコマンドで使用する <gateway-ip> は、ご利用の ASM イングレスゲートウェイの IP アドレスに置き換えてください。
テスト 1:マッチングルールの対象外パスへのアクセス
ルートパス (/) に対して GET リクエストを送信します。ステップ 2 で構成したマッチングルールがこのパスをカバーしていない場合、リクエストは OPA をバイパスし、直接アップストリームサービスに到達します。
curl <gateway-ip>/ -I -X GET期待される出力:
HTTP/1.1 200 OK
server: istio-envoy
date: Tue, 25 Jul 2023 08:30:58 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: 2200 OK 応答は、このパスに対するリクエストが OPA によってインターセプトされていないことを確認します。
テスト 2:認証情報なしでの保護パスへのアクセス
GET リクエストを、/status/201 に対して、Authorization ヘッダーを含めずに送信します。
curl <gateway-ip>/status/201 -I -X GET期待される出力:
HTTP/1.1 403 Forbidden
date: Tue, 25 Jul 2023 08:31:18 GMT
server: istio-envoy
content-length: 0
x-envoy-upstream-service-time: 1403 Forbidden 応答は、許可ルールに一致しないリクエストが OPA によって拒否されることを確認します。
テスト 3:有効な認証情報を用いた保護パスへのアクセス
許可されたユーザー名 alice を用いて、GET リクエストを /status/201 に対して送信します。
curl <gateway-ip>/status/201 -I -X GET --user alice:testpassword期待される出力:
HTTP/1.1 201 Created
server: istio-envoy
date: Tue, 25 Jul 2023 08:31:38 GMT
content-type: text/html; charset=utf-8
access-control-allow-origin: *
access-control-allow-credentials: true
content-length: 0
x-envoy-upstream-service-time: 3201 Created 応答は、ユーザー alice からのリクエストが OPA によって許可されることを確認します。
ステップ 4:ランタイムでの OPA ポリシーの更新
OPA は、ポリシー管理用の HTTP API を提供しています。この API を使用すると、OPA Pod の再デプロイを伴わずにポリシーを更新できます。
以下の例では、許可されるユーザーを alice から bob に変更します。
kubectl exec deployment/httpbin -c istio-proxy -- curl asm-opa:8181/v1/policies/policy/policy.rego -XPUT --data-binary 'package asm.authz
import future.keywords
import input.attributes.request.http as http_request
import input.parsed_path
default allow := false
allow if {
parsed_path[0] == "health"
}
allow if {
http_request.method == "HEAD"
}
allow if {
user_name == "bob"
}
user_name := parsed if {
[_, encoded] := split(http_request.headers.authorization, " ")
[parsed, _] := split(base64url.decode(encoded), ":")
}'このコマンドは、OPA サービス (asm-opa:8181) がクラスター内からのみアクセス可能であるため、httpbin Pod の istio-proxy コンテナから curl を実行します。HTTP PUT メソッドは、指定されたパスにある既存のポリシーを置き換えます。
更新されたポリシーの検証
bobとしてリクエストを送信します。201 Created応答が期待されます。期待される出力:curl <gateway-ip>/status/201 -I -X GET --user bob:testpasswordHTTP/1.1 201 Created server: istio-envoy date: Tue, 25 Jul 2023 08:32:16 GMT content-type: text/html; charset=utf-8 access-control-allow-origin: * access-control-allow-credentials: true content-length: 0 x-envoy-upstream-service-time: 3aliceとしてリクエストを送信します。403 Forbidden応答が期待されます。期待される出力:curl <gateway-ip>/status/201 -I -X GET --user alice:testpasswordHTTP/1.1 403 Forbidden date: Tue, 25 Jul 2023 08:32:49 GMT server: istio-envoy content-length: 0 x-envoy-upstream-service-time: 1
これらの結果より、更新されたポリシーが即座に有効化されたことが確認できます:bob は許可され、alice は拒否されるようになりました。