Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

r/aws_rds_cluster: add domain and domain_iam_role_name to rds_cluster #35753

Merged
merged 8 commits into from
Feb 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .changelog/35753.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:enhancement
resource/aws_rds_cluster: Add `domain` and `domain_iam_role_name` arguments to support [Kerberos authentication](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Concepts.RDS_Fea_Regions_DB-eng.Feature.KerberosAuthentication.html)
```
53 changes: 53 additions & 0 deletions internal/service/rds/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,14 @@ func ResourceCluster() *schema.Resource {
Type: schema.TypeBool,
Optional: true,
},
"domain": {
Type: schema.TypeString,
Optional: true,
},
"domain_iam_role_name": {
Type: schema.TypeString,
Optional: true,
},
"enable_global_write_forwarding": {
Type: schema.TypeBool,
Optional: true,
Expand Down Expand Up @@ -614,6 +622,14 @@ func resourceClusterCreate(ctx context.Context, d *schema.ResourceData, meta int
input.DBSubnetGroupName = aws.String(v.(string))
}

if v, ok := d.GetOk("domain"); ok {
input.Domain = aws.String(v.(string))
}

if v, ok := d.GetOk("domain_iam_role_name"); ok {
input.DomainIAMRoleName = aws.String(v.(string))
}

if v, ok := d.GetOk("enabled_cloudwatch_logs_exports"); ok && v.(*schema.Set).Len() > 0 {
input.EnableCloudwatchLogsExports = flex.ExpandStringSet(v.(*schema.Set))
}
Expand Down Expand Up @@ -732,6 +748,14 @@ func resourceClusterCreate(ctx context.Context, d *schema.ResourceData, meta int
input.DBSubnetGroupName = aws.String(v.(string))
}

if v, ok := d.GetOk("domain"); ok {
input.Domain = aws.String(v.(string))
}

if v, ok := d.GetOk("domain_iam_role_name"); ok {
input.DomainIAMRoleName = aws.String(v.(string))
}

if v, ok := d.GetOk("enabled_cloudwatch_logs_exports"); ok && v.(*schema.Set).Len() > 0 {
input.EnableCloudwatchLogsExports = flex.ExpandStringSet(v.(*schema.Set))
}
Expand Down Expand Up @@ -848,6 +872,14 @@ func resourceClusterCreate(ctx context.Context, d *schema.ResourceData, meta int
input.DBSubnetGroupName = aws.String(v.(string))
}

if v, ok := d.GetOk("domain"); ok {
input.Domain = aws.String(v.(string))
}

if v, ok := d.GetOk("domain_iam_role_name"); ok {
input.DomainIAMRoleName = aws.String(v.(string))
}

if v, ok := d.GetOk("enabled_cloudwatch_logs_exports"); ok && v.(*schema.Set).Len() > 0 {
input.EnableCloudwatchLogsExports = flex.ExpandStringSet(v.(*schema.Set))
}
Expand Down Expand Up @@ -966,6 +998,14 @@ func resourceClusterCreate(ctx context.Context, d *schema.ResourceData, meta int
input.DBSystemId = aws.String(v.(string))
}

if v, ok := d.GetOk("domain"); ok {
input.Domain = aws.String(v.(string))
}

if v, ok := d.GetOk("domain_iam_role_name"); ok {
input.DomainIAMRoleName = aws.String(v.(string))
}

if v, ok := d.GetOk("enable_global_write_forwarding"); ok {
input.EnableGlobalWriteForwarding = aws.Bool(v.(bool))
}
Expand Down Expand Up @@ -1144,6 +1184,14 @@ func resourceClusterRead(ctx context.Context, d *schema.ResourceData, meta inter
d.Set("db_subnet_group_name", dbc.DBSubnetGroup)
d.Set("db_system_id", dbc.DBSystemId)
d.Set("deletion_protection", dbc.DeletionProtection)
if len(dbc.DomainMemberships) > 0 && dbc.DomainMemberships[0] != nil {
domainMembership := dbc.DomainMemberships[0]
d.Set("domain", domainMembership.Domain)
d.Set("domain_iam_role_name", domainMembership.IAMRoleName)
} else {
d.Set("domain", nil)
d.Set("domain_iam_role_name", nil)
}
d.Set("enabled_cloudwatch_logs_exports", aws.StringValueSlice(dbc.EnabledCloudwatchLogsExports))
d.Set("enable_http_endpoint", dbc.HttpEndpointEnabled)
d.Set("endpoint", dbc.Endpoint)
Expand Down Expand Up @@ -1286,6 +1334,11 @@ func resourceClusterUpdate(ctx context.Context, d *schema.ResourceData, meta int
input.DeletionProtection = aws.Bool(d.Get("deletion_protection").(bool))
}

if d.HasChanges("domain", "domain_iam_role_name") {
input.Domain = aws.String(d.Get("domain").(string))
input.DomainIAMRoleName = aws.String(d.Get("domain_iam_role_name").(string))
}

if d.HasChange("enable_global_write_forwarding") {
input.EnableGlobalWriteForwarding = aws.Bool(d.Get("enable_global_write_forwarding").(bool))
}
Expand Down
123 changes: 123 additions & 0 deletions internal/service/rds/cluster_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ func TestAccRDSCluster_basic(t *testing.T) {
resource.TestCheckResourceAttrSet(resourceName, "db_cluster_parameter_group_name"),
resource.TestCheckResourceAttr(resourceName, "db_system_id", ""),
resource.TestCheckResourceAttr(resourceName, "delete_automated_backups", "true"),
resource.TestCheckResourceAttr(resourceName, "domain", ""),
resource.TestCheckResourceAttr(resourceName, "domain_iam_role_name", ""),
resource.TestCheckResourceAttr(resourceName, "enabled_cloudwatch_logs_exports.#", "0"),
resource.TestCheckResourceAttr(resourceName, "engine", tfrds.ClusterEngineAuroraMySQL),
resource.TestCheckResourceAttrSet(resourceName, "engine_version"),
Expand Down Expand Up @@ -876,6 +878,36 @@ func TestAccRDSCluster_missingUserNameCausesError(t *testing.T) {
})
}

func TestAccRDSCluster_domain(t *testing.T) {
ctx := acctest.Context(t)
if testing.Short() {
t.Skip("skipping long-running test in short mode")
}

var dbCluster rds.DBCluster
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
resourceName := "aws_rds_cluster.test"

domain := acctest.RandomDomainName()

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(ctx, t) },
ErrorCheck: acctest.ErrorCheck(t, rds.EndpointsID),
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
CheckDestroy: testAccCheckClusterDestroy(ctx),
Steps: []resource.TestStep{
{
Config: testAccClusterConfig_domain(rName, domain),
Check: resource.ComposeTestCheckFunc(
testAccCheckClusterExists(ctx, resourceName, &dbCluster),
resource.TestCheckResourceAttrSet(resourceName, "domain"),
resource.TestCheckResourceAttrSet(resourceName, "domain_iam_role_name"),
),
},
},
})
}

func TestAccRDSCluster_EnabledCloudWatchLogsExports_mySQL(t *testing.T) {
ctx := acctest.Context(t)
var dbCluster1, dbCluster2, dbCluster3 rds.DBCluster
Expand Down Expand Up @@ -3226,6 +3258,27 @@ resource "aws_rds_cluster" "restore" {
`, rName, enabledCloudwatchLogExports))
}

