Skip to content

Commit 34226f8

Browse files
jeffmccollummdeeks
andauthored
Use individual SGs instead of Default SG (#77)
When deploying the Braintrust data plane, we will no longer use the default VPC security group, but instead create individual security groups for Brainstore, elasticache, rds, and lambdas. Existing deployments will have all resources deployed from Terraform switch from using the default security groups to the individual security groups. The quarantine lambdas that are created outside of Terraform will still have the default VPC Security group of the Quarantine VPC, however these can be changed to use the new Quarantine Security Group instead via the AWS Console or via script. --------- Co-authored-by: Jeff McCollum <[email protected]> Co-authored-by: Mike Deeks <[email protected]>
1 parent e515c3a commit 34226f8

26 files changed

+361
-95
lines changed

main.tf

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ locals {
1111
clickhouse_address = var.use_external_clickhouse_address != null ? var.use_external_clickhouse_address : (
1212
var.enable_clickhouse ? module.clickhouse[0].clickhouse_instance_private_ip : null
1313
)
14+
bastion_security_group = var.enable_braintrust_support_shell_access ? {
15+
"Remote Support Bastion" = module.remote_support[0].remote_support_security_group_id
16+
} : {}
1417
}
1518

1619
module "main_vpc" {
@@ -62,8 +65,14 @@ module "database" {
6265
module.main_vpc.private_subnet_2_id,
6366
module.main_vpc.private_subnet_3_id
6467
]
65-
database_security_group_ids = [module.main_vpc.default_security_group_id]
66-
68+
vpc_id = module.main_vpc.vpc_id
69+
authorized_security_groups = merge(
70+
{
71+
"Lambda Services" = module.services.lambda_security_group_id
72+
"Brainstore" = var.enable_brainstore ? module.brainstore[0].brainstore_instance_security_group_id : null
73+
},
74+
local.bastion_security_group,
75+
)
6776
postgres_storage_iops = var.postgres_storage_iops
6877
postgres_storage_throughput = var.postgres_storage_throughput
6978
auto_minor_version_upgrade = var.postgres_auto_minor_version_upgrade
@@ -80,7 +89,14 @@ module "redis" {
8089
module.main_vpc.private_subnet_2_id,
8190
module.main_vpc.private_subnet_3_id
8291
]
83-
security_group_ids = [module.main_vpc.default_security_group_id]
92+
vpc_id = module.main_vpc.vpc_id
93+
authorized_security_groups = merge(
94+
{
95+
"Lambda Services" = module.services.lambda_security_group_id
96+
"Brainstore" = var.enable_brainstore ? module.brainstore[0].brainstore_instance_security_group_id : null
97+
},
98+
local.bastion_security_group,
99+
)
84100
redis_instance_type = var.redis_instance_type
85101
redis_version = var.redis_version
86102
}
@@ -127,17 +143,16 @@ module "services" {
127143
extra_env_vars = var.service_extra_env_vars
128144

129145
# Networking
130-
service_security_group_ids = [module.main_vpc.default_security_group_id]
146+
vpc_id = module.main_vpc.vpc_id
131147
service_subnet_ids = [
132148
module.main_vpc.private_subnet_1_id,
133149
module.main_vpc.private_subnet_2_id,
134150
module.main_vpc.private_subnet_3_id
135151
]
136152

137153
# Quarantine VPC
138-
use_quarantine_vpc = var.enable_quarantine_vpc
139-
quarantine_vpc_id = var.enable_quarantine_vpc ? module.quarantine_vpc[0].vpc_id : null
140-
quarantine_vpc_default_security_group_id = var.enable_quarantine_vpc ? module.quarantine_vpc[0].default_security_group_id : null
154+
use_quarantine_vpc = var.enable_quarantine_vpc
155+
quarantine_vpc_id = var.enable_quarantine_vpc ? module.quarantine_vpc[0].vpc_id : null
141156
quarantine_vpc_private_subnets = var.enable_quarantine_vpc ? [
142157
module.quarantine_vpc[0].private_subnet_1_id,
143158
module.quarantine_vpc[0].private_subnet_2_id,
@@ -189,8 +204,15 @@ module "brainstore" {
189204
internal_observability_env_name = var.internal_observability_env_name
190205
internal_observability_region = var.internal_observability_region
191206

192-
vpc_id = module.main_vpc.vpc_id
193-
security_group_id = module.main_vpc.default_security_group_id
207+
vpc_id = module.main_vpc.vpc_id
208+
authorized_security_groups = merge(
209+
{
210+
"Lambda Services" = module.services.lambda_security_group_id
211+
},
212+
local.bastion_security_group
213+
)
214+
authorized_security_groups_ssh = local.bastion_security_group
215+
194216
private_subnet_ids = [
195217
module.main_vpc.private_subnet_1_id,
196218
module.main_vpc.private_subnet_2_id,

module-docs.md

Lines changed: 61 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
<!-- BEGIN_TF_DOCS -->
12
## Required Inputs
23

34
The following input variables are required:
@@ -44,22 +45,6 @@ Type: `number`
4445

4546
Default: `-1`
4647

47-
### <a name="input_brainstore_backfill_disable_historical"></a> [brainstore\_backfill\_disable\_historical](#input\_brainstore\_backfill\_disable\_historical)
48-
49-
Description: Disable historical backfill for Brainstore. Don't modify this unless instructed by Braintrust.
50-
51-
Type: `bool`
52-
53-
Default: `false`
54-
55-
### <a name="input_brainstore_backfill_disable_nonhistorical"></a> [brainstore\_backfill\_disable\_nonhistorical](#input\_brainstore\_backfill\_disable\_nonhistorical)
56-
57-
Description: Disable non-historical backfill for Brainstore. Don't modify this unless instructed by Braintrust.
58-
59-
Type: `bool`
60-
61-
Default: `false`
62-
6348
### <a name="input_brainstore_backfill_new_objects"></a> [brainstore\_backfill\_new\_objects](#input\_brainstore\_backfill\_new\_objects)
6449

6550
Description: Enable backfill for new objects for Brainstore. Don't modify this unless instructed by Braintrust.
@@ -74,11 +59,11 @@ Description: Whether to set Brainstore as the default rather than requiring user
7459

7560
Type: `string`
7661

77-
Default: `"true"`
62+
Default: `"force"`
7863

7964
### <a name="input_brainstore_disable_optimization_worker"></a> [brainstore\_disable\_optimization\_worker](#input\_brainstore\_disable\_optimization\_worker)
8065

81-
Description: Disable the optimization worker in Brainstore
66+
Description: Disable the optimization worker globally in Brainstore
8267

8368
Type: `bool`
8469

@@ -92,14 +77,6 @@ Type: `bool`
9277

9378
Default: `true`
9479

95-
### <a name="input_brainstore_enable_index_validation"></a> [brainstore\_enable\_index\_validation](#input\_brainstore\_enable\_index\_validation)
96-
97-
Description: Enable index validation for Brainstore
98-
99-
Type: `bool`
100-
101-
Default: `false`
102-
10380
### <a name="input_brainstore_etl_batch_size"></a> [brainstore\_etl\_batch\_size](#input\_brainstore\_etl\_batch\_size)
10481

10582
Description: The batch size for the ETL process
@@ -110,19 +87,19 @@ Default: `null`
11087

11188
### <a name="input_brainstore_extra_env_vars"></a> [brainstore\_extra\_env\_vars](#input\_brainstore\_extra\_env\_vars)
11289

113-
Description: Extra environment variables to set for Brainstore
90+
Description: Extra environment variables to set for Brainstore reader or dual use nodes
11491

11592
Type: `map(string)`
11693

11794
Default: `{}`
11895

119-
### <a name="input_brainstore_index_validation_only_deletes"></a> [brainstore\_index\_validation\_only\_deletes](#input\_brainstore\_index\_validation\_only\_deletes)
96+
### <a name="input_brainstore_extra_env_vars_writer"></a> [brainstore\_extra\_env\_vars\_writer](#input\_brainstore\_extra\_env\_vars\_writer)
12097

121-
Description: Scope index validation to only deletes in Brainstore. Only applies if brainstore\_enable\_index\_validation is true
98+
Description: Extra environment variables to set for Brainstore writer nodes
12299

123-
Type: `bool`
100+
Type: `map(string)`
124101

125-
Default: `true`
102+
Default: `{}`
126103

127104
### <a name="input_brainstore_instance_count"></a> [brainstore\_instance\_count](#input\_brainstore\_instance\_count)
128105

@@ -284,6 +261,30 @@ Type: `bool`
284261

285262
Default: `true`
286263

264+
### <a name="input_internal_observability_api_key"></a> [internal\_observability\_api\_key](#input\_internal\_observability\_api\_key)
265+
266+
Description: Support for internal observability agent. Do not set this unless instructed by support.
267+
268+
Type: `string`
269+
270+
Default: `""`
271+
272+
### <a name="input_internal_observability_env_name"></a> [internal\_observability\_env\_name](#input\_internal\_observability\_env\_name)
273+
274+
Description: Support for internal observability agent. Do not set this unless instructed by support.
275+
276+
Type: `string`
277+
278+
Default: `""`
279+
280+
### <a name="input_internal_observability_region"></a> [internal\_observability\_region](#input\_internal\_observability\_region)
281+
282+
Description: Support for internal observability agent. Do not set this unless instructed by support.
283+
284+
Type: `string`
285+
286+
Default: `"us5"`
287+
287288
### <a name="input_kms_key_arn"></a> [kms\_key\_arn](#input\_kms\_key\_arn)
288289

289290
Description: Existing KMS key ARN to use for encrypting resources. If not provided, a new key will be created. DO NOT change this after deployment. If you do, it will attempt to destroy your DB and prior S3 objects will no longer be readable.
@@ -476,6 +477,14 @@ Type: `string`
476477

477478
Default: `"7.0"`
478479

480+
### <a name="input_s3_additional_allowed_origins"></a> [s3\_additional\_allowed\_origins](#input\_s3\_additional\_allowed\_origins)
481+
482+
Description: Additional origins to allow for S3 bucket CORS configuration. Supports a wildcard in the domain name.
483+
484+
Type: `list(string)`
485+
486+
Default: `[]`
487+
479488
### <a name="input_service_additional_policy_arns"></a> [service\_additional\_policy\_arns](#input\_service\_additional\_policy\_arns)
480489

481490
Description: Additional policy ARNs to attach to the lambda functions that are the main braintrust service
@@ -548,6 +557,10 @@ Description: The primary endpoint for the dataplane API. This is the value that
548557

549558
Description: Instance ID of the bastion host that Braintrust support staff can connect to using EC2 Instance Connect. Share this with the Braintrust team.
550559

560+
### <a name="output_brainstore_security_group_id"></a> [brainstore\_security\_group\_id](#output\_brainstore\_security\_group\_id)
561+
562+
Description: ID of the security group for the Brainstore instances
563+
551564
### <a name="output_braintrust_support_role_arn"></a> [braintrust\_support\_role\_arn](#output\_braintrust\_support\_role\_arn)
552565

553566
Description: ARN of the Role that grants Braintrust team remote support. Share this with the Braintrust team.
@@ -564,13 +577,13 @@ Description: Name of the Clickhouse S3 bucket
564577

565578
Description: ID of the Clickhouse secret. Note this is the Terraform ID attribute which is a pipe delimited combination of secret ID and version ID
566579

567-
### <a name="output_main_vpc_cidr"></a> [main\_vpc\_cidr](#output\_main\_vpc\_cidr)
580+
### <a name="output_lambda_security_group_id"></a> [lambda\_security\_group\_id](#output\_lambda\_security\_group\_id)
568581

569-
Description: CIDR block of the main VPC
582+
Description: ID of the security group for the Lambda functions
570583

571-
### <a name="output_main_vpc_default_security_group_id"></a> [main\_vpc\_default\_security\_group\_id](#output\_main\_vpc\_default\_security\_group\_id)
584+
### <a name="output_main_vpc_cidr"></a> [main\_vpc\_cidr](#output\_main\_vpc\_cidr)
572585

573-
Description: ID of the default security group in the main VPC
586+
Description: CIDR block of the main VPC
574587

575588
### <a name="output_main_vpc_id"></a> [main\_vpc\_id](#output\_main\_vpc\_id)
576589

@@ -608,6 +621,19 @@ Description: ARN of the main Braintrust Postgres database
608621

609622
Description: ID of the quarantine VPC that user functions run inside of.
610623

624+
### <a name="output_rds_security_group_id"></a> [rds\_security\_group\_id](#output\_rds\_security\_group\_id)
625+
626+
Description: ID of the security group for the RDS instance
627+
611628
### <a name="output_redis_arn"></a> [redis\_arn](#output\_redis\_arn)
612629

613630
Description: ARN of the Redis instance
631+
632+
### <a name="output_redis_security_group_id"></a> [redis\_security\_group\_id](#output\_redis\_security\_group\_id)
633+
634+
Description: ID of the security group for the Elasticache instance
635+
636+
### <a name="output_remote_support_security_group_id"></a> [remote\_support\_security\_group\_id](#output\_remote\_support\_security\_group\_id)
637+
638+
Description: Security Group ID for the Remote Support bastion host.
639+
<!-- END_TF_DOCS -->

modules/brainstore/main-writer.tf

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ resource "aws_launch_template" "brainstore_writer" {
1111
arn = aws_iam_instance_profile.brainstore.arn
1212
}
1313

14-
vpc_security_group_ids = [var.security_group_id]
14+
vpc_security_group_ids = [aws_security_group.brainstore_instance.id]
1515

1616
block_device_mappings {
1717
device_name = "/dev/sda1"
@@ -92,7 +92,7 @@ resource "aws_lb" "brainstore_writer" {
9292
internal = true
9393
load_balancer_type = "network"
9494
subnets = var.private_subnet_ids
95-
security_groups = [var.security_group_id]
95+
security_groups = [aws_security_group.brainstore_elb.id]
9696

9797
lifecycle {
9898
create_before_destroy = true

modules/brainstore/main.tf

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ resource "aws_launch_template" "brainstore" {
1818
arn = aws_iam_instance_profile.brainstore.arn
1919
}
2020

21-
vpc_security_group_ids = [var.security_group_id]
21+
vpc_security_group_ids = [aws_security_group.brainstore_instance.id]
2222

2323
block_device_mappings {
2424
device_name = "/dev/sda1"
@@ -99,7 +99,7 @@ resource "aws_lb" "brainstore" {
9999
internal = true
100100
load_balancer_type = "network"
101101
subnets = var.private_subnet_ids
102-
security_groups = [var.security_group_id]
102+
security_groups = [aws_security_group.brainstore_elb.id]
103103

104104
lifecycle {
105105
# Changing security groups requires a new NLB.

modules/brainstore/outputs.tf

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,13 @@ output "port" {
1717
description = "The port used by Brainstore"
1818
value = var.port
1919
}
20+
21+
output "brainstore_elb_security_group_id" {
22+
description = "The ID of the security group for the Brainstore ELB"
23+
value = aws_security_group.brainstore_elb.id
24+
}
25+
26+
output "brainstore_instance_security_group_id" {
27+
description = "The ID of the security group for the Brainstore instances"
28+
value = aws_security_group.brainstore_instance.id
29+
}

modules/brainstore/security-groups.tf

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
resource "aws_security_group" "brainstore_elb" {
2+
name = "${var.deployment_name}-brainstore-elb"
3+
vpc_id = var.vpc_id
4+
tags = merge({ "Name" = "${var.deployment_name}-brainstore-elb" }, local.common_tags)
5+
}
6+
7+
resource "aws_vpc_security_group_ingress_rule" "brainstore_elb_allow_ingress_from_authorized_security_groups" {
8+
for_each = var.authorized_security_groups
9+
10+
from_port = var.port
11+
to_port = var.port
12+
ip_protocol = "tcp"
13+
referenced_security_group_id = each.value
14+
description = "Allow inbound to brainstore from ${each.key}."
15+
security_group_id = aws_security_group.brainstore_elb.id
16+
}
17+
18+
resource "aws_vpc_security_group_egress_rule" "brainstore_elb_allow_egress_all" {
19+
from_port = -1
20+
to_port = -1
21+
ip_protocol = "-1"
22+
cidr_ipv4 = "0.0.0.0/0"
23+
description = "Allow all outbound traffic from Brainstore ELB."
24+
security_group_id = aws_security_group.brainstore_elb.id
25+
}
26+
27+
resource "aws_security_group" "brainstore_instance" {
28+
name = "${var.deployment_name}-brainstore-instance"
29+
vpc_id = var.vpc_id
30+
tags = merge({ "Name" = "${var.deployment_name}-brainstore-instance" }, local.common_tags)
31+
}
32+
33+
resource "aws_vpc_security_group_ingress_rule" "brainstore_instance_allow_ingress_from_nlb" {
34+
35+
from_port = var.port
36+
to_port = var.port
37+
ip_protocol = "tcp"
38+
referenced_security_group_id = aws_security_group.brainstore_elb.id
39+
description = "Allow inbound to Brainstore instances from NLB."
40+
security_group_id = aws_security_group.brainstore_instance.id
41+
}
42+
43+
resource "aws_vpc_security_group_ingress_rule" "brainstore_instance_allow_ingress_from_authorized_security_groups_ssh" {
44+
for_each = var.authorized_security_groups_ssh
45+
46+
from_port = 22
47+
to_port = 22
48+
ip_protocol = "tcp"
49+
referenced_security_group_id = each.value
50+
description = "Allow inbound SSH to Brainstore instances from ${each.key}."
51+
52+
security_group_id = aws_security_group.brainstore_instance.id
53+
}
54+
55+
resource "aws_vpc_security_group_egress_rule" "brainstore_instance_allow_egress_all" {
56+
57+
from_port = -1
58+
to_port = -1
59+
ip_protocol = "-1"
60+
cidr_ipv4 = "0.0.0.0/0"
61+
description = "Allow all outbound traffic from Brainstore instances."
62+
security_group_id = aws_security_group.brainstore_instance.id
63+
}

modules/brainstore/variables.tf

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,16 @@ variable "vpc_id" {
5252
description = "The ID of the VPC where Brainstore resources will be created"
5353
}
5454

55-
variable "security_group_id" {
56-
type = string
57-
description = "The ID of the security group to use for Brainstore resources"
55+
variable "authorized_security_groups" {
56+
type = map(string)
57+
description = "Map of security group names to their IDs that are authorized to access the Brainstore ELB. Format: { name = <security_group_id> }"
58+
default = {}
59+
}
60+
61+
variable "authorized_security_groups_ssh" {
62+
type = map(string)
63+
description = "Map of security group names to their IDs that are authorized to access Brainstore instances via SSH. Format: { name = <security_group_id> }"
64+
default = {}
5865
}
5966

6067
variable "private_subnet_ids" {

0 commit comments

Comments
 (0)