{ "AWSTemplateFormatVersion": "2010-09-09", "Resources": { "SSHProxySecurityGroup": { "Type": "AWS::EC2::SecurityGroup", "Properties": { "GroupName": { "Ref": "AWS::StackName" }, "GroupDescription": "ssh access allowed via port 22 from anywhere", "SecurityGroupIngress": [ { "CidrIp": "0.0.0.0/0", "Description": "ssh access from anywhere", "IpProtocol": "tcp", "FromPort": 22, "ToPort": 22 }, { "CidrIpv6": "::/0", "Description": "ssh access from anywhere", "IpProtocol": "tcp", "FromPort": 22, "ToPort": 22 } ] } }, "SSHProxyLaunchTemplate": { "Type": "AWS::EC2::LaunchTemplate", "Properties": { "LaunchTemplateName": { "Ref": "AWS::StackName" }, "LaunchTemplateData": { "DisableApiTermination": false, "InstanceInitiatedShutdownBehavior": "terminate", "InstanceType": "t4g.nano", "KeyName": { "Ref": "AWS::StackName" }, "UserData": { "Fn::Base64": { "Fn::Join": [ "\n", [ "#cloud-config", "packages:", " - socat", "", "write_files:", " - path: /etc/ssh/sshd_config.d/99-proxy-restrict.conf", " permissions: 0o600", " content: |", " Match User ec2-user", " AcceptEnv SSH_PROXY_*", " ForceCommand /usr/local/bin/ssh-proxy", " - path: /usr/local/bin/ssh-proxy", " permissions: 0o755", " content: |", " #!/bin/sh -e", " ", " if test -z \"$SSH_ORIGINAL_COMMAND\" ; then", " # RemoteCommand does not set SSH_ORIGINAL_COMMAND, trying to recover", " if test -z \"$1\" ; then", " if test \"$SSH_PROXY_FORWARD\" = 1 ; then set -- forward ; fi", " if test \"$SSH_PROXY_CONNECT\" = 1 ; then set -- connect ; fi", " fi", " SSH_ORIGINAL_COMMAND=\"$(basename \"$0\") $1\"", " fi", " ", " case \"$SSH_ORIGINAL_COMMAND\" in", " ", " 'ssh-proxy forward')", " trap 'sudo systemctl poweroff -qf' EXIT HUP INT PIPE TERM", " # wait five minutes for a client to connect", " i=0 ; while test $i -lt 60 ; do", " sleep 5", " grep -Fq sshd /proc/$PPID/cmdline || exit", " test \"$(ls ssh-client* 2> /dev/null)\" && break", " i=$((i+1))", " done || exit", " # keep the machine alive for at most 24h", " i=0 ; while test $i -lt $((24*60)) ; do", " sleep 60", " grep -Fq sshd /proc/$PPID/cmdline || exit", " i=$((i+1))", " done", " ;;", " ", " 'ssh-proxy connect')", " # last leaving client shuts down machine", " trap 'rm -f ssh-client-$PPID ; sleep 300 ; test \"$(ls ssh-client* 2> /dev/null)\" || sudo systemctl poweroff -qf' EXIT HUP INT PIPE TERM", " # create client marker file", " touch ssh-client-$PPID", " # wait (indefinitely!) for server socket to appear", " while ! test -e \"$HOME/ssh-server\" ; do", " sleep 5", " grep -Fq sshd /proc/$PPID/cmdline || exit", " done", " # connect TTY to server", " socat stdio \"unix-connect:$HOME/ssh-server\"", " ;;", " ", " *)", " exit 1", " ;;", " ", " esac", "" ] ] } }, "BlockDeviceMappings": [ { "DeviceName": "/dev/xvda", "Ebs": { "DeleteOnTermination": true, "VolumeType": "gp3" } } ], "CreditSpecification": { "CpuCredits": "standard" }, "Monitoring": { "Enabled": false }, "NetworkInterfaces": [ { "AssociatePublicIpAddress": true, "DeleteOnTermination": true, "DeviceIndex": 0, "Groups": [ { "Fn::GetAtt": [ "SSHProxySecurityGroup", "GroupId" ] } ] } ], "Placement": { "Tenancy": "default" }, "TagSpecifications": [ { "ResourceType": "instance", "Tags": [ { "Value": "<undefined>", "Key": "ssh-proxy" } ] } ] } } }, "SSHProxyUser": { "Type": "AWS::IAM::User", "Properties": { "UserName": { "Ref": "AWS::StackName" }, "Policies": [ { "PolicyName": { "Ref": "AWS::StackName" }, "PolicyDocument": { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "ec2:DescribeInstances", "Resource": "*" }, { "Effect": "Allow", "Action": "ec2:DescribeImages", "Resource": "*" }, { "Effect": "Allow", "Action": "ec2:RunInstances", "Resource": "*", "Condition": { "StringEquals": { "ec2:LaunchTemplate": { "Fn::Sub": "arn:aws:ec2:${AWS::Region}:${AWS::AccountId}:launch-template/${SSHProxyLaunchTemplate}" } }, "Bool": { "ec2:IsLaunchTemplateResource": "true" } } }, { "Effect": "Allow", "Action": "ec2:RunInstances", "Resource": { "Fn::Sub": "arn:aws:ec2:${AWS::Region}::image/ami-*" }, "Condition": { "StringEquals": { "ec2:Owner": "amazon" } } }, { "Effect": "Allow", "Action": "ec2:RunInstances", "Resource": { "Fn::Sub": "arn:aws:ec2:${AWS::Region}:${AWS::AccountId}:subnet/*" } }, { "Effect": "Allow", "Action": "ec2:CreateTags", "Resource": "*", "Condition": { "StringEquals": { "ec2:CreateAction": "RunInstances" }, "ForAllValues:StringEquals": { "aws:TagKeys": [ "ssh-proxy" ] } } }, { "Effect": "Allow", "Action": "ec2:TerminateInstances", "Resource": "*", "Condition": { "StringLike": { "ec2:ResourceTag/ssh-proxy": "*" } } } ] } } ] } } } }