aquasecurity / trivy

Find vulnerabilities, misconfigurations, secrets, SBOM in containers, Kubernetes, code repositories, clouds and more
https://aquasecurity.github.io/trivy
Apache License 2.0
23.55k stars 2.32k forks source link

feat(terraform): support for `random` provider #5357

Open nikpivkin opened 1 year ago

nikpivkin commented 1 year ago

Random Provider provides resources that generate some values that are available as read-only attributes. But since Trivy does not support these resources, the attributes are left empty, which leads to unexpected results.

Actual:

resource "random_id" "this" {
  byte_length = 1
}

resource "google_project" "this" {
  name            = "test"
  project_id      = random_id.this.hex
  auto_create_network = true
}

Output:

trivy conf .
2023-10-10T18:56:40.380+0700    INFO    Misconfiguration scanning is enabled
2023-10-10T18:56:40.913+0700    INFO    Detected config files: 1

After changing the project id to a static value:

resource "random_id" "this" {
  byte_length = 1
}

resource "google_project" "this" {
  name            = "test"
  project_id      = "test-project-id" // changed
  auto_create_network = true
}

Output:

trivy conf .
2023-10-10T18:57:37.599+0700    INFO    Misconfiguration scanning is enabled
2023-10-10T18:57:38.131+0700    INFO    Detected config files: 2

main.tf (terraform)

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

HIGH: Project has automatic network creation enabled.
═══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
The default network which is provided for a project contains multiple insecure firewall rules which allow ingress to the project's infrastructure. Creation of this network should therefore be disabled.

