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_lb: Add enforce_security_group_inbound_rules_on_private_link_traffic #33767

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
7 changes: 7 additions & 0 deletions .changelog/33767.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
```release-note:enhancement
resource/aws_lb: Add `enforce_security_group_inbound_rules_on_private_link_traffic` argument
```

```release-note:enhancement
data-source/aws_lb: Add `enforce_security_group_inbound_rules_on_private_link_traffic` attribute
```
28 changes: 20 additions & 8 deletions internal/service/elbv2/load_balancer.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import ( // nosemgrep:ci.semgrep.aws.multiple-service-imports
"github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag"
"github.com/hashicorp/terraform-provider-aws/internal/flex"
tfec2 "github.com/hashicorp/terraform-provider-aws/internal/service/ec2"
tfslices "github.com/hashicorp/terraform-provider-aws/internal/slices"
tftags "github.com/hashicorp/terraform-provider-aws/internal/tags"
"github.com/hashicorp/terraform-provider-aws/internal/tfresource"
"github.com/hashicorp/terraform-provider-aws/internal/verify"
Expand Down Expand Up @@ -170,6 +171,13 @@ func ResourceLoadBalancer() *schema.Resource {
Default: false,
DiffSuppressFunc: suppressIfLBTypeNot(elbv2.LoadBalancerTypeEnumApplication),
},
"enforce_security_group_inbound_rules_on_private_link_traffic": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ValidateFunc: validation.StringInSlice(elbv2.EnforceSecurityGroupInboundRulesOnPrivateLinkTrafficEnum_Values(), false),
DiffSuppressFunc: suppressIfLBTypeNot(elbv2.LoadBalancerTypeEnumNetwork),
},
"idle_timeout": {
Type: schema.TypeInt,
Optional: true,
Expand Down Expand Up @@ -595,13 +603,20 @@ func resourceLoadBalancerUpdate(ctx context.Context, d *schema.ResourceData, met
}
}

