OPA 事始め
Open Policy Agent (OPA) 事始め
Copyright: Hiro Osaki 2021
はじめに
このドキュメントは、Open Policy Agent (OPA) を一度触ってみたいという方向けです.
最短経路は8分で済みます.
(本記事は, OPA up and runningのZenn転載版になります.)
1. 初めてのRego: Rego Playground
OPAとそこで使われるRego言語がどんなものなのかを掴むのに, OPAをインストールす必要はありません. 最速の方法は, Styraが開発した"Rego Playground" というWebサービスを使うことです.
1.1. Rego言語のプログラムを動かしてみる (所要: 5分)
-
Evaluateボタンをクリック.
-
初の Rego 言語 プログラミングにチャレンジしましょう. 左のウィンドウの一番下に, 以下の3行を足します.
newdata = msg { msg := concat("", ["Received the message: ", input.message]) }この3行は、新しいデータ
newdataを追加するコードです. -
再度
Evaluateをクリック.OUTPUTウィンドウに新しいデータnewdataが追加されます.
その結果はこのようになります.
{ "hello": true, "newdata": "Received the message: world" }2行目の
"newdata": ...が、新しいデータです. それ以外の"hello"は, もともとのソースコードhello {...}の結果です. -
inputを変える-
右の
INPUTウィンドウに"message":...と書かれてあります. -
この中身を
"message": "distopia"に変えてみます. -
Evaluateを再度クリック. このような結果が出るでしょう.{ "hello": false, "newdata": "Received the message: distopia" }
-
helloの結果を見ます. 先ほどのtrueからfalseに結果が変わっています. 理由は,helloの中身にm == "world"と書かれているためです.この文は, もし
messageが"world"なら, 返り値はtrueになることを意味します.そうでなければ, 返り値は
falseです.
-
-
dataを使ってみる-
dataウィンドウに以下を書き込みます.{ "rule": "be good" } -
左のウィンドウの最後の行に以下を追記します.
importdata = msg { msg := concat("", ["Received the static data: ", data.rule]) } -
Evaluateを再度クリック.

-
新たなコードの結果が表示されます.
"importdata": "Received the static data: be good",
-
1.2. まとめ: OPA が何をするのか (所要: 3分)
-
Rego Playground を使ってみて分かること.

-
OPA はポリシーファイルを読み込む.
ポリシーファイルは Rego 言語でnewdata = msg {...}のように記述されます. (Playgroundの左ウィンドウ) -
OPA は
inputのデータを受け取る.
inputのデータはJSONフォーマットでなければなりません. (Playgroundの右上ウィンドウ) -
OPA は
dataのデータも受け取る.
dataのデータもJSONフォーマットでなければなりません. (Playgroundの右中央のウィンドウ.dataは初期値で{}になっています) -
OPA はポリシーの処理により
outputを生成する.
生成されるoutputもJSONフォーマットです. (Playgroundの右下ウィンドウ)
-
OPA はポリシーファイルを読み込む.
-
まとめ: OPA はRegoファイルを読み込み, JSON データを処理します. そして, OPA は 出力のJSONデータを生成します.
-
詳細は, 公式ドキュメントの
introductionhttps://www.openpolicyagent.org/docs/latest/ に記載されています.
2. 自分の環境でOPAを起動する
2.1. OPA をインストールする(所要: ~ 5分)
-
MacOSなら, 以下のコマンドでインストールできます.
brew install opa -
その他の環境なら, 以下のドキュメントに従い
opaコマンドをインストールします.
2.2. OPAの起動を確認する (所要: 5分))
-
opa runを実行してみます.$ opa runその実行中に,
a = 3やexitを実行できます.$ opa run OPA 0.26.0 (commit , built at ) Run 'help' to see a list of commands and check for updates. > a = 3 Rule 'a' defined in package repl. Type 'show' to see rules. > x = 3 Rule 'x' defined in package repl. Type 'show' to see rules. > show package repl a = 3 x = 3 > exit
2.3. OPAをサーバとして起動する (所要: 5分)
-
example.regoというファイルを作成します.mkdir example/ cd example/ # create example.rego以下を
example.regoとして保存します. 1章と中身は同じですね.package play default hello = false hello { m := input.message m == "world" } newdata = msg { msg := concat("", ["Received the message: ", input.message]) } importdata = msg { msg := concat("", ["Received the static data: ", data.rule]) }input.jsonも以下の内容で作成します. これも1章と同じです.# create input.json{ "input": { "message": "world" } } -
以下コマンドを実行します.
opa run -s ./example.rego -
別のコマンドラインから OPA サーバにリクエストを出します。
- まずは
/v1/data/playにアクセスします.
$ curl localhost:8181/v1/data/play -i -d @input.json -H 'Content-Type: application/json' {"result":{"hello":true,"newdata":"Received the message: world"}}- 次に,
/v1/data/play/helloにアクセスします.
$ curl localhost:8181/v1/data/play/hello -i -d @input.json -H 'Content-Type: application/json' {"result":true} # Same as the value of "hello" in section 1.1/v1/data/play/newdata
$ curl localhost:8181/v1/data/play/newdata -i -d @input.json -H 'Content-Type: application/json' {"result":"Received the message: world"} # Same as the value of "newdata" in section 1.1/v1/data/play/importdata
$ curl localhost:8181/v1/data/play/importdata -i -d @input.json -H 'Content-Type: application/json' {} # This is undefined because no data is imported. - まずは
2.4. OPA にデータを読み込ませる (5 min)
# create data.json
{
"rule": "be good"
}
サーバの起動コマンドを以下のように変えて, OPAサーバを再度起動します.
# add ./data.json to command arguments
opa run -s ./example.rego ./data.json
-
OPAサーバにリクエストを送信します.
/v1/data/play
$ curl localhost:8181/v1/data/play -i -d @input.json -H 'Content-Type: application/json' {"result":{"hello":true,"importdata":"Received the static data: be good","newdata":"Received the message: world"}} # Field "importdata" was added.このように、読み込んだデータに応じてOPAが処理を変えます.
/v1/data/play/importdata
$ curl localhost:8181/v1/data/play/importdata -i -d @input.json -H 'Content-Type: application/json' {"result":"Received the static data: be good"} # Data was added. Same as the value of "importdata" in section 1.1
2.5. まとめ: OPAができること (所要: 3分)
- OPA サーバが自分の環境で起動でき, HTTPリクエストに応じて処理を実行しました.
- HTTP リクエストで JSONデータを送信します.
- さらにボディは
{"input": ***}の形式である必要があります.
- OPA サーバは
<server>/v1/api/data/<package name>[/<object name>]のようなエンドポイントを持ちます.- Regoファイルの最初の行
package playにより,<package name>がplayであることを定義しています. - Regoファイルの中のルールの定義
hello {...}により,<object name>がhelloであることを定義しています.
- Regoファイルの最初の行
- OPAの返り値は,
{"result": ***}の形式のJSONデータです.- 返り値の中身は, アクセスするエンドポイントによって変わります.
- もし
<package name>がリクエストされると, 返り値は"result"フィールドに全部の値を含みます. - もし
<package name>/<object name>がリクエストされると, 返り値は"result"フィールドに指定されたオブジェクト = ルールの結果が含まれます.
- もし
- 返り値の中身は, アクセスするエンドポイントによって変わります.
3. 参考資料
- Rego Playground: https://play.openpolicyagent.org/
- Github
OPArepository: https://github.com/open-policy-agent/opa
Discussion