|
1 #! /usr/bin/perl |
|
2 |
|
3 use 5.010; |
|
4 use strict; |
|
5 use warnings; |
|
6 use Pod::Usage; |
|
7 use Getopt::Long; |
|
8 use Template; |
|
9 #use autodie; |
|
10 |
|
11 my $DIR = "requests"; |
|
12 |
|
13 my $opt_template = "request.cnf"; |
|
14 my $opt_check; |
|
15 my $opt_init; |
|
16 |
|
17 sub genpw($); |
|
18 |
|
19 MAIN: { |
|
20 GetOptions( |
|
21 "template=s" => \$opt_template, |
|
22 "init" => \$opt_init, |
|
23 "check" => \$opt_check, |
|
24 "h|help" => sub { pod2usage(-exit => 0, -verbose => 1) }, |
|
25 "m|man" => sub { pod2usage(-exit => 0, -verbose => 2, |
|
26 -noperldoc => system("perldoc -V >/dev/null 2>&1")) } |
|
27 ) or pod2usage; |
|
28 |
|
29 my $CN = shift; |
|
30 mkdir($DIR), exit if $opt_init; |
|
31 |
|
32 pod2usage if not defined $CN; |
|
33 |
|
34 exit(-f "$DIR/$CN/csr.pem" ? 0 : 1) |
|
35 if $opt_check; |
|
36 |
|
37 rmdir($_ = "$DIR/$CN"); # succeeds if empty |
|
38 mkdir($_ = "$DIR/$CN") or die "directory $_: $!\n"; |
|
39 |
|
40 # create the config template |
|
41 my $tt = Template->new( |
|
42 INCLUDE_PATH => "ca/templates", |
|
43 ) or die "$Template::ERROR\n"; |
|
44 $tt->process($opt_template, { CN => $CN }, "$DIR/$CN/openssl.cnf") |
|
45 or die $tt->error, "\n"; |
|
46 $ENV{OPENSSL_CONF} = "$DIR/$CN/openssl.cnf"; |
|
47 |
|
48 # create the password file |
|
49 open(my $pw, ">", $_ = "$DIR/$CN/secret") or die "$_: $!\n"; |
|
50 say $pw genpw(10); |
|
51 close($pw); |
|
52 |
|
53 system(openssl => "req", |
|
54 qw(-new), |
|
55 -keyout => "$DIR/$CN/key.pem", |
|
56 -out => "$DIR/$CN/csr.pem", |
|
57 -passout => "file:$DIR/$CN/secret"); |
|
58 } |
|
59 |
|
60 sub genpw($) { |
|
61 my $n = shift; |
|
62 my @chars = (qw(_ . - /), "a".."z", "A".."Z", 0..9); |
|
63 join "" => map { @chars[rand @chars + 1] } (1..$n); |
|
64 } |
|
65 |
|
66 |
|
67 __END__ |
|
68 |
|
69 =head1 NAME |
|
70 |
|
71 request - generate a ssl certificate request |
|
72 |
|
73 =head1 SYNOPSIS |
|
74 |
|
75 request [--init] |
|
76 request [--template={file}] {CN} |
|
77 |
|
78 =head1 DESCRIPTION |
|
79 |
|
80 B<request> generates a new SSL certificate signing request. The files |
|
81 (CSR and KEY) are placed in F<requests>. The generated key is protected |
|
82 by a passphrase. The passphrase is written to stdout and has to be saved |
|
83 by the caller! |
|
84 |
|
85 =head1 OPTIONS |
|
86 |
|
87 =over |
|
88 |
|
89 =item B<--template> I<file> |
|
90 |
|
91 The template file to be used for creating the request. The templates will be searched |
|
92 unter F<ca/templates>. The only substituted item is [%CN%]. (default: request.cnf) |
|
93 |
|
94 =cut |
|
95 |
|
96 # vim:sts=4 ts=4 sw=4 aw ai sm: |