♾️

terraform の静的セキュリティスキャンツールの比較 tfsec chekcov snyk terrascan

2023/03/16に公開

terraform の静的セキュリティスキャンツールの比較 tfsec chekcov snyk terrascan

私は普段AWS等のインフラの管理を行うときにはterraformを使ってその管理を行っています。
インフラを実装するにあたって、セキュリティのケアを行っていくことは大切であります[1]
今回は、設計実装段階[2]にCLI[3]からセキュリティのチェックを行うことのできる静的セキュリティスキャンツールについていくつか比較してみました。

この記事が参考になる人は

  • IaCをterraformでやっていてDevSecOpsをはじめてみようと思っている人
  • tfsec,chekcov,snyk,terrascanのcliやgithub actionsへの導入方法を知りたい人
  • tfsec,chekcov,snyk,terrascanの違いを知りたい人

対象のコード

下記の自作コードを今回のスキャン対象にしています。(TODO コンテナの例も入れ込みたい )
https://github.com/piroz/try-iac-scanner

tfsec

tfsecはAqua Security社の、オープンソースツールです。

https://github.com/aquasecurity/tfsec

tfsecはTerraformコードのセキュリティチェックを行うツールで、公式のTerraformセキュリティガイドラインに従って、潜在的な脆弱性を検出します。

tfsecの導入

導入はbrewから行えます

$ brew install tfsec

tfsecの実行

前述の下記レポジトリに対して実行すると

https://github.com/piroz/try-iac-scanner

下記のような結果に

Result #1 HIGH No public access block so not blocking public acls 
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
 s3.tf:1-3
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
   1    resource "aws_s3_bucket" "main" {
   2        name = "my-bucket-name"
   3    }
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
         ID aws-s3-block-public-acls
     Impact PUT calls with public ACLs specified can make objects public
 Resolution Enable blocking any PUT calls with a public ACL specified

 More Information
 - https://aquasecurity.github.io/tfsec/v1.28.1/checks/aws/s3/block-public-acls/
 - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block#block_public_acls
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────


Result #2 HIGH No public access block so not blocking public policies 
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
 s3.tf:1-3
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
   1    resource "aws_s3_bucket" "main" {
   2        name = "my-bucket-name"
   3    }
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
         ID aws-s3-block-public-policy
     Impact Users could put a policy that allows public access
 Resolution Prevent policies that allow public access being PUT

 More Information
 - https://aquasecurity.github.io/tfsec/v1.28.1/checks/aws/s3/block-public-policy/
 - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block#block_public_policy
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────


Result #3 HIGH Bucket does not have encryption enabled 
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
 s3.tf:1-3
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
   1    resource "aws_s3_bucket" "main" {
   2        name = "my-bucket-name"
   3    }
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
         ID aws-s3-enable-bucket-encryption
     Impact The bucket objects could be read if compromised
 Resolution Configure bucket encryption

 More Information
 - https://aquasecurity.github.io/tfsec/v1.28.1/checks/aws/s3/enable-bucket-encryption/
 - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket#enable-default-server-side-encryption
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
# ...省略
 timings
 ──────────────────────────────────────────
 disk i/o             10.536µs
 parsing              114.543µs
 adaptation           64.899µs
 checks               5.613634ms
 total                5.803612ms

 counts
 ──────────────────────────────────────────
 modules downloaded   0
 modules processed    1
 blocks processed     1
 files read           1

 results
 ──────────────────────────────────────────
 passed               3
 ignored              0
 critical             0
 high                 6
 medium               2
 low                  1

 3 passed, 9 potential problem(s) detected.

結構ぞろぞろとでてきていますが

scan結果に下記のようなURLがあり
良いコード例と悪いコード例があり
それを参考に修正していくことになりそうです。

https://aquasecurity.github.io/tfsec/v1.28.1/checks/aws/s3/encryption-customer-key/

また、検出された問題について今回はわけあって対応しないみたいなときには
terraformのコード上に下記のようなコメントを書いておくと

