diff --git a/.changelog/2318.txt b/.changelog/2318.txt new file mode 100644 index 0000000000..dad907219a --- /dev/null +++ b/.changelog/2318.txt @@ -0,0 +1,15 @@ +```release-note:enhancement +resource/mongodbatlas_federated_settings_identity_provider: Adds OIDC Workload support +``` + +```release-note:enhancement +data-source/mongodbatlas_federated_settings_identity_provider: Adds OIDC Workload support +``` + +```release-note:enhancement +data-source/mongodbatlas_federated_settings_identity_providers: Adds OIDC Workload support +``` + +```release-note:enhancement +data-source/mongodbatlas_federated_settings_identity_providers: Adds filtering support for Protocol and IdP type +``` diff --git a/internal/service/federatedsettingsidentityprovider/data_source_federated_settings_identity_provider.go b/internal/service/federatedsettingsidentityprovider/data_source_federated_settings_identity_provider.go index b2d1dd3c51..7a8a94df3c 100644 --- a/internal/service/federatedsettingsidentityprovider/data_source_federated_settings_identity_provider.go +++ b/internal/service/federatedsettingsidentityprovider/data_source_federated_settings_identity_provider.go @@ -236,6 +236,10 @@ func DataSource() *schema.Resource { Type: schema.TypeString, Computed: true, }, + "idp_type": { + Type: schema.TypeString, + Computed: true, + }, }, } } @@ -347,6 +351,10 @@ func dataSourceRead(ctx context.Context, d *schema.ResourceData, meta any) diag. return diag.FromErr(fmt.Errorf("error setting `idp_id` for federatedSettings IdentityProviders: %s", err)) } + if err := d.Set("idp_type", federatedSettingsIdentityProvider.IdpType); err != nil { + return diag.FromErr(fmt.Errorf("error setting `idp_type` for federatedSettings IdentityProviders: %s", err)) + } + d.SetId(federatedSettingsIdentityProvider.Id) return nil diff --git a/internal/service/federatedsettingsidentityprovider/data_source_federated_settings_identity_providers.go b/internal/service/federatedsettingsidentityprovider/data_source_federated_settings_identity_providers.go index 826fc22714..4b2a598929 100644 --- a/internal/service/federatedsettingsidentityprovider/data_source_federated_settings_identity_providers.go +++ b/internal/service/federatedsettingsidentityprovider/data_source_federated_settings_identity_providers.go @@ -11,6 +11,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/mongodb/terraform-provider-mongodbatlas/internal/common/constant" + "github.com/mongodb/terraform-provider-mongodbatlas/internal/common/conversion" "github.com/mongodb/terraform-provider-mongodbatlas/internal/config" ) @@ -22,6 +23,20 @@ func PluralDataSource() *schema.Resource { Type: schema.TypeString, Required: true, }, + "idp_types": { + Type: schema.TypeList, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + Optional: true, + }, + "protocols": { + Type: schema.TypeList, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + Optional: true, + }, "page_num": { Type: schema.TypeInt, Optional: true, @@ -249,6 +264,10 @@ func PluralDataSource() *schema.Resource { Type: schema.TypeString, Computed: true, }, + "idp_type": { + Type: schema.TypeString, + Computed: true, + }, }, }, }, @@ -262,11 +281,13 @@ func dataSourcePluralRead(ctx context.Context, d *schema.ResourceData, meta any) if !federationSettingsIDOk { return diag.FromErr(errors.New("federation_settings_id must be configured")) } + idpTypes := conversion.ExpandStringList(d.Get("idp_types").([]any)) + protocols := conversion.ExpandStringList(d.Get("protocols").([]any)) params := &admin.ListIdentityProvidersApiParams{ FederationSettingsId: federationSettingsID.(string), - Protocol: &[]string{OIDC, SAML}, - IdpType: &[]string{WORKFORCE}, + Protocol: &protocols, + IdpType: &idpTypes, } providers, _, err := connV2.FederatedAuthenticationApi.ListIdentityProvidersWithParams(ctx, params).Execute() diff --git a/internal/service/federatedsettingsidentityprovider/data_source_federated_settings_identity_providers_test.go b/internal/service/federatedsettingsidentityprovider/data_source_federated_settings_identity_providers_test.go index 2060a46065..073011305f 100644 --- a/internal/service/federatedsettingsidentityprovider/data_source_federated_settings_identity_providers_test.go +++ b/internal/service/federatedsettingsidentityprovider/data_source_federated_settings_identity_providers_test.go @@ -6,6 +6,8 @@ import ( "testing" "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/mongodb/terraform-provider-mongodbatlas/internal/common/conversion" + "github.com/mongodb/terraform-provider-mongodbatlas/internal/service/federatedsettingsidentityprovider" "github.com/mongodb/terraform-provider-mongodbatlas/internal/testutil/acc" ) @@ -20,22 +22,66 @@ func TestAccFederatedSettingsIdentityProvidersDS_basic(t *testing.T) { ProtoV6ProviderFactories: acc.TestAccProviderV6Factories, Steps: []resource.TestStep{ { - Config: configBasicPluralDS(federatedSettingsID), + Config: configPluralDS(federatedSettingsID, conversion.StringPtr(federatedsettingsidentityprovider.WORKFORCE), []string{oidcProtocol, samlProtocol}), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttrSet(dataSourceName, "federation_settings_id"), resource.TestCheckResourceAttr(dataSourceName, "results.#", "2"), ), }, + { + Config: configPluralDS(federatedSettingsID, conversion.StringPtr(federatedsettingsidentityprovider.WORKFORCE), []string{samlProtocol}), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet(dataSourceName, "federation_settings_id"), + resource.TestCheckResourceAttr(dataSourceName, "results.#", "1"), + resource.TestCheckResourceAttr(dataSourceName, "results.0.display_name", "SAML-test"), + ), + }, + { + Config: configPluralDS(federatedSettingsID, conversion.StringPtr(federatedsettingsidentityprovider.WORKFORCE), []string{oidcProtocol}), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet(dataSourceName, "federation_settings_id"), + resource.TestCheckResourceAttr(dataSourceName, "results.#", "1"), + resource.TestCheckResourceAttr(dataSourceName, "results.0.display_name", "OIDC-test"), + ), + }, + { + Config: configPluralDS(federatedSettingsID, conversion.StringPtr(federatedsettingsidentityprovider.WORKFORCE), []string{}), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet(dataSourceName, "federation_settings_id"), + resource.TestCheckResourceAttr(dataSourceName, "results.#", "1"), + resource.TestCheckResourceAttr(dataSourceName, "results.0.display_name", "SAML-test"), // if no protocol is specified, it defaults to SAML + ), + }, + { + Config: configPluralDS(federatedSettingsID, conversion.StringPtr(federatedsettingsidentityprovider.WORKLOAD), []string{}), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet(dataSourceName, "federation_settings_id"), + resource.TestCheckResourceAttr(dataSourceName, "results.#", "0"), + ), + }, }, }) } -func configBasicPluralDS(federatedSettingsID string) string { +func configPluralDS(federatedSettingsID string, idpType *string, protocols []string) string { + var protocolString string + if len(protocols) > 1 { + protocolString = fmt.Sprintf(`protocols = [%[1]q, %[2]q]`, protocols[0], protocols[1]) + } else if len(protocols) > 0 { + protocolString = fmt.Sprintf(`protocols = [%[1]q]`, protocols[0]) + } + var idpTypeString string + if idpType != nil { + idpTypeString = fmt.Sprintf(`idp_types = [%[1]q]`, *idpType) + } + return fmt.Sprintf(` data "mongodbatlas_federated_settings_identity_providers" "test" { federation_settings_id = "%[1]s" page_num = 1 items_per_page = 100 + %[2]s + %[3]s } -`, federatedSettingsID) +`, federatedSettingsID, protocolString, idpTypeString) } diff --git a/internal/service/federatedsettingsidentityprovider/model_federated_settings_identity_provider.go b/internal/service/federatedsettingsidentityprovider/model_federated_settings_identity_provider.go index 680a23946a..0292f0fd3b 100644 --- a/internal/service/federatedsettingsidentityprovider/model_federated_settings_identity_provider.go +++ b/internal/service/federatedsettingsidentityprovider/model_federated_settings_identity_provider.go @@ -12,6 +12,7 @@ import ( ) const WORKFORCE = "WORKFORCE" +const WORKLOAD = "WORKLOAD" func ExpandIdentityProviderOIDCCreate(d *schema.ResourceData) *admin.FederationOidcIdentityProviderUpdate { return &admin.FederationOidcIdentityProviderUpdate{ @@ -22,7 +23,7 @@ func ExpandIdentityProviderOIDCCreate(d *schema.ResourceData) *admin.FederationO Description: conversion.StringPtr(d.Get("description").(string)), DisplayName: conversion.StringPtr(d.Get("name").(string)), GroupsClaim: conversion.StringPtr(d.Get("groups_claim").(string)), - IdpType: conversion.StringPtr(WORKFORCE), + IdpType: conversion.StringPtr(d.Get("idp_type").(string)), IssuerUri: conversion.StringPtr(d.Get("issuer_uri").(string)), Protocol: conversion.StringPtr(d.Get("protocol").(string)), RequestedScopes: expandRequestedScopes(d), @@ -100,6 +101,7 @@ func FlattenFederatedSettingsIdentityProvider(federatedSettingsIdentityProvider "user_claim": federatedSettingsIdentityProvider[i].UserClaim, "authorization_type": federatedSettingsIdentityProvider[i].AuthorizationType, "description": federatedSettingsIdentityProvider[i].Description, + "idp_type": federatedSettingsIdentityProvider[i].IdpType, } } } diff --git a/internal/service/federatedsettingsidentityprovider/model_federated_settings_identity_provider_test.go b/internal/service/federatedsettingsidentityprovider/model_federated_settings_identity_provider_test.go index 64e3b9dcda..cc79469ee5 100644 --- a/internal/service/federatedsettingsidentityprovider/model_federated_settings_identity_provider_test.go +++ b/internal/service/federatedsettingsidentityprovider/model_federated_settings_identity_provider_test.go @@ -338,6 +338,7 @@ func TestFlattenFederatedSettingsIdentityProvider(t *testing.T) { AssociatedOrgs: &associatedOrgs, AudienceUri: &audienceURI, DisplayName: &displayName, + IdpType: conversion.StringPtr(federatedsettingsidentityprovider.WORKFORCE), IssuerUri: &issuerURI, OktaIdpId: oktaIdpID, PemFileInfo: &pemFileInfo, @@ -375,6 +376,7 @@ func TestFlattenFederatedSettingsIdentityProvider(t *testing.T) { "user_claim": nilStringPtr, "description": &description, "authorization_type": nilStringPtr, + "idp_type": conversion.StringPtr(federatedsettingsidentityprovider.WORKFORCE), }, }, }, @@ -395,6 +397,7 @@ func TestFlattenFederatedSettingsIdentityProvider(t *testing.T) { UserClaim: &userClaim, Description: &description, AuthorizationType: &authorizationType, + IdpType: conversion.StringPtr(federatedsettingsidentityprovider.WORKFORCE), }, }, output: []map[string]any{ @@ -421,6 +424,7 @@ func TestFlattenFederatedSettingsIdentityProvider(t *testing.T) { "user_claim": &userClaim, "description": &description, "authorization_type": &authorizationType, + "idp_type": conversion.StringPtr(federatedsettingsidentityprovider.WORKFORCE), }, }, }, diff --git a/internal/service/federatedsettingsidentityprovider/resource_federated_settings_identity_provider.go b/internal/service/federatedsettingsidentityprovider/resource_federated_settings_identity_provider.go index 7ecb1a7a36..02cf21f757 100644 --- a/internal/service/federatedsettingsidentityprovider/resource_federated_settings_identity_provider.go +++ b/internal/service/federatedsettingsidentityprovider/resource_federated_settings_identity_provider.go @@ -111,6 +111,11 @@ func Resource() *schema.Resource { Type: schema.TypeString, Optional: true, }, + "idp_type": { + Type: schema.TypeString, + Optional: true, // Required for OIDC IdPs + Computed: true, // If not set for SAML IdPs, it will return WORKFORCE + }, }, } } @@ -230,6 +235,9 @@ func resourceRead(ctx context.Context, d *schema.ResourceData, meta any) diag.Di if err := d.Set("authorization_type", federatedSettingsIdentityProvider.AuthorizationType); err != nil { return diag.FromErr(fmt.Errorf("error setting authorization_type (%s): %s", d.Id(), err)) } + if err := d.Set("idp_type", federatedSettingsIdentityProvider.IdpType); err != nil { + return diag.FromErr(fmt.Errorf("error setting idp_type (%s): %s", d.Id(), err)) + } d.SetId(encodeStateID(federationSettingsID, federatedSettingsIdentityProvider.Id)) @@ -312,10 +320,17 @@ func resourceUpdate(ctx context.Context, d *schema.ResourceData, meta any) diag. if d.HasChange("authorization_type") { updateRequest.AuthorizationType = conversion.StringPtr(d.Get("authorization_type").(string)) } + if d.HasChange("idp_type") { + updateRequest.IdpType = conversion.StringPtr(d.Get("idp_type").(string)) + } if d.HasChange("groups_claim") { groupsClaim := d.Get("groups_claim").(string) - updateRequest.GroupsClaim = &groupsClaim + if groupsClaim == "" { + updateRequest.GroupsClaim = nil + } else { + updateRequest.GroupsClaim = &groupsClaim + } } if d.HasChange("requested_scopes") { diff --git a/internal/service/federatedsettingsidentityprovider/resource_federated_settings_identity_provider_test.go b/internal/service/federatedsettingsidentityprovider/resource_federated_settings_identity_provider_test.go index fa7fdd19ac..280dd433b6 100644 --- a/internal/service/federatedsettingsidentityprovider/resource_federated_settings_identity_provider_test.go +++ b/internal/service/federatedsettingsidentityprovider/resource_federated_settings_identity_provider_test.go @@ -13,6 +13,14 @@ import ( "github.com/mongodb/terraform-provider-mongodbatlas/internal/testutil/acc" ) +var ( + authTypeGroup = "GROUP" + authTypeUser = "USER" + resourceName = "mongodbatlas_federated_settings_identity_provider.test" + dataSourceName = "data.mongodbatlas_federated_settings_identity_provider.test" + dataSourcePluralName = "data.mongodbatlas_federated_settings_identity_providers.test" +) + func TestAccFederatedSettingsIdentityProvider_createError(t *testing.T) { resource.ParallelTest(t, resource.TestCase{ ProtoV6ProviderFactories: acc.TestAccProviderV6Factories, @@ -31,15 +39,18 @@ func TestAccFederatedSettingsIdentityProviderRS_basic(t *testing.T) { resource.ParallelTest(t, *basicSAMLTestCase(t)) } -func TestAccFederatedSettingsIdentityProviderRS_OIDCWorkforce(t *testing.T) { +func TestAccFederatedSettingsIdentityProvider_OIDCWorkforce(t *testing.T) { resource.ParallelTest(t, *basicOIDCWorkforceTestCase(t)) } +func TestAccFederatedSettingsIdentityProvider_OIDCWorkload(t *testing.T) { + resource.ParallelTest(t, *basicOIDCWorkloadTestCase(t)) +} + func basicSAMLTestCase(tb testing.TB) *resource.TestCase { tb.Helper() var ( - resourceName = "mongodbatlas_federated_settings_identity_provider.test" federationSettingsID = os.Getenv("MONGODB_ATLAS_FEDERATION_SETTINGS_ID") idpID = os.Getenv("MONGODB_ATLAS_FEDERATED_IDP_ID") ssoURL = os.Getenv("MONGODB_ATLAS_FEDERATED_SSO_URL") @@ -83,12 +94,10 @@ func basicOIDCWorkforceTestCase(tb testing.TB) *resource.TestCase { tb.Helper() var ( - resourceName = "mongodbatlas_federated_settings_identity_provider.test" - dataSourceName = "data.mongodbatlas_federated_settings_identity_provider.test" federationSettingsID = os.Getenv("MONGODB_ATLAS_FEDERATION_SETTINGS_ID") associatedDomain = os.Getenv("MONGODB_ATLAS_FEDERATED_SETTINGS_ASSOCIATED_DOMAIN") - audience1 = "audience" - audience2 = "audience-updated" + audience1 = "audience-workforce" + audience2 = "audience-workforce-updated" description1 = "tf-acc-test" description2 = "tf-acc-test-updated" attrMapCheck = map[string]string{ @@ -103,6 +112,7 @@ func basicOIDCWorkforceTestCase(tb testing.TB) *resource.TestCase { "protocol": "OIDC", "requested_scopes.0": "profiles", "user_claim": "sub", + "idp_type": federatedsettingsidentityprovider.WORKFORCE, } ) checks := []resource.TestCheckFunc{checkExistsManaged(resourceName)} @@ -138,6 +148,74 @@ func basicOIDCWorkforceTestCase(tb testing.TB) *resource.TestCase { } } +func basicOIDCWorkloadTestCase(tb testing.TB) *resource.TestCase { + tb.Helper() + + var ( + federationSettingsID = os.Getenv("MONGODB_ATLAS_FEDERATION_SETTINGS_ID") + audience1 = "audience" + audience2 = "audience-updated" + description1 = "tf-acc-test" + description2 = "tf-acc-test-updated" + attrMapCheckGroup = map[string]string{ + "audience": audience1, + "authorization_type": authTypeGroup, + "description": description1, + "federation_settings_id": federationSettingsID, + "groups_claim": "groups", + "issuer_uri": "https://token.actions.githubusercontent.com", + "idp_type": federatedsettingsidentityprovider.WORKLOAD, + "protocol": "OIDC", + } + attrMapCheckUser = map[string]string{ + "audience": audience2, + "authorization_type": authTypeUser, + "description": description2, + "federation_settings_id": federationSettingsID, + "issuer_uri": "https://token.actions.githubusercontent.com", + "idp_type": federatedsettingsidentityprovider.WORKLOAD, + "protocol": "OIDC", + "user_claim": "sub", + } + ) + nameChecks := []resource.TestCheckFunc{ + checkExistsManaged(resourceName), + resource.TestCheckResourceAttr(resourceName, "name", "OIDC-workload-CRUD"), + resource.TestCheckResourceAttr(dataSourceName, "display_name", "OIDC-workload-CRUD"), + resource.TestCheckResourceAttr(dataSourcePluralName, "results.0.display_name", "OIDC-workload-CRUD"), + resource.TestCheckResourceAttr(dataSourcePluralName, "results.#", "1"), + } + checks := acc.AddAttrChecks(resourceName, nameChecks, attrMapCheckGroup) + checks = acc.AddAttrChecks(dataSourceName, checks, attrMapCheckGroup) + checks = acc.AddAttrChecksPrefix(dataSourcePluralName, checks, attrMapCheckGroup, "results.0", "federation_settings_id") + + checks2 := acc.AddAttrChecks(resourceName, nameChecks, attrMapCheckUser) + checks2 = acc.AddAttrChecks(dataSourceName, checks2, attrMapCheckUser) + checks2 = acc.AddAttrChecksPrefix(dataSourcePluralName, checks2, attrMapCheckUser, "results.0", "federation_settings_id") + + return &resource.TestCase{ + PreCheck: func() { acc.PreCheckFederatedSettingsIdentityProvider(tb) }, + ProtoV6ProviderFactories: acc.TestAccProviderV6Factories, + Steps: []resource.TestStep{ + { + Config: configOIDCWorkloadBasic(federationSettingsID, description1, audience1, authTypeGroup), + Check: resource.ComposeAggregateTestCheckFunc(checks...), + }, + { + Config: configOIDCWorkloadBasic(federationSettingsID, description2, audience2, authTypeUser), + Check: resource.ComposeAggregateTestCheckFunc(checks2...), + }, + { + Config: configOIDCWorkloadBasic(federationSettingsID, description2, audience2, authTypeUser), + ResourceName: resourceName, + ImportStateIdFunc: importStateIDFuncManaged(resourceName), + ImportState: true, + ImportStateVerify: true, + }, + }, + } +} + func checkExists(resourceName, idpID string) resource.TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[resourceName] @@ -232,6 +310,7 @@ func configOIDCWorkforceBasic(federationSettingsID, associatedDomain, descriptio protocol = "OIDC" requested_scopes = ["profiles"] user_claim = "sub" + idp_type = "WORKFORCE" } data "mongodbatlas_federated_settings_identity_provider" "test" { @@ -239,3 +318,35 @@ func configOIDCWorkforceBasic(federationSettingsID, associatedDomain, descriptio identity_provider_id = mongodbatlas_federated_settings_identity_provider.test.idp_id }`, federationSettingsID, audience, associatedDomain, description) } + +func configOIDCWorkloadBasic(federationSettingsID, description, audience, authorizationType string) string { + groupsClaimRaw := `"groups"` + if authorizationType == authTypeUser { + groupsClaimRaw = `null` + } + return fmt.Sprintf(` + resource "mongodbatlas_federated_settings_identity_provider" "test" { + federation_settings_id = %[1]q + audience = %[2]q + authorization_type = %[5]q + description = %[3]q + issuer_uri = "https://token.actions.githubusercontent.com" + idp_type = %[4]q + name = "OIDC-workload-CRUD" + protocol = "OIDC" + groups_claim = %[6]s + user_claim = "sub" + } + + data "mongodbatlas_federated_settings_identity_provider" "test" { + federation_settings_id = mongodbatlas_federated_settings_identity_provider.test.federation_settings_id + identity_provider_id = mongodbatlas_federated_settings_identity_provider.test.idp_id + } + data "mongodbatlas_federated_settings_identity_providers" "test" { + federation_settings_id = mongodbatlas_federated_settings_identity_provider.test.federation_settings_id + idp_types = [%[4]q] + protocols = [%[7]q] + depends_on = [mongodbatlas_federated_settings_identity_provider.test] + } + `, federationSettingsID, audience, description, federatedsettingsidentityprovider.WORKLOAD, authorizationType, groupsClaimRaw, federatedsettingsidentityprovider.OIDC) +} diff --git a/internal/testutil/acc/attribute_checks.go b/internal/testutil/acc/attribute_checks.go index 149cfee6d2..c0e19fb1ce 100644 --- a/internal/testutil/acc/attribute_checks.go +++ b/internal/testutil/acc/attribute_checks.go @@ -5,7 +5,9 @@ import ( "fmt" "reflect" "regexp" + "slices" "strconv" + "strings" "github.com/hashicorp/terraform-plugin-testing/helper/resource" ) @@ -84,3 +86,18 @@ func AddAttrChecks(targetName string, checks []resource.TestCheckFunc, mapChecks } return newChecks } + +func AddAttrChecksPrefix(targetName string, checks []resource.TestCheckFunc, mapChecks map[string]string, prefix string, skipNames ...string) []resource.TestCheckFunc { + // avoids accidentally modifying existing slice + newChecks := make([]resource.TestCheckFunc, len(checks), len(checks)+len(mapChecks)) + copy(newChecks, checks) + prefix, _ = strings.CutSuffix(prefix, ".") + for key, value := range mapChecks { + if slices.Contains(skipNames, key) { + continue + } + keyWithPrefix := fmt.Sprintf("%s.%s", prefix, key) + newChecks = append(newChecks, resource.TestCheckResourceAttr(targetName, keyWithPrefix, value)) + } + return newChecks +} diff --git a/website/docs/guides/1.17.0-upgrade-guide.html.markdown b/website/docs/guides/1.17.0-upgrade-guide.html.markdown index 4cba8b405d..937a4a6851 100644 --- a/website/docs/guides/1.17.0-upgrade-guide.html.markdown +++ b/website/docs/guides/1.17.0-upgrade-guide.html.markdown @@ -12,7 +12,8 @@ The Terraform MongoDB Atlas Provider version 1.17.0 has a number of new and exci **New Resources, Data Sources, and Features:** -- You can now Create and Delete [MongoDB Atlas OIDC Workforce identity providers](https://www.mongodb.com/docs/atlas/security-oidc/#configure-oidc-authorization) with `mongodbatlas_federated_settings_identity_provider` [resource](https://registry.terraform.io/providers/mongodb/mongodbatlas/latest/docs/resources/federated_settings_identity_provider). +- You can now Create and Delete [MongoDB Atlas OIDC Workforce identity providers](https://www.mongodb.com/docs/atlas/workforce-oidc/) with `mongodbatlas_federated_settings_identity_provider` [resource](https://registry.terraform.io/providers/mongodb/mongodbatlas/latest/docs/resources/federated_settings_identity_provider). +- You can now use [MongoDB Atlas OIDC Workload identity providers](https://www.mongodb.com/docs/atlas/workload-oidc/) with `mongodbatlas_federated_settings_identity_provider` [resource](https://registry.terraform.io/providers/mongodb/mongodbatlas/latest/docs/resources/federated_settings_identity_provider), [`mongodbatlas_federated_settings_identity_provider`](https://registry.terraform.io/providers/mongodb/mongodbatlas/latest/docs/data-sources/federated_settings_identity_provider) and [`mongodbatlas_federated_settings_identity_providers`](https://registry.terraform.io/providers/mongodb/mongodbatlas/latest/docs/data-sources/federated_settings_identity_providers) data sources. **Breaking Changes:**