From ffe24e18dc3dca816ec9ce5ccf66d5d7b5ea70d6 Mon Sep 17 00:00:00 2001 From: Nikita Pivkin Date: Fri, 6 Dec 2024 08:06:26 +0600 Subject: [PATCH] feat(misconf): generate placeholders for random provider resources (#8051) Signed-off-by: nikpivkin --- pkg/iac/scanners/terraform/scanner_test.go | 44 ++++++++++++++++++++++ pkg/iac/terraform/presets.go | 24 ++++++++++-- 2 files changed, 64 insertions(+), 4 deletions(-) diff --git a/pkg/iac/scanners/terraform/scanner_test.go b/pkg/iac/scanners/terraform/scanner_test.go index 215ec796b45d..286a6920ce93 100644 --- a/pkg/iac/scanners/terraform/scanner_test.go +++ b/pkg/iac/scanners/terraform/scanner_test.go @@ -6,6 +6,7 @@ import ( "strconv" "strings" "testing" + "testing/fstest" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -951,3 +952,46 @@ resource "aws_s3_bucket" "test" {} assert.Len(t, results, 2) }) } + +func TestUseRandomProvider(t *testing.T) { + fsys := fstest.MapFS{ + "main.tf": &fstest.MapFile{Data: []byte(`resource "random_id" "suffix" {} + +locals { + bucket = "test-${random_id.suffix.hex}" +} + +resource "aws_s3_bucket" "test" { + bucket = local.bucket +} + +resource "aws_s3_bucket_versioning" "test" { + bucket = local.bucket + versioning_configuration { + status = "Enabled" + } +} +`)}, + } + + check := `package test +import rego.v1 + +deny contains res if { + some bucket in input.aws.s3.buckets + bucket.versioning.enabled.value + res := result.new("Bucket versioning is enabled", bucket) +} +` + + scanner := New( + ScannerWithAllDirectories(true), + rego.WithPolicyReader(strings.NewReader(check)), + rego.WithPolicyNamespaces("test"), + ) + + results, err := scanner.ScanFS(context.TODO(), fsys, ".") + require.NoError(t, err) + + assert.Len(t, results.GetFailed(), 1) +} diff --git a/pkg/iac/terraform/presets.go b/pkg/iac/terraform/presets.go index b29a5fc9c181..61ac78bccd2e 100644 --- a/pkg/iac/terraform/presets.go +++ b/pkg/iac/terraform/presets.go @@ -2,12 +2,23 @@ package terraform import ( "fmt" + "math/rand/v2" "strings" "github.com/google/uuid" "github.com/zclconf/go-cty/cty" ) +var resourceRandomAttributes = map[string][]string{ + // If the user leaves the name blank, Terraform will automatically generate a unique name + "aws_launch_template": {"name"}, + "random_id": {"hex", "dec", "b64_url", "b64_std"}, + "random_password": {"result", "bcrypt_hash"}, + "random_string": {"result"}, + "random_bytes": {"base64", "hex"}, + "random_uuid": {"result"}, +} + func createPresetValues(b *Block) map[string]cty.Value { presets := make(map[string]cty.Value) @@ -23,16 +34,21 @@ func createPresetValues(b *Block) map[string]cty.Value { // workaround for weird iam feature case "aws_iam_policy_document": presets["json"] = cty.StringVal(b.ID()) - // If the user leaves the name blank, Terraform will automatically generate a unique name - case "aws_launch_template": - presets["name"] = cty.StringVal(uuid.New().String()) // allow referencing the current region name case "aws_region": presets["name"] = cty.StringVal("current-region") + case "random_integer": + //nolint:gosec + presets["result"] = cty.NumberIntVal(rand.Int64()) } - return presets + if attrs, exists := resourceRandomAttributes[b.TypeLabel()]; exists { + for _, attr := range attrs { + presets[attr] = cty.StringVal(uuid.New().String()) + } + } + return presets } func postProcessValues(b *Block, input map[string]cty.Value) map[string]cty.Value {