#!/usr/bin/env perl use strict; use warnings; use Carp; use Getopt::Long; use Pod::Usage; use Data::Dumper; use Net::SSL::ExpireDate; use Regexp::Common qw(net); use YAML; use URI::Escape; # use Smart::Comments; MAIN: { my %opt; Getopt::Long::Configure("bundling"); GetOptions(\%opt, 'duration|d=s', 'file|f=s', 'link|l', 'help|h|?') or pod2usage(-verbose=>1); pod2usage(-verbose=>1) if exists $opt{'help'}; pod2usage("missing option: --file") unless exists $opt{'file'}; ### %opt open my $file, '<', $opt{'file'} or croak "$opt{'file'}: $!"; chomp (my @testee = <$file>); close $file; ### @testee my $duration = exists $opt{'duration'} ? $opt{'duration'} : undef; ### $duration my $output = { title => 'Certificate Expire Date', entry => [], }; for my $t (@testee) { next if $t =~ /^#/; next if $t =~ /^$/; ### testee: $t my $ed = Net::SSL::ExpireDate->new( build_arg($t) ); if ($ed->is_expired($duration)) { ### expired: $ed->expire_date->iso8601 push @{$output->{entry}}, { title => $t . ($duration ? " (expire within $duration)" : ''), date => $ed->expire_date->iso8601, }; ${ $output->{entry} }[-1]->{link} = mk_link($ed, $duration) if $opt{'link'}; } } print YAML::Dump $output; exit 0; } sub build_arg { my ($v) = @_; if ($v =~ m{^(file)://(.+)}) { return $1 => $2; } elsif ($v =~ m{^(https)://([^/]+)}) { return $1 => $2; } elsif ($v =~ m{^$RE{net}{domain}{-nospace}{-keep}$}) { return 'https' => $1; } elsif (-r $v) { return 'file' => $v; } else { croak "$v: assume file. but cannot read."; } } sub mk_link { my ($ed, $duration) = @_; $ed->type . '://' . $ed->target . ($duration ? '#' . uri_escape($duration) : ''); } __END__ =head1 NAME B - check and list expired certificates =head1 SYNOPSIS B [ B<--help> ] [ B<--duration> DURATION ] B<--file> DATAFILE $ cat < server-list.txt https://rt.cpan.org https://www.google.com EOF $ check-cert-expire.pl --duration '3 months' --file server-list.txt $ check-cert-expire.pl -d '3 months' -f server-list.txt --- entry: - date: 2015-04-14T05:12:17 title: https://rt.cpan.org title: Certificate Expire Date =head1 DESCRIPTION Examine expire date of certificate and output name and expire date if expired. Output format is YAML. Examinee certificate is both OK via network (HTTPS) and local file. =head1 OPTIONS =over 4 =item B<--file> DATAFILE =item B<-f> DATAFILE DATAFILE is name of plain text file contains testee list. Acceptable list format is the following. FORMAT EXAMPLE =============================== https://FQDN https://rt.cpan.org file://PATH file:///etc/ssl/cert.pem FQDN rt.cpan.org PATH /etc/ssl/cert.pem =item B<--duration> DURATION =item B<-d> DURATION Specify the furtur point to check expiration. If omitted, check against just now. DURATION accepts human readable text. See also L. 3 days 4 months 10 years 4 months and 3days =item B<--link> =item B<-l> Add dummy link attribute. =back =head1 SEE ALSO L, L =head1 AUTHOR HIROSE, Masaaki Ehirose31@gmail.comE =cut # for Emacsen # Local Variables: # mode: cperl # cperl-indent-level: 4 # indent-tabs-mode: nil # End: # vi: set ts=4 sw=4 sts=0 :