See https://avd.aquasec.com/misconfig/avd-gcp-0010
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
 main.tf:8
   via main.tf:5-9 (google_project.this)
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
   5   resource "google_project" "this" {
   6     name            = "test"
   7     project_id      = "test-project-id"
   8 [   auto_create_network = true
   9   }
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
rasmuspfeiffermer commented 9 months ago

This can even lead to a crash, if you use the random_password.password.result as value in a map and use that map in a for_each.

The output of trivy config --debug ./ is:

trivy config --debug ./
2024-01-18T09:11:45.875+0100    DEBUG   Severities: ["UNKNOWN" "LOW" "MEDIUM" "HIGH" "CRITICAL"]
2024-01-18T09:11:45.888+0100    DEBUG   cache dir:  /home/rasmus.pfeiffer/.cache/trivy
2024-01-18T09:11:45.888+0100    INFO    Misconfiguration scanning is enabled
2024-01-18T09:11:45.888+0100    DEBUG   Policies successfully loaded from disk
2024-01-18T09:11:45.888+0100    DEBUG   Enabling misconfiguration scanners: [azure-arm cloudformation dockerfile helm kubernetes terraform terraformplan]
2024-01-18T09:11:45.925+0100    DEBUG   Walk the file tree rooted at '.' in series
2024-01-18T09:11:45.928+0100    DEBUG   Scanning Helm files for misconfigurations...
2024-01-18T09:11:45.929+0100    DEBUG   Scanning Terraform files for misconfigurations...
2024-01-18T09:11:45.929+0100    DEBUG   [misconf] 11:45.929167457 terraform.scanner                Scanning [&{%!s(*mapfs.file=&{ [] {. 256 2147484096 {13934793863686833912 667651600 0x5597a3ff8220} <nil>} {{{0 0} {[] {} 0xc001589d00} map[.terraform:0xc001581fe0 main.tf:0xc0009d63e0] 0}}}) .}] at '.'...
2024-01-18T09:11:45.931+0100    DEBUG   [misconf] 11:45.931317742 terraform.scanner.rego           Overriding filesystem for policies!
2024-01-18T09:11:45.975+0100    DEBUG   [misconf] 11:45.975674699 terraform.scanner.rego           Loaded 188 policies from disk.
2024-01-18T09:11:45.975+0100    DEBUG   [misconf] 11:45.975987041 terraform.scanner.rego           Overriding filesystem for data!
2024-01-18T09:11:46.355+0100    DEBUG   [misconf] 11:46.355516528 terraform.scanner                Scanning root module '.'...
2024-01-18T09:11:46.355+0100    DEBUG   [misconf] 11:46.355569959 terraform.parser.<root>          Setting project/module root to '.'
2024-01-18T09:11:46.355+0100    DEBUG   [misconf] 11:46.355582880 terraform.parser.<root>          Parsing FS from '.'
2024-01-18T09:11:46.355+0100    DEBUG   [misconf] 11:46.355620106 terraform.parser.<root>          Parsing 'main.tf'...
2024-01-18T09:11:46.355+0100    DEBUG   [misconf] 11:46.355931052 terraform.parser.<root>          Added file main.tf.
2024-01-18T09:11:46.355+0100    DEBUG   [misconf] 11:46.355950538 terraform.parser.<root>          Evaluating module...
2024-01-18T09:11:46.356+0100    DEBUG   [misconf] 11:46.356193315 terraform.parser.<root>          Read 7 block(s) and 3 ignore(s) for module 'root' (1 file[s])...
2024-01-18T09:11:46.356+0100    DEBUG   [misconf] 11:46.356228866 terraform.parser.<root>          Added 3 variables from tfvars.
2024-01-18T09:11:46.356+0100    DEBUG   [misconf] 11:46.356249610 terraform.parser.<root>          Error loading module metadata: open .terraform/modules/modules.json: file does not exist.
2024-01-18T09:11:46.356+0100    DEBUG   [misconf] 11:46.356273007 terraform.parser.<root>          Working directory for module evaluation is '/home/rasmus.pfeiffer/Programs/trivy-test'
2024-01-18T09:11:46.356+0100    DEBUG   [misconf] 11:46.356333143 terraform.parser.<root>.evaluator Filesystem key is '8db47db7348b4550b8385e0c63de1f430a84131257d7b18e4542bb85213a28ba'
2024-01-18T09:11:46.356+0100    DEBUG   [misconf] 11:46.356347810 terraform.parser.<root>.evaluator Starting module evaluation...
panic: inconsistent map element types (cty.Object(map[string]cty.Type{"for_each":cty.Object(map[string]cty.Type{"my-first-secret":cty.DynamicPseudoType, "my-second-secret":cty.String, "my-third-secret":cty.DynamicPseudoType}), "id":cty.String, "key_vault_id":cty.String, "name":cty.String, "value":cty.String}) then cty.Object(map[string]cty.Type{"for_each":cty.Object(map[string]cty.Type{"my-first-secret":cty.DynamicPseudoType, "my-second-secret":cty.String, "my-third-secret":cty.DynamicPseudoType}), "id":cty.String, "key_vault_id":cty.String, "name":cty.String, "value":cty.NilType}))

goroutine 1 [running]:
github.com/zclconf/go-cty/cty.MapVal(0xc003294b90)
        github.com/zclconf/go-cty@v1.13.0/cty/value_init.go:220 +0x43b
github.com/aquasecurity/trivy-iac/pkg/scanners/terraform/parser.(*evaluator).expandBlockForEaches(0xc00133e480, {0xc001e16080, 0x7, 0x0?})
        github.com/aquasecurity/trivy-iac@v0.7.0/pkg/scanners/terraform/parser/evaluator.go:325 +0x4bf
github.com/aquasecurity/trivy-iac/pkg/scanners/terraform/parser.(*evaluator).expandBlocks(0x55979f6a9400?, {0xc001ddf240?, 0x55979f6a9400?, 0xc003555e00?})
        github.com/aquasecurity/trivy-iac@v0.7.0/pkg/scanners/terraform/parser/evaluator.go:207 +0x38
github.com/aquasecurity/trivy-iac/pkg/scanners/terraform/parser.(*evaluator).EvaluateAll(0xc00133e480, {0x5597a03cf2c8, 0xc001d05aa0})
        github.com/aquasecurity/trivy-iac@v0.7.0/pkg/scanners/terraform/parser/evaluator.go:152 +0x2e5
github.com/aquasecurity/trivy-iac/pkg/scanners/terraform/parser.(*Parser).EvaluateAll(0xc00111a2c0, {0x5597a03cf2c8, 0xc001d05aa0})
        github.com/aquasecurity/trivy-iac@v0.7.0/pkg/scanners/terraform/parser/parser.go:313 +0x6cd
github.com/aquasecurity/trivy-iac/pkg/scanners/terraform.(*Scanner).ScanFSWithMetrics(0xc00107d500, {0x5597a03cf2c8, 0xc001d05aa0}, {0x5597a030c640?, 0xc0015423d8}, {0x55979edd37b8, 0x1})
        github.com/aquasecurity/trivy-iac@v0.7.0/pkg/scanners/terraform/scanner.go:226 +0x5d0
github.com/aquasecurity/trivy-iac/pkg/scanners/terraform.(*Scanner).ScanFS(0x0?, {0x5597a03cf2c8?, 0xc001d05aa0?}, {0x5597a030c640?, 0xc0015423d8?}, {0x55979edd37b8?, 0x2a?})
        github.com/aquasecurity/trivy-iac@v0.7.0/pkg/scanners/terraform/scanner.go:143 +0x52
github.com/aquasecurity/trivy/pkg/misconf.(*Scanner).Scan(0xc001cba750, {0x5597a03cf2c8, 0xc001d05aa0}, {0x5597a030c640?, 0xc0014e63d8?})
        github.com/aquasecurity/trivy/pkg/misconf/scanner.go:147 +0x1a8
github.com/aquasecurity/trivy/pkg/fanal/analyzer/config.(*Analyzer).PostAnalyze(0xc001484b60, {0x5597a03cf2c8?, 0xc001d05aa0?}, {{0x5597a030c640?, 0xc0014e63d8?}, {0x9?, 0x0?}})
        github.com/aquasecurity/trivy/pkg/fanal/analyzer/config/config.go:45 +0x4c
github.com/aquasecurity/trivy/pkg/fanal/analyzer.AnalyzerGroup.PostAnalyze({{0xc000fa84c0, 0x3, 0x4}, {0xc001019200, 0x7, 0x8}, 0xc001d0a210}, {0x5597a03cf2c8, 0xc001d05aa0}, 0xc0014be640, ...)
        github.com/aquasecurity/trivy/pkg/fanal/analyzer/analyzer.go:491 +0x2bb
github.com/aquasecurity/trivy/pkg/fanal/artifact/local.Artifact.Inspect({{0x7ffe2266dfdf, 0x1}, {0x7f126eeaddc8, 0xc0020e37a0}, {{{0x0, 0x0, 0x0}, {0xc0014d2100, 0x3, 0x4}}, ...}, ...}, ...)
        github.com/aquasecurity/trivy/pkg/fanal/artifact/local/fs.go:163 +0x4ea
github.com/aquasecurity/trivy/pkg/scanner.Scanner.ScanArtifact({{_, _}, {_, _}}, {_, _}, {{0x0, 0x0, 0x0}, {0xc0020e36c0, ...}, ...})
        github.com/aquasecurity/trivy/pkg/scanner/scan.go:146 +0x103
github.com/aquasecurity/trivy/pkg/commands/artifact.scan({_, _}, {{{0x55979d8ed30d, 0xa}, 0x0, 0x0, 0x1, 0x0, 0x45d964b800, {0xc00231fc20, ...}, ...}, ...}, ...)
        github.com/aquasecurity/trivy/pkg/commands/artifact/run.go:704 +0x3b7
github.com/aquasecurity/trivy/pkg/commands/artifact.(*runner).scanArtifact(_, {_, _}, {{{0x55979d8ed30d, 0xa}, 0x0, 0x0, 0x1, 0x0, 0x45d964b800, ...}, ...}, ...)
        github.com/aquasecurity/trivy/pkg/commands/artifact/run.go:267 +0xd9
github.com/aquasecurity/trivy/pkg/commands/artifact.(*runner).scanFS(_, {_, _}, {{{0x55979d8ed30d, 0xa}, 0x0, 0x0, 0x1, 0x0, 0x45d964b800, ...}, ...})
        github.com/aquasecurity/trivy/pkg/commands/artifact/run.go:215 +0xcb
github.com/aquasecurity/trivy/pkg/commands/artifact.(*runner).ScanFilesystem(_, {_, _}, {{{0x55979d8ed30d, 0xa}, 0x0, 0x0, 0x1, 0x0, 0x45d964b800, ...}, ...})
        github.com/aquasecurity/trivy/pkg/commands/artifact/run.go:195 +0x231
github.com/aquasecurity/trivy/pkg/commands/artifact.Run({_, _}, {{{0x55979d8ed30d, 0xa}, 0x0, 0x0, 0x1, 0x0, 0x45d964b800, {0xc00231fc20, ...}, ...}, ...}, ...)
        github.com/aquasecurity/trivy/pkg/commands/artifact/run.go:428 +0x503
github.com/aquasecurity/trivy/pkg/commands.NewConfigCommand.func2(0xc000ed7800, {0xc002754780, 0x1, 0x2})
        github.com/aquasecurity/trivy/pkg/commands/app.go:683 +0x307
github.com/spf13/cobra.(*Command).execute(0xc000ed7800, {0xc002754760, 0x2, 0x2})
        github.com/spf13/cobra@v1.7.0/command.go:940 +0x862
github.com/spf13/cobra.(*Command).ExecuteC(0xc000ed6300)
        github.com/spf13/cobra@v1.7.0/command.go:1068 +0x3bd
github.com/spf13/cobra.(*Command).Execute(0x55979d952b10?)
        github.com/spf13/cobra@v1.7.0/command.go:992 +0x19
main.run()
        ./main.go:35 +0x1c5
main.main()
        ./main.go:17 +0x19

The code to reproduce the crash:

terraform {
  required_version = "1.6.2"

  backend "local" {}

  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "3.86.0"
    }
    random = {
      source  = "hashicorp/random"
      version = "3.6.0"
    }
  }
}

