Plugin IaC Governance for any pipeline, running anywhere. Evaluate plans with Tirith, protect sensitive values, enforce centralised governance, and surface actionable results before infrastructure changes are applied.
Tirith reads the plan your pipeline already produces — the output of terraform show -json tfplan —
checks it against your policies, and exits non-zero so a violating change never reaches apply. The
reason it is a plugin rather than an integration is that one policy set then covers every pipeline
you run it from: the same policy files gate a GitHub Actions job, a GitLab job and a laptop, and in
platform mode Tirith rules and Checkov findings come back in one verdict instead of two tools you
have to reconcile by hand.
It is Apache-2.0 and needs no account. Policies are JSON files in your repository, evaluation happens
on your own runner, and nothing is sent anywhere. If you would rather keep policy in one place across
many repositories, tirith platform check evaluates against the policies a
StackGuardian organization enforces instead — same document, same
verdict, same exit codes. That mode is optional and is the only part that talks to a network.
- What is Tirith?
- Features
- Installation
- Usage
- Run it in CI
- Exit codes
- Evaluating against your StackGuardian organization
- Example Tirith policies
- Getting Started
- Want to contribute?
- Submitting a feedback
- Support
- License
Tirith turns a declarative policy — a JSON file, not a program — into a pass or fail verdict on a concrete infrastructure change. Point it at a terraform plan, a terraform state file, a Kubernetes manifest, an Infracost breakdown or any JSON document, and it reports which rules passed, which failed, and on which resource and value.
- DevSecOps engineers
- Infrastructure architects
- Cloud administrators
- Anyone involved in managing and enforcing infrastructure guardrails
- Simplifies Policy Management: Managing policies in IaC can be complex and costly, requiring multiple codebases. Tirith abstracts these complexities, allowing for centralized and streamlined policy management.
- Extends Beyond Resource Configurations: Tirith's policies cover more than just resource configurations, including cost management and CI/CD definitions, offering a comprehensive compliance solution.
- Cost-Efficient: Maintaining policies within IaC logic is expensive. Tirith reduces costs by centralizing policy management, eliminating the need for duplicate policies across different IaC codebases.
- Eases Policy Creation: Writing Policy as Code is challenging. Tirith simplifies this by providing an intuitive, declarative approach, making it easier to ensure compliance and security.
- An easy to read and simple way to define policy as code against structured formats.
- Use providers to define policies for terraform plan, infracost or any abstract JSON.
- Easily evaluate inputs against policy using pre-defined evaluators like ContainedIn, Equals, RegexMatch etc.
- Write your own provider (plugin) by leveraging a highly extensible and pluggable architecture to support any input formats.
pip install git+https://github.com/StackGuardian/tirith.git
Pin a tag rather than tracking the default branch, so a CI job cannot change behaviour underneath you:
pip install "git+https://github.com/StackGuardian/tirith.git@1.0.5"
1.0.5 is the newest tag; git ls-remote --tags https://github.com/StackGuardian/tirith.git lists
them. Tirith is not on PyPI — pip install tirith installs an unrelated project of the same name, so
install from git. Python 3.8 or newer.
- Clone the repository to your local machine:
git clone https://github.com/StackGuardian/tirith.git
cd tirith-
Start the Docker Engine using docker desktop or CLI.
-
Open the project folder in Visual Studio Code
-
Once inside VS Code, open the Command Palette
(Ctrl+Shift+P or Cmd+Shift+P on macOS)and search for Dev Containers: Rebuild and Reopen in Container. Select this option. -
VS Code will build the dev container based on the devcontainer.json file or Docker configuration provided in the project. This may take a few minutes.
-
Once the container is up, you will have a fully configured development environment running inside Docker.
Reference Links:
https://code.visualstudio.com/docs/devcontainers/containers#_managing-containers
Here we are going to install Tirith in a Python virtual environment.
- Clone the Tirith repository to your system
git clone https://github.com/StackGuardian/tirith.git
- Change directory to the cloned repository
cd tirith
- Setup a virtualenv
virtualenv .venv
- Activate the virtualenv
source .venv/bin/activate
- Install Tirith in the virtualenv
# The -e is optional, just in case you wanna make some changes to the codebase
pip install -e .
- Verify that Tirith is installed
tirith --version
tirith 1.2.0
Congratulations! Tirith has been setup in your system
usage: tirith [-h] [-policy-path PATH] [-input-path PATH] [-var-path PATH]
[-var PATH] [--json] [--verbose] [--fail-on-error] [--version]
Tirith (StackGuardian Policy Framework)
options:
-h, --help show this help message and exit
-policy-path PATH Path containing Tirith policy as code
-input-path PATH Input file path
-var-path PATH Variable file path(s)
-var PATH Inline variable(s)
--json Only print the result in JSON form (useful for passing output to other programs)
--verbose Show detailed logs of from the run
--fail-on-error Exit 3 when a policy fails, instead of 0. Off by default for compatibility.
--version show program's version number and exit
Subcommands:
tirith platform check --help Evaluate against the policies your StackGuardian
organization enforces, rather than local files.
About Tirith:
* Abstract away the implementation complexity of policy engine underneath.
* Simplify creation of declarative policies that are easy to read and interpret.
* Provide a standard framework for scanning various configurations with granularity.
* Provide modularity to enable easy extensibility
* Github - https://github.com/StackGuardian/tirith
* Docs - https://github.com/StackGuardian/tirith#readme
Use StackGuardian/tirith-iac-governance-action. It finds the plan, posts a sticky pull-request comment, creates a check run and sets the job's exit code:
- run: terraform show -json tfplan > plan.json
- uses: StackGuardian/tirith-iac-governance-action@v2With a plan.json in the working directory that is the whole integration — no with: block. Add
with: { fail-on-error: true } to make a failing policy fail the job, and see the action's own README
for the rest of its inputs.
There is no GitLab-native equivalent of the action, so you invoke the CLI directly — which is all the
action does underneath. Given an earlier job that saved plan.json as an artifact:
policy:
image: python:3.12
needs: [plan]
script:
- pip install "git+https://github.com/StackGuardian/tirith.git@1.0.5"
- tirith -policy-path .tirith/policies -input-path plan.json --fail-on-errorSwap the last line for tirith platform check --workflow-id my-repo --input-path plan.json --fail-on-error to use your organization's policies instead of the committed files. Nothing here is
GitLab-specific: any runner that can execute a container and produce a plan works the same way.
| Code | Meaning |
|---|---|
| 0 | Policies passed, or nothing was in scope to gate on |
| 1 | Tirith could not complete the evaluation — bad input, a policy it could not evaluate, unreachable API |
| 2 | Timed out waiting for a StackGuardian run |
| 3 | A policy failed. Only with --fail-on-error, on either surface |
| 130 | Interrupted |
Gate a CI job with --fail-on-error:
tirith -policy-path .tirith/policies -input-path plan.json --fail-on-error
echo $? # 3 a policy failed · 1 nothing could be evaluated · 0 everything passed
Without the flag the exit code is always 0 and the verdict is in the output — that is how the
command has always behaved, and it is left alone so upgrading cannot turn a passing pipeline red.
3 is deliberately not 1. 3 means a check ran and said no. 1 means Tirith could not tell you
either way — an unparseable eval_expression, an unresolved variable, or a policy whose every check was
skipped. A job that treats every non-zero code alike reports an outage as a policy violation, and
cannot tell a working gate from a broken one.
One limit worth stating plainly: a misconfigured policy — an unsupported condition.type, an unknown
required_provider — comes back from the engine as an ordinary failed check with no error attached, so
it is indistinguishable from a real violation and exits 3. It fails closed, which is the safe
direction, but it will point at your infrastructure when the fault is in the policy.
tirith platform check evaluates against the policies your StackGuardian organization enforces,
instead of policy files committed to your repository — so policy lives in one place rather than being
copied into every repository that needs gating.
export SG_API_TOKEN=sgo_... # an organization token
export SG_ORG=my-org
tirith platform check --workflow-id my-repo --input-path plan.json --fail-on-error
It masks the document on your machine before anything leaves it, packs it with your terraform source,
uploads it, runs the policies on StackGuardian, and prints the verdict. --input-path is optional
when a plan.json or tfplan.json is in the working directory.
Common flags:
--region {eu,us} |
Which StackGuardian region. Default eu, or $SG_REGION |
--api-key - |
Read the key from stdin instead of the environment |
--plan-file tfplan |
The binary plan from terraform plan -out=, rendered through terraform show -json in memory. Use --input-path if you already have the JSON |
--state-path / --infracost-path |
Add a state document or a cost breakdown to the evaluation |
--no-source |
Do not upload the terraform source. Discovery still looks in --source-dir for the plan |
--fail-on-error |
Exit 3 when a policy fails, instead of 0 |
--output-json / --output-markdown |
Write the verdict to files for a later CI step |
--api-url overrides --region for a self-hosted or dedicated host. Every flag is in
docs/platform-check.md or tirith platform check --help.
Running this from GitHub Actions? Use the action instead — it wires up the plan discovery, the sticky pull-request comment, the check run and the exit codes for you.
Examples using various providers
Every condition takes an error_tolerance, and it appears in most of the examples below without
being explained. It is a severity threshold for problems reading the input, not for policy failures:
0— anything the provider could not read is an error, and the check fails.1or higher — a problem whose severity is at or below the tolerance is skipped instead. A missing attribute has severity 2, soerror_tolerance: 2turns "this key is not in the plan" from a failure into a non-answer.
That third outcome is why some sample output below shows "passed": null rather than true or
false — the check did not pass and did not fail, it never ran. A skipped check is then removed from
eval_expression before it is evaluated, because None is falsy in Python and leaving it in would
silently read as a failure.
One consequence worth knowing before using it: a policy whose every check is skipped has evaluated
nothing at all, and reports "final_result": null rather than true or false. With
--fail-on-error that exits 1, not 0 and not 3 — a check that looked at nothing is not a pass, and
it is not a violation either. Keep the tolerance at 0 if you would rather such a policy fail outright.
Terraform plan provider — example policies and output
VPC and EC2 instance policy
- AWS VPC instance_tenancy is "default"
- EC2 instance cannot be destroyed
{
"meta": {
"required_provider": "stackguardian/terraform_plan",
"version": "v1"
},
"evaluators": [
{
"id": "check_ec2_tenancy",
"provider_args": {
"operation_type": "attribute",
"terraform_resource_type": "aws_vpc",
"terraform_resource_attribute": "instance_tenancy"
},
"condition": {
"type": "Equals",
"value": "default"
}
},
{
"id": "destroy_ec2",
"provider_args": {
"operation_type": "action",
"terraform_resource_type": "aws_instance"
},
"condition": {
"type": "ContainedIn",
"value": ["destroy"]
}
}
],
"eval_expression": "check_ec2_tenancy && !destroy_ec2"
}Make sure that all aws_s3_bucket are referenced by aws_s3_bucket_intelligent_tiering_configuration (using Terraform plan provider)
{
"meta": {
"required_provider": "stackguardian/terraform_plan",
"version": "v1"
},
"evaluators": [
{
"id": "s3HasLifeCycleIntelligentTiering",
"description": "Make sure all aws_s3_bucket are referenced by aws_s3_bucket_intelligent_tiering_configuration",
"provider_args": {
"operation_type": "direct_references",
"terraform_resource_type": "aws_s3_bucket",
"referenced_by": "aws_s3_bucket_intelligent_tiering_configuration"
},
"condition": {
"type": "Equals",
"value": true,
"error_tolerance": 0
}
}
],
"eval_expression": "s3HasLifeCycleIntelligentTiering"
}Make sure that all AWS ELBs are attached to security group (using Terraform plan provider)
{
"meta": {
"version": "v1",
"required_provider": "stackguardian/terraform_plan"
},
"evaluators": [
{
"id": "aws_elbs_have_direct_references_to_security_group",
"provider_args": {
"operation_type": "direct_references",
"terraform_resource_type": "aws_elb",
"references_to": "aws_security_group"
},
"condition": {
"type": "Equals",
"value": true,
"error_tolerance": 0
}
}
],
"eval_expression": "aws_elbs_have_direct_references_to_security_group"
}Policy:
{
"meta": {
"version": "v1",
"required_provider": "stackguardian/terraform_plan"
},
"evaluators": [
{
"id": "check1",
"provider_args": {
"operation_type": "attribute",
"terraform_resource_type": "aws_vpc",
"terraform_resource_attribute": "instance_tenancy"
},
"condition": {
"type": "Equals",
"value": "default"
}
},
"..."
{
"id": "check22",
"provider_args": {
"operation_type": "attribute",
"terraform_resource_type": "aws_vpc",
"terraform_resource_attribute": "intra_dedicated_network_acl"
},
"condition": {
"type": "Equals",
"value": false
}
}
],
"eval_expression": "check1 && check22"
}
Input:
{
"format_version": "0.1",
"terraform_version": "0.14.11",
"variables": {
"amazon_side_asn": {
"value": "64512"
},
"assign_ipv6_address_on_creation": {
"value": false
},
"azs": {
"value": []
},
"cidr": {
"value": "10.0.0.0/18"
},
"create_database_internet_gateway_route": {
"value": false
},
"..."
"vpn_gateway_id": {
"default": "",
"description": "ID of VPN Gateway to attach to the VPC"
},
"vpn_gateway_tags": {
"default": {},
"description": "Additional tags for the VPN gateway"
}
}
}
JSON Output:
{
"final_result": false,
"evaluators": [
{
"id": "check1",
"passed": true,
"result": [
{
"passed": true,
"message": "default is equal to default",
"meta": {
"address": "aws_vpc.this[0]",
"mode": "managed",
"type": "aws_vpc",
"name": "this",
"index": 0,
"provider_name": "registry.terraform.io/hashicorp/aws",
"change": {
"actions": [
"create"
],
"before": null,
"after": {
"assign_generated_ipv6_cidr_block": false,
"cidr_block": "10.0.0.0/18",
"enable_dns_hostnames": false,
"enable_dns_support": true,
"instance_tenancy": "default",
"tags": {
"Name": ""
},
"tags_all": {}
},
"after_unknown": {
"arn": true,
"default_network_acl_id": true,
"default_route_table_id": true,
"default_security_group_id": true,
"dhcp_options_id": true,
"enable_classiclink": true,
"enable_classiclink_dns_support": true,
"id": true,
"ipv6_association_id": true,
"ipv6_cidr_block": true,
"main_route_table_id": true,
"owner_id": true,
"tags": {},
"tags_all": {
"Name": true
}
}
}
}
},
{
"passed": true,
"message": "default is equal to default",
"meta": {
"address": "aws_vpc.this[0]",
"mode": "managed",
"type": "aws_vpc",
"name": "this",
"index": 1,
"provider_name": "registry.terraform.io/hashicorp/aws",
"change": {
"actions": [
"create"
],
"before": null,
"after": {
"assign_generated_ipv6_cidr_block": false,
"cidr_block": "10.0.0.0/18",
"enable_dns_hostnames": false,
"enable_dns_support": true,
"instance_tenancy": "default",
"tags": {
"Name": ""
},
"tags_all": {}
},
"after_unknown": {
"arn": true,
"default_network_acl_id": true,
"default_route_table_id": true,
"default_security_group_id": true,
"dhcp_options_id": true,
"enable_classiclink": true,
"enable_classiclink_dns_support": true,
"id": true,
"ipv6_association_id": true,
"ipv6_cidr_block": true,
"main_route_table_id": true,
"owner_id": true,
"tags": {},
"tags_all": {
"Name": true
}
}
}
}
}
],
"description": null
},
"..."
{
"id": "check2",
"passed": false,
"result": [
{
"message": "attribute: 'intra_acl_tags' is not found",
"passed": false
}
],
"description": null
},
{
"id": "check22",
"passed": false,
"result": [
{
"message": "attribute: 'intra_dedicated_network_acl' is not found",
"passed": false
}
],
"description": null
}
],
"errors": [],
"eval_expression": "check1 && check22"
}
Infracost Provider — example policies and output
Cost control policy
- EC2 instance cost is lower than 100 USD per month
{
"meta": {
"required_provider": "stackguardian/infracost",
"version": "v1"
},
"evaluators": [
{
"id": "ec2_cost_below_100_per_month",
"provider_args": {
"operation_type": "total_monthly_cost",
"resource_type": ["aws_ec2"]
},
"condition": {
"type": "LessThanEqualTo",
"value": 100
}
}
],
"eval_expression": "ec2_cost_below_100_per_month"
}Policy:
{
"meta": {
"version": "v1",
"required_provider": "stackguardian/infracost"
},
"evaluators": [
{
"id": "cost_check_1",
"provider_args": {
"operation_type": "total_monthly_cost",
"resource_type": [
"*"
]
},
"condition": {
"type": "LessThanEqualTo",
"value": 20
}
},
{
"id": "cost_check_2",
"provider_args": {
"operation_type": "total_monthly_cost",
"resource_type": [
"aws_eks_cluster",
"aws_s3_bucket"
]
},
"condition": {
"type": "LessThanEqualTo",
"value": -1
}
}
],
"eval_expression": "cost_check_1 && cost_check_2"
}Input:
{
"timeGenerated": "2022-04-03T15:19:53.271995639Z",
"summary": {
"totalUnsupportedResources": 0.0,
"totalUsageBasedResources": 1.0,
"totalNoPriceResources": 1.0,
"noPriceResourceCounts": {
"aws_s3_bucket_public_access_block": 1.0
},
"totalDetectedResources": 2.0,
"totalSupportedResources": 1.0,
"unsupportedResourceCounts": {}
},
"diffTotalHourlyCost": "0",
"projects": [
{
"name": "github.com/StackGuardian/template-tf-aws-s3-demo-website/tf_plan.json",
"pastBreakdown": {
...
}
}],
"pastTotalHourlyCost": "0",
"totalMonthlyCost": "100",
"diffTotalMonthlyCost": "0",
"currency": "USD",
"totalHourlyCost": "0",
"pastTotalMonthlyCost": "0",
"version": "0.2"
}
JSON Output:
{
"meta": {
"version": "v1",
"required_provider": "stackguardian/infracost"
},
"final_result": false,
"evaluators": [
{
"id": "cost_check_1",
"passed": false,
"result": [
{
"passed": false,
"message": "300.1 is not less than or equal to 20",
"meta": null
}
],
"description": null
},
{
"id": "cost_check_2",
"passed": false,
"result": [
{
"passed": false,
"message": "100.1 is not less than or equal to -1",
"meta": null
}
],
"description": null
}
],
"errors": [],
"eval_expression": "cost_check_1 && cost_check_2"
}StackGuardian Workflow Policy (using SG workflow provider) — example policies and output
- Terraform Workflow should require an approval to create or destroy resources{
"meta": {
"required_provider": "stackguardian/sg_workflow",
"version": "v1"
},
"evaluators": [
{
"id": "require_approval_before_creating_ec2",
"provider_args": {
"operation_type": "attribute",
"workflow_attribute": "approvalPreApply"
},
"condition": {
"type": "Equals",
"value": true
}
}
],
"eval_expression": "require_approval_before_creating_ec2"
}Policy:
{
"meta": {
"version": "v1",
"required_provider": "stackguardian/sg_workflow"
},
"evaluators": [
{
"id": "wf_check_1",
"provider_args": {
"operation_type": "attribute",
"workflow_attribute": "useMarketplaceTemplate"
},
"condition": {
"type": "Equals",
"value": true
}
},
"..."
{
"id": "wf_check_14",
"provider_args": {
"operation_type": "attribute",
"workflow_attribute": "iacTemplateId"
},
"condition": {
"type": "Equals",
"value": "/stackguardian/s3-website:19"
}
}
],
"eval_expression": "wf_check_1 && wf_check_2 && wf_check_3 && wf_check_4 && wf_check_5 && wf_check_6 && wf_check_7 && wf_check_8 && wf_check_9 && wf_check_10 && wf_check_11 && wf_check_12 && wf_check_13 && wf_check_14"
}Example Input:
{
"DeploymentPlatformConfig": [
{
"config": {
"integrationId": "/integrations/aws-qa"
},
"kind": "AWS_RBAC"
}
],
"Description": "test",
"DocVersion": "V3.BETA",
"EnvironmentVariables": [
{
"config": {
"textValue": "eu-central-1",
"varName": "AWS_DEFAULT_REGION"
}}]
"..."
{
"schemaType": "FORM_JSONSCHEMA"
},
"iacVCSConfig": {
"iacTemplateId": "/stackguardian/s3-website:19",
"useMarketplaceTemplate": true
},
"WfStepsConfig": [],
"WfType": "TERRAFORM",
"_SGInternals": {}
}JSON Output:
{
"meta": {
"version": "v1",
"required_provider": "stackguardian/sg_workflow"
},
"final_result": false,
"evaluators": [
{
"id": "wf_check_1",
"passed": true,
"result": [
{
"passed": true,
"message": "True is equal to True",
"meta": null
}
],
"description": null
},
"..."
{
"id": "wf_check_11",
"passed": false,
"result": [
{
"passed": false,
"message": "True is not equal to False",
"meta": null
}
],
"description": null
},
],
"errors": [],
"eval_expression": "wf_check_1 && wf_check_2 && wf_check_3 && wf_check_4 && wf_check_5 && wf_check_6 && wf_check_7 && wf_check_8 && wf_check_9 && wf_check_10 && wf_check_11 && wf_check_12 && wf_check_13 && wf_check_14"
}JSON — example policies and output
Example Policy{
"meta": {
"version": "v1",
"required_provider": "stackguardian/json"
},
"evaluators": [
{
"id": "check0",
"provider_args": {
"operation_type": "get_value",
"key_path": "z.b"
},
"condition": {
"type": "LessThanEqualTo",
"value": 1,
"error_tolerance": 2
}
},
{
"id": "check1",
"provider_args": {
"operation_type": "get_value",
"key_path": "a.b"
},
"condition": {
"type": "LessThanEqualTo",
"value": 1
}
},
{
"id": "check2",
"provider_args": {
"operation_type": "get_value",
"key_path": "c"
},
"condition": {
"type": "Contains",
"value": "aa"
}
},
{
"id": "check3",
"provider_args": {
"operation_type": "get_value",
"key_path": "nested_map.e.f"
},
"condition": {
"type": "Equals",
"value": "3"
}
},
{
"id": "check4",
"provider_args": {
"operation_type": "get_value",
"key_path": "list_of_dict.*.key1"
},
"condition": {
"type": "Equals",
"value": "value1"
}
},
{
"id": "check5",
"provider_args": {
"operation_type": "get_value",
"key_path": "nested_map"
},
"condition": {
"type": "Equals",
"value": { "e": { "f": "3" } }
}
}
],
"eval_expression": "check1 && check2 && check3 && check4 && check5"
}Example Input
{
"a": {
"b": 1
},
"c": ["aa", "bb"],
"nested_map": {
"e": {
"f": "3"
}
},
"list_of_dict": [
{
"key1": "value1"
},
{
"key1": "value1"
}
]
}JSON Output
{
"meta": {
"version": "v1",
"required_provider": "stackguardian/json"
},
"final_result": true,
"evaluators": [
{
"id": "check0",
"passed": null,
"result": [
{
"message": "key_path: `z.b` is not found (severity: 2)",
"passed": null
}
],
"description": null
},
{
"id": "check1",
"passed": true,
"result": [
{
"passed": true,
"message": "1 is less than equal to 1",
"meta": null
}
],
"description": null
},
{
"id": "check2",
"passed": true,
"result": [
{
"passed": true,
"message": "Found aa inside ['aa', 'bb']",
"meta": null
}
],
"description": null
},
{
"id": "check3",
"passed": true,
"result": [
{
"passed": true,
"message": "3 is equal to 3",
"meta": null
}
],
"description": null
},
{
"id": "check4",
"passed": true,
"result": [
{
"passed": true,
"message": "value1 is equal to value1",
"meta": null
},
{
"passed": true,
"message": "value1 is equal to value1",
"meta": null
}
],
"description": null
},
{
"id": "check5",
"passed": true,
"result": [
{
"passed": true,
"message": "{'e': {'f': '3'}} is equal to {'e': {'f': '3'}}",
"meta": null
}
],
"description": null
}
],
"errors": [],
"eval_expression": "check1 && check2 && check3 && check4 && check5"
}Kubernetes — example policies and output
Kubernetes (using Kubernetes provider)
- Make sure that all pods have a liveness probe defined
{
"meta": {
"version": "v1",
"required_provider": "stackguardian/kubernetes"
},
"evaluators": [
{
"id": "kinds_have_null_liveness_probe",
"provider_args": {
"operation_type": "attribute",
"kubernetes_kind": "Pod",
"attribute_path": "spec.containers.*.livenessProbe"
},
"condition": {
"type": "Contains",
"value": null,
"error_tolerance": 2
}
}
],
"eval_expression": "!kinds_have_null_liveness_probe"
}Example output:
{
"meta": {
"version": "v1",
"required_provider": "stackguardian/kubernetes"
},
"final_result": false,
"evaluators": [
{
"id": "kinds_have_null_liveness_probe",
"passed": true,
"result": [
{
"passed": true,
"message": "Found None inside [None, {'exec': {'command': ['/tmp/healthy', 'cat']}, 'initialDelaySeconds': 5, 'periodSeconds': 5}]",
"meta": null
}
],
"description": null
}
],
"errors": [],
"eval_expression": "!kinds_have_null_liveness_probe"
}This is a short getting started guide for Tirith. We will take a look on how we can use Tirith to guardrail a JSON input.
Create two files, one for input.json one for policy.json.
input.json
{
"path": "/stackguardian/wfgrps/test",
"verb": "POST",
"meta": {
"epoch": 1718860398,
"User-Agent": {
"name": "User-Agent",
"value": "PostmanRuntime/7.26.8"
}
}
}policy.json
{
"meta": {
"version": "v1",
"required_provider": "stackguardian/json"
},
"evaluators": [
{
"id": "can_post",
"provider_args": {
"operation_type": "get_value",
"key_path": "verb"
},
"condition": {
"type": "Equals",
"value": "POST"
}
},
{
"id": "wfgrps_path",
"provider_args": {
"operation_type": "get_value",
"key_path": "path"
},
"condition": {
"type": "RegexMatch",
"value": "/stackguardian/wfgrps/test.*"
}
},
{
"id": "epoch_less_than_8th_july_2024",
"provider_args": {
"operation_type": "get_value",
"key_path": "meta.epoch"
},
"condition": {
"type": "LessThan",
"value": 1720415598
}
}
],
"eval_expression": "can_post && wfgrps_path && epoch_less_than_8th_july_2024"
}To evaluate the policy against the input, run the following command:
tirith -input-path input.json -policy-path policy.jsonExplanation:
-
tirith:- This is the command to run the Tirith program, which is part of the StackGuardian Policy Framework.
-
-input-path input.json:- The
-input-pathoption specifies the path to the input file. - input.json is the file that contains the input data to be scanned by Tirith.
- The
-
-policy-path policy.json:- The
-policy-path optionspecifies the path to the policy file. - policy.json is the file that contains the policies (rules) defined in Tirith's policy as code.
- The
It should print:
Check: can_post
PASSED
Results:
1. PASSED: POST is equal to POST
Check: wfgrps_path
PASSED
Results:
1. PASSED: /stackguardian/wfgrps/test matches regex pattern /stackguardian/wfgrps/test.*
Check: epoch_less_than_8th_july_2024
PASSED
Results:
1. PASSED: 1718860398 is less than 1720415598
Passed: 3 Failed: 0 Skipped: 0
Final expression used:
-> can_post && wfgrps_path && epoch_less_than_8th_july_2024
✔ Passed final evaluator
We are calling for contributors to help build out new features, review pull requests, fix bugs, and maintain overall code quality. Email us at team[at]stackguardian.io, or get started by reading contributing.md.
Go to the Tirith Repository and in the issues tab describe any bug or feature you want to add. If found relevant, the maintainers will assign the issue to you and you may start working on it as mentioned in the next section.
The kinds of issues a contributor can open:
- Report Bugs
- Feature Enhancement
- If any "help" is needed with using Tirith
Head over to the Tirith repository and in the issues tab describe the bug you encountered and we will be happy to take a look into it.
- Go to the repository and fork it.
- Clone the repository in your local machine.
- Open your terminal and
cd tirith - Create your own branch to work on the changes you intend to perform. For e.g. if you want some changes or bug fix to any function in the evaluators, name your branch with something relevant like,
git branch bug-fix-equals-evaluator - After necessary changes,
git push --set-upstream origin bug-fix-equals-evaluator,git checkout mainandgit merge bug-fix-equals-evaluatoror use the GUI to create a "Pull Request" after pushing it in the respective branch. - A review request will be sent to the repository maintainers and your changes will be merged if found relevant.
Wanna submit a feedback? It's as simple as writing and posting it in the feedback section.
Your feedback will help us improve
This project is maintained by StackGuardian.
Open an issue for a bug or a question about policy authoring. For anything specific to a StackGuardian organization — enforcement scope, a run that errored, an API key — contact StackGuardian support instead, since that needs account context this repository has no access to.
Apache License 2.0
The Apache License is a permissive free software license written by the Apache Software Foundation (ASF). It allows all users to use the software for any purpose, to distribute it, to modify it, and to distribute modified versions of the software under the terms of the license, without concern for royalties.



