getssl
getssl copied to clipboard
Creating a new config directory may hang
When a domain config file is begin created the script attempts to download the current certificate from port 443 on the named host. If the name is on a host that's currently firewalled and so doesn't respond the script will wait for the default timeout of the openssl s_client command which could be a very long time (it seems to be two minutes by default on my machine). The code that does this is shown below.
It's only purpose seems to be to guess what the SAN list should be in the new file. The only workaround I can think of is to use curl with a short timeout to check the host is there before fetching the certificate as now.
if [[ -s "$DOMAIN_DIR/getssl.cfg" ]]; then
info "domain config already exists $DOMAIN_DIR/getssl.cfg"
else
info "creating domain config file in $DOMAIN_DIR/getssl.cfg"
#-----FROM HERE-----
# if domain has an existing cert, copy from domain and use to create defaults.
EX_CERT=$(echo \
| openssl s_client -servername "${DOMAIN}" -connect "${DOMAIN}:443" 2>/dev/null \
| openssl x509 2>/dev/null)
EX_SANS="www.${DOMAIN}"
if [[ ! -z "${EX_CERT}" ]]; then
EX_SANS=$(echo "$EX_CERT" \
| openssl x509 -noout -text 2>/dev/null| grep "Subject Alternative Name" -A2 \
| grep -Eo "DNS:[a-zA-Z 0-9.-]*" | sed "s@DNS:$DOMAIN@@g" | grep -v '^$' | cut -c 5-)
EX_SANS=${EX_SANS//$'\n'/','}
fi
#-----TO HERE-----
write_domain_template "$DOMAIN_DIR/getssl.cfg"
fi
Or at least add to the message - one doesn't expect creating a file to take very long. How about: info "Contacting ${DOMAIN} to determine other host names" Perhaps trap ^C and add info "If this takes too long, type ^C to skip this step" On ^C, continue with just the primary name.
I remembered this is bash only, so we could use this fragment. It adds a two second timeout to the openssl command.
(
openssl s_client -servername $DOMAIN -connect $DOMAIN:443 </dev/null & PID=$!
sleep 2 & PIDW=$!
wait -n
kill -9 "$PID" "$PIDW" 2>/dev/null
)
Good idea. That should work. Perhaps '2' should be a variable.
I still think that there should be a message indicating that the server is being contacted; if s_client happens to talk, the user shouldn't be surprised - creating a directory doesn't involve OpenSSL.
The whole point is for s_client to chatter, part of the output (when it works) is the certificate that's needed to find the SAN list it's after. So the full substitution would be something like this:
EX_CERT=$( {
openssl s_client -servername "$DOMAIN" -connect "$DOMAIN":443 </dev/null 2>/dev/null & PID=$!
sleep 2 & PIDW=$!
wait -n
kill -9 "$PID" "$PIDW" 2>/dev/null
} | openssl x509 2>/dev/null)
in place of
EX_CERT=$(echo \
| openssl s_client -servername "${DOMAIN}" -connect "${DOMAIN}:443" 2>/dev/null \
| openssl x509 2>/dev/null)
I got that. I like the solution.
But look at it from the user's POV. The terminal output is:
creating domain config file in ...
If something is making a network connection, it should say so. Both for timing (your original issue), and to avoid surprises (mine). It's astonishing when creating a file materializes data from thin air. And when your firewall pops up with "process foo established TLS connection to ..." Especially in these days of command and control viruses...
The technology is fine. Just don't surprise the user. I suggest something more like this:
info "Contacting ${DOMAIN} to inspect current certificate"
EX_CERT=$( {
openssl s_client -servername "$DOMAIN" -connect "$DOMAIN":443 </dev/null 2>/dev/null & PID=$!
sleep ${CERT_TIMEOUT} & PIDW=$!
wait -n
kill -9 "$PID" "$PIDW" 2>/dev/null
} | openssl x509 2>/dev/null)
I will experiment with this & add it to my PR if it works out.
Thanks for the prod.
It turns out that wait -n requires bash 4.3. I made the timeout conditional and configurable. Doesn't seem worth trying to figure out another approach.
I've updated my fork, which has an outstanding PR ( #289 ). Since I was in the code, seemed worth doing.
Hopefully it will be accepted. You're welcome to test / review for any bugs.
Are there more than just the openssl process in the background? I wouldn't expect so; so the "-n" could be dropped from the "wait".
Is it possible to bypass this check and/or is there an option to already inform the contents of SAN?
Hi @paulocoghi It looks like the fix mentioned above was never implemented and the only way to bypass the check is to manually create the configuration file for a new domain. I'll try and fix this tomorrow.