Open7
Regoの書き方を勉強する
ピン留めされたアイテム
主にOPAのSlackから拾ってきたQAのRegoが、Slackとともに履歴から消えていくのがもったいないので勉強がてら残しておく。
Terraformで、あるAWSのresourceに必ず foo
, bar
, baz
のタグがついてることを確認する
warn[msg] {
required_tags := {"foo", "bar", "baz"}
startswith(resource.type, "aws_")
resource.change.after.tags_all
provided_tag_names := {tag | resource.change.after.tags_all[tag]}
missing_tags := required_tags - provided_tag_names
count(missing_tags) > 0
msg := sprintf("Mandatory tag(s) missing on %v (missing tags: %v)", [resource.address, concat(",", missing_tags)])
}
RBACで、RoleにPermissionがマッピングされているとき、 input
に role
が渡された場合の、対象となる permission
をレスポンスで返す。
groups_to_permissions = {
"admin": ["p1", "p2", "p3", "p4"],
"sales": ["p1", "p2", "p3", "p4"],
"shipping": ["p1", "p2"]
}
permissions = {
"p1": {"action": "read", "resource": "firstname"},
"p2": {"action": "read", "resource": "lastname"},
"p3": {"action": "write", "resource": "firstname"},
"p4": {"action": "write", "resource": "lastname"},
}
# Permissions_for_group...
permissions_for_group[perms] {
x := groups_to_permissions[input.role][_]
perms := permissions[x]
}
InputとOutputの例
# Input
# {
# "role": "shipping"
# }
# Output
# [
# {
# "action": "read",
# "resource": "firstname"
# },
# {
# "action": "read",
# "resource": "lastname"
# }
# ]
- ユーザーは、自分が
owner
のリソースにアクセスできる。 -
group
はアクセスできるリソースのtype
が指定されている。 - ユーザーは、自分が所属する
group
に所属している他ユーザーがowner
のリソースのtype
が、所属しているgroup
でアクセス可能であればアクセスできる。
Regoの↓あたりがポイント。
can_access_resource {
common_groups[group]
g := group[_]
objects[input.resource].type == groups[g].access_resources_within_group[_]
}
common_groups[group] {
owner := objects[input.resource].owner
client := input.user_id
# owner can access own documents
owner != client
groups_owner_set := {x | x := user_groups[owner][_]}
groups_client_set := {x | x := user_groups[client][_]}
group := groups_owner_set & groups_client_set
}
引用元(Slack):https://openpolicyagent.slack.com/archives/C1H19LW4F/p1623967008280200
あらかじめ使っちゃいけないポートが指定されていて、 input.range
で渡されたポート範囲にそのポートが含まれていたら deny
にそのポートをレスポンスで返す。
prohibited_ports := {3, 5, 6}
deny[msg] {
p := prohibited_ports[_]
my_range[p] # lookup
msg := sprintf("prohibited port '%v'", [p])
}
my_range = result_set {
x := split(input.range, " - ")
result := numbers.range(to_number(x[0]), to_number(x[1]))
result_set := {x | x := result[_]} # convert to set
}
Complete Rule Ver.
Multiple Results Ver.
下の2つの例では、Setの差分の抽出方法が違う。
a := [
{
"prop": "a"
},
{
"prop": "b"
}
]
set_a = result {
result := { x | x := a[_].prop }
}
a := [
{
"prop": "a"
},
{
"prop": "b"
}
]
set_a[result] {
result := { x | x := a[_].prop }
}
ユースケースに疑問があるものの、インプットがnumberだったときだけstringに変換するためのRegoの書き方。
num_to_string(x) = sprintf("%v", [x]) {
is_number(x)
}