Skip to content

Commit e27a78d

Browse files
aknyshclaude
andauthored
feat: expose egress_enabled to tighten security group egress (#98)
* Add `egress_enabled` variable * chore: bump stack-config/yaml remote-state to 2.0.0 The aws-account-map repo (cloned by CI for the iam-roles relative-path module) was recently updated to stack-config/yaml v2, which requires cloudposse/utils >= 2.0.0. This component still pinned stack-config 1.8.0, which requires utils < 2.0.0, making the provider graph unsatisfiable. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * Add `egress_enabled` variable * test(fixtures): switch vendored deps to standalone repos with stack-config v2 The vendored account-map came from cloudposse/terraform-aws-components 1.520.0, which uses cloudposse/stack-config/yaml v1.5.0 (constraint utils >= 1.7.1, != 1.4.0, < 2.0.0). After bumping the component's own remote-state to stack-config v2 (utils >= 2.0.0), this old account-map made the resolved utils graph unsatisfiable during atmos deploys. Switch to the standalone aws-account-map@v1.537.2 (uses stack-config v2) and bring vpc + dns-delegated up to the versions used by elasticache-redis. Drop dns-primary; the test suite only depends on vpc and dns-delegated. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * test(fixtures): bump TestServerless engine to Aurora Postgres 17.9 AWS no longer offers Aurora Postgres 13.21 (the version the fixture was pinned to), so cluster creation fails with InvalidParameterCombination. Bump to 17.9, the current latest Aurora Postgres release, and update cluster_family to aurora-postgresql17 to match. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 4cdb023 commit e27a78d

10 files changed

Lines changed: 333 additions & 338 deletions

File tree

README.md

Lines changed: 12 additions & 11 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/README.md

Lines changed: 12 additions & 11 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/cluster-regional.tf

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
# https://www.terraform.io/docs/providers/aws/r/rds_cluster.html
66
module "aurora_postgres_cluster" {
77
source = "cloudposse/rds-cluster/aws"
8-
version = "2.4.0"
8+
version = "2.6.0"
99

1010
cluster_type = "regional"
1111
engine = var.engine
@@ -29,6 +29,7 @@ module "aurora_postgres_cluster" {
2929
reader_dns_name = local.reader_dns_name
3030
security_groups = local.allowed_security_groups
3131
intra_security_group_traffic_enabled = var.intra_security_group_traffic_enabled
32+
egress_enabled = var.egress_enabled
3233
allowed_cidr_blocks = local.allowed_cidr_blocks
3334
iam_database_authentication_enabled = var.iam_database_authentication_enabled
3435
storage_encrypted = var.storage_encrypted

src/remote-state.tf

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
module "vpc" {
22
source = "cloudposse/stack-config/yaml//modules/remote-state"
3-
version = "1.8.0"
3+
version = "2.0.0"
44

55
component = var.vpc_component_name
66

@@ -9,7 +9,7 @@ module "vpc" {
99

1010
module "vpc_ingress" {
1111
source = "cloudposse/stack-config/yaml//modules/remote-state"
12-
version = "1.8.0"
12+
version = "2.0.0"
1313

1414
for_each = {
1515
for i, account in var.allow_ingress_from_vpc_accounts :
@@ -27,18 +27,17 @@ module "vpc_ingress" {
2727

2828
module "eks" {
2929
source = "cloudposse/stack-config/yaml//modules/remote-state"
30-
version = "1.8.0"
30+
version = "2.0.0"
3131

3232
for_each = local.eks_security_group_enabled ? var.eks_component_names : toset([])
3333
component = each.value
3434

3535
context = module.cluster.context
3636
}
3737

38-
3938
module "dns_gbl_delegated" {
4039
source = "cloudposse/stack-config/yaml//modules/remote-state"
41-
version = "1.8.0"
40+
version = "2.0.0"
4241

4342
component = "dns-delegated"
4443
environment = var.dns_gbl_delegated_environment_name

src/variables.tf

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,16 @@ variable "intra_security_group_traffic_enabled" {
388388
description = "Whether to allow traffic between resources inside the database's security group."
389389
}
390390

391+
variable "egress_enabled" {
392+
type = bool
393+
default = true
394+
description = <<-EOT
395+
If `true`, the created security group will allow egress on all ports and protocols to all IP addresses.
396+
If `false`, no egress rules will be created by this module; egress must be configured via other means
397+
(e.g. additional security group rules) or all outbound traffic will be denied.
398+
EOT
399+
}
400+
391401
variable "cluster_parameters" {
392402
type = list(object({
393403
apply_method = string

test/component_test.go

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,18 @@
11
package test
22

33
import (
4+
"context"
45
"fmt"
56
"strings"
67
"testing"
78

9+
"github.com/aws/aws-sdk-go-v2/service/ec2"
810
"github.com/cloudposse/test-helpers/pkg/atmos"
911
helper "github.com/cloudposse/test-helpers/pkg/atmos/component-helper"
1012
"github.com/gruntwork-io/terratest/modules/aws"
11-
"github.com/stretchr/testify/assert"
1213
"github.com/gruntwork-io/terratest/modules/random"
14+
"github.com/stretchr/testify/assert"
15+
"github.com/stretchr/testify/require"
1316
)
1417

1518
type ComponentSuite struct {
@@ -31,7 +34,8 @@ func (s *ComponentSuite) TestBasic() {
3134
"database_port": 5432,
3235
"publicly_accessible": true,
3336
"allowed_cidr_blocks": []string{"0.0.0.0/0"},
34-
"cluster_name": clusterName,
37+
"cluster_name": clusterName,
38+
"egress_enabled": false,
3539
}
3640
componentInstance, _ := s.DeployAtmosComponent(s.T(), component, stack, &inputs)
3741
assert.NotNil(s.T(), componentInstance)
@@ -63,6 +67,17 @@ func (s *ComponentSuite) TestBasic() {
6367
allowedSecurityGroups := atmos.OutputList(s.T(), componentInstance, "allowed_security_groups")
6468
assert.Equal(s.T(), 0, len(allowedSecurityGroups))
6569

70+
securityGroupID := atmos.Output(s.T(), componentInstance, "security_group_id")
71+
assert.NotEmpty(s.T(), securityGroupID)
72+
73+
ec2Client := aws.NewEc2Client(s.T(), awsRegion)
74+
sgOut, err := ec2Client.DescribeSecurityGroups(context.Background(), &ec2.DescribeSecurityGroupsInput{
75+
GroupIds: []string{securityGroupID},
76+
})
77+
require.NoError(s.T(), err)
78+
require.Len(s.T(), sgOut.SecurityGroups, 1)
79+
assert.Empty(s.T(), sgOut.SecurityGroups[0].IpPermissionsEgress, "egress rules should be empty when egress_enabled=false")
80+
6681
clusterIdentifier := atmos.Output(s.T(), componentInstance, "cluster_identifier")
6782

6883
configMap := map[string]interface{}{}
@@ -115,7 +130,7 @@ func (s *ComponentSuite) TestServerless() {
115130
"database_port": 5432,
116131
"publicly_accessible": true,
117132
"allowed_cidr_blocks": []string{"0.0.0.0/0"},
118-
"cluster_name": clusterName,
133+
"cluster_name": clusterName,
119134
}
120135
componentInstance, _ := s.DeployAtmosComponent(s.T(), component, stack, &inputs)
121136
assert.NotNil(s.T(), componentInstance)

test/fixtures/stacks/catalog/usecase/serverless.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ components:
2020
# Serverless v2 configuration
2121
engine_mode: provisioned
2222
instance_type: "db.serverless" # serverless engine_mode ignores `var.instance_type`
23-
engine_version: "13.21" # Latest supported version as of 08/28/2023
24-
cluster_family: aurora-postgresql13
23+
engine_version: "17.9"
24+
cluster_family: aurora-postgresql17
2525
cluster_size: 1
2626
# serverless
2727
serverlessv2_scaling_configuration:

0 commit comments

Comments
 (0)