Skip to content

Commit

Permalink
New Data Source: aws_rds_certificate (#15789)
Browse files Browse the repository at this point in the history
Reference: #15221

Output from acceptance testing in AWS Commercial:

```
--- PASS: TestAccAWSRDSCertificateDataSource_LatestValidTill (10.41s)
--- PASS: TestAccAWSRDSCertificateDataSource_Id (11.03s)
```

Output from acceptance testing in AWS GovCloud (US):

```
--- PASS: TestAccAWSRDSCertificateDataSource_LatestValidTill (15.02s)
--- PASS: TestAccAWSRDSCertificateDataSource_Id (16.86s)
```
  • Loading branch information
bflad committed Oct 22, 2020
1 parent 7bfe0b8 commit 45651d3
Show file tree
Hide file tree
Showing 4 changed files with 276 additions and 0 deletions.
149 changes: 149 additions & 0 deletions aws/data_source_aws_rds_certificate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
package aws

import (
"fmt"
"sort"
"time"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/rds"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

func dataSourceAwsRdsCertificate() *schema.Resource {
return &schema.Resource{
Read: dataSourceAwsRdsCertificateRead,
Schema: map[string]*schema.Schema{
"arn": {
Type: schema.TypeString,
Computed: true,
},
"certificate_type": {
Type: schema.TypeString,
Computed: true,
},
"customer_override": {
Type: schema.TypeBool,
Computed: true,
},
"customer_override_valid_till": {
Type: schema.TypeString,
Computed: true,
},
"id": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"latest_valid_till": {
Type: schema.TypeBool,
Optional: true,
},
"thumbprint": {
Type: schema.TypeString,
Computed: true,
},
"valid_from": {
Type: schema.TypeString,
Computed: true,
},
"valid_till": {
Type: schema.TypeString,
Computed: true,
},
},
}
}

func dataSourceAwsRdsCertificateRead(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).rdsconn

input := &rds.DescribeCertificatesInput{}

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

var certificates []*rds.Certificate

err := conn.DescribeCertificatesPages(input, func(page *rds.DescribeCertificatesOutput, lastPage bool) bool {
if page == nil {
return !lastPage
}

for _, certificate := range page.Certificates {
if certificate == nil {
continue
}

certificates = append(certificates, certificate)
}
return !lastPage
})

if err != nil {
return fmt.Errorf("error reading RDS Certificates: %w", err)
}

if len(certificates) == 0 {
return fmt.Errorf("no RDS Certificates found")
}

// client side filtering
var certificate *rds.Certificate

if d.Get("latest_valid_till").(bool) {
sort.Sort(rdsCertificateValidTillSort(certificates))
certificate = certificates[len(certificates)-1]
}

if len(certificates) > 1 {
return fmt.Errorf("multiple RDS Certificates match the criteria; try changing search query")
}

if certificate == nil && len(certificates) == 1 {
certificate = certificates[0]
}

if certificate == nil {
return fmt.Errorf("no RDS Certificates match the criteria")
}

d.SetId(aws.StringValue(certificate.CertificateIdentifier))

d.Set("arn", certificate.CertificateArn)
d.Set("certificate_type", certificate.CertificateType)
d.Set("customer_override", certificate.CustomerOverride)

if certificate.CustomerOverrideValidTill != nil {
d.Set("customer_override_valid_till", aws.TimeValue(certificate.CustomerOverrideValidTill).Format(time.RFC3339))
}

d.Set("thumbprint", certificate.Thumbprint)

if certificate.ValidFrom != nil {
d.Set("valid_from", aws.TimeValue(certificate.ValidFrom).Format(time.RFC3339))
}

if certificate.ValidTill != nil {
d.Set("valid_till", aws.TimeValue(certificate.ValidTill).Format(time.RFC3339))
}

return nil
}

type rdsCertificateValidTillSort []*rds.Certificate

func (s rdsCertificateValidTillSort) Len() int { return len(s) }
func (s rdsCertificateValidTillSort) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s rdsCertificateValidTillSort) Less(i, j int) bool {
if s[i] == nil || s[i].ValidTill == nil {
return true
}

if s[j] == nil || s[j].ValidTill == nil {
return false
}

return (*s[i].ValidTill).Before(*s[j].ValidTill)
}
88 changes: 88 additions & 0 deletions aws/data_source_aws_rds_certificate_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package aws

import (
"regexp"
"testing"

"github.com/aws/aws-sdk-go/service/rds"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
)

