如果我有实际文件和Mac或linux中的bash shell,我该如何查询证书文件的过期?不是一个网站,而是实际上证书文件本身,假设我有CSR,密钥,PEM和链条文件。
with openssl
:
openssl x509 -enddate -noout -in file.pem
输出在表单上:
notAfter=Nov 3 22:23:50 2014 GMT
还请参见Mikew的答案,以了解如何轻松检查证书是否已过期,或者是否会在一定时间段内,而无需分析上述日期。
如果您只想知道证书是否已过期(或在接下来的N秒内进行),则-checkend <seconds>
的CC_2选项将告诉您:
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/openssl/openssl/issues/6180). .
这是我的bash命令行,按照其到期顺序列出多个证书,最近首先到期。
for pem in /etc/ssl/certs/*.pem; do
printf '%s: %sn'
"$(date --date="$(openssl x509 -enddate -noout -in "$pem"|cut -d= -f 2)" --iso-8601)"
"$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
命令:
# cat {key_name} | openssl x509 -noout -enddate
Example: # cat tower.cert | openssl x509 -noout -enddate
结果:
notAfter=Dec 7 04:03:32 2023 GMT
这是一个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
与接受的答案相同,但请注意,即使在.crt
文件中也可以使用.pem
文件,以防万一您无法找到.pem
文件位置。
openssl x509 -enddate -noout -in e71c8ea7fa97ad6c.crt
结果:
notAfter=Mar 29 06:15:00 2020 GMT
一行在true/false上检查是否在一段时间内过期(例如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
将openssl
字段存储到bash变量
当这个问题被标记为bash时,我经常使用 UNIX EPOCH
存储日期,这对于用$EPOCHSECONDS
剩下的计算时间和通过printf '%(dateFmt)T
bashism ::
{ 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)Tn' 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 %sn"
$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
...
更完整的bash 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=$'n';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: %sn"
${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
字段。为此,我通过将CN
字段设置为文件名来初始化$Subj
数组: declare -A Subj='([CN]="${file##*/}")'
完整的bash脚本
在此处共享一个完整的bash脚本,显示了命令行参数的所有证书,可以通过 file
, domain name
或 IPv4 address
。将过去几天,左右,替代域的数量:
#!/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=$'n';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 %sn"
"${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 %2sn' Not before Not after left
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"
<<<$'HEAD / HTTP/1.0rnr' 2> /dev/null)
else
echo "Unknown argument: '$arg'."
fi
done
解释
- 函数
showCert
创建数组变量$x590
with dates , objection 和objective 和 alt name em>。 - 使用
mapfile
和(仅1个叉子到)date
转换 start 和 end date dates dates << 。/li>- 创建 cossociative数组变量
$Subj
用于解析主题 string(3rd Line:${x509[2]}
)- split 替代名称 array :
$alts
。- 使用
openssl x509
0格式化并打印每个显示的证书- 开始日期,
- 结束日期,
- 左日,
- 几天,
- 通用名称,
- 替代名称的数量和
- 替代名称。
- 创建 cossociative数组变量
用法样本:
./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
对于Mac OSX(El Capitan),尼古拉斯示例的修改对我有用。
for pem in /path/to/certs/*.pem; do
printf '%s: %sn'
"$(date -jf "%b %e %H:%M:%S %Y %Z" "$(openssl x509 -enddate -noout -in "$pem"|cut -d= -f 2)" +"%Y-%m-%d")"
"$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
标志。
如果(出于某种原因)您要在Linux中使用GUI应用程序,请使用gcr-viewer
(在大多数分布中,它是由软件包gcr
安装的(否则在软件包gcr-viewer
中))
gcr-viewer file.pem
# or
gcr-viewer file.crt
我做了一个与该脚本相关的bash脚本,以检查证书是否过期。您可以在需要时使用相同的。
脚本
https://github.com/zeeshanjamal16/usefulscripts/blob/master/ssslcertificateatificateatificateateexpirecheck.sh
readme
https://github.com/zeeshanjamal16/usefulscripts/blob/master/readme.md