Skip to content

Instantly share code, notes, and snippets.

@lukeplausin
Last active September 21, 2024 23:10
Show Gist options
  • Save lukeplausin/4b412d83fb1246b0bed6507b5083b3a7 to your computer and use it in GitHub Desktop.
Save lukeplausin/4b412d83fb1246b0bed6507b5083b3a7 to your computer and use it in GitHub Desktop.
Transfer a file to EC2 SSM instance without using S3 (SSM only)
# This script will explain how to transfer a file to EC2 using SSM ONLY!
# You will need to have permission to run SSM commands on the target machine and have sudo access as well
# Infos
INSTANCE_ID=i-1234567890
FILE_NAME=the_file.tar.gz
# Step 1: Run command on machine to install netcat and dump from port to filename
# < Start session
aws ssm start-session --target $INSTANCE_ID --document-name
# < (On target machine) :
cd && sudo yum install nc -y && sudo nc -l -p 1234 > the_file.tar.gz
# Step 2: On another shell, open a port-forwarding session from your machine to the target machine
aws ssm start-session --target $INSTANCE_ID --document-name AWS-StartPortForwardingSession --parameters '{"portNumber":["1234"],"localPortNumber":["1234"]}'
# Step 3: On yet another shell, cat the source file into the transfer port on localhost over the tunnel
nc -w 3 127.0.0.1 1234 < the_file.tar.gz
# Step 4: Once the command in step 3 finishes, close all of the other shell sessions. Your file should be on the target now.
@ritwik-g
Copy link

This was really useful. Thanks for publishing

@johnp789
Copy link

That's handy! I had to remove the --document-name on the first start-session call.

@pWoLiAn
Copy link

pWoLiAn commented Apr 2, 2024

similarly, have you tried copying a file from ec2 to your local machine without using s3

@toliadobe
Copy link

Extremely helpful! Thank you for sharing.

@bdalli
Copy link

bdalli commented Apr 29, 2024

Very helpful, thank you Luke ..

@s4wet
Copy link

s4wet commented Jun 18, 2024

Thank helpful

@baerrach
Copy link

baerrach commented Jun 25, 2024

Thanks for your script.
I wanted to download a file from the EC2 instance, so the commands are reversed somewhat.

Step 1: On EC2 instance dump from filename to port

nc -l 1234 < the_file.tar.gz

Step 2: On your machine open a shell, open a port-forwarding session from your machine to the target machine

aws ssm start-session --target $INSTANCE_ID --document-name AWS-StartPortForwardingSession --parameters '{"portNumber":["1234"],"localPortNumber":["1234"]}'

Step 3: On your machine open another shell, use nc to read the data over the tunnel and write to destination file

nc -w 3 localhost 1234 > the_file.tar.gz

Step 4: Once the command in step 3 finishes, close all of the other shell sessions. Your file should be on the destination now.

@dmitrygusev
Copy link

Same approach but in one script, save the below script into a file and call it like this:

./upload-file 1234 "/local/path/to/the_file" i-xxxxx "/remote/path/to/the_file"

Note, the script is also creating a folder on the remote if it doesn't exist

upload-file

#!/usr/bin/expect

# Set the script to not time out
set timeout -1

# Capture the script arguments
# Port for netcat
set port [lindex $argv 0]
# File to send via netcat
set file_to_send [lindex $argv 1]
# AWS SSM instance ID
set remote_instance_id [lindex $argv 2]
# Remove file name
set remote_file_name [lindex $argv 3]

# Start AWS SSM session on host A and run netcat to listen on a port
spawn aws ssm start-session --target $remote_instance_id
expect {
    -re "sh-.*" {
        send_user "\nAWS SSM session started.\n"
        send "mkdir -p \"\$(dirname \"$remote_file_name\")\" && nc -l -p $port > \"$remote_file_name\"\r"
        send_user "\nNetcat listener started on port $port > $remote_file_name.\n"
    }
}

# Start a background AWS SSM session for port forwarding
spawn bash -c "aws ssm start-session --target $remote_instance_id --document-name AWS-StartPortForwardingSession --parameters '{\"portNumber\":\[\"$port\"\],\"localPortNumber\":\[\"$port\"\]}'"
expect {
    -re "Waiting for connections" {
        send_user "\nPort forwarding session established.\n"
    }
}

# Use netcat to send the file to the port
spawn bash -c "nc localhost $port < \"$file_to_send\""
expect {
    eof {
        send_user "\nFile sent.\n"
    }
}

# Terminate the netcat listener on the remote host
spawn aws ssm start-session --target $remote_instance_id
expect {
    -re "sh-.*" {
        send_user "\nTerminating netcat listener on remote host.\n"
        send "pkill -f 'nc -l -p $port'\r"
    }
}

# Terminate all AWS SSM sessions
send_user "\nClosing all sessions...\n"
exec pkill -f "aws ssm"
send_user "\nAll sessions terminated.\n"

exit

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment