awssh
TEST
awssh
uses boto3 to list your AWS instances and easily ssh, run commands, create tunnels, and ProxyJump based on
'Key Name'. It supports aws-cli --profile
and --region
options, as well as MFA options --serial-number
and
--token-code
. It also supports aws-cli environment variables AWS_DEFAULT_REGION, AWS_DEFAULT_PROFILE, and
AWS_SHARED_CREDENTIALS_FILE to specify configuration options and credentials.
➜ ~ awssh
EC2 instances in default region:
Name Public IP Private IP Zone Key Name
1 - JumpHost-1 3.13.18.215 10.120.1.119 us-east-2a project-100715
2 - BuildServer None 10.120.1.40 us-east-2a project-100715
3 - JumpHost-2 48.14.28.186 10.120.0.8 us-east-2a project-101018
4 - ML-Supervised None 10.120.1.46 us-east-2a project-101018
5 - Dyna-dyna None 10.120.1.7 us-east-2a project-101018
6 - ECS Instance None 10.120.1.55 us-east-2a project-101018
7 - MySQL-PROD None 10.120.1.55 us-east-2a project-100715
8 - codeCommit None 10.120.1.119 us-east-2a project-100715
Enter server number: 7
Connecting to codeCommit via JumpHost-1:
[centos@code-commit ~]$
Installation
First, install the aws-cli and boto3 libraries:
pip3 install awscli --upgrade --user
pip3 install boto3
Next, set up aws credentials, default profile, and default regions:
aws configure
Note: configure your
AWS Profiles
to be able to use the --profile
option and the AWS_DEFAULT_PROFILE environment variable.
Install the awssh
utility:
pip3 install ssh-aws --user # or pip3 install ssh-aws
Finally, depending on your Python version, make sure that $HOME/Library/Python/<version>/bin
is part of PATH.
echo $PATH
Note: the awssh
utility is installed in $HOME/Library/Python/<version>/bin
which may not be on your PATH.
Version update
echo y | pip3 uninstall ssh-aws
pip3 install ssh-aws --no-cache --user # or pip3 install --no-cache ssh-aws
awssh --version
Requirements
Features
The awssh
utility gives you a list of AWS instances and preconfigures ssh
with the proper user and key.
You can filter by Name
tag. If an instance without an external (elastic) IP is selected, awssh
attempts to find a
jump server to use via the ProxyJump configuration directive (e.g. ssh -A -J user@<jump.host> user@<target.host>
).
Note: Agent forwarding should be used with caution. awssh
provides many useful features, a few of them are:
local and remote port forwarding for ssh-tunneling (e.g. ssh -L 9000:imgur.com:80 user@<ip_address>
), remote
execution of commands providing the -c
option (e.g. awssh --profile prod-acc-2 -c top
), MFA and STS, so you only
need to provide --serial-number
and --token-code
once per cycle, etc. More information on all the features
and convenience that awssh
provides can be found in the help document (awssh --help
).
Note on MFA: The keys and tokens are saved on the AWS credentials file (~/.aws/credentials or the file set by
the environment variable AWS_SHARED_CREDENTIALS_FILE) under the [mfa] profile. They can be reused until expiration
by running awssh --profile mfa
. After expiration, run awssh --serial-number <mfa_arn> --token-code <mfa_code>
to
generate new tokens.
Usage
➜ ~ awssh --help
usage: awssh [-h] [--users USERS [USERS ...]] [--profile PROFILE]
[--region REGION] [-i KEY_PATH] [-c COMMAND] [-r REMOTE_HOST]
[-p REMOTE_PORT] [-l LOCAL_PORT] [--keys KEYS]
[--timeout TIMEOUT] [--console-output] [--version] [--verbose]
[--serial-number SERIAL_NUMBER] [--token-code TOKEN_CODE]
[filter]
SSH, 'ProxyJump', create tunnels, and run commands on your AWS Linux/Unix
infrastructure. "awssh --profile prod-acc-2 --region us-east-2 'rev-proxy' -c
top --users fduran" "awssh --profile prod-acc-2" will attempt ssh with default
users. The default user list is centos, ubuntu, and ec2-user. Due to the
nature of nargs, the option --users needs to be used last. For example: "awssh
--users user1 user2 'rev-proxy'" will not properly filter the results by
'instance-name'; instead try "awssh 'rev-proxy' --users user1 user2". To use
two different users on proxy jump try: --users user1/user2. When the instance
selected has no external IP, a "JumpHost" will be automatically chosen based
on instances with external IPs that share the same ssh 'Key Name'. This is
particularly useful if your project instances share the same 'SSH Key'. You
can also explicitly direct the JumpHost by providing two selections from the
list (i.e. Enter server number: <jump> <target>). MFA: when providing the
--serial-number and --token-code options, awssh creates a profile [mfa] in
your AWS credentials file (~/.aws/credentials or the file set by the
AWS_SHARED_CREDENTIALS_FILE environment variable). You can continue using
these temporary tokens until expiration with "awssh --profile mfa".
positional arguments:
filter Optional instance name or key word as a filter. If
only one instance is found, it will connect to it
directly.
optional arguments:
-h, --help show this help message and exit
--users USERS [USERS ...]
Users to try (centos, ubuntu, and ec2-user are
defaults). To use two different users on proxy jump
try --user user1/user2.
--profile PROFILE Use a specific profile from your credentials file.
--region REGION AWS region (User default if none is provided).
-i KEY_PATH, --key-path KEY_PATH
Absolute key path, overrides, --keys.
-c COMMAND, --command COMMAND
Translates to 'ssh -tt <user>@<ip> <command>'.
-r REMOTE_HOST, --remote-host REMOTE_HOST
Open a tunnel. Equivalent to 'ssh -L <local-
port>:<remote-host>:<remote-port> <selected-aws-host>'.
-p REMOTE_PORT, --remote-port REMOTE_PORT
Port to use on the remote host (default is 5432).
-l LOCAL_PORT, --local-port LOCAL_PORT
Port to use on the local host. Get overwritten by
remote port if not defined.
--keys KEYS Directory of the private keys (~/.ssh by default).
--timeout TIMEOUT SSH connection timeout.
--console-output, -o Display the instance console out before logging in.
--version, -v Returns awssh's version.
--verbose, -V Prints instance details, login details, as well as MFA
details.
MFA:
If MFA is required, provide both '--serial-number' and '--token-code'.
Credentials are saved under [mfa] profile for valid use until expiration.
--serial-number SERIAL_NUMBER
The identification number of the MFA device that is
associated with the IAM user. Specify this value if
the IAM user has a policy that requires MFA
authentication. You can find the device for an IAM
user viewing the user's security credentials.
--token-code TOKEN_CODE
The value provided by the MFA device, if MFA is
required. If any policy requires the IAM user to
submit an MFA code, specify this value. If MFA
authentication is required, the user must provide a
code when requesting a set of temporary security
credentials. A user who fails to provide the code
receives an "access denied" response when requesting
resources that require MFA authentication.
Examples
➜ ~ awssh
EC2 instances in default region:
Name Public IP Private IP Zone Key Name
1 - grafana None 10.120.1.57 us-east-2a ops-production
2 - rev-proxy 3.210.105.22 10.120.1.123 us-east-2a ops-production
3 - bastion-host 18.18.68.15 10.120.1.119 us-east-2a captain_070384
4 - Agent None 10.120.1.40 us-east-2a tsubasa_041381
5 - Chef 18.221.189.21 10.120.0.8 us-east-2a tsubasa_041381
6 - Core-1 None 10.120.1.46 us-east-2a tsubasa_041381
7 - Core-2 None 10.120.2.23 us-east-2b tsubasa_041381
8 - Kubemaster-1 None 10.120.1.24 us-east-2a tsubasa_041381
9 - Kubemaster-2 None 10.120.2.39 us-east-2b tsubasa_041381
10 - Kubeworker-1 None 10.120.1.20 us-east-2a tsubasa_041381
11 - Kubeworker-2 None 10.120.2.54 us-east-2b tsubasa_041381
12 - LB-1 18.66.14.12 10.120.1.122 us-east-2a tsubasa_041381
13 - LB-2 18.17.180.34 10.120.2.83 us-east-2b tsubasa_041381
14 - MongoDB-1 None 10.120.1.61 us-east-2a tsubasa_041381
15 - MongoDB-2 None 10.120.2.48 us-east-2b tsubasa_041381
16 - MongoDB-3 None 10.120.3.26 us-east-2c tsubasa_041381
17 - umqtt-docker-private None 10.120.1.37 us-east-2a captain_041381
18 - umqtt-docker-public None 10.120.1.60 us-east-2a captain_041381
Enter server number: 13 9
Connecting to Kubemaster-2 via LB-2:
Trying with user "centos".
Command: ssh-add ~/.ssh/tsubasa_041381.pem; ssh -A -o ConnectTimeout=5 ConnectTimeout=5 -J centos@18.17.180.34 centos@10.120.3.34
Identity added: ~/.ssh/tsubasa_041381.pem (~/.ssh/tsubasa_041381.pem)
Last login: Wed Sep 25 15:30:11 2019 from lb02
[centos@kubemaster03 ~]$
➜ ~ awssh --user ec2-user/admin
EC2 instances in default region:
Name Public IP Private IP Zone Key Name
1 - grafana None 10.120.1.57 us-east-2a ops-production
2 - rev-proxy 3.210.105.22 10.120.1.123 us-east-2a ops-production
3 - bastion-host 18.18.68.15 10.120.1.119 us-east-2a captain_070384
4 - Agent None 10.120.1.40 us-east-2a tsubasa_041381
5 - Chef 18.221.189.21 10.120.0.8 us-east-2a tsubasa_041381
6 - Core-1 None 10.120.1.46 us-east-2a tsubasa_041381
7 - Core-2 None 10.120.2.23 us-east-2b tsubasa_041381
8 - Kubemaster-1 None 10.120.1.24 us-east-2a tsubasa_041381
9 - Kubemaster-2 None 10.120.2.39 us-east-2b tsubasa_041381
10 - Kubeworker-1 None 10.120.1.20 us-east-2a tsubasa_041381
11 - Kubeworker-2 None 10.120.2.54 us-east-2b tsubasa_041381
12 - LB-1 18.66.14.12 10.120.1.122 us-east-2a tsubasa_041381
13 - LB-2 18.17.180.34 10.120.2.83 us-east-2b tsubasa_041381
14 - MongoDB-1 None 10.120.1.61 us-east-2a tsubasa_041381
15 - MongoDB-2 None 10.120.2.48 us-east-2b tsubasa_041381
16 - MongoDB-3 None 10.120.3.26 us-east-2c tsubasa_041381
17 - umqtt-docker-private None 10.120.1.37 us-east-2a captain_041381
18 - umqtt-docker-public None 10.120.1.60 us-east-2a captain_041381
Enter server number: 13 9
Connecting to Kubemaster-2 via LB-2:
Trying with user "ec2-user/admin".
Command: ssh-add ~/.ssh/tsubasa_041381.pem; ssh -A -o ConnectTimeout=5 ConnectTimeout=5 -J ec2-user@18.17.180.34 admin@10.120.3.34
Identity added: ~/.ssh/tsubasa_041381.pem (~/.ssh/tsubasa_041381.pem)
Last login: Wed Sep 25 15:30:11 2019 from lb02
[admin@kubemaster03 ~]$
➜ ~ awssh --profile prod-acc-2 --region us-east-2 'rev-proxy' -c top --users fduran
EC2 instances in us-east-2 region:
Name Public IP Private IP Zone Key Name
1 - rev-proxy 3.210.105.22 10.120.1.123 us-east-2a ops-production
Found one running instance and connecting to it...
Connecting to: rev-proxy
Trying with user "fduran".
top - 13:11:39 up 25 days, 23:37, 1 user, load average: 0.00, 0.00, 0.00
Tasks: 102 total, 1 running, 65 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.0 us, 0.3 sy, 0.0 ni, 99.7 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 1007644 total, 204248 free, 186744 used, 616652 buff/cache
KiB Swap: 0 total, 0 free, 0 used. 631780 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
860 root 20 0 658992 18576 2420 S 0.3 1.8 6:43.00 containerd
863 root 20 0 734948 35576 4364 S 0.3 3.5 8:59.34 dockerd
1 root 20 0 225432 8968 6456 S 0.0 0.9 0:14.82 systemd
2 root 20 0 0 0 0 S 0.0 0.0 0:00.00 kthreadd
4 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 kworker/0:0H
6 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 mm_percpu_wq
7 root 20 0 0 0 0 S 0.0 0.0 0:03.88 ksoftirqd/0
8 root 20 0 0 0 0 I 0.0 0.0 0:04.65 rcu_sched
9 root 20 0 0 0 0 I 0.0 0.0 0:00.00 rcu_bh
10 root rt 0 0 0 0 S 0.0 0.0 0:00.00 migration/0
11 root rt 0 0 0 0 S 0.0 0.0 0:05.26 watchdog/0
12 root 20 0 0 0 0 S 0.0 0.0 0:00.00 cpuhp/0
➜ ~ awssh --users ubuntu centos -c 'df -h' --verbose
EC2 instances in default region:
Name Public IP Private IP Zone Key Name
1 - grafana None 10.120.1.57 us-east-2a ops-production
2 - rev-proxy 3.210.105.22 10.120.1.123 us-east-2a ops-production
3 - bastion-host 18.18.68.15 10.120.1.119 us-east-2a captain_070384
4 - Agent None 10.120.1.40 us-east-2a tsubasa_041381
5 - Chef 18.221.189.21 10.120.0.8 us-east-2a tsubasa_041381
6 - Core-1 None 10.120.1.46 us-east-2a tsubasa_041381
7 - Core-2 None 10.120.2.23 us-east-2b tsubasa_041381
8 - Kubemaster-1 None 10.120.1.24 us-east-2a tsubasa_041381
9 - Kubemaster-2 None 10.120.2.39 us-east-2b tsubasa_041381
10 - Kubeworker-1 None 10.120.1.20 us-east-2a tsubasa_041381
11 - Kubeworker-2 None 10.120.2.54 us-east-2b tsubasa_041381
12 - LB-1 18.66.14.12 10.120.1.122 us-east-2a tsubasa_041381
13 - LB-2 18.17.180.34 10.120.2.83 us-east-2b tsubasa_041381
14 - MongoDB-1 None 10.120.1.61 us-east-2a tsubasa_041381
15 - MongoDB-2 None 10.120.2.48 us-east-2b tsubasa_041381
16 - MongoDB-3 None 10.120.3.26 us-east-2c tsubasa_041381
17 - umqtt-docker-private None 10.120.1.37 us-east-2a captain_041381
18 - umqtt-docker-public None 10.120.1.60 us-east-2a captain_041381
Enter server number: 1
Connecting to grafana via rev-proxy:
{'availability_zone': 'us-east-2a',
'block devices': None,
'id': 'i-0e3223781',
'key_name': 'ops-production',
'launch time': '2018-12-02T18:20:44+00:00',
'name': 'grafana',
'private_ip_address': '10.120.1.57',
'public_ip_address': 'None',
'security_groups': [{'GroupId': 'sg-09fcac7',
'GroupName': 'prometheus-grafana-alertmanager'}],
'state': 'running',
'type': 't2.medium'}
Trying with user "ubuntu".
Command: ssh-add ~/.ssh/ops-production.pem; ssh -A -o ConnectTimeout=5 -J ubuntu@3.210.105.22 ubuntu@10.120.1.57 -t 'df -h'
Identity added: ~/.ssh/ops-production.pem (~/.ssh/ops-production.pem)
Filesystem Size Used Avail Use% Mounted on
udev 2.0G 0 2.0G 0% /dev
tmpfs 395M 1.1M 394M 1% /run
/dev/xvda1 97G 8.7G 89G 9% /
tmpfs 2.0G 0 2.0G 0% /dev/shm
tmpfs 5.0M 0 5.0M 0% /run/lock
tmpfs 2.0G 0 2.0G 0% /sys/fs/cgroup
/dev/loop1 18M 18M 0 100% /snap/amazon-ssm-agent/1455
/dev/loop4 89M 89M 0 100% /snap/core/7396
/dev/loop2 90M 90M 0 100% /snap/core/7713
/dev/loop3 18M 18M 0 100% /snap/amazon-ssm-agent/1480
tmpfs 395M 0 395M 0% /run/user/1000
Connection to 10.120.1.57 closed.
➜ ~ awssh --serial-number arn:aws:iam::123456789000:mfa/fduran --token-code 123654 --verbose
MFA:
{'Credentials': {'AccessKeyId': 'ACCSEKKKEYID123456',
'Expiration': datetime.datetime(2019, 10, 2, 2, 1, 13, tzinfo=tzutc()),
'SecretAccessKey': 'ASDFASasdfASAFsDFASafrETWERTQWHGDFGADF',
'SessionToken': 'fASDFASDfasdfasdf563453ASDFASGSGHDFHJFGJKfgdhASFGASDFGHSDFGH4537354'},
'ResponseMetadata': {'HTTPHeaders': {'content-length': '804',
'content-type': 'text/xml',
'date': 'Tue, 01 Oct 2019 14:01:12 GMT',
'x-amzn-requestid': 'ed8e874c-e453-11e9-a7fe-7asdfasdf9c59'},
'HTTPStatusCode': 200,
'RequestId': 'edasdf-e443-ase9-a7fe-79asdfgadfgadsf59',
'RetryAttempts': 0}}
EC2 instances in default region:
Name Public IP Private IP Zone Key Name
1 - grafana None 10.120.1.57 us-east-2a ops-production
2 - rev-proxy 3.210.105.22 10.120.1.123 us-east-2a ops-production
3 - bastion-host 18.18.68.15 10.120.1.119 us-east-2a captain_070384
4 - Agent None 10.120.1.40 us-east-2a tsubasa_041381
5 - Chef 18.221.189.21 10.120.0.8 us-east-2a tsubasa_041381
6 - Core-1 None 10.120.1.46 us-east-2a tsubasa_041381
7 - Core-2 None 10.120.2.23 us-east-2b tsubasa_041381
8 - Kubemaster-1 None 10.120.1.24 us-east-2a tsubasa_041381
9 - Kubemaster-2 None 10.120.2.39 us-east-2b tsubasa_041381
10 - Kubeworker-1 None 10.120.1.20 us-east-2a tsubasa_041381
11 - Kubeworker-2 None 10.120.2.54 us-east-2b tsubasa_041381
12 - LB-1 18.66.14.12 10.120.1.122 us-east-2a tsubasa_041381
13 - LB-2 18.17.180.34 10.120.2.83 us-east-2b tsubasa_041381
14 - MongoDB-1 None 10.120.1.61 us-east-2a tsubasa_041381
15 - MongoDB-2 None 10.120.2.48 us-east-2b tsubasa_041381
16 - MongoDB-3 None 10.120.3.26 us-east-2c tsubasa_041381
17 - umqtt-docker-private None 10.120.1.37 us-east-2a captain_041381
18 - umqtt-docker-public None 10.120.1.60 us-east-2a captain_041381
Enter server number: 13 16
Connecting to MongoDB-3 via LB-2:
{'availability_zone': 'us-east-2c',
'block devices': None,
'id': 'i-0929501fe',
'key_name': 'tsubasa_041381',
'launch time': '2019-09-03T11:44:43+00:00',
'name': 'MongoDB-3',
'private_ip_address': '10.120.3.26',
'public_ip_address': 'None',
'security_groups': [{'GroupId': 'sg-fgdaas93',
'GroupName': 'InternalAccess'}],
'state': 'running',
'type': 'c4.4xlarge'}
Trying with user "centos".
Command: ssh-add ~/.ssh/captain_041381.pem; ssh -A -o ConnectTimeout=5 -J centos@18.17.180.34 centos@10.120.3.26
Identity added: ~/.ssh/captain_041381.pem (~/.ssh/captain_041381.pem)
Last login: Tue Oct 1 14:00:48 2019 from lb02
[centos@mongo03 ~]$exit
logout
Connection to 10.120.3.26 closed.
➜ cat ~/.aws/credentials
[mfa]
aws_access_key_id = ACCSEKKKEYID123456
aws_secret_access_key = ASDFASasdfASAFsDFASafrETWERTQWHGDFGADF
aws_session_token = fASDFASDfasdfasdf563453ASDFASGSGHDFHJFGJKfgdhASFGASDFGHSDFGH4537354
.
➜ ~ echo '12 6' | awssh --profile mfa -c top
Connecting to Core-1 via LB-1:
Trying with user "centos".
Command: ssh-add ~/.ssh/tsubasa_041381.pem; ssh -A -o ConnectTimeout=5 -J centos@3.17.18.234 centos@10.120.1.46 -tt 'top'
top - 16:24:22 up 12 days, 15:49, 1 user, load average: 0.06, 0.16, 0.16
Tasks: 167 total, 1 running, 166 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.9 us, 0.3 sy, 0.0 ni, 98.7 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 15233668 total, 3121344 free, 6509484 used, 5602840 buff/cache
KiB Swap: 0 total, 0 free, 0 used. 7574488 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1672 karaf 20 0 12.8g 5.1g 26636 S 6.0 35.1 4171:19 java
1431 root 20 0 1089212 587692 8160 S 5.3 3.9 2594:38 mongos
956 dd-agent 20 0 2323188 83100 28836 S 1.7 0.5 103:33.76 agent
4289 root 20 0 1567988 64672 27532 S 1.3 0.4 295:57.36 kubelet
958 dd-agent 20 0 51704 25824 11444 S 0.7 0.2 46:11.36 process-ag+
1229 node_ex+ 20 0 703708 17932 5344 S 0.7 0.1 65:57.27 node_expor+
1215 root 20 0 602928 25312 22980 S 0.3 0.2 5:53.78 rsyslogd
1414 root 20 0 1653196 49504 14864 S 0.3 0.3 80:01.12 dockerd-cu+
1481 root 20 0 928880 19244 5564 S 0.3 0.1 13:08.66 docker-con+
22365 root 20 0 0 0 0 S 0.3 0.0 0:19.97 kworker/0:0
1 root 20 0 191384 4392 2632 S 0.0 0.0 3:51.29 systemd
2 root 20 0 0 0 0 S 0.0 0.0 0:00.13 kthreadd
3 root 20 0 0 0 0 S 0.0 0.0 0:02.29 ksoftirqd/0
5 root 0 -20 0 0 0 S 0.0 0.0 0:00.00 kworker/0:+
7 root rt 0 0 0 0 S 0.0 0.0 0:00.45 migration/0
8 root 20 0 0 0 0 S 0.0 0.0 0:00.00 rcu_bh
9 root 20 0 0 0 0 S 0.0 0.0 17:23.14 rcu_sched
pypi.org