kakakakakku blog

Weekly Tech Blog: Keep on Learning!

Trivy の Misconfiguration Scanning で Terraform の設定ミスを検出しよう

Trivy の「Misconfiguration Scanning」は Terraform をサポートしていて(AWS CloudFormation もサポートしている👏),Terraform コードのセキュリティ課題や設定ミスを検出できる❗️Trivy を活用した Terraform のスキャンを試した作業ログをまとめる📝

aquasecurity.github.io

tfsec から Trivy へ 🔜

tfsec は現在も使えるけど,今後は Trivy に移行する流れとなっている💡

GitHub Discussions に今年2月頃 tfsec is joining the Trivy family というアナウンスが投稿されている❗️

github.com

さらに GitHub の tfsec リポジトリ(master ブランチ)に今年5月頃 Migrating from tfsec to Trivy (tfsec-to-trivy-migration-guide.md) というドキュメントも追加されていて(プルリクエスト🔗)tfsec サイトのトップページとして表示されるはずの docs/index.md にも移行を推奨するアナウンスが追加されている.

しかし,サイト自体にはまだ反映されてなく正直気付きにくくなっているとは思う💨 重要な情報なのになんで〜

github.com

今月 tfsec: Terraform のセキュリティスキャンを活用しよう - kakakakakku blog を公開したときに Trivy 移行の件を指摘してもらって本当にありがとうございました \( 'ω')/ 感謝ァァァ!!!

Trivy をセットアップする

Trivy のセットアップは macOS だと Homebrew を使えば簡単〜

今回は Trivy v0.44.1 を前提にする.

$ brew install trivy

$ trivy version
Version: 0.44.1

aquasecurity.github.io

Trivy を実行する

Trivy の Misconfiguration Scanning を実行する場合は trivy config コマンドを実行すれば OK👌 以下は検証用の Terraform コードに Trivy を実行してみた結果を抜粋した.Amazon ECR リポジトリのイミュータブル設定を有効化するべきという警告が出ている💨

$ trivy config .

main.tf (terraform)

Tests: 1 (SUCCESSES: 0, FAILURES: 1, EXCEPTIONS: 0)
Failures: 1 (HIGH: 1, CRITICAL: 0)

HIGH: Repository tags are mutable.
════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
ECR images should be set to IMMUTABLE to prevent code injection through image mutation.

This can be done by setting <code>image_tab_mutability</code> to <code>IMMUTABLE</code>

See https://avd.aquasec.com/misconfig/avd-aws-0031
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
 main.tf:11-13
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
  11 ┌ resource "aws_ecr_repository" "playground" {
  12 │   name = "playground"
  13}
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

デフォルトは table フォーマットで出力される.例えば json で出力するなら --format オプションを指定する.ちなみにオプションの多くは後述する trivy.yaml にも設定できる❗️

$ trivy config . --format json | jq '.Results'

[
  {
    "Target": ".",
    "Class": "config",
    "Type": "terraform"
  },
  {
    "Target": "main.tf",
    "Class": "config",
    "Type": "terraform",
    "MisconfSummary": {
      "Successes": 0,
      "Failures": 1,
      "Exceptions": 0
    },
    "Misconfigurations": [
      {
        "Type": "Terraform Security Check",
        "ID": "AVD-AWS-0031",
        "AVDID": "AVD-AWS-0031",
        "Title": "ECR images tags shouldn't be mutable.",
        "Description": "ECR images should be set to IMMUTABLE to prevent code injection through image mutation.\n\nThis can be done by setting <code>image_tab_mutability</code> to <code>IMMUTABLE</code>",
        "Message": "Repository tags are mutable.",
        "Query": "data..",
        "Resolution": "Only use immutable images in ECR",
        "Severity": "HIGH",
        "PrimaryURL": "https://avd.aquasec.com/misconfig/avd-aws-0031",
        "References": [
          "https://sysdig.com/blog/toctou-tag-mutability/",
          "https://avd.aquasec.com/misconfig/avd-aws-0031"
        ],
        "Status": "FAIL",
        "Layer": {},
        "CauseMetadata": {
          "Resource": "aws_ecr_repository.playground",
          "Provider": "AWS",
          "Service": "ecr",
          "StartLine": 11,
          "EndLine": 13,
          "Code": {
            "Lines": [
              {
                "Number": 11,
                "Content": "resource \"aws_ecr_repository\" \"playground\" {",
                "IsCause": true,
                "Annotation": "",
                "Truncated": false,
                "FirstCause": true,
                "LastCause": false
              },
              {
                "Number": 12,
                "Content": "  name = \"playground\"",
                "IsCause": true,
                "Annotation": "",
                "Truncated": false,
                "FirstCause": false,
                "LastCause": false
              },
              {
                "Number": 13,
                "Content": "}",
                "IsCause": true,
                "Annotation": "",
                "Truncated": false,
                "FirstCause": false,
                "LastCause": true
              }
            ]
          }
        }
      }
    ]
  }
]

Trivy の Misconfiguration Scanning にどんなルールがあるのか

AWS 関連だと以下の Vulnerability Database で確認できる.もちろん tfsec と同じルールもあるけど,tfsec よりも対象サービスやルールが圧倒的に多く素晴らしかった👏

avd.aquasec.com

最近改善を担当することになった Terraform プロジェクトに Trivy の Misconfiguration Scanning を実行してみたところ 500件 も Failures が出てきた🔥とは言え,半分以上の警告は Severity(重大度)が LOW になっているため,今後の改善案としてコツコツ修正していくのが良さそう.

そして,今月公開した tfsec の検証記事で紹介したルールが Trivy でどう検出されているのか確認してみた❗️結果としては以下の7種類は「すべて」Trivy でも同じように検出されていた.

