Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

r/aws_apigatewayv2_integration: Add tls_config attribute #13013

Merged
merged 3 commits into from
Jul 22, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -125,6 +124,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 @@ -172,6 +185,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 @@ -217,6 +233,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 @@ -264,6 +283,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 @@ -320,3 +342,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 @@ -40,6 +40,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 @@ -146,6 +147,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 @@ -168,6 +170,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 @@ -210,6 +213,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 @@ -222,7 +226,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 @@ -235,7 +239,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 @@ -252,6 +256,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"),
),
},
{
ewbankkit marked this conversation as resolved.
Show resolved Hide resolved
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 @@ -355,12 +433,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 @@ -445,17 +569,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"
ewbankkit marked this conversation as resolved.
Show resolved Hide resolved
}
}
`))
}

func testAccAWSAPIGatewayV2IntegrationConfig_vpcLinkWebSocket(rName string) string {
return composeConfig(
testAccAWSAPIGatewayV2IntegrationConfig_apiWebSocket(rName),
fmt.Sprintf(`
data "aws_availability_zones" "available" {
state = "available"

Expand Down Expand Up @@ -488,6 +658,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 @@ -508,5 +682,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 @@ -67,6 +67,11 @@ Valid values: `WHEN_NO_MATCH`, `WHEN_NO_TEMPLATES`, `NEVER`. Default is `WHEN_NO
* `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