如何从 PEM 编码证书确定 SSL 证书的到期日期?
- 2024-10-28 08:37:00
- admin 原创
- 73
问题描述:
如果我有实际文件和 Mac 或 Linux 中的 Bash shell,我该如何查询证书文件以了解其何时过期?不是网站,而是证书文件本身,假设我有 csr、key、pem 和 chain 文件。
解决方案 1:
和openssl
:
openssl x509 -enddate -noout -in file.pem
输出形式如下:
notAfter=Nov 3 22:23:50 2014 GMT
另请参阅MikeW 的回答,了解如何轻松检查证书是否已过期,或者是否会在一定时间段内过期,而无需解析上述日期。
解决方案 2:
如果您只是想知道证书是否已过期(或者将在接下来的 N 秒内过期),则选项-checkend <seconds>
将openssl x509
告诉您:
if openssl x509 -checkend 86400 -noout -in file.pem
then
echo "Certificate is good for another day!"
else
echo "Certificate has expired or will do so within 24 hours!"
echo "(or is invalid/not found)"
fi
这省去了您自己进行日期/时间比较的麻烦。
openssl
如果证书尚未过期,并且在接下来的 86400 秒内不会过期(如上例所示),则将返回退出代码0
(零)。如果证书即将过期或已经过期 - 或者出现其他错误(如文件无效/不存在),则返回代码为1
。
(当然,假设时间/日期设置正确)
请注意,旧版本的 openssl 有一个错误,这意味着如果指定的时间checkend
太大,则始终会返回 0(https://github.com/openssl/openssl/issues/6180)。
解决方案 3:
这是我的 bash 命令行,用于按到期顺序列出多个证书,最近到期的证书首先到期。
for pem in /etc/ssl/certs/*.pem; do
printf '%s: %s
' \n "$(date --date="$(openssl x509 -enddate -noout -in "$pem"|cut -d= -f 2)" --iso-8601)" \n "$pem"
done | sort
示例输出:
2015-12-16: /etc/ssl/certs/Staat_der_Nederlanden_Root_CA.pem
2016-03-22: /etc/ssl/certs/CA_Disig.pem
2016-08-14: /etc/ssl/certs/EBG_Elektronik_Sertifika_Hizmet_S.pem
解决方案 4:
命令:
# cat {key_name} | openssl x509 -noout -enddate
Example: # cat tower.cert | openssl x509 -noout -enddate
结果:
notAfter=Dec 7 04:03:32 2023 GMT
解决方案 5:
与接受的答案相同,但请注意,它甚至可以用于.crt
文件而不仅仅是.pem
文件,以防您无法找到.pem
文件位置。
openssl x509 -enddate -noout -in e71c8ea7fa97ad6c.crt
结果:
notAfter=Mar 29 06:15:00 2020 GMT
解决方案 6:
这是一个 bash 函数,它检查所有服务器,假设您使用 DNS 循环。请注意,这需要 GNU 日期,并且不适用于 Mac OS
function check_certs () {
if [ -z "$1" ]
then
echo "domain name missing"
exit 1
fi
name="$1"
shift
now_epoch=$( date +%s )
dig +noall +answer $name | while read _ _ _ _ ip;
do
echo -n "$ip:"
expiry_date=$( echo | openssl s_client -showcerts -servername $name -connect $ip:443 2>/dev/null | openssl x509 -inform pem -noout -enddate | cut -d "=" -f 2 )
echo -n " $expiry_date";
expiry_epoch=$( date -d "$expiry_date" +%s )
expiry_days="$(( ($expiry_epoch - $now_epoch) / (3600 * 24) ))"
echo " $expiry_days days"
done
}
输出示例:
$ check_certs stackoverflow.com
151.101.1.69: Aug 14 12:00:00 2019 GMT 603 days
151.101.65.69: Aug 14 12:00:00 2019 GMT 603 days
151.101.129.69: Aug 14 12:00:00 2019 GMT 603 days
151.101.193.69: Aug 14 12:00:00 2019 GMT 603 days
解决方案 7:
一行检查域名证书是否在一段时间后过期(例如 15 天):
openssl x509 -checkend $(( 24*3600*15 )) -noout -in <(openssl s_client -showcerts -connect my.domain.com:443 </dev/null 2>/dev/null | openssl x509 -outform PEM)
if [ $? -eq 0 ]; then
echo 'good'
else
echo 'bad'
fi
解决方案 8:
openssl
将字段存储到狂欢变量
由于这个问题被标记为狂欢,我经常用它来存储日期,这对于计算剩余时间和通过bashism格式化输出UNIX EPOCH
很有用:$EPOCHSECONDS
`printf '%(dateFmt)T`
{ read -r certStart;read -r certEnd;}< <(date -f <(cut -d = -f 2 <(
openssl x509 -dates -noout -in "$file")) +%s)
然后
printf '%-6s %(%a %d %b %Y, %H %Z)T
' start $certStart end $certEnd
start Mon 01 Nov 2004, 17 UTC
end Mon 01 Jan 2035, 05 UTC
示例,列出内容/etc/ssl/certs
并计算剩余天数:
for file in /etc/ssl/certs/*pem;do
{ read -r certStart;read -r certEnd;}< <(
date -f <(cut -d = -f 2 <(
openssl x509 -dates -noout -in "$file")) +%s)
printf "%(%d %b %Y %T)T - %(%d %b %Y %T)T: %6d %s
" \n $certStart $certEnd $(( (certEnd - EPOCHSECONDS)/86400 )) ${file##*/}
done
05 May 2011 09:37:37 - 31 Dec 2030 09:37:37: 3034 ACCVRAIZ1.pem
26 Oct 2010 08:38:03 - 26 Oct 2040 08:38:03: 6620 Buypass_Class_2_Root_CA.pem
19 Jan 2010 00:00:00 - 18 Jan 2038 23:59:59: 5609 COMODO_RSA_Certification_Authority.pem
13 Nov 2012 00:00:00 - 19 Jan 2038 03:14:07: 5609 GlobalSign_ECC_Root_CA_-_R4.pem
06 Apr 2001 07:29:40 - 06 Apr 2021 07:29:40: -522 Sonera_Class_2_Root_CA.pem
29 Jun 2004 17:39:16 - 29 Jun 2034 17:39:16: 4310 Starfield_Class_2_CA.pem
04 Feb 2016 12:32:16 - 31 Dec 2029 17:23:16: 2669 TrustCor_RootCert_CA-1.pem
01 Nov 2004 17:14:04 - 01 Jan 2035 05:37:19: 4495 XRamp_Global_CA_Root.pem
...
更加完整狂欢x509 读数:
for file in /etc/ssl/certs/*pem;do
mapfile -t x509 < <(openssl x509 -noout -dates -subject -in "$file")
x509=("${x509[@]#*=}")
mapfile -t dates < <(IFS=$'
';date -f - <<<"${x509[*]::2}" +%s)
str="${x509[-1]}"
declare -A Subj='([CN]="${file##*/}")'
while [[ "$str" ]] ;do
lhs=${str%%=*} rhs=${str#$lhs= } rhs=${rhs%% = *} rhs=${rhs%, *}
Subj[${lhs// }]="$rhs"
str=${str#"$lhs= $rhs"} str=${str#, }
done
printf "%(%d %b %Y %T)T - %(%d %b %Y %T)T: %s
" \n ${dates[@]} "${Subj[CN]}"
done
05 May 2011 09:37:37 - 31 Dec 2030 09:37:37: 3034 ACCVRAIZ1
26 Oct 2010 08:38:03 - 26 Oct 2040 08:38:03: 6620 Buypass Class 2 Root CA
19 Jan 2010 00:00:00 - 18 Jan 2038 23:59:59: 5609 COMODO RSA Certification Authority
13 Nov 2012 00:00:00 - 19 Jan 2038 03:14:07: 5609 GlobalSign
06 Apr 2001 07:29:40 - 06 Apr 2021 07:29:40: -522 Sonera Class2 CA
29 Jun 2004 17:39:16 - 29 Jun 2034 17:39:16: 4310 Starfield_Class_2_CA.pem
04 Feb 2016 12:32:16 - 31 Dec 2029 17:23:16: 2669 TrustCor RootCert CA-1
01 Nov 2004 17:14:04 - 01 Jan 2035 05:37:19: 4495 XRamp Global Certification Authority
...
注意:有些证书在主题中没有CN
字段。为此,我$Subj
通过将字段设置为文件名来初始化数组CN
:declare -A Subj='([CN]="${file##*/}")'
满的狂欢脚本
这里分享一个完整的 bash 脚本,显示来自命令行参数的所有证书,可以通过file
、domain name
或 来显示IPv4 address
。将在一行(长行)中输出过去几天、剩余天数、替代域的数量和所有alt :
#!/bin/bash
showCert() {
local x509 dates lhs rhs str alts
mapfile -t x509 < <(
openssl x509 -noout -dates -subject -ext subjectAltName -in "$1")
x509=("${x509[@]#*=}")
mapfile -t dates < <(IFS=$'
';date -f - <<<"${x509[*]::2}" +%s)
str="${x509[2]}"
local -A Subj;Subj[CN]="${file##*/}"
while [[ -n "$str" ]]; do
lhs=${str%%=*} rhs=${str#$lhs= } rhs=${rhs%% = *} rhs=${rhs%, *}
Subj[${lhs// }]="$rhs"
str=${str#"$lhs= $rhs"} str=${str#, }
done
read -ra alts <<<"${x509[4]//,}"
alts=("${alts[@]#*:}")
printf " %(%d %b %Y %H:%M)T %(%d %b %Y %H:%M)T %6d %6d %-30s %3d %s
" \n "${dates[@]}" $(((dates[1]-EPOCHSECONDS)/86400)) $(((EPOCHSECONDS-
dates[0])/86400)) "${Subj[CN]}" "${#alts[@]}" "${alts[*]}"
}
checkIsIpv4() { # throw an error if not valid IPv4
local _iPointer _i _a _vareq=()
for _i ;do
case $_i in *[^0-9.]* ) return 1 ;; esac
read -ra _a <<<"${_i//./ }"
[ ${#_a[@]} -eq 4 ] || return 1
for _iPointer in "${_a[@]}" ;do
(( _iPointer == ( _iPointer & 255 ) )) || return 2
done
done
}
checkIsLabel() {
((${#1}<4 || ${#1}>253)) && return 1
[[ -z ${1//[a-zA-Z0-9.-]} ]] || return 2
[[ -z ${1//.} ]] && return 3
set -- ${1//./ }
(($#<2 )) && return 4
:
}
printf ' %-17s %-17s %6s %6s %-30s %2s
' Not before Not after left \n past Common Name Alt
for arg ;do
if [ -f "$arg" ] ;then
showCert "$arg"
elif checkIsLabel "$arg" || checkIsIpv4 "$arg" ;then
showCert <(openssl s_client -ign_eof -connect "$arg:443" \n <<<$'HEAD / HTTP/1.0
' 2> /dev/null)
else
echo "Unknown argument: '$arg'."
fi
done
解释
函数
showCert
创建一个包含日期、主题和替代名称的数组变量$x590
。使用
mapfile
和(仅1个分支)date
转换开始 日期 和 结束日期。创建一个关联数组变量
$Subj
来解析主题字符串(第三行${x509[2]}
:)将备选 名称拆分到 另一个数组中:
$alts
.使用
printf
格式化和打印每个证书显示开始日期,
结束日期,
剩余天数,
过去的日子里,
通用名称,
替代名称的数量和
替代名称。
使用示例:
./certShow.sh /etc/ssl/certs/ssl-cert-snakeoil.pem www.example.com
Not before Not after left past Common Name Alt
08 Sep 2021 16:49 06 Sep 2031 16:49 3277 372 hostname.local 1 hostname.local
14 Mar 2022 00:00 14 Mar 2023 23:59 179 186 www.example.org 8 www.example.org example.net example.edu example.com example.org www.example.com www.example.edu www.example.net
解决方案 9:
对于 MAC OSX (El Capitan),Nicholas 示例的这个修改对我有用。
for pem in /path/to/certs/*.pem; do
printf '%s: %s
' \n "$(date -jf "%b %e %H:%M:%S %Y %Z" "$(openssl x509 -enddate -noout -in "$pem"|cut -d= -f 2)" +"%Y-%m-%d")" \n "$pem";
done | sort
示例输出:
2014-12-19: /path/to/certs/MDM_Certificate.pem
2015-11-13: /path/to/certs/MDM_AirWatch_Certificate.pem
macOS 不喜欢我的系统上的--date=
或--iso-8601
标志。
解决方案 10:
如果(出于某种原因)您想在 Linux 中使用 GUI 应用程序,请使用gcr-viewer
(在大多数发行版中,它由包安装gcr
(否则在包中gcr-viewer
))
gcr-viewer file.pem
# or
gcr-viewer file.crt
解决方案 11:
这是用于跟踪您的 Letsencrypt 或其他证书的更新的 bash 脚本。结果已排序,方便查看。
#!/bin/sh
echo "Certs expiration"
for filename in /etc/letsencrypt/live/*/cert.pem; do
cert=$(openssl x509 -enddate -subject -noout -in "$filename")
date=$(echo "$cert" | awk 'FNR == 1' | cut -c10- | date +%s -f -)
dexp=$(echo "$cert" | awk 'FNR == 1' | cut -c10-)
subj=$(echo "$cert" | awk 'FNR == 2' | cut -c14-)
echo "$date $dexp $subj"
done | sort -n -k1 | cut -d' ' -f2- | awk '{print "- "$0}'
您可以调整存储证书的路径。
输出示例:
Certs expiration
- Sep 30 03:30:14 2024 GMT example1.com
- Sep 30 03:31:19 2024 GMT example1.org
- Oct 7 03:31:04 2024 GMT example2.com
- Oct 7 03:40:39 2024 GMT example2.org
- Oct 7 07:35:30 2024 GMT example3.com
享受!
解决方案 12:
我制作了一个与之相关的 bash 脚本来检查证书是否已过期。如果需要,您可以使用它。
脚本
https://github.com/zeeshanjamal16/usefulScripts/blob/master/sslCertificateExpireCheck.sh
自述
https://github.com/zeeshanjamal16/usefulScripts/blob/master/README.md
解决方案 13:
使用openssl
这是一个打印出人类可读文本的脚本cert-etime-check.sh
#!/bin/bash
set -euo pipefail
### get a cert file
declare -r cert_file=${1:? error ... cert_file ?}
### start and end dates
declare -r beg_date=$(openssl x509 -noout -startdate -in $cert_file)
declare -r end_date=$(openssl x509 -noout -enddate -in $cert_file)
### subject and issuer
declare -r subject=$(openssl x509 -noout -subject -in $cert_file)
declare -r issuer=$(openssl x509 -noout -issuer -in $cert_file)
### calculate days gone and left
declare -ir beg_sec=$(date --date="${beg_date##*=}" +%s)
declare -ir end_sec=$(date --date="${end_date##*=}" +%s)
declare -ir now_sec=$(date +%s)
declare -ir day_gone=$(( $((now_sec - beg_sec)) / 86400))
declare -ir day_left=$(( $((end_sec - now_sec)) / 86400))
### print result
date --date="${beg_date##*=}" +"beg: %F-%A (gone: $day_gone)"
date --date="${end_date##*=}" +"end: %F-%A (left: $day_left)"
echo sum: $((day_gone + $day_left))
echo sub: ${subject##* = }
echo iss: ${issuer##* = }
echo
date +"now: %F-%A"
用法:./cert-etime-check.sh cert.pem
输出:
beg: 2024-03-04-Monday (gone: 26)
end: 2024-06-02-Sunday (left: 63)
sum: 89
sub: ******.***
iss: R3
now: 2024-03-31-Sunday
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理必备:盘点2024年13款好用的项目管理软件