diff --git a/docs/resources/action.md b/docs/resources/action.md index 7189bb44..8deab2dc 100644 --- a/docs/resources/action.md +++ b/docs/resources/action.md @@ -68,7 +68,7 @@ resource "auth0_action" "my_action" { - `dependencies` (Block Set) List of third party npm modules, and their versions, that this action depends on. (see [below for nested schema](#nestedblock--dependencies)) - `deploy` (Boolean) Deploying an action will create a new immutable version of the action. If the action is currently bound to a trigger, then the system will begin executing the newly deployed version of the action immediately. - `runtime` (String) The Node runtime. Defaults to `node18`. Possible values are: `node16` (not recommended), or `node18` (recommended). -- `secrets` (Block List) List of secrets that are included in an action or a version of an action. Partial management of secrets is not supported. (see [below for nested schema](#nestedblock--secrets)) +- `secrets` (Block Set) List of secrets that are included in an action or a version of an action. Partial management of secrets is not supported. (see [below for nested schema](#nestedblock--secrets)) ### Read-Only diff --git a/internal/auth0/action/expand.go b/internal/auth0/action/expand.go index 82181588..5cacfece 100644 --- a/internal/auth0/action/expand.go +++ b/internal/auth0/action/expand.go @@ -113,12 +113,22 @@ func preventErasingUnmanagedSecrets(ctx context.Context, data *schema.ResourceDa return diag.FromErr(internalError.HandleAPIError(data, err)) } - // We need to also include the secrets that we're about to remove - // against the checks, not just the ones with which we are left. + // Extract changes to secrets from the resource data. oldSecrets, newSecrets := data.GetChange("secrets") - allSecrets := append(oldSecrets.([]interface{}), newSecrets.([]interface{})...) - return checkForUnmanagedActionSecrets(allSecrets, preUpdateAction.GetSecrets()) + // Stores the old and secrets from *schema.Set to slices of interface{}. + var secretsList []interface{} + + if oldSecrets != nil { + secretsList = append(secretsList, oldSecrets.(*schema.Set).List()...) + } + + if newSecrets != nil { + secretsList = append(secretsList, newSecrets.(*schema.Set).List()...) + } + + // Pass allSecrets to check for unmanaged action secrets. + return checkForUnmanagedActionSecrets(secretsList, preUpdateAction.GetSecrets()) } func checkForUnmanagedActionSecrets( @@ -127,7 +137,30 @@ func checkForUnmanagedActionSecrets( ) diag.Diagnostics { secretKeysInConfigMap := make(map[string]bool, len(secretsFromConfig)) for _, secret := range secretsFromConfig { - secretKeyName := secret.(map[string]interface{})["name"].(string) + // Check if the element can be asserted as a map. + secretMap, ok := secret.(map[string]interface{}) + if !ok { + return diag.Diagnostics{ + diag.Diagnostic{ + Severity: diag.Error, + Summary: "Invalid Configuration Format", + Detail: "Secrets configuration contains improperly formatted elements. Each secret must be a map with 'name' and 'value'.", + }, + } + } + + // Safely extract the "name" field from the secret map. + secretKeyName, nameOk := secretMap["name"].(string) + if !nameOk || secretKeyName == "" { + return diag.Diagnostics{ + diag.Diagnostic{ + Severity: diag.Error, + Summary: "Invalid Secret Name", + Detail: "Each secret in the configuration must have a valid 'name' as a string.", + }, + } + } + secretKeysInConfigMap[secretKeyName] = true } diff --git a/internal/auth0/action/resource.go b/internal/auth0/action/resource.go index c0fe29f3..60be2188 100644 --- a/internal/auth0/action/resource.go +++ b/internal/auth0/action/resource.go @@ -93,7 +93,7 @@ func NewResource() *schema.Resource { Description: "The Node runtime. Defaults to `node18`. Possible values are: `node16` (not recommended), or `node18` (recommended).", }, "secrets": { - Type: schema.TypeList, + Type: schema.TypeSet, Optional: true, Description: "List of secrets that are included in an action or a version of an action. Partial management of secrets is not supported.", Elem: &schema.Resource{ diff --git a/internal/auth0/action/resource_test.go b/internal/auth0/action/resource_test.go index a21c4fac..d705fb80 100644 --- a/internal/auth0/action/resource_test.go +++ b/internal/auth0/action/resource_test.go @@ -182,10 +182,10 @@ func TestAccAction(t *testing.T) { resource.TestCheckResourceAttr("auth0_action.my_action", "dependencies.1.name", "moment"), resource.TestCheckResourceAttr("auth0_action.my_action", "dependencies.1.version", "2.29.4"), resource.TestCheckResourceAttr("auth0_action.my_action", "secrets.#", "2"), - resource.TestCheckResourceAttr("auth0_action.my_action", "secrets.0.name", "foo"), - resource.TestCheckResourceAttr("auth0_action.my_action", "secrets.0.value", "123456"), - resource.TestCheckResourceAttr("auth0_action.my_action", "secrets.1.name", "bar"), - resource.TestCheckResourceAttr("auth0_action.my_action", "secrets.1.value", "654321"), + resource.TestCheckResourceAttr("auth0_action.my_action", "secrets.0.name", "bar"), + resource.TestCheckResourceAttr("auth0_action.my_action", "secrets.0.value", "654321"), + resource.TestCheckResourceAttr("auth0_action.my_action", "secrets.1.name", "foo"), + resource.TestCheckResourceAttr("auth0_action.my_action", "secrets.1.value", "123456"), ), }, {