From d0287a24cead63631cefd2c660034b13a4e18f9d Mon Sep 17 00:00:00 2001 From: teowa <104055472+teowa@users.noreply.github.com> Date: Thu, 7 Mar 2024 17:27:30 +0800 Subject: [PATCH] fix cred scan --- commands/credential_scan.go | 138 +++++++++++++++++++----------------- hcl/parse.go | 24 +++++-- hcl/testdata/test2.tf | 32 +++++++++ 3 files changed, 122 insertions(+), 72 deletions(-) create mode 100644 hcl/testdata/test2.tf diff --git a/commands/credential_scan.go b/commands/credential_scan.go index dd6bbe1..4ae647a 100644 --- a/commands/credential_scan.go +++ b/commands/credential_scan.go @@ -270,10 +270,10 @@ func (c CredentialScanCommand) Execute() int { logrus.Infof("find secrets for azapi_resource.%s(%s): %+v", azapiResource.Name, azapiResource.Type, secrets) for k, v := range secrets { - if !strings.HasPrefix(v, "$var.") { + if !strings.HasPrefix(v, "$") || strings.HasPrefix(v, "$local.") { credScanErr := makeCredScanError( azapiResource, - "must use variable for secret field", + "cannot use plain text or 'local' for secret, use 'variable' instead", k, ) credScanErrors = append(credScanErrors, credScanErr) @@ -282,39 +282,41 @@ func (c CredentialScanCommand) Execute() int { continue } - varName := strings.TrimPrefix(v, "$var.") - varName = strings.Split(varName, ".")[0] - theVar, ok := vars[varName] - if !ok { - credScanErr := makeCredScanError( - azapiResource, - fmt.Sprintf("variable %q was not found", varName), - k, - ) - credScanErrors = append(credScanErrors, credScanErr) - logrus.Error(credScanErr) - - continue - } - - if theVar.HasDefault { - credScanErr := makeCredScanError( - azapiResource, - fmt.Sprintf("variable %q (%v:%v) used in secret field but has a default value, please remove the default value", varName, theVar.FileName, theVar.LineNumber), - k, - ) - credScanErrors = append(credScanErrors, credScanErr) - logrus.Error(credScanErr) - } - - if !theVar.IsSensitive { - credScanErr := makeCredScanError( - azapiResource, - fmt.Sprintf("variable %q (%v:%v) used in secret field but is not marked as sensitive, please add \"sensitive=true\" for the variable", varName, theVar.FileName, theVar.LineNumber), - k, - ) - credScanErrors = append(credScanErrors, credScanErr) - logrus.Error(credScanErr) + if strings.HasPrefix(v, "$var.") { + varName := strings.TrimPrefix(v, "$var.") + varName = strings.Split(varName, ".")[0] + theVar, ok := vars[varName] + if !ok { + credScanErr := makeCredScanError( + azapiResource, + fmt.Sprintf("variable %q was not found", varName), + k, + ) + credScanErrors = append(credScanErrors, credScanErr) + logrus.Error(credScanErr) + + continue + } + + if theVar.HasDefault { + credScanErr := makeCredScanError( + azapiResource, + fmt.Sprintf("variable %q (%v:%v) used in secret field but has a default value, please remove the default value", varName, theVar.FileName, theVar.LineNumber), + k, + ) + credScanErrors = append(credScanErrors, credScanErr) + logrus.Error(credScanErr) + } + + if !theVar.IsSensitive { + credScanErr := makeCredScanError( + azapiResource, + fmt.Sprintf("variable %q (%v:%v) used in secret field but is not marked as sensitive, please add \"sensitive=true\" for the variable", varName, theVar.FileName, theVar.LineNumber), + k, + ) + credScanErrors = append(credScanErrors, credScanErr) + logrus.Error(credScanErr) + } } } } @@ -413,10 +415,10 @@ func storeCredScanErrors(wd string, credScanErrors []CredScanError) { func checkAzureProviderSecret(azureProvider hcl.AzureProvider, propertyName, propertyValue string, vars map[string]hcl.Variable) []CredScanError { credScanErrors := make([]CredScanError, 0) - if !strings.HasPrefix(propertyValue, "$var.") { + if !strings.HasPrefix(propertyValue, "$") || strings.HasPrefix(propertyValue, "$local.") { credScanErr := makeCredScanErrorForProvider( azureProvider, - "must use variable for secret field", + "cannot use plain text or 'local' for secret, use 'variable' instead", propertyName, ) credScanErrors = append(credScanErrors, credScanErr) @@ -425,39 +427,41 @@ func checkAzureProviderSecret(azureProvider hcl.AzureProvider, propertyName, pro return credScanErrors } - varName := strings.TrimPrefix(propertyValue, "$var.") - varName = strings.Split(varName, ".")[0] - theVar, ok := vars[varName] - if !ok { - credScanErr := makeCredScanErrorForProvider( - azureProvider, - fmt.Sprintf("variable %q was not found", varName), - propertyName, - ) - credScanErrors = append(credScanErrors, credScanErr) - logrus.Error(credScanErr) + if strings.HasPrefix(propertyValue, "$var.") { + varName := strings.TrimPrefix(propertyValue, "$var.") + varName = strings.Split(varName, ".")[0] + theVar, ok := vars[varName] + if !ok { + credScanErr := makeCredScanErrorForProvider( + azureProvider, + fmt.Sprintf("variable %q was not found", varName), + propertyName, + ) + credScanErrors = append(credScanErrors, credScanErr) + logrus.Error(credScanErr) - return credScanErrors - } + return credScanErrors + } - if theVar.HasDefault { - credScanErr := makeCredScanErrorForProvider( - azureProvider, - fmt.Sprintf("variable %q (%v:%v) used in secret field but has a default value, please remove the default value", varName, theVar.FileName, theVar.LineNumber), - propertyName, - ) - credScanErrors = append(credScanErrors, credScanErr) - logrus.Error(credScanErr) - } + if theVar.HasDefault { + credScanErr := makeCredScanErrorForProvider( + azureProvider, + fmt.Sprintf("variable %q (%v:%v) used in secret field but has a default value, please remove the default value", varName, theVar.FileName, theVar.LineNumber), + propertyName, + ) + credScanErrors = append(credScanErrors, credScanErr) + logrus.Error(credScanErr) + } - if !theVar.IsSensitive { - credScanErr := makeCredScanErrorForProvider( - azureProvider, - fmt.Sprintf("variable %q (%v:%v) used in secret field but is not marked as sensitive, please add \"sensitive=true\" for the variable", varName, theVar.FileName, theVar.LineNumber), - propertyName, - ) - credScanErrors = append(credScanErrors, credScanErr) - logrus.Error(credScanErr) + if !theVar.IsSensitive { + credScanErr := makeCredScanErrorForProvider( + azureProvider, + fmt.Sprintf("variable %q (%v:%v) used in secret field but is not marked as sensitive, please add \"sensitive=true\" for the variable", varName, theVar.FileName, theVar.LineNumber), + propertyName, + ) + credScanErrors = append(credScanErrors, credScanErr) + logrus.Error(credScanErr) + } } return credScanErrors diff --git a/hcl/parse.go b/hcl/parse.go index dce9de8..537c1ed 100644 --- a/hcl/parse.go +++ b/hcl/parse.go @@ -107,14 +107,28 @@ type Variable struct { func mockVariables(traversals []hcl.Traversal) map[string]cty.Value { const variablePrefix = "$" - ret := make(map[string]cty.Value) + result := make(map[string]cty.Value) for _, traversal := range traversals { - for k, v := range mockVariable(traversal, 0, variablePrefix) { - ret[k] = v - } + mockedVariable := mockVariable(traversal, 0, variablePrefix) + result = mergeKeys(result, mockedVariable) } - return ret + return result +} + +func mergeKeys(left, right map[string]cty.Value) map[string]cty.Value { + for key, rightVal := range right { + if leftVal, present := left[key]; present { + if leftVal.Type().IsObjectType() && rightVal.Type().IsObjectType() { + left[key] = cty.ObjectVal(mergeKeys(leftVal.AsValueMap(), rightVal.AsValueMap())) + } else { + left[key] = rightVal + } + } else { + left[key] = rightVal + } + } + return left } // one hcl.Traversal corresponds to one reference diff --git a/hcl/testdata/test2.tf b/hcl/testdata/test2.tf new file mode 100644 index 0000000..3325455 --- /dev/null +++ b/hcl/testdata/test2.tf @@ -0,0 +1,32 @@ +resource "azurerm_resource_group" "test" { + name = "acctest-rg" + location = "East US" +} + +resource "azurerm_storage_account" "test" { + name = "acctestsa37" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + account_tier = "Standard" + account_replication_type = "GRS" +} + +resource "azurerm_spring_cloud_service" "test" { + name = "acctest-sc-37" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name +} + +resource "azapi_resource" "test" { + type = "Microsoft.AppPlatform/spring/storages@2024-01-01-preview" + name = "acctest-ss-37" + parent_id = azurerm_spring_cloud_service.test.id + + body = jsonencode({ + properties = { + accountKey = azurerm_storage_account.test.primary_access_key + accountName = azurerm_storage_account.test.name + storageType = "StorageAccount" + } + }) +}