Skip to content

Commit b1e97e9

Browse files
authored
feat(loadbalancer): add security_group_id and disable_security_group_assignment field (#986)
1 parent 65c6106 commit b1e97e9

File tree

9 files changed

+350
-62
lines changed

9 files changed

+350
-62
lines changed

docs/data-sources/loadbalancer.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,15 @@ data "stackit_loadbalancer" "example" {
3333

3434
### Read-Only
3535

36+
- `disable_security_group_assignment` (Boolean) If set to true, this will disable the automatic assignment of a security group to the load balancer's targets. This option is primarily used to allow targets that are not within the load balancer's own network or SNA (STACKIT Network area). When this is enabled, you are fully responsible for ensuring network connectivity to the targets, including managing all routing and security group rules manually. This setting cannot be changed after the load balancer is created.
3637
- `external_address` (String) External Load Balancer IP address where this Load Balancer is exposed.
3738
- `id` (String) Terraform's internal resource ID. It is structured as "`project_id`","region","`name`".
3839
- `listeners` (Attributes List) List of all listeners which will accept traffic. Limited to 20. (see [below for nested schema](#nestedatt--listeners))
3940
- `networks` (Attributes List) List of networks that listeners and targets reside in. (see [below for nested schema](#nestedatt--networks))
4041
- `options` (Attributes) Defines any optional functionality you want to have enabled on your load balancer. (see [below for nested schema](#nestedatt--options))
4142
- `plan_id` (String) The service plan ID. If not defined, the default service plan is `p10`. Possible values are: `p10`, `p50`, `p250`, `p750`.
4243
- `private_address` (String) Transient private Load Balancer IP address. It can change any time.
44+
- `security_group_id` (String) The ID of the egress security group assigned to the Load Balancer's internal machines. This ID is essential for allowing traffic from the Load Balancer to targets in different networks or STACKIT Network areas (SNA). To enable this, create a security group rule for your target VMs and set the `remote_security_group_id` of that rule to this value. This is typically used when `disable_security_group_assignment` is set to `true`.
4345
- `target_pools` (Attributes List) List of all target pools which will be used in the Load Balancer. Limited to 20. (see [below for nested schema](#nestedatt--target_pools))
4446

4547
<a id="nestedatt--listeners"></a>

docs/resources/loadbalancer.md

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,109 @@ resource "stackit_loadbalancer" "example" {
110110
}
111111
}
112112
113+
# This example demonstrates an advanced setup where the Load Balancer is in one
114+
# network and the target server is in another. This requires manual
115+
# security group configuration using the `disable_security_group_assignment`
116+
# and `security_group_id` attributes.
117+
118+
# We create two separate networks: one for the load balancer and one for the target.
119+
resource "stackit_network" "lb_network" {
120+
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
121+
name = "lb-network-example"
122+
ipv4_prefix = "192.168.1.0/24"
123+
ipv4_nameservers = ["8.8.8.8"]
124+
}
125+
126+
resource "stackit_network" "target_network" {
127+
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
128+
name = "target-network-example"
129+
ipv4_prefix = "192.168.2.0/24"
130+
ipv4_nameservers = ["8.8.8.8"]
131+
}
132+
133+
resource "stackit_public_ip" "example" {
134+
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
135+
}
136+
137+
resource "stackit_loadbalancer" "example" {
138+
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
139+
name = "example-advanced-lb"
140+
external_address = stackit_public_ip.example.ip
141+
142+
# Key setting for manual mode: disables automatic security group handling.
143+
disable_security_group_assignment = true
144+
145+
networks = [{
146+
network_id = stackit_network.lb_network.network_id
147+
role = "ROLE_LISTENERS_AND_TARGETS"
148+
}]
149+
150+
listeners = [{
151+
port = 80
152+
protocol = "PROTOCOL_TCP"
153+
target_pool = "cross-network-pool"
154+
}]
155+
156+
target_pools = [{
157+
name = "cross-network-pool"
158+
target_port = 80
159+
targets = [{
160+
display_name = stackit_server.example.name
161+
ip = stackit_network_interface.nic.ipv4
162+
}]
163+
}]
164+
}
165+
166+
# Create a new security group to be assigned to the target server.
167+
resource "stackit_security_group" "target_sg" {
168+
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
169+
name = "target-sg-for-lb-access"
170+
description = "Allows ingress traffic from the example load balancer."
171+
}
172+
173+
# Create a rule to allow traffic FROM the load balancer.
174+
# This rule uses the computed `security_group_id` of the load balancer.
175+
resource "stackit_security_group_rule" "allow_lb_ingress" {
176+
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
177+
security_group_id = stackit_security_group.target_sg.security_group_id
178+
direction = "ingress"
179+
protocol = {
180+
name = "tcp"
181+
}
182+
183+
# This is the crucial link: it allows traffic from the LB's security group.
184+
remote_security_group_id = stackit_loadbalancer.example.security_group_id
185+
186+
port_range = {
187+
min = 80
188+
max = 80
189+
}
190+
}
191+
192+
resource "stackit_server" "example" {
193+
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
194+
name = "example-remote-target"
195+
machine_type = "g2i.2"
196+
availability_zone = "eu01-1"
197+
198+
boot_volume = {
199+
source_type = "image"
200+
source_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
201+
size = 10
202+
}
203+
204+
network_interfaces = [
205+
stackit_network_interface.nic.network_interface_id
206+
]
207+
}
208+
209+
resource "stackit_network_interface" "nic" {
210+
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
211+
network_id = stackit_network.target_network.network_id
212+
security_group_ids = [stackit_security_group.target_sg.security_group_id]
213+
}
214+
# End of advanced example
215+
113216
# Only use the import statement, if you want to import an existing loadbalancer
114217
import {
115218
to = stackit_loadbalancer.import-example
@@ -130,6 +233,7 @@ import {
130233

131234
### Optional
132235

236+
- `disable_security_group_assignment` (Boolean) If set to true, this will disable the automatic assignment of a security group to the load balancer's targets. This option is primarily used to allow targets that are not within the load balancer's own network or SNA (STACKIT network area). When this is enabled, you are fully responsible for ensuring network connectivity to the targets, including managing all routing and security group rules manually. This setting cannot be changed after the load balancer is created.
133237
- `external_address` (String) External Load Balancer IP address where this Load Balancer is exposed.
134238
- `options` (Attributes) Defines any optional functionality you want to have enabled on your load balancer. (see [below for nested schema](#nestedatt--options))
135239
- `plan_id` (String) The service plan ID. If not defined, the default service plan is `p10`. Possible values are: `p10`, `p50`, `p250`, `p750`.
@@ -139,6 +243,7 @@ import {
139243

140244
- `id` (String) Terraform's internal resource ID. It is structured as "`project_id`","region","`name`".
141245
- `private_address` (String) Transient private Load Balancer IP address. It can change any time.
246+
- `security_group_id` (String) The ID of the egress security group assigned to the Load Balancer's internal machines. This ID is essential for allowing traffic from the Load Balancer to targets in different networks or STACKIT network areas (SNA). To enable this, create a security group rule for your target VMs and set the `remote_security_group_id` of that rule to this value. This is typically used when `disable_security_group_assignment` is set to `true`.
142247

143248
<a id="nestedatt--listeners"></a>
144249
### Nested Schema for `listeners`

examples/resources/stackit_loadbalancer/resource.tf

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,109 @@ resource "stackit_loadbalancer" "example" {
9191
}
9292
}
9393

94+
# This example demonstrates an advanced setup where the Load Balancer is in one
95+
# network and the target server is in another. This requires manual
96+
# security group configuration using the `disable_security_group_assignment`
97+
# and `security_group_id` attributes.
98+
99+
# We create two separate networks: one for the load balancer and one for the target.
100+
resource "stackit_network" "lb_network" {
101+
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
102+
name = "lb-network-example"
103+
ipv4_prefix = "192.168.1.0/24"
104+
ipv4_nameservers = ["8.8.8.8"]
105+
}
106+
107+
resource "stackit_network" "target_network" {
108+
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
109+
name = "target-network-example"
110+
ipv4_prefix = "192.168.2.0/24"
111+
ipv4_nameservers = ["8.8.8.8"]
112+
}
113+
114+
resource "stackit_public_ip" "example" {
115+
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
116+
}
117+
118+
resource "stackit_loadbalancer" "example" {
119+
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
120+
name = "example-advanced-lb"
121+
external_address = stackit_public_ip.example.ip
122+
123+
# Key setting for manual mode: disables automatic security group handling.
124+
disable_security_group_assignment = true
125+
126+
networks = [{
127+
network_id = stackit_network.lb_network.network_id
128+
role = "ROLE_LISTENERS_AND_TARGETS"
129+
}]
130+
131+
listeners = [{
132+
port = 80
133+
protocol = "PROTOCOL_TCP"
134+
target_pool = "cross-network-pool"
135+
}]
136+
137+
target_pools = [{
138+
name = "cross-network-pool"
139+
target_port = 80
140+
targets = [{
141+
display_name = stackit_server.example.name
142+
ip = stackit_network_interface.nic.ipv4
143+
}]
144+
}]
145+
}
146+
147+
# Create a new security group to be assigned to the target server.
148+
resource "stackit_security_group" "target_sg" {
149+
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
150+
name = "target-sg-for-lb-access"
151+
description = "Allows ingress traffic from the example load balancer."
152+
}
153+
154+
# Create a rule to allow traffic FROM the load balancer.
155+
# This rule uses the computed `security_group_id` of the load balancer.
156+
resource "stackit_security_group_rule" "allow_lb_ingress" {
157+
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
158+
security_group_id = stackit_security_group.target_sg.security_group_id
159+
direction = "ingress"
160+
protocol = {
161+
name = "tcp"
162+
}
163+
164+
# This is the crucial link: it allows traffic from the LB's security group.
165+
remote_security_group_id = stackit_loadbalancer.example.security_group_id
166+
167+
port_range = {
168+
min = 80
169+
max = 80
170+
}
171+
}
172+
173+
resource "stackit_server" "example" {
174+
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
175+
name = "example-remote-target"
176+
machine_type = "g2i.2"
177+
availability_zone = "eu01-1"
178+
179+
boot_volume = {
180+
source_type = "image"
181+
source_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
182+
size = 10
183+
}
184+
185+
network_interfaces = [
186+
stackit_network_interface.nic.network_interface_id
187+
]
188+
}
189+
190+
resource "stackit_network_interface" "nic" {
191+
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
192+
network_id = stackit_network.target_network.network_id
193+
security_group_ids = [stackit_security_group.target_sg.security_group_id]
194+
}
195+
# End of advanced example
196+
94197
# Only use the import statement, if you want to import an existing loadbalancer
95198
import {
96199
to = stackit_loadbalancer.import-example

stackit/internal/services/loadbalancer/loadbalancer/datasource.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ func (r *loadBalancerDataSource) Schema(_ context.Context, _ datasource.SchemaRe
6969
"id": "Terraform's internal resource ID. It is structured as \"`project_id`\",\"region\",\"`name`\".",
7070
"project_id": "STACKIT project ID to which the Load Balancer is associated.",
7171
"external_address": "External Load Balancer IP address where this Load Balancer is exposed.",
72+
"disable_security_group_assignment": "If set to true, this will disable the automatic assignment of a security group to the load balancer's targets. This option is primarily used to allow targets that are not within the load balancer's own network or SNA (STACKIT Network area). When this is enabled, you are fully responsible for ensuring network connectivity to the targets, including managing all routing and security group rules manually. This setting cannot be changed after the load balancer is created.",
73+
"security_group_id": "The ID of the egress security group assigned to the Load Balancer's internal machines. This ID is essential for allowing traffic from the Load Balancer to targets in different networks or STACKIT Network areas (SNA). To enable this, create a security group rule for your target VMs and set the `remote_security_group_id` of that rule to this value. This is typically used when `disable_security_group_assignment` is set to `true`.",
7274
"listeners": "List of all listeners which will accept traffic. Limited to 20.",
7375
"port": "Port number where we listen for traffic.",
7476
"protocol": "Protocol is the highest network protocol we understand to load balance.",
@@ -125,6 +127,10 @@ func (r *loadBalancerDataSource) Schema(_ context.Context, _ datasource.SchemaRe
125127
Description: descriptions["external_address"],
126128
Computed: true,
127129
},
130+
"disable_security_group_assignment": schema.BoolAttribute{
131+
Description: descriptions["disable_security_group_assignment"],
132+
Computed: true,
133+
},
128134
"plan_id": schema.StringAttribute{
129135
Description: descriptions["plan_id"],
130136
Computed: true,
@@ -339,6 +345,10 @@ func (r *loadBalancerDataSource) Schema(_ context.Context, _ datasource.SchemaRe
339345
Optional: true,
340346
Description: descriptions["region"],
341347
},
348+
"security_group_id": schema.StringAttribute{
349+
Description: descriptions["security_group_id"],
350+
Computed: true,
351+
},
342352
},
343353
}
344354
}

0 commit comments

Comments
 (0)