Skip to content

Commit

Permalink
Merge pull request #13013 from ewbankkit/issue-12971
Browse files Browse the repository at this point in the history
r/aws_apigatewayv2_integration: Add tls_config attribute
  • Loading branch information
breathingdust authored Jul 22, 2020
2 parents 2abeb15 + 3645f1d commit e3a1c91
Show file tree
Hide file tree
Showing 3 changed files with 239 additions and 13 deletions.
51 changes: 49 additions & 2 deletions aws/resource_aws_apigatewayv2_integration.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,11 +93,10 @@ func resourceAwsApiGatewayV2Integration() *schema.Resource {
apigatewayv2.PassthroughBehaviorWhenNoTemplates,
}, false),
DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool {
// PassthroughBehavior not set for HTTP APIs
// Not set for HTTP APIs.
if old == "" && new == apigatewayv2.PassthroughBehaviorWhenNoMatch {
return true
}

return false
},
},
Expand Down Expand Up @@ -132,6 +131,20 @@ func resourceAwsApiGatewayV2Integration() *schema.Resource {
Default: 29000,
ValidateFunc: validation.IntBetween(50, 29000),
},
"tls_config": {
Type: schema.TypeList,
Optional: true,
MinItems: 0,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"server_name_to_verify": {
Type: schema.TypeString,
Optional: true,
},
},
},
},
},
}
}
Expand Down Expand Up @@ -182,6 +195,9 @@ func resourceAwsApiGatewayV2IntegrationCreate(d *schema.ResourceData, meta inter
if v, ok := d.GetOk("timeout_milliseconds"); ok {
req.TimeoutInMillis = aws.Int64(int64(v.(int)))
}
if v, ok := d.GetOk("tls_config"); ok {
req.TlsConfig = expandApiGateway2TlsConfig(v.([]interface{}))
}

log.Printf("[DEBUG] Creating API Gateway v2 integration: %s", req)
resp, err := conn.CreateIntegration(req)
Expand Down Expand Up @@ -231,6 +247,9 @@ func resourceAwsApiGatewayV2IntegrationRead(d *schema.ResourceData, meta interfa
}
d.Set("template_selection_expression", resp.TemplateSelectionExpression)
d.Set("timeout_milliseconds", resp.TimeoutInMillis)
if err := d.Set("tls_config", flattenApiGateway2TlsConfig(resp.TlsConfig)); err != nil {
return fmt.Errorf("error setting tls_config: %s", err)
}

return nil
}
Expand Down Expand Up @@ -291,6 +310,9 @@ func resourceAwsApiGatewayV2IntegrationUpdate(d *schema.ResourceData, meta inter
if d.HasChange("timeout_milliseconds") {
req.TimeoutInMillis = aws.Int64(int64(d.Get("timeout_milliseconds").(int)))
}
if d.HasChange("tls_config") {
req.TlsConfig = expandApiGateway2TlsConfig(d.Get("tls_config").([]interface{}))
}

log.Printf("[DEBUG] Updating API Gateway v2 integration: %s", req)
_, err := conn.UpdateIntegration(req)
Expand Down Expand Up @@ -347,3 +369,28 @@ func resourceAwsApiGatewayV2IntegrationImport(d *schema.ResourceData, meta inter

return []*schema.ResourceData{d}, nil
}

func expandApiGateway2TlsConfig(vConfig []interface{}) *apigatewayv2.TlsConfigInput {
config := &apigatewayv2.TlsConfigInput{}

if len(vConfig) == 0 || vConfig[0] == nil {
return config
}
mConfig := vConfig[0].(map[string]interface{})

if vServerNameToVerify, ok := mConfig["server_name_to_verify"].(string); ok && vServerNameToVerify != "" {
config.ServerNameToVerify = aws.String(vServerNameToVerify)
}

return config
}

func flattenApiGateway2TlsConfig(config *apigatewayv2.TlsConfig) []interface{} {
if config == nil {
return []interface{}{}
}

return []interface{}{map[string]interface{}{
"server_name_to_verify": aws.StringValue(config.ServerNameToVerify),
}}
}
196 changes: 185 additions & 11 deletions aws/resource_aws_apigatewayv2_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ func TestAccAWSAPIGatewayV2Integration_basicWebSocket(t *testing.T) {
resource.TestCheckResourceAttr(resourceName, "request_templates.%", "0"),
resource.TestCheckResourceAttr(resourceName, "template_selection_expression", ""),
resource.TestCheckResourceAttr(resourceName, "timeout_milliseconds", "29000"),
resource.TestCheckResourceAttr(resourceName, "tls_config.#", "0"),
),
},
{
Expand Down Expand Up @@ -149,6 +150,7 @@ func TestAccAWSAPIGatewayV2Integration_IntegrationTypeHttp(t *testing.T) {
resource.TestCheckResourceAttr(resourceName, "request_templates.application/json", ""),
resource.TestCheckResourceAttr(resourceName, "template_selection_expression", "$request.body.name"),
resource.TestCheckResourceAttr(resourceName, "timeout_milliseconds", "28999"),
resource.TestCheckResourceAttr(resourceName, "tls_config.#", "0"),
),
},
{
Expand All @@ -174,6 +176,7 @@ func TestAccAWSAPIGatewayV2Integration_IntegrationTypeHttp(t *testing.T) {
resource.TestCheckResourceAttr(resourceName, "request_templates.application/xml", "#set($percent=$number/100)"),
resource.TestCheckResourceAttr(resourceName, "template_selection_expression", "$request.body.id"),
resource.TestCheckResourceAttr(resourceName, "timeout_milliseconds", "51"),
resource.TestCheckResourceAttr(resourceName, "tls_config.#", "0"),
),
},
{
Expand Down Expand Up @@ -217,6 +220,7 @@ func TestAccAWSAPIGatewayV2Integration_Lambda(t *testing.T) {
resource.TestCheckResourceAttr(resourceName, "request_templates.%", "0"),
resource.TestCheckResourceAttr(resourceName, "template_selection_expression", ""),
resource.TestCheckResourceAttr(resourceName, "timeout_milliseconds", "29000"),
resource.TestCheckResourceAttr(resourceName, "tls_config.#", "0"),
),
},
{
Expand All @@ -229,7 +233,7 @@ func TestAccAWSAPIGatewayV2Integration_Lambda(t *testing.T) {
})
}

