Skip to content

Commit da5db58

Browse files
committed
pull in additional files supporting self-signed cert generation
1 parent bbd9047 commit da5db58

File tree

2 files changed

+223
-0
lines changed

2 files changed

+223
-0
lines changed
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#!/bin/bash
2+
set -x
3+
4+
DATADIR=$1
5+
USER=$2
6+
GROUP=$3
7+
SUBJECT=$4
8+
DAYS=$5
9+
FORCE=$6
10+
FORCE+=0
11+
12+
if [[ "$FORCE" -eq 1 ]]
13+
then
14+
[ -f "$DATADIR/server.key" ] && /bin/rm "$DATADIR/server.key"
15+
[ -f "$DATADIR/server.crt" ] && /bin/rm "$DATADIR/server.crt"
16+
[ -f "$DATADIR/root.crt" ] && /bin/rm "$DATADIR/root.crt"
17+
fi
18+
19+
/usr/bin/openssl genrsa -des3 -passout pass:puppetlabs-postgresql -out "$DATADIR/server.key" 1024
20+
/usr/bin/openssl rsa -passin pass:puppetlabs-postgresql -in "$DATADIR/server.key" -out "$DATADIR/server.key"
21+
/usr/bin/openssl req -new -key "$DATADIR/server.key" -days "$DAYS" -out "$DATADIR/server.crt" -x509 -subj "$SUBJECT"
22+
/bin/chown "$USER:$GROUP" "$DATADIR/server.key"
23+
/bin/chmod 0400 "$DATADIR/server.key"
24+
/bin/cp "$DATADIR/server.crt" "$DATADIR/root.crt"
25+
26+
EXIT_CODE=`$DATADIR/validate_self_signed_ssl_certificate.pl -p $DATADIR -s "$SUBJECT" -d $DAYS`
27+
exit $EXIT_CODE
28+
29+
# Contributed by Hugh Esco <[email protected]>
30+
# YMD Partners LLC
31+
# to the puppetlabs-postgresql module
32+
# https://github.com/hesco/puppetlabs-postgresql#class-postgresqlserverssl_certificate
33+
Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
#!/usr/bin/env perl
2+
use strict;
3+
use warnings;
4+
5+
use Getopt::Std;
6+
use Time::Piece;
7+
use Time::Seconds;
8+
use Data::Dumper;
9+
10+
our $VERSION = '0.01';
11+
12+
$Getopt::Std::STANDARD_HELP_VERSION = 1;
13+
our( $opt_h, $opt_p, $opt_s, $opt_d );
14+
getopts('hp:s:d:');
15+
my $DATADIR = $opt_p;
16+
my $SUBJECT = $opt_s;
17+
my $DAYS = $opt_d;
18+
my $view_cert_command = 'openssl x509 -noout -text -in ';
19+
20+
if( $opt_h || ! defined( $DATADIR ) || ! defined( $SUBJECT ) || ! defined( $DAYS ) ){
21+
HELP_MESSAGE();
22+
exit 1;
23+
}
24+
25+
my $result = 0;
26+
foreach my $cert ( 'server', 'root' ){
27+
my $cert_params = parse_cert( $cert );
28+
my $subject = parse_subject( $SUBJECT );
29+
my @cert_stats = stat("$DATADIR/$cert.crt");
30+
$subject->{'file_stat'} = gmtime( $cert_stats[9] )->strftime;
31+
$result += evaluate_results( $cert_params, $subject, $DAYS );
32+
# print Dumper $subject, $cert_params;
33+
}
34+
35+
print $result;
36+
exit $result;
37+
38+
sub VERSION_MESSAGE {
39+
print "$0 -- version: $VERSION \n";
40+
return;
41+
}
42+
43+
sub HELP_MESSAGE {
44+
# VERSION_MESSAGE();
45+
print <<"END_OF_USAGE";
46+
47+
Usage: $0 -p /var/lib/postgresql/9.3/main -s '/C=US/ST=GA/L=Atlanta/O=YMDPartnersLLC/CN=pg.example.com/emailAddress=dba\@example.com' -d 3650
48+
-h Display this usage message and exit
49+
-p provide a Path to the postgresql \$PG_DATA directory
50+
-s provide the -subj line used to create the certificate being tested
51+
-d provide the -days argument used to build certificate being tested
52+
--version Display the script's version number
53+
The -p, -s and -d switches are required.
54+
55+
END_OF_USAGE
56+
return;
57+
}
58+
59+
sub evaluate_results {
60+
my $got = shift;
61+
my $expected = shift;
62+
my $days = shift;
63+
64+
my $result = 0;
65+
my @keys = keys %{$expected};
66+
KEY: foreach my $key ( @keys ){
67+
if ( $key =~ /^(before|after|file_stat)$/ ){ next KEY; }
68+
unless( exists( $got->{ $key } ) && exists( $expected->{ $key } ) ){
69+
print STDERR "$key not defined in both \$got and \$expected \n";
70+
next KEY;
71+
}
72+
unless ( $got->{ $key } eq $expected->{ $key } ){
73+
print STDERR "Certificate fails to match data for $key \n";
74+
$result++;
75+
}
76+
}
77+
78+
$result += evaluate_result_dates( $got, $expected, $days );
79+
return $result;
80+
}
81+
82+
sub evaluate_result_dates {
83+
my $got = shift;
84+
my $expected = shift;
85+
my $days = shift;
86+
my $result = 0;
87+
88+
# print 'file_stat: ' . $expected->{'file_stat'} . "\n";
89+
# print 'before: ' . $got->{'before'} . "\n";
90+
# print 'after: ' . $got->{'after'} . "\n";
91+
92+
my $format = '%a, %d %b %Y %T';
93+
# print "$format \n";
94+
95+
$expected->{'file_stat'} =~ s/ UTC$//;
96+
$got->{'before'} =~ s/ UTC$//;
97+
$got->{'after'} =~ s/ UTC$//;
98+
99+
my $file_stat = Time::Piece->strptime( $expected->{'file_stat'}, $format );
100+
my $before = Time::Piece->strptime( $got->{'before'}, $format );
101+
my $after = Time::Piece->strptime( $got->{'after'}, $format );
102+
103+
unless( $file_stat - $before < ( 5 * 60 ) ){
104+
print STDERR "Certificate file created more than five minutes after cert's Not Before timestamp.\n";
105+
$result++;
106+
}
107+
if( $before + ( 60*60*24*( $days - 1 ) ) > $after
108+
|| $before + ( 60*60*24*( $days +2 ) ) < $after ){
109+
print STDERR "Certificate's Not After date outside of tolerance: \n";
110+
print STDERR " Not Before: " . $got->{'before'} . "\n";
111+
print STDERR " Not After : " . $got->{'after'} . "\n";
112+
print STDERR " -days : $days \n";
113+
$result++;
114+
}
115+
116+
return $result;
117+
}
118+
119+
sub get_cert_contents {
120+
my $view_cert = shift;
121+
my @cert_content = split "\n", $view_cert;
122+
return \@cert_content;
123+
}
124+
125+
sub parse_subject {
126+
my $subject = shift;
127+
my %subject;
128+
my @subject_params = split '/', $subject;
129+
KV: foreach ( @subject_params ){
130+
my ($key, $value) = split '=', $_;
131+
unless( defined( $key ) ){ next KV; }
132+
chomp( $key );
133+
chomp( $value );
134+
$subject{$key} = $value;
135+
}
136+
return \%subject;
137+
}
138+
139+
sub parse_cert {
140+
my $cert = shift;
141+
my $cert_file = "$DATADIR/$cert.crt";
142+
my $view_cert = `$view_cert_command $cert_file`;
143+
my $cert_content = get_cert_contents( $view_cert );
144+
my %cert_params;
145+
my @cert_times = map {
146+
$_ =~ /^\ *Not (.*): (.*)$/;
147+
my $k = $1;
148+
my $v = $2;
149+
$k =~ s/\ *$//;
150+
$cert_params{ lc( $k ) } = Time::Piece->strptime( $v, '%b %d %T %Y %Z' )->strftime;
151+
# $cert_params{ lc( $k ) } = $v;
152+
} grep { /^\ *Not / } @{$cert_content};
153+
my @subject = grep { /^\ *Subject: / } @{$cert_content};
154+
my @kv = split /[:,\/]\ ?/, $subject[0];
155+
KV: foreach my $kv ( @kv ){
156+
my ($key, $value) = split '=', $kv;
157+
if( $key =~ m/Subject/ ){ next KV; }
158+
$cert_params{$key} = $value;
159+
}
160+
return \%cert_params;
161+
}
162+
163+
=head1 NAME
164+
165+
validate_self_signed_ssl_certificate.pl
166+
167+
=head1 VERSION
168+
169+
Version 0.01
170+
171+
=head1 SYNOPSIS
172+
173+
perl validate_self_signed_ssl_certificate.pl --help
174+
175+
will provide a usage message
176+
177+
This script intended for use by the postgresql::server::ssl_certificate class
178+
of the puppetlabs-postgresql module to validate the installation of the server.crt
179+
and the root.crt it installs in a Postgresql $PG_DATA directory.
180+
181+
=head1 COPYRIGHT
182+
183+
Contributed by Hugh Esco <[email protected]>
184+
YMD Partners LLC
185+
to the puppetlabs-postgresql module
186+
https://github.com/hesco/puppetlabs-postgresql#class-postgresqlserverssl_certificate
187+
188+
~
189+
=cut
190+

0 commit comments

Comments
 (0)