Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pass-through un-configurable options for enterprise connections #802

Merged
merged 2 commits into from
Aug 31, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ go 1.21

require (
github.com/PuerkitoBio/rehttp v1.2.0
github.com/auth0/go-auth0 v1.0.1
github.com/auth0/go-auth0 v1.0.2
github.com/google/go-cmp v0.5.9
github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320
github.com/hashicorp/go-multierror v1.1.1
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkE
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/armon/go-radix v1.0.0 h1:F4z6KzEeeQIMeLFa97iZU6vupzoecKdU5TX24SNppXI=
github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/auth0/go-auth0 v1.0.1 h1:sMn0GutnNlB5XOg82MZeWwWQ39WJ/F7BUSCpYmfDSXQ=
github.com/auth0/go-auth0 v1.0.1/go.mod h1:C1pQxs66t2TtHsV5B+UxyDveWCWbAlgxQIG4syIPEMg=
github.com/auth0/go-auth0 v1.0.2 h1:kmno85ry9oYIj+Fob0m2E0oSinnPgn3piY+VXM5GIco=
github.com/auth0/go-auth0 v1.0.2/go.mod h1:C1pQxs66t2TtHsV5B+UxyDveWCWbAlgxQIG4syIPEMg=
github.com/aybabtme/iocontrol v0.0.0-20150809002002-ad15bcfc95a0 h1:0NmehRCgyk5rljDQLKUO+cRJCnduDyn11+zGZIc9Z48=
github.com/aybabtme/iocontrol v0.0.0-20150809002002-ad15bcfc95a0/go.mod h1:6L7zgvqo0idzI7IO8de6ZC051AfXb5ipkIJ7bIA2tGA=
github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
Expand Down
208 changes: 205 additions & 3 deletions internal/auth0/connection/expand.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,12 +84,19 @@ func expandConnection(
connection.Realms = value.Strings(config.GetAttr("realms"))
}

var diagnostics diag.Diagnostics
connection.Options, diagnostics = expandConnectionOptions(data, strategy)

if connectionIsEnterprise(strategy) {
connection.ShowAsButton = value.Bool(config.GetAttr("show_as_button"))
}

var diagnostics diag.Diagnostics
connection.Options, diagnostics = expandConnectionOptions(data, strategy)
if !data.IsNewResource() {
err := passThroughUnconfigurableConnectionOptions(ctx, api, data.Id(), strategy, connection)
if err != nil {
return nil, diag.FromErr(err)
}
}
}

