🚀 Support variables in Tirith policy
Is your feature request related to a problem? Please describe. Tirith policies are hard-coded and do not support parameterization. Simple variation require the whole policy to written again.
Describe the solution you'd like If there is a way to define variables in the policy and pass their values in the run-time through a separate file or inline in the tirith command, it would vastly help.
Describe alternatives you've considered Re-writing the policies with all variations.
One important usecase: A policy wants to refer to a value in another JSON file (e.g. SG Template) so we don't need to change the value in the policy everytime the value changes
Inspiration: https://developer.hashicorp.com/terraform/language/values/variables
Tasks:
- How the syntax will look like
- How to provide the files through the cli
- How to replace the references in the policy with the actual variables before the evaluation
Related to https://github.com/StackGuardian/tirith/issues/160
- How to handle string reference when ContainedIn accepts a list?
- This policy needs a workflow to be created from a template to work. This won’t work on a workflow which uses no template.
-
What happens when the template does not have the value referenced. like ${reference::template.TerraformConfig.terraformVersion} does not exist. Use error_tolerance?
- How to specify error tolerance for referenced variables?
- Shall we create a category for workflow and template policy to know when to enforce which policy?
-
Accept several inputs (some as variables as well)
-ior—var-file?- Have namespaces? file paths as namespaces?
How to handle string reference when ContainedIn accepts a list?
I think we need to accept the value as is, ContainedIn works with strings as well. e.g. "a" ContainedIn "baz".
This policy needs a workflow to be created from a template to work. This won’t work on a workflow which uses no template.
Then we shouldn't run it on the workflow that wasn't created from a template right?
What happens when the template does not have the value referenced. like ${reference::template.TerraformConfig.terraformVersion} does not exist. Use error_tolerance?
Per our last discussion, Tirith will just throw an error when the variable is not found.
Shall we create a category for workflow and template policy to know when to enforce which policy?
I think we should, we can define a new key on the Policy object
Accept several inputs (some as variables as well) -i or —var-file ? Have namespaces? file paths as namespaces?
Per our last discussion, we'll accept both, but --var-file with the higher priority to implement. I think we can implement the namespaces later, by defining the reference string as ${var::somevar} we can extend it later to be ${var::<namspace>::somevar}
Also, I'd do the reference by using ${var::.... because it's much shorter
Task description: How to replace the references in the policy with the actual variables before the evaluation
- There will be reference strings included in the policy:
${var::somevar}- We need to search a way to replace the reference strings with the values of the variables, assuming we already got the variables dictionary e.g.
{"somevar": [123, 123]} - Some ideas is using regular expression to replace the reference
- We need to search a way to replace the reference strings with the values of the variables, assuming we already got the variables dictionary e.g.
Steps:
- Parse the policy into dictionary
- Find the reference strings, recursively, one idea is to use regex to find the reference string and extract the variable name
- Replace the reference string with the actual variable
Example:
{
"meta": {
"version": "v1",
"required_provider": "stackguardian/json"
},
"evaluators": [
{
"id": "check0",
"provider_args": {
"operation_type": "get_value",
"key_path": "z.b"
},
"condition": {
"type": "Equals",
"value": "${var::something}"
}
}
],
"eval_expression": "check0"
}
Assuming the variable dict is there:
{"something": {"nested": {"a": "b"}}
After replacement:
{
"meta": {
"version": "v1",
"required_provider": "stackguardian/json"
},
"evaluators": [
{
"id": "check0",
"provider_args": {
"operation_type": "get_value",
"key_path": "z.b"
},
"condition": {
"type": "Equals",
"value": {"nested": {"a": "b"}}
}
}
],
"eval_expression": "check0"
}
User can also put the reference string on another part of the policy, e.g. the key_path
Cases to test:
- When the user wants to put a string that coincidentally matches our reference string syntax, we shouldn't parse as a reference string (we can add a escape sequence)