Skip to content

Instantly share code, notes, and snippets.

@solidsnack
Last active November 27, 2019 11:49
Show Gist options
  • Save solidsnack/d1ba54ac43d79b61f749863cfa3354ab to your computer and use it in GitHub Desktop.
Save solidsnack/d1ba54ac43d79b61f749863cfa3354ab to your computer and use it in GitHub Desktop.
SSH to servers that have SRV records
#!/bin/bash
set -o errexit -o nounset -o pipefail
function --help {
cat <<USAGE
USAGE: ssh-srv <DNS name> <SSH options and args>*
Allows SSH to nodes referenced by SRV records. The SRV records can be
referenced in a "plain style":
service.example.com
or a "full style":
_x._y.service.example.com
If referenced in "plain style", \`ssh-srv\` searches for:
_*._*.service.example.com
The hostnames are sorted and deduplicated and then each host is connected to
in sequence.
USAGE
}
tmp=
function main {
local failures=() names=() dns="$1" ; shift
names=( $(lookup "$dns") )
if [[ ! -t 0 ]]
then buffer_cmd_stream
fi
if [[ ${#names[@]} -le 0 ]]
then
echo "No hosts under: $dns" >&2
exit 2
fi
for hostname in "${names[@]}"
do
if connect "$hostname" "$@"
then :
else
echo "Non-zero exit ($?) on: $hostname" >&2
failures+=( "$hostname" )
fi
done
if [[ ${#failures[@]} -gt 0 ]]
then echo "Non-zero exits: ${failures[@]}" >&2
fi
exit ${#failures[@]}
}
function lookup {
local dns="$1"
case "$dns" in
_*._*.*) : ;; # Matches _http._tcp and other SRV specifiers
*) dns="_*._*.$dns" ;;
esac
dig +short "$dns" SRV | cut -d' ' -f4 | sort | uniq | sed 's/[.]$//'
}
function connect {
if [[ ${#tmp} -gt 0 ]]
then ssh "$@" < "$tmp"
else ssh "$@"
fi
}
function buffer_cmd_stream {
tmp="/tmp/ssh-srv~$(whoami)/$$.$(token)"
mkdir -p "$(dirname "$tmp")"
trap 'rm -rf $tmp' EXIT
cat > "$tmp"
}
function token {
printf '%04x' "$RANDOM" "$RANDOM"
}
case "${1:-}" in
-h|--help) --help ;;
*) main "$@" ;;
esac
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment