Subversion Repositories sysadmin_scripts

Rev

Rev 182 | Rev 185 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

#! /usr/bin/env perl

# Creates a private key, Signing Request, and signed certificate file
# for a target service. Tested on Apache2
#
# Run with the primary domain name as the first parameter, optionally
# followed by one or more alias names. The certificate will be valid
# for all names passed on command line
#
# CA (key and crt) are in the variables $caCRT and $caKey and new files
# are placed in $serverCertDir and named based on the first parameter
#
# An ext file is created, if it doesn't exist, from $sslConfig and
# used to set defaults for the actual csr and crt file creation

use strict;
use warnings;

use FindBin;
use File::Spec;
use Cwd 'abs_path';
use File::Basename;

my $binDir = dirname( abs_path( __FILE__ ) ) . '/';
my $config = $binDir . "makeCert.conf";
my $sslConfig = $binDir . 'openssl.cnf';

die "$config\n";

my $configFile;    # prototype for the domain specific config file
my $caCRT;         # location of the CA crt file
my $caKey;         # location of the CA Key file
my $serverCertDir; # where to put the server certs
my $certDays;      # number of days a certificate is valid for
my $caDays;        # number of days a CA is good for (not used in this script)


die "Config File $config not found\n" unless -f $config;
die "openssl config file $sslConfig not found\n" unless -f $sslConfig;

eval `cat $config`;

die "Can not find CA Cert $caCRT\n" unless -f $caCRT;
die "Can not find CA Key $caKey\n" unless -f $caKey;


# they must pass in at least a domain. All other cli params taken as aliases
# this will also be the filename for each file created, ie $DOMAIN.extension
my $DOMAIN = shift;
die "Usage: $0 domain [alias alias]\n" unless $DOMAIN;

# if the domain doesn't have an ext file, create it
if ( ! -f "$DOMAIN.ext" ) {
   my @newLines;
   # read in the default config file
   open CNF, "<$configFile" or die "Could not read $configFile: $!\n";
   my @config = <CNF>;
   close CNF;
   # remove all line endings
   chomp @config;
   my $line = 0;
   my $inAltNames = 0;
   for my $line ( @config ) {
      if ( $line =~ m/^\[\s*alt_names\s*\]/ ) {
         $inAltNames = 1;
         next;
      }
      if ( $inAltNames ) {
         next if $line !~ m/^\[/;
         $inAltNames = 0;
      }
      push @newLines, $line;
   }
   # start the alt_names section
   push @newLines, '[ alt_names ]';
   # the first DNS entry is the actual domain.
   push @newLines, "DNS.1=$DOMAIN";
   my $dns = 2;
   # read in all aliases and add them as a separate DNS entry
   while ( my $alias = shift ) {
      push @newLines, "DNS.$dns=$alias";
      $dns++;
   }
   # print the ext file back out
   open CNF, ">$serverCertDir$DOMAIN.ext" or die "Could not write to $serverCertDir$DOMAIN.ext: $!\n";
   print CNF join( "\n", @newLines ) . "\n";
   close CNF;
}

# Create an rsa key into $DOMAIN.key
`openssl genpkey -algorithm RSA -out $serverCertDir$DOMAIN.key -pkeyopt rsa_keygen_bits:2048`;
# create a signing request, using $DOMAIN.ext for all the DN stuff saved in $DOMAIN.csr
`openssl req -config $configFile -key $serverCertDir$DOMAIN.key -new -out $serverCertDir$DOMAIN.csr`;
# generate the actual crt file as $DOMAIN.crt, using the csr and ext file
`openssl x509 -req -in $serverCertDir$DOMAIN.csr -CA $caCRT -CAkey $caKey -CAcreateserial -out $serverCertDir$DOMAIN.crt -days $certDays -extensions req_ext -extfile $serverCertDir$DOMAIN.ext`;

print "key and crt created. Use the following command to view the certificate\nopenssl x509 -in $DOMAIN.crt -text -noout\n";
1;