Skip to content

Commit

Permalink
Add terraform.imports and terraform.checks functions (#69)
Browse files Browse the repository at this point in the history
* Add `terraform.imports` function

* Add `terraform.checks` function
  • Loading branch information
wata727 committed Oct 21, 2023
1 parent ead86cc commit 1c73e26
Show file tree
Hide file tree
Showing 16 changed files with 628 additions and 0 deletions.
105 changes: 105 additions & 0 deletions docs/functions.md
Original file line number Diff line number Diff line change
Expand Up @@ -566,6 +566,111 @@ terraform.moved_blocks({"from": "any"}, {})
]
```

## `terraform.imports`

```rego
blocks := terraform.imports(schema, options)
```

Returns Terraform imports blocks.

- `schema` (schema): schema for attributes referenced in rules.
- `options` (object[string: string]): options to change the retrieve/evaluate behavior.

Returns:

- `blocks` (array[object<config: body, decl_range: range>]): Terraform "import" blocks.

The `schema` and `options` are equivalent to the arguments of the `terraform.resources` function.

Examples:

```hcl
import {
to = aws_instance.example
id = "i-abcd1234"
}
```

```rego
terraform.imports({"id": "string"}, {})
```

```json
[
{
"config": {
"id": {
"value": "i-abcd1234",
"unknown": false,
"sensitive": false,
"range": {...}
}
},
"decl_range": {...}
}
]
```

## `terraform.checks`

```rego
blocks := terraform.checks(schema, options)
```

Returns Terraform check blocks.

- `schema` (schema): schema for attributes referenced in rules.
- `options` (object[string: string]): options to change the retrieve/evaluate behavior.

Returns:

- `blocks` (array[object<config: body, decl_range: range>]): Terraform "check" blocks.

The `schema` and `options` are equivalent to the arguments of the `terraform.resources` function.

Examples:

```hcl
check "health_check" {
data "http" "terraform_io" {
url = "https://www.terraform.io"
}
assert {
condition = data.http.terraform_io.status_code == 200
error_message = "${data.http.terraform_io.url} returned an unhealthy status code"
}
}
```

```rego
terraform.checks({"assert": {"condition": "bool"}}, {})
```

```json
[
{
"config": {
"assert": [
{
"config": {
"condition": {
"unknown": true,
"sensitive": false,
"range": {...}
}
},
"labels": null,
"decl_range": {...}
}
]
},
"decl_range": {...}
}
]
```

## `terraform.module_range`

```rego
Expand Down
9 changes: 9 additions & 0 deletions integration/checks/.tflint.hcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
plugin "terraform" {
enabled = false
}

plugin "opa" {
enabled = true

policy_dir = "policies"
}
17 changes: 17 additions & 0 deletions integration/checks/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
check "health_check" {
data "http" "terraform_io" {
url = "https://www.terraform.io"
}

assert {
condition = data.http.terraform_io.status_code == 200
error_message = "${data.http.terraform_io.url} returned an unhealthy status code"
}
}

check "deterministic" {
assert {
condition = 200 == 200
error_message = "condition should be true"
}
}
9 changes: 9 additions & 0 deletions integration/checks/policies/main.rego
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package tflint

deny_deterministic_check_condition[issue] {
checks := terraform.checks({"assert": {"condition": "bool"}}, {})
condition = checks[_].config.assert[_].config.condition
condition.unknown == false

issue := tflint.issue("deterministic check condtion is not allowed", condition.range)
}
24 changes: 24 additions & 0 deletions integration/checks/policies/main_test.rego
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package tflint
import future.keywords

mock_checks(schema, options) := terraform.mock_checks(schema, options, {"main.tf": `
check "deterministic" {
assert {
condition = 200 == 200
error_message = "condition should be true"
}
}`})

test_deny_deterministic_check_condition_passed if {
issues := deny_deterministic_check_condition with terraform.checks as mock_checks

count(issues) == 1
issue := issues[_]
issue.msg == "deterministic check condtion is not allowed"
}

