OPAでANDとORの条件を組み合わせる

OPAのSlackでやりとりされている内容とかが流れていってしまうのが勿体無いので残していこうと思います。(将来的に索引にできたら良いかなと)

f:id:kenev:20190331164752p:plain

上図のようなパターンを考えてみましょう。文で表現すると以下のとおりです。

p1, p2, p3, additional_pがすべてtrueの場合に許可する。additional_pはp9またはp10がtrueであれば良い。

これをRegoで書くと次のようになります。

package play

default allow = false

# this rule says "allow is true if p1 and p2 and p3 and additional_p"
allow {
    p1
    p2
    p3
    additional_p
}

p1 { input.x == 1 }
p2 { input.y == 2 }
p3 { input.z == 3 }

# additional_p is true if p9 or p10
additional_p {
    p9
}

additional_p {
    p10
}

p9 {
    input.a == "foo"
}

p10 {
    input.a == "bar"
}

ポイントは以下のとおりかと!

  • ルールから別のルールを参照できる
  • ルールの中身に書いた式は暗黙的にANDとして扱われる(allowの中のp1, p2, p3, additional_p)
  • 同名のルールは暗黙的にORとして扱われる(additional_p)

試してみましょう!

次のJSONをInputに入れてみます。

{
  "a": "bar",
  "x": 1,
  "y": 2,
  "z": 3
}

そうするとOutputは次のようになります。

{
  "result": {
    "additional_p": true,
    "allow": true,
    "p1": true,
    "p10": true,
    "p2": true,
    "p3": true
  }
}

true の結果が全部返ってくるのでちょっと見づらいですけど、 allowtrue なのがわかります。

Inputの "a": "foo" とした場合でも allowtrue です! なぜなら p9 OR p10 であれば( input.afoo または bar であれば ) additional_ptrue だからです。

Rego Playgroundは下になりますので実際にInputを変えてみてOutputを確認してみると動きの違いを実際にみることができます!

play.openpolicyagent.org

おわりに

  • PolicyのORやANDは暗黙的に行われる
  • ルールの中からルールを呼び出すことでルールを整理できる

参考

kenfdev.hateblo.jp