// Prevent erasing database configuration secrets.
if !data.IsNewResource() && strategy == management.ConnectionStrategyAuth0 {
Expand Down Expand Up @@ -773,3 +780,198 @@ func expandConnectionOptionsScopes(data *schema.ResourceData, options scoper) {
options.SetScopes(true, scope.(string))
}
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# passThroughUnconfigurableConnectionOptions maintains crucial connection options by forwarding them from the current options to the PATCH payload
# This is necessary because the /api/v2/connections/{id}, endpoint does not follow usual
# PATCH behavior, the 'options' property is entirely replaced by the payload object.

Or something similar.

// passThroughUnconfigurableConnectionOptions ensures that read-only connection options
// set by external services do not get removed from the connection resource.
//
// This is necessary because the "/api/v2/connections/{id}" endpoint does not follow usual
// PATCH behavior, the 'options' property is entirely replaced by the payload object.
func passThroughUnconfigurableConnectionOptions(
ctx context.Context,
api *management.Management,
connectionID string,
strategy string,
connection *management.Connection,
) error {
var err error

switch strategy {
case management.ConnectionStrategyAD:
err = passThroughUnconfigurableConnectionOptionsAD(ctx, api, connectionID, connection)
case management.ConnectionStrategyAzureAD:
err = passThroughUnconfigurableConnectionOptionsAzureAD(ctx, api, connectionID, connection)
case management.ConnectionStrategySAML:
err = passThroughUnconfigurableConnectionOptionsSAML(ctx, api, connectionID, connection)
case management.ConnectionStrategyADFS:
err = passThroughUnconfigurableConnectionOptionsADFS(ctx, api, connectionID, connection)
case management.ConnectionStrategyPingFederate:
err = passThroughUnconfigurableConnectionOptionsPingFederate(ctx, api, connectionID, connection)
}

return err
}

func passThroughUnconfigurableConnectionOptionsAD(
ctx context.Context,
api *management.Management,
connectionID string,
connection *management.Connection,
) error {
existingConnection, err := api.Connection.Read(ctx, connectionID)
if err != nil {
return err
}

if existingConnection.Options == nil {
return nil
}

existingOptions := existingConnection.Options.(*management.ConnectionOptionsAD)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I realized after the initial implementation is that we should perform a nil check against existingConnection.Options before the type assertion.

Copy link
Contributor Author

@sergiught sergiught Aug 31, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just curious: Can an already created enterprise connection, not have any options defined? 🤔

I added a nil check in which case we'll skip over the func call.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm actually not sure and to your point, even if it were possible it should be incredibly rare. This would only be precautionary since we've seen occasional panics with type assertions. If you are certain that it is not applicable here, we can remove.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't mind keeping the check for now.


expandedOptions := connection.Options.(*management.ConnectionOptionsAD)
expandedOptions.Thumbprints = existingOptions.Thumbprints
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

expandedOptions.Certs = existingOptions.Certs
expandedOptions.AgentIP = existingOptions.AgentIP
expandedOptions.AgentVersion = existingOptions.AgentVersion
expandedOptions.AgentMode = existingOptions.AgentMode

connection.Options = expandedOptions

return nil
}

func passThroughUnconfigurableConnectionOptionsAzureAD(
ctx context.Context,
api *management.Management,
connectionID string,
connection *management.Connection,
) error {
existingConnection, err := api.Connection.Read(ctx, connectionID)
if err != nil {
return err
}

if existingConnection.Options == nil {
return nil
}

existingOptions := existingConnection.Options.(*management.ConnectionOptionsAzureAD)

expandedOptions := connection.Options.(*management.ConnectionOptionsAzureAD)
expandedOptions.Thumbprints = existingOptions.Thumbprints
expandedOptions.AppDomain = existingOptions.AppDomain
expandedOptions.CertRolloverNotification = existingOptions.CertRolloverNotification
expandedOptions.Granted = existingOptions.Granted
expandedOptions.TenantID = existingOptions.TenantID

connection.Options = expandedOptions

return nil
}

func passThroughUnconfigurableConnectionOptionsADFS(
ctx context.Context,
api *management.Management,
connectionID string,
connection *management.Connection,
) error {
existingConnection, err := api.Connection.Read(ctx, connectionID)
if err != nil {
return err
}

if existingConnection.Options == nil {
return nil
}

existingOptions := existingConnection.Options.(*management.ConnectionOptionsADFS)

expandedOptions := connection.Options.(*management.ConnectionOptionsADFS)
expandedOptions.Thumbprints = existingOptions.Thumbprints
expandedOptions.CertRolloverNotification = existingOptions.CertRolloverNotification
expandedOptions.EntityID = existingOptions.EntityID
expandedOptions.PreviousThumbprints = existingOptions.PreviousThumbprints

connection.Options = expandedOptions

return nil
}

func passThroughUnconfigurableConnectionOptionsSAML(
ctx context.Context,
api *management.Management,
connectionID string,
connection *management.Connection,
) error {
existingConnection, err := api.Connection.Read(ctx, connectionID)
if err != nil {
return err
}

if existingConnection.Options == nil {
return nil
}

existingOptions := existingConnection.Options.(*management.ConnectionOptionsSAML)

expandedOptions := connection.Options.(*management.ConnectionOptionsSAML)
expandedOptions.Thumbprints = existingOptions.Thumbprints
expandedOptions.BindingMethod = existingOptions.BindingMethod
expandedOptions.CertRolloverNotification = existingOptions.CertRolloverNotification
expandedOptions.AgentIP = existingOptions.AgentIP
expandedOptions.AgentVersion = existingOptions.AgentVersion
expandedOptions.AgentMode = existingOptions.AgentMode
expandedOptions.ExtGroups = existingOptions.ExtGroups
expandedOptions.ExtProfile = existingOptions.ExtProfile

connection.Options = expandedOptions

return nil
}

func passThroughUnconfigurableConnectionOptionsPingFederate(
ctx context.Context,
api *management.Management,
connectionID string,
connection *management.Connection,
) error {
existingConnection, err := api.Connection.Read(ctx, connectionID)
if err != nil {
return err
}

if existingConnection.Options == nil {
return nil
}

existingOptions := existingConnection.Options.(*management.ConnectionOptionsPingFederate)

expandedOptions := connection.Options.(*management.ConnectionOptionsPingFederate)
expandedOptions.APIEnableUsers = existingOptions.APIEnableUsers
expandedOptions.SignOutEndpoint = existingOptions.SignOutEndpoint
expandedOptions.Subject = existingOptions.Subject
expandedOptions.DisableSignout = existingOptions.DisableSignout
expandedOptions.UserIDAttribute = existingOptions.UserIDAttribute
expandedOptions.Debug = existingOptions.Debug
expandedOptions.ProtocolBinding = existingOptions.ProtocolBinding
expandedOptions.RequestTemplate = existingOptions.RequestTemplate
expandedOptions.Thumbprints = existingOptions.Thumbprints
expandedOptions.BindingMethod = existingOptions.BindingMethod
expandedOptions.Expires = existingOptions.Expires
expandedOptions.MetadataURL = existingOptions.MetadataURL
expandedOptions.FieldsMap = existingOptions.FieldsMap
expandedOptions.MetadataXML = existingOptions.MetadataXML
expandedOptions.EntityID = existingOptions.EntityID
expandedOptions.CertRolloverNotification = existingOptions.CertRolloverNotification
expandedOptions.SigningKey = existingOptions.SigningKey
expandedOptions.DecryptionKey = existingOptions.DecryptionKey
expandedOptions.AgentIP = existingOptions.AgentIP
expandedOptions.AgentVersion = existingOptions.AgentVersion
expandedOptions.AgentMode = existingOptions.AgentMode
expandedOptions.ExtGroups = existingOptions.ExtGroups
expandedOptions.ExtProfile = existingOptions.ExtProfile

connection.Options = expandedOptions

return nil
}
Loading