func testAccClusterConfig_domain(rName, domain string) string {
return acctest.ConfigCompose(
testAccConfig_ClusterSubnetGroup(rName),
testAccConfig_ServiceRole(rName),
testAccConfig_DirectoryService(rName, domain),
fmt.Sprintf(`
resource "aws_rds_cluster" "test" {
cluster_identifier = %[1]q
engine = %[2]q
master_username = "tfacctest"
master_password = "avoid-plaintext-passwords"
db_subnet_group_name = aws_db_subnet_group.test.name
skip_final_snapshot = true
vpc_security_group_ids = [aws_security_group.test.id]
domain = aws_directory_service_directory.directory.id
domain_iam_role_name = aws_iam_role.role.name
}
`, rName, tfrds.ClusterEngineAuroraPostgreSQL),
)
}

func testAccClusterConfig_enabledCloudWatchLogsExports1(rName, enabledCloudwatchLogExports1 string) string {
return fmt.Sprintf(`
resource "aws_rds_cluster" "test" {
Expand Down Expand Up @@ -4918,6 +4971,76 @@ resource "aws_db_subnet_group" "test" {
)
}

func testAccConfig_ServiceRole(rName string) string {
return fmt.Sprintf(`
resource "aws_iam_role" "role" {
name = %[1]q

assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": [
"directoryservice.rds.${data.aws_partition.current.dns_suffix}",
"rds.${data.aws_partition.current.dns_suffix}"
]
},
"Effect": "Allow",
"Sid": ""
}
]
}
EOF
}

resource "aws_iam_role_policy_attachment" "attatch-policy" {
role = aws_iam_role.role.name
policy_arn = "arn:${data.aws_partition.current.partition}:iam::aws:policy/service-role/AmazonRDSDirectoryServiceAccess"
}
`, rName)
}

func testAccConfig_DirectoryService(rName, domain string) string {
return fmt.Sprintf(`
resource "aws_security_group" "test" {
name = %[1]q
vpc_id = aws_vpc.test.id

tags = {
Name = %[1]q
}
}

resource "aws_security_group_rule" "test" {
type = "egress"
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]

security_group_id = aws_security_group.test.id
}

resource "aws_directory_service_directory" "directory" {
name = %[2]q
password = "SuperSecretPassw0rd"
size = "Small"
type = "MicrosoftAD"
edition = "Standard"

vpc_settings {
vpc_id = aws_vpc.test.id
subnet_ids = [aws_subnet.test[0].id, aws_subnet.test[1].id]
}
}

data "aws_partition" "current" {}
`, rName, domain)
}

func testAccClusterConfig_noDeleteAutomatedBackups(rName, preferredBackupWindow string) string {
return fmt.Sprintf(`
resource "aws_rds_cluster" "test" {
Expand Down
2 changes: 2 additions & 0 deletions website/docs/r/rds_cluster.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,8 @@ This argument supports the following arguments:
* `deletion_protection` - (Optional) If the DB cluster should have deletion protection enabled.
The database can't be deleted when this value is set to `true`.
The default is `false`.
* `domain` - (Optional) The ID of the Directory Service Active Directory domain to create the cluster in.
* `domain_iam_role_name` - (Optional, but required if `domain` is provided) The name of the IAM role to be used when making API calls to the Directory Service.
* `enable_global_write_forwarding` - (Optional) Whether cluster should forward writes to an associated global cluster. Applied to secondary clusters to enable them to forward writes to an [`aws_rds_global_cluster`](/docs/providers/aws/r/rds_global_cluster.html)'s primary cluster. See the [Aurora Userguide documentation](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/aurora-global-database-write-forwarding.html) for more information.
* `enable_http_endpoint` - (Optional) Enable HTTP endpoint (data API). Only valid when `engine_mode` is set to `serverless`.
* `enabled_cloudwatch_logs_exports` - (Optional) Set of log types to export to cloudwatch. If omitted, no logs will be exported. The following log types are supported: `audit`, `error`, `general`, `slowquery`, `postgresql` (PostgreSQL).
Expand Down
Loading