Using fregot eval
to Test Custom Rules¶
Note
Don’t forget to download the fugue.rego library and retrieve a test input file!
This document focuses on using Fregot’s eval
command to test custom rules. fregot eval
is useful for quickly evaluating a single expression, such as policy
.
Using fregot eval
to test a simple rule¶
Simple rules operate on a single resource at a time and advanced rules operate on an entire environment at a time. To test a simple rule with fregot eval
, you tell Fregot exactly which resource in the input
document to test, using the resource’s identifier in double-quotes.
The command structure looks like this:
fregot eval -i <JSON input filename> 'data.<package name>.<allow or deny> with input as input.resources["resource-identifier-goes-here"] <rule filename> fugue.rego
For example:
fregot eval -i input.json 'data.vm_size_simple.allow with input as input.resources["azurerm_virtual_machine.compliant_vm"]' simple-vm-size.rego fugue.rego
You can get the resource’s identifier from the input document. It’ll look something like resource_type.resource_name
. In the example below, which contains two resources, the identifiers are azurerm_virtual_machine.compliant_vm
and azurerm_virtual_machine.noncompliant_vm
:
{ "resources": { "azurerm_virtual_machine.compliant_vm": { "_provider": "provider.azurerm", "_skeleton": { "depends_on": null, "deposed": null, "primary": { "id": "/subscriptions/12345678-1234-5678-9012-123456789012/resourceGroups/example-rg/providers/Microsoft.Compute/virtualMachines/compliantvm", "meta": null, "tainted": false }, } <cut for brevity> }, "azurerm_virtual_machine.noncompliant_vm": { "_provider": "provider.azurerm", "_skeleton": { "depends_on": null, "deposed": null, "primary": { "id": "/subscriptions/12345678-1234-5678-9012-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Compute/virtualMachines/noncompliantvm", "meta": null, "tainted": false } } <cut for brevity> } } }
The output would be a single [true]
or []
(undefined, aka false) value, because you specified a single resource when you entered with input as input.resources["resource-identifier-goes-here"]
as part of the fregot eval
command:
[true]
If you tested an allow
rule and the result is [true]
, the resource is compliant. If you tested a deny
rule and the result is [true]
, the resource is noncompliant.
Using fregot eval
to test an advanced rule¶
You can use fregot eval
to test the policy
rule in an advanced rule. Unlike simple rules, advanced rules don’t require you to specify a particular resource during testing, because the policy
set looks at all resources in the input.
The example below assumes that the input file, .rego
file, and fugue.rego
library are all in the present working directory:
fregot eval -i <JSON input filename> data.<package name>.policy <rule filename> fugue.rego
For example:
fregot eval -i input.json data.vm_size.policy vm_size.rego fugue.rego
Note that we haven’t specified 'with input as...'
as part of the command. That’s because a policy
rule returns a judgment for all resources in an environment, rather than just one, so there’s no need to single out a resource for Fregot to evaluate.
You’ll see results like this:
[[{"id":"/subscriptions/12345678-1234-5678-9012-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Compute/virtualMachines/noncompliantvm","message":"invalid","type":"azurerm_virtual_machine","valid":false},{"id":"/subscriptions/12345678-1234-5678-9012-123456789012/resourceGroups/example-rg/providers/Microsoft.Compute/virtualMachines/compliantvm","message":"","type":"azurerm_virtual_machine","valid":true}]]
If you have jq installed, you can pipe the results into jq
to format the response nicely:
fregot eval -i input.json data.vm_size.policy vm_size.rego fugue.rego | jq .
You’ll see results like this:
[ [ { "id": "/subscriptions/12345678-1234-5678-9012-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Compute/virtualMachines/noncompliantvm", "message": "invalid", "type": "azurerm_virtual_machine", "valid": false }, { "id": "/subscriptions/12345678-1234-5678-9012-123456789012/resourceGroups/example-rg/providers/Microsoft.Compute/virtualMachines/compliantvm", "message": "", "type": "azurerm_virtual_machine", "valid": true } ] ]
In this example, the resource with the ID /subscriptions/12345678-1234-5678-9012-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Compute/virtualMachines/noncompliantvm
returns "valid": false
and is therefore noncompliant with the rule we tested it against.
The resource with the ID /subscriptions/12345678-1234-5678-9012-123456789012/resourceGroups/example-rg/providers/Microsoft.Compute/virtualMachines/compliantvm
is "valid": true
(compliant with the rule).
Note
The resource identifier is different from the resource ID.
The identifier is how Fugue uniquely identifies a resource in an input document, and is at the level directly below the
resources
object in the input.The ID is how the provider identifies a resource, and is called
id
in the input.
Below, the identifier and the id
are in bold:
{ "resources": { "azurerm_virtual_machine.compliant_vm": { "_provider": "provider.azurerm", "_skeleton": { "depends_on": null, "deposed": null, "primary": { "id": "/subscriptions/12345678-1234-5678-9012-123456789012/resourceGroups/example-rg/providers/Microsoft.Compute/virtualMachines/compliantvm", "meta": null, "tainted": false }, } <cut for brevity>