{"id":20468478,"url":"https://github.com/stackguardian/tirith","last_synced_at":"2025-04-04T08:10:01.771Z","repository":{"id":60800610,"uuid":"360277156","full_name":"StackGuardian/tirith","owner":"StackGuardian","description":"StackGuardian Policy Framework","archived":false,"fork":false,"pushed_at":"2025-03-10T22:40:13.000Z","size":13386,"stargazers_count":150,"open_issues_count":52,"forks_count":41,"subscribers_count":6,"default_branch":"main","last_synced_at":"2025-03-28T07:09:04.642Z","etag":null,"topics":["aws","azure","compliance","hacktoberfest","stackguardian","terraform"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/StackGuardian.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-04-21T19:02:06.000Z","updated_at":"2025-03-11T07:39:13.000Z","dependencies_parsed_at":"2023-12-05T00:09:41.754Z","dependency_job_id":"dd2db686-310a-4713-982a-f2fadf53552a","html_url":"https://github.com/StackGuardian/tirith","commit_stats":{"total_commits":357,"total_committers":12,"mean_commits":29.75,"dds":0.73109243697479,"last_synced_commit":"236be570d235ba317fa7f74ac5f50a973c493e90"},"previous_names":[],"tags_count":18,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/StackGuardian%2Ftirith","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/StackGuardian%2Ftirith/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/StackGuardian%2Ftirith/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/StackGuardian%2Ftirith/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/StackGuardian","download_url":"https://codeload.github.com/StackGuardian/tirith/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247142074,"owners_count":20890653,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aws","azure","compliance","hacktoberfest","stackguardian","terraform"],"created_at":"2024-11-15T14:05:38.458Z","updated_at":"2025-04-04T08:10:01.749Z","avatar_url":"https://github.com/StackGuardian.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-2.1-4baaaa.svg)](code_of_conduct.md)\n[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)\n[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=StackGuardian_policy-framework\u0026metric=alert_status\u0026token=4a4d06e73940505edb7fc9d27a7f03b35fbbf23d)](https://sonarcloud.io/summary/new_code?id=StackGuardian_policy-framework)\n[![Maintainability Rating](https://sonarcloud.io/api/project_badges/measure?project=StackGuardian_policy-framework\u0026metric=sqale_rating\u0026token=4a4d06e73940505edb7fc9d27a7f03b35fbbf23d)](https://sonarcloud.io/summary/new_code?id=StackGuardian_policy-framework)\n[![Slack](https://img.shields.io/badge/Slack-4A154B?style=for-the-badge\u0026logo=slack\u0026logoColor=white)](https://join.slack.com/t/stackguardian-ol78820/shared_invite/zt-2ksag36j9-OjmXqQmyXudgYrV6FmesIQ)\n[![codecov](https://codecov.io/gh/StackGuardian/tirith/branch/main/graph/badge.svg)](https://codecov.io/gh/StackGuardian/tirith)\n\n# Tirith (StackGuardian Policy Framework)\n\n## Maintainers\n\nThis project is maintained by [StackGuardian](https://www.linkedin.com/company/stackguardian/).\n\n\n## A call for contributors\n\nWe are calling for contributors to help build out new features, review pull requests, fix bugs, and maintain overall code quality. If you're interested, please email us at team[at]stackguardian.io or get started by reading the [contributing.md](./CONTRIBUTING.md).\n\nTirith scans declarative Infrastructure as Code (IaC) configurations like Terraform against policies defined using JSON.\n\n## Content\n\n\u003c!-- - [Feature Road-Map](#feature-road-map) --\u003e\n\u003c!-- - [Local Development Environment](#local-development-environment) --\u003e\n- [What is Tirith?](#what-is-tirith)\n- [Features](#features)\n- [Installation](#installation)\n- [Usage](#usage)\n- [Example Tirith policies](#example-tirith-policies)\n    - [Terraform Plan](#terraform-plan-provider)\n    - [Infracost](#infracost-provider)\n    - [StackGuardian Workflow Policy](#stackguardian-workflow-policy-using-sg-workflow-provider)\n    - [JSON](#json)\n    - [Kubernetes](#kubernetes)\n- [Getting Started](#getting-started)\n- [Want to contribute?](#want-to-contribute)\n  - [Getting an issue assigned](#getting-an-issue-assigned)\n  - [A bug report](#a-bug-report)\n  - [Opening a Pull Request and getting it merged](#opening-a-pull-request-and-getting-it-merged)\n- [Submitting a feedback](#submitting-a-feedback)\n- [Support](#support)\n- [License](#license)\n\n## What is Tirith?\n\nTirith is a policy framework developed by StackGuardian for enforcing policies on infrastructure configurations such as Terraform, CloudFormation, Kubernetes etc. It simplifies policy creation and enforcement ensuring compliance with infrastructure policies through a user-friendly approach.\n\n## Who is the project for?\n- DevSecOps engineers\n- Infrastructure architects\n- Cloud administrators\n- Anyone involved in managing and enforcing infrastructure guardrails\n\n\n## Why is it important and useful for users?\n\n- **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.\n- **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.\n- **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.\n- **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.\n\n## Features\n\n- An easy to read and simple way to define policy as code against structured formats.\n- Use providers to define policies for terraform plan, infracost or any abstract JSON.\n- Easily evaluate inputs against policy using pre-defined evaluators like ContainedIn, Equals, RegexMatch etc.\n- Write your own provider (plugin) by leveraging a highly extensible and pluggable architecture to support any input formats.\n\n\u003c!-- ## Feature Road-map\n\nThis is only a list of approved features that will be included in Tirith over the next iterations.\n\n- Extended support for Terraform Plan\n- Support for Cloudformation and ARM\n- Extended library of evaluator functions --\u003e\n\n## Installation\n\n### For users\n\n```\npip install git+https://github.com/StackGuardian/tirith.git\n```\n\n### For developers\n\n#### Running the Dev Container\n\n- Clone the repository to your local machine:\n\n```bash\n   git clone \u003crepository-url\u003e\n   cd \u003crepository-folder\u003e\n```\n\n- Start the Docker Engine using docker desktop or CLI.\n\n- Open the project folder in Visual Studio Code\n\n- 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.\n\n- 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.\n\n- Once the container is up, you will have a fully configured development environment running inside Docker.\n\nReference Links: \n\nhttps://code.visualstudio.com/docs/devcontainers/create-dev-container#_create-a-devcontainerjson-file\n\nhttps://code.visualstudio.com/docs/devcontainers/containers#_managing-containers\n\n\n#### Manual Installation\nHere we are going to install Tirith in a Python virtual environment.\n\n1. Clone the Tirith repository to your system\n```\ngit clone https://github.com/StackGuardian/tirith.git\n```\n\n2. Change directory to the cloned repository\n```\ncd tirith\n```\n\n3. Setup a virtualenv\n```\nvirtualenv .venv\n```\n\n4. Activate the virtualenv\n```\nsource .venv/bin/activate\n```\n\n5. Install Tirith in the virtualenv\n```\n# The -e is optional, just in case you wanna make some changes to the codebase\npip install -e .\n```\n\n6. Verify that Tirith is installed\n\n```\ntirith --version\n1.0.0-beta.12\n\n```\n\nCongratulations! Tirith has been setup in your system\n\n## Usage\n\n```\nusage: tirith [-h] [-policy-path PATH] [-input-path PATH] [--json] [--verbose] [--version]\n\nTirith (StackGuardian Policy Framework)\n\noptions:\n  -h, --help         show this help message and exit\n  -policy-path PATH  Path containing Tirith policy as code\n  -input-path PATH   Input file path\n  --json             Only print the result in JSON form (useful for passing output to other programs)\n  --verbose          Show detailed logs of from the run\n  --version          show program's version number and exit\n\nAbout Tirith:\n\n   * Abstract away the implementation complexity of policy engine underneath.\n   * Simplify creation of declarative policies that are easy to read and interpret.\n   * Provide a standard framework for scanning various configurations with granularity.\n   * Provide modularity to enable easy extensibility\n   * Github - https://github.com/StackGuardian/tirith\n   * Docs - https://docs.stackguardian.io/docs/tirith/overview\n```\n\n## Example Tirith policies\n\n[Examples using various providers](tests/providers)\n\n### Terraform plan provider\n\u003cdetails\u003e\n\n#### Example 1:\nVPC and EC2 instance policy\n\n- AWS VPC instance_tenancy is \"default\"\n- EC2 instance cannot be destroyed\n\n```json\n{\n  \"meta\": {\n    \"required_provider\": \"stackguardian/terraform_plan\",\n    \"version\": \"v1\"\n  },\n  \"evaluators\": [\n    {\n      \"id\": \"check_ec2_tenancy\",\n      \"provider_args\": {\n        \"operation_type\": \"attribute\",\n        \"terraform_resource_type\": \"aws_vpc\",\n        \"terraform_resource_attribute\": \"instance_tenancy\"\n      },\n      \"condition\": {\n        \"type\": \"Equals\",\n        \"value\": \"default\"\n      }\n    },\n    {\n      \"id\": \"destroy_ec2\",\n      \"provider_args\": {\n        \"operation_type\": \"action\",\n        \"terraform_resource_type\": \"aws_instance\"\n      },\n      \"condition\": {\n        \"type\": \"ContainedIn\",\n        \"value\": [\"destroy\"]\n      }\n    }\n  ],\n  \"eval_expression\": \"check_ec2_tenancy \u0026\u0026 !destroy_ec2\"\n}\n```\nMake sure that all `aws_s3_bucket` are referenced by `aws_s3_bucket_intelligent_tiering_configuration` (using Terraform plan provider)\n\n```json\n{\n  \"meta\": {\n    \"required_provider\": \"stackguardian/terraform_plan\",\n    \"version\": \"v1\"\n  },\n  \"evaluators\": [\n    {\n      \"id\": \"s3HasLifeCycleIntelligentTiering\",\n      \"description\": \"Make sure all aws_s3_bucket are referenced by aws_s3_bucket_intelligent_tiering_configuration\",\n      \"provider_args\": {\n        \"operation_type\": \"direct_references\",\n        \"terraform_resource_type\": \"aws_s3_bucket\",\n        \"referenced_by\": \"aws_s3_bucket_intelligent_tiering_configuration\"\n      },\n      \"condition\": {\n        \"type\": \"Equals\",\n        \"value\": true,\n        \"error_tolerance\": 0\n      }\n    }\n  ],\n  \"eval_expression\": \"s3HasLifeCycleIntelligentTiering\"\n}\n```\n#### Example 2:\nMake sure that all AWS ELBs are attached to security group (using Terraform plan provider)\n\n```json\n{\n  \"meta\": {\n    \"version\": \"v1\",\n    \"required_provider\": \"stackguardian/terraform_plan\"\n  },\n  \"evaluators\": [\n    {\n      \"id\": \"aws_elbs_have_direct_references_to_security_group\",\n      \"provider_args\": {\n        \"operation_type\": \"direct_references\",\n        \"terraform_resource_type\": \"aws_elb\",\n        \"references_to\": \"aws_security_group\"\n      },\n      \"condition\": {\n        \"type\": \"Equals\",\n        \"value\": true,\n        \"error_tolerance\": 0\n      }\n    }\n  ],\n  \"eval_expression\": \"aws_elbs_have_direct_references_to_security_group\"\n}\n```\n#### Example 3:\nPolicy:\n\n```json\n{\n    \"meta\": {\n        \"version\": \"v1\",\n        \"required_provider\": \"stackguardian/terraform_plan\"\n    },\n    \"evaluators\": [\n        {\n            \"id\": \"check1\",\n            \"provider_args\": {\n                \"operation_type\": \"attribute\",\n                \"terraform_resource_type\": \"aws_vpc\",\n                \"terraform_resource_attribute\": \"instance_tenancy\"\n            },\n            \"condition\": {\n                \"type\": \"Equals\",\n                \"value\": \"default\"\n            }\n        },\n        \"...\"\n         {\n            \"id\": \"check22\",\n            \"provider_args\": {\n                \"operation_type\": \"attribute\",\n                \"terraform_resource_type\": \"aws_vpc\",\n                \"terraform_resource_attribute\": \"intra_dedicated_network_acl\"\n            },\n            \"condition\": {\n                \"type\": \"Equals\",\n                \"value\": false\n            }\n        }\n    ],\n    \"eval_expression\": \"check1 \u0026\u0026 check11 \u0026\u0026 check111 \u0026 check2 \u0026 check22\"\n}\n\n```\n\nInput:\n\n```json\n{\n    \"format_version\": \"0.1\",\n    \"terraform_version\": \"0.14.11\",\n    \"variables\": {\n        \"amazon_side_asn\": {\n            \"value\": \"64512\"\n        },\n        \"assign_ipv6_address_on_creation\": {\n            \"value\": false\n        },\n        \"azs\": {\n            \"value\": []\n        },\n        \"cidr\": {\n            \"value\": \"10.0.0.0/18\"\n        },\n        \"create_database_internet_gateway_route\": {\n            \"value\": false\n        },\n\n        \"...\"\n\n         \"vpn_gateway_id\": {\n                    \"default\": \"\",\n                    \"description\": \"ID of VPN Gateway to attach to the VPC\"\n                },\n                \"vpn_gateway_tags\": {\n                    \"default\": {},\n                    \"description\": \"Additional tags for the VPN gateway\"\n                }\n            }\n        }\n    \n```\n\n\nOutput:\n![](docs/tf_plan_example.gif)\n\nJSON Output:\n```json\n{\n   \"final_result\": false,\n   \"evaluators\": [\n      {\n         \"id\": \"check1\",\n         \"passed\": true,\n         \"result\": [\n            {\n               \"passed\": true,\n               \"message\": \"default is equal to default\",\n               \"meta\": {\n                  \"address\": \"aws_vpc.this[0]\",\n                  \"mode\": \"managed\",\n                  \"type\": \"aws_vpc\",\n                  \"name\": \"this\",\n                  \"index\": 0,\n                  \"provider_name\": \"registry.terraform.io/hashicorp/aws\",\n                  \"change\": {\n                     \"actions\": [\n                        \"create\"\n                     ],\n                     \"before\": null,\n                     \"after\": {\n                        \"assign_generated_ipv6_cidr_block\": false,\n                        \"cidr_block\": \"10.0.0.0/18\",\n                        \"enable_dns_hostnames\": false,\n                        \"enable_dns_support\": true,\n                        \"instance_tenancy\": \"default\",\n                        \"tags\": {\n                           \"Name\": \"\"\n                        },\n                        \"tags_all\": {}\n                     },\n                     \"after_unknown\": {\n                        \"arn\": true,\n                        \"default_network_acl_id\": true,\n                        \"default_route_table_id\": true,\n                        \"default_security_group_id\": true,\n                        \"dhcp_options_id\": true,\n                        \"enable_classiclink\": true,\n                        \"enable_classiclink_dns_support\": true,\n                        \"id\": true,\n                        \"ipv6_association_id\": true,\n                        \"ipv6_cidr_block\": true,\n                        \"main_route_table_id\": true,\n                        \"owner_id\": true,\n                        \"tags\": {},\n                        \"tags_all\": {\n                           \"Name\": true\n                        }\n                     }\n                  }\n               }\n            },\n            {\n               \"passed\": true,\n               \"message\": \"default is equal to default\",\n               \"meta\": {\n                  \"address\": \"aws_vpc.this[0]\",\n                  \"mode\": \"managed\",\n                  \"type\": \"aws_vpc\",\n                  \"name\": \"this\",\n                  \"index\": 1,\n                  \"provider_name\": \"registry.terraform.io/hashicorp/aws\",\n                  \"change\": {\n                     \"actions\": [\n                        \"create\"\n                     ],\n                     \"before\": null,\n                     \"after\": {\n                        \"assign_generated_ipv6_cidr_block\": false,\n                        \"cidr_block\": \"10.0.0.0/18\",\n                        \"enable_dns_hostnames\": false,\n                        \"enable_dns_support\": true,\n                        \"instance_tenancy\": \"default\",\n                        \"tags\": {\n                           \"Name\": \"\"\n                        },\n                        \"tags_all\": {}\n                     },\n                     \"after_unknown\": {\n                        \"arn\": true,\n                        \"default_network_acl_id\": true,\n                        \"default_route_table_id\": true,\n                        \"default_security_group_id\": true,\n                        \"dhcp_options_id\": true,\n                        \"enable_classiclink\": true,\n                        \"enable_classiclink_dns_support\": true,\n                        \"id\": true,\n                        \"ipv6_association_id\": true,\n                        \"ipv6_cidr_block\": true,\n                        \"main_route_table_id\": true,\n                        \"owner_id\": true,\n                        \"tags\": {},\n                        \"tags_all\": {\n                           \"Name\": true\n                        }\n                     }\n                  }\n               }\n            }\n         ],\n         \"description\": null\n      },\n         \"...\"    \n      {\n         \"id\": \"check2\",\n         \"passed\": false,\n         \"result\": [\n            {\n               \"message\": \"attribute: 'intra_acl_tags' is not found\",\n               \"passed\": false\n            }\n         ],\n         \"description\": null\n      },\n      {\n         \"id\": \"check22\",\n         \"passed\": false,\n         \"result\": [\n            {\n               \"message\": \"attribute: 'intra_dedicated_network_acl' is not found\",\n               \"passed\": false\n            }\n         ],\n         \"description\": null\n      }\n   ],\n   \"errors\": [],\n   \"eval_expression\": \"check1 \u0026\u0026 check11 \u0026\u0026 check111 \u0026 check2 \u0026 check22\"\n}\n\n```\n\u003c/details\u003e\n\n### Infracost Provider\n\u003cdetails\u003e\n\nCost control policy\n\n#### Example 1\n- EC2 instance cost is lower than 100 USD per month\n\n```json\n{\n  \"meta\": {\n    \"required_provider\": \"stackguardian/infracost\",\n    \"version\": \"v1\"\n  },\n  \"evaluators\": [\n    {\n      \"id\": \"ec2_cost_below_100_per_month\",\n      \"provider_args\": {\n        \"operation_type\": \"total_monthly_cost\",\n        \"resource_type\": [\"aws_ec2\"]\n      },\n      \"condition\": {\n        \"type\": \"LessThanEqualTo\",\n        \"value\": 100\n      }\n    }\n  ],\n  \"eval_expression\": \"ec2_cost_below_100_per_month\"\n}\n```\n#### Example 2\nPolicy:\n\n```json\n{\n    \"meta\": {\n        \"version\": \"v1\",\n        \"required_provider\": \"stackguardian/infracost\"\n    },\n    \"evaluators\": [\n        {\n            \"id\": \"cost_check_1\",\n            \"provider_args\": {\n                \"operation_type\": \"total_monthly_cost\",\n                \"resource_type\": [\n                    \"*\"\n                ]\n            },\n            \"condition\": {\n                \"type\": \"LessThanEqualTo\",\n                \"value\": 20\n            }\n        },\n        {\n            \"id\": \"cost_check_2\",\n            \"provider_args\": {\n                \"operation_type\": \"total_monthly_cost\",\n                \"resource_type\": [\n                    \"aws_eks_cluster\",\n                    \"aws_s3_bucket\"\n                ]\n            },\n            \"condition\": {\n                \"type\": \"LessThanEqualTo\",\n                \"value\": -1\n            }\n        }\n    ],\n    \"eval_expression\": \"cost_check_1 \u0026\u0026 cost_check_2\"\n}\n```\n\nInput:\n\n```json\n{\n  \"timeGenerated\": \"2022-04-03T15:19:53.271995639Z\",\n  \"summary\": {\n    \"totalUnsupportedResources\": 0.0,\n    \"totalUsageBasedResources\": 1.0,\n    \"totalNoPriceResources\": 1.0,\n    \"noPriceResourceCounts\": {\n      \"aws_s3_bucket_public_access_block\": 1.0\n    },\n    \"totalDetectedResources\": 2.0,\n    \"totalSupportedResources\": 1.0,\n    \"unsupportedResourceCounts\": {}\n  },\n  \"diffTotalHourlyCost\": \"0\",\n  \"projects\": [\n    {\n      \"name\": \"github.com/StackGuardian/template-tf-aws-s3-demo-website/tf_plan.json\",\n      \"pastBreakdown\": {\n\n        ...\n        }\n}],\n    \"pastTotalHourlyCost\": \"0\",\n    \"totalMonthlyCost\": \"100\",\n    \"diffTotalMonthlyCost\": \"0\",\n    \"currency\": \"USD\",\n    \"totalHourlyCost\": \"0\",\n    \"pastTotalMonthlyCost\": \"0\",\n    \"version\": \"0.2\"\n  }\n\n```\n\nOutput:\n![](docs/infracost_example.gif)\n\nJSON Output:\n```json\n{\n   \"meta\": {\n      \"version\": \"v1\",\n      \"required_provider\": \"stackguardian/infracost\"\n   },\n   \"final_result\": false,\n   \"evaluators\": [\n      {\n         \"id\": \"cost_check_1\",\n         \"passed\": false,\n         \"result\": [\n            {\n               \"passed\": false,\n               \"message\": \"300.1 is not less than or equal to 20\",\n               \"meta\": null\n            }\n         ],\n         \"description\": null\n      },\n      {\n         \"id\": \"cost_check_2\",\n         \"passed\": false,\n         \"result\": [\n            {\n               \"passed\": false,\n               \"message\": \"100.1 is not less than or equal to -1\",\n               \"meta\": null\n            }\n         ],\n         \"description\": null\n      }\n   ],\n   \"errors\": [],\n   \"eval_expression\": \"cost_check_1 \u0026\u0026 cost_check_2\"\n}\n```\n\u003c/details\u003e\n\n### StackGuardian Workflow Policy (using SG workflow provider)\n\u003cdetails\u003e\n- Terraform Workflow should require an approval to create or destroy resources\n\n```json\n{\n  \"meta\": {\n    \"required_provider\": \"stackguardian/sg_workflow\",\n    \"version\": \"v1\"\n  },\n  \"evaluators\": [\n    {\n      \"id\": \"require_approval_before_creating_ec2\",\n      \"provider_args\": {\n        \"operation_type\": \"attribute\",\n        \"workflow_attribute\": \"approvalPreApply\"\n      },\n      \"condition\": {\n        \"type\": \"Equals\",\n        \"value\": true\n      }\n    }\n  ],\n  \"eval_expression\": \"require_approval_before_creating_ec2\"\n}\n```\n\n#### Example 2\n\nPolicy:\n\n```json\n{\n    \"meta\": {\n        \"version\": \"v1\",\n        \"required_provider\": \"stackguardian/sg_workflow\"\n    },\n    \"evaluators\": [\n        {\n            \"id\": \"wf_check_1\",\n            \"provider_args\": {\n                \"operation_type\": \"attribute\",\n                \"workflow_attribute\": \"useMarketplaceTemplate\"\n            },\n            \"condition\": {\n                \"type\": \"Equals\",\n                \"value\": true\n            }\n        },\n        \"...\"\n          {\n            \"id\": \"wf_check_14\",\n            \"provider_args\": {\n                \"operation_type\": \"attribute\",\n                \"workflow_attribute\": \"iacTemplateId\"\n            },\n            \"condition\": {\n                \"type\": \"Equals\",\n                \"value\": \"/stackguardian/s3-website:19\"\n            }\n        }\n    ],\n    \"eval_expression\": \"wf_check_1 \u0026\u0026 wf_check_2 \u0026\u0026 wf_check_3 \u0026\u0026 wf_check_4 \u0026\u0026 wf_check_5 \u0026\u0026 wf_check_6 \u0026\u0026 wf_check_7 \u0026\u0026 wf_check_8 \u0026\u0026 wf_check_9 \u0026\u0026 wf_check_10 \u0026\u0026 wf_check_11 \u0026\u0026 wf_check_12 \u0026\u0026 wf_check_13 \u0026\u0026 wf_check_14\"\n}\n```\n\nExample Input:\n\n```json\n{\n \"DeploymentPlatformConfig\": [\n  {\n   \"config\": {\n    \"integrationId\": \"/integrations/aws-qa\"\n   },\n   \"kind\": \"AWS_RBAC\"\n  }\n ],\n \"Description\": \"test\",\n \"DocVersion\": \"V3.BETA\",\n \"EnvironmentVariables\": [\n  {\n   \"config\": {\n    \"textValue\": \"eu-central-1\",\n    \"varName\": \"AWS_DEFAULT_REGION\"\n   }}]\n   \"...\"\n   {\n   \"schemaType\": \"FORM_JSONSCHEMA\"\n  },\n  \"iacVCSConfig\": {\n   \"iacTemplateId\": \"/stackguardian/s3-website:19\",\n   \"useMarketplaceTemplate\": true\n  },\n \n \"WfStepsConfig\": [],\n \"WfType\": \"TERRAFORM\",\n \"_SGInternals\": {}\n}\n```\n\nOutput:\n![](docs/sg_workflow_example.gif)\n\n\nJSON Output:\n\n```json \n\n{\n   \"meta\": {\n      \"version\": \"v1\",\n      \"required_provider\": \"stackguardian/sg_workflow\"\n   },\n   \"final_result\": false,\n   \"evaluators\": [\n      {\n         \"id\": \"wf_check_1\",\n         \"passed\": true,\n         \"result\": [\n            {\n               \"passed\": true,\n               \"message\": \"True is equal to True\",\n               \"meta\": null\n            }\n         ],\n         \"description\": null\n        \n      },\n     \n \"...\"\n\n      {\n         \"id\": \"wf_check_11\",\n         \"passed\": false,\n         \"result\": [\n            {\n               \"passed\": false,\n               \"message\": \"True is not equal to False\",\n               \"meta\": null\n            }\n         ],\n         \"description\": null\n      },\n\n   ],\n   \"errors\": [],\n   \"eval_expression\": \"wf_check_1 \u0026\u0026 wf_check_2 \u0026\u0026 wf_check_3 \u0026\u0026 wf_check_4 \u0026\u0026 wf_check_5 \u0026\u0026 wf_check_6 \u0026\u0026 wf_check_7 \u0026\u0026 wf_check_8 \u0026\u0026 wf_check_9 \u0026\u0026 wf_check_10 \u0026\u0026 wf_check_11 \u0026\u0026 wf_check_12 \u0026\u0026 wf_check_13 \u0026\u0026 wf_check_14\"\n}\n```\n\u003c/details\u003e\n\n### JSON\n\u003cdetails\u003e\nExample Policy\n\n```json\n{\n    \"meta\": {\n        \"version\": \"v1\",\n        \"required_provider\": \"stackguardian/json\"\n    },\n    \"evaluators\": [\n        {\n            \"id\": \"check0\",\n            \"provider_args\": {\n                \"operation_type\": \"get_value\",\n                \"key_path\": \"z.b\"\n            },\n            \"condition\": {\n                \"type\": \"LessThanEqualTo\",\n                \"value\": 1,\n                \"error_tolerance\": 2\n            }\n        },\n        {\n            \"id\": \"check1\",\n            \"provider_args\": {\n                \"operation_type\": \"get_value\",\n                \"key_path\": \"a.b\"\n            },\n            \"condition\": {\n                \"type\": \"LessThanEqualTo\",\n                \"value\": 1\n            }\n        },\n        {\n            \"id\": \"check2\",\n            \"provider_args\": {\n                \"operation_type\": \"get_value\",\n                \"key_path\": \"c\"\n            },\n            \"condition\": {\n                \"type\": \"Contains\",\n                \"value\": \"aa\"\n            }\n        },\n        {\n            \"id\": \"check3\",\n            \"provider_args\": {\n                \"operation_type\": \"get_value\",\n                \"key_path\": \"nested_map.e.f\"\n            },\n            \"condition\": {\n                \"type\": \"Equals\",\n                \"value\": \"3\"\n            }\n        },\n        {\n            \"id\": \"check4\",\n            \"provider_args\": {\n                \"operation_type\": \"get_value\",\n                \"key_path\": \"list_of_dict.*.key1\"\n            },\n            \"condition\": {\n                \"type\": \"Equals\",\n                \"value\": \"value1\"\n            }\n        },\n        {\n            \"id\": \"check5\",\n            \"provider_args\": {\n                \"operation_type\": \"get_value\",\n                \"key_path\": \"nested_map\"\n            },\n            \"condition\": {\n                \"type\": \"Equals\",\n                \"value\": { \"e\": { \"f\": \"3\" } }\n            }\n        }\n    ],\n    \"eval_expression\": \"check1 \u0026\u0026 check2 \u0026\u0026 check3 \u0026\u0026 check4 \u0026\u0026 check5\"\n}\n```\n\nExample Input\n```json\n{\n\t\"a\": {\n\t\t\t\"b\": 1\n\t\t},\n\t\"c\": [\"aa\", \"bb\"],\n\t\"nested_map\": {\n\t\t\"e\": {\n\t\t\t\"f\": \"3\"\n\t\t}\n\t},\n\t\"list_of_dict\": [\n\t\t{\n\t\t\t\"key1\": \"value1\"\n\t\t},\n\t\t{\n\t\t\t\"key1\": \"value1\"\n\t\t}\n\t]\n}\n```\n\nOutput:\n![](docs/json_example.gif)\n\nJSON Output\n```json\n{\n   \"meta\": {\n      \"version\": \"v1\",\n      \"required_provider\": \"stackguardian/json\"\n   },\n   \"final_result\": true,\n   \"evaluators\": [\n      {\n         \"id\": \"check0\",\n         \"passed\": null,\n         \"result\": [\n            {\n               \"message\": \"key_path: `z.b` is not found (severity: 2)\",\n               \"passed\": null\n            }\n         ],\n         \"description\": null\n      },\n      {\n         \"id\": \"check1\",\n         \"passed\": true,\n         \"result\": [\n            {\n               \"passed\": true,\n               \"message\": \"1 is less than equal to 1\",\n               \"meta\": null\n            }\n         ],\n         \"description\": null\n      },\n      {\n         \"id\": \"check2\",\n         \"passed\": true,\n         \"result\": [\n            {\n               \"passed\": true,\n               \"message\": \"Found aa inside ['aa', 'bb']\",\n               \"meta\": null\n            }\n         ],\n         \"description\": null\n      },\n      {\n         \"id\": \"check3\",\n         \"passed\": true,\n         \"result\": [\n            {\n               \"passed\": true,\n               \"message\": \"3 is equal to 3\",\n               \"meta\": null\n            }\n         ],\n         \"description\": null\n      },\n      {\n         \"id\": \"check4\",\n         \"passed\": true,\n         \"result\": [\n            {\n               \"passed\": true,\n               \"message\": \"value1 is equal to value1\",\n               \"meta\": null\n            },\n            {\n               \"passed\": true,\n               \"message\": \"value1 is equal to value1\",\n               \"meta\": null\n            }\n         ],\n         \"description\": null\n      },\n      {\n         \"id\": \"check5\",\n         \"passed\": true,\n         \"result\": [\n            {\n               \"passed\": true,\n               \"message\": \"{'e': {'f': '3'}} is equal to {'e': {'f': '3'}}\",\n               \"meta\": null\n            }\n         ],\n         \"description\": null\n      }\n   ],\n   \"errors\": [],\n   \"eval_expression\": \"check1 \u0026\u0026 check2 \u0026\u0026 check3 \u0026\u0026 check4 \u0026\u0026 check5\"\n```\n\u003c/details\u003e\n\n### Kubernetes\n\u003cdetails\u003e\n\nKubernetes (using Kubernetes provider)\n#### Example 1\n- Make sure that all pods have a liveness probe defined\n\n```json\n{\n  \"meta\": {\n    \"version\": \"v1\",\n    \"required_provider\": \"stackguardian/kubernetes\"\n  },\n  \"evaluators\": [\n    {\n      \"id\": \"kinds_have_null_liveness_probe\",\n      \"provider_args\": {\n        \"operation_type\": \"attribute\",\n        \"kubernetes_kind\": \"Pod\",\n        \"attribute_path\": \"spec.containers.*.livenessProbe\"\n      },\n      \"condition\": {\n        \"type\": \"Contains\",\n        \"value\": null,\n        \"error_tolerance\": 2\n      }\n    }\n  ],\n  \"eval_expression\": \"!kinds_have_null_liveness_probe\"\n}\n```\n#### Example 2\n\nExample Policy:\n\n```json\n{\n  \"meta\": {\n    \"version\": \"v1\",\n    \"required_provider\": \"stackguardian/kubernetes\"\n  },\n  \"evaluators\": [\n    {\n      \"id\": \"kinds_have_null_liveness_probe\",\n      \"provider_args\": {\n        \"operation_type\": \"attribute\",\n        \"kubernetes_kind\": \"Pod\",\n        \"attribute_path\": \"spec.containers.*.livenessProbe\"\n      },\n      \"condition\": {\n        \"type\": \"Contains\",\n        \"value\": null,\n        \"error_tolerance\": 2\n      }\n    }\n  ],\n  \"eval_expression\": \"!kinds_have_null_liveness_probe\"\n}\n```\n\nExample Input:\n\n```yml\napiVersion: v1\nkind: ServiceAccount\nmetadata:\n  name: wfs-demp-wfs-demo\n  labels:\n    helm.sh/chart: wfs-demo-0.1.0\n    app.kubernetes.io/name: wfs-demo\n    app.kubernetes.io/instance: wfs-demp\n    app.kubernetes.io/version: \"1.16.0\"\n    app.kubernetes.io/managed-by: Helm\n---\n# Source: wfs-demo/templates/user-acces.yaml\napiVersion: rbac.authorization.k8s.io/v1\n...\n    - name: wget\n      image: busybox\n      command: ['wget']\n      args: ['wfs-demp-wfs-demo:80']\n      livenessProbe:\n        exec:\n          command:\n          - cat\n          - /tmp/healthy\n        initialDelaySeconds: 5\n        periodSeconds: 5\n  restartPolicy: Never\n\n```\n\nOutput:\n![](docs/kubernetes_example.gif)\n\nJSON Output:\n```json\n{\n   \"meta\": {\n      \"version\": \"v1\",\n      \"required_provider\": \"stackguardian/kubernetes\"\n   },\n   \"final_result\": false,\n   \"evaluators\": [\n      {\n         \"id\": \"kinds_have_null_liveness_probe\",\n         \"passed\": true,\n         \"result\": [\n            {\n               \"passed\": true,\n               \"message\": \"Found None inside [None, {'exec': {'command': ['/tmp/healthy', 'cat']}, 'initialDelaySeconds': 5, 'periodSeconds': 5}]\",\n               \"meta\": null\n            }\n         ],\n         \"description\": null\n      }\n   ],\n   \"errors\": [],\n   \"eval_expression\": \"!kinds_have_null_liveness_probe\"\n}\n```\n\n\u003c/details\u003e\n\u003c!-- ## Local Development Environment\n\n- [Python 3.6 or higher](https://www.python.org/downloads/) is required.\n- [pip](https://pip.pypa.io/en/stable/) is required. --\u003e\n\n\u003c!-- ## Publish Package on test.pypi.org\n* Use the following command to install the latest version of the setuptools package.\n  ```\n    python -m pip install --user --upgrade setuptools\n  ```\n\n* Make sure you are at the same directory where setup.py is located and run this command.\n  ```\n    python setup.py sdist\n  ```\n* Visit \u003ca href=\"https://test.pypi.org/\"\u003etest.pypi.org\u003c/a\u003e and create a new account if not already.\n* Install Twine package using following command.\n  ```\n    pip install twine\n  ```\n* Upload you package to test.pypi using following command.\n  ```\n    twine upload --repository-url https://test.pypi.org/legacy/ dist/*\n  ``` --\u003e\n## Getting Started\n\nThis is a short getting started guide for Tirith. We will take a look on how we can use Tirith to guardrail a JSON input.\n\nCreate two files, one for input.json one for policy.json.\n\n**input.json**\n\n```json\n{\n  \"path\": \"/stackguardian/wfgrps/test\",\n  \"verb\": \"POST\",\n  \"meta\": {\n    \"epoch\": 1718860398,\n    \"User-Agent\": {\n        \"name\": \"User-Agent\",\n        \"value\": \"PostmanRuntime/7.26.8\"\n    }\n  }\n}\n```\n\n**policy.json**\n\n```json\n{\n    \"meta\": {\n        \"version\": \"v1\",\n        \"required_provider\": \"stackguardian/json\"\n    },\n    \"evaluators\": [\n        {\n            \"id\": \"can_post\",\n            \"provider_args\": {\n                \"operation_type\": \"get_value\",\n                \"key_path\": \"verb\"\n            },\n            \"condition\": {\n                \"type\": \"Equals\",\n                \"value\": \"POST\"\n            }\n        },\n        {\n            \"id\": \"wfgrps_path\",\n            \"provider_args\": {\n                \"operation_type\": \"get_value\",\n                \"key_path\": \"path\"\n            },\n            \"condition\": {\n                \"type\": \"RegexMatch\",\n                \"value\": \"/stackguardian/wfgrps/test.*\"\n            }\n        },\n        {\n            \"id\": \"epoch_less_than_8th_july_2024\",\n            \"provider_args\": {\n                \"operation_type\": \"get_value\",\n                \"key_path\": \"meta.epoch\"\n            },\n            \"condition\": {\n                \"type\": \"LessThan\",\n                \"value\": 1720415598\n            }\n        }\n    ],\n    \"eval_expression\": \"can_post \u0026\u0026 wfgrps_path \u0026\u0026 epoch_less_than_8th_july_2024\"\n}\n```\n\n### Evaluating the policy against the input\n\nTo evaluate the policy against the input, run the following command:\n\n```sh\ntirith -input-path input.json -policy-path policy.json\n```\n\nExplanation:\n\n-   `tirith`:\n    -   This is the command to run the Tirith program, which is part of\n         the StackGuardian Policy Framework.\n\n-   `-input-path input.json`:\n    -   The `-input-path` option specifies the path to the input file.\n    -   input.json is the file that contains the input data to be\n         scanned by Tirith.\n\n-   `-policy-path policy.json`:\n    -   The `-policy-path option` specifies the path to the policy file.\n    -   policy.json is the file that contains the policies (rules)\n         defined in Tirith\\'s policy as code.\n\nIt should print:\n```\nCheck: can_post\n  PASSED\n  Results:\n\t1. PASSED: POST is equal to POST\n\nCheck: wfgrps_path\n  PASSED\n  Results:\n\t1. PASSED: /stackguardian/wfgrps/test matches regex pattern /stackguardian/wfgrps/test.*\n\nCheck: epoch_less_than_8th_july_2024\n  PASSED\n  Results:\n\t1. PASSED: 1718860398 is less than 1720415598\n\nPassed: 3 Failed: 0 Skipped: 0\n\nFinal expression used:\n-\u003e can_post \u0026\u0026 wfgrps_path \u0026\u0026 epoch_less_than_8th_july_2024\n✔ Passed final evaluator\n```\n\n\n## Want to contribute?\n\nIf you're interested, please email us at team[at]stackguardian.io or get started by reading the [contributing.md](./CONTRIBUTING.md).\n\n### Getting an issue assigned\n\nGo to the \u003ca href=\"https://github.com/StackGuardian/tirith\"\u003eTirith Repository\u003c/a\u003e and in the \u003ca href=\"https://github.com/stackguardian/tirith/issues\"\u003eissues\u003c/a\u003e 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.\n\n\u003cp\u003eThe kinds of issues a contributor can open:\u003c/p\u003e\n \u003cul\u003e\n\t\u003cli\u003eReport Bugs\u003c/li\u003e\n\t\u003cli\u003eFeature Enhancement\u003c/li\u003e\n\t\u003cli\u003eIf any \"help\" is needed with using Tirith\u003c/li\u003e\n \u003c/ul\u003e\n\n### A bug report\n\nHead over to the \u003ca href=\"https://github.com/StackGuardian/tirith\"\u003eTirith repository\u003c/a\u003e and in the \u003ca href=\"https://github.com/stackguardian/tirith/issues\"\u003eissues\u003c/a\u003e tab describe the bug you encountered and we will be happy to take a look into it.\n\n### Opening a Pull Request and getting it merged?\n\n1.  Go to the \u003ca href =\"https://github.com/StackGuardian/tirith\"\u003erepository\u003c/a\u003e and fork it.\n2.  Clone the repository in your local machine.\n3.  Open your terminal and `cd tirith`\n4.  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`\n5.  After necessary changes, `git push --set-upstream origin bug-fix-equals-evaluator`, `git checkout main` and `git merge bug-fix-equals-evaluator` or use the GUI to create a \"Pull Request\" after pushing it in the respective branch.\n6.  A review request will be sent to the repository maintainers and your changes will be merged if found relevant.\n\n## Submitting a Feedback\n\nWanna submit a feedback? It's as simple as writing and posting it in the \u003ca href=\"https://github.com/StackGuardian/feedback/discussions/8\"\u003efeedback section\u003c/a\u003e.\n\n\u003cp\u003eYour feedback will help us improve\u003c/p\u003e\n\n## Support\n\n## License\n\n\u003ci\u003eApache License 2.0\u003c/i\u003e\n\n\u003cp\u003eThe 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.\u003c/p\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstackguardian%2Ftirith","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstackguardian%2Ftirith","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstackguardian%2Ftirith/lists"}