From 1f87b484c28ef8036fcda4f73de99a530a3622ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Claro?= Date: Tue, 15 Oct 2024 18:49:42 +0100 Subject: [PATCH] ssm: add AWS System Manager support (connect to non-EC2 instances using its Name tag) (#24) --- CHANGELOG.md | 4 ++++ README.md | 17 ++++++++++------- aws-connect | 47 ++++++++++++++++++++++++++++++++++++++++------- package.json | 2 +- 4 files changed, 55 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ef219f..43e1b84 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # CHANGELOG +## [1.0.24] + +- @andreclaro add AWS System Manager support to connect to non-EC2 instances using their Name tag (use of `-m` flag) + ## [1.0.23] - @phamtriduy Support remote tunnel host with AWS-StartPortForwardingSessionToRemoteHost document (via use of `-i` flag) diff --git a/README.md b/README.md index bbe92d8..75aa8e9 100644 --- a/README.md +++ b/README.md @@ -16,22 +16,25 @@ Choose one of the following options: ```bash Usage: -/usr/local/bin/aws-connect [-a ssh|tunnel|document] [-d ] [-c ] [-g ] [-n |-t ] [-r ] [-p ] [-o ] [-x ] [-l] [-s] [-h] [-v] +aws-connect [-a ssh|tunnel|document] [-i ] [-d ] [-c ] [-g ] [-n |-t |-m ] [-r ] [-p ] [-o ] [-x ] [-l] [-s] [-h] [-v] -a Connect interactive session (ssh), establish tunnel (tunnel), or run an ssm document (document) on an instance (default: ssh) + -i Specify the name of the remote host name to tunnel to. Only needed if running ssm tunnel action (default: localhost) + -d Specify the name of the ssm document to run. Only needed if running ssm document action. + -w Values for the ssm document arguments (Optional) + -g The location in aws ssm parameter store of the github token to use (Optional) + -c The name of the cloudwatch group to store logs in. Required for running documents, defaults to aws-connect + -l Flag if the command is going to be long running(8hrs +) -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' + -m Specify the SSM instance name -r AWS region (default: us-east-1) -p AWS profile (default: none) - -o Local ssh tunnel port (only applicable in tunnel mode; default: 9999) + -f Remote tunnel port (only applicable in tunnel mode); Defaults to 22 + -o Local tunnel port (only applicable in tunnel mode; default: 9999) -x override Name tag and connect direct to given instance ID -s Pick a specific instance ID -h Display this help - -d Specify the name of the ssm document to run. - -w Values for the ssm document arguments (Optional) - -g The location in aws ssm parameter store of the github token to use (Optional) - -c The name of the cloudwatch group to store logs in. Required for running documents, defaults to aws-connect - -l Flag if the command is going to be long running(8hrs +) -v Display version ``` diff --git a/aws-connect b/aws-connect index 627d266..5be9159 100755 --- a/aws-connect +++ b/aws-connect @@ -21,7 +21,7 @@ version() { usage() { echo "Usage:" echo "" - echo "$programname [-a ssh|tunnel|document] [-i ] [-d ] [-c ] [-g ] [-n |-t ] [-r ] [-p ] [-o ] [-x ] [-l] [-s] [-h] [-v]" + echo "$programname [-a ssh|tunnel|document] [-i ] [-d ] [-c ] [-g ] [-n |-t |-m ] [-r ] [-p ] [-o ] [-x ] [-l] [-s] [-h] [-v]" echo "" echo " -a Connect interactive session (ssh), establish tunnel (tunnel), or run an ssm document (document) on an instance (default: ssh)" echo " -i Specify the name of the remote host name to tunnel to. Only needed if running ssm tunnel action (default: localhost)" @@ -32,6 +32,7 @@ usage() { echo " -l Flag if the command is going to be long running(8hrs +)" 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 " -m Specify the SSM instance name" echo " -r AWS region (default: us-east-1)" echo " -p AWS profile (default: none)" echo " -f Remote tunnel port (only applicable in tunnel mode); Defaults to 22" @@ -71,8 +72,23 @@ get_instances_by_tag() { echo "${instance_ids_list}" } +get_instance_by_ssm_name() { + name="${1// /}" + region=$2 + profile=$3 + + instance_id=$(aws ssm describe-instance-information \ + --filters "Key=tag:Name,Values=${name}" \ + --query 'InstanceInformationList[*].{Instance:InstanceId,Name:Name}' \ + --output json \ + --region "${region}" \ + --profile "${profile}" | jq -r '.[0].Instance') + + echo "${instance_id}" +} + # get the options and set flags -while getopts "a:d:c:f:g:i:w:n:t:r:p:o:x:shvl" OPTION; do +while getopts "a:d:c:f:g:i:w:n:m:t:r:p:o:x:shvl" OPTION; do case $OPTION in v) version @@ -97,6 +113,9 @@ while getopts "a:d:c:f:g:i:w:n:t:r:p:o:x:shvl" OPTION; do t) tag_value=$OPTARG ;; + m) + ssm_name=$OPTARG + ;; x) instance_id=$OPTARG ;; @@ -166,7 +185,7 @@ if [ ! -e /usr/local/bin/session-manager-plugin ] && [ ! session-manager-plugin fi # Check for mandatory args -if [ -z "${tag_value}" ] && [ -z "${instance_id}" ]; then +if [ -z "${tag_value}" ] && [ -z "${instance_id}" ] && [ -z "${ssm_name}" ]; then usage exit 1 fi @@ -190,11 +209,25 @@ if [ -z "${aws_region:+x}" ]; then fi fi -# If instance ID is set via -x, use it -# If both tag and instance ID are set, use instance id -if [ -z "${instance_id}" ]; then - # Get the list of instances +# Only one of instance ID or ssm instance name can be set +if [ -n "${instance_id}" ] && [ -n "${ssm_name}" ]; then + echo "Cannot specify both instance ID and SSM instance name" + exit 1 +fi + +if [ -n "${instance_id}" ]; then + echo "Instance ID: ${instance_id}" instance_ids=$(get_instances_by_tag "${tag_value}" "${aws_region}" "${aws_profile}") +fi + +if [ -n "${ssm_name}" ]; then + echo "SSM instance name: ${ssm_name}" + instance_id=$(get_instance_by_ssm_name "${ssm_name}" "${aws_region}" "${aws_profile}") +fi + +# If instance ID is set via -x, or ssm instance name via -m, use it +# If both tag and instance ID are set, use instance id +if [ -z "${instance_id}" ] && [ -z "${ssm_name}" ]; then if [ -z "${instance_ids}" ]; then echo "No instances available with tag ${tag_value} in region ${aws_region}" diff --git a/package.json b/package.json index 420fcbb..a3cc22a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "aws-connect", - "version": "0.0.1", + "version": "1.0.24", "description": "Wrapper script around AWS session manager to establish remote shell connections or SSH tunnels", "scripts": ["aws-connect"], "global": "true",