Trivy conifigで特定Terraformリソースの特定アラートを抑制する
やりたいこと
TrivyのconfigサブコマンドでTerraformのコードを静的解析したい。最初からtfsecを利用してもよいが、他にもDockerfileなども静的解析したいのでTrivyで十分であればTrivyだけで対処したい。
一方で、すべての警告に対応できるわけではないので、特定リソースにおいて特定ルールによる警告は抑制したい。同じルールでもあるリソースでは許可しても別のリソースでは許可したくないケースがあるので、指定ルールを一律で許可したくはない。また、同じリソースであってもあるルールは許可しても別のルールは許可したくないケースがあるので、指定リソースを一律で解析除外はしたくない。
Trivy v0.23.0 および tfsec v1.1.4 にて検証。
具体例
AWSのセキュリティグループで、すべての外部接続先を許可する。
resource "aws_security_group" "sample" {
name = "sample-sg"
description = "sample security group"
vpc_id = var.vpc_id
ingress {
description = "allow access HTTP"
from_port = 80
to_port = 80
protocol = "tcp"
self = true
}
egress {
description = "allow all egress connection"
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}
このコードをtrivyで静的解析に掛けると警告を出してくれる。
$ trivy config .
2022-02-12T01:22:44.026Z INFO Detected config files: 1
network.tf (terraform)
=======================================
Tests: 5 (SUCCESSES: 4, FAILURES: 1, EXCEPTIONS: 0)
Failures: 1 (UNKNOWN: 0, LOW: 0, MEDIUM: 0, HIGH: 0, CRITICAL: 1)
+------------------------------------------+--------------+------------------------------------------+----------+------------------------------------------+
| TYPE | MISCONF ID | CHECK | SEVERITY | MESSAGE |
+------------------------------------------+--------------+------------------------------------------+----------+------------------------------------------+
| Terraform Security Check powered by | AVD-AWS-0103 | An inline egress security group rule | CRITICAL | Resource 'aws_security_group.sample' |
| tfsec | | allows traffic to /0. | | defines a fully open egress security |
| | | | | group. |
+------------------------------------------+--------------+------------------------------------------+----------+------------------------------------------+
解決策
tfsecのIgnoring specific issueを利用する。コードの対象箇所にコメントとして tfsec:ignore:RULE
を記載すればその箇所での警告を抑制してくれる。
resource "aws_security_group" "sample" {
...
egress {
description = "allow all egress connection"
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"] #tfsec:ignore:AWS009
}
}
実行結果
$ trivy config .
2022-02-12T01:26:24.832Z INFO Detected config files: 1
network.tf (terraform)
=======================================
Tests: 4 (SUCCESSES: 4, FAILURES: 0, EXCEPTIONS: 0)
Failures: 0 (UNKNOWN: 0, LOW: 0, MEDIUM: 0, HIGH: 0, CRITICAL: 0)
指定するルールID
指定するルールIDとして、 trivy 実行時に警告一覧として出力される MISCONF IDを指定したくなるが、これを指定しても警告を抑制してくれない。
resource "aws_security_group" "sample" {
...
egress {
description = "allow all egress connection"
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"] #tfsec:ignore:AVD-AWS-0103
}
}
また、tfsecは v1.0.0 からルールID体系が変更になった。これに伴い AWS009
といったルールID (leagcy ID)から rules.md に記載されている aws-vpc-no-public-egress-sgr
というルールID(new ID)を指定する必要がある。しかし、trivyでは legacy IDにのみ対応しており、new IDを指定しても警告を抑制してくれない。
resource "aws_security_group" "sample" {
...
egress {
description = "allow all egress connection"
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"] #tfsec:ignore:aws-vpc-no-public-egress-sgr
}
}
以上から、trivyを利用する以上はlegacy IDを指定する必要がある。
legacy IDの取得
では、どうやってlegacy IDを取得するかというと、これが難しい。
trivyにMISCONF IDの替わりにlegacy IDを出力するオプションはなさそう。MISCONF IDからlegacy IDに変換する方法もなさそう。現状ではtfsecを実行して対応するルールIDを取得するしかない。
しかし、tfsecも最新のv1.1.4ではnew IDに移行しており、legacy IDを出力してくれない。このため、古いバージョンのtfsecを実行するか、tfsecが内部で持つ対応マップ を参照してlegacy IDを取得する必要がある。
以上から、legacy IDを取得するためには tfsecを実行する→対応マップでlegacy IDを参照するというステップを経る必要がある。しかし、tfsecで実行する以上はtfsecによる警告も同時に抑制する必要があるが、最新のtfsecではlegacy IDで指定しても警告を抑制してくれない。このため、コードには新旧のルールIDで警告を抑制する必要がある。
resource "aws_security_group" "sample" {
...
egress {
description = "allow all egress connection"
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"] #tfsec:ignore:aws-vpc-no-public-egress-sgr tfsec:ignore:AWS009
}
}
できればMISCONF IDを指定しても trivy が除外してくれるか、trivyが警告出力でlegacy IDを出力する、またはtrivyが警告除外のルールIDとしてnew IDに対応した上で結果出力時にnew IDを出力して欲しいところ。
その他の解決策
trivyignore
検出対象から除外したい脆弱性や設定不備については tirvyignoreを指定することで回避できる。ここでは trivyのMISCONF IDが指定できる。tfsecのlegacy IDやnew IDは指定できない。
$ cat .trivyignore
AVD-AWS-0103
この方法であればtrivyで設定不備が検出された後に tfsecを実行してlegacy IDのマップを参照して、といった作業が不要になる。一方で、ここで指定したIDは他のリソースからも検出が除外される。特定リソースでのみ除外したいという今回の要件には合わない。
--ski-files / --skip-dirs
trivy config --skip-files network.tf .
のような方法で対象ファイル/ディレクトリを解析対象から除外できる。
ただし、この方法では ingress に関する警告も出力されなくなるし、解析対象に含めたいか考慮してファイル分割する必要が出てくる。今回のようにルール適用を制御する用途としては不向き。
Rego policy
Regoのポリシーで今回の要件を実現できるかは不明。実現できたとしても手間が掛かり過ぎるので不適切な気がする。
まとめ
- trivyでterraformの警告を抑制するにはコメントでtfsecのlegacy IDを指定する
- legacy IDを取得するにはtfsecを実行した上で対応表からnew IDとの対応を確認する必要がある
- ここまでしてtrivyを使いたいかは要検討、直接tfsecを使った方が簡単
Discussion