Skip to content

Commit 8d26afc

Browse files
Added tfsec as a security linter (#199)
Added tfsec as a security linter. Includes a small fix to testing that prevents accidentally linting the json output of trunk check. --------- Co-authored-by: Tyler Jang <tyler@trunk.io>
1 parent 34e8447 commit 8d26afc

8 files changed

Lines changed: 87 additions & 23 deletions

File tree

.trunk/trunk.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ runtimes:
1616

1717
lint:
1818
enabled:
19+
- tfsec@1.28.1
1920
- clippy@1.65.0
2021
- golangci-lint@1.51.2
2122
- actionlint@1.6.23

linters/terraform/test_data/terraform_v1.1.0_variables.check.shot

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -13,26 +13,6 @@ exports[`Testing linter terraform test variables 1`] = `
1313
"message": "Terraform 0.11 and earlier required type constraints to be given in quotes, but that form is now deprecated and will be removed in a future version of Terraform. Remove the quotes around "map" and write map(string) instead to explicitly indicate that the map elements are strings.",
1414
"targetType": "terraform",
1515
},
16-
{
17-
"bucket": "terraform",
18-
"code": "Missing value",
19-
"file": "test_data/variables.in.tf.json",
20-
"level": "LEVEL_HIGH",
21-
"line": "1",
22-
"linter": "terraform",
23-
"message": "The JSON data ends prematurely.",
24-
"targetType": "terraform",
25-
},
26-
{
27-
"bucket": "terraform",
28-
"code": "Root value must be object",
29-
"file": "test_data/variables.in.tf.json",
30-
"level": "LEVEL_HIGH",
31-
"line": "1",
32-
"linter": "terraform",
33-
"message": "The root value in a JSON-based configuration must be either a JSON object or a JSON array of objects.",
34-
"targetType": "terraform",
35-
},
3616
],
3717
"lintActions": [
3818
{

linters/tfsec/plugin.yaml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
version: 0.1
2+
lint:
3+
downloads:
4+
- name: tfsec
5+
version: 1.28.1
6+
executable: true
7+
downloads:
8+
- os:
9+
linux: linux
10+
macos: darwin
11+
cpu:
12+
x86_64: amd64
13+
arm_64: arm64
14+
url: https://github.com/aquasecurity/tfsec/releases/download/v${version}/tfsec-${os}-${cpu}
15+
definitions:
16+
- name: tfsec
17+
files: [terraform]
18+
download: tfsec
19+
known_good_version: 1.28.1
20+
commands:
21+
- name: lint
22+
output: sarif
23+
target: ${parent}
24+
run: tfsec ${target} --format=sarif
25+
success_codes: [0, 1]
26+
read_output_from: stdout
27+
environment:
28+
- name: PATH
29+
list: ["${linter}"]
30+
version_command:
31+
parse_regex: v${semver}
32+
run: tfsec --version

linters/tfsec/test_data/aws.in.tf

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
resource "aws_instance" "foo" {
2+
instance_type = "t1.2xlarge"
3+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`Testing linter tfsec test aws 1`] = `
4+
{
5+
"issues": [
6+
{
7+
"bucket": "tfsec",
8+
"code": "aws-ec2-enable-at-rest-encryption",
9+
"column": "1",
10+
"file": "aws.in.tf",
11+
"level": "LEVEL_HIGH",
12+
"line": "1",
13+
"linter": "tfsec",
14+
"message": "Root block device is not encrypted.",
15+
"targetType": "terraform",
16+
},
17+
{
18+
"bucket": "tfsec",
19+
"code": "aws-ec2-enforce-http-token-imds",
20+
"column": "1",
21+
"file": "aws.in.tf",
22+
"level": "LEVEL_HIGH",
23+
"line": "1",
24+
"linter": "tfsec",
25+
"message": "Instance does not require IMDS access to require a token",
26+
"targetType": "terraform",
27+
},
28+
],
29+
"lintActions": [
30+
{
31+
"command": "lint",
32+
"fileGroupName": "terraform",
33+
"linter": "tfsec",
34+
"paths": [
35+
"test_data",
36+
],
37+
"verb": "TRUNK_VERB_CHECK",
38+
},
39+
],
40+
"taskFailures": [],
41+
"unformattedFiles": [],
42+
}
43+
`;

linters/tfsec/tfsec.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
import { linterCheckTest } from "tests";
2+
linterCheckTest({ linterName: "tfsec" });

readme.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,11 +67,11 @@ make the discovery, management and integration of new tools as straight-forward
6767
| Ruby | [brakeman], [rubocop], [rufo], [semgrep], [standardrb] |
6868
| Rust | [clippy], [rustfmt] |
6969
| Scala | [scalafmt] |
70-
| Security | [nancy], [trivy] |
70+
| Security | [nancy], [trivy], [tfsec] |
7171
| SQL | [sqlfluff], [sqlfmt], [sql-formatter] |
7272
| SVG | [svgo] |
7373
| Swift | [stringslint], [swiftlint], [swiftformat] |
74-
| Terraform | [terraform] (validate and fmt), [tflint]<sup><a href="#note-tflint">2</a></sup> |
74+
| Terraform | [terraform] (validate and fmt), [tflint]<sup><a href="#note-tflint">2</a></sup>, [tfsec] |
7575
| TOML | [taplo] |
7676
| Typescript | [eslint], [prettier], [rome], [semgrep] |
7777
| YAML | [prettier], [semgrep], [yamllint] |
@@ -140,6 +140,7 @@ make the discovery, management and integration of new tools as straight-forward
140140
[taplo]: https://github.com/tamasfe/taplo#readme
141141
[terraform]: https://developer.hashicorp.com/terraform/cli/code
142142
[tflint]: https://github.com/terraform-linters/tflint#readme
143+
[tfsec]: https://github.com/aquasecurity/tfsec
143144
[trivy]: https://github.com/aquasecurity/trivy#readme
144145
[yamllint]: https://github.com/adrienverge/yamllint#readme
145146
[yapf]: https://github.com/google/yapf#readme

tests/driver/index.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -466,7 +466,9 @@ export class TrunkDriver {
466466
*/
467467
async runCheckUnit(targetRelativePath: string, linter: string): Promise<TestResult> {
468468
const targetAbsPath = path.resolve(this.sandboxPath ?? "", targetRelativePath);
469-
const resultJsonPath = `${targetAbsPath}.json`;
469+
// this has been changed from ".json" to ".out.json" for linters that run on terraform files
470+
// terraform extensions are .tf and .tf.json - this change prevents accidentally linting the trunk output
471+
const resultJsonPath = `${targetAbsPath}.out.json`;
470472
const args = `--upstream=false ${targetAbsPath}`;
471473
this.debug("Running `trunk check` on %s", targetRelativePath);
472474
return await this.runCheck({ args, linter, targetAbsPath, resultJsonPath });

0 commit comments

Comments
 (0)