trivy によるスキャンでファイルベースの Filtering に対応しました(EXPERIMENTAL な機能なので利用にはご注意下さい)
trivy は コンテナイメージのスキャンに加えて、CloudFormation や Terraform などの IaC 設定ファイルについてもセキュリティスキャンを実行することができます。
tfsec の技術とルールセットを取り込んでいて Terraform に限らない設定ファイルを trivy でチェック可能です。
IaC テンプレートに対してセキュリティ面で危ない設定が無いか確認する際は大変便利なので、私も活用させていただいてます。
今回 v0.45.0 にて、ファイル単位で特定チェックを無視するかどうかを設定できるようになりましたので、試してみました。
ファイルベース Filtering の何が嬉しいか
私は CloudFormation テンプレートに対する静的スキャンを利用しておりますが、特定リソースで特定チェックについて対応しない場合の取り扱いについて悩んでいる部分がありました。(S3 Server Access Logs の出力先として作成したバケットについて、Server Access Logs を有効化しない等)
tf ファイルであれば、下記のようなインラインコメントを利用した方法に対応しております。
#trivy:ignore:AVD-GCP-0051 resource "google_container_cluster" "one_off_test" { name = var.cluster_name location = var.region }
上記方法が yaml ファイルに対しては対応していなかったので、特定リソースで対応しないと決定した際にも .trivyignore
を使ってリポジトリ全体での無視をするような運用をしておりました。
trivy 0.45.0 にて、.trivyignore.yaml
というファイルを定義して読み込ませることでファイルベースの Filtering(特定検出結果の無視) ができるようになりました。
ただ、こちらは EXPERIMENTAL な機能であるため破壊的変更が入る可能性があるようです。
This feature might change without preserving backwards compatibility.
.trivyignore.yaml
とはいえ、個人的には渇望していた機能なので試してみました。
※ こちらも EXPERIMENTAL な機能ですが、Open Policy Agent を利用した Filtering にも対応しているようです。このために Rego を覚えて運用するのも大変に感じたので、今回はファイルベースの Filetering を試してみます。
試してみた
まず、下記 2 つテンプレートを用意しました。
何らかのコンテンツを格納する S3 バケット
AWSTemplateFormatVersion: "2010-09-09" Parameters: BucketNamePrefix: Type: String Resources: ContentsBucket: Type: AWS::S3::Bucket Properties: BucketName: !Sub "${BucketNamePrefix}-contents-bucket" PublicAccessBlockConfiguration: BlockPublicAcls: true BlockPublicPolicy: true IgnorePublicAcls: true RestrictPublicBuckets: true VersioningConfiguration: Status: Enabled BucketEncryption: ServerSideEncryptionConfiguration: - ServerSideEncryptionByDefault: SSEAlgorithm: AES256 LoggingConfiguration: DestinationBucketName: !ImportValue "server-access-logs-bucket-name" LogFilePrefix: !Sub "${BucketNamePrefix}-contents-bucket/"
アカウント内の S3 バケットの Server Access Logs を集約して格納するためのバケット
AWSTemplateFormatVersion: "2010-09-09" Parameters: BucketNamePrefix: Type: String Resources: ServerAccessLogsBucket: Type: AWS::S3::Bucket Properties: BucketName: !Sub "${BucketNamePrefix}-serveraccesslogs-bucket" PublicAccessBlockConfiguration: BlockPublicAcls: true BlockPublicPolicy: true IgnorePublicAcls: true RestrictPublicBuckets: true BucketEncryption: ServerSideEncryptionConfiguration: - ServerSideEncryptionByDefault: SSEAlgorithm: AES256 LifecycleConfiguration: Rules: - Id: Expire365days Status: Enabled ExpirationInDays: 365 Outputs: ServerAccessLogsBucketName: Description: Bucket Name for Server Access Logs Value: !Ref ServerAccessLogsBucket Export: Name: !Sub server-access-logs-bucket-name
リポジトリ全体として KMS 暗号化は不要として、S3-SSE で暗号化されていれば良いとします。
また、Server Access Logs 集約用バケットについては Server Access Logs と Versioning について無効で良いが、今後新しく追加されるリソースではチェックしたいためにこれらのチェックをリポジトリ全体では無効化したくないとします。
その場合、下記のように .trivyignore.yaml
を定義することで特定ルールを無視することが可能です。
misconfigurations: - id: AVD-AWS-0132 statement: "There is no problem with S3-SSE." - id: AVD-AWS-0089 paths: - "cfn/s3-server-access-logs.yaml" statement: "It is the destination bucket for S3 Server access logs." - id: AVD-AWS-0090 paths: - "cfn/s3-server-access-logs.yaml" statement: "It is the destination bucket for S3 Server access logs."
ファイル構造は下記です。
$ tree . -a . ├── .trivyignore.yaml └── cfn ├── s3-contents.yaml └── s3-server-access-logs.yaml
実際にスキャンしてみると、無事特定ルールを無視できました。
$ trivy conf . --ignorefile ./.trivyignore.yaml 2023-09-05T16:52:08.916+0900 INFO Misconfiguration scanning is enabled 2023-09-05T16:52:09.420+0900 INFO Detected config files: 2
s3-content2.yaml
として Server Access Logs を無効化したバケットを追加して再度スキャンしてみます。
AWSTemplateFormatVersion: "2010-09-09" Parameters: BucketNamePrefix: Type: String Resources: ContentsBucket2: Type: AWS::S3::Bucket Properties: BucketName: !Sub "${BucketNamePrefix}-contents-bucket2" PublicAccessBlockConfiguration: BlockPublicAcls: true BlockPublicPolicy: true IgnorePublicAcls: true RestrictPublicBuckets: true VersioningConfiguration: Status: Enabled BucketEncryption: ServerSideEncryptionConfiguration: - ServerSideEncryptionByDefault: SSEAlgorithm: AES256
こちらではきちんと検出することができました!
> trivy conf . --ignorefile ./.trivyignore.yaml 2023-09-05T17:57:31.583+0900 INFO Misconfiguration scanning is enabled 2023-09-05T17:57:32.087+0900 INFO Detected config files: 3 cfn/s3-content2.yaml (cloudformation) Tests: 11 (SUCCESSES: 10, FAILURES: 1, EXCEPTIONS: 0) Failures: 1 (UNKNOWN: 0, LOW: 1, MEDIUM: 0, HIGH: 0, CRITICAL: 0) LOW: Bucket has logging disabled ════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════ Ensures S3 bucket logging is enabled for S3 buckets See https://avd.aquasec.com/misconfig/avd-aws-0089 ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── cfn/s3-content2.yaml:8-22 ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── 8 ┌ ContentsBucket2: 9 │ Type: AWS::S3::Bucket 10 │ Properties: 11 │ BucketName: !Sub "${BucketNamePrefix}-contents-bucket2" 12 │ PublicAccessBlockConfiguration: 13 │ BlockPublicAcls: true 14 │ BlockPublicPolicy: true 15 │ IgnorePublicAcls: true 16 └ RestrictPublicBuckets: true .. ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
現状、 .trivyignore.yaml
を利用する場合は明確に --ignorefile
として指定する必要があるようです。
また、Dockerfile や k8s の manifest ファイル等のスキャンに加え、イメージスキャンの際も同様の Filtering を適用できるようです。
まとめ
楽にファイルベースの Filtering ができるようになって最高でした!
まだ実験的な機能のようですが、上手く活用できるとより便利に trivy を活用できると思います!