備忘録のため,内容の正当性については責任を持ちません。

Perl (というか openssl コマンド) でリモートのサーバに接続し、SSL 証明書の有効期限を取得する方法。


openssl コマンドでリモートのサーバの SSL を証明書を取得するには、s_client を使う。

$ openssl s_client -connect ${host}:${port} -showcerts

取得した証明書から有効期限を取得するには、証明書を openssl x509 にパイプで渡せば良い。

$ ... | openssl x509 -dates -noout

例えば www.google.co.jp:443 のものを取得すると、次のように表示される。

notBefore=Apr 24 12:36:07 2013 GMT
notAfter=Dec 30 00:00:00 2013 GMT

notAfter の値が有効期限なので、これをパースして求める日時フォーマットに変換してやる。今回は Perl の DateTime::Format::Strptime モジュールを使用する。

#!/usr/bin/env perl

use strict;
use warnings;
use DateTime::Format::Strptime;

print &get_ssl_expire($ARGV[0]) . "\n";

sub get_ssl_expire {
    my $host = shift || "";
    my $port = shift || 443;

    return "" if ($host !~ /^[a-z0-9\.\-]+$/i);
    return "" if ($port !~ /^[0-9]+$/);

    my $date;
    my $timeout = 10;
    my $cmd = "echo | openssl s_client -connect $host:$port -showcerts 2> /dev/null";
    $cmd .= " | openssl x509 -dates -noout 2> /dev/null";
    $cmd .= " | grep notAfter | awk -F= '{print \$2}'";
    eval {
        local $SIG{ALRM} = sub {die};
        alarm($timeout);
        $date = qx/$cmd/;
        chomp $date;
        alarm(0);
    };
    return "" if ($@);
    return "" if ($date !~ /^([A-Z][a-z]{2})\s+([0-9]{1,2})\s+[0-9:]{8}\s+([0-9]{4})\s+[A-Z]{3}$/);

    my $strp = DateTime::Format::Strptime->new(pattern => "%b %d %T %Y %Z");

    return $strp->parse_datetime($date)->ymd;
}

実行すると次のようになる。

$ ./get_ssl_expire.pl www.google.co.jp
2013-12-30

別の日時フォーマットで取り出したい場合は、ymd メソッドを適当なものに変更すれば良い。

openssl コマンドを使わずに、証明書の取得も Perl で実現したいなら、Net::SSLeay モジュールを使用するという手もある。


コメント

コメントする




CAPTCHA