diff --git a/pkg/iac-providers/tfplan/v1/load-file.go b/pkg/iac-providers/tfplan/v1/load-file.go index 004172633..5b61cd8cd 100644 --- a/pkg/iac-providers/tfplan/v1/load-file.go +++ b/pkg/iac-providers/tfplan/v1/load-file.go @@ -20,22 +20,24 @@ import ( "encoding/json" "fmt" "io/ioutil" + "strings" "github.com/accurics/terrascan/pkg/iac-providers/output" "github.com/accurics/terrascan/pkg/utils" "go.uber.org/zap" ) -const ( - jqQuery = `[.planned_values.root_module | .. | select(.type? != null and .address? != null and .mode? == "managed") | {id: .address?, type: .type?, name: .name?, config: .values?, source: ""}]` - tfPlanFormatVersion = "0.1" -) +const jqQuery = `[.planned_values.root_module | .. | select(.type? != null and .address? != null and .mode? == "managed") | {id: .address?, type: .type?, name: .name?, config: .values?, source: ""}]` var ( - errIncorrectFormatVersion = fmt.Errorf("terraform format version shoule be '%s'", tfPlanFormatVersion) + errIncorrectFormatVersion = fmt.Errorf("terraform format version shoule be one of '%s'", strings.Join(getTfPlanFormatVersions(), ", ")) errEmptyTerraformVersion = fmt.Errorf("terraform version cannot be empty in tfplan json") ) +func getTfPlanFormatVersions() []string { + return []string{"0.1", "0.2"} +} + // LoadIacFile parses the given tfplan file from the given file path func (t *TFPlan) LoadIacFile(absFilePath string, options map[string]interface{}) (allResourcesConfig output.AllResourceConfigs, err error) { @@ -93,7 +95,7 @@ func (t *TFPlan) isValidTFPlanJSON(tfjson []byte) error { } // check format version - if t.FormatVersion != tfPlanFormatVersion { + if !isValidVersion(t.FormatVersion) { return errIncorrectFormatVersion } @@ -104,3 +106,12 @@ func (t *TFPlan) isValidTFPlanJSON(tfjson []byte) error { return nil } + +func isValidVersion(v string) bool { + for _, x := range getTfPlanFormatVersions() { + if x == v { + return true + } + } + return false +} diff --git a/pkg/iac-providers/tfplan/v1/load-file_test.go b/pkg/iac-providers/tfplan/v1/load-file_test.go index 43d109293..8625065ed 100644 --- a/pkg/iac-providers/tfplan/v1/load-file_test.go +++ b/pkg/iac-providers/tfplan/v1/load-file_test.go @@ -59,7 +59,7 @@ func TestLoadIacFile(t *testing.T) { name: "invalid tfplan json", filePath: filepath.Join("testdata", "invalid-tfplan.json"), tfplan: TFPlan{}, - wantErr: fmt.Errorf("invalid terraform json file; error: 'terraform format version shoule be '0.1''"), + wantErr: fmt.Errorf("invalid terraform json file; error: 'terraform format version shoule be one of '0.1, 0.2''"), }, { name: "valid tfplan json", @@ -67,6 +67,12 @@ func TestLoadIacFile(t *testing.T) { tfplan: TFPlan{}, wantErr: nil, }, + { + name: "valid tfplan v0.2 json", + filePath: filepath.Join("testdata", "valid-tfplan-0.2.json"), + tfplan: TFPlan{}, + wantErr: nil, + }, } for _, tt := range table { diff --git a/pkg/iac-providers/tfplan/v1/testdata/valid-tfplan-0.2.json b/pkg/iac-providers/tfplan/v1/testdata/valid-tfplan-0.2.json new file mode 100644 index 000000000..d4f19718a --- /dev/null +++ b/pkg/iac-providers/tfplan/v1/testdata/valid-tfplan-0.2.json @@ -0,0 +1 @@ +{"format_version":"0.2","terraform_version":"1.0.9","variables":{"s3_bucket_prefix":{"value":"sample_prefix_test20"}},"planned_values":{"root_module":{"resources":[{"address":"aws_s3_bucket.demo-example","mode":"managed","type":"aws_s3_bucket","name":"demo-example","provider_name":"registry.terraform.io/hashicorp/aws","schema_version":0,"values":{"acl":"private","bucket":"demoexample-1","bucket_prefix":null,"cors_rule":[],"force_destroy":false,"grant":[],"lifecycle_rule":[],"logging":[],"object_lock_configuration":[],"policy":null,"replication_configuration":[],"server_side_encryption_configuration":[],"tags":null,"versioning":[{"enabled":false,"mfa_delete":false}],"website":[]},"sensitive_values":{"cors_rule":[],"grant":[],"lifecycle_rule":[],"logging":[],"object_lock_configuration":[],"replication_configuration":[],"server_side_encryption_configuration":[],"tags_all":{},"versioning":[{}],"website":[]}},{"address":"aws_s3_bucket.demo-s3","mode":"managed","type":"aws_s3_bucket","name":"demo-s3","provider_name":"registry.terraform.io/hashicorp/aws","schema_version":0,"values":{"acl":"private","bucket":"sample_prefix_test20","bucket_prefix":null,"cors_rule":[],"force_destroy":false,"grant":[],"lifecycle_rule":[],"logging":[],"object_lock_configuration":[],"policy":null,"replication_configuration":[],"server_side_encryption_configuration":[],"tags":null,"versioning":[{"enabled":false,"mfa_delete":false}],"website":[]},"sensitive_values":{"cors_rule":[],"grant":[],"lifecycle_rule":[],"logging":[],"object_lock_configuration":[],"replication_configuration":[],"server_side_encryption_configuration":[],"tags_all":{},"versioning":[{}],"website":[]}}]}},"resource_changes":[{"address":"aws_s3_bucket.demo-example","mode":"managed","type":"aws_s3_bucket","name":"demo-example","provider_name":"registry.terraform.io/hashicorp/aws","change":{"actions":["create"],"before":null,"after":{"acl":"private","bucket":"demoexample-1","bucket_prefix":null,"cors_rule":[],"force_destroy":false,"grant":[],"lifecycle_rule":[],"logging":[],"object_lock_configuration":[],"policy":null,"replication_configuration":[],"server_side_encryption_configuration":[],"tags":null,"versioning":[{"enabled":false,"mfa_delete":false}],"website":[]},"after_unknown":{"acceleration_status":true,"arn":true,"bucket_domain_name":true,"bucket_regional_domain_name":true,"cors_rule":[],"grant":[],"hosted_zone_id":true,"id":true,"lifecycle_rule":[],"logging":[],"object_lock_configuration":[],"region":true,"replication_configuration":[],"request_payer":true,"server_side_encryption_configuration":[],"tags_all":true,"versioning":[{}],"website":[],"website_domain":true,"website_endpoint":true},"before_sensitive":false,"after_sensitive":{"cors_rule":[],"grant":[],"lifecycle_rule":[],"logging":[],"object_lock_configuration":[],"replication_configuration":[],"server_side_encryption_configuration":[],"tags_all":{},"versioning":[{}],"website":[]}}},{"address":"aws_s3_bucket.demo-s3","mode":"managed","type":"aws_s3_bucket","name":"demo-s3","provider_name":"registry.terraform.io/hashicorp/aws","change":{"actions":["create"],"before":null,"after":{"acl":"private","bucket":"sample_prefix_test20","bucket_prefix":null,"cors_rule":[],"force_destroy":false,"grant":[],"lifecycle_rule":[],"logging":[],"object_lock_configuration":[],"policy":null,"replication_configuration":[],"server_side_encryption_configuration":[],"tags":null,"versioning":[{"enabled":false,"mfa_delete":false}],"website":[]},"after_unknown":{"acceleration_status":true,"arn":true,"bucket_domain_name":true,"bucket_regional_domain_name":true,"cors_rule":[],"grant":[],"hosted_zone_id":true,"id":true,"lifecycle_rule":[],"logging":[],"object_lock_configuration":[],"region":true,"replication_configuration":[],"request_payer":true,"server_side_encryption_configuration":[],"tags_all":true,"versioning":[{}],"website":[],"website_domain":true,"website_endpoint":true},"before_sensitive":false,"after_sensitive":{"cors_rule":[],"grant":[],"lifecycle_rule":[],"logging":[],"object_lock_configuration":[],"replication_configuration":[],"server_side_encryption_configuration":[],"tags_all":{},"versioning":[{}],"website":[]}}}],"configuration":{"provider_config":{"aws":{"name":"aws","expressions":{"region":{"constant_value":"us-east-1"}}}},"root_module":{"resources":[{"address":"aws_s3_bucket.demo-example","mode":"managed","type":"aws_s3_bucket","name":"demo-example","provider_config_key":"aws","expressions":{"bucket":{"constant_value":"demoexample-1"},"versioning":[{"enabled":{"constant_value":false},"mfa_delete":{"constant_value":false}}]},"schema_version":0},{"address":"aws_s3_bucket.demo-s3","mode":"managed","type":"aws_s3_bucket","name":"demo-s3","provider_config_key":"aws","expressions":{"bucket":{"references":["var.s3_bucket_prefix"]},"versioning":[{"enabled":{"constant_value":false},"mfa_delete":{"constant_value":false}}]},"schema_version":0}],"variables":{"s3_bucket_prefix":{"default":"sample_prefix_test20"}}}}}