diff --git a/.changelog/2509.txt b/.changelog/2509.txt new file mode 100644 index 0000000000..68aab37b6a --- /dev/null +++ b/.changelog/2509.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +resource/mongodbatlas_encryption_at_rest: Adds new `azure_key_vault_config.#.require_private_networking` field to enable connection to Azure Key Vault over private networking +``` diff --git a/internal/common/conversion/type_conversion.go b/internal/common/conversion/type_conversion.go index 21a555db76..a05d8ecccd 100644 --- a/internal/common/conversion/type_conversion.go +++ b/internal/common/conversion/type_conversion.go @@ -62,3 +62,8 @@ func IsStringPresent(strPtr *string) bool { func MongoDBRegionToAWSRegion(region string) string { return strings.ReplaceAll(strings.ToLower(region), "_", "-") } + +// AWSRegionToMongoDBRegion converts region in us-east-1-like format to US_EAST_1-like +func AWSRegionToMongoDBRegion(region string) string { + return strings.ReplaceAll(strings.ToUpper(region), "-", "_") +} diff --git a/internal/common/conversion/type_conversion_test.go b/internal/common/conversion/type_conversion_test.go index badf82f279..028d7d163a 100644 --- a/internal/common/conversion/type_conversion_test.go +++ b/internal/common/conversion/type_conversion_test.go @@ -4,8 +4,9 @@ import ( "testing" "time" - "github.com/mongodb/terraform-provider-mongodbatlas/internal/common/conversion" "github.com/stretchr/testify/assert" + + "github.com/mongodb/terraform-provider-mongodbatlas/internal/common/conversion" ) func TestTimeWithoutNanos(t *testing.T) { @@ -78,3 +79,19 @@ func TestMongoDBRegionToAWSRegion(t *testing.T) { } } } + +func TestAWSRegionToMongoDBRegion(t *testing.T) { + tests := []struct { + region string + expected string + }{ + {"us-east-1", "US_EAST_1"}, + {"US-EAST-1", "US_EAST_1"}, + } + + for _, test := range tests { + if resp := conversion.AWSRegionToMongoDBRegion(test.region); resp != test.expected { + t.Errorf("AWSRegionToMongoDBRegion(%v) = %v; want %v", test.region, resp, test.expected) + } + } +} diff --git a/internal/service/encryptionatrest/model_encryption_at_rest.go b/internal/service/encryptionatrest/model_encryption_at_rest.go index 0e40129e11..b192009824 100644 --- a/internal/service/encryptionatrest/model_encryption_at_rest.go +++ b/internal/service/encryptionatrest/model_encryption_at_rest.go @@ -3,9 +3,11 @@ package encryptionatrest import ( "context" + "go.mongodb.org/atlas-sdk/v20240805001/admin" + "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/mongodb/terraform-provider-mongodbatlas/internal/common/conversion" - "go.mongodb.org/atlas-sdk/v20240805001/admin" ) func NewTfEncryptionAtRestRSModel(ctx context.Context, projectID string, encryptionResp *admin.EncryptionAtRest) *TfEncryptionAtRestRSModel { @@ -42,15 +44,16 @@ func NewTFAzureKeyVaultConfig(ctx context.Context, az *admin.AzureKeyVault) []Tf return []TfAzureKeyVaultConfigModel{ { - Enabled: types.BoolPointerValue(az.Enabled), - ClientID: types.StringValue(az.GetClientID()), - AzureEnvironment: types.StringValue(az.GetAzureEnvironment()), - SubscriptionID: types.StringValue(az.GetSubscriptionID()), - ResourceGroupName: types.StringValue(az.GetResourceGroupName()), - KeyVaultName: types.StringValue(az.GetKeyVaultName()), - KeyIdentifier: types.StringValue(az.GetKeyIdentifier()), - TenantID: types.StringValue(az.GetTenantID()), - Secret: conversion.StringNullIfEmpty(az.GetSecret()), + Enabled: types.BoolPointerValue(az.Enabled), + ClientID: types.StringValue(az.GetClientID()), + AzureEnvironment: types.StringValue(az.GetAzureEnvironment()), + SubscriptionID: types.StringValue(az.GetSubscriptionID()), + ResourceGroupName: types.StringValue(az.GetResourceGroupName()), + KeyVaultName: types.StringValue(az.GetKeyVaultName()), + KeyIdentifier: types.StringValue(az.GetKeyIdentifier()), + TenantID: types.StringValue(az.GetTenantID()), + Secret: conversion.StringNullIfEmpty(az.GetSecret()), + RequirePrivateNetworking: types.BoolValue(az.GetRequirePrivateNetworking()), }, } } @@ -107,14 +110,15 @@ func NewAtlasAzureKeyVault(tfAzKeyVaultConfigSlice []TfAzureKeyVaultConfigModel) v := tfAzKeyVaultConfigSlice[0] return &admin.AzureKeyVault{ - Enabled: v.Enabled.ValueBoolPointer(), - ClientID: v.ClientID.ValueStringPointer(), - AzureEnvironment: v.AzureEnvironment.ValueStringPointer(), - SubscriptionID: v.SubscriptionID.ValueStringPointer(), - ResourceGroupName: v.ResourceGroupName.ValueStringPointer(), - KeyVaultName: v.KeyVaultName.ValueStringPointer(), - KeyIdentifier: v.KeyIdentifier.ValueStringPointer(), - Secret: v.Secret.ValueStringPointer(), - TenantID: v.TenantID.ValueStringPointer(), + Enabled: v.Enabled.ValueBoolPointer(), + ClientID: v.ClientID.ValueStringPointer(), + AzureEnvironment: v.AzureEnvironment.ValueStringPointer(), + SubscriptionID: v.SubscriptionID.ValueStringPointer(), + ResourceGroupName: v.ResourceGroupName.ValueStringPointer(), + KeyVaultName: v.KeyVaultName.ValueStringPointer(), + KeyIdentifier: v.KeyIdentifier.ValueStringPointer(), + Secret: v.Secret.ValueStringPointer(), + TenantID: v.TenantID.ValueStringPointer(), + RequirePrivateNetworking: v.RequirePrivateNetworking.ValueBoolPointer(), } } diff --git a/internal/service/encryptionatrest/model_encryption_at_rest_test.go b/internal/service/encryptionatrest/model_encryption_at_rest_test.go index ea426bc1a8..9569ff635b 100644 --- a/internal/service/encryptionatrest/model_encryption_at_rest_test.go +++ b/internal/service/encryptionatrest/model_encryption_at_rest_test.go @@ -4,31 +4,34 @@ import ( "context" "testing" + "go.mongodb.org/atlas-sdk/v20240805001/admin" + "github.com/hashicorp/terraform-plugin-framework/types" - "github.com/mongodb/terraform-provider-mongodbatlas/internal/service/encryptionatrest" "github.com/stretchr/testify/assert" - "go.mongodb.org/atlas-sdk/v20240805001/admin" + + "github.com/mongodb/terraform-provider-mongodbatlas/internal/service/encryptionatrest" ) var ( - projectID = "projectID" - enabled = true - customerMasterKeyID = "CustomerMasterKeyID" - region = "Region" - accessKeyID = "AccessKeyID" - secretAccessKey = "SecretAccessKey" - roleID = "RoleID" - clientID = "clientID" - azureEnvironment = "AzureEnvironment" - subscriptionID = "SubscriptionID" - resourceGroupName = "ResourceGroupName" - keyVaultName = "KeyVaultName" - keyIdentifier = "KeyIdentifier" - tenantID = "TenantID" - secret = "Secret" - keyVersionResourceID = "KeyVersionResourceID" - serviceAccountKey = "ServiceAccountKey" - AWSKMSConfiguration = &admin.AWSKMSConfiguration{ + projectID = "projectID" + enabled = true + requirePrivateNetworking = true + customerMasterKeyID = "CustomerMasterKeyID" + region = "Region" + accessKeyID = "AccessKeyID" + secretAccessKey = "SecretAccessKey" + roleID = "RoleID" + clientID = "clientID" + azureEnvironment = "AzureEnvironment" + subscriptionID = "SubscriptionID" + resourceGroupName = "ResourceGroupName" + keyVaultName = "KeyVaultName" + keyIdentifier = "KeyIdentifier" + tenantID = "TenantID" + secret = "Secret" + keyVersionResourceID = "KeyVersionResourceID" + serviceAccountKey = "ServiceAccountKey" + AWSKMSConfiguration = &admin.AWSKMSConfiguration{ Enabled: &enabled, CustomerMasterKeyID: &customerMasterKeyID, Region: ®ion, @@ -45,26 +48,28 @@ var ( RoleID: types.StringValue(roleID), } AzureKeyVault = &admin.AzureKeyVault{ - Enabled: &enabled, - ClientID: &clientID, - AzureEnvironment: &azureEnvironment, - SubscriptionID: &subscriptionID, - ResourceGroupName: &resourceGroupName, - KeyVaultName: &keyVaultName, - KeyIdentifier: &keyIdentifier, - TenantID: &tenantID, - Secret: &secret, + Enabled: &enabled, + ClientID: &clientID, + AzureEnvironment: &azureEnvironment, + SubscriptionID: &subscriptionID, + ResourceGroupName: &resourceGroupName, + KeyVaultName: &keyVaultName, + KeyIdentifier: &keyIdentifier, + TenantID: &tenantID, + Secret: &secret, + RequirePrivateNetworking: &requirePrivateNetworking, } TfAzureKeyVaultConfigModel = encryptionatrest.TfAzureKeyVaultConfigModel{ - Enabled: types.BoolValue(enabled), - ClientID: types.StringValue(clientID), - AzureEnvironment: types.StringValue(azureEnvironment), - SubscriptionID: types.StringValue(subscriptionID), - ResourceGroupName: types.StringValue(resourceGroupName), - KeyVaultName: types.StringValue(keyVaultName), - KeyIdentifier: types.StringValue(keyIdentifier), - TenantID: types.StringValue(tenantID), - Secret: types.StringValue(secret), + Enabled: types.BoolValue(enabled), + ClientID: types.StringValue(clientID), + AzureEnvironment: types.StringValue(azureEnvironment), + SubscriptionID: types.StringValue(subscriptionID), + ResourceGroupName: types.StringValue(resourceGroupName), + KeyVaultName: types.StringValue(keyVaultName), + KeyIdentifier: types.StringValue(keyIdentifier), + TenantID: types.StringValue(tenantID), + Secret: types.StringValue(secret), + RequirePrivateNetworking: types.BoolValue(requirePrivateNetworking), } GoogleCloudKMS = &admin.GoogleCloudKMS{ Enabled: &enabled, diff --git a/internal/service/encryptionatrest/resource_encryption_at_rest.go b/internal/service/encryptionatrest/resource_encryption_at_rest.go index 010cc03f3a..977664f86b 100644 --- a/internal/service/encryptionatrest/resource_encryption_at_rest.go +++ b/internal/service/encryptionatrest/resource_encryption_at_rest.go @@ -9,6 +9,8 @@ import ( "reflect" "time" + "go.mongodb.org/atlas-sdk/v20240805001/admin" + "github.com/hashicorp/terraform-plugin-framework-validators/listvalidator" "github.com/hashicorp/terraform-plugin-framework/path" "github.com/hashicorp/terraform-plugin-framework/resource" @@ -19,12 +21,12 @@ import ( "github.com/hashicorp/terraform-plugin-framework/schema/validator" "github.com/hashicorp/terraform-plugin-framework/types" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" + "github.com/mongodb/terraform-provider-mongodbatlas/internal/common/conversion" "github.com/mongodb/terraform-provider-mongodbatlas/internal/common/retrystrategy" "github.com/mongodb/terraform-provider-mongodbatlas/internal/common/validate" "github.com/mongodb/terraform-provider-mongodbatlas/internal/config" "github.com/mongodb/terraform-provider-mongodbatlas/internal/service/project" - "go.mongodb.org/atlas-sdk/v20240805001/admin" ) const ( @@ -67,15 +69,16 @@ type TfAwsKmsConfigModel struct { Enabled types.Bool `tfsdk:"enabled"` } type TfAzureKeyVaultConfigModel struct { - ClientID types.String `tfsdk:"client_id"` - AzureEnvironment types.String `tfsdk:"azure_environment"` - SubscriptionID types.String `tfsdk:"subscription_id"` - ResourceGroupName types.String `tfsdk:"resource_group_name"` - KeyVaultName types.String `tfsdk:"key_vault_name"` - KeyIdentifier types.String `tfsdk:"key_identifier"` - Secret types.String `tfsdk:"secret"` - TenantID types.String `tfsdk:"tenant_id"` - Enabled types.Bool `tfsdk:"enabled"` + ClientID types.String `tfsdk:"client_id"` + AzureEnvironment types.String `tfsdk:"azure_environment"` + SubscriptionID types.String `tfsdk:"subscription_id"` + ResourceGroupName types.String `tfsdk:"resource_group_name"` + KeyVaultName types.String `tfsdk:"key_vault_name"` + KeyIdentifier types.String `tfsdk:"key_identifier"` + Secret types.String `tfsdk:"secret"` + TenantID types.String `tfsdk:"tenant_id"` + Enabled types.Bool `tfsdk:"enabled"` + RequirePrivateNetworking types.Bool `tfsdk:"require_private_networking"` } type TfGcpKmsConfigModel struct { ServiceAccountKey types.String `tfsdk:"service_account_key"` @@ -173,6 +176,13 @@ func (r *encryptionAtRestRS) Schema(ctx context.Context, req resource.SchemaRequ Optional: true, Sensitive: true, }, + "require_private_networking": schema.BoolAttribute{ + Optional: true, + Computed: true, + PlanModifiers: []planmodifier.Bool{ + boolplanmodifier.UseStateForUnknown(), + }, + }, }, }, }, diff --git a/internal/service/encryptionatrest/resource_encryption_at_rest_migration_test.go b/internal/service/encryptionatrest/resource_encryption_at_rest_migration_test.go index 0c5f638c7a..285c8423ba 100644 --- a/internal/service/encryptionatrest/resource_encryption_at_rest_migration_test.go +++ b/internal/service/encryptionatrest/resource_encryption_at_rest_migration_test.go @@ -1,15 +1,18 @@ package encryptionatrest_test import ( + "fmt" "os" "testing" + "go.mongodb.org/atlas-sdk/v20240805001/admin" + "github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-plugin-testing/plancheck" + "github.com/mongodb/terraform-provider-mongodbatlas/internal/common/conversion" "github.com/mongodb/terraform-provider-mongodbatlas/internal/testutil/acc" "github.com/mongodb/terraform-provider-mongodbatlas/internal/testutil/mig" - "go.mongodb.org/atlas-sdk/v20240805001/admin" ) func TestMigEncryptionAtRest_basicAWS(t *testing.T) { @@ -22,7 +25,7 @@ func TestMigEncryptionAtRest_basicAWS(t *testing.T) { awsKms = admin.AWSKMSConfiguration{ Enabled: conversion.Pointer(true), CustomerMasterKeyID: conversion.StringPtr(os.Getenv("AWS_CUSTOMER_MASTER_KEY_ID")), - Region: conversion.StringPtr(os.Getenv("AWS_REGION")), + Region: conversion.StringPtr(conversion.AWSRegionToMongoDBRegion(os.Getenv("AWS_REGION"))), RoleId: conversion.StringPtr(os.Getenv("AWS_ROLE_ID")), } ) @@ -62,15 +65,15 @@ func TestMigEncryptionAtRest_withRole_basicAWS(t *testing.T) { var ( resourceName = "mongodbatlas_encryption_at_rest.test" projectID = os.Getenv("MONGODB_ATLAS_PROJECT_ID") - accessKeyID = os.Getenv("AWS_ACCESS_KEY_ID") - secretKey = os.Getenv("AWS_SECRET_ACCESS_KEY") - policyName = acc.RandomName() - roleName = acc.RandomName() + + awsIAMRoleName = acc.RandomIAMRole() + awsIAMRolePolicyName = fmt.Sprintf("%s-policy", awsIAMRoleName) + awsKeyName = acc.RandomName() awsKms = admin.AWSKMSConfiguration{ Enabled: conversion.Pointer(true), + Region: conversion.StringPtr(conversion.AWSRegionToMongoDBRegion(os.Getenv("AWS_REGION"))), CustomerMasterKeyID: conversion.StringPtr(os.Getenv("AWS_CUSTOMER_MASTER_KEY_ID")), - Region: conversion.StringPtr(os.Getenv("AWS_REGION")), } ) @@ -80,18 +83,17 @@ func TestMigEncryptionAtRest_withRole_basicAWS(t *testing.T) { Steps: []resource.TestStep{ { ExternalProviders: mig.ExternalProvidersWithAWS(), - Config: testAccMongoDBAtlasEncryptionAtRestConfigAwsKmsWithRole(awsKms.GetRegion(), accessKeyID, secretKey, projectID, policyName, roleName, false, &awsKms), + Config: testAccMongoDBAtlasEncryptionAtRestConfigAwsKmsWithRole(projectID, awsIAMRoleName, awsIAMRolePolicyName, awsKeyName, &awsKms), }, { ExternalProviders: acc.ExternalProvidersOnlyAWS(), ProtoV6ProviderFactories: acc.TestAccProviderV6Factories, - Config: testAccMongoDBAtlasEncryptionAtRestConfigAwsKmsWithRole(awsKms.GetRegion(), accessKeyID, secretKey, projectID, policyName, roleName, false, &awsKms), + Config: testAccMongoDBAtlasEncryptionAtRestConfigAwsKmsWithRole(projectID, awsIAMRoleName, awsIAMRolePolicyName, awsKeyName, &awsKms), Check: resource.ComposeAggregateTestCheckFunc( testAccCheckMongoDBAtlasEncryptionAtRestExists(resourceName), resource.TestCheckResourceAttr(resourceName, "project_id", projectID), resource.TestCheckResourceAttr(resourceName, "aws_kms_config.0.enabled", "true"), resource.TestCheckResourceAttr(resourceName, "aws_kms_config.0.region", awsKms.GetRegion()), - resource.TestCheckResourceAttr(resourceName, "aws_kms_config.0.role_id", awsKms.GetRoleId()), ), ConfigPlanChecks: resource.ConfigPlanChecks{ PreApply: []plancheck.PlanCheck{ @@ -130,7 +132,7 @@ func TestMigEncryptionAtRest_basicAzure(t *testing.T) { Steps: []resource.TestStep{ { ExternalProviders: mig.ExternalProviders(), - Config: testAccMongoDBAtlasEncryptionAtRestConfigAzureKeyVault(projectID, &azureKeyVault), + Config: testAccMongoDBAtlasEncryptionAtRestConfigAzureKeyVault(projectID, &azureKeyVault, false), Check: resource.ComposeAggregateTestCheckFunc( testAccCheckMongoDBAtlasEncryptionAtRestExists(resourceName), resource.TestCheckResourceAttr(resourceName, "project_id", projectID), @@ -142,7 +144,7 @@ func TestMigEncryptionAtRest_basicAzure(t *testing.T) { }, { ProtoV6ProviderFactories: acc.TestAccProviderV6Factories, - Config: testAccMongoDBAtlasEncryptionAtRestConfigAzureKeyVault(projectID, &azureKeyVault), + Config: testAccMongoDBAtlasEncryptionAtRestConfigAzureKeyVault(projectID, &azureKeyVault, false), ConfigPlanChecks: resource.ConfigPlanChecks{ PreApply: []plancheck.PlanCheck{ acc.DebugPlan(), @@ -207,7 +209,7 @@ func TestMigEncryptionAtRest_basicAWS_from_v1_11_0(t *testing.T) { AccessKeyID: conversion.StringPtr(os.Getenv("AWS_ACCESS_KEY_ID")), SecretAccessKey: conversion.StringPtr(os.Getenv("AWS_SECRET_ACCESS_KEY")), CustomerMasterKeyID: conversion.StringPtr(os.Getenv("AWS_CUSTOMER_MASTER_KEY_ID")), - Region: conversion.StringPtr(os.Getenv("AWS_REGION")), + Region: conversion.StringPtr(conversion.AWSRegionToMongoDBRegion(os.Getenv("AWS_REGION"))), RoleId: conversion.StringPtr(os.Getenv("AWS_ROLE_ID")), } ) diff --git a/internal/service/encryptionatrest/resource_encryption_at_rest_test.go b/internal/service/encryptionatrest/resource_encryption_at_rest_test.go index 0b9980e92c..2b81de97cc 100644 --- a/internal/service/encryptionatrest/resource_encryption_at_rest_test.go +++ b/internal/service/encryptionatrest/resource_encryption_at_rest_test.go @@ -5,101 +5,22 @@ import ( "errors" "fmt" "os" + "strconv" "testing" + "go.mongodb.org/atlas-sdk/v20240805001/admin" + "go.mongodb.org/atlas-sdk/v20240805001/mockadmin" + "github.com/hashicorp/terraform-plugin-framework/types" "github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-plugin-testing/terraform" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" + "github.com/mongodb/terraform-provider-mongodbatlas/internal/common/conversion" "github.com/mongodb/terraform-provider-mongodbatlas/internal/common/retrystrategy" "github.com/mongodb/terraform-provider-mongodbatlas/internal/service/encryptionatrest" "github.com/mongodb/terraform-provider-mongodbatlas/internal/testutil/acc" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/mock" - "go.mongodb.org/atlas-sdk/v20240805001/admin" - "go.mongodb.org/atlas-sdk/v20240805001/mockadmin" -) - -const ( - initialConfigEncryptionRestRoleAWS = ` -provider "aws" { - region = lower(replace("%[1]s", "_", "-")) - access_key = "%[2]s" - secret_key = "%[3]s" -} - -%[7]s - -resource "mongodbatlas_cloud_provider_access" "test" { - project_id = "%[4]s" - provider_name = "AWS" - %[8]s - -} - -resource "aws_iam_role_policy" "test_policy" { - name = "%[5]s" - role = aws_iam_role.test_role.id - - policy = <<-EOF - { - "Version": "2012-10-17", - "Statement": [ - { - "Effect": "Deny", - "Action": "*", - "Resource": "*" - } - ] - } - EOF -} - -resource "aws_iam_role" "test_role" { - name = "%[6]s" - - assume_role_policy = <