-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathec2ssh
More file actions
executable file
·207 lines (171 loc) · 5.74 KB
/
ec2ssh
File metadata and controls
executable file
·207 lines (171 loc) · 5.74 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
#!/bin/bash
# Connect to ec2 instances using either InstanceId, Name tag or Ip address
# Usage:
# - ec2ssh i-123124123123
# - ec2ssh [-n 2] name_tag
# - ec2ssh IP
username=ec2-user
keypath=~/.ssh/aws
ssh_opts=""
# Use awless or awscli (auto tries awless, and if not, awscli)
backend=auto
ssh_strict=false
# Route through VPN
add_route=false
route='$ip dev tun0 scope link'
usage(){
cat << EOF
Usage:
ec2ssh [options] host [command]
Options:
-l List only, but do not run ssh
-b backend Use backend to query aws [awscli or awless] (Default: $backend)
-r region AWS region
-u username username (Default: $username)
-h hostnum When using a pattern, connect to this number of host on the list
-s true/false If true, use ssh strict hostkey mode (Default: $ssh_strict)
-d debug. Just echo the ssh command
-q quiet. Do not print ec2ssh messages
Examples:
ec2ssh i-123124123123
ec2ssh -n 2 -s false name_tag
ec2ssh -u ubuntu i-123412332 ls /
EOF
exit 1
}
add_route(){
export ip=$1
local ip_route="$(echo ${route} | envsubst) "
ip route | grep -qx "$ip_route" || { echo "Adding route to $ip" >&2; sudo ip route add $ip_route; }
}
backend_auto(){
command -v awless > /dev/null && echo -n awless && return
command -v aws > /dev/null && echo -n awscli && return
echo "ERROR. No awless or aws commands found in path. Aborting"
exit 1
}
while getopts "lqd:p:r:u:n:s:" o; do
case "${o}" in
l) listonly=true ;;
d) debug="echo" ;;
b) backend=${OPTARG} ;;
p) profile=${OPTARG} ;;
r) region=${OPTARG} ;;
u) username=${OPTARG} ;;
n) hostnum=$((${OPTARG}-1)) ;;
s) ssh_strict=${OPTARG} ;;
q) quiet=true ;;
*) usage ;;
esac
done
shift $((OPTIND-1))
host=$1; shift
# Resolve auto backend
[ "$backend" == "auto" ] && backend=$(backend_auto)
# Generic functions
get_running_instances(){ ${backend}_get_running_instances $@; }
filter_by(){ ${backend}_filter_by $@; }
get_by_id(){ ${backend}_get_by_id $@; }
get_by_publicip(){ ${backend}_get_by_publicip $@; }
get_by_privateip(){ ${backend}_get_by_privateip $@; }
get_instance_id_by_name(){ ${backend}_get_instance_id_by_name $@; }
list_instances_by_name(){ echo "Instance list"; ${backend}_list_instances_by_name $@ | cat -n; echo ""; }
# awscli stuff
awscli_args(){
args=""
[ "$profile" ] && args="$args --profile $profile"
[ "$region" ] && args="$args --region $region"
echo -n "$args"
}
awscli="aws $(awscli_args)"
awscli_get_running_instances(){
$awscli ec2 describe-instances | jq -r '.Reservations[].Instances[] | select(.State.Name=="running")'
}
awscli_filter_by(){
field=$1
value=$2
echo "$instances" | jq -r 'select(.'$field'=="'$value'") | .PublicIpAddress, .KeyName, (.Tags[] | select(.Key=="Name") | .Value), .InstanceId' | xargs
}
awscli_get_by_id(){
awscli_filter_by InstanceId $1
}
awscli_get_by_publicip(){
awscli_filter_by PublicIpAddress $1
}
awscli_get_by_privateip(){
awscli_filter_by PrivateIpAddress $1
}
awscli_list_instances_by_name(){
name=$1
echo "$instances" | jq -r 'select((.Tags[]|select(.Key=="Name")|.Value) | contains("'$name'")) | "\(.InstanceId) \((.Tags[] | select(.Key=="Name") | .Value)) \(.PublicIpAddress)"' 2>/dev/null
}
awscli_get_instance_id_by_name(){
name=$1
num=${2:-0}
echo "$instances" | jq 'select((.Tags[]|select(.Key=="Name")|.Value) | contains("'$name'"))' 2>/dev/null | jq -s . | jq -r .[$num].InstanceId
}
# awless stuff
awless_args(){
args="--format=json"
[ "$profile" ] && args="$args -p $profile"
[ "$region" ] && args="$args -r $region"
echo -n "$args"
}
awless="awless $(awless_args)"
awless_get_running_instances(){
$awless list instances | jq '.[] | select(.State=="running")'
}
awless_filter_by(){
field=$1
value=$2
echo "$instances" | jq -r 'select(.'$field'=="'$value'") | .PublicIP, .KeyPair, .Name, .ID' | xargs
}
awless_get_by_id(){
awless_filter_by ID $1
}
awless_get_by_publicip(){
awless_filter_by PublicIP $1
}
awless_get_by_privateip(){
awless_filter_by PrivateIP $1
}
awless_list_instances_by_name(){
name=$1
echo "$instances" | jq -r 'select(.[] | contains("'$name'")) | "\(.ID) \(.Name) \(.PublicIP)"' 2>/dev/null
}
awless_get_instance_id_by_name(){
name=$1
num=${2:-0}
echo "$instances" | jq 'select(.[] | contains("'$name'"))' 2>/dev/null | jq -s . | jq -r .[$num].ID
}
# Common code
instances=$(get_running_instances)
# This is a instance ID
if echo $host | grep -e "^i-" -q; then
read -r i_ip i_key i_name i_id <<<$(get_by_id $host)
# Or an IP address
elif echo $host | grep -P "^([0-9]+\.){3}[0-9]+" -q; then
read -r i_ip i_key i_name i_id <<<$(get_by_publicip $host)
[ "$i_ip" ] || read -r i_ip i_key i_name i_id <<<$(get_by_privateip $host)
# or a DNS name that resolves
elif [ "$(dig +short $host)" ]; then
hostIP=$(dig +short $host)
read -r i_ip i_key i_name i_id <<<$(get_by_publicip $hostIP)
# Everything else should be an instance name
elif [ "$listonly" == "true" ]; then
list_instances_by_name $host
exit 0
else
desired_num_instance_id=$(get_instance_id_by_name $host $hostnum)
read -r i_ip i_key i_name i_id <<<$(get_by_id $desired_num_instance_id)
fi
# Disable strict host key checking if needed
[ "$ssh_strict" == "false" ] && ssh_opts="$ssh_opts -o StrictHostKeyChecking=false"
if [ "$i_ip" ]; then
[ "$quiet" != "true" ] && echo -e "ec2ssh to $i_id $i_name $i_ip\n" >&2
[ "$listonly" == "true" ] && exit 0
[ "$add_route" == "true" ] && add_route $i_ip
$debug ssh $ssh_opts -i $keypath/$i_key $username@$i_ip "$@"
else
echo "ERROR. Host '$host' not found"
fi