test_deny_deterministic_check_condition_failed if {
issues := deny_deterministic_check_condition with terraform.checks as mock_checks

count(issues) == 0
}
25 changes: 25 additions & 0 deletions integration/checks/result.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"issues": [
{
"rule": {
"name": "opa_deny_deterministic_check_condition",
"severity": "error",
"link": "policies/main.rego:3"
},
"message": "deterministic check condtion is not allowed",
"range": {
"filename": "main.tf",
"start": {
"line": 14,
"column": 17
},
"end": {
"line": 14,
"column": 27
}
},
"callers": []
}
],
"errors": []
}
25 changes: 25 additions & 0 deletions integration/checks/result_test.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"issues": [
{
"rule": {
"name": "opa_test_deny_deterministic_check_condition_failed",
"severity": "error",
"link": "policies/main_test.rego:20"
},
"message": "test failed",
"range": {
"filename": "",
"start": {
"line": 0,
"column": 0
},
"end": {
"line": 0,
"column": 0
}
},
"callers": []
}
],
"errors": []
}
9 changes: 9 additions & 0 deletions integration/imports/.tflint.hcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
plugin "terraform" {
enabled = false
}

plugin "opa" {
enabled = true

policy_dir = "policies"
}
4 changes: 4 additions & 0 deletions integration/imports/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import {
to = aws_instance.example
id = "i-abcd1234"
}
8 changes: 8 additions & 0 deletions integration/imports/policies/main.rego
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package tflint

deny_import_blocks[issue] {
imports := terraform.imports({}, {})
count(imports) > 0

issue := tflint.issue("import blocks are not allowed", imports[0].decl_range)
}
22 changes: 22 additions & 0 deletions integration/imports/policies/main_test.rego
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package tflint
import future.keywords

mock_imports(schema, options) := terraform.mock_imports(schema, options, {"main.tf": `
import {
to = aws_instance.example
id = "i-abcd1234"
}`})

test_deny_import_blocks_passed if {
issues := deny_import_blocks with terraform.imports as mock_imports

count(issues) == 1
issue := issues[_]
issue.msg == "import blocks are not allowed"
}

test_deny_import_blocks_failed if {
issues := deny_import_blocks with terraform.imports as mock_imports

count(issues) == 0
}
25 changes: 25 additions & 0 deletions integration/imports/result.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"issues": [
{
"rule": {
"name": "opa_deny_import_blocks",
"severity": "error",
"link": "policies/main.rego:3"
},
"message": "import blocks are not allowed",
"range": {
"filename": "main.tf",
"start": {
"line": 1,
"column": 1
},
"end": {
"line": 1,
"column": 7
}
},
"callers": []
}
],
"errors": []
}
25 changes: 25 additions & 0 deletions integration/imports/result_test.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"issues": [
{
"rule": {
"name": "opa_test_deny_import_blocks_failed",
"severity": "error",
"link": "policies/main_test.rego:18"
},
"message": "test failed",
"range": {
"filename": "",
"start": {
"line": 0,
"column": 0
},
"end": {
"line": 0,
"column": 0
}
},
"callers": []
}
],
"errors": []
}
22 changes: 22 additions & 0 deletions integration/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,28 @@ func TestIntegration(t *testing.T) {
dir: "moved",
test: true,
},
{
name: "imports",
command: exec.Command("tflint", "--format", "json", "--force"),
dir: "imports",
},
{
name: "imports (test)",
command: exec.Command("tflint", "--format", "json", "--force"),
dir: "imports",
test: true,
},
{
name: "checks",
command: exec.Command("tflint", "--format", "json", "--force"),
dir: "checks",
},
{
name: "checks (test)",
command: exec.Command("tflint", "--format", "json", "--force"),
dir: "checks",
test: true,
},
}

dir, _ := os.Getwd()
Expand Down
Loading

0 comments on commit 1c73e26

Please sign in to comment.