after measure
Teardown
Remove only what the harness created. Consumer first, then provider. Do not touch TGW, inspection VPC, or Network Firewall policy.
Stop here if you still need the lab. This deletes the stream path permanently.
Order
| Step | Account | Delete |
|---|---|---|
| 1 | consumer | Interface endpoint → subscriber EC2 → SGs → IAM (and lab-only SSM VPCE if you created one) |
| 2 | shared-services | Endpoint service → NLB → target group → relay EC2 → SG → IAM (and lab-only SSM VPCE if you created one) |
Discover by tag if you lost IDs:
export AWS_REGION=ap-southeast-6
aws resourcegroupstaggingapi get-resources \
--profile consumer --region "$AWS_REGION" \
--tag-filters Key=demo,Values=pl-vs-inspected-tgw \
--query 'ResourceTagMappingList[].ResourceARN' --output table
aws resourcegroupstaggingapi get-resources \
--profile shared-services --region "$AWS_REGION" \
--tag-filters Key=demo,Values=pl-vs-inspected-tgw \
--query 'ResourceTagMappingList[].ResourceARN' --output table
1. Consumer
export AWS_PROFILE=consumer
export AWS_REGION=ap-southeast-6
aws sts get-caller-identity
Interface endpoint
# Example — use your EP_ID from Consumer setup
export EP_ID=vpce-0eeee3333ffff4444
aws ec2 delete-vpc-endpoints \
--profile consumer --region "$AWS_REGION" \
--vpc-endpoint-ids "$EP_ID"
Validate
aws ec2 describe-vpc-endpoints \
--profile consumer --region "$AWS_REGION" \
--vpc-endpoint-ids "$EP_ID" \
--query 'VpcEndpoints[0].State' --output text
deleting
Subscriber EC2
export CONSUMER_INSTANCE_ID=i-0cccc1111dddd2222
aws ec2 terminate-instances \
--profile consumer --region "$AWS_REGION" \
--instance-ids "$CONSUMER_INSTANCE_ID"
aws ec2 wait instance-terminated \
--profile consumer --region "$AWS_REGION" \
--instance-ids "$CONSUMER_INSTANCE_ID"
Security groups
Wait until ENIs from the endpoint and instance are gone, then:
export CONSUMER_ENDPOINT_SG_ID=sg-0eeee3333ffff4444
export CONSUMER_INSTANCE_SG_ID=sg-0cccc1111dddd2222
aws ec2 delete-security-group \
--profile consumer --region "$AWS_REGION" \
--group-id "$CONSUMER_ENDPOINT_SG_ID"
aws ec2 delete-security-group \
--profile consumer --region "$AWS_REGION" \
--group-id "$CONSUMER_INSTANCE_SG_ID"
If delete fails with “DependencyViolation”, wait ~30 s and retry.
IAM instance profile
aws iam remove-role-from-instance-profile \
--profile consumer \
--instance-profile-name plvtgw-ec2-ssm \
--role-name plvtgw-ec2-ssm
aws iam delete-instance-profile \
--profile consumer \
--instance-profile-name plvtgw-ec2-ssm
aws iam detach-role-policy \
--profile consumer \
--role-name plvtgw-ec2-ssm \
--policy-arn arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
aws iam delete-role \
--profile consumer \
--role-name plvtgw-ec2-ssm
Skip IAM deletes if the role is shared with other workloads.
Lab-only SSM endpoint (optional)
Only if you created a tagged plvtgw-ssm interface endpoint during Consumer prep:
aws ec2 describe-vpc-endpoints \
--profile consumer --region "$AWS_REGION" \
--filters Name=tag:Name,Values=plvtgw-ssm \
--query 'VpcEndpoints[].VpcEndpointId' --output text
# then:
# aws ec2 delete-vpc-endpoints --profile consumer --region "$AWS_REGION" --vpc-endpoint-ids vpce-…
Do not delete pre-existing spoke SSM endpoints you did not create for this lab.
2. Provider (shared-services)
export AWS_PROFILE=shared-services
export AWS_REGION=ap-southeast-6
aws sts get-caller-identity
Endpoint service
export SVC_ID=vpce-svc-0aaaa1111bbbb2222
aws ec2 delete-vpc-endpoint-service-configurations \
--profile shared-services --region "$AWS_REGION" \
--service-ids "$SVC_ID"
NLB, listener, target group
export NLB_ARN=arn:aws:elasticloadbalancing:ap-southeast-6:111122223333:loadbalancer/net/plvtgw-nlb/0123456789abcdef
export TG_ARN=arn:aws:elasticloadbalancing:ap-southeast-6:111122223333:targetgroup/plvtgw-tg/fedcba9876543210
# Listener (if still present)
LISTENER_ARN=$(aws elbv2 describe-listeners \
--profile shared-services --region "$AWS_REGION" \
--load-balancer-arn "$NLB_ARN" \
--query 'Listeners[0].ListenerArn' --output text)
aws elbv2 delete-listener \
--profile shared-services --region "$AWS_REGION" \
--listener-arn "$LISTENER_ARN"
aws elbv2 delete-load-balancer \
--profile shared-services --region "$AWS_REGION" \
--load-balancer-arn "$NLB_ARN"
# Wait until describe fails
until ! aws elbv2 describe-load-balancers \
--profile shared-services --region "$AWS_REGION" \
--load-balancer-arns "$NLB_ARN" &>/dev/null; do
sleep 5
done
aws elbv2 delete-target-group \
--profile shared-services --region "$AWS_REGION" \
--target-group-arn "$TG_ARN"
Relay EC2
export PROVIDER_INSTANCE_ID=i-0aaaa1111bbbb2222
aws ec2 terminate-instances \
--profile shared-services --region "$AWS_REGION" \
--instance-ids "$PROVIDER_INSTANCE_ID"
aws ec2 wait instance-terminated \
--profile shared-services --region "$AWS_REGION" \
--instance-ids "$PROVIDER_INSTANCE_ID"
Host files under /opt/plvtgw and plvtgw-relay.service disappear with the instance.
Security group + IAM
export PROVIDER_SG_ID=sg-0relay1111cccc2222
aws ec2 delete-security-group \
--profile shared-services --region "$AWS_REGION" \
--group-id "$PROVIDER_SG_ID"
aws iam remove-role-from-instance-profile \
--profile shared-services \
--instance-profile-name plvtgw-ec2-ssm \
--role-name plvtgw-ec2-ssm
aws iam delete-instance-profile \
--profile shared-services \
--instance-profile-name plvtgw-ec2-ssm
aws iam detach-role-policy \
--profile shared-services \
--role-name plvtgw-ec2-ssm \
--policy-arn arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
aws iam delete-role \
--profile shared-services \
--role-name plvtgw-ec2-ssm
Lab-only SSM endpoint (optional)
Same rule as consumer — only delete a plvtgw-ssm endpoint you created for this lab.
Leave alone
| Resource | Why |
|---|---|
| Transit Gateway, attachments, spoke routes | Hub prerequisite |
| Inspection VPC / Network Firewall policy | Hub prerequisite |
| Pre-existing SSM / other interface endpoints | Not harness-owned |
| Spoke VPCs and subnets | Already existed |
If you temporarily opened hub firewall for consumer → provider :9000 outside this repo, reverse that in the network account. That change is not part of the harness tag.
Confirm clean
aws resourcegroupstaggingapi get-resources \
--profile consumer --region "$AWS_REGION" \
--tag-filters Key=demo,Values=pl-vs-inspected-tgw \
--query 'ResourceTagMappingList' --output table
aws resourcegroupstaggingapi get-resources \
--profile shared-services --region "$AWS_REGION" \
--tag-filters Key=demo,Values=pl-vs-inspected-tgw \
--query 'ResourceTagMappingList' --output table
Empty tables (or only lingering ARNs in deleting) means teardown is done.
Laptop helper (needs scripts/.state from setup): ./scripts/teardown.sh.