From cc38378870a9a99d07802c52c980ef05b8db1139 Mon Sep 17 00:00:00 2001 From: Radek Simko Date: Mon, 29 Aug 2016 20:51:59 +0100 Subject: [PATCH] provider/aws: API Gateway Custom Authorizer (#8535) * [WIP] AWS APIGateway Custom Authorizer * provider/aws: api_gateway_method - Add missing fields to Read+Update * provider/aws: Make API Gateway name in test more specific * provider/aws: APIG - Use minimal configuration in create request --- .../resource_aws_api_gateway_authorizer.go | 7 +- .../aws/resource_aws_api_gateway_method.go | 60 ++++++-- .../resource_aws_api_gateway_method_test.go | 142 +++++++++++++++++- .../aws/r/api_gateway_method.html.markdown | 3 +- 4 files changed, 200 insertions(+), 12 deletions(-) diff --git a/builtin/providers/aws/resource_aws_api_gateway_authorizer.go b/builtin/providers/aws/resource_aws_api_gateway_authorizer.go index 6b00518138..8f881e185c 100644 --- a/builtin/providers/aws/resource_aws_api_gateway_authorizer.go +++ b/builtin/providers/aws/resource_aws_api_gateway_authorizer.go @@ -3,6 +3,7 @@ package aws import ( "fmt" "log" + "strings" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/awserr" @@ -200,7 +201,11 @@ func resourceAwsApiGatewayAuthorizerDelete(d *schema.ResourceData, meta interfac log.Printf("[INFO] Deleting API Gateway Authorizer: %s", input) _, err := conn.DeleteAuthorizer(&input) if err != nil { - return fmt.Errorf("Deleting API Gateway Authorizer failed: %s", err) + // XXX: Figure out a way to delete the method that depends on the authorizer first + // otherwise the authorizer will be dangling until the API is deleted + if !strings.Contains(err.Error(), "ConflictException") { + return fmt.Errorf("Deleting API Gateway Authorizer failed: %s", err) + } } return nil diff --git a/builtin/providers/aws/resource_aws_api_gateway_method.go b/builtin/providers/aws/resource_aws_api_gateway_method.go index 0f26d634e5..577c44e152 100644 --- a/builtin/providers/aws/resource_aws_api_gateway_method.go +++ b/builtin/providers/aws/resource_aws_api_gateway_method.go @@ -46,6 +46,11 @@ func resourceAwsApiGatewayMethod() *schema.Resource { Required: true, }, + "authorizer_id": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + }, + "api_key_required": &schema.Schema{ Type: schema.TypeBool, Optional: true, @@ -78,10 +83,21 @@ func resourceAwsApiGatewayMethod() *schema.Resource { func resourceAwsApiGatewayMethodCreate(d *schema.ResourceData, meta interface{}) error { conn := meta.(*AWSClient).apigateway + input := apigateway.PutMethodInput{ + AuthorizationType: aws.String(d.Get("authorization").(string)), + HttpMethod: aws.String(d.Get("http_method").(string)), + ResourceId: aws.String(d.Get("resource_id").(string)), + RestApiId: aws.String(d.Get("rest_api_id").(string)), + ApiKeyRequired: aws.Bool(d.Get("api_key_required").(bool)), + } + models := make(map[string]string) for k, v := range d.Get("request_models").(map[string]interface{}) { models[k] = v.(string) } + if len(models) > 0 { + input.RequestModels = aws.StringMap(models) + } parameters := make(map[string]bool) if kv, ok := d.GetOk("request_parameters"); ok { @@ -92,22 +108,20 @@ func resourceAwsApiGatewayMethodCreate(d *schema.ResourceData, meta interface{}) parameters[k] = value } } + input.RequestParameters = aws.BoolMap(parameters) } if v, ok := d.GetOk("request_parameters_in_json"); ok { if err := json.Unmarshal([]byte(v.(string)), ¶meters); err != nil { return fmt.Errorf("Error unmarshaling request_parameters_in_json: %s", err) } + input.RequestParameters = aws.BoolMap(parameters) } - _, err := conn.PutMethod(&apigateway.PutMethodInput{ - AuthorizationType: aws.String(d.Get("authorization").(string)), - HttpMethod: aws.String(d.Get("http_method").(string)), - ResourceId: aws.String(d.Get("resource_id").(string)), - RestApiId: aws.String(d.Get("rest_api_id").(string)), - RequestModels: aws.StringMap(models), - RequestParameters: aws.BoolMap(parameters), - ApiKeyRequired: aws.Bool(d.Get("api_key_required").(bool)), - }) + if v, ok := d.GetOk("authorizer_id"); ok { + input.AuthorizerId = aws.String(v.(string)) + } + + _, err := conn.PutMethod(&input) if err != nil { return fmt.Errorf("Error creating API Gateway Method: %s", err) } @@ -138,6 +152,10 @@ func resourceAwsApiGatewayMethodRead(d *schema.ResourceData, meta interface{}) e d.SetId(fmt.Sprintf("agm-%s-%s-%s", d.Get("rest_api_id").(string), d.Get("resource_id").(string), d.Get("http_method").(string))) d.Set("request_parameters", aws.BoolValueMap(out.RequestParameters)) d.Set("request_parameters_in_json", aws.BoolValueMap(out.RequestParameters)) + d.Set("api_key_required", out.ApiKeyRequired) + d.Set("authorization_type", out.AuthorizationType) + d.Set("authorizer_id", out.AuthorizerId) + d.Set("request_models", aws.StringValueMap(out.RequestModels)) return nil } @@ -184,6 +202,30 @@ func resourceAwsApiGatewayMethodUpdate(d *schema.ResourceData, meta interface{}) operations = append(operations, ops...) } + if d.HasChange("authorization") { + operations = append(operations, &apigateway.PatchOperation{ + Op: aws.String("replace"), + Path: aws.String("/authorizationType"), + Value: aws.String(d.Get("authorization").(string)), + }) + } + + if d.HasChange("authorizer_id") { + operations = append(operations, &apigateway.PatchOperation{ + Op: aws.String("replace"), + Path: aws.String("/authorizerId"), + Value: aws.String(d.Get("authorizer_id").(string)), + }) + } + + if d.HasChange("api_key_required") { + operations = append(operations, &apigateway.PatchOperation{ + Op: aws.String("replace"), + Path: aws.String("/apiKeyRequired"), + Value: aws.String(fmt.Sprintf("%t", d.Get("api_key_required").(bool))), + }) + } + method, err := conn.UpdateMethod(&apigateway.UpdateMethodInput{ HttpMethod: aws.String(d.Get("http_method").(string)), ResourceId: aws.String(d.Get("resource_id").(string)), diff --git a/builtin/providers/aws/resource_aws_api_gateway_method_test.go b/builtin/providers/aws/resource_aws_api_gateway_method_test.go index 05738affcb..4183838b7d 100644 --- a/builtin/providers/aws/resource_aws_api_gateway_method_test.go +++ b/builtin/providers/aws/resource_aws_api_gateway_method_test.go @@ -2,6 +2,7 @@ package aws import ( "fmt" + "regexp" "testing" "github.com/aws/aws-sdk-go/aws" @@ -44,12 +45,51 @@ func TestAccAWSAPIGatewayMethod_basic(t *testing.T) { }) } +func TestAccAWSAPIGatewayMethod_customauthorizer(t *testing.T) { + var conf apigateway.Method + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSAPIGatewayMethodDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccAWSAPIGatewayMethodConfigWithCustomAuthorizer, + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSAPIGatewayMethodExists("aws_api_gateway_method.test", &conf), + testAccCheckAWSAPIGatewayMethodAttributes(&conf), + resource.TestCheckResourceAttr( + "aws_api_gateway_method.test", "http_method", "GET"), + resource.TestCheckResourceAttr( + "aws_api_gateway_method.test", "authorization", "CUSTOM"), + resource.TestMatchResourceAttr( + "aws_api_gateway_method.test", "authorizer_id", regexp.MustCompile("^[a-z0-9]{6}$")), + resource.TestCheckResourceAttr( + "aws_api_gateway_method.test", "request_models.application/json", "Error"), + ), + }, + + resource.TestStep{ + Config: testAccAWSAPIGatewayMethodConfigUpdate, + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSAPIGatewayMethodExists("aws_api_gateway_method.test", &conf), + testAccCheckAWSAPIGatewayMethodAttributesUpdate(&conf), + resource.TestCheckResourceAttr( + "aws_api_gateway_method.test", "authorization", "NONE"), + resource.TestCheckResourceAttr( + "aws_api_gateway_method.test", "authorizer_id", ""), + ), + }, + }, + }) +} + func testAccCheckAWSAPIGatewayMethodAttributes(conf *apigateway.Method) resource.TestCheckFunc { return func(s *terraform.State) error { if *conf.HttpMethod != "GET" { return fmt.Errorf("Wrong HttpMethod: %q", *conf.HttpMethod) } - if *conf.AuthorizationType != "NONE" { + if *conf.AuthorizationType != "NONE" && *conf.AuthorizationType != "CUSTOM" { return fmt.Errorf("Wrong Authorization: %q", *conf.AuthorizationType) } @@ -154,6 +194,106 @@ func testAccCheckAWSAPIGatewayMethodDestroy(s *terraform.State) error { return nil } +const testAccAWSAPIGatewayMethodConfigWithCustomAuthorizer = ` +resource "aws_api_gateway_rest_api" "test" { + name = "tf-acc-test-custom-auth" +} + +resource "aws_iam_role" "invocation_role" { + name = "tf_acc_api_gateway_auth_invocation_role" + path = "/" + assume_role_policy = <