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_acmpca_certificate_authority: Add support for OCSP #25720

Merged
merged 5 commits into from
Jul 7, 2022
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/25720.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:enhancement
resource/aws_acmpca_certificate_authority: Add `revocation_configuration.ocsp_configuration` argument
```
62 changes: 60 additions & 2 deletions internal/service/acmpca/certificate_authority.go
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,31 @@ func ResourceCertificateAuthority() *schema.Resource {
},
},
},
// https://docs.aws.amazon.com/acm-pca/latest/APIReference/API_OcspConfiguration.html
"ocsp_configuration": {
Type: schema.TypeList,
Optional: true,
MaxItems: 1,
DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool {
if old == "1" && new == "0" {
return true
}
return false
},
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"enabled": {
Type: schema.TypeBool,
Required: true,
},
"ocsp_custom_cname": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: validation.StringLenBetween(0, 253),
},
},
},
},
},
},
},
Expand Down Expand Up @@ -630,6 +655,24 @@ func expandCrlConfiguration(l []interface{}) *acmpca.CrlConfiguration {
return config
}

func expandOcspConfiguration(l []interface{}) *acmpca.OcspConfiguration {
if len(l) == 0 {
return nil
}

m := l[0].(map[string]interface{})

config := &acmpca.OcspConfiguration{
Enabled: aws.Bool(m["enabled"].(bool)),
}

if v, ok := m["ocsp_custom_cname"]; ok && v.(string) != "" {
config.OcspCustomCname = aws.String(v.(string))
}

return config
}

func expandRevocationConfiguration(l []interface{}) *acmpca.RevocationConfiguration {
if len(l) == 0 {
return nil
Expand All @@ -638,7 +681,8 @@ func expandRevocationConfiguration(l []interface{}) *acmpca.RevocationConfigurat
m := l[0].(map[string]interface{})

config := &acmpca.RevocationConfiguration{
CrlConfiguration: expandCrlConfiguration(m["crl_configuration"].([]interface{})),
CrlConfiguration: expandCrlConfiguration(m["crl_configuration"].([]interface{})),
OcspConfiguration: expandOcspConfiguration(m["ocsp_configuration"].([]interface{})),
}

return config
Expand Down Expand Up @@ -698,13 +742,27 @@ func flattenCrlConfiguration(config *acmpca.CrlConfiguration) []interface{} {
return []interface{}{m}
}

func flattenOcspConfiguration(config *acmpca.OcspConfiguration) []interface{} {
if config == nil {
return []interface{}{}
}

m := map[string]interface{}{
"enabled": aws.BoolValue(config.Enabled),
"ocsp_custom_cname": aws.StringValue(config.OcspCustomCname),
}

return []interface{}{m}
}

func flattenRevocationConfiguration(config *acmpca.RevocationConfiguration) []interface{} {
if config == nil {
return []interface{}{}
}

m := map[string]interface{}{
"crl_configuration": flattenCrlConfiguration(config.CrlConfiguration),
"crl_configuration": flattenCrlConfiguration(config.CrlConfiguration),
"ocsp_configuration": flattenOcspConfiguration(config.OcspConfiguration),
}

return []interface{}{m}
Expand Down
18 changes: 18 additions & 0 deletions internal/service/acmpca/certificate_authority_data_source.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,24 @@ func DataSourceCertificateAuthority() *schema.Resource {
},
},
},
// https://docs.aws.amazon.com/acm-pca/latest/APIReference/API_OcspConfiguration.html
"ocsp_configuration": {
Type: schema.TypeList,
Optional: true,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"enabled": {
Type: schema.TypeBool,
Computed: true,
},
"ocsp_custom_cname": {
Type: schema.TypeString,
Computed: true,
},
},
},
},
},
},
},
Expand Down
196 changes: 196 additions & 0 deletions internal/service/acmpca/certificate_authority_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,155 @@ func TestAccACMPCACertificateAuthority_RevocationCrl_s3ObjectACL(t *testing.T) {
})
}

func TestAccACMPCACertificateAuthority_RevocationOcsp_enabled(t *testing.T) {
var certificateAuthority acmpca.CertificateAuthority
resourceName := "aws_acmpca_certificate_authority.test"

commonName := acctest.RandomDomainName()

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(t) },
ErrorCheck: acctest.ErrorCheck(t, acmpca.EndpointsID),
ProviderFactories: acctest.ProviderFactories,
CheckDestroy: testAccCheckCertificateAuthorityDestroy,
Steps: []resource.TestStep{
// Test creating OCSP revocation configuration on resource creation
{
Config: testAccCertificateAuthorityConfig_revocationConfigurationOcspConfigurationEnabled(commonName, true),
Check: resource.ComposeTestCheckFunc(
acctest.CheckACMPCACertificateAuthorityExists(resourceName, &certificateAuthority),
resource.TestCheckResourceAttr(resourceName, "revocation_configuration.#", "1"),
resource.TestCheckResourceAttr(resourceName, "revocation_configuration.0.ocsp_configuration.#", "1"),
resource.TestCheckResourceAttr(resourceName, "revocation_configuration.0.ocsp_configuration.0.enabled", "true"),
resource.TestCheckResourceAttr(resourceName, "revocation_configuration.0.ocsp_configuration.0.ocsp_custom_cname", ""),
),
},
// Test importing OCSP revocation configuration
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{
"permanent_deletion_time_in_days",
},
},
// Test disabling OCSP revocation configuration
{
Config: testAccCertificateAuthorityConfig_revocationConfigurationOcspConfigurationEnabled(commonName, false),
Check: resource.ComposeTestCheckFunc(
acctest.CheckACMPCACertificateAuthorityExists(resourceName, &certificateAuthority),
resource.TestCheckResourceAttr(resourceName, "revocation_configuration.#", "1"),
resource.TestCheckResourceAttr(resourceName, "revocation_configuration.0.ocsp_configuration.#", "1"),
resource.TestCheckResourceAttr(resourceName, "revocation_configuration.0.ocsp_configuration.0.enabled", "false"),
),
},
// Test enabling OCSP revocation configuration
{
Config: testAccCertificateAuthorityConfig_revocationConfigurationOcspConfigurationEnabled(commonName, true),
Check: resource.ComposeTestCheckFunc(
acctest.CheckACMPCACertificateAuthorityExists(resourceName, &certificateAuthority),
resource.TestCheckResourceAttr(resourceName, "revocation_configuration.#", "1"),
resource.TestCheckResourceAttr(resourceName, "revocation_configuration.0.ocsp_configuration.#", "1"),
resource.TestCheckResourceAttr(resourceName, "revocation_configuration.0.ocsp_configuration.0.enabled", "true"),
resource.TestCheckResourceAttr(resourceName, "revocation_configuration.0.ocsp_configuration.0.ocsp_custom_cname", ""),
),
},
// Test removing revocation configuration on resource update
{
Config: testAccCertificateAuthorityConfig_required(commonName),
Check: resource.ComposeTestCheckFunc(
acctest.CheckACMPCACertificateAuthorityExists(resourceName, &certificateAuthority),
resource.TestCheckResourceAttr(resourceName, "revocation_configuration.#", "1"),
resource.TestCheckResourceAttr(resourceName, "revocation_configuration.0.ocsp_configuration.#", "1"),
resource.TestCheckResourceAttr(resourceName, "revocation_configuration.0.ocsp_configuration.0.enabled", "false"),
),
},
},
})
}

func TestAccACMPCACertificateAuthority_RevocationOcsp_customCNAME(t *testing.T) {
var certificateAuthority acmpca.CertificateAuthority
resourceName := "aws_acmpca_certificate_authority.test"

domain := acctest.RandomDomain()
commonName := domain.String()
customCName := domain.Subdomain("ocspl").String()
customCName2 := domain.Subdomain("ocsp2").String()

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(t) },
ErrorCheck: acctest.ErrorCheck(t, acmpca.EndpointsID),
ProviderFactories: acctest.ProviderFactories,
CheckDestroy: testAccCheckCertificateAuthorityDestroy,
Steps: []resource.TestStep{
// Test creating revocation configuration on resource creation
{
Config: testAccCertificateAuthorityConfig_revocationConfigurationOcspConfigurationCustomCNAME(commonName, customCName),
Check: resource.ComposeTestCheckFunc(
acctest.CheckACMPCACertificateAuthorityExists(resourceName, &certificateAuthority),
resource.TestCheckResourceAttr(resourceName, "revocation_configuration.#", "1"),
resource.TestCheckResourceAttr(resourceName, "revocation_configuration.0.ocsp_configuration.#", "1"),
resource.TestCheckResourceAttr(resourceName, "revocation_configuration.0.ocsp_configuration.0.enabled", "true"),
resource.TestCheckResourceAttr(resourceName, "revocation_configuration.0.ocsp_configuration.0.ocsp_custom_cname", customCName),
),
},
// Test importing OCSP revocation configuration
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{
"permanent_deletion_time_in_days",
},
},
// Test updating OCSP revocation configuration
{
Config: testAccCertificateAuthorityConfig_revocationConfigurationOcspConfigurationCustomCNAME(commonName, customCName2),
Check: resource.ComposeTestCheckFunc(
acctest.CheckACMPCACertificateAuthorityExists(resourceName, &certificateAuthority),
resource.TestCheckResourceAttr(resourceName, "revocation_configuration.#", "1"),
resource.TestCheckResourceAttr(resourceName, "revocation_configuration.0.ocsp_configuration.#", "1"),
resource.TestCheckResourceAttr(resourceName, "revocation_configuration.0.ocsp_configuration.0.enabled", "true"),
resource.TestCheckResourceAttr(resourceName, "revocation_configuration.0.ocsp_configuration.0.ocsp_custom_cname", customCName2),
),
},
// Test removing OCSP custom cname on resource update
{
Config: testAccCertificateAuthorityConfig_revocationConfigurationOcspConfigurationEnabled(commonName, true),
Check: resource.ComposeTestCheckFunc(
acctest.CheckACMPCACertificateAuthorityExists(resourceName, &certificateAuthority),
resource.TestCheckResourceAttr(resourceName, "revocation_configuration.#", "1"),
resource.TestCheckResourceAttr(resourceName, "revocation_configuration.0.ocsp_configuration.#", "1"),
resource.TestCheckResourceAttr(resourceName, "revocation_configuration.0.ocsp_configuration.0.enabled", "true"),
resource.TestCheckResourceAttr(resourceName, "revocation_configuration.0.ocsp_configuration.0.ocsp_custom_cname", ""),
),
},
// Test adding OCSP custom cname on resource update
{
Config: testAccCertificateAuthorityConfig_revocationConfigurationOcspConfigurationCustomCNAME(commonName, customCName),
Check: resource.ComposeTestCheckFunc(
acctest.CheckACMPCACertificateAuthorityExists(resourceName, &certificateAuthority),
resource.TestCheckResourceAttr(resourceName, "revocation_configuration.#", "1"),
resource.TestCheckResourceAttr(resourceName, "revocation_configuration.0.ocsp_configuration.#", "1"),
resource.TestCheckResourceAttr(resourceName, "revocation_configuration.0.ocsp_configuration.0.enabled", "true"),
resource.TestCheckResourceAttr(resourceName, "revocation_configuration.0.ocsp_configuration.0.ocsp_custom_cname", customCName),
),
},
// Test removing revocation configuration on resource update
{
Config: testAccCertificateAuthorityConfig_required(commonName),
Check: resource.ComposeTestCheckFunc(
acctest.CheckACMPCACertificateAuthorityExists(resourceName, &certificateAuthority),
resource.TestCheckResourceAttr(resourceName, "revocation_configuration.#", "1"),
resource.TestCheckResourceAttr(resourceName, "revocation_configuration.0.ocsp_configuration.#", "1"),
resource.TestCheckResourceAttr(resourceName, "revocation_configuration.0.ocsp_configuration.0.enabled", "false"),
),
},
},
})
}

func TestAccACMPCACertificateAuthority_tags(t *testing.T) {
var certificateAuthority acmpca.CertificateAuthority
resourceName := "aws_acmpca_certificate_authority.test"
Expand Down Expand Up @@ -716,6 +865,53 @@ resource "aws_acmpca_certificate_authority" "test" {
`, commonName, s3ObjectAcl))
}

