PR

注目のOpen Policy Agent、その概要とKubernetesでの活用事例

2020年5月19日(火)
吉田 龍馬(よしだ・りゅうま)

はじめに

Kubernetesコミュニティにおいて、ここ数年で国内外の企業がOpen Policy Agentを導入しているという話を耳にすることが多くなってきました。今回は、KubernetesをはじめとしたCloud Native技術には触れているが、Open Policy Agentにはまだ触れたことがない方向けに、その概要や仕組み、Kubernetesでの活用事例などを紹介します。

なお、ここで扱うOpen Policy Agentの情報は執筆時点(2020年4月26日現在)での最新バージョンv0.19.1に基づいたものとなります。

Open Policy Agentとは

Open Policy Agent(以下、OPA)はオープンソースの軽量かつ汎用的なポリシーエンジンです。ポリシーをコードとして管理する(Policy as Code)ためのポリシー言語Regoと、アプリケーションからの問い合わせに対してポリシーの評価を行うAPIが提供されています。OPAは"oh-pa"、Regoは"ray-go"と発音します。

OPAをサイドカー、デーモン、ライブラリなどでアプリケーションに統合し、アプリケーション内のリクエスト制御をAPIを介してOPAに問い合わせた評価結果から判定するアーキテクチャにすることで、アプリケーションからポリシー制御の機能を切り離すことが可能になります。

OPAによりポリシー制御を分離することで、アプリケーションのソースコード変更、再デプロイを必要としないポリシー管理や、様々なアプリケーションにおけるポリシー制御を統一された仕組みで実現できます。

OPAの公式ページでは、マイクロサービスにおけるサービス間の認可、問い合わせ元の権限に基づいたデータフィルタリング、KubernetesのAdmission Controlを使ったリソースのバリデーション、SSHとsudoでのアクセス制御、Terraformの設定ファイルのバリデーションなど、様々なユースケースが紹介されています。

OPAの仕組み

ハイレベルアーキテクチャ

OPAはDocumentの集合であるData、Ruleの集合であるPolicyと、それらを操作するAPIで構成され、APIを介して受け取った問い合わせを元にDataをPolicyで評価した結果を返すアーキテクチャとなっています。

DataとPoilicyについて

DataはJSON形式のデータで、アプリケーションまたはユーザーがData APIを介して外部からロードする静的データのBase Documentと、RuleによるData(Base Document、Virtual Document)の評価結果であるVirtual Documentの2種類で構成されています。問い合わせ時の入力データもBase Documentに分類されますが、文脈によってInput DocumentやQuery Inputと表現されます。

PolicyはRegoを使用して定義されたRuleから構成されています。単一または複数のRuleを定義したRegoファイルをPolicy Moduleとして、Policy APIを介してOPAに追加できます。

チュートリアル

OPAでHTTP APIを認可することを想定したチュートリアルを紹介します。

仕様

HTTP APIに給与を参照するエンドポイント”GET /finance/salary/{user}”が実装されていると仮定して、以下のポリシーに基づいた認可処理をOPAで行っていきます。

  • 社員は自身の給与を参照できる
  • マネージャーは部下の給与も参照できる

また、OPAへの問い合わせ時には、入力データとして以下の情報を渡すこととします。

  • HTTPメソッド
  • エンドポイント
  • リクエスト元のユーザー

チュートリアルの実施

OPAをServerモードで起動します。今回はAPIも操作したいので、ローカルにDockerで起動したOPAを利用していきますが、公式から提供されているRego Playgroundを使ってWeb上で試すことも可能です。

$ docker run --rm -d --name opa -p 8181:8181 openpolicyagent/opa:0.19.1 run --server

起動時点でまだData, Policyは存在しないため、まずはData API経由で社員情報をBase DocumentとしてOPAに追加します。今回はaliceの部下がbob、charlieの部下がdavidと定義しています。

$ cat subordinates.json
{
  "alice": ["bob"],
  "bob": [],
  "charlie": ["david"],
  "david": []
}

$ curl -X PUT -H 'Content-Type:application/json' --data-binary @subordinates.json \
    localhost:8181/v1/data/subordinates

追加したBase DocumentはData APIを介して参照できます。Data APIを実行してみるとレスポンスのresultに先程追加した社員情報が格納されていることがわかります。

$ curl -s localhost:8181/v1/data/subordinates | jq .
{
  "result": {
    "alice": [
      "bob"
    ],
    "bob": [],
    "charlie": [
      "david"
    ],
    "david": []
  }
}

次に、Policy Moduleを作成します。このPolicy Module内ではallowという給与が参照可能か真偽値を返すRuleを定義しています。allowでは社員情報と入力データを元に評価が行われます。

また、パッケージ名とRule名から評価結果であるVirtual Documentの参照先が決定されます。今回はhttpapi.authzというパッケージ名でallowというRule名なので、Data APIから参照する場合は/v1/data/httpapi/authz/allow、他のRuleから参照する場合はdata.httpapi.authz.allowから評価結果を得ることができます。

$ cat httpapi_authz.rego
package httpapi.authz

# 社員情報をインポート
import data.subordinates as subord

default allow = false

# 社員は自身の給与を参照できる
allow {
  some username
  input.method == "GET"
  input.path = ["finance", "salary", username]
  input.user == username
}

# マネージャーは部下の給与も参照できる
allow {
  some username
  input.method == "GET"
  input.path = ["finance", "salary", username]
  subord[input.user][_] == username
}

作成したPolicy ModuleをPolicy APIを介してOPAに追加します。

$ curl -X PUT -H 'Content-Type: text/plain' --data-binary @httpapi_authz.rego \
    localhost:8181/v1/policies/httpapi_authz

これでData, Policyの準備が完了したので、OPAに問い合わせのテストを行っていきます。以下はaliceがalice(自分)の給与を参照できるか問い合わせた例です。自分の給与は参照できるポリシーなのでtrueという評価結果が得られました。

$ cat alice_to_alice.json
{
  "input": {
    "method": "GET",
    "path": ["finance", "salary", "alice"],
    "user": "alice"
  }
}

$ curl -s -X POST -H 'Content-Type:application/json' --data-binary @alice_to_alice.json \
    localhost:8181/v1/data/httpapi/authz/allow | jq .
{
  "result": true
}

次は、aliceがbobの給与を参照できるか問い合わせた例です。マネージャーは部下の給与も参照できるポリシーなのでtrueという評価結果が得られました。

$ cat alice_to_bob.json
{
  "input": {
    "method": "GET",
    "path": ["finance", "salary", "bob"],
    "user": "alice"
  }
}

$ curl -s -X POST -H 'Content-Type:application/json' --data-binary @alice_to_bob.json \
    localhost:8181/v1/data/httpapi/authz/allow | jq .
{
  "result": true
}

最後は、aliceがdavidの給与を参照できるか問い合わせた例です。マネージャーは部下の給与も参照できるポリシーですが、davidはcharlieの部下でaliceの部下ではないのでfalseという評価結果が得られました。

$ cat alice_to_david.json
{
  "input": {
    "method": "GET",
    "path": ["finance", "salary", "david"],
    "user": "alice"
  }
}

$ curl -s -X POST -H 'Content-Type:application/json' --data-binary @alice_to_david.json \
    localhost:8181/v1/data/httpapi/authz/allow | jq .
{
  "result": false
}

今回は手動で入力データを作成してOPAに問い合わせを行いましたが、HTTP APIの内部でリクエスト情報から入力データを自動生成してOPAに問い合わせを行い、得られた評価結果からリクエスト制御を行うことでHTTP APIの認可をOPAに切り出すことができます。

また、このチュートリアルではHTTP APIの認可として簡単なポリシーを例にしましたが、RegoにはBuild-inされている関数が多数あるので、JWTを検証してClaimsの値を使用したり、TLSクライアント証明書の情報を使用したりなど、要件に応じてポリシーを作り込んでいくことも可能です。

KubernetesでのOPA活用事例

ここでは、KubernetesにおけるOPAの活用事例を紹介します。

Kubernetesリソースのバリデーション

Kubernetesクラスタに意図しないリソースが適用されることを避けるために、GatekeeperをAdmission Controller Webhookとして導入することで、kube-apiserverでOPAによるCRDベースのポリシーに基づいたリソースのバリデーションを行うことができます。これはPodSecurityPolicyの代替にもなります。

ほかにもkube-apiserverでのバリデーションではなく、マニフェストをバージョン管理しているリポジトリにCIでconftestを導入することで、マニフェストに対してOPAによるポリシーに基づいたユニットテストを実行することもできます。

RBACの拡張

Kubernetes Authorization via Open Policy Agentで紹介されていた事例です。社内にKubernetesクラスタを提供しているチームでは利用者の拡大によりRBACによる認可の管理に課題を抱えており、RBACのようなホワイトリスト形式での認可に加えOPAによるブラックリスト形式の認可を採用したという話です。アーキテクチャとしてはWebhook ModuleとAdmission Controller WebhookにGatekeeperを採用しているようです。

ワークロードから実行された悪意ある処理の検知

Secure Kubernetes using eBPF & Open Policy Agentで紹介されていた事例です。Kubernetesクラスタにデプロイされているワークロードから実行された悪意のある処理を検知するためにeBPFを使用してシステムコールを解析し、ポリシー違反がないかをOPAに問い合わせるアーキテクチャを採用しているようです。

Service Meshにおけるサービス間の認可

Data PlaneとしてEnvoyを採用しているService Meshであれば、EnvoyのExternal Authorization(認可の処理を別システムに任せるための機能)としてOPAを統合することで、リクエスト情報を元にサービス間の認可をOPAで行うことができます。また、Istioを使用しているケースでは公式で提供されているプラグインが利用できます。

おわりに

今回はOPAに触れたことがない方向けに、その概要や仕組み、Kubernetesでの活用事例などを紹介しました。OPAはCNCFのIncubatingプロジェクト(2020年4月26日現在)としてホストされており、開発も活発でコミュニティも拡大していて、国内外で採用事例が増えてきています。現在抱えている課題をOPAで解決できそうであれば、導入を検討してみるのも良いでしょう。

【参考資料】
https://www.openpolicyagent.org
https://github.com/open-policy-agent/opa

著者
吉田 龍馬(よしだ・りゅうま)
ゼットラボ株式会社/ヤフー株式会社
2015年にDMM.comに新卒として入社。Hadoop Ecosystemを利用したデータ分析基盤の開発と運用に従事。2018年12月よりゼットラボ株式会社でKubernetesをベースとしたインフラ基盤の研究開発を行っており、現在はCloud Nativeなアクセス制御システム(認証、認可)の研究開発を担当している。SPIFFE/SPIREプロジェクトのコントリビューター。CKA-1900-001691-0100保有。Twitter: @ryysud、GitHub: @ryysud

連載バックナンバー

Think IT会員サービス無料登録受付中

Think ITでは、より付加価値の高いコンテンツを会員サービスとして提供しています。会員登録を済ませてThink ITのWebサイトにログインすることでさまざまな限定特典を入手できるようになります。

Think IT会員サービスの概要とメリットをチェック

他にもこの記事が読まれています