From 13a4b4109c046eed393b3e711dc2259090c1bdbd Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Mon, 3 Jun 2019 09:40:32 -0400 Subject: [PATCH 1/3] Add 'aws_api_gateway_v2_authorizer' resource. --- aws/provider.go | 1 + aws/resource_aws_api_gateway2_authorizer.go | 174 +++++++++++++ ...source_aws_api_gateway2_authorizer_test.go | 237 ++++++++++++++++++ website/aws.erb | 3 + .../r/api_gateway_v2_authorizer.html.markdown | 53 ++++ 5 files changed, 468 insertions(+) create mode 100644 aws/resource_aws_api_gateway2_authorizer.go create mode 100644 aws/resource_aws_api_gateway2_authorizer_test.go create mode 100644 website/docs/r/api_gateway_v2_authorizer.html.markdown diff --git a/aws/provider.go b/aws/provider.go index 7de35b36bd84..1d3b8df66464 100644 --- a/aws/provider.go +++ b/aws/provider.go @@ -355,6 +355,7 @@ func Provider() terraform.ResourceProvider { "aws_api_gateway_usage_plan_key": resourceAwsApiGatewayUsagePlanKey(), "aws_api_gateway_vpc_link": resourceAwsApiGatewayVpcLink(), "aws_apigatewayv2_api": resourceAwsApiGatewayV2Api(), + "aws_api_gateway_v2_authorizer": resourceAwsApiGateway2Authorizer(), "aws_app_cookie_stickiness_policy": resourceAwsAppCookieStickinessPolicy(), "aws_appautoscaling_target": resourceAwsAppautoscalingTarget(), "aws_appautoscaling_policy": resourceAwsAppautoscalingPolicy(), diff --git a/aws/resource_aws_api_gateway2_authorizer.go b/aws/resource_aws_api_gateway2_authorizer.go new file mode 100644 index 000000000000..e08ba4e97f8c --- /dev/null +++ b/aws/resource_aws_api_gateway2_authorizer.go @@ -0,0 +1,174 @@ +package aws + +import ( + "fmt" + "log" + "strings" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/apigatewayv2" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/helper/validation" +) + +func resourceAwsApiGateway2Authorizer() *schema.Resource { + return &schema.Resource{ + Create: resourceAwsApiGateway2AuthorizerCreate, + Read: resourceAwsApiGateway2AuthorizerRead, + Update: resourceAwsApiGateway2AuthorizerUpdate, + Delete: resourceAwsApiGateway2AuthorizerDelete, + Importer: &schema.ResourceImporter{ + State: resourceAwsApiGateway2AuthorizerImport, + }, + + Schema: map[string]*schema.Schema{ + "api_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "authorizer_credentials_arn": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validateArn, + }, + "authorizer_type": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{ + apigatewayv2.AuthorizerTypeRequest, + }, false), + }, + "authorizer_uri": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringLenBetween(1, 2048), + }, + "identity_sources": { + Type: schema.TypeSet, + Required: true, + MinItems: 1, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "name": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringLenBetween(1, 128), + }, + }, + } +} + +func resourceAwsApiGateway2AuthorizerCreate(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).apigatewayv2conn + + req := &apigatewayv2.CreateAuthorizerInput{ + ApiId: aws.String(d.Get("api_id").(string)), + AuthorizerType: aws.String(d.Get("authorizer_type").(string)), + AuthorizerUri: aws.String(d.Get("authorizer_uri").(string)), + IdentitySource: expandStringSet(d.Get("identity_sources").(*schema.Set)), + Name: aws.String(d.Get("name").(string)), + } + if v, ok := d.GetOk("authorizer_credentials_arn"); ok { + req.AuthorizerCredentialsArn = aws.String(v.(string)) + } + + log.Printf("[DEBUG] Creating API Gateway v2 authorizer: %s", req) + resp, err := conn.CreateAuthorizer(req) + if err != nil { + return fmt.Errorf("error creating API Gateway v2 authorizer: %s", err) + } + + d.SetId(aws.StringValue(resp.AuthorizerId)) + + return resourceAwsApiGateway2AuthorizerRead(d, meta) +} + +func resourceAwsApiGateway2AuthorizerRead(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).apigatewayv2conn + + resp, err := conn.GetAuthorizer(&apigatewayv2.GetAuthorizerInput{ + ApiId: aws.String(d.Get("api_id").(string)), + AuthorizerId: aws.String(d.Id()), + }) + if isAWSErr(err, apigatewayv2.ErrCodeNotFoundException, "") { + log.Printf("[WARN] API Gateway v2 authorizer (%s) not found, removing from state", d.Id()) + d.SetId("") + return nil + } + if err != nil { + return fmt.Errorf("error reading API Gateway v2 authorizer: %s", err) + } + + d.Set("authorizer_credentials_arn", resp.AuthorizerCredentialsArn) + d.Set("authorizer_type", resp.AuthorizerType) + d.Set("authorizer_uri", resp.AuthorizerUri) + if err := d.Set("identity_sources", flattenStringSet(resp.IdentitySource)); err != nil { + return fmt.Errorf("error setting identity_sources: %s", err) + } + d.Set("name", resp.Name) + + return nil +} + +func resourceAwsApiGateway2AuthorizerUpdate(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).apigatewayv2conn + + req := &apigatewayv2.UpdateAuthorizerInput{ + ApiId: aws.String(d.Get("api_id").(string)), + AuthorizerId: aws.String(d.Id()), + } + if d.HasChange("authorizer_credentials_arn") { + req.AuthorizerCredentialsArn = aws.String(d.Get("authorizer_credentials_arn").(string)) + } + if d.HasChange("authorizer_type") { + req.AuthorizerType = aws.String(d.Get("authorizer_type").(string)) + } + if d.HasChange("authorizer_uri") { + req.AuthorizerUri = aws.String(d.Get("authorizer_uri").(string)) + } + if d.HasChange("identity_sources") { + req.IdentitySource = expandStringSet(d.Get("identity_sources").(*schema.Set)) + } + if d.HasChange("name") { + req.Name = aws.String(d.Get("name").(string)) + } + + log.Printf("[DEBUG] Updating API Gateway v2 authorizer: %s", req) + _, err := conn.UpdateAuthorizer(req) + if err != nil { + return fmt.Errorf("error updating API Gateway v2 authorizer: %s", err) + } + + return resourceAwsApiGateway2AuthorizerRead(d, meta) +} + +func resourceAwsApiGateway2AuthorizerDelete(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).apigatewayv2conn + + log.Printf("[DEBUG] Deleting API Gateway v2 authorizer (%s)", d.Id()) + _, err := conn.DeleteAuthorizer(&apigatewayv2.DeleteAuthorizerInput{ + ApiId: aws.String(d.Get("api_id").(string)), + AuthorizerId: aws.String(d.Id()), + }) + if isAWSErr(err, apigatewayv2.ErrCodeNotFoundException, "") { + return nil + } + if err != nil { + return fmt.Errorf("error deleting API Gateway v2 authorizer: %s", err) + } + + return nil +} + +func resourceAwsApiGateway2AuthorizerImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { + parts := strings.Split(d.Id(), "/") + if len(parts) != 2 { + return []*schema.ResourceData{}, fmt.Errorf("Wrong format of resource: %s. Please follow 'api-id/authorizer-id'", d.Id()) + } + + d.SetId(parts[1]) + d.Set("api_id", parts[0]) + + return []*schema.ResourceData{d}, nil +} diff --git a/aws/resource_aws_api_gateway2_authorizer_test.go b/aws/resource_aws_api_gateway2_authorizer_test.go new file mode 100644 index 000000000000..b6738422b303 --- /dev/null +++ b/aws/resource_aws_api_gateway2_authorizer_test.go @@ -0,0 +1,237 @@ +package aws + +import ( + "fmt" + "testing" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/apigatewayv2" + "github.com/hashicorp/terraform-plugin-sdk/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/terraform" +) + +func TestAccAWSAPIGateway2Authorizer_basic(t *testing.T) { + resourceName := "aws_api_gateway_v2_authorizer.test" + lambdaResourceName := "aws_lambda_function.test" + rName := fmt.Sprintf("tf-testacc-apigwv2-%s", acctest.RandStringFromCharSet(13, acctest.CharSetAlphaNum)) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSAPIGateway2AuthorizerDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSAPIGateway2AuthorizerConfig_basic(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSAPIGateway2AuthorizerExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "authorizer_credentials_arn", ""), + resource.TestCheckResourceAttr(resourceName, "authorizer_type", "REQUEST"), + resource.TestCheckResourceAttrPair(resourceName, "authorizer_uri", lambdaResourceName, "invoke_arn"), + resource.TestCheckResourceAttr(resourceName, "identity_sources.#", "1"), + resource.TestCheckResourceAttr(resourceName, "identity_sources.645907014", "route.request.header.Auth"), + resource.TestCheckResourceAttr(resourceName, "name", rName), + ), + }, + { + ResourceName: resourceName, + ImportStateIdFunc: testAccAWSAPIGateway2AuthorizerImportStateIdFunc(resourceName), + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccAWSAPIGateway2Authorizer_Credentials(t *testing.T) { + resourceName := "aws_api_gateway_v2_authorizer.test" + iamRoleResourceName := "aws_iam_role.test" + lambdaResourceName := "aws_lambda_function.test" + rName := fmt.Sprintf("tf-testacc-apigwv2-%s", acctest.RandStringFromCharSet(13, acctest.CharSetAlphaNum)) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSAPIGateway2AuthorizerDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSAPIGateway2AuthorizerConfig_credentials(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSAPIGateway2AuthorizerExists(resourceName), + resource.TestCheckResourceAttrPair(resourceName, "authorizer_credentials_arn", iamRoleResourceName, "arn"), + resource.TestCheckResourceAttr(resourceName, "authorizer_type", "REQUEST"), + resource.TestCheckResourceAttrPair(resourceName, "authorizer_uri", lambdaResourceName, "invoke_arn"), + resource.TestCheckResourceAttr(resourceName, "identity_sources.#", "1"), + resource.TestCheckResourceAttr(resourceName, "identity_sources.645907014", "route.request.header.Auth"), + resource.TestCheckResourceAttr(resourceName, "name", rName), + ), + }, + { + ResourceName: resourceName, + ImportStateIdFunc: testAccAWSAPIGateway2AuthorizerImportStateIdFunc(resourceName), + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccAWSAPIGateway2AuthorizerConfig_credentialsUpdated(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSAPIGateway2AuthorizerExists(resourceName), + resource.TestCheckResourceAttrPair(resourceName, "authorizer_credentials_arn", iamRoleResourceName, "arn"), + resource.TestCheckResourceAttr(resourceName, "authorizer_type", "REQUEST"), + resource.TestCheckResourceAttrPair(resourceName, "authorizer_uri", lambdaResourceName, "invoke_arn"), + resource.TestCheckResourceAttr(resourceName, "identity_sources.#", "2"), + resource.TestCheckResourceAttr(resourceName, "identity_sources.645907014", "route.request.header.Auth"), + resource.TestCheckResourceAttr(resourceName, "identity_sources.4138478046", "route.request.querystring.Name"), + resource.TestCheckResourceAttr(resourceName, "name", fmt.Sprintf("%s-updated", rName)), + ), + }, + { + Config: testAccAWSAPIGateway2AuthorizerConfig_basic(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSAPIGateway2AuthorizerExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "authorizer_credentials_arn", ""), + resource.TestCheckResourceAttr(resourceName, "authorizer_type", "REQUEST"), + resource.TestCheckResourceAttrPair(resourceName, "authorizer_uri", lambdaResourceName, "invoke_arn"), + resource.TestCheckResourceAttr(resourceName, "identity_sources.#", "1"), + resource.TestCheckResourceAttr(resourceName, "identity_sources.645907014", "route.request.header.Auth"), + resource.TestCheckResourceAttr(resourceName, "name", rName), + ), + }, + }, + }) +} + +func testAccCheckAWSAPIGateway2AuthorizerDestroy(s *terraform.State) error { + conn := testAccProvider.Meta().(*AWSClient).apigatewayv2conn + + for _, rs := range s.RootModule().Resources { + if rs.Type != "aws_api_gateway_v2_authorizer" { + continue + } + + _, err := conn.GetAuthorizer(&apigatewayv2.GetAuthorizerInput{ + ApiId: aws.String(rs.Primary.Attributes["api_id"]), + AuthorizerId: aws.String(rs.Primary.ID), + }) + if isAWSErr(err, apigatewayv2.ErrCodeNotFoundException, "") { + continue + } + if err != nil { + return err + } + + return fmt.Errorf("API Gateway v2 authorizer %s still exists", rs.Primary.ID) + } + + return nil +} + +func testAccCheckAWSAPIGateway2AuthorizerExists(n string) 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 API Gateway v2 authorizer ID is set") + } + + conn := testAccProvider.Meta().(*AWSClient).apigatewayv2conn + + _, err := conn.GetAuthorizer(&apigatewayv2.GetAuthorizerInput{ + ApiId: aws.String(rs.Primary.Attributes["api_id"]), + AuthorizerId: aws.String(rs.Primary.ID), + }) + if err != nil { + return err + } + + return nil + } +} + +func testAccAWSAPIGateway2AuthorizerImportStateIdFunc(resourceName string) resource.ImportStateIdFunc { + return func(s *terraform.State) (string, error) { + rs, ok := s.RootModule().Resources[resourceName] + if !ok { + return "", fmt.Errorf("Not Found: %s", resourceName) + } + + return fmt.Sprintf("%s/%s", rs.Primary.Attributes["api_id"], rs.Primary.ID), nil + } +} + +func testAccAWSAPIGateway2AuthorizerConfig_base(rName string) string { + return baseAccAWSLambdaConfig(rName, rName, rName) + fmt.Sprintf(` +resource "aws_lambda_function" "test" { + filename = "test-fixtures/lambdatest.zip" + function_name = %[1]q + role = "${aws_iam_role.iam_for_lambda.arn}" + handler = "index.handler" + runtime = "nodejs10.x" +} + +resource "aws_api_gateway_v2_api" "test" { + name = %[1]q + protocol_type = "WEBSOCKET" + route_selection_expression = "$request.body.action" +} + +resource "aws_iam_role" "test" { + name = "%[1]s_auth_invocation_role" + path = "/" + + assume_role_policy = < aws_apigatewayv2_api +
  • + aws_api_gateway_v2_authorizer +
  • diff --git a/website/docs/r/api_gateway_v2_authorizer.html.markdown b/website/docs/r/api_gateway_v2_authorizer.html.markdown new file mode 100644 index 000000000000..ca10461a9e56 --- /dev/null +++ b/website/docs/r/api_gateway_v2_authorizer.html.markdown @@ -0,0 +1,53 @@ +--- +layout: "aws" +page_title: "AWS: aws_api_gateway_v2_authorizer" +sidebar_current: "docs-aws-resource-api-gateway-v2-authorizer" +description: |- + Manages an Amazon API Gateway Version 2 authorizer. +--- + +# Resource: aws_api_gateway_v2_authorizer + +Manages an Amazon API Gateway Version 2 authorizer. +More information can be found in the [Amazon API Gateway Developer Guide](https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-websocket-api.html). + +## Example Usage + +### Basic + +```hcl +resource "aws_api_gateway_v2_authorizer" "example" { + api_id = "${aws_api_gateway_v2_api.example.id}" + authorizer_type = "REQUEST" + authorizer_uri = "${aws_lambda_function.example.invoke_arn}" + identity_sources = ["route.request.header.Auth"] + name = "example-authorizer" +} +``` + +## Argument Reference + +The following arguments are supported: + +* `api_id` - (Required) The API identifier. +* `authorizer_type` - (Required) The authorizer type. Valid values: `REQUEST`. +* `authorizer_uri` - (Required) The authorizer's Uniform Resource Identifier (URI). +For `REQUEST` authorizers this must be a well-formed Lambda function URI, such as the `invoke_arn` attribute of the [`aws_lambda_function`](/docs/providers/aws/r/lambda_function.html) resource. +* `identity_sources` - (Required) The identity sources for which authorization is requested. +For `REQUEST` authorizers the value is a list of one or more mapping expressions of the specified request parameters. +* `name` - (Required) The name of the authorizer. +* `authorizer_credentials_arn` - (Optional) The required credentials as an IAM role for API Gateway to invoke the authorizer. + +## Attribute Reference + +In addition to all arguments above, the following attributes are exported: + +* `id` - The authorizer identifier. + +## Import + +`aws_api_gateway_v2_authorizer` can be imported by using the API identifier and authorizer identifier, e.g. + +``` +$ terraform import aws_api_gateway_v2_authorizer.example aabbccddee/1122334 +``` From 6d33537eae2afd2d293bff7af963e736aba51c57 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 13 Mar 2020 15:09:32 -0400 Subject: [PATCH 2/3] 'aws_api_gateway2_authorizer' -> 'aws_apigatewayv2_authorizer'. --- aws/provider.go | 2 +- ...> resource_aws_apigatewayv2_authorizer.go} | 26 ++-- ...ource_aws_apigatewayv2_authorizer_test.go} | 120 ++++++++++++------ website/aws.erb | 2 +- ... => apigatewayv2_authorizer.html.markdown} | 14 +- 5 files changed, 104 insertions(+), 60 deletions(-) rename aws/{resource_aws_api_gateway2_authorizer.go => resource_aws_apigatewayv2_authorizer.go} (83%) rename aws/{resource_aws_api_gateway2_authorizer_test.go => resource_aws_apigatewayv2_authorizer_test.go} (61%) rename website/docs/r/{api_gateway_v2_authorizer.html.markdown => apigatewayv2_authorizer.html.markdown} (77%) diff --git a/aws/provider.go b/aws/provider.go index 1d3b8df66464..07adf0d34b5a 100644 --- a/aws/provider.go +++ b/aws/provider.go @@ -355,7 +355,7 @@ func Provider() terraform.ResourceProvider { "aws_api_gateway_usage_plan_key": resourceAwsApiGatewayUsagePlanKey(), "aws_api_gateway_vpc_link": resourceAwsApiGatewayVpcLink(), "aws_apigatewayv2_api": resourceAwsApiGatewayV2Api(), - "aws_api_gateway_v2_authorizer": resourceAwsApiGateway2Authorizer(), + "aws_apigatewayv2_authorizer": resourceAwsApiGatewayV2Authorizer(), "aws_app_cookie_stickiness_policy": resourceAwsAppCookieStickinessPolicy(), "aws_appautoscaling_target": resourceAwsAppautoscalingTarget(), "aws_appautoscaling_policy": resourceAwsAppautoscalingPolicy(), diff --git a/aws/resource_aws_api_gateway2_authorizer.go b/aws/resource_aws_apigatewayv2_authorizer.go similarity index 83% rename from aws/resource_aws_api_gateway2_authorizer.go rename to aws/resource_aws_apigatewayv2_authorizer.go index e08ba4e97f8c..c1a1bf7bbdad 100644 --- a/aws/resource_aws_api_gateway2_authorizer.go +++ b/aws/resource_aws_apigatewayv2_authorizer.go @@ -11,14 +11,14 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/helper/validation" ) -func resourceAwsApiGateway2Authorizer() *schema.Resource { +func resourceAwsApiGatewayV2Authorizer() *schema.Resource { return &schema.Resource{ - Create: resourceAwsApiGateway2AuthorizerCreate, - Read: resourceAwsApiGateway2AuthorizerRead, - Update: resourceAwsApiGateway2AuthorizerUpdate, - Delete: resourceAwsApiGateway2AuthorizerDelete, + Create: resourceAwsApiGatewayV2AuthorizerCreate, + Read: resourceAwsApiGatewayV2AuthorizerRead, + Update: resourceAwsApiGatewayV2AuthorizerUpdate, + Delete: resourceAwsApiGatewayV2AuthorizerDelete, Importer: &schema.ResourceImporter{ - State: resourceAwsApiGateway2AuthorizerImport, + State: resourceAwsApiGatewayV2AuthorizerImport, }, Schema: map[string]*schema.Schema{ @@ -59,7 +59,7 @@ func resourceAwsApiGateway2Authorizer() *schema.Resource { } } -func resourceAwsApiGateway2AuthorizerCreate(d *schema.ResourceData, meta interface{}) error { +func resourceAwsApiGatewayV2AuthorizerCreate(d *schema.ResourceData, meta interface{}) error { conn := meta.(*AWSClient).apigatewayv2conn req := &apigatewayv2.CreateAuthorizerInput{ @@ -81,10 +81,10 @@ func resourceAwsApiGateway2AuthorizerCreate(d *schema.ResourceData, meta interfa d.SetId(aws.StringValue(resp.AuthorizerId)) - return resourceAwsApiGateway2AuthorizerRead(d, meta) + return resourceAwsApiGatewayV2AuthorizerRead(d, meta) } -func resourceAwsApiGateway2AuthorizerRead(d *schema.ResourceData, meta interface{}) error { +func resourceAwsApiGatewayV2AuthorizerRead(d *schema.ResourceData, meta interface{}) error { conn := meta.(*AWSClient).apigatewayv2conn resp, err := conn.GetAuthorizer(&apigatewayv2.GetAuthorizerInput{ @@ -111,7 +111,7 @@ func resourceAwsApiGateway2AuthorizerRead(d *schema.ResourceData, meta interface return nil } -func resourceAwsApiGateway2AuthorizerUpdate(d *schema.ResourceData, meta interface{}) error { +func resourceAwsApiGatewayV2AuthorizerUpdate(d *schema.ResourceData, meta interface{}) error { conn := meta.(*AWSClient).apigatewayv2conn req := &apigatewayv2.UpdateAuthorizerInput{ @@ -140,10 +140,10 @@ func resourceAwsApiGateway2AuthorizerUpdate(d *schema.ResourceData, meta interfa return fmt.Errorf("error updating API Gateway v2 authorizer: %s", err) } - return resourceAwsApiGateway2AuthorizerRead(d, meta) + return resourceAwsApiGatewayV2AuthorizerRead(d, meta) } -func resourceAwsApiGateway2AuthorizerDelete(d *schema.ResourceData, meta interface{}) error { +func resourceAwsApiGatewayV2AuthorizerDelete(d *schema.ResourceData, meta interface{}) error { conn := meta.(*AWSClient).apigatewayv2conn log.Printf("[DEBUG] Deleting API Gateway v2 authorizer (%s)", d.Id()) @@ -161,7 +161,7 @@ func resourceAwsApiGateway2AuthorizerDelete(d *schema.ResourceData, meta interfa return nil } -func resourceAwsApiGateway2AuthorizerImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { +func resourceAwsApiGatewayV2AuthorizerImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { parts := strings.Split(d.Id(), "/") if len(parts) != 2 { return []*schema.ResourceData{}, fmt.Errorf("Wrong format of resource: %s. Please follow 'api-id/authorizer-id'", d.Id()) diff --git a/aws/resource_aws_api_gateway2_authorizer_test.go b/aws/resource_aws_apigatewayv2_authorizer_test.go similarity index 61% rename from aws/resource_aws_api_gateway2_authorizer_test.go rename to aws/resource_aws_apigatewayv2_authorizer_test.go index b6738422b303..adafc4710db7 100644 --- a/aws/resource_aws_api_gateway2_authorizer_test.go +++ b/aws/resource_aws_apigatewayv2_authorizer_test.go @@ -11,20 +11,22 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/terraform" ) -func TestAccAWSAPIGateway2Authorizer_basic(t *testing.T) { - resourceName := "aws_api_gateway_v2_authorizer.test" +func TestAccAWSAPIGatewayV2Authorizer_basic(t *testing.T) { + var apiId string + var v apigatewayv2.GetAuthorizerOutput + resourceName := "aws_apigatewayv2_authorizer.test" lambdaResourceName := "aws_lambda_function.test" - rName := fmt.Sprintf("tf-testacc-apigwv2-%s", acctest.RandStringFromCharSet(13, acctest.CharSetAlphaNum)) + rName := acctest.RandomWithPrefix("tf-acc-test") resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, - CheckDestroy: testAccCheckAWSAPIGateway2AuthorizerDestroy, + CheckDestroy: testAccCheckAWSAPIGatewayV2AuthorizerDestroy, Steps: []resource.TestStep{ { - Config: testAccAWSAPIGateway2AuthorizerConfig_basic(rName), + Config: testAccAWSAPIGatewayV2AuthorizerConfig_basic(rName), Check: resource.ComposeTestCheckFunc( - testAccCheckAWSAPIGateway2AuthorizerExists(resourceName), + testAccCheckAWSAPIGatewayV2AuthorizerExists(resourceName, &apiId, &v), resource.TestCheckResourceAttr(resourceName, "authorizer_credentials_arn", ""), resource.TestCheckResourceAttr(resourceName, "authorizer_type", "REQUEST"), resource.TestCheckResourceAttrPair(resourceName, "authorizer_uri", lambdaResourceName, "invoke_arn"), @@ -35,7 +37,7 @@ func TestAccAWSAPIGateway2Authorizer_basic(t *testing.T) { }, { ResourceName: resourceName, - ImportStateIdFunc: testAccAWSAPIGateway2AuthorizerImportStateIdFunc(resourceName), + ImportStateIdFunc: testAccAWSAPIGatewayV2AuthorizerImportStateIdFunc(resourceName), ImportState: true, ImportStateVerify: true, }, @@ -43,21 +45,46 @@ func TestAccAWSAPIGateway2Authorizer_basic(t *testing.T) { }) } -func TestAccAWSAPIGateway2Authorizer_Credentials(t *testing.T) { - resourceName := "aws_api_gateway_v2_authorizer.test" +func TestAccAWSAPIGatewayV2Authorizer_disappears(t *testing.T) { + var apiId string + var v apigatewayv2.GetAuthorizerOutput + resourceName := "aws_apigatewayv2_authorizer.test" + rName := acctest.RandomWithPrefix("tf-acc-test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSAPIGatewayV2AuthorizerDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSAPIGatewayV2AuthorizerConfig_basic(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSAPIGatewayV2AuthorizerExists(resourceName, &apiId, &v), + testAccCheckAWSAPIGatewayV2AuthorizerDisappears(&apiId, &v), + ), + ExpectNonEmptyPlan: true, + }, + }, + }) +} + +func TestAccAWSAPIGatewayV2Authorizer_Credentials(t *testing.T) { + var apiId string + var v apigatewayv2.GetAuthorizerOutput + resourceName := "aws_apigatewayv2_authorizer.test" iamRoleResourceName := "aws_iam_role.test" lambdaResourceName := "aws_lambda_function.test" - rName := fmt.Sprintf("tf-testacc-apigwv2-%s", acctest.RandStringFromCharSet(13, acctest.CharSetAlphaNum)) + rName := acctest.RandomWithPrefix("tf-acc-test") resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, - CheckDestroy: testAccCheckAWSAPIGateway2AuthorizerDestroy, + CheckDestroy: testAccCheckAWSAPIGatewayV2AuthorizerDestroy, Steps: []resource.TestStep{ { - Config: testAccAWSAPIGateway2AuthorizerConfig_credentials(rName), + Config: testAccAWSAPIGatewayV2AuthorizerConfig_credentials(rName), Check: resource.ComposeTestCheckFunc( - testAccCheckAWSAPIGateway2AuthorizerExists(resourceName), + testAccCheckAWSAPIGatewayV2AuthorizerExists(resourceName, &apiId, &v), resource.TestCheckResourceAttrPair(resourceName, "authorizer_credentials_arn", iamRoleResourceName, "arn"), resource.TestCheckResourceAttr(resourceName, "authorizer_type", "REQUEST"), resource.TestCheckResourceAttrPair(resourceName, "authorizer_uri", lambdaResourceName, "invoke_arn"), @@ -68,14 +95,14 @@ func TestAccAWSAPIGateway2Authorizer_Credentials(t *testing.T) { }, { ResourceName: resourceName, - ImportStateIdFunc: testAccAWSAPIGateway2AuthorizerImportStateIdFunc(resourceName), + ImportStateIdFunc: testAccAWSAPIGatewayV2AuthorizerImportStateIdFunc(resourceName), ImportState: true, ImportStateVerify: true, }, { - Config: testAccAWSAPIGateway2AuthorizerConfig_credentialsUpdated(rName), + Config: testAccAWSAPIGatewayV2AuthorizerConfig_credentialsUpdated(rName), Check: resource.ComposeTestCheckFunc( - testAccCheckAWSAPIGateway2AuthorizerExists(resourceName), + testAccCheckAWSAPIGatewayV2AuthorizerExists(resourceName, &apiId, &v), resource.TestCheckResourceAttrPair(resourceName, "authorizer_credentials_arn", iamRoleResourceName, "arn"), resource.TestCheckResourceAttr(resourceName, "authorizer_type", "REQUEST"), resource.TestCheckResourceAttrPair(resourceName, "authorizer_uri", lambdaResourceName, "invoke_arn"), @@ -86,9 +113,9 @@ func TestAccAWSAPIGateway2Authorizer_Credentials(t *testing.T) { ), }, { - Config: testAccAWSAPIGateway2AuthorizerConfig_basic(rName), + Config: testAccAWSAPIGatewayV2AuthorizerConfig_basic(rName), Check: resource.ComposeTestCheckFunc( - testAccCheckAWSAPIGateway2AuthorizerExists(resourceName), + testAccCheckAWSAPIGatewayV2AuthorizerExists(resourceName, &apiId, &v), resource.TestCheckResourceAttr(resourceName, "authorizer_credentials_arn", ""), resource.TestCheckResourceAttr(resourceName, "authorizer_type", "REQUEST"), resource.TestCheckResourceAttrPair(resourceName, "authorizer_uri", lambdaResourceName, "invoke_arn"), @@ -101,11 +128,11 @@ func TestAccAWSAPIGateway2Authorizer_Credentials(t *testing.T) { }) } -func testAccCheckAWSAPIGateway2AuthorizerDestroy(s *terraform.State) error { +func testAccCheckAWSAPIGatewayV2AuthorizerDestroy(s *terraform.State) error { conn := testAccProvider.Meta().(*AWSClient).apigatewayv2conn for _, rs := range s.RootModule().Resources { - if rs.Type != "aws_api_gateway_v2_authorizer" { + if rs.Type != "aws_apigatewayv2_authorizer" { continue } @@ -126,7 +153,20 @@ func testAccCheckAWSAPIGateway2AuthorizerDestroy(s *terraform.State) error { return nil } -func testAccCheckAWSAPIGateway2AuthorizerExists(n string) resource.TestCheckFunc { +func testAccCheckAWSAPIGatewayV2AuthorizerDisappears(apiId *string, v *apigatewayv2.GetAuthorizerOutput) resource.TestCheckFunc { + return func(s *terraform.State) error { + conn := testAccProvider.Meta().(*AWSClient).apigatewayv2conn + + _, err := conn.DeleteAuthorizer(&apigatewayv2.DeleteAuthorizerInput{ + ApiId: apiId, + AuthorizerId: v.AuthorizerId, + }) + + return err + } +} + +func testAccCheckAWSAPIGatewayV2AuthorizerExists(n string, vApiId *string, v *apigatewayv2.GetAuthorizerOutput) resource.TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[n] if !ok { @@ -139,19 +179,23 @@ func testAccCheckAWSAPIGateway2AuthorizerExists(n string) resource.TestCheckFunc conn := testAccProvider.Meta().(*AWSClient).apigatewayv2conn - _, err := conn.GetAuthorizer(&apigatewayv2.GetAuthorizerInput{ - ApiId: aws.String(rs.Primary.Attributes["api_id"]), + apiId := aws.String(rs.Primary.Attributes["api_id"]) + resp, err := conn.GetAuthorizer(&apigatewayv2.GetAuthorizerInput{ + ApiId: apiId, AuthorizerId: aws.String(rs.Primary.ID), }) if err != nil { return err } + *vApiId = *apiId + *v = *resp + return nil } } -func testAccAWSAPIGateway2AuthorizerImportStateIdFunc(resourceName string) resource.ImportStateIdFunc { +func testAccAWSAPIGatewayV2AuthorizerImportStateIdFunc(resourceName string) resource.ImportStateIdFunc { return func(s *terraform.State) (string, error) { rs, ok := s.RootModule().Resources[resourceName] if !ok { @@ -162,7 +206,7 @@ func testAccAWSAPIGateway2AuthorizerImportStateIdFunc(resourceName string) resou } } -func testAccAWSAPIGateway2AuthorizerConfig_base(rName string) string { +func testAccAWSAPIGatewayV2AuthorizerConfig_base(rName string) string { return baseAccAWSLambdaConfig(rName, rName, rName) + fmt.Sprintf(` resource "aws_lambda_function" "test" { filename = "test-fixtures/lambdatest.zip" @@ -172,7 +216,7 @@ resource "aws_lambda_function" "test" { runtime = "nodejs10.x" } -resource "aws_api_gateway_v2_api" "test" { +resource "aws_apigatewayv2_api" "test" { name = %[1]q protocol_type = "WEBSOCKET" route_selection_expression = "$request.body.action" @@ -196,10 +240,10 @@ EOF `, rName) } -func testAccAWSAPIGateway2AuthorizerConfig_basic(rName string) string { - return testAccAWSAPIGateway2AuthorizerConfig_base(rName) + fmt.Sprintf(` -resource "aws_api_gateway_v2_authorizer" "test" { - api_id = "${aws_api_gateway_v2_api.test.id}" +func testAccAWSAPIGatewayV2AuthorizerConfig_basic(rName string) string { + return testAccAWSAPIGatewayV2AuthorizerConfig_base(rName) + fmt.Sprintf(` +resource "aws_apigatewayv2_authorizer" "test" { + api_id = "${aws_apigatewayv2_api.test.id}" authorizer_type = "REQUEST" authorizer_uri = "${aws_lambda_function.test.invoke_arn}" identity_sources = ["route.request.header.Auth"] @@ -208,10 +252,10 @@ resource "aws_api_gateway_v2_authorizer" "test" { `, rName) } -func testAccAWSAPIGateway2AuthorizerConfig_credentials(rName string) string { - return testAccAWSAPIGateway2AuthorizerConfig_base(rName) + fmt.Sprintf(` -resource "aws_api_gateway_v2_authorizer" "test" { - api_id = "${aws_api_gateway_v2_api.test.id}" +func testAccAWSAPIGatewayV2AuthorizerConfig_credentials(rName string) string { + return testAccAWSAPIGatewayV2AuthorizerConfig_base(rName) + fmt.Sprintf(` +resource "aws_apigatewayv2_authorizer" "test" { + api_id = "${aws_apigatewayv2_api.test.id}" authorizer_type = "REQUEST" authorizer_uri = "${aws_lambda_function.test.invoke_arn}" identity_sources = ["route.request.header.Auth"] @@ -222,10 +266,10 @@ resource "aws_api_gateway_v2_authorizer" "test" { `, rName) } -func testAccAWSAPIGateway2AuthorizerConfig_credentialsUpdated(rName string) string { - return testAccAWSAPIGateway2AuthorizerConfig_base(rName) + fmt.Sprintf(` -resource "aws_api_gateway_v2_authorizer" "test" { - api_id = "${aws_api_gateway_v2_api.test.id}" +func testAccAWSAPIGatewayV2AuthorizerConfig_credentialsUpdated(rName string) string { + return testAccAWSAPIGatewayV2AuthorizerConfig_base(rName) + fmt.Sprintf(` +resource "aws_apigatewayv2_authorizer" "test" { + api_id = "${aws_apigatewayv2_api.test.id}" authorizer_type = "REQUEST" authorizer_uri = "${aws_lambda_function.test.invoke_arn}" identity_sources = ["route.request.header.Auth", "route.request.querystring.Name"] diff --git a/website/aws.erb b/website/aws.erb index 331dc1132d90..54455c4f84f8 100644 --- a/website/aws.erb +++ b/website/aws.erb @@ -219,7 +219,7 @@ aws_apigatewayv2_api
  • - aws_api_gateway_v2_authorizer + aws_apigatewayv2_authorizer
  • diff --git a/website/docs/r/api_gateway_v2_authorizer.html.markdown b/website/docs/r/apigatewayv2_authorizer.html.markdown similarity index 77% rename from website/docs/r/api_gateway_v2_authorizer.html.markdown rename to website/docs/r/apigatewayv2_authorizer.html.markdown index ca10461a9e56..47019886b1d6 100644 --- a/website/docs/r/api_gateway_v2_authorizer.html.markdown +++ b/website/docs/r/apigatewayv2_authorizer.html.markdown @@ -1,12 +1,12 @@ --- +subcategory: "API Gateway v2 (WebSocket and HTTP APIs)" layout: "aws" -page_title: "AWS: aws_api_gateway_v2_authorizer" -sidebar_current: "docs-aws-resource-api-gateway-v2-authorizer" +page_title: "AWS: aws_apigatewayv2_authorizer" description: |- Manages an Amazon API Gateway Version 2 authorizer. --- -# Resource: aws_api_gateway_v2_authorizer +# Resource: aws_apigatewayv2_authorizer Manages an Amazon API Gateway Version 2 authorizer. More information can be found in the [Amazon API Gateway Developer Guide](https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-websocket-api.html). @@ -16,8 +16,8 @@ More information can be found in the [Amazon API Gateway Developer Guide](https: ### Basic ```hcl -resource "aws_api_gateway_v2_authorizer" "example" { - api_id = "${aws_api_gateway_v2_api.example.id}" +resource "aws_apigatewayv2_authorizer" "example" { + api_id = "${aws_apigatewayv2_api.example.id}" authorizer_type = "REQUEST" authorizer_uri = "${aws_lambda_function.example.invoke_arn}" identity_sources = ["route.request.header.Auth"] @@ -46,8 +46,8 @@ In addition to all arguments above, the following attributes are exported: ## Import -`aws_api_gateway_v2_authorizer` can be imported by using the API identifier and authorizer identifier, e.g. +`aws_apigatewayv2_authorizer` can be imported by using the API identifier and authorizer identifier, e.g. ``` -$ terraform import aws_api_gateway_v2_authorizer.example aabbccddee/1122334 +$ terraform import aws_apigatewayv2_authorizer.example aabbccddee/1122334 ``` From 4c27f541ac3710fe260347fbefe08e79765c8469 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Sun, 15 Mar 2020 18:41:06 -0400 Subject: [PATCH 3/3] r/aws_apigatewayv2_authorizer: Add support for JWT. --- aws/resource_aws_apigatewayv2_authorizer.go | 64 +++++++++- ...source_aws_apigatewayv2_authorizer_test.go | 109 +++++++++++++++++- .../r/apigatewayv2_authorizer.html.markdown | 36 +++++- 3 files changed, 199 insertions(+), 10 deletions(-) diff --git a/aws/resource_aws_apigatewayv2_authorizer.go b/aws/resource_aws_apigatewayv2_authorizer.go index c1a1bf7bbdad..e761cbf2ca6a 100644 --- a/aws/resource_aws_apigatewayv2_authorizer.go +++ b/aws/resource_aws_apigatewayv2_authorizer.go @@ -36,12 +36,13 @@ func resourceAwsApiGatewayV2Authorizer() *schema.Resource { Type: schema.TypeString, Required: true, ValidateFunc: validation.StringInSlice([]string{ + apigatewayv2.AuthorizerTypeJwt, apigatewayv2.AuthorizerTypeRequest, }, false), }, "authorizer_uri": { Type: schema.TypeString, - Required: true, + Optional: true, ValidateFunc: validation.StringLenBetween(1, 2048), }, "identity_sources": { @@ -50,6 +51,25 @@ func resourceAwsApiGatewayV2Authorizer() *schema.Resource { MinItems: 1, Elem: &schema.Schema{Type: schema.TypeString}, }, + "jwt_configuration": { + Type: schema.TypeList, + Optional: true, + MinItems: 0, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "audience": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "issuer": { + Type: schema.TypeString, + Optional: true, + }, + }, + }, + }, "name": { Type: schema.TypeString, Required: true, @@ -65,13 +85,18 @@ func resourceAwsApiGatewayV2AuthorizerCreate(d *schema.ResourceData, meta interf req := &apigatewayv2.CreateAuthorizerInput{ ApiId: aws.String(d.Get("api_id").(string)), AuthorizerType: aws.String(d.Get("authorizer_type").(string)), - AuthorizerUri: aws.String(d.Get("authorizer_uri").(string)), IdentitySource: expandStringSet(d.Get("identity_sources").(*schema.Set)), Name: aws.String(d.Get("name").(string)), } if v, ok := d.GetOk("authorizer_credentials_arn"); ok { req.AuthorizerCredentialsArn = aws.String(v.(string)) } + if v, ok := d.GetOk("authorizer_uri"); ok { + req.AuthorizerUri = aws.String(v.(string)) + } + if v, ok := d.GetOk("jwt_configuration"); ok { + req.JwtConfiguration = expandApiGateway2JwtConfiguration(v.([]interface{})) + } log.Printf("[DEBUG] Creating API Gateway v2 authorizer: %s", req) resp, err := conn.CreateAuthorizer(req) @@ -106,6 +131,9 @@ func resourceAwsApiGatewayV2AuthorizerRead(d *schema.ResourceData, meta interfac if err := d.Set("identity_sources", flattenStringSet(resp.IdentitySource)); err != nil { return fmt.Errorf("error setting identity_sources: %s", err) } + if err := d.Set("jwt_configuration", flattenApiGateway2JwtConfiguration(resp.JwtConfiguration)); err != nil { + return fmt.Errorf("error setting jwt_configuration: %s", err) + } d.Set("name", resp.Name) return nil @@ -133,6 +161,9 @@ func resourceAwsApiGatewayV2AuthorizerUpdate(d *schema.ResourceData, meta interf if d.HasChange("name") { req.Name = aws.String(d.Get("name").(string)) } + if d.HasChange("jwt_configuration") { + req.JwtConfiguration = expandApiGateway2JwtConfiguration(d.Get("jwt_configuration").([]interface{})) + } log.Printf("[DEBUG] Updating API Gateway v2 authorizer: %s", req) _, err := conn.UpdateAuthorizer(req) @@ -172,3 +203,32 @@ func resourceAwsApiGatewayV2AuthorizerImport(d *schema.ResourceData, meta interf return []*schema.ResourceData{d}, nil } + +func expandApiGateway2JwtConfiguration(vConfiguration []interface{}) *apigatewayv2.JWTConfiguration { + configuration := &apigatewayv2.JWTConfiguration{} + + if len(vConfiguration) == 0 || vConfiguration[0] == nil { + return configuration + } + mConfiguration := vConfiguration[0].(map[string]interface{}) + + if vAudience, ok := mConfiguration["audience"].(*schema.Set); ok && vAudience.Len() > 0 { + configuration.Audience = expandStringSet(vAudience) + } + if vIssuer, ok := mConfiguration["issuer"].(string); ok && vIssuer != "" { + configuration.Issuer = aws.String(vIssuer) + } + + return configuration +} + +func flattenApiGateway2JwtConfiguration(configuration *apigatewayv2.JWTConfiguration) []interface{} { + if configuration == nil { + return []interface{}{} + } + + return []interface{}{map[string]interface{}{ + "audience": flattenStringSet(configuration.Audience), + "issuer": aws.StringValue(configuration.Issuer), + }} +} diff --git a/aws/resource_aws_apigatewayv2_authorizer_test.go b/aws/resource_aws_apigatewayv2_authorizer_test.go index adafc4710db7..37ae39ce3f9e 100644 --- a/aws/resource_aws_apigatewayv2_authorizer_test.go +++ b/aws/resource_aws_apigatewayv2_authorizer_test.go @@ -32,6 +32,7 @@ func TestAccAWSAPIGatewayV2Authorizer_basic(t *testing.T) { resource.TestCheckResourceAttrPair(resourceName, "authorizer_uri", lambdaResourceName, "invoke_arn"), resource.TestCheckResourceAttr(resourceName, "identity_sources.#", "1"), resource.TestCheckResourceAttr(resourceName, "identity_sources.645907014", "route.request.header.Auth"), + resource.TestCheckResourceAttr(resourceName, "jwt_configuration.#", "0"), resource.TestCheckResourceAttr(resourceName, "name", rName), ), }, @@ -90,6 +91,7 @@ func TestAccAWSAPIGatewayV2Authorizer_Credentials(t *testing.T) { resource.TestCheckResourceAttrPair(resourceName, "authorizer_uri", lambdaResourceName, "invoke_arn"), resource.TestCheckResourceAttr(resourceName, "identity_sources.#", "1"), resource.TestCheckResourceAttr(resourceName, "identity_sources.645907014", "route.request.header.Auth"), + resource.TestCheckResourceAttr(resourceName, "jwt_configuration.#", "0"), resource.TestCheckResourceAttr(resourceName, "name", rName), ), }, @@ -109,6 +111,7 @@ func TestAccAWSAPIGatewayV2Authorizer_Credentials(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "identity_sources.#", "2"), resource.TestCheckResourceAttr(resourceName, "identity_sources.645907014", "route.request.header.Auth"), resource.TestCheckResourceAttr(resourceName, "identity_sources.4138478046", "route.request.querystring.Name"), + resource.TestCheckResourceAttr(resourceName, "jwt_configuration.#", "0"), resource.TestCheckResourceAttr(resourceName, "name", fmt.Sprintf("%s-updated", rName)), ), }, @@ -121,6 +124,59 @@ func TestAccAWSAPIGatewayV2Authorizer_Credentials(t *testing.T) { resource.TestCheckResourceAttrPair(resourceName, "authorizer_uri", lambdaResourceName, "invoke_arn"), resource.TestCheckResourceAttr(resourceName, "identity_sources.#", "1"), resource.TestCheckResourceAttr(resourceName, "identity_sources.645907014", "route.request.header.Auth"), + resource.TestCheckResourceAttr(resourceName, "jwt_configuration.#", "0"), + resource.TestCheckResourceAttr(resourceName, "name", rName), + ), + }, + }, + }) +} + +func TestAccAWSAPIGatewayV2Authorizer_JWT(t *testing.T) { + var apiId string + var v apigatewayv2.GetAuthorizerOutput + resourceName := "aws_apigatewayv2_authorizer.test" + rName := acctest.RandomWithPrefix("tf-acc-test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSAPIGatewayV2AuthorizerDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSAPIGatewayV2AuthorizerConfig_jwt(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSAPIGatewayV2AuthorizerExists(resourceName, &apiId, &v), + resource.TestCheckResourceAttr(resourceName, "authorizer_credentials_arn", ""), + resource.TestCheckResourceAttr(resourceName, "authorizer_type", "JWT"), + resource.TestCheckResourceAttr(resourceName, "authorizer_uri", ""), + resource.TestCheckResourceAttr(resourceName, "identity_sources.#", "1"), + resource.TestCheckResourceAttr(resourceName, "identity_sources.2786136151", "$request.header.Authorization"), + resource.TestCheckResourceAttr(resourceName, "jwt_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "jwt_configuration.0.audience.#", "1"), + resource.TestCheckResourceAttr(resourceName, "jwt_configuration.0.audience.1785148924", "test"), + resource.TestCheckResourceAttr(resourceName, "name", rName), + ), + }, + { + ResourceName: resourceName, + ImportStateIdFunc: testAccAWSAPIGatewayV2AuthorizerImportStateIdFunc(resourceName), + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccAWSAPIGatewayV2AuthorizerConfig_jwtUpdated(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSAPIGatewayV2AuthorizerExists(resourceName, &apiId, &v), + resource.TestCheckResourceAttr(resourceName, "authorizer_credentials_arn", ""), + resource.TestCheckResourceAttr(resourceName, "authorizer_type", "JWT"), + resource.TestCheckResourceAttr(resourceName, "authorizer_uri", ""), + resource.TestCheckResourceAttr(resourceName, "identity_sources.#", "1"), + resource.TestCheckResourceAttr(resourceName, "identity_sources.2786136151", "$request.header.Authorization"), + resource.TestCheckResourceAttr(resourceName, "jwt_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "jwt_configuration.0.audience.#", "2"), + resource.TestCheckResourceAttr(resourceName, "jwt_configuration.0.audience.1785148924", "test"), + resource.TestCheckResourceAttr(resourceName, "jwt_configuration.0.audience.2323796166", "testing"), resource.TestCheckResourceAttr(resourceName, "name", rName), ), }, @@ -206,7 +262,7 @@ func testAccAWSAPIGatewayV2AuthorizerImportStateIdFunc(resourceName string) reso } } -func testAccAWSAPIGatewayV2AuthorizerConfig_base(rName string) string { +func testAccAWSAPIGatewayV2AuthorizerConfig_baseWebSocket(rName string) string { return baseAccAWSLambdaConfig(rName, rName, rName) + fmt.Sprintf(` resource "aws_lambda_function" "test" { filename = "test-fixtures/lambdatest.zip" @@ -240,8 +296,21 @@ EOF `, rName) } +func testAccAWSAPIGatewayV2AuthorizerConfig_baseHttp(rName string) string { + return baseAccAWSLambdaConfig(rName, rName, rName) + fmt.Sprintf(` +resource "aws_apigatewayv2_api" "test" { + name = %[1]q + protocol_type = "HTTP" +} + +resource "aws_cognito_user_pool" "test" { + name = %[1]q +} +`, rName) +} + func testAccAWSAPIGatewayV2AuthorizerConfig_basic(rName string) string { - return testAccAWSAPIGatewayV2AuthorizerConfig_base(rName) + fmt.Sprintf(` + return testAccAWSAPIGatewayV2AuthorizerConfig_baseWebSocket(rName) + fmt.Sprintf(` resource "aws_apigatewayv2_authorizer" "test" { api_id = "${aws_apigatewayv2_api.test.id}" authorizer_type = "REQUEST" @@ -253,7 +322,7 @@ resource "aws_apigatewayv2_authorizer" "test" { } func testAccAWSAPIGatewayV2AuthorizerConfig_credentials(rName string) string { - return testAccAWSAPIGatewayV2AuthorizerConfig_base(rName) + fmt.Sprintf(` + return testAccAWSAPIGatewayV2AuthorizerConfig_baseWebSocket(rName) + fmt.Sprintf(` resource "aws_apigatewayv2_authorizer" "test" { api_id = "${aws_apigatewayv2_api.test.id}" authorizer_type = "REQUEST" @@ -267,7 +336,7 @@ resource "aws_apigatewayv2_authorizer" "test" { } func testAccAWSAPIGatewayV2AuthorizerConfig_credentialsUpdated(rName string) string { - return testAccAWSAPIGatewayV2AuthorizerConfig_base(rName) + fmt.Sprintf(` + return testAccAWSAPIGatewayV2AuthorizerConfig_baseWebSocket(rName) + fmt.Sprintf(` resource "aws_apigatewayv2_authorizer" "test" { api_id = "${aws_apigatewayv2_api.test.id}" authorizer_type = "REQUEST" @@ -279,3 +348,35 @@ resource "aws_apigatewayv2_authorizer" "test" { } `, rName) } + +func testAccAWSAPIGatewayV2AuthorizerConfig_jwt(rName string) string { + return testAccAWSAPIGatewayV2AuthorizerConfig_baseHttp(rName) + fmt.Sprintf(` +resource "aws_apigatewayv2_authorizer" "test" { + api_id = "${aws_apigatewayv2_api.test.id}" + authorizer_type = "JWT" + identity_sources = ["$request.header.Authorization"] + name = %[1]q + + jwt_configuration { + audience = ["test"] + issuer = "https://${aws_cognito_user_pool.test.endpoint}" + } +} +`, rName) +} + +func testAccAWSAPIGatewayV2AuthorizerConfig_jwtUpdated(rName string) string { + return testAccAWSAPIGatewayV2AuthorizerConfig_baseHttp(rName) + fmt.Sprintf(` +resource "aws_apigatewayv2_authorizer" "test" { + api_id = "${aws_apigatewayv2_api.test.id}" + authorizer_type = "JWT" + identity_sources = ["$request.header.Authorization"] + name = %[1]q + + jwt_configuration { + audience = ["test", "testing"] + issuer = "https://${aws_cognito_user_pool.test.endpoint}" + } +} +`, rName) +} diff --git a/website/docs/r/apigatewayv2_authorizer.html.markdown b/website/docs/r/apigatewayv2_authorizer.html.markdown index 47019886b1d6..f8321b4e1022 100644 --- a/website/docs/r/apigatewayv2_authorizer.html.markdown +++ b/website/docs/r/apigatewayv2_authorizer.html.markdown @@ -13,7 +13,7 @@ More information can be found in the [Amazon API Gateway Developer Guide](https: ## Example Usage -### Basic +### Basic WebSocket API ```hcl resource "aws_apigatewayv2_authorizer" "example" { @@ -25,18 +25,46 @@ resource "aws_apigatewayv2_authorizer" "example" { } ``` +### Basic HTTP API + +```hcl +resource "aws_apigatewayv2_authorizer" "example" { + api_id = "${aws_apigatewayv2_api.example.id}" + authorizer_type = "JWT" + identity_sources = ["$request.header.Authorization"] + name = "example-authorizer" + + jwt_configuration { + audience = ["example"] + issuer = "https://${aws_cognito_user_pool.example.endpoint}" + } +} +``` + ## Argument Reference The following arguments are supported: * `api_id` - (Required) The API identifier. -* `authorizer_type` - (Required) The authorizer type. Valid values: `REQUEST`. -* `authorizer_uri` - (Required) The authorizer's Uniform Resource Identifier (URI). -For `REQUEST` authorizers this must be a well-formed Lambda function URI, such as the `invoke_arn` attribute of the [`aws_lambda_function`](/docs/providers/aws/r/lambda_function.html) resource. +* `authorizer_type` - (Required) The authorizer type. Valid values: `JWT`, `REQUEST`. +For WebSocket APIs, specify `REQUEST` for a Lambda function using incoming request parameters. + For HTTP APIs, specify `JWT` to use JSON Web Tokens. * `identity_sources` - (Required) The identity sources for which authorization is requested. For `REQUEST` authorizers the value is a list of one or more mapping expressions of the specified request parameters. +For `JWT` authorizers the single entry specifies where to extract the JSON Web Token (JWT) from inbound requests. * `name` - (Required) The name of the authorizer. * `authorizer_credentials_arn` - (Optional) The required credentials as an IAM role for API Gateway to invoke the authorizer. +Supported only for `REQUEST` authorizers. +* `authorizer_uri` - (Optional) The authorizer's Uniform Resource Identifier (URI). +For `REQUEST` authorizers this must be a well-formed Lambda function URI, such as the `invoke_arn` attribute of the [`aws_lambda_function`](/docs/providers/aws/r/lambda_function.html) resource. +Supported only for `REQUEST` authorizers. +* `jwt_configuration` - (Optional) The configuration of a JWT authorizer. Required for the `JWT` authorizer type. +Supported only for HTTP APIs. + +The `jwt_configuration` object supports the following: + +* `audience` - (Optional) A list of the intended recipients of the JWT. A valid JWT must provide an aud that matches at least one entry in this list. +* `issuer` - (Optional) The base domain of the identity provider that issues JSON Web Tokens, such as the `endpoint` attribute of the [`aws_cognito_user_pool`](/docs/providers/aws/r/cognito_user_pool.html) resource. ## Attribute Reference