Skip to content

Commit

Permalink
Move checking for unmanaged config secrets from the read to the update
Browse files Browse the repository at this point in the history
  • Loading branch information
sergiught committed Mar 1, 2023
1 parent 813398f commit dfa3a7c
Show file tree
Hide file tree
Showing 9 changed files with 925 additions and 645 deletions.
31 changes: 27 additions & 4 deletions internal/auth0/connection/expand.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (
"github.com/auth0/terraform-provider-auth0/internal/value"
)

func expandConnection(d *schema.ResourceData) (*management.Connection, diag.Diagnostics) {
func expandConnection(d *schema.ResourceData, api *management.Management) (*management.Connection, diag.Diagnostics) {
config := d.GetRawConfig()

connection := &management.Connection{
Expand Down Expand Up @@ -40,7 +40,7 @@ func expandConnection(d *schema.ResourceData) (*management.Connection, diag.Diag
config.GetAttr("options").ForEachElement(func(_ cty.Value, options cty.Value) (stop bool) {
switch strategy {
case management.ConnectionStrategyAuth0:
connection.Options, diagnostics = expandConnectionOptionsAuth0(options)
connection.Options, diagnostics = expandConnectionOptionsAuth0(d, options, api)
case management.ConnectionStrategyGoogleOAuth2:
connection.Options, diagnostics = expandConnectionOptionsGoogleOAuth2(d, options)
case management.ConnectionStrategyGoogleApps:
Expand Down Expand Up @@ -140,7 +140,11 @@ func expandConnectionOptionsGitHub(
return options, diag.FromErr(err)
}

func expandConnectionOptionsAuth0(config cty.Value) (*management.ConnectionOptions, diag.Diagnostics) {
func expandConnectionOptionsAuth0(
d *schema.ResourceData,
config cty.Value,
api *management.Management,
) (*management.ConnectionOptions, diag.Diagnostics) {
options := &management.ConnectionOptions{
PasswordPolicy: value.String(config.GetAttr("password_policy")),
NonPersistentAttrs: value.Strings(config.GetAttr("non_persistent_attrs")),
Expand Down Expand Up @@ -270,8 +274,27 @@ func expandConnectionOptionsAuth0(config cty.Value) (*management.ConnectionOptio

var err error
options.UpstreamParams, err = value.MapFromJSON(config.GetAttr("upstream_params"))
if err != nil {
return nil, diag.FromErr(err)
}

return options, diag.FromErr(err)
if !d.IsNewResource() {
apiConn, err := api.Connection.Read(d.Id())
if err != nil {
return nil, diag.FromErr(err)
}

diags := checkForUnmanagedConfigurationSecrets(
options.GetConfiguration(),
apiConn.Options.(*management.ConnectionOptions).GetConfiguration(),
)

if diags.HasError() {
return nil, diags
}
}

return options, nil
}

func expandConnectionOptionsGoogleOAuth2(
Expand Down
64 changes: 64 additions & 0 deletions internal/auth0/connection/expand_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package connection

import (
"testing"

"github.com/hashicorp/go-cty/cty"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/stretchr/testify/assert"
)

func TestCheckForUnmanagedConfigurationSecrets(t *testing.T) {
var testCases = []struct {
name string
givenConfigFromTF map[string]string
givenConfigFromAPI map[string]string
expectedDiagnostics diag.Diagnostics
}{
{
name: "custom database has no configuration",
givenConfigFromTF: map[string]string{},
givenConfigFromAPI: map[string]string{},
expectedDiagnostics: diag.Diagnostics(nil),
},
{
name: "custom database has no unmanaged configuration",
givenConfigFromTF: map[string]string{
"foo": "bar",
},
givenConfigFromAPI: map[string]string{
"foo": "bar",
},
expectedDiagnostics: diag.Diagnostics(nil),
},
{
name: "custom database has unmanaged configuration",
givenConfigFromTF: map[string]string{
"foo": "bar",
},
givenConfigFromAPI: map[string]string{
"foo": "bar",
"anotherFoo": "anotherBar",
},
expectedDiagnostics: diag.Diagnostics{
diag.Diagnostic{
Severity: diag.Error,
Summary: "Unmanaged Configuration Secret",
Detail: "Detected a configuration secret not managed through terraform: \"anotherFoo\". If you proceed, this configuration secret will get deleted. It is required to add this configuration secret to your custom database settings to prevent unintentionally destructive results.",
AttributePath: cty.Path{cty.GetAttrStep{Name: "options.configuration"}},
},
},
},
}

for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
actualDiagnostics := checkForUnmanagedConfigurationSecrets(
testCase.givenConfigFromTF,
testCase.givenConfigFromAPI,
)

assert.Equal(t, testCase.expectedDiagnostics, actualDiagnostics)
})
}
}
11 changes: 3 additions & 8 deletions internal/auth0/connection/flatten.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,24 +150,19 @@ func flattenConnectionOptionsAuth0(
}
m["upstream_params"] = upstreamParams

diags := checkForUnmanagedConfigurationSecrets(
dbSecretConfig.(map[string]interface{}),
options.GetConfiguration(),
)

return m, diags
return m, nil
}

// checkForUnmanagedConfigurationSecrets is used to assess keys diff because values are sent back encrypted.
func checkForUnmanagedConfigurationSecrets(configFromTF map[string]interface{}, configFromAPI map[string]string) diag.Diagnostics {
func checkForUnmanagedConfigurationSecrets(configFromTF, configFromAPI map[string]string) diag.Diagnostics {
var warnings diag.Diagnostics

for key := range configFromAPI {
if _, ok := configFromTF[key]; !ok {
warnings = append(warnings, diag.Diagnostic{
Severity: diag.Error,
Summary: "Unmanaged Configuration Secret",
Detail: fmt.Sprintf("Detected a configuration secret not managed though terraform: %q. "+
Detail: fmt.Sprintf("Detected a configuration secret not managed through terraform: %q. "+
"If you proceed, this configuration secret will get deleted. It is required to "+
"add this configuration secret to your custom database settings to "+
"prevent unintentionally destructive results.",
Expand Down
57 changes: 0 additions & 57 deletions internal/auth0/connection/flatten_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@ import (
"testing"

"github.com/auth0/go-auth0/management"
"github.com/hashicorp/go-cty/cty"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/stretchr/testify/assert"
)

func TestFlattenConnectionOptions(t *testing.T) {
Expand Down Expand Up @@ -52,58 +50,3 @@ func TestFlattenConnectionOptionsEmail(t *testing.T) {
t.Errorf("Expected no diagnostic warnings, got %v", diags)
}
}

func TestCheckForUnmanagedConfigurationSecrets(t *testing.T) {
var testCases = []struct {
name string
givenConfigFromTF map[string]interface{}
givenConfigFromAPI map[string]string
expectedDiagnostics diag.Diagnostics
}{
{
name: "custom database has no configuration",
givenConfigFromTF: map[string]interface{}{},
givenConfigFromAPI: map[string]string{},
expectedDiagnostics: diag.Diagnostics(nil),
},
{
name: "custom database has no unmanaged configuration",
givenConfigFromTF: map[string]interface{}{
"foo": "bar",
},
givenConfigFromAPI: map[string]string{
"foo": "bar",
},
expectedDiagnostics: diag.Diagnostics(nil),
},
{
name: "custom database has unmanaged configuration",
givenConfigFromTF: map[string]interface{}{
"foo": "bar",
},
givenConfigFromAPI: map[string]string{
"foo": "bar",
"anotherFoo": "anotherBar",
},
expectedDiagnostics: diag.Diagnostics{
diag.Diagnostic{
Severity: diag.Error,
Summary: "Unmanaged Configuration Secret",
Detail: "Detected a configuration secret not managed though terraform: \"anotherFoo\". If you proceed, this configuration secret will get deleted. It is required to add this configuration secret to your custom database settings to prevent unintentionally destructive results.",
AttributePath: cty.Path{cty.GetAttrStep{Name: "options.configuration"}},
},
},
},
}

for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
actualDiagnostics := checkForUnmanagedConfigurationSecrets(
testCase.givenConfigFromTF,
testCase.givenConfigFromAPI,
)

assert.Equal(t, testCase.expectedDiagnostics, actualDiagnostics)
})
}
}
4 changes: 2 additions & 2 deletions internal/auth0/connection/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ func NewResource() *schema.Resource {
func createConnection(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
api := m.(*management.Management)

connection, diagnostics := expandConnection(d)
connection, diagnostics := expandConnection(d, api)
if diagnostics.HasError() {
return diagnostics
}
Expand Down Expand Up @@ -105,7 +105,7 @@ func readConnection(ctx context.Context, d *schema.ResourceData, m interface{})
func updateConnection(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
api := m.(*management.Management)

connection, diagnostics := expandConnection(d)
connection, diagnostics := expandConnection(d, api)
if diagnostics.HasError() {
return diagnostics
}
Expand Down
37 changes: 37 additions & 0 deletions internal/auth0/connection/resource_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package connection_test

import (
"fmt"
"os"
"regexp"
"testing"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
Expand Down Expand Up @@ -1416,6 +1418,41 @@ func TestAccConnectionConfiguration(t *testing.T) {
})
}

func TestAccConnectionConfigurationFailsToUpdateWhenEncounteringUnmanagedSecrets(t *testing.T) {
if os.Getenv("AUTH0_DOMAIN") != acctest.RecordingsDomain {
t.Skip()
}

acctest.Test(t, resource.TestCase{
Steps: []resource.TestStep{
{
Config: `
resource "auth0_connection" "my_connection" {
name = "Unmanaged-Secrets"
strategy = "auth0"
}`,
ResourceName: "auth0_connection.my_connection",
ImportState: true,
ImportStateId: "con_8yq21qxhWtFQi0aM",
ImportStatePersist: true,
},
{
Config: `
resource "auth0_connection" "my_connection" {
name = "Unmanaged-Secrets"
strategy = "auth0"
options {
configuration = {
foo = "xxx"
}
}
}`,
ExpectError: regexp.MustCompile("Detected a configuration secret not managed through terraform"),
},
},
})
}

const testAccConnectionConfigurationCreate = `
resource "auth0_connection" "my_connection" {
name = "Acceptance-Test-Connection-{{.testName}}"
Expand Down
Loading

0 comments on commit dfa3a7c

Please sign in to comment.