kakakakakku.hatenablog.com

Severity(重大度): CRITICAL

🔗 No Public Ingress Sgr

セキュリティグループ(インバウンド)で 0.0.0.0/0 は避けるべし!という警告🛑

CRITICAL: Security group rule allows ingress from public internet.
════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
Opening up ports to the public internet is generally to be avoided. You should restrict access to IP addresses or ranges that explicitly require it where possible.

See https://avd.aquasec.com/misconfig/avd-aws-0107
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

avd.aquasec.com

🔗 No Public Egress Sgr

セキュリティグループ(アウトバウンド)で 0.0.0.0/0 は避けるべし!という警告🛑

CRITICAL: Security group rule allows egress to multiple public internet addresses.
════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
Opening up ports to connect out to the public internet is generally to be avoided. You should restrict access to IP addresses or ranges that are explicitly required where possible.

See https://avd.aquasec.com/misconfig/avd-aws-0104
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

avd.aquasec.com

Severity(重大度): HIGH

🔗 No Policy Wildcards

IAM ポリシーを記述するときにワイルドカード * は避けるべし!という警告🛑

HIGH: IAM policy document uses wildcarded action 's3:*'
════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
You should use the principle of least privilege when defining your IAM policies. This means you should specify each exact permission required without using wildcards, as this could cause the granting of access to certain undesired actions, resources and principals.

See https://avd.aquasec.com/misconfig/avd-aws-0057
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

avd.aquasec.com

🔗 Enforce Immutable Repository

Amazon ECR リポジトリのイメージタグを上書きできないようにイミュータブル設定を有効化せよ!という警告🛑

HIGH: Repository tags are mutable.
════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
ECR images should be set to IMMUTABLE to prevent code injection through image mutation.

This can be done by setting <code>image_tab_mutability</code> to <code>IMMUTABLE</code>

See https://avd.aquasec.com/misconfig/avd-aws-0031
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

avd.aquasec.com

🔗 Enable Image Scans

Amazon ECR リポジトリのイメージスキャンを有効化せよ!という警告🛑

HIGH: Image scanning is not enabled.
════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
Repository image scans should be enabled to ensure vulnerable software can be discovered and remediated as soon as possible.

See https://avd.aquasec.com/misconfig/avd-aws-0030
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

avd.aquasec.com

🔗 Drop Invalid Headers

Application Load Balancer (ALB) で 無効なヘッダーフィールドを削除 を有効化せよ!という警告🛑

HIGH: Application load balancer is not set to drop invalid headers.
════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
Passing unknown or invalid headers through to the target poses a potential risk of compromise. 

By setting drop_invalid_header_fields to true, anything that doe not conform to well known, defined headers will be removed by the load balancer.

See https://avd.aquasec.com/misconfig/avd-aws-0052
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

avd.aquasec.com

Severity(重大度): LOW

🔗 Add Description To Security Group Rule

セキュリティグループの各エントリーに説明を設定せよ!という警告🛑

LOW: Security group rule does not have a description.
════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
Security group rules should include a description for auditing purposes.

Simplifies auditing, debugging, and managing security groups.

See https://avd.aquasec.com/misconfig/avd-aws-0124
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

avd.aquasec.com

不要な警告を減らす

Trivy の設定ファイル trivy.yaml を活用すると細かく挙動を制御できる.例えば Trivy で警告する Severity(重大度)の閾値を設定する場合は以下のように書くことで LOW / MEDIUM を無視できて警告を大幅に減らせる👏

severity:
  - HIGH
  - CRITICAL

もし特定の警告を無視する場合はまた別の設定ファイル .trivyignore に ID を設定すれば OK👌

AVD-AWS-0030
AVD-AWS-0031
AVD-AWS-0053
AVD-AWS-0057
AVD-AWS-0104
AVD-AWS-0107

個別に警告を無視する

Terraform コードにインラインコメントとして #trivy:ignore:... と書けば個別に警告を無視できる.以下は例として Alb Not Public の警告を無視するために #trivy:ignore:AVD-AWS-0053 と書いた.

#trivy:ignore:AVD-AWS-0053
resource "aws_lb" "alb" {
  name                       = "alb"
  load_balancer_type         = "application"
  internal                   = false
(中略)

aquasecurity.github.io

Trivy を GitHub Actions で動かす

Trivy を GitHub Actions で動かす場合は「trivy-action」を使えば簡単に導入できる❗️

github.com

1点注意点としては Trivy は警告があってもデフォルトでは exit code 0 を返す.よって GitHub Actions をエラーにするために exit code 1 を返すように設定ファイル trivy.yamlexit-code: 1 と書いておく💡

exit-code: 1

severity:
  - HIGH
  - CRITICAL

単純な GitHub Actions ワークフローとしてはこんな感じかとー👀

name: Trivy

on:
  push:
    branches:
      - master
  pull_request:
    branches:
      - master

jobs:
  trivy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Run Trivy
        uses: aquasecurity/trivy-action@master
        with:
          scan-type: config
          trivy-config: trivy.yaml

まとめ

アナウンスも出ているように今後は tfsec ではなく Trivy 中心になりそう❗️tfsec を導入する予定があるなら Trivy を検討すると良さそうだし,今まで tfsec を使っている場合は基本的には Trivy でも同じ警告は出せそうだから移行を検討してみると良さそう👌

あと早く tfsec サイトのトップページに GitHub 最新の docs/index.md をデプロイしてもらえるともっと Trivy の Misconfiguration Scanning が Terraform をサポートしていて tfsec の移行先になっていることを広く知ってもらえると思う📣

Trivy x Terraform 活用していくぞぉーーー \( 'ω')/