You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
DevOps-Bash-tools/bin/ssl_verify_cert_by_ip.sh

148 lines
3.5 KiB
Bash

#!/usr/bin/env bash
# vim:ts=4:sts=4:sw=4:et
#
# Author: Hari Sekhon
# Date: 2022-09-22 13:03:06 +0100 (Thu, 22 Sep 2022)
#
# https://github.com/HariSekhon/DevOps-Bash-tools
#
# License: see accompanying Hari Sekhon LICENSE file
#
# If you're using my code you're welcome to connect with me on LinkedIn and optionally send me feedback to help steer this or other code I publish
#
# https://www.linkedin.com/in/HariSekhon
#
set -euo pipefail
[ -n "${DEBUG:-}" ] && set -x
srcdir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck disable=SC1090,SC1091
. "$srcdir/lib/utils.sh"
# shellcheck disable=SC2034,SC2154
usage_description="
Verifies the SSL certificates for FQDNs at specific IP addresses via curl
Useful to test SSL source addresses for CDNs, such as Cloudflare Proxied sources before enabling SSL Full-Strict Mode for end-to-end, or Kubernetes ingresses (see also curl_k8s_ingress.sh)
Port defaults to 443 if not specified
If any of the arguments are a file, then reads the contents of that file as the 'FQDN,IP,Port' tuples, one per line either comma or space separated. Useful for bulk testing.
For a better version of this see check_ssl_cert.pl in the Advanced Nagios Plugins Collection:
check_ssl_cert.pl - checks Expiry days remaining, Domain, Subject Alternative Names, SNI
https://github.com/HariSekhon/Nagios-Plugins
"
# used by usage() in lib/utils.sh
# shellcheck disable=SC2034
usage_args="fqdn:ip[:port] [ fqdn2:ip[:port]] [fqdn3:ip[:port]] ... ]"
help_usage "$@"
min_args 1 "$@"
exitcode=0
# otherwise will silently fail getting openssl output on incorrect host
set +o pipefail
check_fqdn_ip(){
local fqdn="$1"
local ip="$2"
local port="${3:-443}"
local url="https://$fqdn"
echo -n "Checking SSL '$url' at '$ip': "
set +e
if curl -s --fail "$url" --resolve "$fqdn:$port:$ip" &>/dev/null; then
echo "OK"
else
echo "FAILED"
exitcode=1
fi
set -e
}
parse_arg(){
local arg="$1"
fqdn="${arg%%:*}"
ip_port="${arg#*:}"
ip="${ip_port%%:*}"
port="${ip_port##*:}"
if [ "$port" = "$ip" ]; then
port=""
fi
echo "$fqdn" "$ip" "$port"
}
process_arg(){
local arg="$1"
read -r fqdn ip port < <(parse_arg "$arg")
check_fqdn_ip "$fqdn" "$ip" "$port"
}
validate_arg(){
local arg="$1"
read -r fqdn ip port < <(parse_arg "$arg")
if [ -n "$port" ]; then
if ! [[ "$port" =~ ^[[:digit:]]+$ ]]; then
die "Invalid Port '$port' detected in '$arg'"
fi
fi
# shellcheck disable=SC2154
if ! [[ "$ip" =~ ^$ip_regex$ ]]; then
die "Invalid IP '$ip' detected in '$arg'"
fi
#if ! [[ "$fqdn" =~ ^$domain_regex$ ]]; then
# die "Invalid FQDN '$fqdn' given in '$arg'"
#fi
}
parse_file(){
local filename="$1"
sed 's/#.*//;
/^[[:space:]]*$/d;
s/[,:]/ /g' "$filename"
}
process_file(){
local filename="$1"
parse_file "$filename" |
while read -r fqdn ip port; do
check_fqdn_ip "$fqdn" "$ip" "$port"
done
}
validate_file(){
local filename="$1"
parse_file "$filename" |
while read -r fqdn ip port; do
validate_arg "$fqdn:$ip:$port"
done
}
# pre-validate before running anything, quicker
for arg; do
if [ -f "$arg" ]; then
validate_file "$arg"
continue
else
validate_arg "$arg"
fi
done
for arg; do
if [ -f "$arg" ]; then
process_file "$arg"
continue
else
process_arg "$arg"
fi
done
exit $exitcode