Skip to content

feat(aws): add VPN-based local provisioning and existing VPC support#490

Open
nobody-Justheader wants to merge 2 commits intoOrange-Cyberdefense:mainfrom
nobody-Justheader:main
Open

feat(aws): add VPN-based local provisioning and existing VPC support#490
nobody-Justheader wants to merge 2 commits intoOrange-Cyberdefense:mainfrom
nobody-Justheader:main

Conversation

@nobody-Justheader
Copy link
Copy Markdown

@nobody-Justheader nobody-Justheader commented Mar 26, 2026

AWS VPN-Based Local Provisioning

Motivation

The current AWS provider requires a jumpbox EC2 instance to run Ansible provisioning remotely over SSH. This has two significant pain points:

Cost — The jumpbox (t2.medium) runs continuously alongside the lab VMs. Even when you're not actively provisioning or using the lab, you're paying for it. For labs that sit idle between pentest sessions, this adds up.

Workflow friction — All Ansible execution happens on the jumpbox, which means syncing sources over SSH, managing tunnels, and debugging remotely. If you're already running Kali or another attack box locally (which most pentesters are), the jumpbox is redundant infrastructure that gets in the way.

AWS Client VPN solves both problems. It provides direct L3 connectivity into the VPC from your local machine, so Ansible runs locally — the same way it works with VirtualBox and VMware providers. The VPN endpoint is created on-demand with vpn_connect and torn down with vpn_disconnect, so you only pay the ~$0.10/hr AWS Client VPN charge when you're actively connected.

What this adds

  • Local provisioning mode for AWS — Select local as the provisioning method to skip the jumpbox entirely and use VPN instead
  • On-demand VPN lifecyclevpn_connect and vpn_disconnect CLI commands manage the AWS Client VPN endpoint independently from lab VMs
  • Separate Terraform state — The VPN module lives in workspace/<id>/vpn/ with its own state file, so creating/destroying the VPN never touches running lab infrastructure
  • Auto-generated mutual TLS — CA, server, and client certificates are created via Terraform tls_* resources with ACM upload — no manual PKI needed
  • OpenVPN config output — A ready-to-use .ovpn config is generated as a Terraform output with embedded certs
  • Existing VPC support — Optionally set aws_vpc_id, aws_subnet_id, and aws_security_group_id in goad.ini to deploy into pre-existing network infrastructure
  • Conditional jumpbox — Jumpbox EC2 instance, SSH keypair, elastic IP, and related outputs are omitted when using local mode
  • VPN security group rule — Automatically adds an ingress rule allowing all traffic from the VPN client CIDR
  • Clean destroydestroy command attempts vpn_disconnect first when using local mode

Usage

# In goad.py interactive console:
set_provider aws
set_provisioning_method local
create

# After lab is provisioned, connect VPN:
vpn_connect
# Import the ovpn config from terraform output, connect with OpenVPN client
# Run provision_lab — Ansible runs locally over VPN

# Disconnect when done to stop VPN charges:
vpn_disconnect

Existing VPC mode (optional)

Add to ~/.goad/goad.ini:

[aws]
aws_vpc_id = vpc-xxxxxxxxx
aws_subnet_id = subnet-xxxxxxxxx
aws_security_group_id = sg-xxxxxxxxx

Also fixes: #472 — Dynamic AMI resolution for all regions

Previously, Windows and Ubuntu AMI IDs were hardcoded for eu-west-3, causing AuthFailure errors when deploying in other regions. This PR adds data "aws_ami" lookups that dynamically resolve the latest AMI for the configured region:

  • Windows VMsdata.aws_ami.windows_2016, windows_2019, windows_2022, windows_2025 resolve by SKU via locals.ami_lookup. The windows_sku field in each lab's config (e.g. 2019-Datacenter) maps to the correct AMI automatically.
  • Jumpboxdata.aws_ami.ubuntu_22_04 resolves the latest Ubuntu 22.04 AMI from Canonical.
  • Linux VMs — Same dynamic Ubuntu lookup.

Hardcoded AMI IDs in lab files are retained as fallbacks but will never be used for standard SKUs. Also updated the stale ami-03440f0d88fea1060 references to ami-0a4c1700182f3bc09 as a safety net.

Fixes #472

Files changed

  • goad/provider/terraform/aws.py — Local provisioner support, VPN methods, existing VPC config
  • goad/instance.py — Conditional jumpbox skipping, VPN folder generation
  • goad/goadpath.py — VPN path helper
  • goad/config.py — Optional VPC config fields
  • goad.py — VPN CLI commands, jumpbox skip, VPN disconnect on destroy
  • template/provider/aws/vpn/* — New VPN Terraform templates
  • template/provider/aws/windows.tf — Dynamic Windows AMI lookup via data "aws_ami" + locals.ami_lookup
  • template/provider/aws/jumpbox.tf — Dynamic Ubuntu AMI lookup
  • template/provider/aws/linux.tf — Dynamic Ubuntu AMI lookup
  • template/provider/aws/{network,outputs,variables}.tf — Conditional Jinja2 for existing VPC and local mode
  • ad/*/providers/aws/windows.tf — Updated fallback AMI IDs
  • extensions/*/providers/aws/windows.tf — Updated fallback AMI IDs

- Add local provisioning mode to AWS provider (vpn_connect/vpn_disconnect)
- Add VPN Terraform module templates (certificates, endpoint, OpenVPN config)
- Support existing VPC via aws_vpc_id/aws_subnet_id/aws_security_group_id config
- Skip jumpbox resources when using local provisioning
- Add VPN client CIDR security group ingress rule for local mode
- Add vpn_connect/vpn_disconnect CLI commands
- Attempt VPN disconnect before destroy for local mode instances
Replace ami-03440f0d88fea1060 with ami-0a4c1700182f3bc09
(Windows_Server-2019-English-Full-Base-2025.11.12) across all labs
and extensions.

Fixes Orange-Cyberdefense#472
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.

[AWS]: Windows AMI's are outdated

1 participant