Skip to content

Add Lambda VPC proxy for MBE-to-OpenEMS B2B access#74

Closed
amalbet wants to merge 5 commits into
mainfrom
worktree-agent-a5df6547
Closed

Add Lambda VPC proxy for MBE-to-OpenEMS B2B access#74
amalbet wants to merge 5 commits into
mainfrom
worktree-agent-a5df6547

Conversation

@amalbet

@amalbet amalbet commented Apr 21, 2026

Copy link
Copy Markdown

Summary

Adds a Lambda VPC proxy to iac/dev/ that allows MBE (on Vercel) to securely access the OpenEMS B2B REST API without exposing the backend to the public internet. This is Option 3 from the architecture discussion in PR #70.

  • Lambda sits inside the VPC, forwards JSON-RPC requests to the backend via private IP
  • Function URL with IAM auth (SigV4) — stronger than API keys, logged in CloudTrail
  • Stateless passthrough (~15 lines) — no business logic, no dependencies, deploy once
  • Cost: ~$0/mo (Lambda free tier covers MBE's ~100-500 req/month)

Closes #73

Changes

New files:

  • iac/dev/lambda/index.mjs — Node.js 20 proxy function (handles errors, base64 encoding)
  • iac/dev/lambda.tf — Lambda function, IAM roles, security group, Function URL, CloudWatch log group, Vercel invoker IAM user + access key

Modified files:

  • iac/dev/security.tf — Added EC2 SG ingress rule from Lambda SG on port 8082 (SG-to-SG)
  • iac/dev/outputs.tf — Renamed b2b_urlb2b_url_direct, added b2b_url_lambda, IAM key outputs
  • iac/dev/variables.tf — Added openems_b2b_creds (sensitive)
  • iac/dev/terraform.tfvars.example — Documented new variable
  • iac/dev/.gitignore — Added lambda/proxy.zip

Prerequisites

Before terraform apply:

  • Aidan needs to add AWSLambda_FullAccess (or scoped lambda:*) to the claude-code-dev IAM user
  • openems_b2b_creds must be set in terraform.tfvars (base64-encoded user:password)

Test plan

  • terraform plan shows Lambda + IAM + SG resources to create (no changes to existing EC2/VPC)
  • terraform apply succeeds
  • Lambda appears in AWS Console, attached to the dev VPC
  • Manual test with awscurl: POST to the Function URL with SigV4 → valid JSON-RPC response from backend
  • CloudWatch logs show the invocation
  • EC2 SG shows inbound rule from Lambda SG on port 8082
  • terraform destroy cleans up all Lambda resources + log group

🤖 Generated with Claude Code

amalbet and others added 5 commits April 16, 2026 15:39
Provisions an isolated dev environment on AWS: VPC 10.100.0.0/16 with a
public subnet, t3.large Ubuntu 22.04 instance running the full
docker-compose stack via setup.sh, security group scoped to an
allowed_ips variable (no 0.0.0.0/0 exposure), and an IAM role for SSM
Session Manager access (no SSH key required).

State is stored in the existing openems-deployment-tf-state-file S3
bucket under a separate key (iac/dev/terraform.tfstate) so it does not
collide with the production ECS deployment in iac/.

User-data clones the local-deployment branch and runs setup.sh --edges 2
on first boot. Bootstrap takes ~10 min on a fresh instance.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Signed-off-by: Alejandro Malbet <amalbet@gmail.com>
Signed-off-by: Aidan Barnes <66229298+aidan-barnes-axm@users.noreply.github.com>
- backend.tf: point to Aidan's state bucket
  (docker-openems-feature-dev-iac) and lock table
  (docker-openems-feature-dev-iac-state-lock) in the dev account
- provider.tf: change Environment tag from "dev" to "aidev" to match
  the IAM policies Aidan configured for the dev account

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Signed-off-by: Alejandro Malbet <amalbet@gmail.com>
Implements ticket #73. Adds a Node.js 20 Lambda function inside the dev VPC
that proxies JSON-RPC requests from Vercel (MBE) to the OpenEMS Backend on
its private IP via port 8082. Auth is IAM SigV4 via Function URL.

- iac/dev/lambda/index.mjs: passthrough proxy with error handling, native
  fetch (no npm deps), handles isBase64Encoded, returns 502 on unreachable
- iac/dev/lambda.tf: all Lambda resources — archive_file, IAM role +
  AWSLambdaVPCAccessExecutionRole, Lambda SG (egress 8082 to EC2 SG),
  aws_lambda_function (128MB/30s/VPC), Function URL (AWS_IAM/BUFFERED),
  CloudWatch log group (14-day retention), MBE invoker IAM user + access key
  + user policy (lambda:InvokeFunctionUrl on this Lambda ARN only)
- iac/dev/security.tf: aws_security_group_rule ingress 8082 from Lambda SG
  to EC2 SG (SG-to-SG reference, no CIDR)
- iac/dev/outputs.tf: rename b2b_url → b2b_url_direct, add b2b_url_lambda,
  lambda_invoker_access_key_id, lambda_invoker_secret_key (sensitive)
- iac/dev/variables.tf: add openems_b2b_creds (sensitive, no default)
- iac/dev/terraform.tfvars.example: document openems_b2b_creds format

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Alejandro Malbet <amalbet@gmail.com>
- lambda.tf: use `security_groups` (list) instead of invalid
  `source_security_group_id` for inline egress block
- .gitignore: add lambda/proxy.zip (created by archive_file at plan time)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Signed-off-by: Alejandro Malbet <amalbet@gmail.com>
@amalbet amalbet closed this Apr 21, 2026
@amalbet amalbet deleted the worktree-agent-a5df6547 branch April 21, 2026 03:23
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.

Add Lambda VPC proxy for MBE-to-OpenEMS B2B access

2 participants