if d.HasChange("security_groups") {
if d.HasChanges("enforce_security_group_inbound_rules_on_private_link_traffic", "security_groups") {
sgs := flex.ExpandStringSet(d.Get("security_groups").(*schema.Set))

params := &elbv2.SetSecurityGroupsInput{
LoadBalancerArn: aws.String(d.Id()),
SecurityGroups: sgs,
}

if v := d.Get("load_balancer_type"); v == elbv2.LoadBalancerTypeEnumNetwork {
if v, ok := d.GetOk("enforce_security_group_inbound_rules_on_private_link_traffic"); ok {
params.EnforceSecurityGroupInboundRulesOnPrivateLinkTraffic = aws.String(v.(string))
}
}

_, err := conn.SetSecurityGroupsWithContext(ctx, params)
if err != nil {
return sdkdiag.AppendErrorf(diags, "failure Setting LB Security Groups: %s", err)
Expand Down Expand Up @@ -889,14 +904,10 @@ func getLBNameFromARN(arn string) (string, error) {
return matches[1], nil
}

// flattenSubnetsFromAvailabilityZones creates a slice of strings containing the subnet IDs
// for the ALB based on the AvailabilityZones structure returned by the API.
func flattenSubnetsFromAvailabilityZones(availabilityZones []*elbv2.AvailabilityZone) []string {
var result []string
for _, az := range availabilityZones {
result = append(result, aws.StringValue(az.SubnetId))
}
return result
return tfslices.ApplyToAll(availabilityZones, func(v *elbv2.AvailabilityZone) string {
return aws.StringValue(v.SubnetId)
})
}

func flattenSubnetMappingsFromAvailabilityZones(availabilityZones []*elbv2.AvailabilityZone) []map[string]interface{} {
Expand Down Expand Up @@ -939,6 +950,7 @@ func flattenResource(ctx context.Context, d *schema.ResourceData, meta interface
d.Set("arn_suffix", SuffixFromARN(lb.LoadBalancerArn))
d.Set("customer_owned_ipv4_pool", lb.CustomerOwnedIpv4Pool)
d.Set("dns_name", lb.DNSName)
d.Set("enforce_security_group_inbound_rules_on_private_link_traffic", lb.EnforceSecurityGroupInboundRulesOnPrivateLinkTraffic)
d.Set("internal", aws.StringValue(lb.Scheme) == elbv2.LoadBalancerSchemeEnumInternal)
d.Set("ip_address_type", lb.IpAddressType)
d.Set("load_balancer_type", lb.Type)
Expand Down
27 changes: 14 additions & 13 deletions internal/service/elbv2/load_balancer_data_source.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,10 @@ func DataSourceLoadBalancer() *schema.Resource {
Type: schema.TypeBool,
Computed: true,
},
"enforce_security_group_inbound_rules_on_private_link_traffic": {
Type: schema.TypeString,
Computed: true,
},
"idle_timeout": {
Type: schema.TypeInt,
Computed: true,
Expand Down Expand Up @@ -234,28 +238,25 @@ func dataSourceLoadBalancerRead(ctx context.Context, d *schema.ResourceData, met
}

lb := results[0]

d.SetId(aws.StringValue(lb.LoadBalancerArn))

d.Set("arn", lb.LoadBalancerArn)
d.Set("arn_suffix", SuffixFromARN(lb.LoadBalancerArn))
d.Set("name", lb.LoadBalancerName)
d.Set("internal", lb.Scheme != nil && aws.StringValue(lb.Scheme) == "internal")
d.Set("security_groups", flex.FlattenStringList(lb.SecurityGroups))
d.Set("vpc_id", lb.VpcId)
d.Set("zone_id", lb.CanonicalHostedZoneId)
d.Set("customer_owned_ipv4_pool", lb.CustomerOwnedIpv4Pool)
d.Set("dns_name", lb.DNSName)
d.Set("enforce_security_group_inbound_rules_on_private_link_traffic", lb.EnforceSecurityGroupInboundRulesOnPrivateLinkTraffic)
d.Set("ip_address_type", lb.IpAddressType)
d.Set("name", lb.LoadBalancerName)
d.Set("internal", aws.StringValue(lb.Scheme) == "internal")
d.Set("load_balancer_type", lb.Type)
d.Set("customer_owned_ipv4_pool", lb.CustomerOwnedIpv4Pool)

if err := d.Set("subnets", flattenSubnetsFromAvailabilityZones(lb.AvailabilityZones)); err != nil {
return sdkdiag.AppendErrorf(diags, "setting subnets: %s", err)
}

d.Set("security_groups", aws.StringValueSlice(lb.SecurityGroups))
if err := d.Set("subnet_mapping", flattenSubnetMappingsFromAvailabilityZones(lb.AvailabilityZones)); err != nil {
return sdkdiag.AppendErrorf(diags, "setting subnet_mapping: %s", err)
}
if err := d.Set("subnets", flattenSubnetsFromAvailabilityZones(lb.AvailabilityZones)); err != nil {
return sdkdiag.AppendErrorf(diags, "setting subnets: %s", err)
}
d.Set("vpc_id", lb.VpcId)
d.Set("zone_id", lb.CanonicalHostedZoneId)

attributesResp, err := conn.DescribeLoadBalancerAttributesWithContext(ctx, &elbv2.DescribeLoadBalancerAttributesInput{
LoadBalancerArn: aws.String(d.Id()),
Expand Down
3 changes: 3 additions & 0 deletions internal/service/elbv2/load_balancer_data_source_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ func TestAccELBV2LoadBalancerDataSource_basic(t *testing.T) {
resource.TestCheckResourceAttrPair(dataSourceName, "ip_address_type", resourceName, "ip_address_type"),
resource.TestCheckResourceAttrPair(dataSourceName, "subnet_mapping.#", resourceName, "subnet_mapping.#"),
resource.TestCheckResourceAttrPair(dataSourceName, "desync_mitigation_mode", resourceName, "desync_mitigation_mode"),
resource.TestCheckResourceAttrPair(dataSourceName, "enforce_security_group_inbound_rules_on_private_link_traffic", resourceName, "enforce_security_group_inbound_rules_on_private_link_traffic"),
resource.TestCheckResourceAttrPair(dataSourceName2, "name", resourceName, "name"),
resource.TestCheckResourceAttrPair(dataSourceName2, "internal", resourceName, "internal"),
resource.TestCheckResourceAttrPair(dataSourceName2, "subnets.#", resourceName, "subnets.#"),
Expand All @@ -61,6 +62,7 @@ func TestAccELBV2LoadBalancerDataSource_basic(t *testing.T) {
resource.TestCheckResourceAttrPair(dataSourceName2, "ip_address_type", resourceName, "ip_address_type"),
resource.TestCheckResourceAttrPair(dataSourceName2, "subnet_mapping.#", resourceName, "subnet_mapping.#"),
resource.TestCheckResourceAttrPair(dataSourceName2, "desync_mitigation_mode", resourceName, "desync_mitigation_mode"),
resource.TestCheckResourceAttrPair(dataSourceName2, "enforce_security_group_inbound_rules_on_private_link_traffic", resourceName, "enforce_security_group_inbound_rules_on_private_link_traffic"),
resource.TestCheckResourceAttrPair(dataSourceName3, "name", resourceName, "name"),
resource.TestCheckResourceAttrPair(dataSourceName3, "internal", resourceName, "internal"),
resource.TestCheckResourceAttrPair(dataSourceName3, "subnets.#", resourceName, "subnets.#"),
Expand All @@ -77,6 +79,7 @@ func TestAccELBV2LoadBalancerDataSource_basic(t *testing.T) {
resource.TestCheckResourceAttrPair(dataSourceName3, "ip_address_type", resourceName, "ip_address_type"),
resource.TestCheckResourceAttrPair(dataSourceName3, "subnet_mapping.#", resourceName, "subnet_mapping.#"),
resource.TestCheckResourceAttrPair(dataSourceName3, "desync_mitigation_mode", resourceName, "desync_mitigation_mode"),
resource.TestCheckResourceAttrPair(dataSourceName3, "enforce_security_group_inbound_rules_on_private_link_traffic", resourceName, "enforce_security_group_inbound_rules_on_private_link_traffic"),
resource.TestCheckResourceAttrPair(dataSourceName3, "enable_tls_version_and_cipher_suite_headers", resourceName, "enable_tls_version_and_cipher_suite_headers"),
resource.TestCheckResourceAttrPair(dataSourceName3, "enable_xff_client_port", resourceName, "enable_xff_client_port"),
resource.TestCheckResourceAttrPair(dataSourceName3, "xff_header_processing_mode", resourceName, "xff_header_processing_mode"),
Expand Down
105 changes: 105 additions & 0 deletions internal/service/elbv2/load_balancer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -915,13 +915,15 @@ func TestAccELBV2LoadBalancer_ApplicationLoadBalancer_updatedSecurityGroups(t *t
Check: resource.ComposeAggregateTestCheckFunc(
testAccCheckLoadBalancerExists(ctx, resourceName, &pre),
resource.TestCheckResourceAttr(resourceName, "security_groups.#", "1"),
resource.TestCheckResourceAttr(resourceName, "enforce_security_group_inbound_rules_on_private_link_traffic", ""),
),
},
{
Config: testAccLoadBalancerConfig_albUpdateSecurityGroups(rName),
Check: resource.ComposeAggregateTestCheckFunc(
testAccCheckLoadBalancerExists(ctx, resourceName, &post),
resource.TestCheckResourceAttr(resourceName, "security_groups.#", "2"),
resource.TestCheckResourceAttr(resourceName, "enforce_security_group_inbound_rules_on_private_link_traffic", ""),
testAccCheckLoadBalancerNotRecreated(&pre, &post),
),
},
Expand Down Expand Up @@ -1389,6 +1391,7 @@ func TestAccELBV2LoadBalancer_NetworkLoadBalancer_updateSecurityGroups(t *testin
Check: resource.ComposeAggregateTestCheckFunc(
testAccCheckLoadBalancerExists(ctx, resourceName, &lb1),
resource.TestCheckResourceAttr(resourceName, "security_groups.#", "0"),
resource.TestCheckResourceAttr(resourceName, "enforce_security_group_inbound_rules_on_private_link_traffic", ""),
),
},
{
Expand All @@ -1397,6 +1400,7 @@ func TestAccELBV2LoadBalancer_NetworkLoadBalancer_updateSecurityGroups(t *testin
testAccCheckLoadBalancerExists(ctx, resourceName, &lb2),
testAccCheckLoadBalancerRecreated(&lb2, &lb1),
resource.TestCheckResourceAttr(resourceName, "security_groups.#", "1"),
resource.TestCheckResourceAttr(resourceName, "enforce_security_group_inbound_rules_on_private_link_traffic", ""),
),
},
{
Expand All @@ -1405,6 +1409,7 @@ func TestAccELBV2LoadBalancer_NetworkLoadBalancer_updateSecurityGroups(t *testin
testAccCheckLoadBalancerExists(ctx, resourceName, &lb3),
testAccCheckLoadBalancerNotRecreated(&lb3, &lb2),
resource.TestCheckResourceAttr(resourceName, "security_groups.#", "2"),
resource.TestCheckResourceAttr(resourceName, "enforce_security_group_inbound_rules_on_private_link_traffic", ""),
),
},
{
Expand All @@ -1413,6 +1418,67 @@ func TestAccELBV2LoadBalancer_NetworkLoadBalancer_updateSecurityGroups(t *testin
testAccCheckLoadBalancerExists(ctx, resourceName, &lb4),
testAccCheckLoadBalancerRecreated(&lb4, &lb3),
resource.TestCheckResourceAttr(resourceName, "security_groups.#", "0"),
resource.TestCheckResourceAttr(resourceName, "enforce_security_group_inbound_rules_on_private_link_traffic", ""),
),
},
},
})
}

func TestAccELBV2LoadBalancer_NetworkLoadBalancer_enforcePrivateLink(t *testing.T) {
ctx := acctest.Context(t)
var lb1 elbv2.LoadBalancer
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
resourceName := "aws_lb.test"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(ctx, t) },
ErrorCheck: acctest.ErrorCheck(t, elbv2.EndpointsID),
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
CheckDestroy: testAccCheckLoadBalancerDestroy(ctx),
Steps: []resource.TestStep{
{
Config: testAccLoadBalancerConfig_nlbSecurityGroupsEnforcePrivateLink(rName, 1, "off"),
Check: resource.ComposeAggregateTestCheckFunc(
testAccCheckLoadBalancerExists(ctx, resourceName, &lb1),
resource.TestCheckResourceAttr(resourceName, "security_groups.#", "1"),
resource.TestCheckResourceAttr(resourceName, "enforce_security_group_inbound_rules_on_private_link_traffic", "off")),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
{
Config: testAccLoadBalancerConfig_nlbSecurityGroups(rName, 1),
Check: resource.ComposeAggregateTestCheckFunc(
testAccCheckLoadBalancerExists(ctx, resourceName, &lb1),
resource.TestCheckResourceAttr(resourceName, "security_groups.#", "1"),
resource.TestCheckResourceAttr(resourceName, "enforce_security_group_inbound_rules_on_private_link_traffic", "off"),
),
},
{
Config: testAccLoadBalancerConfig_nlbSecurityGroupsEnforcePrivateLink(rName, 1, "on"),
Check: resource.ComposeAggregateTestCheckFunc(
testAccCheckLoadBalancerExists(ctx, resourceName, &lb1),
resource.TestCheckResourceAttr(resourceName, "security_groups.#", "1"),
resource.TestCheckResourceAttr(resourceName, "enforce_security_group_inbound_rules_on_private_link_traffic", "on"),
),
},
{
Config: testAccLoadBalancerConfig_nlbSecurityGroupsEnforcePrivateLink(rName, 1, "off"),
Check: resource.ComposeAggregateTestCheckFunc(
testAccCheckLoadBalancerExists(ctx, resourceName, &lb1),
resource.TestCheckResourceAttr(resourceName, "security_groups.#", "1"),
resource.TestCheckResourceAttr(resourceName, "enforce_security_group_inbound_rules_on_private_link_traffic", "off"),
),
},
{
Config: testAccLoadBalancerConfig_nlbSecurityGroups(rName, 1),
Check: resource.ComposeAggregateTestCheckFunc(
testAccCheckLoadBalancerExists(ctx, resourceName, &lb1),
resource.TestCheckResourceAttr(resourceName, "security_groups.#", "1"),
resource.TestCheckResourceAttr(resourceName, "enforce_security_group_inbound_rules_on_private_link_traffic", "off"),
),
},
},
Expand Down Expand Up @@ -2656,6 +2722,45 @@ resource "aws_lb" "test" {
`, rName, n))
}

func testAccLoadBalancerConfig_nlbSecurityGroupsEnforcePrivateLink(rName string, n int, enforcePrivateLink string) string {
return acctest.ConfigCompose(acctest.ConfigVPCWithSubnets(rName, 2), fmt.Sprintf(`
resource "aws_security_group" "test" {
count = 3

name = "%[1]s-${count.index}"
vpc_id = aws_vpc.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 = %[1]q
}
}

resource "aws_lb" "test" {
internal = true
load_balancer_type = "network"
name = %[1]q
subnets = aws_subnet.test[*].id
security_groups = slice(aws_security_group.test[*].id, 0, %[2]d)

enforce_security_group_inbound_rules_on_private_link_traffic = %[3]q
}
`, rName, n, enforcePrivateLink))
}

func testAccLoadBalancerConfig_nlbSubnets(rName string, subnetCount int) string {
return acctest.ConfigCompose(acctest.ConfigVPCWithSubnets(rName, subnetCount), fmt.Sprintf(`
resource "aws_lb" "test" {
Expand Down
1 change: 1 addition & 0 deletions website/docs/r/lb.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ This resource supports the following arguments:
* `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`
* `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`.
* `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`.
* `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`.
* `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.
* `internal` - (Optional) If true, the LB will be internal. Defaults to `false`.
* `ip_address_type` - (Optional) The type of IP addresses used by the subnets for your load balancer. The possible values are `ipv4` and `dualstack`.
Expand Down
Loading