func TestAccAWSRDSCertificateDataSource_Id(t *testing.T) {
dataSourceName := "data.aws_rds_certificate.test"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t); testAccAWSRDSCertificatePreCheck(t) },
Providers: testAccProviders,
CheckDestroy: nil,
Steps: []resource.TestStep{
{
Config: testAccAWSRDSCertificateDataSourceConfigId(),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttrPair(dataSourceName, "id", "data.aws_rds_certificate.latest", "id"),
),
},
},
})
}

func TestAccAWSRDSCertificateDataSource_LatestValidTill(t *testing.T) {
dataSourceName := "data.aws_rds_certificate.test"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t); testAccAWSRDSCertificatePreCheck(t) },
Providers: testAccProviders,
CheckDestroy: nil,
Steps: []resource.TestStep{
{
Config: testAccAWSRDSCertificateDataSourceConfigLatestValidTill(),
Check: resource.ComposeTestCheckFunc(
testAccMatchResourceAttrRegionalARNNoAccount(dataSourceName, "arn", "rds", regexp.MustCompile(`cert:rds-ca-[0-9]{4}`)),
resource.TestCheckResourceAttr(dataSourceName, "certificate_type", "CA"),
resource.TestCheckResourceAttr(dataSourceName, "customer_override", "false"),
resource.TestCheckNoResourceAttr(dataSourceName, "customer_override_valid_till"),
resource.TestMatchResourceAttr(dataSourceName, "id", regexp.MustCompile(`rds-ca-[0-9]{4}`)),
resource.TestMatchResourceAttr(dataSourceName, "thumbprint", regexp.MustCompile(`[0-9a-f]+`)),
resource.TestMatchResourceAttr(dataSourceName, "valid_from", regexp.MustCompile(rfc3339RegexPattern)),
resource.TestMatchResourceAttr(dataSourceName, "valid_till", regexp.MustCompile(rfc3339RegexPattern)),
),
},
},
})
}

func testAccAWSRDSCertificatePreCheck(t *testing.T) {
conn := testAccProvider.Meta().(*AWSClient).rdsconn

input := &rds.DescribeCertificatesInput{}

_, err := conn.DescribeCertificates(input)

if testAccPreCheckSkipError(err) {
t.Skipf("skipping acceptance testing: %s", err)
}

if err != nil {
t.Fatalf("unexpected PreCheck error: %s", err)
}
}

func testAccAWSRDSCertificateDataSourceConfigId() string {
return `
data "aws_rds_certificate" "latest" {
latest_valid_till = true
}
data "aws_rds_certificate" "test" {
id = data.aws_rds_certificate.latest.id
}
`
}

func testAccAWSRDSCertificateDataSourceConfigLatestValidTill() string {
return `
data "aws_rds_certificate" "test" {
latest_valid_till = true
}
`
}
1 change: 1 addition & 0 deletions aws/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,7 @@ func Provider() *schema.Provider {
"aws_pricing_product": dataSourceAwsPricingProduct(),
"aws_qldb_ledger": dataSourceAwsQLDBLedger(),
"aws_ram_resource_share": dataSourceAwsRamResourceShare(),
"aws_rds_certificate": dataSourceAwsRdsCertificate(),
"aws_rds_cluster": dataSourceAwsRdsCluster(),
"aws_rds_engine_version": dataSourceAwsRdsEngineVersion(),
"aws_rds_orderable_db_instance": dataSourceAwsRdsOrderableDbInstance(),
Expand Down
38 changes: 38 additions & 0 deletions website/docs/d/rds_certificate.html.markdown
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
---
subcategory: "RDS"
layout: "aws"
page_title: "AWS: aws_rds_certificate"
description: |-
Information about an RDS Certificate.
---

# Data Source: aws_rds_certificate

Information about an RDS Certificate.

## Example Usage

```hcl
data "aws_rds_certificate" "example" {
latest_valid_till = true
}
```

## Argument Reference

The following arguments are supported:

* `id` - (Optional) Certificate identifier. For example, `rds-ca-2019`.
* `latest_valid_till` - (Optional) When enabled, returns the certificate with the latest `ValidTill`.

## Attribute Reference

In addition to all arguments above, the following attributes are exported:

* `arn` - Amazon Resource Name (ARN) of the certificate.
* `certificate_type` - Type of certificate. For example, `CA`.
* `customer_override` - Boolean whether there is an override for the default certificate identifier.
* `customer_override_valid_till` - If there is an override for the default certificate identifier, when the override expires.
* `thumbprint` - Thumbprint of the certificate.
* `valid_from` - [RFC3339 format](https://tools.ietf.org/html/rfc3339#section-5.8) of certificate starting validity date.
* `valid_till` - [RFC3339 format](https://tools.ietf.org/html/rfc3339#section-5.8) of certificate ending validity date.

0 comments on commit 45651d3

Please sign in to comment.