* feat(oidc): OIDC Prompt Support Boundary OIDC method does not currently support passing in prompts during authentication. This change adds the capability of passing OIDC prompts. Prompts are optional OIDC parameters that determine the behaviour of the authentication server: https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest Add new optional `prompts` option to `boundary_auth_method_oidc` resource. `prompts` option are optional OIDC parameters that determine the behavior of the authentication server.
610 lines
21 KiB
Go
610 lines
21 KiB
Go
// Copyright (c) HashiCorp, Inc.
|
|
// SPDX-License-Identifier: MPL-2.0
|
|
|
|
package provider
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"net/http"
|
|
|
|
"github.com/hashicorp/boundary/api"
|
|
"github.com/hashicorp/boundary/api/authmethods"
|
|
"github.com/hashicorp/boundary/api/scopes"
|
|
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
|
|
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
|
)
|
|
|
|
const (
|
|
authmethodTypeOidc = "oidc"
|
|
authmethodOidcIssuerKey = "issuer"
|
|
authmethodOidcClientIdKey = "client_id"
|
|
authmethodOidcClientSecretKey = "client_secret"
|
|
authmethodOidcMaxAgeKey = "max_age"
|
|
authmethodOidcApiUrlPrefixKey = "api_url_prefix"
|
|
authmethodOidcIdpCaCertsKey = "idp_ca_certs"
|
|
authmethodOidcAllowedAudiencesKey = "allowed_audiences"
|
|
authmethodOidcDisableDiscoveredConfigValidationKey = "disable_discovered_config_validation"
|
|
authmethodOidcSigningAlgorithmsKey = "signing_algorithms"
|
|
authmethodOidcIsPrimaryAuthMethodForScope = "is_primary_for_scope"
|
|
authmethodOidcAccountClaimMapsKey = "account_claim_maps"
|
|
authmethodOidcClaimsScopesKey = "claims_scopes"
|
|
authmethodOidcPromptsKey = "prompts"
|
|
|
|
// computed-only parameters
|
|
authmethodOidcCallbackUrlKey = "callback_url"
|
|
authmethodOidcClientSecretHmacKey = "client_secret_hmac"
|
|
authmethodOidcStateKey = "state"
|
|
)
|
|
|
|
func resourceAuthMethodOidc() *schema.Resource {
|
|
return &schema.Resource{
|
|
Description: "The OIDC auth method resource allows you to configure a Boundary auth_method_oidc.",
|
|
|
|
CreateContext: resourceAuthMethodOidcCreate,
|
|
ReadContext: resourceAuthMethodOidcRead,
|
|
UpdateContext: resourceAuthMethodOidcUpdate,
|
|
DeleteContext: resourceAuthMethodOidcDelete,
|
|
Importer: &schema.ResourceImporter{
|
|
StateContext: schema.ImportStatePassthroughContext,
|
|
},
|
|
|
|
Schema: map[string]*schema.Schema{
|
|
IDKey: {
|
|
Description: "The ID of the auth method.",
|
|
Type: schema.TypeString,
|
|
Computed: true,
|
|
},
|
|
NameKey: {
|
|
Description: "The auth method name. Defaults to the resource name.",
|
|
Type: schema.TypeString,
|
|
Optional: true,
|
|
},
|
|
DescriptionKey: {
|
|
Description: "The auth method description.",
|
|
Type: schema.TypeString,
|
|
Optional: true,
|
|
},
|
|
ScopeIdKey: {
|
|
Description: "The scope ID.",
|
|
Type: schema.TypeString,
|
|
Required: true,
|
|
ForceNew: true,
|
|
},
|
|
|
|
// OIDC specific configurable parameters
|
|
authmethodOidcAllowedAudiencesKey: {
|
|
Description: "Audiences for which the provider responses will be allowed",
|
|
Type: schema.TypeList,
|
|
Elem: &schema.Schema{
|
|
Type: schema.TypeString,
|
|
},
|
|
Optional: true,
|
|
},
|
|
authmethodOidcApiUrlPrefixKey: {
|
|
Description: "The API prefix to use when generating callback URLs for the provider. Should be set to an address at which the provider can reach back to the controller.",
|
|
Type: schema.TypeString,
|
|
Optional: true,
|
|
},
|
|
authmethodOidcIdpCaCertsKey: {
|
|
Description: "A list of CA certificates to trust when validating the IdP's token signatures.",
|
|
Type: schema.TypeList,
|
|
Elem: &schema.Schema{
|
|
Type: schema.TypeString,
|
|
},
|
|
Optional: true,
|
|
},
|
|
authmethodOidcClientIdKey: {
|
|
Description: "The client ID assigned to this auth method from the provider.",
|
|
Type: schema.TypeString,
|
|
Optional: true,
|
|
},
|
|
authmethodOidcClientSecretKey: {
|
|
Description: "The secret key assigned to this auth method from the provider. Once set, only the hash will be kept and the original value can be removed from configuration.",
|
|
Type: schema.TypeString,
|
|
Optional: true,
|
|
Sensitive: true,
|
|
},
|
|
authmethodOidcIssuerKey: {
|
|
Description: "The issuer corresponding to the provider, which must match the issuer field in generated tokens.",
|
|
Type: schema.TypeString,
|
|
Optional: true,
|
|
},
|
|
authmethodOidcDisableDiscoveredConfigValidationKey: {
|
|
Description: "Disables validation logic ensuring that the OIDC provider's information from its discovery endpoint matches the information here. The validation is only performed at create or update time.",
|
|
Type: schema.TypeBool,
|
|
Optional: true,
|
|
},
|
|
authmethodOidcMaxAgeKey: {
|
|
Description: `The max age to provide to the provider, indicating how much time is allowed to have passed since the last authentication before the user is challenged again. ` +
|
|
`A value of 0 sets an immediate requirement for all users to reauthenticate, and an unset maxAge results in a Terraform value of -1 and the default TTL of the chosen OIDC will be used.`,
|
|
Type: schema.TypeInt,
|
|
Optional: true,
|
|
Default: -1,
|
|
},
|
|
authmethodOidcSigningAlgorithmsKey: {
|
|
Description: "Allowed signing algorithms for the provider's issued tokens.",
|
|
Type: schema.TypeList,
|
|
Elem: &schema.Schema{
|
|
Type: schema.TypeString,
|
|
},
|
|
Optional: true,
|
|
},
|
|
authmethodOidcAccountClaimMapsKey: {
|
|
Description: "Account claim maps for the to_claim of sub.",
|
|
Type: schema.TypeList,
|
|
Elem: &schema.Schema{
|
|
Type: schema.TypeString,
|
|
},
|
|
Optional: true,
|
|
// per comment in https://github.com/hashicorp/boundary/pull/1186
|
|
ForceNew: true,
|
|
},
|
|
authmethodOidcClaimsScopesKey: {
|
|
Description: "Claims scopes.",
|
|
Type: schema.TypeList,
|
|
Elem: &schema.Schema{
|
|
Type: schema.TypeString,
|
|
},
|
|
Optional: true,
|
|
},
|
|
authmethodOidcPromptsKey: {
|
|
Description: "The prompts passed to the identity provider to determine whether to prompt the end-user for reauthentication, account selection or consent. " +
|
|
"Please note the values passed are case-sensitive. The valid values are: `none`, `login`, `consent` and `select_account`. ",
|
|
Type: schema.TypeList,
|
|
Elem: &schema.Schema{
|
|
Type: schema.TypeString,
|
|
},
|
|
Optional: true,
|
|
},
|
|
|
|
// OIDC specific immutable and computed parameters
|
|
authmethodOidcClientSecretHmacKey: {
|
|
Description: "The HMAC of the client secret returned by the Boundary controller, which is used for comparison after initial setting of the value.",
|
|
Type: schema.TypeString,
|
|
Optional: true,
|
|
Computed: true,
|
|
},
|
|
authmethodOidcStateKey: {
|
|
Description: "Can be one of 'inactive', 'active-private', or 'active-public'. Currently automatically set to active-public.",
|
|
Type: schema.TypeString,
|
|
Optional: true,
|
|
Computed: true,
|
|
},
|
|
authmethodOidcCallbackUrlKey: {
|
|
Description: "The URL that should be provided to the IdP for callbacks.",
|
|
Type: schema.TypeString,
|
|
Optional: true,
|
|
Computed: true,
|
|
},
|
|
authmethodOidcIsPrimaryAuthMethodForScope: {
|
|
Description: "When true, makes this auth method the primary auth method for the scope in which it resides. The primary auth method for a scope means the user will be automatically created when they login using an OIDC account.",
|
|
Type: schema.TypeBool,
|
|
Optional: true,
|
|
},
|
|
|
|
TypeKey: {
|
|
Description: "The type of auth method; hardcoded.",
|
|
Type: schema.TypeString,
|
|
Default: authmethodTypeOidc,
|
|
Optional: true,
|
|
},
|
|
},
|
|
}
|
|
}
|
|
|
|
func setFromOidcAuthMethodResponseMap(d *schema.ResourceData, raw map[string]interface{}) diag.Diagnostics {
|
|
d.Set(NameKey, raw[NameKey])
|
|
d.Set(DescriptionKey, raw[DescriptionKey])
|
|
d.Set(ScopeIdKey, raw[ScopeIdKey])
|
|
d.Set(TypeKey, raw[TypeKey])
|
|
|
|
if attrsVal, ok := raw["attributes"]; ok {
|
|
attrs := attrsVal.(map[string]interface{})
|
|
|
|
// these are always set
|
|
d.Set(authmethodOidcStateKey, attrs[authmethodOidcStateKey].(string))
|
|
d.Set(authmethodOidcIssuerKey, attrs[authmethodOidcIssuerKey].(string))
|
|
d.Set(authmethodOidcClientIdKey, attrs[authmethodOidcClientIdKey].(string))
|
|
d.Set(authmethodOidcClientSecretHmacKey, attrs[authmethodOidcClientSecretHmacKey].(string))
|
|
|
|
if certs, ok := attrs[authmethodOidcIdpCaCertsKey]; ok {
|
|
d.Set(authmethodOidcIdpCaCertsKey, certs.([]interface{}))
|
|
}
|
|
|
|
if aud, ok := attrs[authmethodOidcAllowedAudiencesKey]; ok {
|
|
d.Set(authmethodOidcAllowedAudiencesKey, aud.([]interface{}))
|
|
}
|
|
|
|
if m, ok := attrs[authmethodOidcMaxAgeKey]; ok {
|
|
maxAge := m.(json.Number)
|
|
maxAgeInt, _ := maxAge.Int64()
|
|
d.Set(authmethodOidcMaxAgeKey, maxAgeInt)
|
|
}
|
|
|
|
if val, ok := attrs[authmethodOidcApiUrlPrefixKey]; ok {
|
|
d.Set(authmethodOidcApiUrlPrefixKey, val.(string))
|
|
}
|
|
|
|
if val, ok := attrs[authmethodOidcCallbackUrlKey]; ok {
|
|
d.Set(authmethodOidcCallbackUrlKey, val.(string))
|
|
}
|
|
|
|
if val, ok := attrs[authmethodOidcSigningAlgorithmsKey]; ok {
|
|
d.Set(authmethodOidcSigningAlgorithmsKey, val.([]interface{}))
|
|
}
|
|
|
|
if p, ok := attrs[authmethodOidcIsPrimaryAuthMethodForScope]; ok {
|
|
d.Set(authmethodOidcIsPrimaryAuthMethodForScope, p.(bool))
|
|
}
|
|
|
|
if p, ok := attrs[authmethodOidcDisableDiscoveredConfigValidationKey]; ok {
|
|
d.Set(authmethodOidcDisableDiscoveredConfigValidationKey, p.(bool))
|
|
}
|
|
|
|
if p, ok := attrs[authmethodOidcAccountClaimMapsKey]; ok {
|
|
d.Set(authmethodOidcAccountClaimMapsKey, p.([]interface{}))
|
|
}
|
|
|
|
if p, ok := attrs[authmethodOidcClaimsScopesKey]; ok {
|
|
d.Set(authmethodOidcClaimsScopesKey, p.([]interface{}))
|
|
}
|
|
|
|
if val, ok := attrs[authmethodOidcPromptsKey]; ok {
|
|
d.Set(authmethodOidcPromptsKey, val.([]interface{}))
|
|
}
|
|
}
|
|
|
|
d.SetId(raw["id"].(string))
|
|
|
|
return nil
|
|
}
|
|
|
|
func resourceAuthMethodOidcCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
|
|
md := meta.(*metaData)
|
|
|
|
var typeStr string
|
|
if typeVal, ok := d.GetOk(TypeKey); ok {
|
|
typeStr = typeVal.(string)
|
|
} else {
|
|
return diag.Errorf("no type provided")
|
|
}
|
|
|
|
opts := []authmethods.Option{}
|
|
|
|
opts = append(opts, authmethods.WithAutomaticVersioning(true))
|
|
|
|
if issuer, ok := d.GetOk(authmethodOidcIssuerKey); ok {
|
|
opts = append(opts, authmethods.WithOidcAuthMethodIssuer(issuer.(string)))
|
|
}
|
|
if clientId, ok := d.GetOk(authmethodOidcClientIdKey); ok {
|
|
opts = append(opts, authmethods.WithOidcAuthMethodClientId(clientId.(string)))
|
|
}
|
|
if clientSecret, ok := d.GetOk(authmethodOidcClientSecretKey); ok {
|
|
opts = append(opts, authmethods.WithOidcAuthMethodClientSecret(clientSecret.(string)))
|
|
}
|
|
// null values are not correctly recognized by the Terraform SDK, so we instead check here for maxAge value
|
|
// if maxAge is unset it will default and set the terraform state to -1 and clear the maxAge param in Boundary
|
|
if maxAge, _ := d.GetOk(authmethodOidcMaxAgeKey); maxAge.(int) >= 0 {
|
|
opts = append(opts, authmethods.WithOidcAuthMethodMaxAge(uint32(maxAge.(int))))
|
|
} else {
|
|
opts = append(opts, authmethods.DefaultOidcAuthMethodMaxAge())
|
|
}
|
|
if prefix, ok := d.GetOk(authmethodOidcApiUrlPrefixKey); ok {
|
|
opts = append(opts, authmethods.WithOidcAuthMethodApiUrlPrefix(prefix.(string)))
|
|
}
|
|
if certs, ok := d.GetOk(authmethodOidcIdpCaCertsKey); ok {
|
|
certList := []string{}
|
|
for _, c := range certs.([]interface{}) {
|
|
certList = append(certList, c.(string))
|
|
}
|
|
|
|
opts = append(opts, authmethods.WithOidcAuthMethodIdpCaCerts(certList))
|
|
}
|
|
if aud, ok := d.GetOk(authmethodOidcAllowedAudiencesKey); ok {
|
|
audList := []string{}
|
|
for _, c := range aud.([]interface{}) {
|
|
audList = append(audList, c.(string))
|
|
}
|
|
opts = append(opts, authmethods.WithOidcAuthMethodAllowedAudiences(audList))
|
|
}
|
|
if dis, ok := d.GetOk(authmethodOidcDisableDiscoveredConfigValidationKey); ok {
|
|
opts = append(opts, authmethods.WithOidcAuthMethodDisableDiscoveredConfigValidation(dis.(bool)))
|
|
}
|
|
if algos, ok := d.GetOk(authmethodOidcSigningAlgorithmsKey); ok {
|
|
algoList := []string{}
|
|
for _, c := range algos.([]interface{}) {
|
|
algoList = append(algoList, c.(string))
|
|
}
|
|
opts = append(opts, authmethods.WithOidcAuthMethodSigningAlgorithms(algoList))
|
|
}
|
|
|
|
if claims, ok := d.GetOk(authmethodOidcAccountClaimMapsKey); ok {
|
|
cList := []string{}
|
|
for _, c := range claims.([]interface{}) {
|
|
cList = append(cList, c.(string))
|
|
}
|
|
opts = append(opts, authmethods.WithOidcAuthMethodAccountClaimMaps(cList))
|
|
}
|
|
|
|
if claimsScopes, ok := d.GetOk(authmethodOidcClaimsScopesKey); ok {
|
|
cList := []string{}
|
|
for _, c := range claimsScopes.([]interface{}) {
|
|
cList = append(cList, c.(string))
|
|
}
|
|
opts = append(opts, authmethods.WithOidcAuthMethodClaimsScopes(cList))
|
|
}
|
|
|
|
if prompts, ok := d.GetOk(authmethodOidcPromptsKey); ok {
|
|
promptList := []string{}
|
|
for _, p := range prompts.([]interface{}) {
|
|
promptList = append(promptList, p.(string))
|
|
}
|
|
opts = append(opts, authmethods.WithOidcAuthMethodPrompts(promptList))
|
|
}
|
|
|
|
nameVal, ok := d.GetOk(NameKey)
|
|
if ok {
|
|
nameStr := nameVal.(string)
|
|
opts = append(opts, authmethods.WithName(nameStr))
|
|
}
|
|
|
|
descVal, ok := d.GetOk(DescriptionKey)
|
|
if ok {
|
|
descStr := descVal.(string)
|
|
opts = append(opts, authmethods.WithDescription(descStr))
|
|
}
|
|
|
|
var scopeId string
|
|
if scopeIdVal, ok := d.GetOk(ScopeIdKey); ok {
|
|
scopeId = scopeIdVal.(string)
|
|
} else {
|
|
return diag.Errorf("no scope ID provided")
|
|
}
|
|
|
|
amClient := authmethods.NewClient(md.client)
|
|
|
|
amcr, err := amClient.Create(ctx, typeStr, scopeId, opts...)
|
|
if err != nil {
|
|
return diag.Errorf("error creating auth method: %v", err)
|
|
}
|
|
if amcr == nil {
|
|
return diag.Errorf("nil auth method after create")
|
|
}
|
|
// need to update state is create was successful to avoid loosing state if the change state or update
|
|
// scope step that follows errors out
|
|
if err := setFromOidcAuthMethodResponseMap(d, amcr.GetResponse().Map); err != nil {
|
|
return diag.Errorf("%v", err)
|
|
}
|
|
|
|
amid := amcr.GetResponse().Map["id"].(string)
|
|
|
|
// auto set to active-public state
|
|
_, err = amClient.ChangeState(ctx, amid, 0, "active-public", authmethods.WithAutomaticVersioning(true))
|
|
if err != nil {
|
|
return diag.Errorf("%v", err)
|
|
}
|
|
|
|
// update scope when set to primary
|
|
if p, ok := d.GetOk(authmethodOidcIsPrimaryAuthMethodForScope); ok {
|
|
if p.(bool) {
|
|
if err := updateScopeWithPrimaryAuthMethodId(ctx, scopeId, amid, meta); err != nil {
|
|
return diag.Errorf("%v", err)
|
|
}
|
|
|
|
amcr.GetResponse().Map[authmethodOidcIsPrimaryAuthMethodForScope] = true
|
|
}
|
|
}
|
|
|
|
return setFromOidcAuthMethodResponseMap(d, amcr.GetResponse().Map)
|
|
}
|
|
|
|
func updateScopeWithPrimaryAuthMethodId(ctx context.Context, scopeId, authmethodId string, meta interface{}) diag.Diagnostics {
|
|
md := meta.(*metaData)
|
|
scp := scopes.NewClient(md.client)
|
|
|
|
opts := []scopes.Option{}
|
|
opts = append(opts, scopes.WithAutomaticVersioning(true))
|
|
opts = append(opts, scopes.WithPrimaryAuthMethodId(authmethodId))
|
|
|
|
_, err := scp.Update(ctx, scopeId, 0, opts...)
|
|
if err != nil {
|
|
return diag.Errorf("error updating scope: %v", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func readScopeIsPrimaryAuthMethodId(ctx context.Context, scopeId, authmethodId string, meta interface{}) (diag.Diagnostics, bool) {
|
|
md := meta.(*metaData)
|
|
scp := scopes.NewClient(md.client)
|
|
|
|
srr, err := scp.Read(ctx, scopeId)
|
|
if err != nil {
|
|
return diag.Errorf("%s", err), false
|
|
}
|
|
|
|
if p, ok := srr.GetResponse().Map["primary_auth_method_id"]; ok {
|
|
if p == authmethodId {
|
|
return nil, true
|
|
}
|
|
}
|
|
|
|
return nil, false
|
|
}
|
|
|
|
func resourceAuthMethodOidcRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
|
|
md := meta.(*metaData)
|
|
amClient := authmethods.NewClient(md.client)
|
|
|
|
amrr, err := amClient.Read(ctx, d.Id())
|
|
if err != nil {
|
|
if apiErr := api.AsServerError(err); apiErr.Response().StatusCode() == http.StatusNotFound {
|
|
d.SetId("")
|
|
return nil
|
|
}
|
|
return diag.Errorf("error reading auth method: %v", err)
|
|
}
|
|
if amrr == nil {
|
|
return diag.Errorf("auth method nil after read")
|
|
}
|
|
|
|
serr, isPrimary := readScopeIsPrimaryAuthMethodId(ctx, amrr.GetResponse().Map["scope_id"].(string), amrr.GetResponse().Map["id"].(string), meta)
|
|
if err != nil {
|
|
return diag.Errorf("%v", serr)
|
|
}
|
|
|
|
if isPrimary {
|
|
amrr.GetResponse().Map[authmethodOidcIsPrimaryAuthMethodForScope] = true
|
|
}
|
|
|
|
return setFromOidcAuthMethodResponseMap(d, amrr.GetResponse().Map)
|
|
}
|
|
|
|
func resourceAuthMethodOidcUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
|
|
md := meta.(*metaData)
|
|
amClient := authmethods.NewClient(md.client)
|
|
|
|
opts := []authmethods.Option{}
|
|
|
|
if d.HasChange(NameKey) {
|
|
opts = append(opts, authmethods.DefaultName())
|
|
nameVal, ok := d.GetOk(NameKey)
|
|
if ok {
|
|
opts = append(opts, authmethods.WithName(nameVal.(string)))
|
|
}
|
|
}
|
|
|
|
if d.HasChange(DescriptionKey) {
|
|
opts = append(opts, authmethods.DefaultDescription())
|
|
descVal, ok := d.GetOk(DescriptionKey)
|
|
if ok {
|
|
opts = append(opts, authmethods.WithDescription(descVal.(string)))
|
|
}
|
|
}
|
|
|
|
if d.HasChange(authmethodOidcIssuerKey) {
|
|
if issuer, ok := d.GetOk(authmethodOidcIssuerKey); ok {
|
|
opts = append(opts, authmethods.WithOidcAuthMethodIssuer(issuer.(string)))
|
|
}
|
|
}
|
|
if d.HasChange(authmethodOidcClientIdKey) {
|
|
if clientId, ok := d.GetOk(authmethodOidcClientIdKey); ok {
|
|
opts = append(opts, authmethods.WithOidcAuthMethodClientId(clientId.(string)))
|
|
}
|
|
}
|
|
if d.HasChange(authmethodOidcClientSecretKey) {
|
|
if clientSecret, ok := d.GetOk(authmethodOidcClientSecretKey); ok {
|
|
opts = append(opts, authmethods.WithOidcAuthMethodClientSecret(clientSecret.(string)))
|
|
}
|
|
}
|
|
if d.HasChange(authmethodOidcMaxAgeKey) {
|
|
// null values are not correctly recognized by the Terraform SDK, so we instead check here for maxAge value
|
|
// if maxAge is unset it will default and set the terraform state to -1 and clear the maxAge param in Boundary
|
|
if maxAge, _ := d.GetOk(authmethodOidcMaxAgeKey); maxAge.(int) >= 0 {
|
|
opts = append(opts, authmethods.WithOidcAuthMethodMaxAge(uint32(maxAge.(int))))
|
|
} else {
|
|
opts = append(opts, authmethods.DefaultOidcAuthMethodMaxAge())
|
|
}
|
|
}
|
|
if d.HasChange(authmethodOidcSigningAlgorithmsKey) {
|
|
if algos, ok := d.GetOk(authmethodOidcSigningAlgorithmsKey); ok {
|
|
var signingAlgs []string
|
|
for _, alg := range algos.([]interface{}) {
|
|
signingAlgs = append(signingAlgs, alg.(string))
|
|
}
|
|
opts = append(opts, authmethods.WithOidcAuthMethodSigningAlgorithms(signingAlgs))
|
|
}
|
|
}
|
|
if d.HasChange(authmethodOidcApiUrlPrefixKey) {
|
|
if prefix, ok := d.GetOk(authmethodOidcApiUrlPrefixKey); ok {
|
|
opts = append(opts, authmethods.WithOidcAuthMethodApiUrlPrefix(prefix.(string)))
|
|
}
|
|
}
|
|
if d.HasChange(authmethodOidcClientSecretHmacKey) {
|
|
if sec, ok := d.GetOk(authmethodOidcClientSecretHmacKey); ok {
|
|
opts = append(opts, authmethods.WithOidcAuthMethodClientSecret(sec.(string)))
|
|
}
|
|
}
|
|
if d.HasChange(authmethodOidcAllowedAudiencesKey) {
|
|
if val, ok := d.GetOk(authmethodOidcAllowedAudiencesKey); ok {
|
|
var audiences []string
|
|
for _, aud := range val.([]interface{}) {
|
|
audiences = append(audiences, aud.(string))
|
|
}
|
|
opts = append(opts, authmethods.WithOidcAuthMethodAllowedAudiences(audiences))
|
|
}
|
|
}
|
|
if d.HasChange(authmethodOidcIdpCaCertsKey) {
|
|
if val, ok := d.GetOk(authmethodOidcIdpCaCertsKey); ok {
|
|
certs := []string{}
|
|
for _, cert := range val.([]interface{}) {
|
|
certs = append(certs, cert.(string))
|
|
}
|
|
opts = append(opts, authmethods.WithOidcAuthMethodIdpCaCerts(certs))
|
|
}
|
|
}
|
|
if d.HasChange(authmethodOidcDisableDiscoveredConfigValidationKey) {
|
|
if val, ok := d.GetOk(authmethodOidcDisableDiscoveredConfigValidationKey); ok {
|
|
opts = append(opts, authmethods.WithOidcAuthMethodDisableDiscoveredConfigValidation(val.(bool)))
|
|
}
|
|
}
|
|
if d.HasChange(authmethodOidcClaimsScopesKey) {
|
|
if val, ok := d.GetOk(authmethodOidcClaimsScopesKey); ok {
|
|
claimsScopes := []string{}
|
|
for _, c := range val.([]interface{}) {
|
|
claimsScopes = append(claimsScopes, c.(string))
|
|
}
|
|
opts = append(opts, authmethods.WithOidcAuthMethodClaimsScopes(claimsScopes))
|
|
}
|
|
}
|
|
if d.HasChange(authmethodOidcPromptsKey) {
|
|
if prompts, ok := d.GetOk(authmethodOidcPromptsKey); ok {
|
|
var promptsList []string
|
|
for _, prompt := range prompts.([]interface{}) {
|
|
promptsList = append(promptsList, prompt.(string))
|
|
}
|
|
opts = append(opts, authmethods.WithOidcAuthMethodPrompts(promptsList))
|
|
}
|
|
}
|
|
|
|
if len(opts) > 0 {
|
|
opts = append(opts, authmethods.WithAutomaticVersioning(true))
|
|
amur, err := amClient.Update(ctx, d.Id(), 0, opts...)
|
|
if err != nil {
|
|
return diag.Errorf("error updating auth method: %v", err)
|
|
}
|
|
|
|
if d.HasChange(authmethodOidcIsPrimaryAuthMethodForScope) {
|
|
if p, ok := d.GetOk(authmethodOidcIsPrimaryAuthMethodForScope); ok {
|
|
if p.(bool) {
|
|
if err := updateScopeWithPrimaryAuthMethodId(
|
|
ctx,
|
|
amur.GetResponse().Map["scope_id"].(string),
|
|
amur.GetResponse().Map["id"].(string),
|
|
meta); err != nil {
|
|
return diag.Errorf("%v", err)
|
|
}
|
|
|
|
amur.GetResponse().Map[authmethodOidcIsPrimaryAuthMethodForScope] = true
|
|
}
|
|
}
|
|
}
|
|
|
|
return setFromOidcAuthMethodResponseMap(d, amur.GetResponse().Map)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func resourceAuthMethodOidcDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
|
|
md := meta.(*metaData)
|
|
amClient := authmethods.NewClient(md.client)
|
|
|
|
_, err := amClient.Delete(ctx, d.Id())
|
|
if err != nil {
|
|
return diag.Errorf("error deleting auth method: %v", err)
|
|
}
|
|
|
|
return nil
|
|
}
|