在共享主机上自动生成和更新 SSL

Auto Generate and Update SSL on Shared Hosting

我正在尝试自动生成 SSL 证书并将它们上传到我在 namecheap.com

上的共享主机

主机不提供任何无需支付大量费用即可自动管理 ssl 证书的方法。

我正在尝试让这个脚本正常工作

https://catelin.net/2018/03/24/fully-automate-ssl-tls-certificate-renewal-with-cpanel/

我们的想法是 运行 bash 在您自己的 linux 盒子上创建脚本,它将通过 cpanel 更新 ssl 证书。

我对这部分代码有困难。在我的实际代码中,我更新了服务器名称信息。主要问题是我在 bash 脚本中编写的经验很少。

certificate=$(echo |openssl s_client -servername yourserver.com -connect yourserver.com:443 2>/tmp/cert.tmp|openssl x509 -checkend $[86400 * $RENEW] -enddate)
if [ "$certificate" == "" ]; then
  echo "Error: unable to check certificate"
else
  if [[ $certificate =~ (.*)Certificate will expire ]]; then
    echo $certificate
    ...

我在这里遇到一个错误(我确信这是我的第一个错误...)

./certupdate.sh: line 19: syntax error in conditional expression
./certupdate.sh: line 19: syntax error near `will'
./certupdate.sh: line 19: `    if [[ $certificate =~ (.*)Certificate will expire ]]; then'

任何帮助都会很棒。

或者,如果有人对如何更新 ssl 证书有更好的想法,那就更好了。总的来说 PHP 会很棒,因为我对此比较熟悉。

shell 通过按空格拆分将每一行解析为标记。 [[ built-in 和 =~ 的语法要求每一侧都有一个标记。您可以通过在每个不是标记分隔符的空白字符前面放置反斜杠,或者引用应该是单个标记的序列来防止在空格上拆分。

  if [[ $certificate =~ (.*)"Certificate will expire" ]]; then

除此之外,您在这里真的不需要正则表达式。 (如果你确实使用了一个,.* 周围的括号是多余的。事实上整个 .* 是多余的。)

  if [[ $certificate = *"Certificate will expire"* ]]; then

除了之外,您尝试复制的脚本还有许多其他问题,尽管这些问题比较小。可能只是想找一个更好的博客 copy/paste from.

这里有一个快速重构,希望能使脚本更加地道,但我可能遗漏了一些问题,并且没有任何方法来测试它。

#!/bin/bash

# Don't use uppercase for private variables
renew=22

# For diagnostic messages
me=${0##*/}

# Parametrize domain name
dom="yourserver.com"
email="email@example.org"

# Don't echo so much junk
# (I will silently drop the other junk output without comment)
# echo "======================================="
# Fix date formatting, print diagnostic to stderr
date "+$me: %c START" >&2
# Use a unique temp file to avoid symlink attacks and concurrency problems
t=$(mktemp -t letsencryptCA.XXXXXXXXXX.crt) || exit
# Clean it up when we are done
trap 'rm -f "$t"' ERR EXIT
wget -O "$t" https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.pem.txt

# Avoid obsolete $[ ... ] math syntax
# Avoid superfluous echo |
# Don't write stderr to a junk file
# Maybe add 2>/dev/null on the first openssl if this is too noisy
certificate=$(openssl s_client -servername "$dom" -connect "$dom":443 </dev/null | 
              openssl x509 -checkend $((86400 * $renew)) -enddate)
# Indentation fixes
if [ "$certificate" == "" ]; then
    # Error messages indicate script's name, and go to standard error
    # Include domain name in error message
    # Fixed throughout below
    echo "$me: Error: unable to check $dom certificate" >&2
    # Exit with an error, too
    exit 123
else
    # Quote string
    # Move this outside the conditional, to avoid repeated code
    echo "$certificate"

    # Fix comparison
    if [[ $certificate = *"Certificate will expire"* ]]; then

        echo "$me: $dom certificate needs to be renewed" >&2
    
        # No idea here, assume this is okay
        # Wrap horribly long command though
        certbot certonly --non-interactive --staple-ocsp \
            --email "$email" -d "$dom" -d "www.$dom" \
            --agree-tos --manual \
            --manual-auth-hook /path/toyour/scripts/letsencryptauth.sh \
            --manual-cleanup-hook /path/toyour/scripts/letsencryptclean.sh
        echo "$me: $dom cert process completed, now uploading it to CPanel" >&2
    
        # Weird indentation fixed again
        USER='cpanel username' PASS='cpanelpassword' EMAIL="$email" \
        /usr/bin/php /path/toyour/scripts/sslic.php "$dom" \
            /etc/letsencrypt/live/"$dom"/cert.pem \
            /etc/letsencrypt/live/"$dom"/privkey.pem "$t"
        echo "$me: $dom upload to cpanel process complete" >&2
    
    else
        echo "$me: $dom cert does not need to be renewed" >&2
    fi
fi
# Fix date formatting, print diagnostic to stderr
date "+$me: %c END" >&2

date%c 格式说明符包括年份,而原始代码省略了它。我认为此更改是一项功能而不是错误。

还有很多 hard-coded 路径等可能应该更好地参数化。

openssl 的 stderr 输出非常适中,我认为我们绝对不需要丢弃它;另一方面,将其转储到临时文件中几乎肯定会在实际出现问题(网络故障或其他原因)时隐藏有用的诊断信息。

tripleee$ openssl s_client -servername www.whosebug.com \
>   -connect www.whosebug.com:443 </dev/null >/dev/null
depth=2 O = Digital Signature Trust Co., CN = DST Root CA X3
verify return:1
depth=1 C = US, O = Let's Encrypt, CN = Let's Encrypt Authority X3
verify return:1
depth=0 CN = *.stackexchange.com
verify return:1