provider "azurerm" {
  features {}
}

provider "random" {}

locals {
  secrets = {
    my-first-secret  = null
    my-second-secret = "aghj(/)="
    my-third-secret  = random_password.password.result
  }
}

resource "random_password" "password" {
  length = 32
}

resource "azurerm_key_vault" "key_vault" {
  name                = "kv-example"
  location            = "westeurope"
  resource_group_name = "rg-example"
  tenant_id           = "00000000-0000-0000-0000-000000000000"
  sku_name            = "standard"
  #tfsec:ignore:azure-keyvault-no-purge
  purge_protection_enabled        = false
  enabled_for_deployment          = false
  enabled_for_disk_encryption     = false
  enabled_for_template_deployment = false
  soft_delete_retention_days      = 7

  network_acls {
    default_action = "Deny"
    bypass         = "AzureServices"
  }

  lifecycle {
    ignore_changes = [access_policy]
  }
}

#tfsec:ignore:azure-keyvault-content-type-for-secret tfsec:ignore:azure-keyvault-ensure-secret-expiry
resource "azurerm_key_vault_secret" "secrets" {
  for_each = local.secrets

  name         = each.key
  value        = each.value != null ? each.value : "Change me!"
  key_vault_id = azurerm_key_vault.key_vault.id
}

This is the line that causes the crash: my-third-secret = random_password.password.result

nikpivkin commented 9 months ago

@rasmuspfeiffermer What version of Trivy are you using? This bug has been fixed.

rasmuspfeiffermer commented 9 months ago

@nikpivkin I was using version 0.48.0 and just updated to 0.48.3 and the crash is fixed.

simar7 commented 9 months ago

@rasmuspfeiffermer What version of Trivy are you using? This bug has been fixed.

@nikpivkin do you know which PR closed this issue?

nikpivkin commented 9 months ago

@simar7 I was referring to the for-each bug.