Co-authored-by: hashicorp-copywrite[bot] <110428419+hashicorp-copywrite[bot]@users.noreply.github.com>
610 lines
21 KiB
Go
610 lines
21 KiB
Go
// Copyright IBM Corp. 2020, 2026
|
|
// 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
|
|
}
|