比较本地和远程 SSL 证书以确定它们是否相同

比较本地和远程 SSL 证书以确定它们是否相同

我正在部署我们的 LetsEncrypt SSL 证书。我有每天运行的 cron 作业,并在需要时使用 certbot 更新证书。我还有一个将证书部署到负载均衡器的脚本。

当证书续订时,Certbot 会有一个部署回调。续订证书后,Certbot 会立即调用我的脚本。这似乎工作正常——大多数情况下。但是,如果部署因任何原因失败,我希望它第二天再试一次。看起来 certbot 中没有为此内置任何功能。

如何实现具有以下逻辑的脚本:

if [ /etc/letsencrypt/live/example.com/cert.pem != certfrom https://example.com/ ]
then
    example.com-cert-deploy.sh
fi

答案1

您可以使用类似如下的方法:

$ openssl s_client -showcerts -servername example.com -connect example.com:443 </dev/null

...除其他内容外,还将输出服务器证书。您可以解析它,保存它,然后将其与磁盘上的其他证书进行比较。

答案2

将本地证书的“指纹”与有效证书进行比较就足够了。

可以通过下面两个命令获取这两个指纹:

  • openssl x509 -in /etc/letsencrypt/live/example.com/cert.pem -fingerprint -noout
  • echo | openssl s_client -showcerts -connect example.com:443 -servername example.com 2>&1 | openssl x509 -fingerprint -noout

为了便于比较,我将它们放入带有错误检查的脚本中。它接受域名作为参数,如果两者不同,则以失败状态退出。它可以这样使用:

if ! ./lets-encrypt-installed-test.sh --quiet example.com
then
    ./example.com-cert-deploy.sh
fi

以下是脚本的完整内容:

#!/bin/sh

set -e 

quiet=0

for var in "$@"
do
    case "$var" in
        -q)
            quiet=1
            ;;
        --quiet)
            quiet=1
            ;;
        -*)
            echo "Unexpected argument $var" >&2
            exit 1
            ;;
        *.*)
            domain="$var"
            ;;
        *)
            echo "Expected argument $var" >&2
            exit 1
            ;;
    esac
done

if [ "z$domain" == "z" ]
then
    echo "Expected domain as parameter to $0" >&2
    exit 1
fi

lefile="/etc/letsencrypt/live/$domain/cert.pem"

if [ ! -e $lefile ]
then    
    echo "Lets Encrypt file does not exist: $lefile" >&2
    exit 1
fi

leprint=`openssl x509 -in $lefile -fingerprint -noout`

case "$leprint" in
    *Fingerprint*)
        ;;
    *)
        echo "No fingerprint from $lefile" >&2
        exit 1
        ;;
esac

liveprint=`echo | openssl s_client -showcerts -connect "$domain":443 -servername "$domain" 2>&1 | openssl x509 -fingerprint | grep -i fingerprint`

case "$liveprint" in
    *Fingerprint*)
        ;;
    *)
        echo "No fingerprint from SSL cert of https://$domain/" >&2
        exit 1
        ;;
esac

if [ "$leprint" != "$liveprint" ]
then
    if [ "$quiet" == "0" ]
    then
        echo "Fingerprints for local and remote SSL certificates differ:" >&2
        echo "$lefile: $leprint" >&2
        echo "https://$domain/: $liveprint" >&2
    fi
    exit 1
fi 

exit 0

相关内容