Skip to content

Commit 212bd7e

Browse files
authored
Windows support (#14)
* Add instructions for Windows * Add RunShellScript based script for Windows * Add ec2-instance-connect based script for Windows * Add a note on script output on Windows
1 parent bcabc37 commit 212bd7e

File tree

4 files changed

+229
-0
lines changed

4 files changed

+229
-0
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# aws-ssm-ec2-proxy-command
22
Open an SSH connection to your ec2 instances via AWS SSM without the need to open any ssh port in you security groups.
33

4+
### Windows users
5+
In order to use this project on Windows refer to [README.windows.md](README.windows.md)
46
#### Prerequisits
57
* Local Setup
68
* [Install AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-install.html)

README.windows.md

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
# aws-ssm-ec2-proxy-command (Windows)
2+
3+
Open an SSH connection to your ec2 instances via AWS SSM without the need to open any ssh port in you security groups.
4+
5+
#### Prerequisits
6+
7+
* Local Setup
8+
* [Install AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-install.html)
9+
* Windows `winget install Amazon.AWSCLI`
10+
* [Install AWS CLI Session Manager Plugin](https://docs.aws.amazon.com/systems-manager/latest/userguide/session-manager-working-with-install-plugin.html)
11+
* Windows `winget install Amazon.SessionManagerPlugin`
12+
* Ensure Your IAM Permissions
13+
* [IAM Policy Example](aws-ssm-ec2-iam-policy.json)
14+
* `ssm:StartSession` for DocumentName: `AWS-StartSSHSession` and Target Instance
15+
* [AWS Documentation](https://docs.aws.amazon.com/systems-manager/latest/userguide/getting-started-restrict-access-examples.html)
16+
* `ssm:SendCommand` for DocumentName: `AWS-RunShellScript` and Target Instance
17+
* [AWS Documentation](https://docs.aws.amazon.com/systems-manager/latest/userguide/sysman-rc-setting-up.html)
18+
* Target Instance Setup
19+
* [Ensure SSM Permissions](https://docs.aws.amazon.com/systems-manager/latest/userguide/setup-instance-profile.html) fo Target Instance Profile
20+
* Ensure SSM Agent is installed (preinstalled on all AWS Linux AMIs already)
21+
* [Install SSM Agent on Linux Instances](https://docs.aws.amazon.com/systems-manager/latest/userguide/sysman-install-ssm-agent.html)
22+
* `yum install -y https://s3.amazonaws.com/ec2-downloads-windows/SSMAgent/latest/linux_amd64/amazon-ssm-agent.rpm & service amazon-ssm-agent restart`
23+
* [SSM Agent on Windows Instances](https://docs.aws.amazon.com/systems-manager/latest/userguide/sysman-install-ssm-win.html)
24+
25+
#### Install SSH Proxy Command
26+
27+
- Move proxy command script [aws-ssm-ec2-proxy-command.ps1](aws-ssm-ec2-proxy-command.ps1) to `~/.ssh/aws-ssm-ec2-proxy-command.ps1`
28+
29+
- Ensure you are allowed to execute powershell scripts (see [Set-ExecutionPolicy](https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.security/set-executionpolicy) command)
30+
31+
Unfortunately on Windows is not possible to show output while running ProxyCommand, script output is interpreted as SSH banner which is available with SSH verbose options.
32+
33+
##### Setup SSH Config [optional]
34+
35+
* Add ssh config entry for aws ec2 instances to your `~/.ssh/config`. Adjust key file path if needed.
36+
37+
```ssh-config
38+
host i-* mi-*
39+
IdentityFile ~/.ssh/id_rsa
40+
ProxyCommand powershell.exe ~/.ssh/aws-ssm-ec2-proxy-command.ps1 %h %r %p ~/.ssh/id_rsa.pub
41+
StrictHostKeyChecking no
42+
```
43+
44+
#### Open SSH Connection
45+
46+
* Ensure AWS CLI environemnt variables are set properly e.g.
47+
* `export AWS_PROFILE=default` or `AWS_PROFILE=default ssh ... <INSTACEC_USER>@<INSTANCE_ID>`
48+
* If default region does not match instance region you need to provide it
49+
* e.g. `<INSTACEC_USER>@<INSTANCE_ID>--<INSTANCE_REGION>`
50+
51+
###### SSH Command with SSH Config Setup
52+
53+
`ssh <INSTACEC_USER>@<INSTANCE_ID>`
54+
55+
* e.g. `ssh ec2-user@i-1234567890`
56+
57+
###### SSH Command with ProxyCommand CLI Option
58+
59+
```powershell
60+
ssh.exe <INSTACEC_USER>@<INSTANCE_ID> `
61+
-i "~/.ssh/id_rsa" `
62+
-o ProxyCommand="powershell.exe ~/.ssh/aws-ssm-ec2-proxy-command.ps1 %h %r %p ~/.ssh/id_rsa.pub"
63+
```
64+
65+
## Alternative Implementation with `ec2-instance-connect`
66+
67+
The advantage from security perspective it that you don't need to grant `ssm:SendCommand` to users and there by the permission to execute everything as root.
68+
Instead you only grant `ec2-instance-connect:SendSSHPublicKey` permission to a specific instance user e.g. `ec2-user`.
69+
70+
* Ensure [Prerequisits](#prerequisits)
71+
* Use this [aws-ssm-ec2-proxy-command.ps1](ec2-instance-connect/aws-ssm-ec2-proxy-command.ps1) proxy command script instead
72+
* Use this [IAM Policy Example](ec2-instance-connect/aws-ssm-ec2-iam-policy.json) instead
73+
* `ssm:StartSession` for DocumentName: `AWS-StartSSHSession` and Target Instance
74+
* [AWS Documentation](https://docs.aws.amazon.com/systems-manager/latest/userguide/getting-started-restrict-access-examples.html)
75+
* `ec2-instance-connect:SendSSHPublicKey`
76+
* [AWS Documentation](https://docs.aws.amazon.com/systems-manager/latest/userguide/sysman-rc-setting-up.html)
77+
* You may need to adjust `ec2:osuser` to match your needs. Default osuser is `ec2-user`
78+
* Follow [Install Guide](#install-ssh-proxy-command)

aws-ssm-ec2-proxy-command.ps1

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
#!/usr/bin/env sh
2+
######## Source ################################################################
3+
#
4+
# https://github.com/qoomon/aws-ssm-ec2-proxy-command
5+
#
6+
######## Usage #################################################################
7+
# https://github.com/qoomon/aws-ssm-ec2-proxy-command/blob/master/README.md
8+
#
9+
# Install Proxy Command
10+
# - Move this script to ~/.ssh/aws-ssm-ec2-proxy-command.ps1
11+
# - Ensure you are allowed to execute powershell scripts (see Set-ExecutionPolicy command)
12+
#
13+
# Add following SSH Config Entry to ~/.ssh/config
14+
# host i-* mi-*
15+
# IdentityFile ~/.ssh/id_rsa
16+
# ProxyCommand powershell .exe ~/.ssh/aws-ssm-ec2-proxy-command.ps1 %h %r %p ~/.ssh/id_rsa.pub
17+
# StrictHostKeyChecking no
18+
#
19+
# Ensure SSM Permissions for Target Instance Profile
20+
# https://docs.aws.amazon.com/systems-manager/latest/userguide/setup-instance-profile.html
21+
#
22+
# Open SSH Connection
23+
# ssh <INSTANCE_USER>@<INSTANCE_ID>
24+
#
25+
# Ensure AWS CLI environment variables are set properly
26+
# e.g. AWS_PROFILE='default' ssh ec2-user@i-xxxxxxxxxxxxxxxx
27+
#
28+
# If default region does not match instance region you need to provide it like this
29+
# ssh <INSTANCE_USER>@<INSTANCE_ID>--<INSTANCE_REGION>
30+
#
31+
################################################################################
32+
$ErrorActionPreference = "Stop"
33+
34+
$REGION_SEPARATOR = "--"
35+
36+
$ec2_instance_id = $args[0]
37+
$ssh_user = $args[1]
38+
$ssh_port = $args[2]
39+
$ssh_public_key_path = $args[3]
40+
$ssh_public_key = (Get-Content $ssh_public_key_path | Select-Object -first 1)
41+
$ssh_public_key_timeout = 60
42+
43+
44+
$splitted_instance = $ec2_instance_id -split $REGION_SEPARATOR
45+
46+
if ($splitted_instance.Length -gt 1)
47+
{
48+
$ec2_instance_id = $splitted_instance[0]
49+
$env:AWS_DEFAULT_REGION = $splitted_instance[1]
50+
}
51+
52+
$authorized_key = "$ssh_public_key ssm-session"
53+
$script = @"
54+
\"
55+
mkdir -p ~$ssh_user/.ssh && cd ~$ssh_user/.ssh || exit 1
56+
57+
echo '$authorized_key' >> authorized_keys
58+
59+
sleep $ssh_public_key_timeout
60+
61+
grep -v -F '$authorized_key' authorized_keys > .authorized_keys
62+
mv .authorized_keys authorized_keys
63+
\"
64+
"@
65+
66+
Write-Output "Add public key $ssh_public_key_path for $ssh_user at instance $ec2_instance_id for $ssh_public_key_timeout seconds"
67+
aws ssm send-command `
68+
--instance-ids "$ec2_instance_id" `
69+
--document-name 'AWS-RunShellScript' `
70+
--comment "Add an SSH public key to authorized_keys for $ssh_public_key_timeout seconds" `
71+
--parameters commands="$script"
72+
if($LASTEXITCODE -ne 0) { Write-Error "Failed to add public key with error $output" }
73+
74+
Write-Output "Start ssm session to instance $ec2_instance_id"
75+
aws ssm start-session `
76+
--target "$ec2_instance_id" `
77+
--document-name 'AWS-StartSSHSession' `
78+
--parameters "portNumber=$ssh_port"
79+
if($LASTEXITCODE -ne 0) { Write-Error "Failed to start ssm session to instance $output" }
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
#!/usr/bin/env sh
2+
######## Source ################################################################
3+
#
4+
# https://github.com/qoomon/aws-ssm-ec2-proxy-command
5+
#
6+
######## Usage #################################################################
7+
# https://github.com/qoomon/aws-ssm-ec2-proxy-command/blob/master/README.md
8+
#
9+
# Install Proxy Command
10+
# - Move this script to ~/.ssh/aws-ssm-ec2-proxy-command.ps1
11+
# - Ensure you are allowed to execute powershell scripts (see Set-ExecutionPolicy command)
12+
#
13+
# Add following SSH Config Entry to ~/.ssh/config
14+
# host i-* mi-*
15+
# IdentityFile ~/.ssh/id_rsa
16+
# ProxyCommand powershell .exe ~/.ssh/aws-ssm-ec2-proxy-command.ps1 %h %r %p ~/.ssh/id_rsa.pub
17+
# StrictHostKeyChecking no
18+
#
19+
# Ensure SSM Permissions for Target Instance Profile
20+
# https://docs.aws.amazon.com/systems-manager/latest/userguide/setup-instance-profile.html
21+
#
22+
# Open SSH Connection
23+
# ssh <INSTANCE_USER>@<INSTANCE_ID>
24+
#
25+
# Ensure AWS CLI environment variables are set properly
26+
# e.g. AWS_PROFILE='default' ssh ec2-user@i-xxxxxxxxxxxxxxxx
27+
#
28+
# If default region does not match instance region you need to provide it like this
29+
# ssh <INSTANCE_USER>@<INSTANCE_ID>--<INSTANCE_REGION>
30+
#
31+
################################################################################
32+
$ErrorActionPreference = "Stop"
33+
34+
$REGION_SEPARATOR = "--"
35+
36+
$ec2_instance_id = $args[0]
37+
$ssh_user = $args[1]
38+
$ssh_port = $args[2]
39+
$ssh_public_key_path= $args[3]
40+
41+
$splitted_instance = $ec2_instance_id -split $REGION_SEPARATOR
42+
43+
if ($splitted_instance.Length -gt 1)
44+
{
45+
$ec2_instance_id = $splitted_instance[0]
46+
$env:AWS_DEFAULT_REGION = $splitted_instance[1]
47+
}
48+
49+
$instance_availability_zone = (
50+
aws ec2 describe-instances `
51+
--instance-id "$ec2_instance_id" `
52+
--query "Reservations[0].Instances[0].Placement.AvailabilityZone" `
53+
--output text `
54+
)
55+
if($LASTEXITCODE -ne 0) { Write-Error "Failed to get availability zone for instance $ec2_instance_id" }
56+
57+
Write-Output "Add public key $ssh_public_key_path for $ssh_user at instance $ec2_instance_id for 60 seconds"
58+
aws ec2-instance-connect send-ssh-public-key `
59+
--instance-id "$ec2_instance_id" `
60+
--instance-os-user "$ssh_user" `
61+
--ssh-public-key "file://$ssh_public_key_path" `
62+
--availability-zone "$instance_availability_zone"
63+
if($LASTEXITCODE -ne 0) { Write-Error "Failed to add public key for $ssh_user at instance $ec2_instance_id" }
64+
65+
Write-Output "Start ssm session to instance $ec2_instance_id"
66+
aws ssm start-session `
67+
--target "$ec2_instance_id" `
68+
--document-name 'AWS-StartSSHSession' `
69+
--parameters "portNumber=$ssh_port"
70+
if($LASTEXITCODE -ne 0) { Write-Error "Failed to start ssm session to instance $ec2_instance_id" }

0 commit comments

Comments
 (0)