Skip to content

Commit fabea86

Browse files
authored
Merge pull request #33767 from evan-cleary/f-aws_lb-enforce_security_group_inbound_rules_on_private_link_traffic
r/aws_lb: Add enforce_security_group_inbound_rules_on_private_link_traffic
2 parents 754ca2c + e2b4362 commit fabea86

File tree

6 files changed

+150
-21
lines changed

6 files changed

+150
-21
lines changed

.changelog/33767.txt

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
```release-note:enhancement
2+
resource/aws_lb: Add `enforce_security_group_inbound_rules_on_private_link_traffic` argument
3+
```
4+
5+
```release-note:enhancement
6+
data-source/aws_lb: Add `enforce_security_group_inbound_rules_on_private_link_traffic` attribute
7+
```

internal/service/elbv2/load_balancer.go

+20-8
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import ( // nosemgrep:ci.semgrep.aws.multiple-service-imports
2929
"github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag"
3030
"github.com/hashicorp/terraform-provider-aws/internal/flex"
3131
tfec2 "github.com/hashicorp/terraform-provider-aws/internal/service/ec2"
32+
tfslices "github.com/hashicorp/terraform-provider-aws/internal/slices"
3233
tftags "github.com/hashicorp/terraform-provider-aws/internal/tags"
3334
"github.com/hashicorp/terraform-provider-aws/internal/tfresource"
3435
"github.com/hashicorp/terraform-provider-aws/internal/verify"
@@ -170,6 +171,13 @@ func ResourceLoadBalancer() *schema.Resource {
170171
Default: false,
171172
DiffSuppressFunc: suppressIfLBTypeNot(elbv2.LoadBalancerTypeEnumApplication),
172173
},
174+
"enforce_security_group_inbound_rules_on_private_link_traffic": {
175+
Type: schema.TypeString,
176+
Optional: true,
177+
Computed: true,
178+
ValidateFunc: validation.StringInSlice(elbv2.EnforceSecurityGroupInboundRulesOnPrivateLinkTrafficEnum_Values(), false),
179+
DiffSuppressFunc: suppressIfLBTypeNot(elbv2.LoadBalancerTypeEnumNetwork),
180+
},
173181
"idle_timeout": {
174182
Type: schema.TypeInt,
175183
Optional: true,
@@ -595,13 +603,20 @@ func resourceLoadBalancerUpdate(ctx context.Context, d *schema.ResourceData, met
595603
}
596604
}
597605

598-
if d.HasChange("security_groups") {
606+
if d.HasChanges("enforce_security_group_inbound_rules_on_private_link_traffic", "security_groups") {
599607
sgs := flex.ExpandStringSet(d.Get("security_groups").(*schema.Set))
600608

601609
params := &elbv2.SetSecurityGroupsInput{
602610
LoadBalancerArn: aws.String(d.Id()),
603611
SecurityGroups: sgs,
604612
}
613+
614+
if v := d.Get("load_balancer_type"); v == elbv2.LoadBalancerTypeEnumNetwork {
615+
if v, ok := d.GetOk("enforce_security_group_inbound_rules_on_private_link_traffic"); ok {
616+
params.EnforceSecurityGroupInboundRulesOnPrivateLinkTraffic = aws.String(v.(string))
617+
}
618+
}
619+
605620
_, err := conn.SetSecurityGroupsWithContext(ctx, params)
606621
if err != nil {
607622
return sdkdiag.AppendErrorf(diags, "failure Setting LB Security Groups: %s", err)
@@ -889,14 +904,10 @@ func getLBNameFromARN(arn string) (string, error) {
889904
return matches[1], nil
890905
}
891906

892-
// flattenSubnetsFromAvailabilityZones creates a slice of strings containing the subnet IDs
893-
// for the ALB based on the AvailabilityZones structure returned by the API.
894907
func flattenSubnetsFromAvailabilityZones(availabilityZones []*elbv2.AvailabilityZone) []string {
895-
var result []string
896-
for _, az := range availabilityZones {
897-
result = append(result, aws.StringValue(az.SubnetId))
898-
}
899-
return result
908+
return tfslices.ApplyToAll(availabilityZones, func(v *elbv2.AvailabilityZone) string {
909+
return aws.StringValue(v.SubnetId)
910+
})
900911
}
901912

902913
func flattenSubnetMappingsFromAvailabilityZones(availabilityZones []*elbv2.AvailabilityZone) []map[string]interface{} {
@@ -939,6 +950,7 @@ func flattenResource(ctx context.Context, d *schema.ResourceData, meta interface
939950
d.Set("arn_suffix", SuffixFromARN(lb.LoadBalancerArn))
940951
d.Set("customer_owned_ipv4_pool", lb.CustomerOwnedIpv4Pool)
941952
d.Set("dns_name", lb.DNSName)
953+
d.Set("enforce_security_group_inbound_rules_on_private_link_traffic", lb.EnforceSecurityGroupInboundRulesOnPrivateLinkTraffic)
942954
d.Set("internal", aws.StringValue(lb.Scheme) == elbv2.LoadBalancerSchemeEnumInternal)
943955
d.Set("ip_address_type", lb.IpAddressType)
944956
d.Set("load_balancer_type", lb.Type)

internal/service/elbv2/load_balancer_data_source.go

+14-13
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,10 @@ func DataSourceLoadBalancer() *schema.Resource {
103103
Type: schema.TypeBool,
104104
Computed: true,
105105
},
106+
"enforce_security_group_inbound_rules_on_private_link_traffic": {
107+
Type: schema.TypeString,
108+
Computed: true,
109+
},
106110
"idle_timeout": {
107111
Type: schema.TypeInt,
108112
Computed: true,
@@ -234,28 +238,25 @@ func dataSourceLoadBalancerRead(ctx context.Context, d *schema.ResourceData, met
234238
}
235239

236240
lb := results[0]
237-
238241
d.SetId(aws.StringValue(lb.LoadBalancerArn))
239-
240242
d.Set("arn", lb.LoadBalancerArn)
241243
d.Set("arn_suffix", SuffixFromARN(lb.LoadBalancerArn))
242-
d.Set("name", lb.LoadBalancerName)
243-
d.Set("internal", lb.Scheme != nil && aws.StringValue(lb.Scheme) == "internal")
244-
d.Set("security_groups", flex.FlattenStringList(lb.SecurityGroups))
245-
d.Set("vpc_id", lb.VpcId)
246-
d.Set("zone_id", lb.CanonicalHostedZoneId)
244+
d.Set("customer_owned_ipv4_pool", lb.CustomerOwnedIpv4Pool)
247245
d.Set("dns_name", lb.DNSName)
246+
d.Set("enforce_security_group_inbound_rules_on_private_link_traffic", lb.EnforceSecurityGroupInboundRulesOnPrivateLinkTraffic)
248247
d.Set("ip_address_type", lb.IpAddressType)
248+
d.Set("name", lb.LoadBalancerName)
249+
d.Set("internal", aws.StringValue(lb.Scheme) == "internal")
249250
d.Set("load_balancer_type", lb.Type)
250-
d.Set("customer_owned_ipv4_pool", lb.CustomerOwnedIpv4Pool)
251-
252-
if err := d.Set("subnets", flattenSubnetsFromAvailabilityZones(lb.AvailabilityZones)); err != nil {
253-
return sdkdiag.AppendErrorf(diags, "setting subnets: %s", err)
254-
}
255-
251+
d.Set("security_groups", aws.StringValueSlice(lb.SecurityGroups))
256252
if err := d.Set("subnet_mapping", flattenSubnetMappingsFromAvailabilityZones(lb.AvailabilityZones)); err != nil {
257253
return sdkdiag.AppendErrorf(diags, "setting subnet_mapping: %s", err)
258254
}
255+
if err := d.Set("subnets", flattenSubnetsFromAvailabilityZones(lb.AvailabilityZones)); err != nil {
256+
return sdkdiag.AppendErrorf(diags, "setting subnets: %s", err)
257+
}
258+
d.Set("vpc_id", lb.VpcId)
259+
d.Set("zone_id", lb.CanonicalHostedZoneId)
259260

260261
attributesResp, err := conn.DescribeLoadBalancerAttributesWithContext(ctx, &elbv2.DescribeLoadBalancerAttributesInput{
261262
LoadBalancerArn: aws.String(d.Id()),

internal/service/elbv2/load_balancer_data_source_test.go

+3
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ func TestAccELBV2LoadBalancerDataSource_basic(t *testing.T) {
4545
resource.TestCheckResourceAttrPair(dataSourceName, "ip_address_type", resourceName, "ip_address_type"),
4646
resource.TestCheckResourceAttrPair(dataSourceName, "subnet_mapping.#", resourceName, "subnet_mapping.#"),
4747
resource.TestCheckResourceAttrPair(dataSourceName, "desync_mitigation_mode", resourceName, "desync_mitigation_mode"),
48+
resource.TestCheckResourceAttrPair(dataSourceName, "enforce_security_group_inbound_rules_on_private_link_traffic", resourceName, "enforce_security_group_inbound_rules_on_private_link_traffic"),
4849
resource.TestCheckResourceAttrPair(dataSourceName2, "name", resourceName, "name"),
4950
resource.TestCheckResourceAttrPair(dataSourceName2, "internal", resourceName, "internal"),
5051
resource.TestCheckResourceAttrPair(dataSourceName2, "subnets.#", resourceName, "subnets.#"),
@@ -61,6 +62,7 @@ func TestAccELBV2LoadBalancerDataSource_basic(t *testing.T) {
6162
resource.TestCheckResourceAttrPair(dataSourceName2, "ip_address_type", resourceName, "ip_address_type"),
6263
resource.TestCheckResourceAttrPair(dataSourceName2, "subnet_mapping.#", resourceName, "subnet_mapping.#"),
6364
resource.TestCheckResourceAttrPair(dataSourceName2, "desync_mitigation_mode", resourceName, "desync_mitigation_mode"),
65+
resource.TestCheckResourceAttrPair(dataSourceName2, "enforce_security_group_inbound_rules_on_private_link_traffic", resourceName, "enforce_security_group_inbound_rules_on_private_link_traffic"),
6466
resource.TestCheckResourceAttrPair(dataSourceName3, "name", resourceName, "name"),
6567
resource.TestCheckResourceAttrPair(dataSourceName3, "internal", resourceName, "internal"),
6668
resource.TestCheckResourceAttrPair(dataSourceName3, "subnets.#", resourceName, "subnets.#"),
@@ -77,6 +79,7 @@ func TestAccELBV2LoadBalancerDataSource_basic(t *testing.T) {
7779
resource.TestCheckResourceAttrPair(dataSourceName3, "ip_address_type", resourceName, "ip_address_type"),
7880
resource.TestCheckResourceAttrPair(dataSourceName3, "subnet_mapping.#", resourceName, "subnet_mapping.#"),
7981
resource.TestCheckResourceAttrPair(dataSourceName3, "desync_mitigation_mode", resourceName, "desync_mitigation_mode"),
82+
resource.TestCheckResourceAttrPair(dataSourceName3, "enforce_security_group_inbound_rules_on_private_link_traffic", resourceName, "enforce_security_group_inbound_rules_on_private_link_traffic"),
8083
resource.TestCheckResourceAttrPair(dataSourceName3, "enable_tls_version_and_cipher_suite_headers", resourceName, "enable_tls_version_and_cipher_suite_headers"),
8184
resource.TestCheckResourceAttrPair(dataSourceName3, "enable_xff_client_port", resourceName, "enable_xff_client_port"),
8285
resource.TestCheckResourceAttrPair(dataSourceName3, "xff_header_processing_mode", resourceName, "xff_header_processing_mode"),

internal/service/elbv2/load_balancer_test.go

+105
Original file line numberDiff line numberDiff line change
@@ -915,13 +915,15 @@ func TestAccELBV2LoadBalancer_ApplicationLoadBalancer_updatedSecurityGroups(t *t
915915
Check: resource.ComposeAggregateTestCheckFunc(
916916
testAccCheckLoadBalancerExists(ctx, resourceName, &pre),
917917
resource.TestCheckResourceAttr(resourceName, "security_groups.#", "1"),
918+
resource.TestCheckResourceAttr(resourceName, "enforce_security_group_inbound_rules_on_private_link_traffic", ""),
918919
),
919920
},
920921
{
921922
Config: testAccLoadBalancerConfig_albUpdateSecurityGroups(rName),
922923
Check: resource.ComposeAggregateTestCheckFunc(
923924
testAccCheckLoadBalancerExists(ctx, resourceName, &post),
924925
resource.TestCheckResourceAttr(resourceName, "security_groups.#", "2"),
926+
resource.TestCheckResourceAttr(resourceName, "enforce_security_group_inbound_rules_on_private_link_traffic", ""),
925927
testAccCheckLoadBalancerNotRecreated(&pre, &post),
926928
),
927929
},
@@ -1389,6 +1391,7 @@ func TestAccELBV2LoadBalancer_NetworkLoadBalancer_updateSecurityGroups(t *testin
13891391
Check: resource.ComposeAggregateTestCheckFunc(
13901392
testAccCheckLoadBalancerExists(ctx, resourceName, &lb1),
13911393
resource.TestCheckResourceAttr(resourceName, "security_groups.#", "0"),
1394+
resource.TestCheckResourceAttr(resourceName, "enforce_security_group_inbound_rules_on_private_link_traffic", ""),
13921395
),
13931396
},
13941397
{
@@ -1397,6 +1400,7 @@ func TestAccELBV2LoadBalancer_NetworkLoadBalancer_updateSecurityGroups(t *testin
13971400
testAccCheckLoadBalancerExists(ctx, resourceName, &lb2),
13981401
testAccCheckLoadBalancerRecreated(&lb2, &lb1),
13991402
resource.TestCheckResourceAttr(resourceName, "security_groups.#", "1"),
1403+
resource.TestCheckResourceAttr(resourceName, "enforce_security_group_inbound_rules_on_private_link_traffic", ""),
14001404
),
14011405
},
14021406
{
@@ -1405,6 +1409,7 @@ func TestAccELBV2LoadBalancer_NetworkLoadBalancer_updateSecurityGroups(t *testin
14051409
testAccCheckLoadBalancerExists(ctx, resourceName, &lb3),
14061410
testAccCheckLoadBalancerNotRecreated(&lb3, &lb2),
14071411
resource.TestCheckResourceAttr(resourceName, "security_groups.#", "2"),
1412+
resource.TestCheckResourceAttr(resourceName, "enforce_security_group_inbound_rules_on_private_link_traffic", ""),
14081413
),
14091414
},
14101415
{
@@ -1413,6 +1418,67 @@ func TestAccELBV2LoadBalancer_NetworkLoadBalancer_updateSecurityGroups(t *testin
14131418
testAccCheckLoadBalancerExists(ctx, resourceName, &lb4),
14141419
testAccCheckLoadBalancerRecreated(&lb4, &lb3),
14151420
resource.TestCheckResourceAttr(resourceName, "security_groups.#", "0"),
1421+
resource.TestCheckResourceAttr(resourceName, "enforce_security_group_inbound_rules_on_private_link_traffic", ""),
1422+
),
1423+
},
1424+
},
1425+
})
1426+
}
1427+
1428+
func TestAccELBV2LoadBalancer_NetworkLoadBalancer_enforcePrivateLink(t *testing.T) {
1429+
ctx := acctest.Context(t)
1430+
var lb1 elbv2.LoadBalancer
1431+
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
1432+
resourceName := "aws_lb.test"
1433+
1434+
resource.ParallelTest(t, resource.TestCase{
1435+
PreCheck: func() { acctest.PreCheck(ctx, t) },
1436+
ErrorCheck: acctest.ErrorCheck(t, elbv2.EndpointsID),
1437+
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
1438+
CheckDestroy: testAccCheckLoadBalancerDestroy(ctx),
1439+
Steps: []resource.TestStep{
1440+
{
1441+
Config: testAccLoadBalancerConfig_nlbSecurityGroupsEnforcePrivateLink(rName, 1, "off"),
1442+
Check: resource.ComposeAggregateTestCheckFunc(
1443+
testAccCheckLoadBalancerExists(ctx, resourceName, &lb1),
1444+
resource.TestCheckResourceAttr(resourceName, "security_groups.#", "1"),
1445+
resource.TestCheckResourceAttr(resourceName, "enforce_security_group_inbound_rules_on_private_link_traffic", "off")),
1446+
},
1447+
{
1448+
ResourceName: resourceName,
1449+
ImportState: true,
1450+
ImportStateVerify: true,
1451+
},
1452+
{
1453+
Config: testAccLoadBalancerConfig_nlbSecurityGroups(rName, 1),
1454+
Check: resource.ComposeAggregateTestCheckFunc(
1455+
testAccCheckLoadBalancerExists(ctx, resourceName, &lb1),
1456+
resource.TestCheckResourceAttr(resourceName, "security_groups.#", "1"),
1457+
resource.TestCheckResourceAttr(resourceName, "enforce_security_group_inbound_rules_on_private_link_traffic", "off"),
1458+
),
1459+
},
1460+
{
1461+
Config: testAccLoadBalancerConfig_nlbSecurityGroupsEnforcePrivateLink(rName, 1, "on"),
1462+
Check: resource.ComposeAggregateTestCheckFunc(
1463+
testAccCheckLoadBalancerExists(ctx, resourceName, &lb1),
1464+
resource.TestCheckResourceAttr(resourceName, "security_groups.#", "1"),
1465+
resource.TestCheckResourceAttr(resourceName, "enforce_security_group_inbound_rules_on_private_link_traffic", "on"),
1466+
),
1467+
},
1468+
{
1469+
Config: testAccLoadBalancerConfig_nlbSecurityGroupsEnforcePrivateLink(rName, 1, "off"),
1470+
Check: resource.ComposeAggregateTestCheckFunc(
1471+
testAccCheckLoadBalancerExists(ctx, resourceName, &lb1),
1472+
resource.TestCheckResourceAttr(resourceName, "security_groups.#", "1"),
1473+
resource.TestCheckResourceAttr(resourceName, "enforce_security_group_inbound_rules_on_private_link_traffic", "off"),
1474+
),
1475+
},
1476+
{
1477+
Config: testAccLoadBalancerConfig_nlbSecurityGroups(rName, 1),
1478+
Check: resource.ComposeAggregateTestCheckFunc(
1479+
testAccCheckLoadBalancerExists(ctx, resourceName, &lb1),
1480+
resource.TestCheckResourceAttr(resourceName, "security_groups.#", "1"),
1481+
resource.TestCheckResourceAttr(resourceName, "enforce_security_group_inbound_rules_on_private_link_traffic", "off"),
14161482
),
14171483
},
14181484
},
@@ -2656,6 +2722,45 @@ resource "aws_lb" "test" {
26562722
`, rName, n))
26572723
}
26582724

2725+
func testAccLoadBalancerConfig_nlbSecurityGroupsEnforcePrivateLink(rName string, n int, enforcePrivateLink string) string {
2726+
return acctest.ConfigCompose(acctest.ConfigVPCWithSubnets(rName, 2), fmt.Sprintf(`
2727+
resource "aws_security_group" "test" {
2728+
count = 3
2729+
2730+
name = "%[1]s-${count.index}"
2731+
vpc_id = aws_vpc.test.id
2732+
2733+
ingress {
2734+
from_port = 0
2735+
to_port = 0
2736+
protocol = "-1"
2737+
cidr_blocks = ["0.0.0.0/0"]
2738+
}
2739+
2740+
egress {
2741+
from_port = 0
2742+
to_port = 0
2743+
protocol = "-1"
2744+
cidr_blocks = ["0.0.0.0/0"]
2745+
}
2746+
2747+
tags = {
2748+
Name = %[1]q
2749+
}
2750+
}
2751+
2752+
resource "aws_lb" "test" {
2753+
internal = true
2754+
load_balancer_type = "network"
2755+
name = %[1]q
2756+
subnets = aws_subnet.test[*].id
2757+
security_groups = slice(aws_security_group.test[*].id, 0, %[2]d)
2758+
2759+
enforce_security_group_inbound_rules_on_private_link_traffic = %[3]q
2760+
}
2761+
`, rName, n, enforcePrivateLink))
2762+
}
2763+
26592764
func testAccLoadBalancerConfig_nlbSubnets(rName string, subnetCount int) string {
26602765
return acctest.ConfigCompose(acctest.ConfigVPCWithSubnets(rName, subnetCount), fmt.Sprintf(`
26612766
resource "aws_lb" "test" {

website/docs/r/lb.html.markdown

+1
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ This resource supports the following arguments:
112112
* `enable_tls_version_and_cipher_suite_headers` - (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. Only valid for Load Balancers of type `application`. Defaults to `false`
113113
* `enable_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 in `application` load balancers. Defaults to `false`.
114114
* `enable_waf_fail_open` - (Optional) Indicates whether to allow a WAF-enabled load balancer to route requests to targets if it is unable to forward the request to AWS WAF. Defaults to `false`.
115+
* `enforce_security_group_inbound_rules_on_private_link_traffic` - (Optional) Indicates whether inbound security group rules are enforced for traffic originating from a PrivateLink. Only valid for Load Balancers of type `network`. The possible values are `on` and `off`.
115116
* `idle_timeout` - (Optional) The time in seconds that the connection is allowed to be idle. Only valid for Load Balancers of type `application`. Default: 60.
116117
* `internal` - (Optional) If true, the LB will be internal. Defaults to `false`.
117118
* `ip_address_type` - (Optional) The type of IP addresses used by the subnets for your load balancer. The possible values are `ipv4` and `dualstack`.

0 commit comments

Comments
 (0)