Remove the attack surface entirely: no open ports, no internet path, and every session tied to a real identity and recorded.
The problem
Bastion hosts and shared SSH keys are a liability: open ports, keys that never rotate, and no idea who typed what. Zero trust flips the model. Access is granted per identity, per session, for a limited time, and the network itself offers nothing to attack.
What you’ll build
- A private VPC with no internet gateway and no NAT, only VPC endpoints for SSM, KMS, CloudWatch Logs and S3
- A workload instance whose security group has zero inbound rules and IMDSv2 enforced
- Session Manager preferences: KMS-encrypted sessions, 15-minute idle timeout, 60-minute max, full transcripts to CloudWatch Logs and S3
- An IAM Identity Center permission set that can only start sessions on instances tagged
zt-access=engineers(ABAC), valid for 1 hour - A real-time “session started” notification showing who, where and from which IP
AWS services used
How it works
- AuthenticateEngineers sign in through Identity Center (SSO + MFA) and get a 1-hour session.
- AuthorizeThe permission set only allows
ssm:StartSessionon instances with the right tag. - ConnectSession Manager tunnels over private endpoints. Nothing listens on the instance.
- RecordKeystrokes stream, encrypted, to CloudWatch Logs and S3, and EventBridge announces the session instantly.
Key design decisions
- Tag-based access (ABAC) scales better than per-instance policies.
- Port forwarding through Session Manager reaches private databases with still no open ports.
- Session preferences are an account-wide document, so the template makes creating it optional.
Deploy it
aws cloudformation deploy --stack-name zero-trust \
--template-file template.yaml --capabilities CAPABILITY_IAM \
--parameter-overrides NotificationEmail=you@example.com
# With IAM Identity Center (recommended)
aws cloudformation deploy --stack-name zero-trust \
--template-file template.yaml --capabilities CAPABILITY_IAM \
--parameter-overrides \
IdentityCenterInstanceArn=arn:aws:sso:::instance/ssoins-xxxxxxxx \
IdentityCenterGroupId=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
Full prerequisites, parameters and clean-up steps are in the project README on the code page.
See it work
Port-scan the instance and get nothing back. Then start a session through SSO, run a command, and find the full transcript in CloudWatch Logs plus an email naming exactly who connected.
Skills this demonstrates
Get the code
Every file needed to build this project, written as a deployable CloudFormation template and validated with the CloudFormation schema.
Leave a Reply