func TestAccAWSAPIGatewayV2Integration_VpcLink(t *testing.T) {
func TestAccAWSAPIGatewayV2Integration_VpcLinkWebSocket(t *testing.T) {
var apiId string
var v apigatewayv2.GetIntegrationOutput
resourceName := "aws_apigatewayv2_integration.test"
Expand All @@ -242,7 +246,7 @@ func TestAccAWSAPIGatewayV2Integration_VpcLink(t *testing.T) {
CheckDestroy: testAccCheckAWSAPIGatewayV2IntegrationDestroy,
Steps: []resource.TestStep{
{
Config: testAccAWSAPIGatewayV2IntegrationConfig_vpcLink(rName),
Config: testAccAWSAPIGatewayV2IntegrationConfig_vpcLinkWebSocket(rName),
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSAPIGatewayV2IntegrationExists(resourceName, &apiId, &v),
resource.TestCheckResourceAttrPair(resourceName, "connection_id", vpcLinkResourceName, "id"),
Expand All @@ -260,6 +264,80 @@ func TestAccAWSAPIGatewayV2Integration_VpcLink(t *testing.T) {
resource.TestCheckResourceAttr(resourceName, "request_templates.%", "0"),
resource.TestCheckResourceAttr(resourceName, "template_selection_expression", ""),
resource.TestCheckResourceAttr(resourceName, "timeout_milliseconds", "12345"),
resource.TestCheckResourceAttr(resourceName, "tls_config.#", "0"),
),
},
{
ResourceName: resourceName,
ImportStateIdFunc: testAccAWSAPIGatewayV2IntegrationImportStateIdFunc(resourceName),
ImportState: true,
ImportStateVerify: true,
},
},
})
}

