Skip to content

Commit

Permalink
Merge pull request #1 from opsani/master
Browse files Browse the repository at this point in the history
Support for specifying an instance by tag
  • Loading branch information
dnorth98 authored May 1, 2020
2 parents 6929f41 + adfad64 commit 683237d
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 16 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# CHANGELOG

## [1.0.10]

- Support for specifying an instance by tag

## [1.0.9]

- Update readme
Expand Down
14 changes: 12 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@ Wrapper script around AWS session manager to establish remote shell connections
```bash
Usage:

/usr/local/bin/aws-connect -a ssh|tunnel -n <instance name> [-r region] [-p profile name] [-o port] [-x instance id] [-s] [-h] [-v]
/usr/local/bin/aws-connect -a ssh|tunnel [-n <instance name>|-t <instance tag>] [-r region] [-p profile name] [-o port] [-x instance id] [-s] [-h] [-v]

-a Connect interactive session or establish ssh tunnel (default: ssh)
-n Value for the Name tag of an EC2 instance
-t Specify a tag instead of a name. The tag can be 'key' or 'key=value'
-r AWS region (default: us-east-1)
-p AWS profile (default: none)
-o Local ssh tunnel port (only applicable in tunnel mode; default: 9999)
Expand All @@ -34,7 +35,7 @@ Usage:

NOTE: If there are multiple instances with the same tag, one is chosen

2. Establish an interactive shell session with a specfic instance tagged with a Name of my-app in the us-east-2 region using the AWS CLI profile
2. Establish an interactive shell session with a specific instance tagged with a Name of my-app in the us-east-2 region using the AWS CLI profile

`aws-connect -a ssh -n my-app -r us-east-2 -p staging -s`

Expand All @@ -45,3 +46,12 @@ In this case, a list of instance IDs will be provided and one can be chosen to c
`aws-connect -a tunnel -n my-app -r us-east-2 -p staging -o 8888`

The SSH tunnel can then be used for things like connecting to an RDS database that the instance may have access to. Just point your DB client to localhost, port 8888 for the SSH forwarding.

4. Establish an interactive shell session with a specific instance with a tag CLUSTER (will list all instances with that tag and ask for input)

`aws-connect -s -t CLUSTER`

4. Establish an interactive shell session with a specific instance with a tag CLUSTER=prod (will list all instances with that tag and ask for input)

`aws-connect -s -t CLUSTER=prod`

54 changes: 40 additions & 14 deletions aws-connect
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# Wrapper around AWS session manager for instance access and SSH tunnels

programname=$0
version=1.0.9
version=1.0.10

# Defaults
action=ssh
Expand All @@ -19,10 +19,11 @@ version() {
usage() {
echo "Usage:"
echo ""
echo "$programname -a ssh|tunnel -n <instance name> [-r region] [-p profile name] [-o port] [-x instance id] [-s] [-h] [-v]"
echo "$programname -a ssh|tunnel [-n <instance name>|-t <instance tag>] [-r region] [-p profile name] [-o port] [-x instance id] [-s] [-h] [-v]"
echo ""
echo " -a Connect interactive session or establish ssh tunnel (default: ssh)"
echo " -n Value for the Name tag of an EC2 instance"
echo " -t Specify a tag instead of a name. The tag can be 'key' or 'key=value'"
echo " -r AWS region (default: us-east-1)"
echo " -p AWS profile (default: none)"
echo " -o Local ssh tunnel port (only applicable in tunnel mode; default: 9999)"
Expand All @@ -37,23 +38,32 @@ compareable_version() {
echo "$@" | awk -F. '{ printf("%d%03d%03d%03d\n", $1,$2,$3,$4); }';
}

get_instances_by_name_tag() {
name_tag=$1
get_instances_by_tag() {
tag_key=${1%%=*}
tag_value=${1#*=}
region=$2
profile=$3

if [ "$tag_value" == "$1" ]; then
# No tag value specified
tag_filter="Name=tag-key,Values=${tag_key}"
else
tag_filter="Name=tag:${tag_key},Values=${tag_value}"
fi

instance_ids_list=$(aws ec2 describe-instances \
--filters "Name=tag:Name,Values=${name_tag}" "Name=instance-state-name,Values=running" \
--query 'Reservations[].Instances[].InstanceId' \
--filters "$tag_filter" "Name=instance-state-name,Values=running" \
--query 'Reservations[*].Instances[*].{Instance:InstanceId,Name:Tags[?Key==`Name`]|[0].Value}' \
--output text \
--region "${region}" \
--profile "${profile}")

# Returns a space delimitted list of instance_id,Name
echo "${instance_ids_list}"
}

# get the options and set flags
while getopts "a:n:r:p:o:x:shv" OPTION; do
while getopts "a:n:t:r:p:o:x:shv" OPTION; do
case $OPTION in
v)
version
Expand All @@ -73,6 +83,9 @@ while getopts "a:n:r:p:o:x:shv" OPTION; do
aws_profile=$OPTARG
;;
n)
tag_value="Name=$OPTARG"
;;
t)
tag_value=$OPTARG
;;
x)
Expand Down Expand Up @@ -132,18 +145,29 @@ fi
# If both tag and instance ID are set, use instance id
if [ -z "${instance_id}" ]; then
# Get the list of instances
instance_ids=$(get_instances_by_name_tag "${tag_value}" "${aws_region}" "${aws_profile}")
instance_ids=$(get_instances_by_tag "${tag_value}" "${aws_region}" "${aws_profile}")

if [ -z "${instance_ids}" ]; then
echo "No instances available named ${tag_value} in region ${aws_region}"
echo "No instances available with tag ${tag_value} in region ${aws_region}"
else
# Parse instance id ouput
declare -a arr_instance_ids
declare -a arr_instance_names
i=1
while IFS= read -r line; do
arr_instance_ids[i]=$(sed -e 's/^\([^[:blank:]]\{1,\}\).*$/\1/' <<< "$line")
arr_instance_names[i]=$(sed -e 's/^\([^[:blank:]]\{1,\}[[:blank:]]\{1,\}\)//' <<< "$line")

i=$(( i + 1 ))
done <<< "$instance_ids"

if [ "${interactive_mode}" -eq 1 ]; then
echo "Select an instance to connect to"

inst_num=1
for instance in ${instance_ids}
for instance in ${arr_instance_ids[@]}
do
echo "${inst_num}) ${instance}"
echo "${inst_num}) ${arr_instance_ids[inst_num]} (${arr_instance_names[inst_num]})"
inst_num=$(( inst_num + 1 ))
done

Expand All @@ -159,17 +183,19 @@ if [ -z "${instance_id}" ]; then
exit 1
fi

instance_id=$(echo "${instance_ids}" | awk -v field_num="${choice_num}" '{print $field_num}')
instance_id=${arr_instance_ids[choice_num]}
instance_name=${arr_instance_names[choice_num]}
else
# We only need one instance
instance_id=$(echo "${instance_ids}" | cut -f1)
instance_id=${arr_instance_ids[1]}
instance_name=${arr_instance_names[1]}
fi
fi
fi

# SSH or tunnel
if [ "${action}" == "ssh" ]; then
echo "Establishing session manager connection to ${tag_value} (${instance_id})"
echo "Establishing session manager connection to ${instance_name} (${instance_id})"
aws ssm start-session \
--target "${instance_id}" \
--region "${aws_region}" \
Expand Down

0 comments on commit 683237d

Please sign in to comment.