Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

491 quic support #492

Merged
merged 3 commits into from
Nov 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
2023-11-30 Matteo Corti <[email protected]>

* check_ssl_cert: Added QUIC support

2023-11-21 Matteo Corti <[email protected]>

* check_ssl_cert (main): Support for LibreSSL and IP addresses
Expand Down
1 change: 1 addition & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# News

* QUIC support
* OpenSSL 3.2.0 Support
* 2023-11-23 Version 2.77.0
* Added support for MQTTS
Expand Down
9 changes: 5 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -200,10 +200,10 @@ Options:
integers, 2 otherwise
-P,--protocol protocol Use the specific protocol:
dns, ftp, ftps, http, https (default),
h2 (HTTP/2), imap, imaps, irc, ircs, ldap,
ldaps, mqtts, mysql, pop3, pop3s,
postgres, sieve, smtp, smtps, tds, xmpp,
xmpp-server.
h2 (HTTP/2), h3 (HTTP/3), imap, imaps,
irc, ircs, ldap, ldaps, mqtts, mysql,
pop3, pop3s, postgres, sieve, smtp, smtps,
tds, xmpp, xmpp-server.
ftp, imap, irc, ldap, pop3, postgres,
sieve, smtp: switch to TLS using StartTLS
--password source Password source for a local certificate,
Expand All @@ -213,6 +213,7 @@ Options:
--proxy proxy Set http_proxy and the s_client -proxy
option
--python-bin path Path of the python binary to be used
--quic Use QUIC
-q,--quiet Do not produce any output
-r,--rootcert path Root certificate or directory to be used
for certificate validation
Expand Down
3 changes: 2 additions & 1 deletion RELEASE_NOTES.md
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
OpenSSL 3.2.0 Support
* QUIC support
* OpenSSL 3.2.0 support
77 changes: 58 additions & 19 deletions check_ssl_cert
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ fetch_http_headers() {
# -L (--location): follow redirects
# -k (--insecure): ignore TLS problems (we want to check the headers anyway)
# -o (--output): discard the output (we are only interested in the HTTP headers)
exec_with_timeout "${CURL_BIN} ${CURL_PROXY} ${CURL_RESOLVE} ${CURL_PROXY_ARGUMENT} ${INETPROTO} -k -s -D- -A '${HTTP_USER_AGENT}' -o /dev/null -L https://${HOST}${path}" "${CACHED_HEADERS}"
exec_with_timeout "${CURL_BIN} ${CURL_QUIC} ${CURL_PROXY} ${CURL_RESOLVE} ${CURL_PROXY_ARGUMENT} ${INETPROTO} -k -s -D- -A '${HTTP_USER_AGENT}' -o /dev/null -L https://${HOST}${path}" "${CACHED_HEADERS}"
RET=$?

if [ "${RET}" -ne 0 ]; then
Expand Down Expand Up @@ -463,10 +463,10 @@ usage() {
echo " integers, 2 otherwise"
echo " -P,--protocol protocol Use the specific protocol:"
echo " dns, ftp, ftps, http, https (default),"
echo " h2 (HTTP/2), imap, imaps, irc, ircs, ldap,"
echo " ldaps, mqtts, mysql, pop3, pop3s,"
echo " postgres, sieve, smtp, smtps, tds, xmpp,"
echo " xmpp-server."
echo " h2 (HTTP/2), h3 (HTTP/3), imap, imaps,"
echo " irc, ircs, ldap, ldaps, mqtts, mysql,"
echo " pop3, pop3s, postgres, sieve, smtp, smtps,"
echo " tds, xmpp, xmpp-server."
echo " ftp, imap, irc, ldap, pop3, postgres,"
echo " sieve, smtp: switch to TLS using StartTLS"
echo " --password source Password source for a local certificate,"
Expand All @@ -477,6 +477,7 @@ usage() {
echo " option"
echo " --python-bin path Path of the python binary to be used"
# Delimiter at 78 chars ############################################################
echo " --quic Use QUIC"
echo " -q,--quiet Do not produce any output"
# Delimiter at 78 chars ############################################################
echo " -r,--rootcert path Root certificate or directory to be used"
Expand Down Expand Up @@ -1904,9 +1905,9 @@ check_crl() {

TIMEOUT_REASON="fetching CRL"
if [ -n "${HTTP_USER_AGENT}" ]; then
exec_with_timeout "${CURL_BIN} ${CURL_PROXY} ${CURL_PROXY_ARGUMENT} ${INETPROTO} --silent --user-agent '${HTTP_USER_AGENT}' --location \\\"${CRL_URI}\\\" > ${CRL_TMP}"
exec_with_timeout "${CURL_BIN} ${CURL_PROXY} ${CURL_PROXY_ARGUMENT} ${CURL_QUIC} ${INETPROTO} --silent --user-agent '${HTTP_USER_AGENT}' --location \\\"${CRL_URI}\\\" > ${CRL_TMP}"
else
exec_with_timeout "${CURL_BIN} ${CURL_PROXY} ${CURL_PROXY_ARGUMENT} ${INETPROTO} --silent --location \\\"${CRL_URI}\\\" > ${CRL_TMP}"
exec_with_timeout "${CURL_BIN} ${CURL_PROXY} ${CURL_PROXY_ARGUMENT} ${CURL_QUIC} ${INETPROTO} --silent --location \\\"${CRL_URI}\\\" > ${CRL_TMP}"
fi
unset TIMEOUT_REASON

Expand Down Expand Up @@ -2033,9 +2034,9 @@ check_ocsp() {

TIMEOUT_REASON="OCSP: fetching issuer ${ELEMENT_ISSUER_URI}"
if [ -n "${HTTP_USER_AGENT}" ]; then
exec_with_timeout "${CURL_BIN} ${CURL_PROXY} ${CURL_PROXY_ARGUMENT} ${INETPROTO} --silent --user-agent '${HTTP_USER_AGENT}' --location \\\"${ELEMENT_ISSUER_URI}\\\" > ${ISSUER_CERT_TMP}"
exec_with_timeout "${CURL_BIN} ${CURL_PROXY} ${CURL_PROXY_ARGUMENT} ${CURL_QUIC} ${INETPROTO} --silent --user-agent '${HTTP_USER_AGENT}' --location \\\"${ELEMENT_ISSUER_URI}\\\" > ${ISSUER_CERT_TMP}"
else
exec_with_timeout "${CURL_BIN} ${CURL_PROXY} ${CURL_PROXY_ARGUMENT} ${INETPROTO} --silent --location \\\"${ELEMENT_ISSUER_URI}\\\" > ${ISSUER_CERT_TMP}"
exec_with_timeout "${CURL_BIN} ${CURL_PROXY} ${CURL_PROXY_ARGUMENT} ${CURL_QUIC} ${INETPROTO} --silent --location \\\"${ELEMENT_ISSUER_URI}\\\" > ${ISSUER_CERT_TMP}"
fi
unset TIMEOUT_REASON

Expand Down Expand Up @@ -2590,7 +2591,11 @@ fetch_certificate() {
fi

# Check if a protocol was specified (if not HTTP switch to TLS)
if [ -n "${PROTOCOL}" ] && [ "${PROTOCOL}" != 'http' ] && [ "${PROTOCOL}" != 'https' ] && [ "${PROTOCOL}" != 'h2' ]; then
if [ -n "${PROTOCOL}" ] &&
[ "${PROTOCOL}" != 'http' ] &&
[ "${PROTOCOL}" != 'https' ] &&
[ "${PROTOCOL}" != 'h2' ] &&
[ "${PROTOCOL}" != 'h3' ]; then

case "${PROTOCOL}" in
pop3 | ftp)
Expand Down Expand Up @@ -2787,9 +2792,11 @@ fetch_certificate() {

if [ "${PROTOCOL}" = 'h2' ]; then
ALPN="-alpn h2"
elif [ "${PROTOCOL}" = 'h3' ]; then
ALPN="-alpn h3"
fi

exec_with_timeout "printf '${HTTP_REQUEST}' | ${OPENSSL} s_client ${SECURITY_LEVEL} ${INETPROTO} ${CLIENT} ${CLIENTPASS} -crlf ${ALPN} -connect ${HOST_ADDR}:${PORT} ${SERVERNAME} ${SCLIENT_PROXY} ${SCLIENT_PROXY_ARGUMENT} -showcerts -verify 6 ${ROOT_CA} ${SSL_VERSION} ${SSL_VERSION_DISABLED} ${SSL_AU} ${STATUS} ${DANE} ${RENEGOTIATION} 2> ${ERROR} 1> ${CERT}"
exec_with_timeout "printf '${HTTP_REQUEST}' | ${OPENSSL} s_client ${QUIC} ${SECURITY_LEVEL} ${INETPROTO} ${CLIENT} ${CLIENTPASS} -crlf ${ALPN} -connect ${HOST_ADDR}:${PORT} ${SERVERNAME} ${SCLIENT_PROXY} ${SCLIENT_PROXY_ARGUMENT} -showcerts -verify 6 ${ROOT_CA} ${SSL_VERSION} ${SSL_VERSION_DISABLED} ${SSL_AU} ${STATUS} ${DANE} ${RENEGOTIATION} 2> ${ERROR} 1> ${CERT}"
RET=$?

fi
Expand Down Expand Up @@ -2877,6 +2884,10 @@ fetch_certificate() {
prepend_critical_message 'Self signed certificate'
fi

elif ascii_grep 'quic_do_handshake' "${ERROR}"; then

prepend_critical_message 'QUIC not supported'

elif ascii_grep 'dh[ ]key[ ]too[ ]small' "${ERROR}"; then

prepend_critical_message 'DH with a key too small'
Expand Down Expand Up @@ -3008,6 +3019,10 @@ fetch_certificate() {
if ! "${GREP_BIN}" -q -F 'ALPN protocol: h2' "${CERT}"; then
prepend_critical_message 'The server does not support HTTP/2'
fi
elif [ "${PROTOCOL}" = 'h3' ]; then
if ! "${GREP_BIN}" -q -F 'ALPN protocol: h3' "${CERT}"; then
prepend_critical_message 'The server does not support HTTP/3'
fi
fi

fi
Expand Down Expand Up @@ -3325,6 +3340,10 @@ parse_command_line_options() {
PROMETHEUS=1
shift
;;
--quic)
QUIC='-quic'
shift
;;
-q | --quiet)
QUIET=1
shift
Expand Down Expand Up @@ -4221,7 +4240,7 @@ main() {
http)
PORT=80
;;
https | h2)
https | h2 | h3)
PORT=443
;;
mqtts)
Expand Down Expand Up @@ -4378,6 +4397,26 @@ main() {
check_required_prog "${OPENSSL}"
OPENSSL=${PROG}

if [ -n "${QUIC}" ] ; then

require_s_client_option '-quic'

# QUIC requires HTTP/2
if [ -n "${PROTOCOL}" ] && [ "${PROTOCOL}" != 'h3' ]; then
critical 'QUIC only works with HTTP/2'
else
verboselog '--quic specified enabling HTTP/3'
PROTOCOL='h3'
fi

# check if curl supports HTTP/3
if curl --help all | grep -q -- --http3 ; then
debuglog 'curl supports HTTP/3'
CURL_QUIC='--http3'
fi

fi

##############################################################################
# custom grep
if [ -z "${GREP_BIN}" ]; then
Expand Down Expand Up @@ -4618,7 +4657,7 @@ main() {
DNS_OVER_HTTP=${TEMPFILE}

TIMEOUT_REASON="Resolving over HTTP with ${RESOLVE_OVER_HTTP}"
exec_with_timeout "${CURL_BIN} ${CURL_PROXY} ${CURL_PROXY_ARGUMENT} ${INETPROTO} --silent --user-agent '${HTTP_USER_AGENT}' -H 'Content-Type: application/dns-json' https://${RESOLVE_OVER_HTTP}/resolve?name=${HOST}\\&type=A" "${DNS_OVER_HTTP}"
exec_with_timeout "${CURL_BIN} ${CURL_PROXY} ${CURL_PROXY_ARGUMENT} ${CURL_QUIC} ${INETPROTO} --silent --user-agent '${HTTP_USER_AGENT}' -H 'Content-Type: application/dns-json' https://${RESOLVE_OVER_HTTP}/resolve?name=${HOST}\\&type=A" "${DNS_OVER_HTTP}"

if [ "${DEBUG}" -ge 1 ]; then
jq < "${DNS_OVER_HTTP}" | sed 's/^/[DBG] /' 1>&2
Expand Down Expand Up @@ -4888,9 +4927,9 @@ main() {

TIMEOUT_REASON="fetching certificate file"
if [ -n "${HTTP_USER_AGENT}" ]; then
exec_with_timeout "${CURL_BIN} ${CURL_PROXY} ${CURL_PROXY_ARGUMENT} ${INETPROTO} --silent --user-agent '${HTTP_USER_AGENT}' --location \\\"${FILE_URI}\\\" > ${FILE}"
exec_with_timeout "${CURL_BIN} ${CURL_PROXY} ${CURL_PROXY_ARGUMENT} ${CURL_QUIC} ${INETPROTO} --silent --user-agent '${HTTP_USER_AGENT}' --location \\\"${FILE_URI}\\\" > ${FILE}"
else
exec_with_timeout "${CURL_BIN} ${CURL_PROXY} ${CURL_PROXY_ARGUMENT} ${INETPROTO} --silent --location \\\"${FILE_URI}\\\" > ${FILE}"
exec_with_timeout "${CURL_BIN} ${CURL_PROXY} ${CURL_PROXY_ARGUMENT} ${CURL_QUIC} ${INETPROTO} --silent --location \\\"${FILE_URI}\\\" > ${FILE}"
fi
unset TIMEOUT_REASON

Expand Down Expand Up @@ -5366,7 +5405,7 @@ main() {
# Check if curl is needed and if it supports the -4 and -6 options
if [ -z "${CURL_BIN}" ]; then
if [ -n "${SSL_LAB_CRIT_ASSESSMENT}" ] || [ -n "${OCSP}" ]; then
if ! "${CURL_BIN}" --manual | "${GREP_BIN}" -F -q -- -6 && [ -n "${INETPROTO}" ]; then
if ! "${CURL_BIN}" --help all | "${GREP_BIN}" -F -q -- -6 && [ -n "${INETPROTO}" ]; then
unknown "curl does not support the ${INETPROTO} option"
fi
fi
Expand Down Expand Up @@ -6640,13 +6679,13 @@ ${WARNING}"

debuglog "http_proxy = ${http_proxy}"
debuglog "HTTPS_PROXY = ${HTTPS_PROXY}"
debuglog "executing ${CURL_BIN} ${CURL_PROXY} ${CURL_PROXY_ARGUMENT} ${INETPROTO} --silent \"https://api.ssllabs.com/api/v2/analyze?host=${HOST_NAME}${IGNORE_SSL_LABS_CACHE}\""
debuglog "executing ${CURL_BIN} ${CURL_PROXY} ${CURL_PROXY_ARGUMENT} ${CURL_QUIC} ${INETPROTO} --silent \"https://api.ssllabs.com/api/v2/analyze?host=${HOST_NAME}${IGNORE_SSL_LABS_CACHE}\""

if [ -n "${SNI}" ]; then
exec_with_timeout "${CURL_BIN} ${CURL_PROXY} ${CURL_PROXY_ARGUMENT} ${INETPROTO} --silent \\\"https://api.ssllabs.com/api/v2/analyze?host=${SNI}${IGNORE_SSL_LABS_CACHE}\\\" > ${JSON}"
exec_with_timeout "${CURL_BIN} ${CURL_PROXY} ${CURL_PROXY_ARGUMENT} ${CURL_QUIC} ${INETPROTO} --silent \\\"https://api.ssllabs.com/api/v2/analyze?host=${SNI}${IGNORE_SSL_LABS_CACHE}\\\" > ${JSON}"
CURL_RETURN_CODE=$?
else
exec_with_timeout "${CURL_BIN} ${CURL_PROXY} ${CURL_PROXY_ARGUMENT} ${INETPROTO} --silent \\\"https://api.ssllabs.com/api/v2/analyze?host=${HOST_NAME}${IGNORE_SSL_LABS_CACHE}\\\" > ${JSON}"
exec_with_timeout "${CURL_BIN} ${CURL_PROXY} ${CURL_PROXY_ARGUMENT} ${CURL_QUIC} ${INETPROTO} --silent \\\"https://api.ssllabs.com/api/v2/analyze?host=${HOST_NAME}${IGNORE_SSL_LABS_CACHE}\\\" > ${JSON}"
CURL_RETURN_CODE=$?
fi

Expand Down
5 changes: 4 additions & 1 deletion check_ssl_cert.1
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,7 @@ TCP port (default 443)
Number of decimal places for durations: defaults to 0 if critical or warning are integers, 2 otherwise
.TP
.BR "-P,--protocol" " protocol"
Use the specific protocol: dns, ftp, ftps, http, https (default), h2 (HTTP/2), imap, imaps, irc, ircs, ldap, ldaps, mqtts, mysql, pop3, pop3s, postgres, sieve, smtp, smtps, tds, xmpp, xmpp-server, ftp, imap, irc, ldap, pop3, postgres, sieve, smtp: switch to TLS using StartTLS.
Use the specific protocol: dns, ftp, ftps, http, https (default), h2 (HTTP/2), h3 (HTTP/3), imap, imaps, irc, ircs, ldap, ldaps, mqtts, mysql, pop3, pop3s, postgres, sieve, smtp, smtps, tds, xmpp, xmpp-server, ftp, imap, irc, ldap, pop3, postgres, sieve, smtp: switch to TLS using StartTLS.
.BR
These protocols switch to TLS using StartTLS: ftp, imap, irc, ldap, mysql, pop3, smtp.
.TP
Expand All @@ -349,6 +349,9 @@ Set http_proxy and the s_client -proxy option
.BR " --python-bin" " path"
Path of the python binary to be used
.TP
.BR " --quic"
Use QUIC
.TP
.BR "-q,--quiet"
Do not produce any output
.TP
Expand Down
2 changes: 1 addition & 1 deletion check_ssl_cert.completion
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ _check_ssl_cert() {
# only the autocompletion with long options is implemented: long options are more readable and quick to enter since we are
# using autocompletion.
#
opts="--file --host --noauth --all --all-local --allow-empty-san --clientcert --configuration --critical --check-chain --check-ciphers --check-ciphers-warnings --check-http-headers --check-ssl-labs --check-ssl-labs-warn --clientpass --crl --curl-bin --user-agent --custom-http-header --dane --date --debug-cert --debug-file --debug-headers --debug-time --default-format --dig-bin --do-not-resolve --dtls --dtls1 --dtls1_2 --ecdsa --element --file-bin --fingerprint --first-element-only --force-dconv-date --force-perl-date --format --grep-bin --http-headers-path --http-use-get --ignore-altnames --jks-alias --ignore-connection-problems --ignore-exp --ignore-http-headers --ignore-host-cn --ignore-incomplete-chain --ignore-maximum-validity --ignore-ocsp --ignore-ocsp-errors --ignore-ocsp-timeout --ignore-sct --ignore-sig-alg --ignore-ssl-labs-cache --ignore-tls-renegotiation --inetproto protocol --info --init-host-cache --issuer-cert-cache --long-output --match --maximum-validity --nmap-bin --no-perf --no-proxy --no-proxy-curl --no-proxy-s_client --no-ssl2 --no-ssl3 --no-tls1 --no-tls1_1 --no-tls1_2 --no-tls1_3 --not-issued-by --not-valid-longer-than --ocsp-critical --ocsp-warning --openssl --password --path --precision --prometheus --proxy --require-client-cert --require-dnssec --require-http-header --require-no-http-header --require-no-ssl2 --require-no-ssl3 --require-no-tls1 --require-no-tls1_1 --require-ocsp-stapling --require-purpose --require-purpose-critical --resolve --resolve-over-http --rootcert-dir --rootcert-file --rsa --serial --security-level --skip-element --sni --ssl2 --ssl3 --temp --terse --tls1 --tls1_1 --tls1_2 --tls1_3 --xmpphost -4 -6 --clientkey --protocol --version --debug --email --help --issuer --cn --org --port port --rootcert --quiet --selfsigned --timeout --url --verbose --warning --python-bin"
opts="--file --host --noauth --all --all-local --allow-empty-san --clientcert --configuration --critical --check-chain --check-ciphers --check-ciphers-warnings --check-http-headers --check-ssl-labs --check-ssl-labs-warn --clientpass --crl --curl-bin --user-agent --custom-http-header --dane --date --debug-cert --debug-file --debug-headers --debug-time --default-format --dig-bin --do-not-resolve --dtls --dtls1 --dtls1_2 --ecdsa --element --file-bin --fingerprint --first-element-only --force-dconv-date --force-perl-date --format --grep-bin --http-headers-path --http-use-get --ignore-altnames --jks-alias --ignore-connection-problems --ignore-exp --ignore-http-headers --ignore-host-cn --ignore-incomplete-chain --ignore-maximum-validity --ignore-ocsp --ignore-ocsp-errors --ignore-ocsp-timeout --ignore-sct --ignore-sig-alg --ignore-ssl-labs-cache --ignore-tls-renegotiation --inetproto protocol --info --init-host-cache --issuer-cert-cache --long-output --match --maximum-validity --nmap-bin --no-perf --no-proxy --no-proxy-curl --no-proxy-s_client --no-ssl2 --no-ssl3 --no-tls1 --no-tls1_1 --no-tls1_2 --no-tls1_3 --not-issued-by --not-valid-longer-than --ocsp-critical --ocsp-warning --openssl --password --path --precision --prometheus --proxy --require-client-cert --require-dnssec --require-http-header --require-no-http-header --require-no-ssl2 --require-no-ssl3 --require-no-tls1 --require-no-tls1_1 --require-ocsp-stapling --require-purpose --require-purpose-critical --resolve --resolve-over-http --rootcert-dir --rootcert-file --rsa --serial --security-level --skip-element --sni --ssl2 --ssl3 --temp --terse --tls1 --tls1_1 --tls1_2 --tls1_3 --xmpphost -4 -6 --clientkey --protocol --version --debug --email --help --issuer --cn --org --port port --rootcert --quic --quiet --selfsigned --timeout --url --verbose --warning --python-bin"

if [[ ${cur} == -* || ${COMP_CWORD} -eq 1 ]]; then
# shellcheck disable=2207
Expand Down
7 changes: 6 additions & 1 deletion check_ssl_cert_icinga2.conf
Original file line number Diff line number Diff line change
Expand Up @@ -504,7 +504,12 @@ object CheckCommand "ssl_cert_extended" {
description = "Path of the python binary to be used"
}

"--quiet" = {
"--quic" = {
set_if = "$ssl_cert_extended_quic$"
description = "Use QUIC"
}

"--quiet" = {
set_if = "$ssl_cert_extended_quiet$"
description = "Do not produce any output"
}
Expand Down
1 change: 0 additions & 1 deletion test/derlink.cer

This file was deleted.

Binary file added test/derlink.cer
Binary file not shown.
20 changes: 20 additions & 0 deletions test/integration_tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -1698,6 +1698,26 @@ testMQTTS() {
assertEquals "wrong exit code" "${NAGIOS_OK}" "${EXIT_CODE}"
}

testQUIC() {

if [ -n "${http_proxy}" ] ; then

echo "Skipping: no proxy support for QUIC"

elif "${OPENSSL}" s_client -help 2>&1 | grep -q -- -quic ; then

# shellcheck disable=SC2086
${SCRIPT} ${TEST_DEBUG} --host www.google.com --quic
EXIT_CODE=$?
assertEquals "wrong exit code" "${NAGIOS_OK}" "${EXIT_CODE}"

else

echo "Skipping: OpenSSL does not support QUIC"

fi
}

testDNS() {

# shellcheck disable=SC2086
Expand Down
Loading