Skip to content

Instantly share code, notes, and snippets.

@vitkin
Last active October 31, 2022 11:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vitkin/8c9269847276b9a4af45229b0ac2f57e to your computer and use it in GitHub Desktop.
Save vitkin/8c9269847276b9a4af45229b0ac2f57e to your computer and use it in GitHub Desktop.
AWS ECS Connect
#!/usr/bin/env bash
# shellcheck enable=require-variable-braces
set -e
while [ ${#} -ne 0 ]; do
case ${1} in
-c) ;&
--cluster)
CLUSTER="${2?'cluster: argument not set'}"
shift ;;
-s) ;&
--service)
SERVICE="${2?'service: argument not set'}"
shift ;;
-t) ;&
--task)
TASK="${2?'task: argument not set'}"
shift ;;
-C) ;&
--container)
CONTAINER="${2?'container: argument not set'}"
shift ;;
-T) ;&
--target)
TARGET="${2?'target: argument not set'}"
shift ;;
-L) ;&
--local-port)
LOCAL_PORT="${2?'local port: argument not set'}"
shift ;;
-P) ;&
--proxy-port)
PROXY_PORT="${2?'proxy port: argument not set'}"
shift ;;
-R) ;&
--run)
RUN="${2?'run: argument not set'}"
shift ;;
*)
break ;;
esac
shift
done
_RED=$'\e[0;31m'
_BLUE=$'\e[0;34m'
_NORMAL=$'\e[m'
set_param() {
eval "param=\"\${${1}}\""
if [ -z "${param}" ]; then
# shellcheck disable=2207
opts=( $( eval "aws ecs --output text --query ${2}" ) )
PS3="${_RED}Select a ${1}: ${_NORMAL}"
select opt in "${opts[@]}"; do
param="$(
awk -F'/' '{ print $NF }' <<< "${opt:-${opts[0]}}"
)"
break
done
fi
eval "${1}='${param}'"
echo "${_BLUE}${1}: ${param}${_NORMAL}"
}
set_param CLUSTER 'clusterArns list-clusters'
set_param SERVICE "serviceArns list-services --cluster ${CLUSTER}"
set_param TASK "taskArns list-tasks --cluster ${CLUSTER} --service-name ${SERVICE}"
set_param CONTAINER "'tasks[*].containers[*].name' describe-tasks --cluster ${CLUSTER} --tasks ${TASK}"
if [ -z "${TARGET}" ]; then
aws ecs execute-command \
--cluster "${CLUSTER}" \
--task "${TASK}" \
--container "${CONTAINER}" \
--interactive \
--command "${RUN:-sh}"
exit
fi
LOCAL_PORT="${LOCAL_PORT:-${TARGET/*:/}}"
PROXY_PORT="${PROXY_PORT:-$(( 65536 - ${TARGET/*:/} ))}"
aws ecs execute-command \
--cluster "${CLUSTER}" \
--task "${TASK}" \
--container "${CONTAINER}" \
--interactive \
--command "sh -c '[ -f /usr/bin/socat ] || \
( apt-get update && apt-get install -y socat ) || \
yum install -y socat || \
apk add socat'"
aws ecs execute-command \
--cluster "${CLUSTER}" \
--task "${TASK}" \
--container "${CONTAINER}" \
--interactive \
--command "socat TCP-LISTEN:${PROXY_PORT},fork TCP:${TARGET}" |
awk \
-F':' \
-v CLUSTER="${CLUSTER}" \
-v TASK="${TASK}" \
-v RUNTIME_ID="$(
aws ecs describe-tasks \
--cluster "${CLUSTER}" \
--tasks "${TASK}" \
--query "tasks[].containers[?name=='${CONTAINER}'].runtimeId" \
--output text
)" \
-v PARAMETERS="localPortNumber=${LOCAL_PORT},portNumber=${PROXY_PORT}" \
'
/SessionId/ {
gsub(/^ /, "", $2)
print $0
CMD = "\
trap \"aws ssm terminate-session --session-id " $2 "\" EXIT; \
trap \"exit\" INT TERM; \
aws ssm start-session \
--target ecs:" CLUSTER "_" TASK "_" RUNTIME_ID " \
--document-name AWS-StartPortForwardingSession \
--parameters " PARAMETERS " \
"
while ( CMD | getline LINE ) {
print LINE
if ( LINE ~ /Connection to destination port failed/ ) {
exit 1
}
}
}
'
# For getting details about the SSM document:
# aws ssm get-document --name AWS-StartPortForwardingSession --output text # --document-format YAML
# vim: set filetype=bash tabstop=2 foldmethod=marker expandtab:
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment