conftest icon indicating copy to clipboard operation
conftest copied to clipboard

Exceptions are always considered to be exceptions in output

Open jpreese opened this issue 4 years ago • 2 comments

If an exception exists, it is always considered to be an exception in the output -- regardless of if the policy failed. For example:

package main

deny_foo[msg] {
  false
  msg := "foo"
}

exception[rules] {
  rules = ["foo"]
}
echo "{}" | conftest test -

Results in:

EXCP - - main - data.main.exception[_][_] == "foo"

1 test, 0 passed, 0 warnings, 0 failures, 1 exception

However, the policy did not fail.

It feels more accurate to consider this a passed result and only trigger an exception in the output if a policy would have otherwise failed. Pending discussion from the community.

jpreese avatar Apr 21 '21 21:04 jpreese

Some thoughts from Slack:

  • "Exception" verbiage in its current form could be considered confusing. A better name may be "Exclusions" to represent what is really happening. Also "Skip" or "Ignore".

  • The proposed behavior in this PR is more true to the word "Exception". However, would require a v1.0.0 release to do any large re-name refactor.

jpreese avatar May 07 '21 22:05 jpreese

Hi,

just came across this. I have a similar issue when trying to enforce naming-conventions to an existing terraform project (while keeping a list of exceptions).

For example:

# main.tf
resource "null_resource" "no-exception-resource" {

}

resource "null_resource" "my-resource-name" {

}

resource "null_resource" "my_other_resource" {

}

with a rego file:

package main

names = { name | _ := input.resource[_][name] }

resource_name_exceptions = {
 "my-resource-name"
}

deny_no_dashes_in_resource_name[msg] {
    name = names[_]
    contains(name, "-")
    msg := sprintf("Name '%s' should not have any dashes in it", [name])
}


exception[rules] {
  name = names[_]
  not resource_name_exceptions[name]
  rules = ["no_dashes_in_resource_name"]
}
$ conftest test main.tf
EXCP - /Users/hamishhutchings/scratch/tf-policy/main.tf - main - data.main.exception[_][_] == "no_dashes_in_resource_name"

It's not a foolproof method, because there isn't any notification that an exception is happening, but I'm currently doing the following:

package main

names = { name | _ := input.resource[_][name] }

resource_name_exceptions = {
 "my-resource-name"
}

deny_no_dashes_in_resource_name[msg] {
    name = names[_]
    contains(name, "-")

    # Exceptions are currently limited to excluding a whole file.
    # So we need to filter out exceptions in the rule itself.
    not resource_name_exceptions[name]
    msg := sprintf("Name '%s' should not have any dashes in it", [name])
}
$ conftest test main.tf
FAIL - /Users/hamishhutchings/scratch/tf-policy/main.tf - main - Name 'no-exception-resource' should not have any dashes in it

I would suggest updating the the documentation linked here to explicitly state that an exclusion will exclude the whole file, as it's not very clear until one starts playing with it.


EDIT: I did a bit of playing, And expanding the above gives what I want:

package main

names = { name | _ := input.resource[_][name] }

resource_name_exceptions = {
 "my-resource-name"
}

deny_no_dashes_in_resource_name[msg] {
  false
}

exception[rules] {
    name = names[_]
    resource_name_exceptions[name]
    rules = ["no_dashes_in_resource_name"]
}

deny[msg] {
    name = names[_]
    contains(name, "-")

    # Exceptions are currently limited to excluding a whole file.
    # So we need to filter out exceptions in the rule itself.
    not resource_name_exceptions[name]
    msg := sprintf("Name '%s' should not have any dashes in it", [name])
}

moredhel avatar Jun 21 '21 14:06 moredhel