tirith icon indicating copy to clipboard operation
tirith copied to clipboard

🚀 Support variables in Tirith policy

Open Akshat0694 opened this issue 1 year ago • 5 comments

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.

Akshat0694 avatar Apr 17 '24 07:04 Akshat0694

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:

  1. How the syntax will look like
  2. How to provide the files through the cli
  3. How to replace the references in the policy with the actual variables before the evaluation

refeed avatar Aug 06 '24 07:08 refeed

Related to https://github.com/StackGuardian/tirith/issues/160

refeed avatar Aug 06 '24 07:08 refeed

  • 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) -i or —var-file ?
    • Have namespaces? file paths as namespaces?

arunim2405 avatar Aug 14 '24 09:08 arunim2405

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

refeed avatar Aug 14 '24 09:08 refeed

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

Steps:

  1. Parse the policy into dictionary
  2. Find the reference strings, recursively, one idea is to use regex to find the reference string and extract the variable name
  3. 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)

refeed avatar Aug 15 '24 07:08 refeed