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

[New Resource]: aws_rds_certificate #35003

Merged
merged 29 commits into from
Jul 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
ce5787f
Init new RDS Certificate override resource
obounaim Dec 20, 2023
724e094
Add missing SetId() to fix create action
obounaim Dec 20, 2023
d15169d
Fix typo in file name
obounaim Dec 20, 2023
3d02a81
Init RDS Certificate Acc tests
obounaim Dec 20, 2023
01ba474
Init RDS Certificate documentation
obounaim Dec 20, 2023
0ac4810
Update RDS Certificate Schema
obounaim Dec 20, 2023
54d83d2
Fix certificate identifier conversion in RDS service
obounaim Dec 22, 2023
374f506
Add test for AWS RDS certificate functionality
obounaim Dec 22, 2023
bb21a54
Add changelog entry
obounaim Dec 22, 2023
fecb64c
Removes trailing spaces from MD document
obounaim Dec 22, 2023
3e2d3c0
Removes "RDS" in func name inside rds package
obounaim Dec 22, 2023
d10c83a
Omit Computed and Optional set to false
obounaim Dec 22, 2023
7329b1e
Run make gen
obounaim Dec 22, 2023
65ed76f
Fix semgrep: Include "RDS" in test name
obounaim Dec 22, 2023
eacb578
Fix semgrep error
obounaim Dec 23, 2023
750c263
Fix semgrep error
obounaim Dec 23, 2023
03659c7
Fix semgrep error
obounaim Dec 23, 2023
1f93234
Add importer for certificate resource
obounaim Dec 24, 2023
4288b84
Add import example for AWS RDS certificate
obounaim Dec 24, 2023
1fba017
Remove empty line in rds_certificate.html.markdown
obounaim Dec 24, 2023
4c0dfa4
Add import block for default EBS encryption state
obounaim Dec 24, 2023
e59e70d
Fix import block in rds_certificate.html.markdown
obounaim Dec 24, 2023
2e31192
Fix RDS certificate acc test
obounaim Dec 24, 2023
dc2d73f
Fix typo in documentation
obounaim Jan 4, 2024
504da0d
Fix semgrep error
obounaim May 9, 2024
500f904
Use region as ID and other optimization
obounaim May 10, 2024
7aeda1d
Read after creating or updating the resource
obounaim May 13, 2024
f6b87b9
Merge branch 'main' into HEAD
ewbankkit Jul 12, 2024
b5855f9
r/aws_rds_certificate: Tidy up.
ewbankkit Jul 12, 2024
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/35003.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:new-resource
aws_rds_certificate
```
147 changes: 147 additions & 0 deletions internal/service/rds/certificate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package rds

import (
"context"
"log"

"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/service/rds"
"github.com/aws/aws-sdk-go-v2/service/rds/types"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-provider-aws/internal/conns"
"github.com/hashicorp/terraform-provider-aws/internal/errs"
"github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag"
tfslices "github.com/hashicorp/terraform-provider-aws/internal/slices"
"github.com/hashicorp/terraform-provider-aws/internal/tfresource"
)

// @SDKResource("aws_rds_certificate", name="Default Certificate")
func resourceCertificate() *schema.Resource {
return &schema.Resource{
CreateWithoutTimeout: resourceCertificatePut,
ReadWithoutTimeout: resourceCertificateRead,
UpdateWithoutTimeout: resourceCertificatePut,
DeleteWithoutTimeout: resourceCertificateDelete,

Importer: &schema.ResourceImporter{
StateContext: schema.ImportStatePassthroughContext,
},

Schema: map[string]*schema.Schema{
"certificate_identifier": {
Type: schema.TypeString,
Required: true,
},
},
}
}

func resourceCertificatePut(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
var diags diag.Diagnostics
conn := meta.(*conns.AWSClient).RDSClient(ctx)

certificateID := d.Get("certificate_identifier").(string)
input := &rds.ModifyCertificatesInput{
CertificateIdentifier: aws.String(certificateID),
}

_, err := conn.ModifyCertificates(ctx, input)

if err != nil {
return sdkdiag.AppendErrorf(diags, "setting RDS Default Certificate (%s): %s", certificateID, err)
}

if d.IsNewResource() {
d.SetId(meta.(*conns.AWSClient).Region)
}

return append(diags, resourceCertificateRead(ctx, d, meta)...)
}

func resourceCertificateRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
var diags diag.Diagnostics
conn := meta.(*conns.AWSClient).RDSClient(ctx)

output, err := findDefaultCertificate(ctx, conn)

if !d.IsNewResource() && tfresource.NotFound(err) {
log.Printf("[WARN] RDS Default Certificate (%s) not found, removing from state", d.Id())
d.SetId("")
return diags
}

if err != nil {
return sdkdiag.AppendErrorf(diags, "reading RDS Default Certificate (%s): %s", d.Id(), err)
}

d.Set("certificate_identifier", output.CertificateIdentifier)

return diags
}

func resourceCertificateDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
var diags diag.Diagnostics
conn := meta.(*conns.AWSClient).RDSClient(ctx)

log.Printf("[DEBUG] Deleting RDS Default Certificate: %s", d.Id())
_, err := conn.ModifyCertificates(ctx, &rds.ModifyCertificatesInput{
RemoveCustomerOverride: aws.Bool(true),
})

if err != nil {
return sdkdiag.AppendErrorf(diags, "removing RDS Default Certificate (%s): %s", d.Id(), err)
}

return diags
}

func findCertificate(ctx context.Context, conn *rds.Client, input *rds.DescribeCertificatesInput, filter tfslices.Predicate[*types.Certificate]) (*types.Certificate, error) {
output, err := findCertificates(ctx, conn, input, filter)

if err != nil {
return nil, err
}

return tfresource.AssertSingleValueResult(output)
}

func findCertificates(ctx context.Context, conn *rds.Client, input *rds.DescribeCertificatesInput, filter tfslices.Predicate[*types.Certificate]) ([]types.Certificate, error) {
var output []types.Certificate

pages := rds.NewDescribeCertificatesPaginator(conn, input)
for pages.HasMorePages() {
page, err := pages.NextPage(ctx)

if errs.IsA[*types.CertificateNotFoundFault](err) {
return nil, &retry.NotFoundError{
LastError: err,
LastRequest: input,
}
}

if err != nil {
return nil, err
}

for _, v := range page.Certificates {
if filter(&v) {
output = append(output, v)
}
}
}

return output, nil
}

func findDefaultCertificate(ctx context.Context, conn *rds.Client) (*types.Certificate, error) {
input := &rds.DescribeCertificatesInput{}

return findCertificate(ctx, conn, input, func(v *types.Certificate) bool {
return aws.ToBool(v.CustomerOverride)
})
}
142 changes: 142 additions & 0 deletions internal/service/rds/certificate_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package rds_test

import (
"context"
"fmt"
"testing"

"github.com/aws/aws-sdk-go-v2/service/rds/types"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/hashicorp/terraform-plugin-testing/terraform"
"github.com/hashicorp/terraform-provider-aws/internal/acctest"
"github.com/hashicorp/terraform-provider-aws/internal/conns"
tfrds "github.com/hashicorp/terraform-provider-aws/internal/service/rds"
"github.com/hashicorp/terraform-provider-aws/internal/tfresource"
"github.com/hashicorp/terraform-provider-aws/names"
)

func TestAccRDSCertificate_serial(t *testing.T) {
t.Parallel()

testCases := map[string]func(t *testing.T){
acctest.CtBasic: testAccCertificate_basic,
acctest.CtDisappears: testAccCertificate_disappears,
}

acctest.RunSerialTests1Level(t, testCases, 0)
}

func testAccCertificate_basic(t *testing.T) {
ctx := acctest.Context(t)
var v types.Certificate
resourceName := "aws_rds_certificate.test"

resource.Test(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(ctx, t) },
ErrorCheck: acctest.ErrorCheck(t, names.RDSServiceID),
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
CheckDestroy: testAccCheckCertificateDestroy(ctx),
Steps: []resource.TestStep{
{
Config: testAccCertificateConfig_basic("rds-ca-rsa4096-g1"),
Check: resource.ComposeTestCheckFunc(
testAccCheckCertificateExists(ctx, resourceName, &v),
resource.TestCheckResourceAttr(resourceName, "certificate_identifier", "rds-ca-rsa4096-g1"),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
{
Config: testAccCertificateConfig_basic("rds-ca-ecc384-g1"),
Check: resource.ComposeTestCheckFunc(
testAccCheckCertificateExists(ctx, resourceName, &v),
resource.TestCheckResourceAttr(resourceName, "certificate_identifier", "rds-ca-ecc384-g1"),
),
},
},
})
}

func testAccCertificate_disappears(t *testing.T) {
ctx := acctest.Context(t)
var v types.Certificate
resourceName := "aws_rds_certificate.test"

resource.Test(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(ctx, t) },
ErrorCheck: acctest.ErrorCheck(t, names.RDSServiceID),
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
CheckDestroy: testAccCheckCertificateDestroy(ctx),
Steps: []resource.TestStep{
{
Config: testAccCertificateConfig_basic("rds-ca-rsa4096-g1"),
Check: resource.ComposeTestCheckFunc(
testAccCheckCertificateExists(ctx, resourceName, &v),
acctest.CheckResourceDisappears(ctx, acctest.Provider, tfrds.ResourceCertificate(), resourceName),
),
ExpectNonEmptyPlan: true,
},
},
})
}

func testAccCheckCertificateDestroy(ctx context.Context) resource.TestCheckFunc {
return func(s *terraform.State) error {
conn := acctest.Provider.Meta().(*conns.AWSClient).RDSClient(ctx)

for _, rs := range s.RootModule().Resources {
if rs.Type != "aws_rds_certificate" {
continue
}

_, err := tfrds.FindDefaultCertificate(ctx, conn)

if tfresource.NotFound(err) {
continue
}

if err != nil {
return err
}

return fmt.Errorf("RDS Default Certificate %s still exists", rs.Primary.ID)
}

return nil
}
}

func testAccCheckCertificateExists(ctx context.Context, n string, v *types.Certificate) resource.TestCheckFunc {
return func(s *terraform.State) error {
_, ok := s.RootModule().Resources[n]
if !ok {
return fmt.Errorf("Not found: %s", n)
}

conn := acctest.Provider.Meta().(*conns.AWSClient).RDSClient(ctx)

output, err := tfrds.FindDefaultCertificate(ctx, conn)

if err != nil {
return err
}

*v = *output

return nil
}
}

func testAccCertificateConfig_basic(certificateID string) string {
return fmt.Sprintf(`
resource "aws_rds_certificate" "test" {
certificate_identifier = %[1]q
}
`, certificateID)
}
2 changes: 2 additions & 0 deletions internal/service/rds/exports_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package rds

// Exports for use in tests only.
var (
ResourceCertificate = resourceCertificate
ResourceEventSubscription = resourceEventSubscription
ResourceProxy = resourceProxy
ResourceProxyDefaultTargetGroup = resourceProxyDefaultTargetGroup
Expand All @@ -17,6 +18,7 @@ var (
FindDBProxyEndpointByTwoPartKey = findDBProxyEndpointByTwoPartKey
FindDBProxyTargetByFourPartKey = findDBProxyTargetByFourPartKey
FindDBSubnetGroupByName = findDBSubnetGroupByName
FindDefaultCertificate = findDefaultCertificate
FindDefaultDBProxyTargetGroupByDBProxyName = findDefaultDBProxyTargetGroupByDBProxyName
FindEventSubscriptionByID = findEventSubscriptionByID
ListTags = listTags
Expand Down
5 changes: 5 additions & 0 deletions internal/service/rds/service_package_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

48 changes: 48 additions & 0 deletions website/docs/r/rds_certificate.html.markdown
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
---
subcategory: "RDS (Relational Database)"
layout: "aws"
page_title: "AWS: aws_rds_certificate"
description: |-
Terraform resource for managing an AWS RDS (Relational Database) Certificate.
---

# Resource: aws_rds_certificate

Provides a resource to override the system-default Secure Sockets Layer/Transport Layer Security (SSL/TLS) certificate for Amazon RDS for new DB instances in the current AWS region.

~> **NOTE:** Removing this Terraform resource removes the override. New DB instances will use the system-default certificate for the current AWS region.

## Example Usage

```terraform
resource "aws_rds_certificate" "example" {
certificate_identifier = "rds-ca-rsa4096-g1"
}
```

## Argument Reference

The following arguments are required:

* `certificate_identifier` - (Required) Certificate identifier. For example, `rds-ca-rsa4096-g1`. Refer to [AWS RDS (Relational Database) Certificate Identifier](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.SSL.html#UsingWithRDS.SSL.CertificateIdentifier) for more information.

## Attribute Reference

This resource exports no additional attributes.

## Import

In Terraform v1.5.0 and later, use an [`import` block](https://developer.hashicorp.com/terraform/language/import) to import the RDS certificate override. For example:

```terraform
import {
to = aws_rds_certificate.example
id = default
}
```

Using `terraform import`, import the default EBS encryption state. For example:

```console
% terraform import aws_rds_certificate.example default
```
Loading