From 1a6d1edb78ea9d52463f5c6fbc24191eb1679120 Mon Sep 17 00:00:00 2001 From: Eric Richter Date: Sun, 7 Nov 2021 16:00:54 +0100 Subject: [PATCH 1/5] tls_version_and_cipher_suite --- internal/service/elbv2/load_balancer.go | 18 +++ internal/service/elbv2/load_balancer_test.go | 109 +++++++++++++++++++ website/docs/r/lb.html.markdown | 1 + 3 files changed, 128 insertions(+) diff --git a/internal/service/elbv2/load_balancer.go b/internal/service/elbv2/load_balancer.go index 969436f28cd..bb0cacb6f4c 100644 --- a/internal/service/elbv2/load_balancer.go +++ b/internal/service/elbv2/load_balancer.go @@ -206,6 +206,13 @@ func ResourceLoadBalancer() *schema.Resource { DiffSuppressFunc: suppressIfLBType("network"), }, + "tls_version_and_cipher_suite": { + Type: schema.TypeBool, + Optional: true, + Default: false, + DiffSuppressFunc: suppressIfLBType("network"), + }, + "enable_cross_zone_load_balancing": { Type: schema.TypeBool, Optional: true, @@ -468,6 +475,13 @@ func resourceLoadBalancerUpdate(d *schema.ResourceData, meta interface{}) error }) } + if d.HasChange("tls_version_and_cipher_suite") || d.IsNewResource() { + attributes = append(attributes, &elbv2.LoadBalancerAttribute{ + Key: aws.String("routing.http.tls_version_and_cipher_suite.enabled"), + Value: aws.String(strconv.FormatBool(d.Get("tls_version_and_cipher_suite").(bool))), + }) + } + case elbv2.LoadBalancerTypeEnumGateway, elbv2.LoadBalancerTypeEnumNetwork: if d.HasChange("enable_cross_zone_load_balancing") || d.IsNewResource() { attributes = append(attributes, &elbv2.LoadBalancerAttribute{ @@ -812,6 +826,10 @@ func flattenResource(d *schema.ResourceData, meta interface{}, lb *elbv2.LoadBal dropInvalidHeaderFieldsEnabled := aws.StringValue(attr.Value) == "true" log.Printf("[DEBUG] Setting LB Invalid Header Fields Enabled: %t", dropInvalidHeaderFieldsEnabled) d.Set("drop_invalid_header_fields", dropInvalidHeaderFieldsEnabled) + case "routing.http.x_amzn_tls_version_and_cipher_suite.enabled": + amznTLSHeadersEnabled := aws.StringValue(attr.Value) == "true" + log.Printf("[DEBUG] Setting LB TLS Headers Fields Enabled: %t", amznTLSHeadersEnabled) + d.Set("tls_version_and_cipher_suite", amznTLSHeadersEnabled) case "deletion_protection.enabled": protectionEnabled := aws.StringValue(attr.Value) == "true" log.Printf("[DEBUG] Setting LB Deletion Protection Enabled: %t", protectionEnabled) diff --git a/internal/service/elbv2/load_balancer_test.go b/internal/service/elbv2/load_balancer_test.go index a4781f48c60..61e0ae9a08f 100644 --- a/internal/service/elbv2/load_balancer_test.go +++ b/internal/service/elbv2/load_balancer_test.go @@ -561,6 +561,46 @@ func TestAccELBV2LoadBalancer_ApplicationLoadBalancer_updateHTTP2(t *testing.T) }) } +func TestAccELBV2LoadBalancer_ApplicationLoadBalancer_updateTLSVersionAndCipherSuite(t *testing.T) { + var pre, mid, post elbv2.LoadBalancer + lbName := fmt.Sprintf("testAccAWSalb-headers-%s", sdkacctest.RandString(10)) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + ErrorCheck: acctest.ErrorCheck(t, elbv2.EndpointsID), + Providers: acctest.Providers, + CheckDestroy: testAccCheckLoadBalancerDestroy, + Steps: []resource.TestStep{ + { + Config: testAccLoadBalancerConfig_enableTLSVersionAndCipherSuite(lbName, false), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckLoadBalancerExists("aws_lb.lb_test", &pre), + testAccCheckLoadBalancerAttribute("aws_lb.lb_test", "routing.http.tls_version_and_cipher_suite.enabled", "false"), + resource.TestCheckResourceAttr("aws_lb.lb_test", "tls_version_and_cipher_suite", "false"), + ), + }, + { + Config: testAccLoadBalancerConfig_enableTLSVersionAndCipherSuite(lbName, true), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckLoadBalancerExists("aws_lb.lb_test", &mid), + testAccCheckLoadBalancerAttribute("aws_lb.lb_test", "routing.http.tls_version_and_cipher_suite.enabled", "true"), + resource.TestCheckResourceAttr("aws_lb.lb_test", "tls_version_and_cipher_suite", "true"), + testAccChecklbARNs(&pre, &mid), + ), + }, + { + Config: testAccLoadBalancerConfig_enableTLSVersionAndCipherSuite(lbName, false), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckLoadBalancerExists("aws_lb.lb_test", &post), + testAccCheckLoadBalancerAttribute("aws_lb.lb_test", "routing.http.tls_version_and_cipher_suite.enabled", "false"), + resource.TestCheckResourceAttr("aws_lb.lb_test", "tls_version_and_cipher_suite", "false"), + testAccChecklbARNs(&mid, &post), + ), + }, + }, + }) +} + func TestAccELBV2LoadBalancer_ApplicationLoadBalancer_updateDropInvalidHeaderFields(t *testing.T) { var pre, mid, post elbv2.LoadBalancer lbName := fmt.Sprintf("testAccAWSalb-headers-%s", sdkacctest.RandString(10)) @@ -1684,6 +1724,75 @@ resource "aws_security_group" "alb_test" { `, lbName, http2)) } +func testAccLoadBalancerConfig_enableTLSVersionAndCipherSuite(lbName string, tls_version_and_cipher_suite bool) string { + return acctest.ConfigCompose(acctest.ConfigAvailableAZsNoOptIn(), fmt.Sprintf(` +resource "aws_lb" "lb_test" { + name = "%s" + internal = true + security_groups = [aws_security_group.alb_test.id] + subnets = aws_subnet.alb_test[*].id + + idle_timeout = 30 + enable_deletion_protection = false + + tls_version_and_cipher_suite = %t + + tags = { + Name = "TestAccAWSALB_basic" + } +} + +variable "subnets" { + default = ["10.0.1.0/24", "10.0.2.0/24"] + type = list(string) +} + +resource "aws_vpc" "alb_test" { + cidr_block = "10.0.0.0/16" + + tags = { + Name = "terraform-testacc-lb-basic" + } +} + +resource "aws_subnet" "alb_test" { + count = 2 + vpc_id = aws_vpc.alb_test.id + cidr_block = element(var.subnets, count.index) + map_public_ip_on_launch = true + availability_zone = element(data.aws_availability_zones.available.names, count.index) + + tags = { + Name = "tf-acc-lb-basic-${count.index}" + } +} + +resource "aws_security_group" "alb_test" { + name = "allow_all_alb_test" + description = "Used for ALB Testing" + vpc_id = aws_vpc.alb_test.id + + ingress { + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } + + egress { + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } + + tags = { + Name = "TestAccAWSALB_basic" + } +} +`, lbName, tls_version_and_cipher_suite)) +} + func testAccLoadBalancerConfig_enableDropInvalidHeaderFields(lbName string, dropInvalid bool) string { return acctest.ConfigCompose(acctest.ConfigAvailableAZsNoOptIn(), fmt.Sprintf(` resource "aws_lb" "lb_test" { diff --git a/website/docs/r/lb.html.markdown b/website/docs/r/lb.html.markdown index d572957f1ee..a04fdcac9ef 100644 --- a/website/docs/r/lb.html.markdown +++ b/website/docs/r/lb.html.markdown @@ -109,6 +109,7 @@ Terraform will autogenerate a name beginning with `tf-lb`. * `load_balancer_type` - (Optional) The type of load balancer to create. Possible values are `application`, `gateway`, or `network`. The default value is `application`. * `security_groups` - (Optional) A list of security group IDs to assign to the LB. Only valid for Load Balancers of type `application`. * `drop_invalid_header_fields` - (Optional) Indicates whether HTTP headers with header fields that are not valid are removed by the load balancer (true) or routed to targets (false). The default is false. Elastic Load Balancing requires that message header names contain only alphanumeric characters and hyphens. Only valid for Load Balancers of type `application`. +* `tls_version_and_cipher_suite` - (Optional) Indicates whether the two headers (x-amzn-tls-version and x-amzn-tls-cipher-suite), which contain information about the negotiated TLS version and cipher suite, are added to the client request before sending it to the target. The x-amzn-tls-version header has information about the TLS protocol version negotiated with the client, and the x-amzn-tls-cipher-suite header has information about the cipher suite negotiated with the client. Both headers are in OpenSSL format. The possible values for the attribute are true and false. The default is `false`. Only valid for Load Balancers of type `application`. * `access_logs` - (Optional) An Access Logs block. Access Logs documented below. * `subnets` - (Optional) A list of subnet IDs to attach to the LB. Subnets cannot be updated for Load Balancers of type `network`. Changing this value From 94bb3de41610180a8005e0958cd3dac8f7fd5fa1 Mon Sep 17 00:00:00 2001 From: Eric Richter Date: Sun, 7 Nov 2021 16:10:35 +0100 Subject: [PATCH 2/5] changelog --- .changelog/21667.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/21667.txt diff --git a/.changelog/21667.txt b/.changelog/21667.txt new file mode 100644 index 00000000000..99e498d3732 --- /dev/null +++ b/.changelog/21667.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +resource/aws_lb: Add `tls_version_and_cipher_suite` argument to the loadbalancer +``` \ No newline at end of file From c86e7b0425ac7f14204a1a1df66497f2ab6ecbb2 Mon Sep 17 00:00:00 2001 From: Eric Richter Date: Sun, 7 Nov 2021 19:23:19 +0100 Subject: [PATCH 3/5] Few corrections from testacc --- internal/service/elbv2/load_balancer.go | 2 +- internal/service/elbv2/load_balancer_test.go | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/internal/service/elbv2/load_balancer.go b/internal/service/elbv2/load_balancer.go index bb0cacb6f4c..e6d87f592d7 100644 --- a/internal/service/elbv2/load_balancer.go +++ b/internal/service/elbv2/load_balancer.go @@ -477,7 +477,7 @@ func resourceLoadBalancerUpdate(d *schema.ResourceData, meta interface{}) error if d.HasChange("tls_version_and_cipher_suite") || d.IsNewResource() { attributes = append(attributes, &elbv2.LoadBalancerAttribute{ - Key: aws.String("routing.http.tls_version_and_cipher_suite.enabled"), + Key: aws.String("routing.http.x_amzn_tls_version_and_cipher_suite.enabled"), Value: aws.String(strconv.FormatBool(d.Get("tls_version_and_cipher_suite").(bool))), }) } diff --git a/internal/service/elbv2/load_balancer_test.go b/internal/service/elbv2/load_balancer_test.go index 61e0ae9a08f..ff0fb08663a 100644 --- a/internal/service/elbv2/load_balancer_test.go +++ b/internal/service/elbv2/load_balancer_test.go @@ -575,7 +575,7 @@ func TestAccELBV2LoadBalancer_ApplicationLoadBalancer_updateTLSVersionAndCipherS Config: testAccLoadBalancerConfig_enableTLSVersionAndCipherSuite(lbName, false), Check: resource.ComposeAggregateTestCheckFunc( testAccCheckLoadBalancerExists("aws_lb.lb_test", &pre), - testAccCheckLoadBalancerAttribute("aws_lb.lb_test", "routing.http.tls_version_and_cipher_suite.enabled", "false"), + testAccCheckLoadBalancerAttribute("aws_lb.lb_test", "routing.http.x_amzn_tls_version_and_cipher_suite.enabled", "false"), resource.TestCheckResourceAttr("aws_lb.lb_test", "tls_version_and_cipher_suite", "false"), ), }, @@ -583,7 +583,7 @@ func TestAccELBV2LoadBalancer_ApplicationLoadBalancer_updateTLSVersionAndCipherS Config: testAccLoadBalancerConfig_enableTLSVersionAndCipherSuite(lbName, true), Check: resource.ComposeAggregateTestCheckFunc( testAccCheckLoadBalancerExists("aws_lb.lb_test", &mid), - testAccCheckLoadBalancerAttribute("aws_lb.lb_test", "routing.http.tls_version_and_cipher_suite.enabled", "true"), + testAccCheckLoadBalancerAttribute("aws_lb.lb_test", "routing.http.x_amzn_tls_version_and_cipher_suite.enabled", "true"), resource.TestCheckResourceAttr("aws_lb.lb_test", "tls_version_and_cipher_suite", "true"), testAccChecklbARNs(&pre, &mid), ), @@ -592,7 +592,7 @@ func TestAccELBV2LoadBalancer_ApplicationLoadBalancer_updateTLSVersionAndCipherS Config: testAccLoadBalancerConfig_enableTLSVersionAndCipherSuite(lbName, false), Check: resource.ComposeAggregateTestCheckFunc( testAccCheckLoadBalancerExists("aws_lb.lb_test", &post), - testAccCheckLoadBalancerAttribute("aws_lb.lb_test", "routing.http.tls_version_and_cipher_suite.enabled", "false"), + testAccCheckLoadBalancerAttribute("aws_lb.lb_test", "routing.http.x_amzn_tls_version_and_cipher_suite.enabled", "false"), resource.TestCheckResourceAttr("aws_lb.lb_test", "tls_version_and_cipher_suite", "false"), testAccChecklbARNs(&mid, &post), ), From e67ea22d017b5023eecee361d583c2b2e760dfac Mon Sep 17 00:00:00 2001 From: Eric Richter Date: Sun, 5 Dec 2021 11:48:32 +0100 Subject: [PATCH 4/5] Add xff_client_port to elbv2 --- internal/service/elbv2/load_balancer.go | 19 ++++ internal/service/elbv2/load_balancer_test.go | 109 +++++++++++++++++++ 2 files changed, 128 insertions(+) diff --git a/internal/service/elbv2/load_balancer.go b/internal/service/elbv2/load_balancer.go index 7190994fc7d..11be1c02af6 100644 --- a/internal/service/elbv2/load_balancer.go +++ b/internal/service/elbv2/load_balancer.go @@ -213,6 +213,13 @@ func ResourceLoadBalancer() *schema.Resource { DiffSuppressFunc: suppressIfLBType("network"), }, + "xff_client_port": { + Type: schema.TypeBool, + Optional: true, + Default: false, + DiffSuppressFunc: suppressIfLBType("network"), + }, + "enable_cross_zone_load_balancing": { Type: schema.TypeBool, Optional: true, @@ -514,6 +521,14 @@ func resourceLoadBalancerUpdate(d *schema.ResourceData, meta interface{}) error Value: aws.String(strconv.FormatBool(d.Get("tls_version_and_cipher_suite").(bool))), }) } + + if d.HasChange("xff_client_port") || d.IsNewResource() { + attributes = append(attributes, &elbv2.LoadBalancerAttribute{ + Key: aws.String("routing.http.xff_client_port.enabled"), + Value: aws.String(strconv.FormatBool(d.Get("xff_client_port").(bool))), + }) + } + if d.HasChange("desync_mitigation_mode") || d.IsNewResource() { attributes = append(attributes, &elbv2.LoadBalancerAttribute{ Key: aws.String("routing.http.desync_mitigation_mode"), @@ -850,6 +865,10 @@ func flattenResource(d *schema.ResourceData, meta interface{}, lb *elbv2.LoadBal amznTLSHeadersEnabled := aws.StringValue(attr.Value) == "true" log.Printf("[DEBUG] Setting LB TLS Headers Fields Enabled: %t", amznTLSHeadersEnabled) d.Set("tls_version_and_cipher_suite", amznTLSHeadersEnabled) + case "routing.http.xff_client_port.enabled": + amznTLSHeadersEnabled := aws.StringValue(attr.Value) == "true" + log.Printf("[DEBUG] Setting LB TLS Headers Fields Enabled: %t", amznTLSHeadersEnabled) + d.Set("xff_client_port", amznTLSHeadersEnabled) case "deletion_protection.enabled": protectionEnabled := aws.StringValue(attr.Value) == "true" log.Printf("[DEBUG] Setting LB Deletion Protection Enabled: %t", protectionEnabled) diff --git a/internal/service/elbv2/load_balancer_test.go b/internal/service/elbv2/load_balancer_test.go index f4113cd6170..85dca7bbb9c 100644 --- a/internal/service/elbv2/load_balancer_test.go +++ b/internal/service/elbv2/load_balancer_test.go @@ -604,6 +604,46 @@ func TestAccELBV2LoadBalancer_ApplicationLoadBalancer_updateTLSVersionAndCipherS }) } +func TestAccELBV2LoadBalancer_ApplicationLoadBalancer_updateXFFClientPort(t *testing.T) { + var pre, mid, post elbv2.LoadBalancer + lbName := fmt.Sprintf("testAccAWSalb-headers-%s", sdkacctest.RandString(10)) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + ErrorCheck: acctest.ErrorCheck(t, elbv2.EndpointsID), + Providers: acctest.Providers, + CheckDestroy: testAccCheckLoadBalancerDestroy, + Steps: []resource.TestStep{ + { + Config: testAccLoadBalancerConfig_updateXFFClientPort(lbName, false), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckLoadBalancerExists("aws_lb.lb_test", &pre), + testAccCheckLoadBalancerAttribute("aws_lb.lb_test", "routing.http.xff_client_port.enabled", "false"), + resource.TestCheckResourceAttr("aws_lb.lb_test", "xff_client_port", "false"), + ), + }, + { + Config: testAccLoadBalancerConfig_updateXFFClientPort(lbName, true), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckLoadBalancerExists("aws_lb.lb_test", &mid), + testAccCheckLoadBalancerAttribute("aws_lb.lb_test", "routing.http.xff_client_port.enabled", "true"), + resource.TestCheckResourceAttr("aws_lb.lb_test", "xff_client_port", "true"), + testAccChecklbARNs(&pre, &mid), + ), + }, + { + Config: testAccLoadBalancerConfig_updateXFFClientPort(lbName, false), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckLoadBalancerExists("aws_lb.lb_test", &post), + testAccCheckLoadBalancerAttribute("aws_lb.lb_test", "routing.http.xff_client_port.enabled", "false"), + resource.TestCheckResourceAttr("aws_lb.lb_test", "xff_client_port", "false"), + testAccChecklbARNs(&mid, &post), + ), + }, + }, + }) +} + func TestAccELBV2LoadBalancer_ApplicationLoadBalancer_updateDropInvalidHeaderFields(t *testing.T) { var pre, mid, post elbv2.LoadBalancer lbName := fmt.Sprintf("testAccAWSalb-headers-%s", sdkacctest.RandString(10)) @@ -1893,6 +1933,75 @@ resource "aws_security_group" "alb_test" { `, lbName, tls_version_and_cipher_suite)) } +func testAccLoadBalancerConfig_updateXFFClientPort(lbName string, xff_client_port bool) string { + return acctest.ConfigCompose(acctest.ConfigAvailableAZsNoOptIn(), fmt.Sprintf(` +resource "aws_lb" "lb_test" { + name = "%s" + internal = true + security_groups = [aws_security_group.alb_test.id] + subnets = aws_subnet.alb_test[*].id + + idle_timeout = 30 + enable_deletion_protection = false + + xff_client_port = %t + + tags = { + Name = "TestAccAWSALB_basic" + } +} + +variable "subnets" { + default = ["10.0.1.0/24", "10.0.2.0/24"] + type = list(string) +} + +resource "aws_vpc" "alb_test" { + cidr_block = "10.0.0.0/16" + + tags = { + Name = "terraform-testacc-lb-basic" + } +} + +resource "aws_subnet" "alb_test" { + count = 2 + vpc_id = aws_vpc.alb_test.id + cidr_block = element(var.subnets, count.index) + map_public_ip_on_launch = true + availability_zone = element(data.aws_availability_zones.available.names, count.index) + + tags = { + Name = "tf-acc-lb-basic-${count.index}" + } +} + +resource "aws_security_group" "alb_test" { + name = "allow_all_alb_test" + description = "Used for ALB Testing" + vpc_id = aws_vpc.alb_test.id + + ingress { + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } + + egress { + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } + + tags = { + Name = "TestAccAWSALB_basic" + } +} +`, lbName, xff_client_port)) +} + func testAccLoadBalancerConfig_enableDropInvalidHeaderFields(lbName string, dropInvalid bool) string { return acctest.ConfigCompose(acctest.ConfigAvailableAZsNoOptIn(), fmt.Sprintf(` resource "aws_lb" "lb_test" { From 2b95115c62828a3613cd51d912891de5682eecae Mon Sep 17 00:00:00 2001 From: Eric Richter Date: Sun, 5 Dec 2021 11:55:51 +0100 Subject: [PATCH 5/5] Add documentation --- .changelog/21667.txt | 1 + website/docs/r/lb.html.markdown | 1 + 2 files changed, 2 insertions(+) diff --git a/.changelog/21667.txt b/.changelog/21667.txt index 99e498d3732..266109908f4 100644 --- a/.changelog/21667.txt +++ b/.changelog/21667.txt @@ -1,3 +1,4 @@ ```release-note:enhancement resource/aws_lb: Add `tls_version_and_cipher_suite` argument to the loadbalancer +resource/aws_lb: Add `xff_client_port` argument to the loadbalancer ``` \ No newline at end of file diff --git a/website/docs/r/lb.html.markdown b/website/docs/r/lb.html.markdown index b9ec9f35fab..c69dc390618 100644 --- a/website/docs/r/lb.html.markdown +++ b/website/docs/r/lb.html.markdown @@ -110,6 +110,7 @@ Terraform will autogenerate a name beginning with `tf-lb`. * `security_groups` - (Optional) A list of security group IDs to assign to the LB. Only valid for Load Balancers of type `application`. * `drop_invalid_header_fields` - (Optional) Indicates whether HTTP headers with header fields that are not valid are removed by the load balancer (true) or routed to targets (false). The default is false. Elastic Load Balancing requires that message header names contain only alphanumeric characters and hyphens. Only valid for Load Balancers of type `application`. * `tls_version_and_cipher_suite` - (Optional) Indicates whether the two headers (x-amzn-tls-version and x-amzn-tls-cipher-suite), which contain information about the negotiated TLS version and cipher suite, are added to the client request before sending it to the target. The x-amzn-tls-version header has information about the TLS protocol version negotiated with the client, and the x-amzn-tls-cipher-suite header has information about the cipher suite negotiated with the client. Both headers are in OpenSSL format. The possible values for the attribute are true and false. The default is `false`. Only valid for Load Balancers of type `application`. +* `xff_client_port` - (Optional) Indicates whether the X-Forwarded-For header should preserve the source port that the client used to connect to the load balancer. The possible values are true and false. The default is `false`. Only valid for Load Balancers of type `application`. * `access_logs` - (Optional) An Access Logs block. Access Logs documented below. * `subnets` - (Optional) A list of subnet IDs to attach to the LB. Subnets cannot be updated for Load Balancers of type `network`. Changing this value