func TestAccAWSAPIGatewayV2Integration_VpcLinkHttp(t *testing.T) {
var apiId string
var v apigatewayv2.GetIntegrationOutput
resourceName := "aws_apigatewayv2_integration.test"
vpcLinkResourceName := "aws_apigatewayv2_vpc_link.test"
lbListenerResourceName := "aws_lb_listener.test"
rName := acctest.RandomWithPrefix("tf-acc-test")

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSAPIGatewayV2IntegrationDestroy,
Steps: []resource.TestStep{
{
Config: testAccAWSAPIGatewayV2IntegrationConfig_vpcLinkHttp(rName),
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSAPIGatewayV2IntegrationExists(resourceName, &apiId, &v),
resource.TestCheckResourceAttrPair(resourceName, "connection_id", vpcLinkResourceName, "id"),
resource.TestCheckResourceAttr(resourceName, "connection_type", "VPC_LINK"),
resource.TestCheckResourceAttr(resourceName, "content_handling_strategy", ""),
resource.TestCheckResourceAttr(resourceName, "credentials_arn", ""),
resource.TestCheckResourceAttr(resourceName, "description", "Test private integration"),
resource.TestCheckResourceAttr(resourceName, "integration_method", "GET"),
resource.TestCheckResourceAttr(resourceName, "integration_response_selection_expression", ""),
resource.TestCheckResourceAttr(resourceName, "integration_type", "HTTP_PROXY"),
resource.TestCheckResourceAttrPair(resourceName, "integration_uri", lbListenerResourceName, "arn"),
resource.TestCheckResourceAttr(resourceName, "passthrough_behavior", ""),
resource.TestCheckResourceAttr(resourceName, "payload_format_version", "1.0"),
resource.TestCheckResourceAttr(resourceName, "request_templates.%", "0"),
resource.TestCheckResourceAttr(resourceName, "template_selection_expression", ""),
resource.TestCheckResourceAttr(resourceName, "timeout_milliseconds", "5001"),
resource.TestCheckResourceAttr(resourceName, "tls_config.#", "1"),
resource.TestCheckResourceAttr(resourceName, "tls_config.0.server_name_to_verify", "www.example.com"),
),
},
{
ResourceName: resourceName,
ImportStateIdFunc: testAccAWSAPIGatewayV2IntegrationImportStateIdFunc(resourceName),
ImportState: true,
ImportStateVerify: true,
},
{
Config: testAccAWSAPIGatewayV2IntegrationConfig_vpcLinkHttpUpdated(rName),
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSAPIGatewayV2IntegrationExists(resourceName, &apiId, &v),
resource.TestCheckResourceAttrPair(resourceName, "connection_id", vpcLinkResourceName, "id"),
resource.TestCheckResourceAttr(resourceName, "connection_type", "VPC_LINK"),
resource.TestCheckResourceAttr(resourceName, "content_handling_strategy", ""),
resource.TestCheckResourceAttr(resourceName, "credentials_arn", ""),
resource.TestCheckResourceAttr(resourceName, "description", "Test private integration updated"),
resource.TestCheckResourceAttr(resourceName, "integration_method", "POST"),
resource.TestCheckResourceAttr(resourceName, "integration_response_selection_expression", ""),
resource.TestCheckResourceAttr(resourceName, "integration_type", "HTTP_PROXY"),
resource.TestCheckResourceAttrPair(resourceName, "integration_uri", lbListenerResourceName, "arn"),
resource.TestCheckResourceAttr(resourceName, "passthrough_behavior", ""),
resource.TestCheckResourceAttr(resourceName, "payload_format_version", "1.0"),
resource.TestCheckResourceAttr(resourceName, "request_templates.%", "0"),
resource.TestCheckResourceAttr(resourceName, "template_selection_expression", ""),
resource.TestCheckResourceAttr(resourceName, "timeout_milliseconds", "4999"),
resource.TestCheckResourceAttr(resourceName, "tls_config.#", "1"),
resource.TestCheckResourceAttr(resourceName, "tls_config.0.server_name_to_verify", "www.example.org"),
),
},
{
Expand Down Expand Up @@ -363,12 +441,58 @@ resource "aws_apigatewayv2_api" "test" {
func testAccAWSAPIGatewayV2IntegrationConfig_apiHttp(rName string) string {
return fmt.Sprintf(`
resource "aws_apigatewayv2_api" "test" {
name = %[1]q
protocol_type = "HTTP"
name = %[1]q
protocol_type = "HTTP"
}
`, rName)
}

func testAccAWSAPIGatewayV2IntegrationConfig_vpcLinkHttpBase(rName string) string {
return composeConfig(
testAccAWSAPIGatewayV2IntegrationConfig_apiHttp(rName),
testAccAWSAPIGatewayV2VpcLinkConfig_basic(rName),
fmt.Sprintf(`
resource "aws_lb" "test" {
name = %[1]q
internal = true
load_balancer_type = "network"
subnets = ["${aws_subnet.test.*.id[0]}", "${aws_subnet.test.*.id[1]}"]
tags = {
Name = %[1]q
}
}
resource "aws_lb_target_group" "test" {
name = %[1]q
port = 80
protocol = "TCP"
vpc_id = "${aws_vpc.test.id}"
health_check {
port = 80
protocol = "TCP"
}
tags = {
Name = %[1]q
}
}
resource "aws_lb_listener" "test" {
load_balancer_arn = "${aws_lb.test.arn}"
port = "80"
protocol = "TCP"
default_action {
target_group_arn = "${aws_lb_target_group.test.arn}"
type = "forward"
}
}
`, rName))
}

func testAccAWSAPIGatewayV2IntegrationConfig_basic(rName string) string {
return testAccAWSAPIGatewayV2IntegrationConfig_apiWebSocket(rName) + `
resource "aws_apigatewayv2_integration" "test" {
Expand Down Expand Up @@ -462,17 +586,63 @@ resource "aws_apigatewayv2_integration" "test" {
func testAccAWSAPIGatewayV2IntegrationConfig_httpProxy(rName string) string {
return testAccAWSAPIGatewayV2IntegrationConfig_apiHttp(rName) + fmt.Sprintf(`
resource "aws_apigatewayv2_integration" "test" {
api_id = "${aws_apigatewayv2_api.test.id}"
integration_type = "HTTP_PROXY"
api_id = "${aws_apigatewayv2_api.test.id}"
integration_type = "HTTP_PROXY"
integration_method = "GET"
integration_uri = "https://example.com"
integration_method = "GET"
integration_uri = "https://example.com"
}
`)
}

func testAccAWSAPIGatewayV2IntegrationConfig_vpcLink(rName string) string {
return testAccAWSAPIGatewayV2IntegrationConfig_apiWebSocket(rName) + fmt.Sprintf(`
func testAccAWSAPIGatewayV2IntegrationConfig_vpcLinkHttp(rName string) string {
return composeConfig(
testAccAWSAPIGatewayV2IntegrationConfig_vpcLinkHttpBase(rName),
fmt.Sprintf(`
resource "aws_apigatewayv2_integration" "test" {
api_id = "${aws_apigatewayv2_api.test.id}"
integration_type = "HTTP_PROXY"
connection_type = "VPC_LINK"
connection_id = "${aws_apigatewayv2_vpc_link.test.id}"
description = "Test private integration"
integration_method = "GET"
integration_uri = "${aws_lb_listener.test.arn}"
timeout_milliseconds = 5001
tls_config {
server_name_to_verify = "www.example.com"
}
}
`))
}

func testAccAWSAPIGatewayV2IntegrationConfig_vpcLinkHttpUpdated(rName string) string {
return composeConfig(
testAccAWSAPIGatewayV2IntegrationConfig_vpcLinkHttpBase(rName),
fmt.Sprintf(`
resource "aws_apigatewayv2_integration" "test" {
api_id = "${aws_apigatewayv2_api.test.id}"
integration_type = "HTTP_PROXY"
connection_type = "VPC_LINK"
connection_id = "${aws_apigatewayv2_vpc_link.test.id}"
description = "Test private integration updated"
integration_method = "POST"
integration_uri = "${aws_lb_listener.test.arn}"
timeout_milliseconds = 4999
tls_config {
server_name_to_verify = "www.example.org"
}
}
`))
}

func testAccAWSAPIGatewayV2IntegrationConfig_vpcLinkWebSocket(rName string) string {
return composeConfig(
testAccAWSAPIGatewayV2IntegrationConfig_apiWebSocket(rName),
fmt.Sprintf(`
data "aws_availability_zones" "available" {
state = "available"
Expand Down Expand Up @@ -505,6 +675,10 @@ resource "aws_lb" "test" {
internal = true
load_balancer_type = "network"
subnets = ["${aws_subnet.test.id}"]
tags = {
Name = %[1]q
}
}
resource "aws_api_gateway_vpc_link" "test" {
Expand All @@ -525,5 +699,5 @@ resource "aws_apigatewayv2_integration" "test" {
passthrough_behavior = "NEVER"
timeout_milliseconds = 12345
}
`, rName)
`, rName))
}
5 changes: 5 additions & 0 deletions website/docs/r/apigatewayv2_integration.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,11 @@ Supported only for WebSocket APIs.
* `request_templates` - (Optional) A map of Velocity templates that are applied on the request payload based on the value of the Content-Type header sent by the client. Supported only for WebSocket APIs.
* `template_selection_expression` - (Optional) The [template selection expression](https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-websocket-api-selection-expressions.html#apigateway-websocket-api-template-selection-expressions) for the integration.
* `timeout_milliseconds` - (Optional) Custom timeout between 50 and 29,000 milliseconds. The default value is 29,000 milliseconds or 29 seconds.
* `tls_config` - (Optional) The TLS configuration for a private integration. Supported only for HTTP APIs.

The `tls_config` object supports the following:

* `server_name_to_verify` - (Optional) If you specify a server name, API Gateway uses it to verify the hostname on the integration's certificate. The server name is also included in the TLS handshake to support Server Name Indication (SNI) or virtual hosting.

## Attribute Reference

Expand Down

0 comments on commit e3a1c91

Please sign in to comment.