From 44c7437413600fafb1aed319a03c9b6df62fdce8 Mon Sep 17 00:00:00 2001 From: BillLynch Date: Sun, 16 Aug 2020 14:03:20 +0100 Subject: [PATCH 1/9] CHORE: add aws_iot_authorizer resource --- aws/provider.go | 1 + aws/resource_aws_iot_authorizer.go | 213 ++++++++++++++++++ aws/resource_aws_iot_authorizer_test.go | 207 +++++++++++++++++ .../iot-authroizer-signing-key.pem | 9 + website/docs/r/iot_authorizer.html.markdown | 50 ++++ 5 files changed, 480 insertions(+) create mode 100644 aws/resource_aws_iot_authorizer.go create mode 100644 aws/resource_aws_iot_authorizer_test.go create mode 100644 aws/test-fixtures/iot-authroizer-signing-key.pem create mode 100644 website/docs/r/iot_authorizer.html.markdown diff --git a/aws/provider.go b/aws/provider.go index 4e26b991cd9e..6e990105ddf0 100644 --- a/aws/provider.go +++ b/aws/provider.go @@ -872,6 +872,7 @@ func Provider() *schema.Provider { "aws_inspector_resource_group": resourceAWSInspectorResourceGroup(), "aws_instance": resourceAwsInstance(), "aws_internet_gateway": resourceAwsInternetGateway(), + "aws_iot_authorizer": resourceAwsIoTAuthorizer(), "aws_iot_certificate": resourceAwsIotCertificate(), "aws_iot_policy": resourceAwsIotPolicy(), "aws_iot_policy_attachment": resourceAwsIotPolicyAttachment(), diff --git a/aws/resource_aws_iot_authorizer.go b/aws/resource_aws_iot_authorizer.go new file mode 100644 index 000000000000..6bbe0fa2e424 --- /dev/null +++ b/aws/resource_aws_iot_authorizer.go @@ -0,0 +1,213 @@ +package aws + +import ( + "fmt" + "github.com/aws/aws-sdk-go/service/iot" + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "log" + "regexp" + "time" + + "github.com/aws/aws-sdk-go/aws" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/helper/validation" +) + +func resourceAwsIoTAuthorizer() *schema.Resource { + return &schema.Resource{ + Create: resourceAwsIotAuthorizerCreate, + Read: resourceAwsIotAuthorizerRead, + Update: resourceAwsIotAuthorizerUpdate, + Delete: resourceAwsIotAuthorizerDelete, + + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.All( + validation.StringLenBetween(1, 128), + validation.StringMatch(regexp.MustCompile(`^[\w=,@-]+`), "must contain only alphanumeric characters, underscores, and hyphens"), + ), + }, + "authorizer_function_arn": { + Type: schema.TypeString, + Required: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + ValidateFunc: validateArn, + }, + }, + "signing_disabled": { + Type: schema.TypeBool, + Required: true, + Elem: &schema.Schema{ + Type: schema.TypeBool, + }, + }, + "status": { + Type: schema.TypeString, + Optional: true, + Default: iot.AuthorizerStatusActive, + ValidateFunc: validation.StringInSlice([]string{ + iot.AuthorizerStatusActive, + iot.AuthorizerStatusInactive, + }, false), + }, + "token_key_name": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.All( + validation.StringLenBetween(1, 128), + validation.StringMatch(regexp.MustCompile(`^[A-Za-z0-9_-]+`), "must contain only alphanumeric characters, underscores, and hyphens"), + ), + }, + "token_signing_public_keys": { + Type: schema.TypeMap, + Required: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Sensitive: true, + }, + }, + } +} + +func resourceAwsIotAuthorizerCreate(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).iotconn + + tokenSigningPublicKeys := make(map[string]string) + for k, v := range d.Get("token_signing_public_keys").(map[string]interface{}) { + tokenSigningPublicKeys[k] = v.(string) + } + + input := iot.CreateAuthorizerInput{ + AuthorizerFunctionArn: aws.String(d.Get("authorizer_function_arn").(string)), + AuthorizerName: aws.String(d.Get("name").(string)), + SigningDisabled: aws.Bool(d.Get("signing_disabled").(bool)), + Status: aws.String(d.Get("status").(string)), + TokenKeyName: aws.String(d.Get("token_key_name").(string)), + TokenSigningPublicKeys: aws.StringMap(tokenSigningPublicKeys), + } + + log.Printf("[INFO] Creating IoT Authorizer: %s", input) + out, err := conn.CreateAuthorizer(&input) + if err != nil { + return fmt.Errorf("Error creating IoT Authorizer: %w", err) + } + + d.SetId(aws.StringValue(out.AuthorizerName)) + + return resourceAwsIotAuthorizerRead(d, meta) +} + +func resourceAwsIotAuthorizerRead(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).iotconn + + log.Printf("[INFO] Reading IoT Authorizer %s", d.Id()) + input := iot.DescribeAuthorizerInput{ + AuthorizerName: aws.String(d.Id()), + } + + authorizerDescription, err := conn.DescribeAuthorizer(&input) + if err != nil { + if isAWSErr(err, iot.ErrCodeResourceNotFoundException, "") { + log.Printf("[WARN] No IoT Authorizer (%s) not found, removing from state", d.Id()) + d.SetId("") + return nil + } + return err + } + authorizer := authorizerDescription.AuthorizerDescription + log.Printf("[DEBUG] Received IoT Authorizer: %s", authorizer) + + d.Set("authorizer_function_arn", authorizer.AuthorizerFunctionArn) + d.Set("signing_disabled", authorizer.SigningDisabled) + d.Set("status", authorizer.Status) + d.Set("token_key_name", authorizer.TokenKeyName) + d.Set("name", authorizer.AuthorizerName) + if err := d.Set("token_signing_public_keys", authorizer.TokenSigningPublicKeys); err != nil { + return fmt.Errorf("Error setting token signing keys for IoT Authrozer: %s", err) + } + + return nil +} + +func resourceAwsIotAuthorizerUpdate(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).iotconn + + tokenSigningPublicKeys := make(map[string]string) + for k, v := range d.Get("token_signing_public_keys").(map[string]interface{}) { + tokenSigningPublicKeys[k] = v.(string) + } + + input := iot.UpdateAuthorizerInput{ + AuthorizerFunctionArn: aws.String(d.Get("authorizer_function_arn").(string)), + AuthorizerName: aws.String(d.Id()), + Status: aws.String(d.Get("status").(string)), + TokenKeyName: aws.String(d.Get("token_key_name").(string)), + TokenSigningPublicKeys: aws.StringMap(tokenSigningPublicKeys), + } + + log.Printf("[INFO] Updating IoT Authorizer: %s", input) + _, err := conn.UpdateAuthorizer(&input) + if err != nil { + return fmt.Errorf("Updating IoT Authorizer failed: %w", err) + } + + return resourceAwsIotAuthorizerRead(d, meta) +} + +func resourceAwsIotAuthorizerDelete(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).iotconn + input := iot.DeleteAuthorizerInput{ + AuthorizerName: aws.String(d.Id()), + } + + status := d.Get("status").(string) + + // In order to delete an IoT Authorizer, you must set it inactive first. + if status == iot.AuthorizerStatusActive { + setInactiveError := d.Set("status", iot.AuthorizerStatusInactive) + + if setInactiveError != nil { + return fmt.Errorf("Setting IoT Authorizer to INACTIVE failed: %w", setInactiveError) + + } + updateErr := resourceAwsIotAuthorizerUpdate(d, meta) + + if updateErr != nil { + return fmt.Errorf("Updating IoT Authorizer to INACTIVE failed: %w", updateErr) + } + } + + log.Printf("[INFO] Deleting IoT Authorizer: %s", input) + err := resource.Retry(5*time.Minute, func() *resource.RetryError { + _, err := conn.DeleteAuthorizer(&input) + + if err != nil { + if isAWSErr(err, iot.ErrCodeInvalidRequestException, "") { + return resource.RetryableError(err) + } + if isAWSErr(err, iot.ErrCodeResourceNotFoundException, "") { + return nil + } + + return resource.NonRetryableError(err) + } + + return nil + }) + if isResourceTimeoutError(err) { + _, err = conn.DeleteAuthorizer(&input) + if isAWSErr(err, iot.ErrCodeResourceNotFoundException, "") { + return nil + } + } + if err != nil { + return fmt.Errorf("Error deleting IOT Authorizer: %s", err) + } + return nil +} diff --git a/aws/resource_aws_iot_authorizer_test.go b/aws/resource_aws_iot_authorizer_test.go new file mode 100644 index 000000000000..c87cd8b3fd5f --- /dev/null +++ b/aws/resource_aws_iot_authorizer_test.go @@ -0,0 +1,207 @@ +package aws + +import ( + "fmt" + "github.com/aws/aws-sdk-go/service/iot" + "testing" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/awserr" + "github.com/hashicorp/terraform-plugin-sdk/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/terraform" +) + +func TestAccAWSIoTAuthorizer(t *testing.T) { + var conf iot.DescribeAuthorizerOutput + rName := acctest.RandomWithPrefix("tf-acc-test") + resourceName := "aws_iot_authorizer.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSIoTAuthorizerDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSIoTAuthorizerConfig(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSIoTAuthorizerExists(resourceName, &conf), + ), + }, + { + Config: testAccAWSIoTAuthorizerConfig_defaultStatus(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSIoTAuthorizerExists(resourceName, &conf), + resource.TestCheckResourceAttr(resourceName, "status", iot.AuthorizerStatusActive), + ), + }, + { + Config: testAccAWSIoTAuthorizerConfig_update(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSIoTAuthorizerExists(resourceName, &conf), + resource.TestCheckResourceAttr(resourceName, "signing_disabled", "false"), + resource.TestCheckResourceAttr(resourceName, "name", rName), + resource.TestCheckResourceAttr(resourceName, "status", iot.AuthorizerStatusInactive), + ), + }, + }, + }) +} + +func TestAccAWSIoTAuthorizer_disappears(t *testing.T) { + var conf iot.DescribeAuthorizerOutput + rName := acctest.RandomWithPrefix("tf-acc-test") + resourceName := "aws_iot_authorizer.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSIoTAuthorizerDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSIoTAuthorizerConfig(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSIoTAuthorizerExists(resourceName, &conf), + testAccCheckResourceDisappears(testAccProvider, resourceAwsIoTAuthorizer(), resourceName), + ), + ExpectNonEmptyPlan: true, + }, + }, + }) +} + +func testAccCheckAWSIoTAuthorizerExists(n string, res *iot.DescribeAuthorizerOutput) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Not found: %s", n) + } + + if rs.Primary.ID == "" { + return fmt.Errorf("No IoT Authorizer ID is set") + } + + conn := testAccProvider.Meta().(*AWSClient).iotconn + + req := &iot.DescribeAuthorizerInput{ + AuthorizerName: aws.String(rs.Primary.ID), + } + describe, err := conn.DescribeAuthorizer(req) + if err != nil { + return err + } + + *res = *describe + + return nil + } +} + +func testAccCheckAWSIoTAuthorizerDestroy(s *terraform.State) error { + conn := testAccProvider.Meta().(*AWSClient).iotconn + + for _, rs := range s.RootModule().Resources { + if rs.Type != "aws_iot_authorizer" { + continue + } + + req := &iot.DescribeAuthorizerInput{ + AuthorizerName: aws.String(rs.Primary.ID), + } + _, err := conn.DescribeAuthorizer(req) + + if err == nil { + return fmt.Errorf("IoT Authorizer still exists") + } + + aws2err, ok := err.(awserr.Error) + if !ok { + return err + } + if aws2err.Code() != iot.ErrCodeResourceNotFoundException { + return err + } + + return nil + } + + return nil +} + +func testAccAWSIoTAuthorizerConfigBase(rName string) string { + return fmt.Sprintf(` +resource "aws_iam_role" "lambda" { + name = "%[1]s-lambda" + + assume_role_policy = < Date: Sun, 16 Aug 2020 14:16:41 +0100 Subject: [PATCH 2/9] CHORE: update imports to v2 of terraform-plugin-sdk --- aws/resource_aws_iot_authorizer.go | 6 +++--- aws/resource_aws_iot_authorizer_test.go | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/aws/resource_aws_iot_authorizer.go b/aws/resource_aws_iot_authorizer.go index 6bbe0fa2e424..f514634116f8 100644 --- a/aws/resource_aws_iot_authorizer.go +++ b/aws/resource_aws_iot_authorizer.go @@ -3,14 +3,14 @@ package aws import ( "fmt" "github.com/aws/aws-sdk-go/service/iot" - "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "log" "regexp" "time" "github.com/aws/aws-sdk-go/aws" - "github.com/hashicorp/terraform-plugin-sdk/helper/schema" - "github.com/hashicorp/terraform-plugin-sdk/helper/validation" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" ) func resourceAwsIoTAuthorizer() *schema.Resource { diff --git a/aws/resource_aws_iot_authorizer_test.go b/aws/resource_aws_iot_authorizer_test.go index c87cd8b3fd5f..d8984373139b 100644 --- a/aws/resource_aws_iot_authorizer_test.go +++ b/aws/resource_aws_iot_authorizer_test.go @@ -7,9 +7,9 @@ import ( "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/awserr" - "github.com/hashicorp/terraform-plugin-sdk/helper/acctest" - "github.com/hashicorp/terraform-plugin-sdk/helper/resource" - "github.com/hashicorp/terraform-plugin-sdk/terraform" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" ) func TestAccAWSIoTAuthorizer(t *testing.T) { From b07f538b8311cf68db171c72f679e89c873647ea Mon Sep 17 00:00:00 2001 From: BillLynch Date: Sun, 16 Aug 2020 14:31:33 +0100 Subject: [PATCH 3/9] FIX: lint issues --- aws/resource_aws_iot_authorizer_test.go | 2 +- website/docs/r/iot_authorizer.html.markdown | 13 ++++++------- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/aws/resource_aws_iot_authorizer_test.go b/aws/resource_aws_iot_authorizer_test.go index d8984373139b..7c5b7598f8a5 100644 --- a/aws/resource_aws_iot_authorizer_test.go +++ b/aws/resource_aws_iot_authorizer_test.go @@ -12,7 +12,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" ) -func TestAccAWSIoTAuthorizer(t *testing.T) { +func TestAccAWSIoTAuthorizer_basic(t *testing.T) { var conf iot.DescribeAuthorizerOutput rName := acctest.RandomWithPrefix("tf-acc-test") resourceName := "aws_iot_authorizer.test" diff --git a/website/docs/r/iot_authorizer.html.markdown b/website/docs/r/iot_authorizer.html.markdown index de2bb510b575..0067a8dcd100 100644 --- a/website/docs/r/iot_authorizer.html.markdown +++ b/website/docs/r/iot_authorizer.html.markdown @@ -14,11 +14,11 @@ Creates and manages an AWS IoT Authorizer. ```hcl resource "aws_iot_authorizer" "example" { - name = "example" - authorizer_function_arn = aws_lambda_function.example.arn - signing_disabled = false - status = "ACTIVE" - token_key_name = "Token-Header" + name = "example" + authorizer_function_arn = aws_lambda_function.example.arn + signing_disabled = false + status = "ACTIVE" + token_key_name = "Token-Header" token_signing_public_keys = { Key1 = "${file("test-fixtures/iot-authroizer-signing-key.pem")}" } @@ -30,8 +30,7 @@ resource "aws_iot_authorizer" "example" { * `name` - (Required) The name of the authorizer. * `authorizer_function_arn` - (Required) The ARN of the authorizer's Lambda function. * `signing_disabled` - (Required) Specifies whether AWS IoT validates the token signature in an authorization request. -* `status` - (Optional) The status of Authorizer request at creation. -This must be either `ACTIVE` or `INACTIVE` defaults to `ACTIVE`. +* `status` - (Optional) The status of Authorizer request at creation. This must be either `ACTIVE` or `INACTIVE` defaults to `ACTIVE`. * `token_key_name` - (Required) The name of the token key used to extract the token from the HTTP headers. * `token_signing_public_keys` - (Required) The public keys used to verify the digital signature returned by your custom authentication service. From c7f06d89be57ad5535f112d8b36f174274d26c6f Mon Sep 17 00:00:00 2001 From: BillLynch Date: Sun, 16 Aug 2020 14:42:22 +0100 Subject: [PATCH 4/9] FIX: remove Elem with incompatible type --- aws/resource_aws_iot_authorizer.go | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/aws/resource_aws_iot_authorizer.go b/aws/resource_aws_iot_authorizer.go index f514634116f8..2f077c1b0e0c 100644 --- a/aws/resource_aws_iot_authorizer.go +++ b/aws/resource_aws_iot_authorizer.go @@ -34,19 +34,13 @@ func resourceAwsIoTAuthorizer() *schema.Resource { ), }, "authorizer_function_arn": { - Type: schema.TypeString, - Required: true, - Elem: &schema.Schema{ - Type: schema.TypeString, - ValidateFunc: validateArn, - }, + Type: schema.TypeString, + Required: true, + ValidateFunc: validateArn, }, "signing_disabled": { Type: schema.TypeBool, Required: true, - Elem: &schema.Schema{ - Type: schema.TypeBool, - }, }, "status": { Type: schema.TypeString, From b068b23f362ed57cf74adf0e69d0d731d04ffc42 Mon Sep 17 00:00:00 2001 From: BillLynch Date: Mon, 14 Sep 2020 09:31:57 +0100 Subject: [PATCH 5/9] CHORE: fix typos --- aws/resource_aws_iot_authorizer_test.go | 8 ++++---- ...zer-signing-key.pem => iot-authorizer-signing-key.pem} | 0 website/docs/r/iot_authorizer.html.markdown | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) rename aws/test-fixtures/{iot-authroizer-signing-key.pem => iot-authorizer-signing-key.pem} (100%) diff --git a/aws/resource_aws_iot_authorizer_test.go b/aws/resource_aws_iot_authorizer_test.go index 7c5b7598f8a5..9f7cd3473d26 100644 --- a/aws/resource_aws_iot_authorizer_test.go +++ b/aws/resource_aws_iot_authorizer_test.go @@ -170,7 +170,7 @@ resource "aws_iot_authorizer" "test" { status = "ACTIVE" token_key_name = "Token-Header" token_signing_public_keys = { - Key1 = "${file("test-fixtures/iot-authroizer-signing-key.pem")}" + Key1 = "${file("test-fixtures/iot-authorizer-signing-key.pem")}" } } `, rName) @@ -185,8 +185,8 @@ resource "aws_iot_authorizer" "test" { token_key_name = "Token-Header" status = "INACTIVE" token_signing_public_keys = { - Key1 = "${file("test-fixtures/iot-authroizer-signing-key.pem")}" - Key2 = "${file("test-fixtures/iot-authroizer-signing-key.pem")}" + Key1 = "${file("test-fixtures/iot-authorizer-signing-key.pem")}" + Key2 = "${file("test-fixtures/iot-authorizer-signing-key.pem")}" } } `, rName) @@ -200,7 +200,7 @@ resource "aws_iot_authorizer" "test" { signing_disabled = false token_key_name = "Token-Header" token_signing_public_keys = { - Key1 = "${file("test-fixtures/iot-authroizer-signing-key.pem")}" + Key1 = "${file("test-fixtures/iot-authorizer-signing-key.pem")}" } } `, rName) diff --git a/aws/test-fixtures/iot-authroizer-signing-key.pem b/aws/test-fixtures/iot-authorizer-signing-key.pem similarity index 100% rename from aws/test-fixtures/iot-authroizer-signing-key.pem rename to aws/test-fixtures/iot-authorizer-signing-key.pem diff --git a/website/docs/r/iot_authorizer.html.markdown b/website/docs/r/iot_authorizer.html.markdown index 0067a8dcd100..fa1a45348c56 100644 --- a/website/docs/r/iot_authorizer.html.markdown +++ b/website/docs/r/iot_authorizer.html.markdown @@ -20,7 +20,7 @@ resource "aws_iot_authorizer" "example" { status = "ACTIVE" token_key_name = "Token-Header" token_signing_public_keys = { - Key1 = "${file("test-fixtures/iot-authroizer-signing-key.pem")}" + Key1 = "${file("test-fixtures/iot-authorizer-signing-key.pem")}" } } ``` From 319afa28362a3070fa85850386cf8e6f0742cdbd Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Mon, 27 Sep 2021 17:48:02 -0400 Subject: [PATCH 6/9] r/aws_iot_authorizer: Documentation tweaks. --- website/docs/r/iot_authorizer.html.markdown | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/website/docs/r/iot_authorizer.html.markdown b/website/docs/r/iot_authorizer.html.markdown index fa1a45348c56..fa21a1e82d4c 100644 --- a/website/docs/r/iot_authorizer.html.markdown +++ b/website/docs/r/iot_authorizer.html.markdown @@ -12,13 +12,14 @@ Creates and manages an AWS IoT Authorizer. ## Example Usage -```hcl +```terraform resource "aws_iot_authorizer" "example" { name = "example" authorizer_function_arn = aws_lambda_function.example.arn signing_disabled = false status = "ACTIVE" token_key_name = "Token-Header" + token_signing_public_keys = { Key1 = "${file("test-fixtures/iot-authorizer-signing-key.pem")}" } From 3115ad704d17e293d252a08d72c4b3aa9375f23e Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Mon, 27 Sep 2021 17:48:39 -0400 Subject: [PATCH 7/9] r/aws_iot_authorizer: Add and use 'internal/service/iot'. --- aws/internal/service/iot/finder/iot.go | 34 +++++ aws/resource_aws_iot_authorizer.go | 177 +++++++++++++----------- aws/resource_aws_iot_authorizer_test.go | 39 +++--- 3 files changed, 143 insertions(+), 107 deletions(-) create mode 100644 aws/internal/service/iot/finder/iot.go diff --git a/aws/internal/service/iot/finder/iot.go b/aws/internal/service/iot/finder/iot.go new file mode 100644 index 000000000000..cfde1ca65971 --- /dev/null +++ b/aws/internal/service/iot/finder/iot.go @@ -0,0 +1,34 @@ +package finder + +import ( + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/iot" + "github.com/hashicorp/aws-sdk-go-base/tfawserr" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/terraform-providers/terraform-provider-aws/aws/internal/tfresource" +) + +func AuthorizerByName(conn *iot.IoT, name string) (*iot.AuthorizerDescription, error) { + input := &iot.DescribeAuthorizerInput{ + AuthorizerName: aws.String(name), + } + + output, err := conn.DescribeAuthorizer(input) + + if tfawserr.ErrCodeEquals(err, iot.ErrCodeResourceNotFoundException) { + return nil, &resource.NotFoundError{ + LastError: err, + LastRequest: input, + } + } + + if err != nil { + return nil, err + } + + if output == nil || output.AuthorizerDescription == nil { + return nil, tfresource.NewEmptyResultError(input) + } + + return output.AuthorizerDescription, nil +} diff --git a/aws/resource_aws_iot_authorizer.go b/aws/resource_aws_iot_authorizer.go index 2f077c1b0e0c..15b727bfad4f 100644 --- a/aws/resource_aws_iot_authorizer.go +++ b/aws/resource_aws_iot_authorizer.go @@ -2,15 +2,16 @@ package aws import ( "fmt" - "github.com/aws/aws-sdk-go/service/iot" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "log" "regexp" - "time" "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/iot" + "github.com/hashicorp/aws-sdk-go-base/tfawserr" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" + "github.com/terraform-providers/terraform-provider-aws/aws/internal/service/iot/finder" + "github.com/terraform-providers/terraform-provider-aws/aws/internal/tfresource" ) func resourceAwsIoTAuthorizer() *schema.Resource { @@ -25,6 +26,15 @@ func resourceAwsIoTAuthorizer() *schema.Resource { }, Schema: map[string]*schema.Schema{ + "arn": { + Type: schema.TypeString, + Computed: true, + }, + "authorizer_function_arn": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validateArn, + }, "name": { Type: schema.TypeString, Required: true, @@ -33,23 +43,15 @@ func resourceAwsIoTAuthorizer() *schema.Resource { validation.StringMatch(regexp.MustCompile(`^[\w=,@-]+`), "must contain only alphanumeric characters, underscores, and hyphens"), ), }, - "authorizer_function_arn": { - Type: schema.TypeString, - Required: true, - ValidateFunc: validateArn, - }, "signing_disabled": { Type: schema.TypeBool, Required: true, }, "status": { - Type: schema.TypeString, - Optional: true, - Default: iot.AuthorizerStatusActive, - ValidateFunc: validation.StringInSlice([]string{ - iot.AuthorizerStatusActive, - iot.AuthorizerStatusInactive, - }, false), + Type: schema.TypeString, + Optional: true, + Default: iot.AuthorizerStatusActive, + ValidateFunc: validation.StringInSlice(iot.AuthorizerStatus_Values(), false), }, "token_key_name": { Type: schema.TypeString, @@ -72,27 +74,27 @@ func resourceAwsIoTAuthorizer() *schema.Resource { func resourceAwsIotAuthorizerCreate(d *schema.ResourceData, meta interface{}) error { conn := meta.(*AWSClient).iotconn - tokenSigningPublicKeys := make(map[string]string) - for k, v := range d.Get("token_signing_public_keys").(map[string]interface{}) { - tokenSigningPublicKeys[k] = v.(string) - } - - input := iot.CreateAuthorizerInput{ + name := d.Get("name").(string) + input := &iot.CreateAuthorizerInput{ AuthorizerFunctionArn: aws.String(d.Get("authorizer_function_arn").(string)), - AuthorizerName: aws.String(d.Get("name").(string)), + AuthorizerName: aws.String(name), SigningDisabled: aws.Bool(d.Get("signing_disabled").(bool)), Status: aws.String(d.Get("status").(string)), - TokenKeyName: aws.String(d.Get("token_key_name").(string)), - TokenSigningPublicKeys: aws.StringMap(tokenSigningPublicKeys), + TokenSigningPublicKeys: expandStringMap(d.Get("token_signing_public_keys").(map[string]interface{})), + } + + if v, ok := d.GetOk("token_key_name"); ok { + input.TokenKeyName = aws.String(v.(string)) } log.Printf("[INFO] Creating IoT Authorizer: %s", input) - out, err := conn.CreateAuthorizer(&input) + output, err := conn.CreateAuthorizer(input) + if err != nil { - return fmt.Errorf("Error creating IoT Authorizer: %w", err) + return fmt.Errorf("error creating IoT Authorizer (%s): %w", name, err) } - d.SetId(aws.StringValue(out.AuthorizerName)) + d.SetId(aws.StringValue(output.AuthorizerName)) return resourceAwsIotAuthorizerRead(d, meta) } @@ -100,31 +102,25 @@ func resourceAwsIotAuthorizerCreate(d *schema.ResourceData, meta interface{}) er func resourceAwsIotAuthorizerRead(d *schema.ResourceData, meta interface{}) error { conn := meta.(*AWSClient).iotconn - log.Printf("[INFO] Reading IoT Authorizer %s", d.Id()) - input := iot.DescribeAuthorizerInput{ - AuthorizerName: aws.String(d.Id()), + authorizer, err := finder.AuthorizerByName(conn, d.Id()) + + if !d.IsNewResource() && tfresource.NotFound(err) { + log.Printf("[WARN] IoT Authorizer (%s) not found, removing from state", d.Id()) + d.SetId("") + return nil } - authorizerDescription, err := conn.DescribeAuthorizer(&input) if err != nil { - if isAWSErr(err, iot.ErrCodeResourceNotFoundException, "") { - log.Printf("[WARN] No IoT Authorizer (%s) not found, removing from state", d.Id()) - d.SetId("") - return nil - } - return err + return fmt.Errorf("error reading IoT Authorizer (%s): %w", d.Id(), err) } - authorizer := authorizerDescription.AuthorizerDescription - log.Printf("[DEBUG] Received IoT Authorizer: %s", authorizer) + d.Set("arn", authorizer.AuthorizerArn) d.Set("authorizer_function_arn", authorizer.AuthorizerFunctionArn) + d.Set("name", authorizer.AuthorizerName) d.Set("signing_disabled", authorizer.SigningDisabled) d.Set("status", authorizer.Status) d.Set("token_key_name", authorizer.TokenKeyName) - d.Set("name", authorizer.AuthorizerName) - if err := d.Set("token_signing_public_keys", authorizer.TokenSigningPublicKeys); err != nil { - return fmt.Errorf("Error setting token signing keys for IoT Authrozer: %s", err) - } + d.Set("token_signing_public_keys", aws.StringValueMap(authorizer.TokenSigningPublicKeys)) return nil } @@ -132,23 +128,31 @@ func resourceAwsIotAuthorizerRead(d *schema.ResourceData, meta interface{}) erro func resourceAwsIotAuthorizerUpdate(d *schema.ResourceData, meta interface{}) error { conn := meta.(*AWSClient).iotconn - tokenSigningPublicKeys := make(map[string]string) - for k, v := range d.Get("token_signing_public_keys").(map[string]interface{}) { - tokenSigningPublicKeys[k] = v.(string) + input := iot.UpdateAuthorizerInput{ + AuthorizerName: aws.String(d.Id()), + } + + if d.HasChange("authorizer_function_arn") { + input.AuthorizerFunctionArn = aws.String(d.Get("authorizer_function_arn").(string)) } - input := iot.UpdateAuthorizerInput{ - AuthorizerFunctionArn: aws.String(d.Get("authorizer_function_arn").(string)), - AuthorizerName: aws.String(d.Id()), - Status: aws.String(d.Get("status").(string)), - TokenKeyName: aws.String(d.Get("token_key_name").(string)), - TokenSigningPublicKeys: aws.StringMap(tokenSigningPublicKeys), + if d.HasChange("status") { + input.Status = aws.String(d.Get("status").(string)) + } + + if d.HasChange("token_key_name") { + input.TokenKeyName = aws.String(d.Get("token_key_name").(string)) + } + + if d.HasChange("token_signing_public_keys") { + input.TokenSigningPublicKeys = expandStringMap(d.Get("token_signing_public_keys").(map[string]interface{})) } log.Printf("[INFO] Updating IoT Authorizer: %s", input) _, err := conn.UpdateAuthorizer(&input) + if err != nil { - return fmt.Errorf("Updating IoT Authorizer failed: %w", err) + return fmt.Errorf("error updating IoT Authorizer (%s): %w", d.Id(), err) } return resourceAwsIotAuthorizerRead(d, meta) @@ -156,52 +160,57 @@ func resourceAwsIotAuthorizerUpdate(d *schema.ResourceData, meta interface{}) er func resourceAwsIotAuthorizerDelete(d *schema.ResourceData, meta interface{}) error { conn := meta.(*AWSClient).iotconn - input := iot.DeleteAuthorizerInput{ - AuthorizerName: aws.String(d.Id()), - } - - status := d.Get("status").(string) // In order to delete an IoT Authorizer, you must set it inactive first. - if status == iot.AuthorizerStatusActive { - setInactiveError := d.Set("status", iot.AuthorizerStatusInactive) - - if setInactiveError != nil { - return fmt.Errorf("Setting IoT Authorizer to INACTIVE failed: %w", setInactiveError) + if d.Get("status").(string) == iot.AuthorizerStatusActive { + log.Printf("[INFO] Deactivating IoT Authorizer: %s", d.Id()) + _, err := conn.UpdateAuthorizer(&iot.UpdateAuthorizerInput{ + AuthorizerName: aws.String(d.Id()), + Status: aws.String(iot.AuthorizerStatusInactive), + }) + if err != nil { + return fmt.Errorf("error deactivating IoT Authorizer (%s): %w", d.Id(), err) } - updateErr := resourceAwsIotAuthorizerUpdate(d, meta) + } - if updateErr != nil { - return fmt.Errorf("Updating IoT Authorizer to INACTIVE failed: %w", updateErr) - } + log.Printf("[INFO] Deleting IoT Authorizer: %s", d.Id()) + _, err := conn.DeleteAuthorizer(&iot.DeleteAuthorizerInput{ + AuthorizerName: aws.String(d.Id()), + }) + + if tfawserr.ErrCodeEquals(err, iot.ErrCodeResourceNotFoundException) { + return nil } - log.Printf("[INFO] Deleting IoT Authorizer: %s", input) - err := resource.Retry(5*time.Minute, func() *resource.RetryError { - _, err := conn.DeleteAuthorizer(&input) + /* + err := resource.Retry(5*time.Minute, func() *resource.RetryError { + _, err := conn.DeleteAuthorizer(&input) - if err != nil { - if isAWSErr(err, iot.ErrCodeInvalidRequestException, "") { - return resource.RetryableError(err) + if err != nil { + if isAWSErr(err, iot.ErrCodeInvalidRequestException, "") { + return resource.RetryableError(err) + } + if isAWSErr(err, iot.ErrCodeResourceNotFoundException, "") { + return nil + } + + return resource.NonRetryableError(err) } + + return nil + }) + if isResourceTimeoutError(err) { + _, err = conn.DeleteAuthorizer(&input) if isAWSErr(err, iot.ErrCodeResourceNotFoundException, "") { return nil } - - return resource.NonRetryableError(err) } + */ - return nil - }) - if isResourceTimeoutError(err) { - _, err = conn.DeleteAuthorizer(&input) - if isAWSErr(err, iot.ErrCodeResourceNotFoundException, "") { - return nil - } - } if err != nil { - return fmt.Errorf("Error deleting IOT Authorizer: %s", err) + return fmt.Errorf("error deleting IOT Authorizer (%s): %w", d.Id(), err) } + return nil } diff --git a/aws/resource_aws_iot_authorizer_test.go b/aws/resource_aws_iot_authorizer_test.go index 9f7cd3473d26..6c1e341da8ae 100644 --- a/aws/resource_aws_iot_authorizer_test.go +++ b/aws/resource_aws_iot_authorizer_test.go @@ -2,23 +2,24 @@ package aws import ( "fmt" - "github.com/aws/aws-sdk-go/service/iot" "testing" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/awserr" + "github.com/aws/aws-sdk-go/service/iot" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + "github.com/terraform-providers/terraform-provider-aws/aws/internal/service/iot/finder" + "github.com/terraform-providers/terraform-provider-aws/aws/internal/tfresource" ) func TestAccAWSIoTAuthorizer_basic(t *testing.T) { - var conf iot.DescribeAuthorizerOutput + var conf iot.AuthorizerDescription rName := acctest.RandomWithPrefix("tf-acc-test") resourceName := "aws_iot_authorizer.test" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, + ErrorCheck: testAccErrorCheck(t, iot.EndpointsID), Providers: testAccProviders, CheckDestroy: testAccCheckAWSIoTAuthorizerDestroy, Steps: []resource.TestStep{ @@ -49,12 +50,13 @@ func TestAccAWSIoTAuthorizer_basic(t *testing.T) { } func TestAccAWSIoTAuthorizer_disappears(t *testing.T) { - var conf iot.DescribeAuthorizerOutput + var conf iot.AuthorizerDescription rName := acctest.RandomWithPrefix("tf-acc-test") resourceName := "aws_iot_authorizer.test" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, + ErrorCheck: testAccErrorCheck(t, iot.EndpointsID), Providers: testAccProviders, CheckDestroy: testAccCheckAWSIoTAuthorizerDestroy, Steps: []resource.TestStep{ @@ -70,7 +72,7 @@ func TestAccAWSIoTAuthorizer_disappears(t *testing.T) { }) } -func testAccCheckAWSIoTAuthorizerExists(n string, res *iot.DescribeAuthorizerOutput) resource.TestCheckFunc { +func testAccCheckAWSIoTAuthorizerExists(n string, v *iot.AuthorizerDescription) resource.TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[n] if !ok { @@ -83,15 +85,13 @@ func testAccCheckAWSIoTAuthorizerExists(n string, res *iot.DescribeAuthorizerOut conn := testAccProvider.Meta().(*AWSClient).iotconn - req := &iot.DescribeAuthorizerInput{ - AuthorizerName: aws.String(rs.Primary.ID), - } - describe, err := conn.DescribeAuthorizer(req) + output, err := finder.AuthorizerByName(conn, rs.Primary.ID) + if err != nil { return err } - *res = *describe + *v = *output return nil } @@ -105,24 +105,17 @@ func testAccCheckAWSIoTAuthorizerDestroy(s *terraform.State) error { continue } - req := &iot.DescribeAuthorizerInput{ - AuthorizerName: aws.String(rs.Primary.ID), - } - _, err := conn.DescribeAuthorizer(req) + _, err := finder.AuthorizerByName(conn, rs.Primary.ID) - if err == nil { - return fmt.Errorf("IoT Authorizer still exists") + if tfresource.NotFound(err) { + continue } - aws2err, ok := err.(awserr.Error) - if !ok { - return err - } - if aws2err.Code() != iot.ErrCodeResourceNotFoundException { + if err != nil { return err } - return nil + return fmt.Errorf("IoT Authorizer %s still exists", rs.Primary.ID) } return nil From 8004165bcc5ffe228e6d156228355c08f3c3a8b2 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Tue, 28 Sep 2021 10:02:24 -0400 Subject: [PATCH 8/9] r/aws_iot_authorizer: 'token_key_name' and 'token_signing_public_keys' are only required if signing is enabled. --- aws/resource_aws_iot_authorizer.go | 58 ++++---- aws/resource_aws_iot_authorizer_test.go | 145 ++++++++++++++------ website/docs/r/iot_authorizer.html.markdown | 10 +- 3 files changed, 138 insertions(+), 75 deletions(-) diff --git a/aws/resource_aws_iot_authorizer.go b/aws/resource_aws_iot_authorizer.go index 15b727bfad4f..450bc72675b7 100644 --- a/aws/resource_aws_iot_authorizer.go +++ b/aws/resource_aws_iot_authorizer.go @@ -1,6 +1,8 @@ package aws import ( + "context" + "errors" "fmt" "log" "regexp" @@ -25,6 +27,8 @@ func resourceAwsIoTAuthorizer() *schema.Resource { State: schema.ImportStatePassthrough, }, + CustomizeDiff: resourceAwsIotAuthorizerCustomizeDiff, + Schema: map[string]*schema.Schema{ "arn": { Type: schema.TypeString, @@ -45,7 +49,8 @@ func resourceAwsIoTAuthorizer() *schema.Resource { }, "signing_disabled": { Type: schema.TypeBool, - Required: true, + Optional: true, + Default: false, }, "status": { Type: schema.TypeString, @@ -63,7 +68,7 @@ func resourceAwsIoTAuthorizer() *schema.Resource { }, "token_signing_public_keys": { Type: schema.TypeMap, - Required: true, + Optional: true, Elem: &schema.Schema{Type: schema.TypeString}, Sensitive: true, }, @@ -76,17 +81,20 @@ func resourceAwsIotAuthorizerCreate(d *schema.ResourceData, meta interface{}) er name := d.Get("name").(string) input := &iot.CreateAuthorizerInput{ - AuthorizerFunctionArn: aws.String(d.Get("authorizer_function_arn").(string)), - AuthorizerName: aws.String(name), - SigningDisabled: aws.Bool(d.Get("signing_disabled").(bool)), - Status: aws.String(d.Get("status").(string)), - TokenSigningPublicKeys: expandStringMap(d.Get("token_signing_public_keys").(map[string]interface{})), + AuthorizerFunctionArn: aws.String(d.Get("authorizer_function_arn").(string)), + AuthorizerName: aws.String(name), + SigningDisabled: aws.Bool(d.Get("signing_disabled").(bool)), + Status: aws.String(d.Get("status").(string)), } if v, ok := d.GetOk("token_key_name"); ok { input.TokenKeyName = aws.String(v.(string)) } + if v, ok := d.GetOk("token_signing_public_keys"); ok { + input.TokenSigningPublicKeys = expandStringMap(v.(map[string]interface{})) + } + log.Printf("[INFO] Creating IoT Authorizer: %s", input) output, err := conn.CreateAuthorizer(input) @@ -183,33 +191,21 @@ func resourceAwsIotAuthorizerDelete(d *schema.ResourceData, meta interface{}) er return nil } - /* - err := resource.Retry(5*time.Minute, func() *resource.RetryError { - _, err := conn.DeleteAuthorizer(&input) - - if err != nil { - if isAWSErr(err, iot.ErrCodeInvalidRequestException, "") { - return resource.RetryableError(err) - } - if isAWSErr(err, iot.ErrCodeResourceNotFoundException, "") { - return nil - } + if err != nil { + return fmt.Errorf("error deleting IOT Authorizer (%s): %w", d.Id(), err) + } - return resource.NonRetryableError(err) - } + return nil +} - return nil - }) - if isResourceTimeoutError(err) { - _, err = conn.DeleteAuthorizer(&input) - if isAWSErr(err, iot.ErrCodeResourceNotFoundException, "") { - return nil - } +func resourceAwsIotAuthorizerCustomizeDiff(_ context.Context, diff *schema.ResourceDiff, v interface{}) error { + if !diff.Get("signing_disabled").(bool) { + if _, ok := diff.GetOk("token_key_name"); !ok { + return errors.New(`"token_key_name" is required when signing is enabled`) + } + if _, ok := diff.GetOk("token_signing_public_keys"); !ok { + return errors.New(`"token_signing_public_keys" is required when signing is enabled`) } - */ - - if err != nil { - return fmt.Errorf("error deleting IOT Authorizer (%s): %w", d.Id(), err) } return nil diff --git a/aws/resource_aws_iot_authorizer_test.go b/aws/resource_aws_iot_authorizer_test.go index 6c1e341da8ae..82de8e844fdc 100644 --- a/aws/resource_aws_iot_authorizer_test.go +++ b/aws/resource_aws_iot_authorizer_test.go @@ -24,32 +24,83 @@ func TestAccAWSIoTAuthorizer_basic(t *testing.T) { CheckDestroy: testAccCheckAWSIoTAuthorizerDestroy, Steps: []resource.TestStep{ { - Config: testAccAWSIoTAuthorizerConfig(rName), + Config: testAccAWSIoTAuthorizerConfigBasic(rName), Check: resource.ComposeTestCheckFunc( testAccCheckAWSIoTAuthorizerExists(resourceName, &conf), + testAccCheckResourceAttrRegionalARN(resourceName, "arn", "iot", fmt.Sprintf("authorizer/%s", rName)), + resource.TestCheckResourceAttr(resourceName, "name", rName), + resource.TestCheckResourceAttr(resourceName, "signing_disabled", "false"), + resource.TestCheckResourceAttr(resourceName, "status", "ACTIVE"), + resource.TestCheckResourceAttr(resourceName, "token_key_name", "Token-Header-1"), + resource.TestCheckResourceAttr(resourceName, "token_signing_public_keys.%", "1"), + resource.TestCheckResourceAttrSet(resourceName, "token_signing_public_keys.Key1"), ), }, { - Config: testAccAWSIoTAuthorizerConfig_defaultStatus(rName), + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccAWSIoTAuthorizer_disappears(t *testing.T) { + var conf iot.AuthorizerDescription + rName := acctest.RandomWithPrefix("tf-acc-test") + resourceName := "aws_iot_authorizer.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ErrorCheck: testAccErrorCheck(t, iot.EndpointsID), + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSIoTAuthorizerDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSIoTAuthorizerConfigBasic(rName), Check: resource.ComposeTestCheckFunc( testAccCheckAWSIoTAuthorizerExists(resourceName, &conf), - resource.TestCheckResourceAttr(resourceName, "status", iot.AuthorizerStatusActive), + testAccCheckResourceDisappears(testAccProvider, resourceAwsIoTAuthorizer(), resourceName), ), + ExpectNonEmptyPlan: true, }, + }, + }) +} + +func TestAccAWSIoTAuthorizer_SigningDisabled(t *testing.T) { + var conf iot.AuthorizerDescription + rName := acctest.RandomWithPrefix("tf-acc-test") + resourceName := "aws_iot_authorizer.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ErrorCheck: testAccErrorCheck(t, iot.EndpointsID), + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSIoTAuthorizerDestroy, + Steps: []resource.TestStep{ { - Config: testAccAWSIoTAuthorizerConfig_update(rName), + Config: testAccAWSIoTAuthorizerConfigSigningDisabled(rName), Check: resource.ComposeTestCheckFunc( testAccCheckAWSIoTAuthorizerExists(resourceName, &conf), - resource.TestCheckResourceAttr(resourceName, "signing_disabled", "false"), + testAccCheckResourceAttrRegionalARN(resourceName, "arn", "iot", fmt.Sprintf("authorizer/%s", rName)), resource.TestCheckResourceAttr(resourceName, "name", rName), - resource.TestCheckResourceAttr(resourceName, "status", iot.AuthorizerStatusInactive), + resource.TestCheckResourceAttr(resourceName, "signing_disabled", "true"), + resource.TestCheckResourceAttr(resourceName, "status", "INACTIVE"), + resource.TestCheckResourceAttr(resourceName, "token_key_name", ""), + resource.TestCheckResourceAttr(resourceName, "token_signing_public_keys.%", "0"), ), }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, }, }) } -func TestAccAWSIoTAuthorizer_disappears(t *testing.T) { +func TestAccAWSIoTAuthorizer_Update(t *testing.T) { var conf iot.AuthorizerDescription rName := acctest.RandomWithPrefix("tf-acc-test") resourceName := "aws_iot_authorizer.test" @@ -61,12 +112,31 @@ func TestAccAWSIoTAuthorizer_disappears(t *testing.T) { CheckDestroy: testAccCheckAWSIoTAuthorizerDestroy, Steps: []resource.TestStep{ { - Config: testAccAWSIoTAuthorizerConfig(rName), + Config: testAccAWSIoTAuthorizerConfigBasic(rName), Check: resource.ComposeTestCheckFunc( testAccCheckAWSIoTAuthorizerExists(resourceName, &conf), - testAccCheckResourceDisappears(testAccProvider, resourceAwsIoTAuthorizer(), resourceName), + testAccCheckResourceAttrRegionalARN(resourceName, "arn", "iot", fmt.Sprintf("authorizer/%s", rName)), + resource.TestCheckResourceAttr(resourceName, "name", rName), + resource.TestCheckResourceAttr(resourceName, "signing_disabled", "false"), + resource.TestCheckResourceAttr(resourceName, "status", "ACTIVE"), + resource.TestCheckResourceAttr(resourceName, "token_key_name", "Token-Header-1"), + resource.TestCheckResourceAttr(resourceName, "token_signing_public_keys.%", "1"), + resource.TestCheckResourceAttrSet(resourceName, "token_signing_public_keys.Key1"), + ), + }, + { + Config: testAccAWSIoTAuthorizerConfigUpdated(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSIoTAuthorizerExists(resourceName, &conf), + testAccCheckResourceAttrRegionalARN(resourceName, "arn", "iot", fmt.Sprintf("authorizer/%s", rName)), + resource.TestCheckResourceAttr(resourceName, "name", rName), + resource.TestCheckResourceAttr(resourceName, "signing_disabled", "false"), + resource.TestCheckResourceAttr(resourceName, "status", "INACTIVE"), + resource.TestCheckResourceAttr(resourceName, "token_key_name", "Token-Header-2"), + resource.TestCheckResourceAttr(resourceName, "token_signing_public_keys.%", "2"), + resource.TestCheckResourceAttrSet(resourceName, "token_signing_public_keys.Key1"), + resource.TestCheckResourceAttrSet(resourceName, "token_signing_public_keys.Key2"), ), - ExpectNonEmptyPlan: true, }, }, }) @@ -123,8 +193,8 @@ func testAccCheckAWSIoTAuthorizerDestroy(s *terraform.State) error { func testAccAWSIoTAuthorizerConfigBase(rName string) string { return fmt.Sprintf(` -resource "aws_iam_role" "lambda" { - name = "%[1]s-lambda" +resource "aws_iam_role" "test" { + name = %[1]q assume_role_policy = < Date: Tue, 28 Sep 2021 10:13:12 -0400 Subject: [PATCH 9/9] Fix tfproviderdocs error. --- website/docs/r/iot_authorizer.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/r/iot_authorizer.html.markdown b/website/docs/r/iot_authorizer.html.markdown index 8fee11e27e88..d504c7f66d19 100644 --- a/website/docs/r/iot_authorizer.html.markdown +++ b/website/docs/r/iot_authorizer.html.markdown @@ -37,7 +37,7 @@ resource "aws_iot_authorizer" "example" { ## Attributes Reference -In addition to the arguments above, the following attributes are exported: +In addition to all arguments above, the following attributes are exported: * `arn` - The ARN of the authorizer.