Alibaba Cloud Service Mesh (ASM) は Open Policy Agent (OPA) プラグインと統合されており、アプリケーションに対してきめ細かいアクセス制御ポリシーを定義できます。v1.8.6.41 以降の ASM インスタンスでは、ConfigMap を設定して OPA ポリシーを Pod に自動的にプッシュすることで、動的なポリシー更新が可能です。このトピックでは、ASM で OPA ポリシーを動的に更新する方法を説明します。
前提条件
-
v1.8.6.41-gb1d8f288-aliyun 以降の ASM インスタンスが作成されていること。詳細については、「ASM インスタンスの作成」をご参照ください。
Container Service for Kubernetes (ACK) マネージドクラスターが作成されていること。詳細については、「ACK マネージドクラスターの作成」をご参照ください。
背景情報
CNCF のインキュベーションプロジェクトとしてホストされている Open Policy Agent (OPA) は、アプリケーションのきめ細かなアクセス制御を実装するために使用できるポリシーエンジンです。汎用ポリシーエンジンとして、OPA はマイクロサービスと並行してスタンドアロンサービスとしてデプロイできます。アプリケーションを保護するためには、マイクロサービスへの各リクエストが権限付与される必要があります。マイクロサービスは OPA API にクエリを送信して、リクエストが許可されているかどうかを判断します。
手順1:OPA の有効化
-
ASM コンソールにログインします。
-
左側のナビゲーションウィンドウで、 を選択します。
-
[メッシュ管理] ページで、設定する ASM インスタンスを見つけます。ASM インスタンスの名前をクリックするか、[操作] 列の [管理] をクリックします。
-
Basic Information ページで、右上の Settings をクリックします。
-
Settings Update パネルで、[OPA プラグインを有効にする] を選択します。
-
OK をクリックします。
Basic Information ページで、OPA Plug-in のステータスが Enable に変わります。
手順2:ConfigMap の作成
ASM は OPA ポリシーの動的な更新をサポートしています。Service Mesh に openpolicyagent.org/policy=rego ラベルを設定すると、ポリシーはすべての名前空間にわたり、OPA サイドカーが注入されたすべての Pod に自動的にプッシュされます。ConfigMap を削除すると、ポリシーも Pod から削除されます。
-
Pod の OPA ポリシーを定義する場合、
default allowフィールドは 1 つしか含めることができません。複数の OPA ポリシー関連の ConfigMap が Pod に適用され、各ポリシーがdefault allowフィールドを定義している場合、複数のdefault allowフィールドが原因で動的更新が失敗します。 -
OPA サイドカーは、起動するために
opa-policyという名前の ConfigMap に依存します。この ConfigMap を削除すると、対応する OPA ポリシーも OPA サイドカーから削除されます。ConfigMap を再作成してもポリシーは復元されません。Pod を再作成する必要があります。
-
opa-policy という名前の ConfigMap を作成します。
OPA サイドカーの起動には、
opa-policyという名前の ConfigMap が必要です。この ConfigMap は動的更新をサポートしています。この ConfigMap は基本的なポリシー設定にのみ使用してください。複雑なポリシーは、他の ConfigMap を通じて動的に追加します。-
次の内容を使用して、opa-policy という名前の YAML ファイルを作成します。
apiVersion: v1 kind: ConfigMap metadata: name: opa-policy data: policy.rego: | ### このポリシーで許可されるパスは、OPA ポリシーの動的更新に必要です。これらのパスが設定されていない場合、更新は失敗します。 package istio.authz import input.parsed_path allow { parsed_path[0] = "v1" parsed_path[1] = "policies" } -
次のコマンドを実行して ConfigMap を作成します。
kubectl apply -f opa-policy.yaml
-
-
opa-policy-add という名前の ConfigMap を作成します。
この ConfigMap を使用して OPA ポリシーを定義します。
-
次の内容を使用して、opa-policy-add という名前の YAML ファイルを作成します。
apiVersion: v1 kind: ConfigMap metadata: name: opa-policy-add labels: ### ConfigMap に次のラベルを設定する必要があります。設定しない場合、ConfigMap が定義する OPA ポリシーは動的に更新できません。 openpolicyagent.org/policy: rego data: policy.rego: | ### 次のコードは、サンプルポリシーの定義を示しています。実際のニーズに基づいてポリシーを定義してください。 package istio.authz import input.attributes.request.http as http_request default allow = false allow { roles_for_user[r] required_roles[r] } roles_for_user[r] { r := user_roles[user_name][_] } required_roles[r] { perm := role_perms[r][_] perm.method = http_request.method perm.path = http_request.path } user_name = parsed { [_, encoded] := split(http_request.headers.authorization, " ") [parsed, _] := split(base64url.decode(encoded), ":") } user_roles = { "guest1": ["guest"], "admin1": ["admin"] } role_perms = { "guest": [ {"method": "GET", "path": "/productpage"}, ], "admin": [ {"method": "GET", "path": "/productpage"}, {"method": "GET", "path": "/api/v1/products"}, ], }-
user_roles:ユーザーにロールを割り当てます。この例では、guest1にguestロールを、admin1にadminロールを割り当てます。 -
role_perms:各ロールの権限を設定します。この例では、guestロールには /productpage パスへのアクセスを許可し、adminロールには /productpage と /api/v1/products パスへのアクセスを許可します。
-
-
次のコマンドを実行して ConfigMap を作成します。
kubectl apply -f opa-policy-add.yaml
-
-
次のコマンドを実行して、ポリシーのプッシュ結果を表示します。
プッシュステータスは ConfigMap の
アノテーションで更新されます。kubectl get configmap opa-policy-add -o yamlコマンド出力で ConfigMap を表示します。
-
プッシュが成功した場合、ConfigMap に次の情報が表示されます。
openpolicyagent.org/policy-status: '{"status":"ok"}' -
プッシュが失敗した場合、対応するエラーメッセージが表示されます。
-
手順3:OPA サイドカーのインジェクション
サンプルアプリケーション Bookinfo を ASM インスタンスにデプロイし、Bookinfo アプリケーションの各 Pod に OPA サイドカーがインジェクトされているかを確認します。
-
Bookinfo サンプルアプリケーションを ASM インスタンスにデプロイします。詳細については、「ASM インスタンスへのアプリケーションのデプロイ」をご参照ください。
-
必要に応じて、Istio の仮想サービスとイングレスゲートウェイサービスを定義します。詳細については、「Istio を使用したバージョンベースのトラフィックルーティング」をご参照ください。
-
Bookinfo アプリケーションの各アプリケーションの Pod に OPA サイドカーがインジェクトされているかを確認します。
左側のナビゲーションウィンドウで、クラスター をクリックします。
クラスターリスト ページで、対象クラスターの名前をクリックするか、操作 列の 詳細 をクリックします。
クラスター管理ページの左側のナビゲーションウィンドウで、 を選択します。
-
ポッド ページで、名前空間 ドロップダウンリストから [default] を選択し、対象アプリケーションの Pod 名をクリックします。
コンテナー タブで、サイドカープロキシ (istio-proxy) と OPA サイドカー (opa-istio) がインジェクトされていることを確認します。この確認を各アプリケーション Pod で繰り返します。
手順4:OPA ポリシーが期待どおりにアクセス制御を実装していることの確認
-
次のコマンドを実行します。結果は、
guestロールを持つguest1ユーザーが/productpageにはアクセスできるが、/api/v1/productsへのアクセスは拒否されることを示しています。curl -X GET http://{{イングレスゲートウェイサービスの IP アドレス}}/productpage --user guest1:password -I次の出力が期待されます。
HTTP/1.1 200 OKcurl -X GET http://{{イングレスゲートウェイサービスの IP アドレス}}/api/v1/products --user guest1:password -I次の出力が期待されます。
HTTP/1.1 403 Forbidden -
次のコマンドを実行します。結果は、
adminロールを持つadmin1ユーザーが/productpageと/api/v1/productsの両方のパスにアクセスできることを示しています。curl -X GET http://{{イングレスゲートウェイサービスの IP アドレス}}/productpage --user admin1:password -I次の出力が期待されます。
HTTP/1.1 200 OKcurl -X GET http://{{イングレスゲートウェイサービスの IP アドレス}}/api/v1/products --user admin1:password -I次の出力が期待されます。
HTTP/1.1 200 OK上記の結果は、定義された OPA ポリシーが期待どおりにアクセス制御を実装していることを示しています。
手順5:OPA ポリシーの動的更新
-
ACK クラスターで次のコマンドを実行して、opa-policy-add という名前の ConfigMap を更新します。
kubectl replace -n {ACK クラスターが存在する名前空間} -f - <<EOF apiVersion: v1 kind: ConfigMap metadata: name: opa-policy-add labels: ### ConfigMap に次のラベルを設定する必要があります。設定しない場合、ConfigMap が定義する OPA ポリシーは動的に更新できません。 openpolicyagent.org/policy: rego data: policy.rego: | ### 次のコードは、サンプルポリシーの定義を示しています。実際のニーズに基づいてポリシーを定義してください。 package istio.authz import input.attributes.request.http as http_request default allow = false allow { roles_for_user[r] required_roles[r] } roles_for_user[r] { r := user_roles[user_name][_] } required_roles[r] { perm := role_perms[r][_] perm.method = http_request.method perm.path = http_request.path } user_name = parsed { [_, encoded] := split(http_request.headers.authorization, " ") [parsed, _] := split(base64url.decode(encoded), ":") } user_roles = { "guest1": ["guest", "admin"], "admin1": ["admin"] } role_perms = { "guest": [ {"method": "GET", "path": "/productpage"}, ], "admin": [ {"method": "GET", "path": "/productpage"}, {"method": "GET", "path": "/api/v1/products"}, ], } EOF-
user_roles:ユーザーにロールを割り当てます。この例では、guest1にguestとadminの両方のロールを付与し、admin1にはadminロールを付与します。 -
role_perms:各ロールの権限を設定します。この例では、guestロールには /productpage パスへのアクセスを許可し、adminロールには /productpage と /api/v1/products パスへのアクセスを許可します。
-
-
次のコマンドを実行して、ポリシーのプッシュ結果を表示します。
プッシュのステータスは、ConfigMap の
アノテーションに更新されます。kubectl get configmap opa-policy-add -o yamlコマンド出力で ConfigMap を表示します。
-
プッシュが成功した場合、ConfigMap に次の情報が表示されます。
openpolicyagent.org/policy-status: '{"status":"ok"}' -
プッシュが失敗した場合、対応するエラーメッセージが表示されます。
-
手順6:OPA ポリシーが動的に更新されたことの確認
次の cURL コマンドを実行します。結果は、admin ロールが guest1 ユーザーに割り当てられたことを示します。さらに、guest1 ユーザーは、/productpage または /api/v1/products を含む URL を使用してアプリケーションにアクセスする権限を持ちます。
curl -X GET http://{{イングレスゲートウェイサービスの IP アドレス}}/productpage --user guest1:password -I次の出力が期待されます。
HTTP/1.1 200 OKcurl -X GET http://{{イングレスゲートウェイサービスの IP アドレス}}/api/v1/products --user guest1:password -I次の出力が期待されます。
HTTP/1.1 200 OKOPA ポリシーが更新される前、guest1 ユーザーは /productpage を含む URL でアプリケーションにアクセスできましたが、/api/v1/products を含む URL ではアクセスできませんでした。OPA ポリシーが更新された後、guest1 ユーザーは /productpage または /api/v1/products を含む URL でアプリケーションにアクセスできるようになりました。この結果は、OPA ポリシーが動的に更新されたことを示しています。