Subversion Repositories sysadmin_scripts

Rev

Rev 184 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
179 rodolico 1
#! /usr/bin/env perl
2
 
182 rodolico 3
# Creates a private key, Signing Request, and signed certificate file
4
# for a target service. Tested on Apache2
5
#
6
# Run with the primary domain name as the first parameter, optionally
7
# followed by one or more alias names. The certificate will be valid
8
# for all names passed on command line
9
#
10
# CA (key and crt) are in the variables $caCRT and $caKey and new files
11
# are placed in $serverCertDir and named based on the first parameter
12
#
13
# An ext file is created, if it doesn't exist, from $sslConfig and
14
# used to set defaults for the actual csr and crt file creation
15
 
179 rodolico 16
use strict;
17
use warnings;
18
 
182 rodolico 19
use FindBin;
20
use File::Spec;
21
use Cwd 'abs_path';
22
use File::Basename;
179 rodolico 23
 
182 rodolico 24
my $binDir = dirname( abs_path( __FILE__ ) ) . '/';
25
my $config = $binDir . "makeCert.conf";
26
my $sslConfig = $binDir . 'openssl.cnf';
27
 
28
my $configFile;    # prototype for the domain specific config file
29
my $caCRT;         # location of the CA crt file
30
my $caKey;         # location of the CA Key file
31
my $serverCertDir; # where to put the server certs
32
my $certDays;      # number of days a certificate is valid for
33
my $caDays;        # number of days a CA is good for (not used in this script)
34
 
35
 
36
die "Config File $config not found\n" unless -f $config;
37
die "openssl config file $sslConfig not found\n" unless -f $sslConfig;
38
 
39
eval `cat $config`;
40
 
41
die "Can not find CA Cert $caCRT\n" unless -f $caCRT;
42
die "Can not find CA Key $caKey\n" unless -f $caKey;
43
 
185 rodolico 44
# this is a sloppy IPv4 recognizer, but it is faster than the more accurate
45
# ^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$
46
# See https://www.oreilly.com/library/view/regular-expressions-cookbook/9780596802837/ch07s16.html
47
my $ipv4Regex = '^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$';
182 rodolico 48
 
179 rodolico 49
# they must pass in at least a domain. All other cli params taken as aliases
50
# this will also be the filename for each file created, ie $DOMAIN.extension
51
my $DOMAIN = shift;
52
die "Usage: $0 domain [alias alias]\n" unless $DOMAIN;
53
 
185 rodolico 54
my $extFile = $serverCertDir . "$DOMAIN.ext";
55
my $crtFile = $serverCertDir . "$DOMAIN.crt";
56
my $keyFile = $serverCertDir . "$DOMAIN.key";
57
my $csrFile = $serverCertDir . "$DOMAIN.csr";
58
 
179 rodolico 59
# if the domain doesn't have an ext file, create it
185 rodolico 60
if ( ! -f $extFile ) {
61
   print "EXT File not found, creating new one\n";
182 rodolico 62
   my @newLines;
179 rodolico 63
   # read in the default config file
64
   open CNF, "<$configFile" or die "Could not read $configFile: $!\n";
65
   my @config = <CNF>;
66
   close CNF;
67
   # remove all line endings
68
   chomp @config;
182 rodolico 69
   my $line = 0;
70
   my $inAltNames = 0;
71
   for my $line ( @config ) {
185 rodolico 72
      if ( $line =~ m/^CN\s*=/ ) { # here is the common name; change it
73
         $line = "CN = $DOMAIN";
74
      } elsif ( $line =~ m/^\[\s*alt_names\s*\]/ ) {
182 rodolico 75
         $inAltNames = 1;
76
         next;
77
      }
78
      if ( $inAltNames ) {
79
         next if $line !~ m/^\[/;
80
         $inAltNames = 0;
81
      }
82
      push @newLines, $line;
83
   }
84
   # start the alt_names section
85
   push @newLines, '[ alt_names ]';
179 rodolico 86
   # the first DNS entry is the actual domain.
185 rodolico 87
   # it will work, but is mislabeled, if $DOMAIN is actually an IP
182 rodolico 88
   push @newLines, "DNS.1=$DOMAIN";
179 rodolico 89
   my $dns = 2;
90
   # read in all aliases and add them as a separate DNS entry
185 rodolico 91
   # pretty sloppy in that we don't track IP and DNS separately
92
   # and we are using a sloppy regex to detect IP's, but it
93
   # is pretty fast.
179 rodolico 94
   while ( my $alias = shift ) {
185 rodolico 95
      push @newLines, ($alias =~ m/$ipv4Regex/ ? 'IP' : 'DNS' ) . ".$dns=$alias";
179 rodolico 96
      $dns++;
97
   }
98
   # print the ext file back out
185 rodolico 99
   open CNF, ">$extFile" or die "Could not write to $extFile: $!\n";
182 rodolico 100
   print CNF join( "\n", @newLines ) . "\n";
179 rodolico 101
   close CNF;
102
}
103
 
185 rodolico 104
die;
105
 
179 rodolico 106
# Create an rsa key into $DOMAIN.key
185 rodolico 107
`openssl genpkey -algorithm RSA -out $keyFile -pkeyopt rsa_keygen_bits:2048`;
179 rodolico 108
# create a signing request, using $DOMAIN.ext for all the DN stuff saved in $DOMAIN.csr
185 rodolico 109
`openssl req -config $extFile -key $keyFile -new -out $csrFile`;
179 rodolico 110
# generate the actual crt file as $DOMAIN.crt, using the csr and ext file
185 rodolico 111
`openssl x509 -req -in $csrFile -CA $caCRT -CAkey $caKey -CAcreateserial -out $crtFile -days $certDays -extensions req_ext -extfile $extFile`;
179 rodolico 112
 
185 rodolico 113
print "key and crt created. Use the following command to view the certificate\nopenssl x509 -in $crtFile -text -noout\n";
114
print "and the following to view CSR\nopenssl req -in $csrFile -text -noout\n";
179 rodolico 115
1;