From b530e358759a12f238fc12089a3d67cf9f042469 Mon Sep 17 00:00:00 2001 From: Anthony Wat Date: Wed, 10 Jan 2024 20:28:37 -0500 Subject: [PATCH 1/3] fix: Correct data type of role_arn in aws_iot_ca_certificate --- .changelog/35234.txt | 3 + internal/service/iot/ca_certificate.go | 2 +- internal/service/iot/ca_certificate_test.go | 182 ++++++++++++++++++++ 3 files changed, 186 insertions(+), 1 deletion(-) create mode 100644 .changelog/35234.txt diff --git a/.changelog/35234.txt b/.changelog/35234.txt new file mode 100644 index 00000000000..75afc1fdff8 --- /dev/null +++ b/.changelog/35234.txt @@ -0,0 +1,3 @@ +```release-note:bug +resource/aws_iot_ca_certificate: Correct data type of the `role_arn` attribute +``` \ No newline at end of file diff --git a/internal/service/iot/ca_certificate.go b/internal/service/iot/ca_certificate.go index e5d72c436cb..02ce921c760 100644 --- a/internal/service/iot/ca_certificate.go +++ b/internal/service/iot/ca_certificate.go @@ -76,7 +76,7 @@ func ResourceCACertificate() *schema.Resource { Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "role_arn": { - Type: schema.TypeBool, + Type: schema.TypeString, Optional: true, ValidateFunc: verify.ValidARN, }, diff --git a/internal/service/iot/ca_certificate_test.go b/internal/service/iot/ca_certificate_test.go index d588466716d..abae1f3b124 100644 --- a/internal/service/iot/ca_certificate_test.go +++ b/internal/service/iot/ca_certificate_test.go @@ -7,6 +7,7 @@ import ( "context" "fmt" "testing" + "time" "github.com/aws/aws-sdk-go/service/iot" "github.com/hashicorp/terraform-plugin-testing/helper/resource" @@ -163,6 +164,41 @@ func TestAccIoTCACertificate_defaultMode(t *testing.T) { }) } +func TestAccIoTCACertificate_registrationConfig(t *testing.T) { + ctx := acctest.Context(t) + resourceName := "aws_iot_ca_certificate.test" + testExternalProviders := map[string]resource.ExternalProvider{ + "tls": { + Source: "hashicorp/tls", + VersionConstraint: "4.0.4", + }, + } + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, iot.EndpointsID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + ExternalProviders: testExternalProviders, + CheckDestroy: testAccCheckCACertificateDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccCACertificateConfig_registrationConfig_iamRole(), + // Hard wait here for the IAM role to work around eventual consistency issues + Check: acctest.CheckSleep(t, 10*time.Second), + }, + { + Config: testAccCACertificateConfig_registrationConfig(), + Check: resource.ComposeTestCheckFunc( + testAccCheckCACertificateExists(ctx, resourceName), + resource.TestCheckResourceAttr(resourceName, "registration_config.#", "1"), + resource.TestCheckResourceAttrSet(resourceName, "registration_config.0.role_arn"), + resource.TestCheckResourceAttrSet(resourceName, "registration_config.0.template_body"), + ), + }, + }, + }) +} + func testAccCheckCACertificateExists(ctx context.Context, n string) resource.TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[n] @@ -301,3 +337,149 @@ resource "aws_iot_ca_certificate" "test" { data "aws_iot_registration_code" "test" {} `, active, allowAutoRegistration) } + +func testAccCACertificateConfig_registrationConfig_iamRole() string { + return ` +resource "aws_iam_role" "test" { + name = "test_iot_role" + assume_role_policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Effect = "Allow" + Principal = { + Service = "iot.amazonaws.com" + } + Action = "sts:AssumeRole" + } + ] + }) +} +` +} + +func testAccCACertificateConfig_registrationConfig() string { + return acctest.ConfigCompose(testAccCACertificateConfig_registrationConfig_iamRole(), ` +data "aws_caller_identity" "current" {} + +data "aws_partition" "current" {} + +data "aws_region" "current" {} + +resource "tls_self_signed_cert" "ca" { + private_key_pem = tls_private_key.ca.private_key_pem + subject { + common_name = "example.com" + organization = "ACME Examples, Inc" + } + validity_period_hours = 12 + allowed_uses = [ + "key_encipherment", + "digital_signature", + "server_auth", + ] + is_ca_certificate = true +} + +resource "tls_private_key" "ca" { + algorithm = "RSA" +} + +resource "tls_cert_request" "verification" { + private_key_pem = tls_private_key.verification.private_key_pem + subject { + common_name = data.aws_iot_registration_code.test.registration_code + } +} + +resource "tls_private_key" "verification" { + algorithm = "RSA" +} + +resource "tls_locally_signed_cert" "verification" { + cert_request_pem = tls_cert_request.verification.cert_request_pem + ca_private_key_pem = tls_private_key.ca.private_key_pem + ca_cert_pem = tls_self_signed_cert.ca.cert_pem + validity_period_hours = 12 + allowed_uses = [ + "key_encipherment", + "digital_signature", + "server_auth", + ] +} + +resource "aws_iot_ca_certificate" "test" { + active = true + allow_auto_registration = true + ca_certificate_pem = tls_self_signed_cert.ca.cert_pem + certificate_mode = "DEFAULT" + verification_certificate_pem = tls_locally_signed_cert.verification.cert_pem + registration_config { + role_arn = aws_iam_role.test.arn + template_body = < Date: Fri, 12 Jan 2024 09:15:38 -0500 Subject: [PATCH 2/3] Tweak CHANGELOG entry. --- .changelog/35234.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changelog/35234.txt b/.changelog/35234.txt index 75afc1fdff8..46d08ff94d1 100644 --- a/.changelog/35234.txt +++ b/.changelog/35234.txt @@ -1,3 +1,3 @@ ```release-note:bug -resource/aws_iot_ca_certificate: Correct data type of the `role_arn` attribute +resource/aws_iot_ca_certificate: Change `registration_config.role_arn` from `TypeBool` to `TypeString`, fixing `Inappropriate value for attribute "role_arn": a bool is required` errors ``` \ No newline at end of file From 0cd107411ab05271ebff132ecec6ec1425da076d Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 12 Jan 2024 09:27:47 -0500 Subject: [PATCH 3/3] r/aws_iot_ca_certificate: Retry for IAM eventual consistency. --- internal/service/iot/ca_certificate.go | 14 +++++++++++--- internal/service/iot/ca_certificate_test.go | 6 ------ 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/internal/service/iot/ca_certificate.go b/internal/service/iot/ca_certificate.go index 02ce921c760..d8fbce79852 100644 --- a/internal/service/iot/ca_certificate.go +++ b/internal/service/iot/ca_certificate.go @@ -159,13 +159,17 @@ func resourceCACertificateCreate(ctx context.Context, d *schema.ResourceData, me input.VerificationCertificate = aws.String(v.(string)) } - output, err := conn.RegisterCACertificateWithContext(ctx, input) + outputRaw, err := tfresource.RetryWhenAWSErrMessageContains(ctx, propagationTimeout, + func() (interface{}, error) { + return conn.RegisterCACertificateWithContext(ctx, input) + }, + iot.ErrCodeInvalidRequestException, "included in the RegistrationConfig does not exist or cannot be assumed by AWS IoT") if err != nil { return sdkdiag.AppendErrorf(diags, "registering IoT CA Certificate: %s", err) } - d.SetId(aws.StringValue(output.CertificateId)) + d.SetId(aws.StringValue(outputRaw.(*iot.RegisterCACertificateOutput).CertificateId)) return append(diags, resourceCACertificateRead(ctx, d, meta)...) } @@ -239,7 +243,11 @@ func resourceCACertificateUpdate(ctx context.Context, d *schema.ResourceData, me } } - _, err := conn.UpdateCACertificateWithContext(ctx, input) + _, err := tfresource.RetryWhenAWSErrMessageContains(ctx, propagationTimeout, + func() (interface{}, error) { + return conn.UpdateCACertificateWithContext(ctx, input) + }, + iot.ErrCodeInvalidRequestException, "included in the RegistrationConfig does not exist or cannot be assumed by AWS IoT") if err != nil { return sdkdiag.AppendErrorf(diags, "updating IoT CA Certificate (%s): %s", d.Id(), err) diff --git a/internal/service/iot/ca_certificate_test.go b/internal/service/iot/ca_certificate_test.go index abae1f3b124..f77629d431d 100644 --- a/internal/service/iot/ca_certificate_test.go +++ b/internal/service/iot/ca_certificate_test.go @@ -7,7 +7,6 @@ import ( "context" "fmt" "testing" - "time" "github.com/aws/aws-sdk-go/service/iot" "github.com/hashicorp/terraform-plugin-testing/helper/resource" @@ -181,11 +180,6 @@ func TestAccIoTCACertificate_registrationConfig(t *testing.T) { ExternalProviders: testExternalProviders, CheckDestroy: testAccCheckCACertificateDestroy(ctx), Steps: []resource.TestStep{ - { - Config: testAccCACertificateConfig_registrationConfig_iamRole(), - // Hard wait here for the IAM role to work around eventual consistency issues - Check: acctest.CheckSleep(t, 10*time.Second), - }, { Config: testAccCACertificateConfig_registrationConfig(), Check: resource.ComposeTestCheckFunc(