Resourcely-cli
resourcely-cli
is a command line utility that helps Resourcely evaluate Guardrails against Terraform plans. It runs in on your infrastructure, typically a CI/CD runner, and only sends lightweight metadata about Guardrail violations back to Resourcely.
This page describes general resourcely-cli
concepts that apply to any runner.
Running the CLI
resourcely-cli
is available as a Docker container or as a self-contained binary. Individual users never need to run resourcely-cli
manually. See CI/CD & Terraform Runners for how to configure various CI systems to run resourcely-cli
automatically.
JSON output
resourcely-cli
can produce a JSON file with finding details. You can consume them in code that gathers statistics, sends slack messages, etc. Pass --output_file <filename>
to enable this feature.
Here is an example file with comments describing each field:
{
// Contains a list of all findings, including ones from evaluate-only guardrails
"findings": [
{
"actions": {
// PR approvals triggered by this finding
"approval": {
// The name of the Notification Group in resourcely
"resourcely_team": "default",
// The rest of the fields are properties of the Notification Group
"github_reviewers": [
"secops"
],
"gitlab_reviewers": [],
}
},
// The ID of the guardrail
"guardrail_id": "787de9a7-8cd7-4dd7-8851-f88653ed0900",
// A link to the guardrail's detail page
"guardrail_link": "https://portal.resourcely.io/guardrails/5e89f370-f0f9-4e5f-95c0-4b0759c7b0a8",
// The state of the guardrail at the time resourcely-cli ran. Values:
// GUARDRAIL_STATE_ACTIVE
// GUARDRAIL_STATE_EVALUATE_ONLY
"guardrail_state": "GUARDRAIL_STATE_ACTIVE",
// The part of the guardrail that was violated
"requirement": "REQUIRE egress.from_port != 10",
// The resource that violated the guardrail
"resource": {
"address": "aws_security_group.blah",
"tf_config_root_path": "us-east-1",
"environment": "dev",
"actions": [
"create"
]
}
}
]
}
Advanced usage
If you use .resourcely.yaml to define multiple config roots (and optionally, environments), you probably need to use resourcely-cli
to evaluate multiple plans, one per config root (and environment).
Below, we'll use the following resourcely.yaml in examples:
terraform_config_roots:
- name: "Global resources"
path: global
# no environments for the sake of example
- name: "Regional resources"
path: regional
environments:
- name: dev
tfvars_file: regional/dev.tfvars
- name: prod
tfvars_file: regional/prod.tfvars
Running resourcely-cli with many plans
You can run resourcely-cli
with several plans at once. For each plan, you must specify the config root (and environment, if applicable). Resourcely uses these values to merge findings from each plan and determine when it can approve the pull request.
Examples:
$ resourcely-cli <other args> \
--config_root_path global --plan global.tfplan.json
$ resourcely-cli <other args> \
--config_root_path regional --environment dev --plan regional-dev.tfplan.json \
--config_root_path regional --environment prod --plan regional-prod.tfplan.json
You can pass --error_on_violations
parameter to Resourcely-cli if you want it to exist with non-zero when it finds guardrail violations
Multiple runs of resourcely-cli
Some CI/CD setups can't access every plan in one place, so they must run resourcely-cli
multiple times. After each run of resourcely-cli
, Resourcely will merge findings from that run over any prior findings, using the config root and (optionally) environment as the key.
An example for the sake of demonstrating the merge logic:
# Assume we ran the commands from the previous section. There were 9 findings:
# 1 in global, 3 in regional-dev, and 5 in regional-prod.
# The developer fixes 3/3 regional-dev findings, and 2/5 regional-prod findings.
# Your CI job then runs resourcely-cli for dev and prod separately.
$ resourcely-cli <other args> \
--config_root_path regional --environment dev --plan regional-dev.tfplan.json
# This run replaced the 3 regional-dev findings with zero findings. There are now
# 6 findings total - 1 in global and 5 in regional-prod.
$ resourcely-cli <other args> \
--config_root_path regional --environment prod --plan regional-prod.tfplan.json
# This run replaced the 5 regional-prod findings with the 3 un-fixed findings. There
# are now 4 findings total - 1 in global and 3 in regional-prod.
You can pass --output_file
to write findings to a file (as json)
Pull request approval
When a pull request is created, Resourcely computes the set of plans that it expects to receive findings from. Resourcely will only approve the pull request once it has received findings from every plan for the PR's latest commit.
Resourcely computes the set of expected plans based on which files the pull request has changed:
If the PR changes a
.tf
file in a config root......if that config root does not have environments, Resourcely expects one plan from it.
...otherwise, Resourcely expects one plan from each of its environments.
Additionally, if the PR changes a
.tfvars
file listed inresourcely.yaml
, Resourcely expects one plan from that config root and environment.
Examples:
Files changed: global/main.tf, regional/main.tf
3 expected plans: global (no env), regional dev, regional prod
# Note the change to main.tf. Resourcely will expect a plan from both envs, even
# though only one env's tfvars changed.
Files changed: regional/main.tf, regional/dev.tfvars
2 expected plans: regional dev, regional prod
Files changed: regional/prod.tfvars
1 expected plans: regional prod
Last updated