diff --git a/internal/provider/provider_sdk2.go b/internal/provider/provider_sdk2.go index c65de103c8..ee4cf6bfd3 100644 --- a/internal/provider/provider_sdk2.go +++ b/internal/provider/provider_sdk2.go @@ -175,7 +175,6 @@ func getDataSourcesMap() map[string]*schema.Resource { "mongodbatlas_privatelink_endpoints_service_serverless": privatelinkendpointserviceserverless.PluralDataSource(), "mongodbatlas_third_party_integration": thirdpartyintegration.DataSource(), "mongodbatlas_third_party_integrations": thirdpartyintegration.PluralDataSource(), - "mongodbatlas_cloud_provider_access": cloudprovideraccess.DataSource(), "mongodbatlas_cloud_provider_access_setup": cloudprovideraccess.DataSourceSetup(), "mongodbatlas_custom_dns_configuration_cluster_aws": customdnsconfigurationclusteraws.DataSource(), "mongodbatlas_online_archive": onlinearchive.DataSource(), @@ -253,7 +252,6 @@ func getResourcesMap() map[string]*schema.Resource { "mongodbatlas_custom_dns_configuration_cluster_aws": customdnsconfigurationclusteraws.Resource(), "mongodbatlas_ldap_configuration": ldapconfiguration.Resource(), "mongodbatlas_ldap_verify": ldapverify.Resource(), - "mongodbatlas_cloud_provider_access": cloudprovideraccess.Resource(), "mongodbatlas_cloud_provider_access_setup": cloudprovideraccess.ResourceSetup(), "mongodbatlas_cloud_provider_access_authorization": cloudprovideraccess.ResourceAuthorization(), "mongodbatlas_search_index": searchindex.Resource(), diff --git a/internal/service/cloudprovideraccess/data_source_cloud_provider_access.go b/internal/service/cloudprovideraccess/data_source_cloud_provider_access.go deleted file mode 100644 index ab726bf487..0000000000 --- a/internal/service/cloudprovideraccess/data_source_cloud_provider_access.go +++ /dev/null @@ -1,159 +0,0 @@ -package cloudprovideraccess - -import ( - "context" - "fmt" - - "github.com/hashicorp/terraform-plugin-sdk/v2/diag" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/id" - "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/config" - matlas "go.mongodb.org/atlas/mongodbatlas" -) - -func DataSource() *schema.Resource { - return &schema.Resource{ - ReadContext: dataSourceMongoDBAtlasCloudProviderAccessRead, - DeprecationMessage: fmt.Sprintf(constant.DeprecationResourceByDateWithReplacement, "v1.14.0", "mongodbatlas_cloud_provider_access_setup"), - Schema: map[string]*schema.Schema{ - "project_id": { - Type: schema.TypeString, - Required: true, - }, - "aws_iam_roles": { - Type: schema.TypeList, - Elem: dataSourceMongoDBAtlasCloudProviderAccess(), - Computed: true, - }, - }, - } -} - -func dataSourceMongoDBAtlasCloudProviderAccess() *schema.Resource { - return &schema.Resource{ - Schema: map[string]*schema.Schema{ - "atlas_aws_account_arn": { - Type: schema.TypeString, - Computed: true, - }, - "atlas_assumed_role_external_id": { - Type: schema.TypeString, - Computed: true, - }, - "authorized_date": { - Type: schema.TypeString, - Computed: true, - }, - "created_date": { - Type: schema.TypeString, - Computed: true, - }, - "iam_assumed_role_arn": { - Type: schema.TypeString, - Computed: true, - }, - "provider_name": { - Type: schema.TypeString, - Computed: true, - }, - "role_id": { - Type: schema.TypeString, - Computed: true, - }, - "feature_usages": { - Type: schema.TypeList, - Elem: featureUsagesSchema(), - Computed: true, - }, - }, - } -} - -func featureUsagesSchema() *schema.Resource { - return &schema.Resource{ - Schema: map[string]*schema.Schema{ - "feature_type": { - Type: schema.TypeString, - Computed: true, - }, - "feature_id": { - Type: schema.TypeMap, - Computed: true, - }, - }, - } -} - -func dataSourceMongoDBAtlasCloudProviderAccessRead(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics { - conn := meta.(*config.MongoDBClient).Atlas - projectID := d.Get("project_id").(string) - - roles, _, err := conn.CloudProviderAccess.ListRoles(ctx, projectID) - - if err != nil { - return diag.FromErr(fmt.Errorf(ErrorCloudProviderGetRead, err)) - } - - if err = d.Set("aws_iam_roles", flatCloudProviderAccessRolesAWS(roles)); err != nil { - return diag.FromErr(fmt.Errorf(ErrorCloudProviderGetRead, err)) - } - - d.SetId(id.UniqueId()) - - return nil -} - -func flatCloudProviderAccessRolesAWS(roles *matlas.CloudProviderAccessRoles) (list []map[string]any) { - list = make([]map[string]any, 0, len(roles.AWSIAMRoles)) - for i := range roles.AWSIAMRoles { - role := &(roles.AWSIAMRoles[i]) - list = append(list, roleToSchemaAWS(role)) - } - - return list -} - -func roleToSchemaAWS(role *matlas.CloudProviderAccessRole) map[string]any { - out := map[string]any{ - "atlas_aws_account_arn": role.AtlasAWSAccountARN, - "atlas_assumed_role_external_id": role.AtlasAssumedRoleExternalID, - "authorized_date": role.AuthorizedDate, - "created_date": role.CreatedDate, - "iam_assumed_role_arn": role.IAMAssumedRoleARN, - "provider_name": role.ProviderName, - "role_id": role.RoleID, - } - - features := make([]map[string]any, 0, len(role.FeatureUsages)) - - for _, featureUsage := range role.FeatureUsages { - features = append(features, featureToSchema(featureUsage)) - } - - out["feature_usages"] = features - - return out -} - -func featureToSchema(feature *matlas.FeatureUsage) map[string]any { - return map[string]any{ - "feature_type": feature.FeatureType, - "feature_id": feature.FeatureID, - } -} - -func featureUsagesSchemaV0() *schema.Resource { - return &schema.Resource{ - Schema: map[string]*schema.Schema{ - "feature_type": { - Type: schema.TypeString, - Computed: true, - }, - "feature_id": { - Type: schema.TypeString, - Computed: true, - }, - }, - } -} diff --git a/internal/service/cloudprovideraccess/resource_cloud_provider_access.go b/internal/service/cloudprovideraccess/resource_cloud_provider_access.go deleted file mode 100644 index 079b1710a6..0000000000 --- a/internal/service/cloudprovideraccess/resource_cloud_provider_access.go +++ /dev/null @@ -1,316 +0,0 @@ -package cloudprovideraccess - -import ( - "context" - "fmt" - "net/http" - "regexp" - - "github.com/hashicorp/terraform-plugin-sdk/v2/diag" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" - "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" - matlas "go.mongodb.org/atlas/mongodbatlas" -) - -const ( - errorCloudProviderAccessCreate = "error creating cloud provider access %s" - errorCloudProviderAccessUpdate = "error updating cloud provider access %s" - errorCloudProviderAccessDelete = "error deleting cloud provider access %s" - errorCloudProviderAccessImporter = "error importing cloud provider access %s" - ErrorCloudProviderGetRead = "error reading cloud provider access %s" -) - -func Resource() *schema.Resource { - return &schema.Resource{ - CreateContext: resourceMongoDBAtlasCloudProviderAccessCreate, - ReadContext: resourceMongoDBAtlasCloudProviderAccessRead, - UpdateContext: resourceMongoDBAtlasCloudProviderAccessUpdate, - DeleteContext: resourceMongoDBAtlasCloudProviderAccessDelete, - Importer: &schema.ResourceImporter{ - StateContext: resourceMongoDBAtlasCloudProviderAccessImportState, - }, - DeprecationMessage: fmt.Sprintf(constant.DeprecationResourceByDateWithReplacement, "v1.14.0", "mongodbatlas_cloud_provider_access_setup and mongodbatlas_cloud_provider_access_authorization"), - Schema: map[string]*schema.Schema{ - "project_id": { - Type: schema.TypeString, - Required: true, - }, - "provider_name": { - Type: schema.TypeString, - Required: true, - ValidateFunc: validation.StringInSlice([]string{"AWS"}, false), - }, - "atlas_aws_account_arn": { - Type: schema.TypeString, - Computed: true, - }, - "atlas_assumed_role_external_id": { - Type: schema.TypeString, - Computed: true, - }, - "authorized_date": { - Type: schema.TypeString, - Computed: true, - }, - "created_date": { - Type: schema.TypeString, - Computed: true, - }, - "iam_assumed_role_arn": { - Type: schema.TypeString, - Optional: true, - Computed: true, - }, - "role_id": { - Type: schema.TypeString, - Computed: true, - }, - "feature_usages": { - Type: schema.TypeList, - Elem: featureUsagesSchema(), - Computed: true, - }, - }, - SchemaVersion: 1, - StateUpgraders: []schema.StateUpgrader{ - { - Type: resourceMongoDBAtlasCloudProviderAccessV0().CoreConfigSchema().ImpliedType(), - Upgrade: resourceMongoDBAtlasCloudProviderAccessStateUpgradeV0, - Version: 0, - }, - }, - } -} - -func resourceMongoDBAtlasCloudProviderAccessCreate(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics { - projectID := d.Get("project_id").(string) - - conn := meta.(*config.MongoDBClient).Atlas - - requestParameters := &matlas.CloudProviderAccessRoleRequest{ - ProviderName: d.Get("provider_name").(string), - } - - role, _, err := conn.CloudProviderAccess.CreateRole(ctx, projectID, requestParameters) - - if err != nil { - return diag.FromErr(fmt.Errorf(errorCloudProviderAccessCreate, err)) - } - - roleSchema := roleToSchema(role) - - d.SetId(conversion.EncodeStateID(map[string]string{ - "id": role.RoleID, - "project_id": projectID, - "provider_name": role.ProviderName, - })) - - for key, val := range roleSchema { - if err := d.Set(key, val); err != nil { - return diag.FromErr(fmt.Errorf(errorCloudProviderAccessCreate, err)) - } - } - - return nil -} - -func resourceMongoDBAtlasCloudProviderAccessRead(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics { - // sadly there is no just get API - conn := meta.(*config.MongoDBClient).Atlas - ids := conversion.DecodeStateID(d.Id()) - projectID := ids["project_id"] - roleID := ids["id"] - - role, resp, err := conn.CloudProviderAccess.GetRole(context.Background(), projectID, roleID) - if err != nil { - if resp != nil && resp.StatusCode == http.StatusNotFound { - d.SetId("") - return nil - } - - return diag.FromErr(fmt.Errorf(ErrorCloudProviderGetRead, err)) - } - - roleSchema := roleToSchema(role) - for key, val := range roleSchema { - if err := d.Set(key, val); err != nil { - return diag.FromErr(fmt.Errorf(ErrorCloudProviderGetRead, err)) - } - } - - return nil -} - -func resourceMongoDBAtlasCloudProviderAccessUpdate(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics { - conn := meta.(*config.MongoDBClient).Atlas - ids := conversion.DecodeStateID(d.Id()) - - projectID := ids["project_id"] - roleID := ids["id"] - - if d.HasChanges("provider_name", "iam_assumed_role_arn") { - req := &matlas.CloudProviderAccessRoleRequest{ - ProviderName: d.Get("provider_name").(string), - IAMAssumedRoleARN: conversion.Pointer(d.Get("iam_assumed_role_arn").(string)), - } - - role, _, err := conn.CloudProviderAccess.AuthorizeRole(ctx, projectID, roleID, req) - if err != nil { - return diag.FromErr(fmt.Errorf(errorCloudProviderAccessUpdate, err)) - } - - roleSchema := roleToSchema(role) - - for key, val := range roleSchema { - if err := d.Set(key, val); err != nil { - return diag.FromErr(fmt.Errorf(ErrorCloudProviderGetRead, err)) - } - } - } - - return nil -} - -func resourceMongoDBAtlasCloudProviderAccessDelete(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics { - conn := meta.(*config.MongoDBClient).Atlas - ids := conversion.DecodeStateID(d.Id()) - - projectID := ids["project_id"] - roleID := ids["id"] - providerName := ids["provider_name"] - - req := &matlas.CloudProviderDeauthorizationRequest{ - ProviderName: providerName, - RoleID: roleID, - GroupID: projectID, - } - - _, err := conn.CloudProviderAccess.DeauthorizeRole(ctx, req) - - if err != nil { - return diag.FromErr(fmt.Errorf(errorCloudProviderAccessDelete, err)) - } - - return nil -} - -func resourceMongoDBAtlasCloudProviderAccessImportState(ctx context.Context, d *schema.ResourceData, meta any) ([]*schema.ResourceData, error) { - projectID, providerName, roleID, err := splitCloudProviderAccessID(d.Id()) - - if err != nil { - return nil, fmt.Errorf(errorCloudProviderAccessImporter, err) - } - - // searching id in internal format - d.SetId(conversion.EncodeStateID(map[string]string{ - "id": roleID, - "project_id": projectID, - "provider_name": providerName, - })) - - err2 := resourceMongoDBAtlasCloudProviderAccessRead(ctx, d, meta) - - if err2 != nil { - return nil, fmt.Errorf(errorCloudProviderAccessImporter, err) - } - - // case of not found - if d.Id() == "" { - return nil, fmt.Errorf(errorCloudProviderAccessImporter, " Resource not found at the cloud please check your id") - } - - // params syncing - if err = d.Set("project_id", projectID); err != nil { - return nil, fmt.Errorf(errorCloudProviderAccessImporter, err) - } - - return []*schema.ResourceData{d}, nil -} - -// format {project_id}-{provider-name}-{role-id} -func splitCloudProviderAccessID(id string) (projectID, providerName, roleID string, err error) { - var re = regexp.MustCompile(`(?s)^([0-9a-fA-F]{24})-(.*)-(.*)$`) - parts := re.FindStringSubmatch(id) - - if len(parts) != 4 { - err = fmt.Errorf(errorCloudProviderAccessImporter, "format please use {project_id}-{provider-name}-{role-id}") - return - } - - projectID, providerName, roleID = parts[1], parts[2], parts[3] - - return -} - -func resourceMongoDBAtlasCloudProviderAccessV0() *schema.Resource { - return &schema.Resource{ - Schema: map[string]*schema.Schema{ - "project_id": { - Type: schema.TypeString, - Required: true, - }, - "provider_name": { - Type: schema.TypeString, - Required: true, - ValidateFunc: validation.StringInSlice([]string{"AWS"}, false), - }, - "atlas_aws_account_arn": { - Type: schema.TypeString, - Computed: true, - }, - "atlas_assumed_role_external_id": { - Type: schema.TypeString, - Computed: true, - }, - "authorized_date": { - Type: schema.TypeString, - Computed: true, - }, - "created_date": { - Type: schema.TypeString, - Computed: true, - }, - "iam_assumed_role_arn": { - Type: schema.TypeString, - Optional: true, - Computed: true, - }, - "role_id": { - Type: schema.TypeString, - Computed: true, - }, - "feature_usages": { - Type: schema.TypeList, - Elem: featureUsagesSchemaV0(), - Computed: true, - }, - }, - } -} - -func resourceMongoDBAtlasCloudProviderAccessStateUpgradeV0(ctx context.Context, rawState map[string]any, meta any) (map[string]any, error) { - rawState["feature_usages"] = []any{map[string]any{}} - return rawState, nil -} - -func roleToSchema(role *matlas.CloudProviderAccessRole) map[string]any { - out := map[string]any{ - "atlas_aws_account_arn": role.AtlasAWSAccountARN, - "atlas_assumed_role_external_id": role.AtlasAssumedRoleExternalID, - "authorized_date": role.AuthorizedDate, - "created_date": role.CreatedDate, - "iam_assumed_role_arn": role.IAMAssumedRoleARN, - "provider_name": role.ProviderName, - "role_id": role.RoleID, - } - - features := make([]map[string]any, 0, len(role.FeatureUsages)) - for _, featureUsage := range role.FeatureUsages { - features = append(features, featureToSchema(featureUsage)) - } - out["feature_usages"] = features - return out -} diff --git a/internal/service/cloudprovideraccess/resource_cloud_provider_access_authorization.go b/internal/service/cloudprovideraccess/resource_cloud_provider_access_authorization.go index 1e03af0871..c9a31745d8 100644 --- a/internal/service/cloudprovideraccess/resource_cloud_provider_access_authorization.go +++ b/internal/service/cloudprovideraccess/resource_cloud_provider_access_authorization.go @@ -321,3 +321,25 @@ func authorizeRole(ctx context.Context, client *matlas.Client, d *schema.Resourc return nil } + +func featureUsagesSchema() *schema.Resource { + return &schema.Resource{ + Schema: map[string]*schema.Schema{ + "feature_type": { + Type: schema.TypeString, + Computed: true, + }, + "feature_id": { + Type: schema.TypeMap, + Computed: true, + }, + }, + } +} + +func featureToSchema(feature *matlas.FeatureUsage) map[string]any { + return map[string]any{ + "feature_type": feature.FeatureType, + "feature_id": feature.FeatureID, + } +} diff --git a/internal/service/cloudprovideraccess/resource_cloud_provider_access_authorization_test.go b/internal/service/cloudprovideraccess/resource_cloud_provider_access_authorization_test.go index 1359441516..deb0aa2226 100644 --- a/internal/service/cloudprovideraccess/resource_cloud_provider_access_authorization_test.go +++ b/internal/service/cloudprovideraccess/resource_cloud_provider_access_authorization_test.go @@ -1,13 +1,19 @@ package cloudprovideraccess_test import ( + "context" "fmt" "os" "testing" "github.com/hashicorp/terraform-plugin-testing/helper/acctest" "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/terraform" + "github.com/mongodb/terraform-provider-mongodbatlas/internal/common/conversion" + "github.com/mongodb/terraform-provider-mongodbatlas/internal/config" + "github.com/mongodb/terraform-provider-mongodbatlas/internal/service/cloudprovideraccess" "github.com/mongodb/terraform-provider-mongodbatlas/internal/testutil/acc" + matlas "go.mongodb.org/atlas/mongodbatlas" ) func TestAccConfigRSCloudProviderAccessAuthorizationAWS_basic(t *testing.T) { @@ -147,3 +153,38 @@ func testAccMongoDBAtlasCloudProviderAccessAuthorizationAzure(orgID, projectName } `, orgID, projectName, atlasAzureAppID, servicePrincipalID, tenantID) } + +func testAccCheckMongoDBAtlasProviderAccessDestroy(s *terraform.State) error { + conn := acc.TestAccProviderSdkV2.Meta().(*config.MongoDBClient).Atlas + for _, rs := range s.RootModule().Resources { + if rs.Type != "mongodbatlas_cloud_provider_access" { + continue + } + + ids := conversion.DecodeStateID(rs.Primary.ID) + + roles, _, err := conn.CloudProviderAccess.ListRoles(context.Background(), ids["project_id"]) + + if err != nil { + return fmt.Errorf(cloudprovideraccess.ErrorCloudProviderGetRead, err) + } + + var targetRole matlas.CloudProviderAccessRole + + // searching in roles + for i := range roles.AWSIAMRoles { + role := &(roles.AWSIAMRoles[i]) + + if role.RoleID == ids["id"] && role.ProviderName == ids["provider_name"] { + targetRole = *role + } + } + + // Found !! + if targetRole.RoleID != "" { + return fmt.Errorf("error cloud Provider Access Role (%s) still exists", ids["id"]) + } + } + + return nil +} diff --git a/internal/service/cloudprovideraccess/resource_cloud_provider_access_setup.go b/internal/service/cloudprovideraccess/resource_cloud_provider_access_setup.go index 005575acb9..1f831a7589 100644 --- a/internal/service/cloudprovideraccess/resource_cloud_provider_access_setup.go +++ b/internal/service/cloudprovideraccess/resource_cloud_provider_access_setup.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "net/http" + "regexp" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" @@ -20,6 +21,14 @@ import ( -> The delete deletes and deauthorize the role */ +const ( + errorCloudProviderAccessCreate = "error creating cloud provider access %s" + errorCloudProviderAccessUpdate = "error updating cloud provider access %s" + errorCloudProviderAccessDelete = "error deleting cloud provider access %s" + errorCloudProviderAccessImporter = "error importing cloud provider access %s" + ErrorCloudProviderGetRead = "error reading cloud provider access %s" +) + func ResourceSetup() *schema.Resource { return &schema.Resource{ ReadContext: resourceMongoDBAtlasCloudProviderAccessSetupRead, @@ -266,3 +275,18 @@ func resourceMongoDBAtlasCloudProviderAccessSetupImportState(ctx context.Context return []*schema.ResourceData{d}, nil } + +// format {project_id}-{provider-name}-{role-id} +func splitCloudProviderAccessID(id string) (projectID, providerName, roleID string, err error) { + var re = regexp.MustCompile(`(?s)^([0-9a-fA-F]{24})-(.*)-(.*)$`) + parts := re.FindStringSubmatch(id) + + if len(parts) != 4 { + err = fmt.Errorf(errorCloudProviderAccessImporter, "format please use {project_id}-{provider-name}-{role-id}") + return + } + + projectID, providerName, roleID = parts[1], parts[2], parts[3] + + return +} diff --git a/internal/service/cloudprovideraccess/resource_cloud_provider_access_setup_test.go b/internal/service/cloudprovideraccess/resource_cloud_provider_access_setup_test.go index fc506f793c..033dcd49f6 100644 --- a/internal/service/cloudprovideraccess/resource_cloud_provider_access_setup_test.go +++ b/internal/service/cloudprovideraccess/resource_cloud_provider_access_setup_test.go @@ -1,12 +1,17 @@ package cloudprovideraccess_test import ( + "context" "fmt" "os" "testing" "github.com/hashicorp/terraform-plugin-testing/helper/acctest" "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/terraform" + "github.com/mongodb/terraform-provider-mongodbatlas/internal/common/conversion" + "github.com/mongodb/terraform-provider-mongodbatlas/internal/config" + "github.com/mongodb/terraform-provider-mongodbatlas/internal/service/cloudprovideraccess" "github.com/mongodb/terraform-provider-mongodbatlas/internal/testutil/acc" matlas "go.mongodb.org/atlas/mongodbatlas" ) @@ -156,3 +161,61 @@ func testAccMongoDBAtlasCloudProviderAccessSetupAzure(orgID, projectName, atlasA } `, orgID, projectName, atlasAzureAppID, servicePrincipalID, tenantID) } + +func testAccCheckMongoDBAtlasProviderAccessExists(resourceName string, targetRole *matlas.CloudProviderAccessRole) resource.TestCheckFunc { + return func(s *terraform.State) error { + conn := acc.TestAccProviderSdkV2.Meta().(*config.MongoDBClient).Atlas + + rs, ok := s.RootModule().Resources[resourceName] + if !ok { + return fmt.Errorf("not found: %s", resourceName) + } + + if rs.Primary.Attributes["project_id"] == "" { + return fmt.Errorf("no ID is set") + } + + ids := conversion.DecodeStateID(rs.Primary.ID) + providerName := ids["provider_name"] + id := ids["id"] + + roles, _, err := conn.CloudProviderAccess.ListRoles(context.Background(), ids["project_id"]) + + if err != nil { + return fmt.Errorf(cloudprovideraccess.ErrorCloudProviderGetRead, err) + } + + if providerName == "AWS" { + for i := range roles.AWSIAMRoles { + if roles.AWSIAMRoles[i].RoleID == id && roles.AWSIAMRoles[i].ProviderName == providerName { + *targetRole = roles.AWSIAMRoles[i] + return nil + } + } + } + + if providerName == "AZURE" { + for i := range roles.AzureServicePrincipals { + if *roles.AzureServicePrincipals[i].AzureID == id && roles.AzureServicePrincipals[i].ProviderName == providerName { + *targetRole = roles.AzureServicePrincipals[i] + return nil + } + } + } + + return fmt.Errorf("error cloud Provider Access (%s) does not exist", ids["project_id"]) + } +} + +func testAccCheckMongoDBAtlasCloudProviderAccessImportStateIDFunc(resourceName string) resource.ImportStateIdFunc { + return func(s *terraform.State) (string, error) { + rs, ok := s.RootModule().Resources[resourceName] + if !ok { + return "", fmt.Errorf("not found: %s", resourceName) + } + + ids := conversion.DecodeStateID(rs.Primary.ID) + + return fmt.Sprintf("%s-%s-%s", ids["project_id"], ids["provider_name"], ids["id"]), nil + } +} diff --git a/internal/service/cloudprovideraccess/resource_cloud_provider_access_test.go b/internal/service/cloudprovideraccess/resource_cloud_provider_access_test.go deleted file mode 100644 index 7559a36279..0000000000 --- a/internal/service/cloudprovideraccess/resource_cloud_provider_access_test.go +++ /dev/null @@ -1,190 +0,0 @@ -package cloudprovideraccess_test - -import ( - "context" - "fmt" - "os" - "testing" - - "github.com/hashicorp/terraform-plugin-testing/helper/acctest" - "github.com/hashicorp/terraform-plugin-testing/helper/resource" - "github.com/hashicorp/terraform-plugin-testing/terraform" - "github.com/mongodb/terraform-provider-mongodbatlas/internal/common/conversion" - "github.com/mongodb/terraform-provider-mongodbatlas/internal/config" - "github.com/mongodb/terraform-provider-mongodbatlas/internal/service/cloudprovideraccess" - "github.com/mongodb/terraform-provider-mongodbatlas/internal/testutil/acc" - matlas "go.mongodb.org/atlas/mongodbatlas" -) - -func TestAccConfigRSCloudProviderAccessAWS_basic(t *testing.T) { - var ( - resourceName = "mongodbatlas_cloud_provider_access.test" - dataSourceName = "data.mongodbatlas_cloud_provider_access.test" - orgID = os.Getenv("MONGODB_ATLAS_ORG_ID") - projectName = acctest.RandomWithPrefix("test-acc") - targetRole = matlas.CloudProviderAccessRole{} - ) - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acc.PreCheckBasic(t) }, - ProtoV6ProviderFactories: acc.TestAccProviderV6Factories, - Steps: []resource.TestStep{ - { - Config: testAccMongoDBAtlasCloudProviderAccessAWS(orgID, projectName), - Check: resource.ComposeTestCheckFunc( - testAccCheckMongoDBAtlasProviderAccessExists(resourceName, &targetRole), - resource.TestCheckResourceAttrSet(resourceName, "atlas_assumed_role_external_id"), - resource.TestCheckResourceAttrSet(resourceName, "atlas_aws_account_arn"), - resource.TestCheckResourceAttrSet(dataSourceName, "aws_iam_roles.0.atlas_assumed_role_external_id"), - resource.TestCheckResourceAttrSet(dataSourceName, "aws_iam_roles.0.atlas_aws_account_arn"), - resource.TestCheckResourceAttrSet(dataSourceName, "aws_iam_roles.0.created_date"), - resource.TestCheckResourceAttrSet(dataSourceName, "aws_iam_roles.0.provider_name"), - resource.TestCheckResourceAttrSet(dataSourceName, "aws_iam_roles.0.role_id"), - resource.TestCheckResourceAttrSet(dataSourceName, "aws_iam_roles.0.created_date"), - ), - }, - }, - }, - ) -} - -func TestAccConfigRSCloudProviderAccess_importBasic(t *testing.T) { - var ( - resourceName = "mongodbatlas_cloud_provider_access.test" - orgID = os.Getenv("MONGODB_ATLAS_ORG_ID") - projectName = acctest.RandomWithPrefix("test-acc") - targetRole = matlas.CloudProviderAccessRole{} - ) - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acc.PreCheckBasic(t) }, - ProtoV6ProviderFactories: acc.TestAccProviderV6Factories, - Steps: []resource.TestStep{ - { - Config: testAccMongoDBAtlasCloudProviderAccessAWS(orgID, projectName), - Check: resource.ComposeTestCheckFunc( - testAccCheckMongoDBAtlasProviderAccessExists(resourceName, &targetRole), - resource.TestCheckResourceAttrSet(resourceName, "atlas_assumed_role_external_id"), - resource.TestCheckResourceAttrSet(resourceName, "atlas_aws_account_arn"), - ), - }, - { - ResourceName: resourceName, - ImportStateIdFunc: testAccCheckMongoDBAtlasCloudProviderAccessImportStateIDFunc(resourceName), - ImportState: true, - ImportStateVerify: true, - }, - }, - }, - ) -} - -func testAccCheckMongoDBAtlasCloudProviderAccessImportStateIDFunc(resourceName string) resource.ImportStateIdFunc { - return func(s *terraform.State) (string, error) { - rs, ok := s.RootModule().Resources[resourceName] - if !ok { - return "", fmt.Errorf("not found: %s", resourceName) - } - - ids := conversion.DecodeStateID(rs.Primary.ID) - - return fmt.Sprintf("%s-%s-%s", ids["project_id"], ids["provider_name"], ids["id"]), nil - } -} - -func testAccCheckMongoDBAtlasProviderAccessDestroy(s *terraform.State) error { - conn := acc.TestAccProviderSdkV2.Meta().(*config.MongoDBClient).Atlas - for _, rs := range s.RootModule().Resources { - if rs.Type != "mongodbatlas_cloud_provider_access" { - continue - } - - ids := conversion.DecodeStateID(rs.Primary.ID) - - roles, _, err := conn.CloudProviderAccess.ListRoles(context.Background(), ids["project_id"]) - - if err != nil { - return fmt.Errorf(cloudprovideraccess.ErrorCloudProviderGetRead, err) - } - - var targetRole matlas.CloudProviderAccessRole - - // searching in roles - for i := range roles.AWSIAMRoles { - role := &(roles.AWSIAMRoles[i]) - - if role.RoleID == ids["id"] && role.ProviderName == ids["provider_name"] { - targetRole = *role - } - } - - // Found !! - if targetRole.RoleID != "" { - return fmt.Errorf("error cloud Provider Access Role (%s) still exists", ids["id"]) - } - } - - return nil -} - -func testAccCheckMongoDBAtlasProviderAccessExists(resourceName string, targetRole *matlas.CloudProviderAccessRole) resource.TestCheckFunc { - return func(s *terraform.State) error { - conn := acc.TestAccProviderSdkV2.Meta().(*config.MongoDBClient).Atlas - - rs, ok := s.RootModule().Resources[resourceName] - if !ok { - return fmt.Errorf("not found: %s", resourceName) - } - - if rs.Primary.Attributes["project_id"] == "" { - return fmt.Errorf("no ID is set") - } - - ids := conversion.DecodeStateID(rs.Primary.ID) - providerName := ids["provider_name"] - id := ids["id"] - - roles, _, err := conn.CloudProviderAccess.ListRoles(context.Background(), ids["project_id"]) - - if err != nil { - return fmt.Errorf(cloudprovideraccess.ErrorCloudProviderGetRead, err) - } - - if providerName == "AWS" { - for i := range roles.AWSIAMRoles { - if roles.AWSIAMRoles[i].RoleID == id && roles.AWSIAMRoles[i].ProviderName == providerName { - *targetRole = roles.AWSIAMRoles[i] - return nil - } - } - } - - if providerName == "AZURE" { - for i := range roles.AzureServicePrincipals { - if *roles.AzureServicePrincipals[i].AzureID == id && roles.AzureServicePrincipals[i].ProviderName == providerName { - *targetRole = roles.AzureServicePrincipals[i] - return nil - } - } - } - - return fmt.Errorf("error cloud Provider Access (%s) does not exist", ids["project_id"]) - } -} - -func testAccMongoDBAtlasCloudProviderAccessAWS(orgID, projectName string) string { - return fmt.Sprintf(` - resource "mongodbatlas_project" "test" { - name = %[2]q - org_id = %[1]q - } - resource "mongodbatlas_cloud_provider_access" "test" { - project_id = mongodbatlas_project.test.id - provider_name = "AWS" - } - - data "mongodbatlas_cloud_provider_access" "test" { - project_id = mongodbatlas_cloud_provider_access.test.project_id - } - `, orgID, projectName) -} diff --git a/website/docs/d/cloud_provider_access.markdown b/website/docs/d/cloud_provider_access.markdown deleted file mode 100644 index f3d57036be..0000000000 --- a/website/docs/d/cloud_provider_access.markdown +++ /dev/null @@ -1,52 +0,0 @@ ---- -layout: "mongodbatlas" -page_title: "MongoDB Atlas: mongodbatlas_cloud_provider_access" -sidebar_current: "docs-mongodbatlas-datasource-cloud-provider-access" -description: |- - Allows you to get the list of cloud provider access roles ---- - -**WARNING:** The data source `mongodbatlas_cloud_provider_access` is deprecated and will be removed in version v1.14.0, use the data source `mongodbatlas_cloud_provider_access_setup` instead. - -# Data Source: mongodbatlas_cloud_provider_access - -`mongodbatlas_cloud_provider_access` allows you to get the list of cloud provider access roles, currently only AWS and Azure is supported. - --> **NOTE:** Groups and projects are synonymous terms. You may find `groupId` in the official documentation. - -## Example Usage -```terraform -resource "mongodbatlas_cloud_provider_access" "test_role" { - project_id = "64259ee860c43338194b0f8e" - provider_name = "AWS" -} - -data "mongodbatlas_cloud_provider_access" "all" { - project_id = mongodbatlas_cloud_provider_access.test_role.project_id -} -``` - -## Argument Reference - -* `project_id` - (Required) The unique ID for the project to get all Cloud Provider Access - -## Attributes Reference - -In addition to all arguments above, the following attributes are exported: - -* `id` - Autogenerated Unique ID for this data source. -* `aws_iam_roles` - A list where each represents a Cloud Provider Access Role. - -### Each element in the aws_iam_roles array consists in an object with the following elements - -* `atlas_assumed_role_external_id` - Unique external ID Atlas uses when assuming the IAM role in your AWS account. -* `atlas_aws_account_arn` - ARN associated with the Atlas AWS account used to assume IAM roles in your AWS account. -* `authorized_date` - Date on which this role was authorized. -* `created_date` - Date on which this role was created. -* `feature_usages` - Atlas features this AWS IAM role is linked to. -* `iam_assumed_role_arn` - ARN of the IAM Role that Atlas assumes when accessing resources in your AWS account. -* `provider_name` - Name of the cloud provider. Currently limited to AWS. -* `role_id` - Unique ID of this role. - - -See [MongoDB Atlas API](https://docs.atlas.mongodb.com/reference/api/cloud-provider-access-get-roles/) Documentation for more information. diff --git a/website/docs/r/cloud_provider_access.markdown b/website/docs/r/cloud_provider_access.markdown index 85aaebc842..4b2e65c90a 100644 --- a/website/docs/r/cloud_provider_access.markdown +++ b/website/docs/r/cloud_provider_access.markdown @@ -8,13 +8,11 @@ description: |- # Resource: Cloud Provider Access Configuration Paths -The Terraform MongoDB Atlas Provider offers two either-or/mutually exclusive paths to perform an authorization for a cloud provider role - +The Terraform MongoDB Atlas Provider offers the following path to perform an authorization for a cloud provider role - * A Two Resource path: consisting of `mongodbatlas_cloud_provider_access_setup` and `mongodbatlas_cloud_provider_access_authorization`. The first resource, `mongodbatlas_cloud_provider_access_setup`, only generates the initial configuration (create, delete operations). The second resource, `mongodbatlas_cloud_provider_access_authorization`, helps to perform the authorization using the role_id of the first resource. This path is helpful in a multi-provider Terraform file, and allows for a single and decoupled apply. See example of this Two Resource path option with AWS Cloud [here](https://github.com/mongodb/terraform-provider-mongodbatlas/tree/master/examples/atlas-cloud-provider-access/aws) and AZURE Cloud [here](https://github.com/mongodb/terraform-provider-mongodbatlas/tree/master/examples/atlas-cloud-provider-access/azure). -* A Single Resource path: using the `mongodbatlas_cloud_provider_access` that at provision time sets up all the required configuration for a given provider, then with a subsequent update it can perform the authorize of the role. Note this path requires two `terraform apply` commands, once for setup and once for auth. This resource supports only `AWS`. -**WARNING:** The resource `mongodbatlas_cloud_provider_access` is deprecated and will be removed in version v1.14.0, use the Two Resource path instead. -> **IMPORTANT** If you want to move from the single resource path to the two resources path see the [migration guide](https://registry.terraform.io/providers/mongodb/mongodbatlas/latest/docs/guides/0.9.1-upgrade-guide#migration-to-cloud-provider-access-setup) @@ -154,68 +152,7 @@ Conditional * `feature_usages` - Atlas features this AWS IAM role is linked to. -## mongodbatlas_cloud_provider_access -**WARNING:** The resource `mongodbatlas_cloud_provider_access` is deprecated and will be removed in version v1.14.0, use the Two Resource path instead. +## Import mongodbatlas_cloud_provider_access_authorization -`mongodbatlas_cloud_provider_access` Allows you to register and authorize AWS IAM roles in Atlas. This is the resource to use for the single resource path described above. - --> **NOTE:** Groups and projects are synonymous terms. You may find `groupId` in the official documentation. - --> **NOTE:** The update of the argument iam_assumed_role_arn is one step in a procedure to create unified AWS access for Atlas services. For the complete procedure, see [Set Up Unified AWS Access](https://docs.atlas.mongodb.com/security/set-up-unified-aws-access/#set-up-unified-aws-access). - -## Example Usage - -```terraform - -resource "mongodbatlas_cloud_provider_access" "test_role" { - project_id = "64259ee860c43338194b0f8e" - project_id = "64259ee860c43338194b0f8e" - provider_name = "AWS" -} - -``` - -## Argument Reference - -* `project_id` - (Required) The unique ID for the project -* `provider_name` - (Required) The cloud provider for which to create a new role. Currently only AWS is supported. -* `iam_assumed_role_arn` - (Optional) - ARN of the IAM Role that Atlas assumes when accessing resources in your AWS account. This value is required after the creation (register of the role) as part of [Set Up Unified AWS Access](https://docs.atlas.mongodb.com/security/set-up-unified-aws-access/#set-up-unified-aws-access). - - -## Attributes Reference - -* `id` - Unique identifier used by terraform for internal management. -* `atlas_assumed_role_external_id` - Unique external ID Atlas uses when assuming the IAM role in your AWS account. -* `atlas_aws_account_arn` - ARN associated with the Atlas AWS account used to assume IAM roles in your AWS account. -* `authorized_date` - Date on which this role was authorized. -* `created_date` - Date on which this role was created. -* `feature_usages` - Atlas features this AWS IAM role is linked to. -* `provider_name` - Name of the cloud provider. Currently limited to AWS. -* `role_id` - Unique ID of this role. - -## Authorize role - -Once the resource is created add the field `iam_assumed_role_arn` see [Set Up Unified AWS Access](https://docs.atlas.mongodb.com/security/set-up-unified-aws-access/#set-up-unified-aws-access) , and execute a new `terraform apply` this will create a PATCH request. - -```terraform - -resource "mongodbatlas_cloud_provider_access" "test_role" { - project_id = "" - provider_name = "AWS" - iam_assumed_role_arn = "arn:aws:iam::772401394250:role/test-user-role" -} - -``` - -## Import - -The Cloud Provider Access resource can be imported using project ID and the provider name and mongodbatlas role id, in the format `project_id`-`provider_name`-`role_id`, e.g. - -``` -$ terraform import mongodbatlas_cloud_provider_access.my_role 1112222b3bf99403840e8934-AWS-5fc17d476f7a33224f5b224e -``` - - - -See [MongoDB Atlas API](https://docs.atlas.mongodb.com/reference/api/cloud-provider-access-create-one-role/) Documentation for more information. +The Cloud Provider Access Authorization resource cannot be imported. \ No newline at end of file