问题
We are using conftest to validate if our terraform changeset applies to certain rules & compliances. One thing we want to validate is wether our AWS resources are tagged according to the AWS tagging convention, which specifies certain tags to use (e.g. Owner, ApplicationRole, Project) and specifies that all tags and values are in CamelCase.
in terraform the changeset is portrayed in the following (simplified) json output:
{
"resource_changes":{
"provider_name":"aws",
"change":{
"before":{
},
"after":{
"tags":{
"ApplicationRole":"SomeValue",
"Owner":"SomeValue",
"Project":"SomeValue"
}
}
}
}
}
What I am now trying to do is to validate the following:
- Check wether tags are set.
- Validate if the keys and values are all camelcase.
- Check that the keys include the set (ApplicationRole, Owner, Project) in the minimum.
However, I am having trouble defining that in Rego (I am quite new to OPA).
Is there a way to "loop" over the keys and values of an object, and validate if they are formatted correctly?
in pseudo code:
for key, value in tags {
re_match(`([A-Z][a-z0-9]+)+`, key)
re_match(`([A-Z][a-z0-9]+)+`, value)
}
I have tried the following:
tags_camel_case(tags) {
some key
val := tags[key]
re_match(`^([A-Z][a-z0-9]+)+`, key) # why is key not evaluated?
re_match(`^([A-Z][a-z0-9]+)+`, val)
}
However, when evaluating against the following test json:
{
"AppRole": "SomeValue",
"appRole": "SomeValue"
}
the rule returns true, even though I am checking both key and value vs the regex
回答1:
The tags_camel_case(tags)
function returns true for the input with two keys because (by default) variables in Rego are existentially quantified. This means rule bodies are satisfied if for some set of variable bindings, the statements in the rule body are true. In the example above, the rule body would be satisfied by {key=AppRole, val=SomeValue}
.
To express for all you can use a simple trick. First write a rule to check if any of the tags ARE NOT camel case. Second write the rule to check if the first rule is not satisfied.
For example:
# checks if all tags are camel case
tags_camel_case(tags) {
not any_tags_not_camel_case(tags)
}
# checks if any tags are NOT camel case
any_tags_not_camel_case(tags) {
some key
val := tags[key]
not is_camel_case(key, val)
}
# checks if a and b are both camel case
is_camel_case(a, b) {
re_match(`^([A-Z][a-z0-9]+)+`, a)
re_match(`^([A-Z][a-z0-9]+)+`, b)
}
For more info on expression 'for all' in Rego see https://www.openpolicyagent.org/docs/latest/how-do-i-write-policies/#universal-quantification-for-all
来源:https://stackoverflow.com/questions/56663463/can-i-loop-over-keys-and-values-of-an-object-in-opa-to-validate-if-they-adhere-t