# tfsec:ignore:aws-s3-specify-public-access-block
resource "aws_s3_bucket" "main" {

下記のようにtfsecの警告をignoredにすることはできます

$ tfsec --include-ignored
# ...省略
Result #9 IGNORED (LOW) Bucket does not have a corresponding public access block. 
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
  s3.tf:2-4
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
    2    resource "aws_s3_bucket" "main" {
    3        name = "my-bucket-name"
    4    }
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
          ID aws-s3-specify-public-access-block
      Impact Public access policies may be applied to sensitive data buckets
  Resolution Define a aws_s3_bucket_public_access_block for the given bucket to control public access policies

  More Information
  - https://aquasecurity.github.io/tfsec/v1.28.1/checks/aws/s3/specify-public-access-block/
  - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block#bucket
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────


  timings
  ──────────────────────────────────────────
  disk i/o             9.706µs
  parsing              115.315µs
  adaptation           65.411µs
  checks               5.079941ms
  total                5.270373ms

  counts
  ──────────────────────────────────────────
  modules downloaded   0
  modules processed    1
  blocks processed     1
  files read           1

  results
  ──────────────────────────────────────────
  passed               3
  ignored              1
  critical             0
  high                 6
  medium               2
  low                  0

  3 passed, 1 ignored, 8 potential problem(s) detected.

ignoredしたものをcheck結果に表示したい場合--include-ignoredオプションつきでtfsecを起動する必要がありました。

また、ignoreの有効期限を設定することもできて下記のように記述すれば可能です

# tfsec:ignore:aws-s3-specify-public-access-block:exp:2022-01-02
resource "aws_s3_bucket" "main" {

ignoreについてのドキュメントは下記です

https://aquasecurity.github.io/tfsec/v1.0.11/getting-started/configuration/ignores/

tfsec GitHub Actions

GitHub Actionsへの追加は当該Github レポジトリのActionsタブからtfsecを検索してconfitgureボタンを押すと、yamlの編集画面になります。

下記のように編集して追加すればtfsecをGitHub Actionsへ組み込むことができます
(私は、schedule実行のeventをコメント化しました)

https://github.com/piroz/try-iac-scanner/commit/37b66d30cbe4a5ed1bb2f7bd9a6607b694988c24

checkcov

checkcovはBridgecrew社の、オープンソースツールです。

https://github.com/bridgecrewio/checkov

Terraformコードの静的分析を行い、セキュリティ、コスト、パフォーマンス、ベストプラクティスに関する問題を特定します。

checkcovの導入

導入はpipやhomebrew等から行えます。私はpython環境の整備はしていたのでpipでインストールしました

※python環境が必要です。私がubuntu22.04でのpython環境を構築した際の内容は下記で参照できます

https://zenn.dev/hiroshimraz/articles/2598456e4c94f9

$ pip install checkov

※もしhomebrewでinstallしたい場合は

$ brew install checkov

checkcovの実行

前述の下記レポジトリに対して実行すると

https://github.com/piroz/try-iac-scanner

下記のような結果に

checkov --file s3.tf 
[ terraform framework ]: 100%|████████████████████|[1/1], Current File Scanned=s
[ secrets framework ]: 100%|████████████████████|[1/1], Current File Scanned=s3.

       _               _              
   ___| |__   ___  ___| | _______   __
  / __| '_ \ / _ \/ __| |/ / _ \ \ / /
 | (__| | | |  __/ (__|   < (_) \ V / 
  \___|_| |_|\___|\___|_|\_\___/ \_/  
                                      
By bridgecrew.io | version: 2.3.124 

terraform scan results:

Passed checks: 4, Failed checks: 7, Skipped checks: 0
# ...省略
Check: CKV_AWS_145: "Ensure that S3 buckets are encrypted with KMS by default"
	FAILED for resource: aws_s3_bucket.main
	File: /s3.tf:1-3
	Guide: https://docs.bridgecrew.io/docs/ensure-that-s3-buckets-are-encrypted-with-kms-by-default

		1 | resource "aws_s3_bucket" "main" {
		2 |     name = "my-bucket-name"
		3 | }

tfsecの場合、passedなどの結果がコマンド実行結果の最終行にでてきていて、cliでの実行時は見やすいかもしれないと思いました。

checkovでもtfsec同様、scan結果に下記のようなURLがあり
それを参考に修正していくことになりそうです。

https://docs.bridgecrew.io/docs/ensure-that-s3-buckets-are-encrypted-with-kms-by-default

また、検出された問題について今回はわけあって対応しないみたいなときもcheckovでも
terraformのコード上に下記のようなコメントを書いておくと

resource "aws_s3_bucket" "main" {
  # checkov:skip=CKV2_AWS_6

下記のようにcheckovのcheckをSKIPPEDすることはできます

# ...省略
Passed checks: 4, Failed checks: 6, Skipped checks: 1
# ...省略
Check: CKV2_AWS_6: "Ensure that S3 bucket has a Public Access block"
	SKIPPED for resource: aws_s3_bucket.main
	Suppress comment: No comment provided
	File: /s3.tf:2-5
	Guide: https://docs.bridgecrew.io/docs/s3-bucket-should-have-public-access-blocks-defaults-to-false-if-the-public-access-block-is-not-attached

SKIPPEDされたものはCLIでの実行結果の最後に出力されます。

checkov GitHub Actions

checkov のgithub actionsは下記を参考にして

https://github.com/marketplace/actions/checkov-github-action

このような感じに導入できます

https://github.com/piroz/try-iac-scanner/blob/3ae49b5fbfebc945cdd15bc12b8e0a305ae39f68/.github/workflows/checkov.yml

snyk

snykは、Terraformを含む多数のプログラミング言語やフレームワークに対応した、継続的なセキュリティ監視のための統合セキュリティプラットフォームです。Terraformに対応しており、Terraformのコードをスキャンし、潜在的なセキュリティ上の問題を特定することができます。

snykの導入

以下のcliを使います

https://github.com/snyk/cli

導入はhomebrewから行えます。

$ brew tap snyk/tap
$ brew install snyk

node.jsの環境がすでにある場合は下記のようにinstallすることも可能です

$ npm install snyk@latest -g

snykの登録

snykを実行するためは登録が必要です
今回はpricingstart freeからfreeplanを登録してすすめています

登録を完了したあとcliで認証をします

$ snyk auth

snykの実行

前述の下記レポジトリに対して実行すると

https://github.com/piroz/try-iac-scanner

下記のような結果に

$ snyk iac test

Snyk Infrastructure as Code

✔ Test completed.

Issues

Low Severity Issues: 3

  [Low] S3 bucket versioning disabled
  Info:    S3 bucket versioning is disabled. Changes or deletion of objects will
           not be reversible
  Rule:    https://snyk.io/security-rules/SNYK-CC-TF-124
  Path:    resource > aws_s3_bucket[main] > versioning > enabled
  File:    s3.tf
  Resolve: For AWS provider < v4.0.0, set `versioning.enabled` attribute to
           `true`. For AWS provider >= v4.0.0, add aws_s3_bucket_versioning
           resource.

  [Low] S3 bucket MFA delete control disabled
  Info:    S3 bucket will not enforce MFA login on delete requests. Object could
           be deleted without stronger MFA authorization
  Rule:    https://snyk.io/security-rules/SNYK-CC-TF-127
  Path:    resource > aws_s3_bucket[main] > versioning > mfa_delete
  File:    s3.tf
  Resolve: Follow instructions in `https://docs.aws.amazon.com/AmazonS3/latest/u
           serguide/MultiFactorAuthenticationDelete.html` to manually configure
           the MFA setting. For AWS provider < v4.0.0 set
           `versioning.mfa_delete` attribute to `true` in aws_s3_bucket
           resource. For AWS provider >= v4.0.0 set
           'versioning_configuration.mfa_delete` attribute to `Enabled`. The
           terraform change is required to reflect the setting in the state file

  [Low] S3 server access logging is disabled
  Info:    The s3 access logs will not be collected. There will be no audit
           trail of access to s3 objects
  Rule:    https://snyk.io/security-rules/SNYK-CC-TF-45
  Path:    input > resource > aws_s3_bucket[main] > logging
  File:    s3.tf
  Resolve: For AWS provider < v4.0.0, add `logging` block attribute. For AWS
           provider >= v4.0.0, add aws_s3_bucket_logging resource.

Medium Severity Issues: 1

  [Medium] Non-encrypted S3 Bucket
  Info:    Non-encrypted S3 Bucket. A non-encrypted S3 bucket increases the
           likelihood of unintentional data exposure
  Rule:    https://snyk.io/security-rules/SNYK-CC-TF-4
  Path:    input > resource > aws_s3_bucket[main]
  File:    s3.tf
  Resolve: For AWS provider < v4.0.0, set `server_side_encryption_configuration`
           block attribute. For AWS provider >= v4.0.0 add
           aws_s3_bucket_server_side_encryption_configuration resource.

High Severity Issues: 1

  [High] S3 block public ACLs control is disabled
  Info:    Bucket does not prevent creation of public ACLs. Anyone who can
           manage bucket's ACLs will be able to grant public access to the
           bucket
  Rule:    https://snyk.io/security-rules/SNYK-CC-TF-95
  Path:    resource > aws_s3_bucket[main]
  File:    s3.tf
  Resolve: Set the `aws_s3_bucket_public_access_block` `block_public_acls` field
           to true.

-------------------------------------------------------

Test Summary

  Organization: piroz
  Project name: piroz/try-iac-scanner

✔ Files without issues: 0
✗ Files with issues: 1
  Ignored issues: 0
  Total issues: 5 [ 0 critical, 1 high, 1 medium, 3 low ]

-------------------------------------------------------

Tip

  New: Share your test results in the Snyk Web UI with the option --report

iacのscan以外にsnyk iac describeで管理済みのリソースとのdriftを検知するような機能もあるようで、snykは総合ツールの方向性で構築されていそうでした。

なお、snyk iacについては現状tfファイルをまたいで関連するリソース設定(例えばaws_s3_bucket_aclaws_s3_bucketを別ファイルに定義)していた場合、誤検知してしまうような仕様になっているとのことで、tfファイルを分割しているような環境では注意が必要そうです。

https://docs.snyk.io/scan-cloud-deployment/snyk-infrastructure-as-code/scan-terraform-files/terraform-aws-provider-support

snyk Github Actions

snykのtokenが必要なので下記の手順で取得します

https://github.com/snyk/actions#getting-your-snyk-token

cliは先の手順でセットアップ済みなのでsnyk config get apiで取得可能でした

https://github.com/snyk/actions

todo

terrascan

terrascanもTerraformによって生成されたIaCコードをscanするツールでAWS,Azure,GCPに対応しています。

terrascanの導入

https://github.com/tenable/terrascan

導入はhomebrewからも行えるのでhomebrewから導入しました。

$ brew install terrascan

terrascanの実行

前述の下記レポジトリに対して実行すると

https://github.com/piroz/try-iac-scanner

下記のような結果に

$ terrascan scan
2023/04/16 08:39:24 [DEBUG] GET https://registry.terraform.io/v1/providers/hashicorp/aws/versions


Scan Errors -

        IaC Type            :   arm
        Directory           :   /home/xxx/try-iac-scanner
        Error Message       :   ARM files not found in the directory /home/xxx/try-iac-scanner

        -----------------------------------------------------------------------

        IaC Type            :   docker
        Directory           :   /home/xxx/try-iac-scanner
        Error Message       :   Dockerfile not found in the directory /home/xxx/try-iac-scanner

        -----------------------------------------------------------------------

        IaC Type            :   cft
        Directory           :   /home/xxx/try-iac-scanner/.github/workflows
        Error Message       :   error while loading iac file '/home/xxx/try-iac-scanner/.github/workflows/checkov.yml', err: failed to find valid Resources key in file: /home/xxx/try-iac-scanner/.github/workflows/checkov.yml

        -----------------------------------------------------------------------

        IaC Type            :   cft
        Directory           :   /home/xxx/try-iac-scanner/.github/workflows
        Error Message       :   error while loading iac file '/home/xxx/try-iac-scanner/.github/workflows/snyk-infrastructure.yml', err: failed to find valid Resources key in file: /home/xxx/try-iac-scanner/.github/workflows/snyk-infrastructure.yml

        -----------------------------------------------------------------------

        IaC Type            :   cft
        Directory           :   /home/xxx/try-iac-scanner/.github/workflows
        Error Message       :   error while loading iac file '/home/xxx/try-iac-scanner/.github/workflows/tfsec.yml', err: failed to find valid Resources key in file: /home/xxx/try-iac-scanner/.github/workflows/tfsec.yml

        -----------------------------------------------------------------------

        IaC Type            :   kustomize
        Directory           :   /home/xxx/try-iac-scanner
        Error Message       :   kustomization.y(a)ml file not found in the directory /home/xxx/try-iac-scanner

        -----------------------------------------------------------------------

        IaC Type            :   helm
        Directory           :   /home/xxx/try-iac-scanner
        Error Message       :   no helm charts found in directory /home/xxx/try-iac-scanner

        -----------------------------------------------------------------------



Scan Summary -

        File/Folder         :   /home/xxx/try-iac-scanner
        IaC Type            :   terraform
        Scanned At          :   2023-04-15 23:39:25.923043388 +0000 UTC
        Policies Validated  :   10
        Violated Policies   :   0
        Low                 :   0
        Medium              :   0
        High                :   0

tfsec,checkov,snykが指摘していた問題についてはterrascanは指摘をしてくれなかったです。
Policies Validated: 10な内容はどうだったか気になったので調べると

documentに記載の下記のpoliciesが調査されていそう?

https://github.com/tenable/terrascan/blob/master/docs/policies/aws.md#aws_s3_bucket

terrascanが利用するregoのポリシーについては下記あたりにありそうだった

https://github.com/tenable/terrascan/tree/ec6cae94a031524e469c0b572a64cd7315a963c3/pkg/policies/opa/rego/aws/aws_s3_bucket

todo

脚注
  1. 非常に手間のかかることでも ↩︎

  2. DevSecOpsの信条「シフト・レフト」を実践する際に ↩︎

  3. ubuntu 22.04環境で試しています ↩︎

Discussion