Open Policy Agent (OPA) 事始め
Copyright: Hiro Osaki 2021
はじめに
このドキュメントは、Open Policy Agent (OPA) を一度触ってみたいという方向けです.
最短経路は8分で済みます. ソースコードもHello worldレベルを目指します.
(本記事は, OPA up and runningのQiita転載版になります.)
1. 初めてのRego: Rego Playground
OPAとそこで使われるRego言語がどんなものなのかを掴むのに, OPAをインストールす必要はありません. 最速の方法は, Styraが開発した"Rego Playground" というWebサービスを使うことです.
1.1. Rego言語のプログラムを動かしてみる (所要: 5分)
- https://play.openpolicyagent.org/ にアクセス.
-
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データを生成します.
詳細は, 公式ドキュメントの
introduction
https://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
OPA
repository: https://github.com/open-policy-agent/opa