func testAccCertificateAuthorityConfig_revocationConfigurationOcspConfigurationCustomCNAME(commonName, customCname string) string {
return fmt.Sprintf(`
resource "aws_acmpca_certificate_authority" "test" {
permanent_deletion_time_in_days = 7

certificate_authority_configuration {
key_algorithm = "RSA_4096"
signing_algorithm = "SHA512WITHRSA"

subject {
common_name = %[1]q
}
}

revocation_configuration {
ocsp_configuration {
enabled = true
ocsp_custom_cname = %[2]q
}
}
}
`, commonName, customCname)
}

func testAccCertificateAuthorityConfig_revocationConfigurationOcspConfigurationEnabled(commonName string, enabled bool) string {
return fmt.Sprintf(`
resource "aws_acmpca_certificate_authority" "test" {
permanent_deletion_time_in_days = 7

certificate_authority_configuration {
key_algorithm = "RSA_4096"
signing_algorithm = "SHA512WITHRSA"

subject {
common_name = %[1]q
}
}

revocation_configuration {
ocsp_configuration {
enabled = %[2]t
}
}
}
`, commonName, enabled)
}

func testAccCertificateAuthorityConfig_S3Bucket(rName string) string {
return fmt.Sprintf(`
resource "aws_s3_bucket" "test" {
Expand Down
2 changes: 2 additions & 0 deletions website/docs/d/acmpca_certificate_authority.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ In addition to all arguments above, the following attributes are exported:
* `revocation_configuration.0.crl_configuration.0.expiration_in_days` - Number of days until a certificate expires.
* `revocation_configuration.0.crl_configuration.0.s3_bucket_name` - Name of the S3 bucket that contains the CRL.
* `revocation_configuration.0.crl_configuration.0.s3_object_acl` - Whether the CRL is publicly readable or privately held in the CRL Amazon S3 bucket.
* `revocation_configuration.0.ocsp_configuration.0.enabled` - Boolean value that specifies whether a custom OCSP responder is enabled.
* `revocation_configuration.0.ocsp_configuration.0.ocsp_custom_cname` - A CNAME specifying a customized OCSP domain.
* `serial` - Serial number of the certificate authority. Only available after the certificate authority certificate has been imported.
* `status` - Status of the certificate authority.
* `tags` - Specifies a key-value map of user-defined tags that are attached to the certificate authority.
Expand Down
7 changes: 7 additions & 0 deletions website/docs/r/acmpca_certificate_authority.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,8 @@ Contains information about the certificate subject. Identifies the entity that o
### revocation_configuration

* `crl_configuration` - (Optional) Nested argument containing configuration of the certificate revocation list (CRL), if any, maintained by the certificate authority. Defined below.
* `ocsp_configuration` - (Optional) Nested argument containing configuration of
the custom OCSP responder endpoint. Defined below.

#### crl_configuration

Expand All @@ -134,6 +136,11 @@ Contains information about the certificate subject. Identifies the entity that o
* `s3_bucket_name` - (Optional) Name of the S3 bucket that contains the CRL. If you do not provide a value for the `custom_cname` argument, the name of your S3 bucket is placed into the CRL Distribution Points extension of the issued certificate. You must specify a bucket policy that allows ACM PCA to write the CRL to your bucket. Must be less than or equal to 255 characters in length.
* `s3_object_acl` - (Optional) Determines whether the CRL will be publicly readable or privately held in the CRL Amazon S3 bucket. Defaults to `PUBLIC_READ`.

#### ocsp_configuration

* `enabled` - (Required) Boolean value that specifies whether a custom OCSP responder is enabled.
* `ocsp_custom_cname` - (Optional) A CNAME specifying a customized OCSP domain. Note: The value of the CNAME must not include a protocol prefix such as "http://" or "https://".

## Attributes Reference

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