Skip to content

Harden STS calls with VPC endpoints#275

Draft
starfolkai[bot] wants to merge 1 commit into
mainfrom
harden-sts-vpc-endpoints
Draft

Harden STS calls with VPC endpoints#275
starfolkai[bot] wants to merge 1 commit into
mainfrom
harden-sts-vpc-endpoints

Conversation

@starfolkai

@starfolkai starfolkai Bot commented Jun 26, 2026

Copy link
Copy Markdown

Summary

Adds configurable interface VPC endpoints (STS, EC2, CloudWatch Logs) and locks the quarantine function role down so that the function code is confined to the VPC and to CloudWatch Logs, while the Lambda service retains exactly the access it needs.

1. Configurable interface VPC endpoints (modules/vpc)

  • The shared vpc module creates interface endpoints for STS, EC2, and CloudWatch Logs, each gated by its own variable (enable_sts_vpc_endpoint, enable_ec2_vpc_endpoint, enable_logs_vpc_endpoint, default false) and defined as an individual count-gated aws_vpc_endpoint resource (Interface type, private_dns_enabled = true, all three private subnets).
  • Quarantine VPC: all three always created (wired true from the root).
  • Main VPC: all three disabled for now (wired false from the root).
  • The shared vpc_endpoints_tls security group is always created.
  • Module outputs sts_vpc_endpoint_id, ec2_vpc_endpoint_id, logs_vpc_endpoint_id (null when not created).

2. Quarantine function role lockdown (modules/services-common)

The quarantine_function_role (used by user-defined quarantine Lambdas) is governed by three policies that separate the two callers of the role — the Lambda service (lambda:SourceFunctionArn absent) and the function code (lambda:SourceFunctionArn present):

  • QuarantineFunctionExecution — a tightened, self-managed replacement for the AWS-managed AWSLambdaVPCAccessExecutionRole. The EC2 ENI actions (CreateNetworkInterface, DescribeNetworkInterfaces, DescribeSubnets, DeleteNetworkInterface, Assign/UnassignPrivateIpAddresses) are granted only to the Lambda service, via Null: { "lambda:SourceFunctionArn": "true" }. CloudWatch Logs is granted to both the service (log delivery) and the function code.
  • QuarantineFunctionVpcLockdown — denies any call whose aws:SourceVpc is not the quarantine VPC. The service's ENI/Logs actions carry no aws:SourceVpc, so they are excluded via NotAction (a blanket * deny would break VPC attachment and logging).
  • QuarantineFunctionCodeLogsOnly — denies the function's own code anything other than the three CloudWatch Logs actions, and additionally denies any function-code call that does not originate from inside the quarantine VPC.

Net effect: the function code can do nothing but write CloudWatch Logs from inside the quarantine VPC; the Lambda service retains exactly the ENI + log-delivery access it needs and nothing more.

Notes / caveats

  • Authorizing the Lambda service vs. the function code is done with lambda:SourceFunctionArn (present only for function-code calls). There is no positive "principal == Lambda service" key for the ENI calls, and aws:ViaAWSService is not a documented/reliable lever for Hyperplane ENI management, so it is intentionally not used.
  • Regional vs. global STS: private DNS only redirects sts.<region>.amazonaws.com; the legacy global sts.amazonaws.com would bypass the endpoint. Modern AWS SDKs default to regional STS.

Testing

  • terraform fmt, terraform validate, and tflint --recursive pass.
  • Example module (examples/braintrust-data-plane) validates against the local module.
  • No terraform plan/apply run (no AWS credentials).

🤖 Generated with Claude Code

Created by mike

Slack thread

@starfolkai starfolkai Bot force-pushed the harden-sts-vpc-endpoints branch 6 times, most recently from 2bc8494 to c84269b Compare June 27, 2026 00:18
Add configurable interface VPC endpoints (STS, EC2, CloudWatch Logs) to
the shared vpc module, each gated by its own variable and defined as an
individual count-based resource. The quarantine VPC always creates all
three so its traffic stays on the AWS network; the main VPC leaves them
disabled for now. The shared vpc_endpoints_tls security group is always
created.

Lock down the quarantine function role:
- Replace the AWS-managed AWSLambdaVPCAccessExecutionRole with a tightened
  self-managed execution policy: the EC2 ENI actions are authorized for the
  Lambda service only (lambda:SourceFunctionArn absent); CloudWatch Logs is
  granted to both the service and the function code.
- Deny any call that does not originate from inside the quarantine VPC
  (aws:SourceVpc), excluding the Lambda-service ENI/Logs actions (which carry
  no aws:SourceVpc) so VPC networking and logging keep working.
- Restrict the function's own code (lambda:SourceFunctionArn present) to the
  three CloudWatch Logs actions and require its calls originate from inside
  the quarantine VPC.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@starfolkai starfolkai Bot force-pushed the harden-sts-vpc-endpoints branch from c84269b to 99d67eb Compare June 27, 2026 03:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant