File Coverage

blib/lib/App/sslmaker.pm
Criterion Covered Total %
statement 168 174 96.5
branch 60 82 73.1
condition 25 42 59.5
subroutine 34 34 100.0
pod 12 12 100.0
total 299 344 86.9


line stmt bran cond sub pod time code
1             package App::sslmaker;
2 6     6   540582 use strict;
  6         69  
  6         190  
3 6     6   32 use warnings;
  6         11  
  6         178  
4              
5 6     6   37 use Carp qw(confess);
  6         21  
  6         295  
6 6     6   3805 use Data::Dumper ();
  6         42840  
  6         187  
7 6     6   4452 use Path::Tiny;
  6         72518  
  6         387  
8 6     6   2718 use File::umask;
  6         2208  
  6         841  
9              
10 6   50 6   44 use constant DEBUG => $ENV{SSLMAKER_DEBUG} || 0;
  6         14  
  6         470  
11 6   50 6   41 use constant DEFAULT_BITS => $ENV{SSLMAKER_BITS} || 4096;
  6         18  
  6         385  
12 6   50 6   34 use constant DEFAULT_DAYS => $ENV{SSLMAKER_DAYS} || 365;
  6         12  
  6         1730  
13              
14             our $VERSION = '0.18';
15             our $OPENSSL = $ENV{SSLMAKER_OPENSSL} || 'openssl';
16              
17             my @CONFIG_TEMPLATE_KEYS = qw(bits cert crl_days days home key);
18              
19             # heavily inspired by Mojo::Loader::_all()
20             my %DATA = do {
21             seek DATA, 0, 0;
22             my $data = join '', ;
23             $data =~ s/^.*\n__DATA__\r?\n/\n/s;
24             $data =~ s/\n__END__\r?\n.*$/\n/s;
25             $data = [split /^@@\s*(.+?)\s*\r?\n/m, $data];
26             shift @$data; # first element is empty string
27             @$data;
28             };
29              
30             # need to be defined up front
31             sub openssl {
32 35 100   35 1 1815 my $cb = ref $_[-1] eq 'CODE' ? pop : sub { print STDERR $_[1] if DEBUG == 2 and length $_[1] };
  40     40   1366  
33 40 100       144 my $self = ref $_[0] ? shift : __PACKAGE__;
34 40         102 my $buf = '';
35              
36 6     6   2989 use IPC::Open3;
  6         23167  
  6         323  
37 6     6   45 use Symbol;
  6         15  
  6         16377  
38 40         57 $self->_d("\$ $OPENSSL @_") if DEBUG;
39 40         319 my $OUT = gensym;
40 40         1327 my $pid = open3(undef, $OUT, $OUT, $OPENSSL => @_);
41              
42 40         138043 while (1) {
43 1387         2411629 my $l = sysread $OUT, my $read, 8096;
44 1387 50       6751 confess "$OPENSSL: $!" unless defined $l;
45 1387 100       2521 last unless $l;
46 1347         3026 $buf .= $read;
47             }
48              
49 40         970 waitpid $pid, 0;
50 40 100       1176 confess sprintf 'openssl %s FAIL (%s) (%s)', join(' ', @_), $? >> 8, $buf if $?;
51 39         507 $self->$cb($buf);
52             }
53              
54             sub make_cert {
55 4     4 1 20 my ($self, $args) = @_;
56 4 50       91 my $asset = $args->{cert} ? Path::Tiny->new($args->{cert}) : Path::Tiny->tempfile;
57              
58 4         99 local $UMASK = 0222; # make files with mode 444
59 4 50       121 confess '"subject" is required' unless my $subject = $self->_render_subject($self->subject, $args->{subject});
60             openssl qw(req -new -sha256 -x509 -extensions v3_ca),
61             -passin => $self->_passphrase($args->{passphrase}),
62             -days => $args->{days} || DEFAULT_DAYS,
63             -key => $args->{key},
64 4   100     40 -out => $asset->path,
65             -subj => $subject;
66              
67 4         348 return $asset;
68             }
69              
70             sub make_crl {
71 2     2 1 20 my ($self, $args) = @_;
72 2 50       94 my $asset = $args->{crl} ? Path::Tiny->new($args->{crl}) : Path::Tiny->tempfile;
73              
74 2         119 local $UMASK = 0122; # make files with mode 644
75              
76             openssl qw(ca -gencrl),
77             -keyfile => $args->{key},
78             -cert => $args->{cert},
79 2 50       110 $args->{passphrase} ? (-passin => $self->_passphrase($args->{passphrase})) : (), -out => $asset->path;
80              
81 2         94 return $asset;
82             }
83              
84             sub make_csr {
85 8     8 1 1691 my ($self, $args) = @_;
86 8 100       193 my $asset = $args->{csr} ? Path::Tiny->new($args->{csr}) : Path::Tiny->tempfile;
87              
88 8         1454 local $UMASK = 0277; # make files with mode 400
89              
90 8 50       230 confess '"subject" is required' unless my $subject = $self->_render_subject($self->subject, $args->{subject});
91             openssl qw(req -new -sha256), $args->{passphrase} ? (-passin => $self->_passphrase($args->{passphrase})) : (),
92             -key => $args->{key},
93 8 100 100     159 -days => $args->{days} || DEFAULT_DAYS,
94             -out => $asset->path,
95             -subj => $subject;
96              
97 8         393 return $asset;
98             }
99              
100             sub make_directories {
101 7     7 1 3518 my ($self, $args) = @_;
102 7         53 my $home = $self->_home($args);
103 7         475 my $file;
104              
105 7         84 $home->mkpath;
106 7 50       2330 -w $home or confess "Cannot write to $home";
107 7         207 mkdir $home->child($_) for qw(certs csr crl newcerts private);
108 7 50       3571 chmod 0700, $home->child('private') or confess "Could not chmod 0700 'private' in $home";
109              
110 7 50       534 if ($args->{templates}) {
111 7         86 local $UMASK = 0122; # make files with mode 644
112 7 50       250 $self->render_to_file('crlnumber', $file, {}) unless -e ($file = $home->child('crlnumber'));
113 7 50       40 $self->render_to_file('index.txt', $file, {}) unless -e ($file = $home->child('index.txt'));
114 7 50       42 $self->render_to_file('index.txt.attr', $file, {}) unless -e ($file = $home->child('index.txt.attr'));
115 7 50       36 $self->render_to_file('serial', $file, {}) unless -e ($file = $home->child('serial'));
116             }
117              
118 7         90 return $args->{home}; # TBD, but will be true
119             }
120              
121             sub make_key {
122 12     12 1 73 my ($self, $args) = @_;
123 12 100       142 my $asset = $args->{key} ? Path::Tiny->new($args->{key}) : Path::Tiny->tempfile;
124 12         18228 my $passphrase;
125              
126 12         86 local $UMASK = 0277; # make files with mode 400
127              
128 12 100       362 if ($passphrase = $args->{passphrase}) {
129 7         44 $passphrase = $self->_passphrase($passphrase);
130 7 50 33     323 Path::Tiny->new($1)->spew({binmode => ':raw'}, $self->_random_passphrase(64))
131             if $passphrase =~ m!^file:(.+)! and !-e $1;
132             }
133              
134             openssl 'genrsa', $passphrase ? (-aes256 => -passout => $passphrase) : (),
135             -out => $asset->path,
136 12 100 100     3218 $args->{bits} || DEFAULT_BITS;
137              
138 12         616 return $asset;
139             }
140              
141             # copy/paste from Mojo::Base::new()
142             sub new {
143 17     17 1 94797 my $class = shift;
144 17 50 33     495 bless @_ ? @_ > 1 ? {@_} : {%{$_[0]}} : {}, ref $class || $class;
  0 100       0  
145             }
146              
147             sub render_to_file {
148 49     49 1 5249 my $stash = pop;
149 49         192 my ($self, $name, $path) = @_;
150 49         215 my $template = $self->_render_template($name, $stash);
151 49         87 my $asset;
152              
153 49 100       334 $asset = $path ? Path::Tiny->new($path) : Path::Tiny->tempfile;
154 49         103124 $asset->spew({binmode => ":raw"}, $template);
155 49         21966 $asset;
156             }
157              
158             sub revoke_cert {
159 2     2 1 5 my ($self, $args) = @_;
160 2         6 my $home = $self->_home($args);
161              
162 2   33     45 local $args->{crl} = $args->{crl} || $home->child('crl.pem');
163              
164             openssl qw(ca), $args->{passphrase} ? (-passin => $self->_passphrase($args->{passphrase})) : (),
165 2 50       101 -revoke => $args->{revoke};
166              
167 2         71 return $self->make_crl($args); # TBD, but will be true
168             }
169              
170             sub sign_csr {
171 7     7 1 47 my ($self, $args) = @_;
172 7 100       63 my $asset = $args->{cert} ? Path::Tiny->new($args->{cert}) : Path::Tiny->tempfile;
173              
174 7         634 local $UMASK = 0222; # make files with mode 444
175              
176             openssl qw(ca -batch -notext -md sha256),
177             -keyfile => $args->{ca_key},
178             -cert => $args->{ca_cert},
179             -passin => $self->_passphrase($args->{passphrase}),
180             -extensions => $args->{extensions} || 'usr_cert',
181             -out => $asset->path,
182 7   50     200 -in => $args->{csr};
183              
184 7         378 return $asset;
185             }
186              
187             sub subject {
188 20     20 1 1497 my $self = shift;
189 20 100 100     470 return $self->{subject} // $ENV{SSLMAKER_SUBJECT} // '' unless @_;
      100        
190 6         81 $self->{subject} = $self->_render_subject(@_);
191 6         44 return $self;
192             }
193              
194             sub with_config {
195 28     28 1 23560 my ($self, $cb, $args) = @_;
196 28   100     212 my $key = join ':', 'config', map { ($_, $args->{$_} // ''); } @CONFIG_TEMPLATE_KEYS;
  168         1735  
197              
198 28         453 local $args->{home} = $self->_home($args);
199              
200             {
201 28         3299 local $UMASK = 0177; # read/write for current user
  28         156  
202 28   66     1005 $self->{$key} ||= $self->render_to_file('openssl.cnf', $args);
203             }
204              
205 28         345 local $ENV{OPENSSL_CONF} = $self->{$key}->path;
206 28         2220 return $self->$cb($args);
207             }
208              
209             sub _cat {
210 2     2   295 my $self = shift;
211 2         14 my $dest = pop;
212              
213 2 50       68 open my $DEST, '>', $dest or confess "Write $dest failed: $!";
214 2         208 local @ARGV = @_;
215 2         59 print $DEST $_ for <>;
216 2 50       449 close $DEST or confess "Close $dest failed: $!";
217 2         139 return $dest;
218             }
219              
220             sub _d {
221 35     35   622 return 0 unless DEBUG;
222 0         0 my ($self, $msg) = @_;
223 0         0 print STDERR "$msg\n";
224 0         0 return 0;
225             }
226              
227             sub _home {
228 37     37   126 my ($self, $args) = @_;
229 37 100       335 return Path::Tiny->new($args->{home}) if exists $args->{home};
230 15 100       130 return Path::Tiny->new($args->{ca_key})->parent(2) if $args->{ca_key};
231 12 50       209 return Path::Tiny->new($args->{key})->parent(2) if $args->{key};
232 0         0 confess 'home is required';
233             }
234              
235             sub _parse_subject {
236 25     25   178 my ($self, $val) = @_;
237 25 100       131 return $val if ref $val eq 'HASH';
238              
239             # /C=US/ST=Texas/L=Dallas/O=Company/OU=Department/CN=example.com/emailAddress=admin@example.com
240             # Subject: C = US, ST = Texas, L = Dallas, O = Company, OU = Department, CN = superduper
241 24 100       406 my $re = index($val, '/') == 0 ? qr{/([A-Za-z]+)=([^/]*)} : qr{([A-Za-z]+)\s*=\s*([^,]*)};
242 24         80 my %subject;
243 24         1256 $subject{$1} = $2 while $val =~ /$re/g;
244 24         5935 return \%subject;
245             }
246              
247             sub _passphrase {
248 25     25   95 my ($self, $phrase) = @_;
249              
250 25 50 33     251 confess "passphrase is required" unless defined $phrase and length $phrase;
251 25 50       247 return confess "TODO" if ref $phrase eq 'SCALAR';
252 25         93 return "file:$phrase";
253             }
254              
255             sub _random_passphrase {
256 8     8   289 my ($self, $length) = @_;
257 8         130 my @chr = ('a' .. 'z', 'A' .. 'Z', 0 .. 9);
258 8         52 join '', map { $chr[rand @chr] } 1 .. $length;
  511         1034  
259             }
260              
261             sub _read_subject_from_cert {
262 3     3   83 my ($self, $cert) = @_;
263 3         8 my %subject;
264              
265             # Subject: C = US, ST = Texas, L = Dallas, O = Company, OU = Department, CN = superduper
266             return openssl qw(x509 -noout -text -in), $cert => sub {
267 3     3   31 print STDERR $_[1] if DEBUG == 2 and length $_[1];
268 3 50       123 return $self->_parse_subject($1) if $_[1] =~ m!Subject:\s+(.+)!;
269 3         40 };
270              
271 0         0 die qq(Could not read subject from "$cert".);
272             }
273              
274             sub _render_subject {
275 18     18   83 my $self = shift;
276              
277 18         50 my %subject;
278 18         159 for my $i (@_) {
279 34 100       163 next unless $i;
280 25         72 $self->_d(qq(# Subject from @{[-r $i ? 'file' : 'data']} "$i")) if DEBUG == 2;
281 25 100       811 my $s = -r $i ? $self->_read_subject_from_cert($i) : $self->_parse_subject($i);
282 25         128 map { $self->_d(sprintf '- %-12s %s', "$_:", "$s->{$_}") } sort keys %$s if DEBUG == 2;
283 25         409 $subject{$_} = $s->{$_} for keys %$s;
284             }
285              
286 18         89 return join '/', '', map {"$_=$subject{$_}"} grep { defined $subject{$_} } qw(C ST L O OU CN emailAddress);
  93         435  
  126         270  
287             }
288              
289             # used in script/sslmaker
290             sub _render_template {
291 49     49   118 my ($self, $name, $stash) = @_;
292 49   33     258 my $template = $DATA{$name} // confess "No such template: $name";
293 49   33     467 $template =~ s!<%=\s*([^%]+)\s*%>!{eval $1 // confess $@}!ges; # super cheap template parser
  205         5262  
  205         13330  
294 49         220 $template;
295             }
296              
297             1;
298              
299             =encoding utf8
300              
301             =head1 NAME
302              
303             App::sslmaker - Be your own SSL certificate authority
304              
305             =head1 VERSION
306              
307             0.16
308              
309             =head1 DESCRIPTION
310              
311             L is a module that provide methods for acting as your own
312             L (certificate authority).
313             It can creating SSL keys, certificates and signing requests. The methods
314             should have good defaults and "just work", so you don't have to worry about
315             the details. "Just work" depends on safe defaults, which will change when
316             new and more secure standards come along.
317              
318             The openssl commands are based on the instructions from
319             L.
320              
321             This module is used by the C command line application, but can also
322             act as a standalone toolkit.
323              
324             =head1 DISCLAIMER
325              
326             This module is based on tips and tricks from online resources, and has been
327             reviewed by security experts. Even so, the L of this application or
328             any parts involved cannot be held responsible for the security of your
329             server, application or other parts that use the files generated by this
330             library.
331              
332             =head1 SYNOPSIS
333              
334             $ sslmaker [options]
335              
336             # 1. Initial CA setup
337             # 1a. The CA admin generates root CA key and certificate
338             $ sslmaker root --subject "/C=US/ST=Texas/L=Dallas/O=Company/OU=Department/CN=superduper"
339              
340             # 1b. The CA admin generates intermediate CA key and certificate
341             # Uses the --subject from root CA by default
342             $ sslmaker intermediate
343              
344             # 2. Client certificate setup
345             # 2a. The client generates a server key and certificate signing request
346             # Can be done on any other server
347             # Uses the --subject from intermediate CA if available
348             $ sslmaker generate
349             $ sslmaker generate www.example.com
350              
351             # 2b. The client sends the signing request file to the CA admin
352              
353             # 3. CA sign and revoke process
354             # 3a. The CA admin signs the certificate request
355             $ sslmaker sign www.example.com.csr.pem
356             $ sslmaker sign www.example.com.csr.pem [outfile]
357              
358             # 3b. The CA admin sends back the signed certificate which the client can use
359              
360             # 3c. The CA can revoke a certificate
361             $ sslmaker revoke
362             $ sslmaker revoke /etc/ssl/sslmaker/newcerts/1000.pem
363              
364             # 4. Utility commands
365             # 4a. Create dhparam file
366             $ sslmaker dhparam
367             $ sslmaker dhparam /etc/ssl/sslmaker/dhparam.pem 2048
368              
369             # 4b. Show the manual for App::sslmaker
370             $ sslmaker man
371              
372             =head1 ENVIRONMENT VARIABLES
373              
374             =over 2
375              
376             =item * SSLMAKER_BITS
377              
378             Default bits for a generated certificate. Default is 4096.
379              
380             =item * SSLMAKER_DAYS
381              
382             Default days before expiring a generated certificate. Default is 365.
383              
384             =item * SSLMAKER_DEBUG
385              
386             Setting this to "0" will output less debug information from C.
387              
388             =item * SSLMAKER_HOME
389              
390             Used by the C script as default home directory. Default is either
391             "/etc/pki/sslmaker" or "/etc/ssl/sslmaker".
392              
393             Directory structure is:
394              
395             # generated by "sslmaker root"
396             $SSLMAKER_HOME/root/ca.cert.pem
397             $SSLMAKER_HOME/root/ca.key.pem
398             $SSLMAKER_HOME/root/crlnumber
399             $SSLMAKER_HOME/root/index.txt
400             $SSLMAKER_HOME/root/index.txt.attr
401             $SSLMAKER_HOME/root/passphrase
402             $SSLMAKER_HOME/root/serial
403              
404             # generated by "sslmaker intermediate"
405             $SSLMAKER_HOME/certs/ca-chain.cert.pem
406             $SSLMAKER_HOME/certs/ca.cert.pem
407             $SSLMAKER_HOME/certs/ca.csr.pem
408             $SSLMAKER_HOME/private/ca.key.pem
409             $SSLMAKER_HOME/private/passphrase
410             $SSLMAKER_HOME/root/newcerts/1000.pem
411             $SSLMAKER_HOME/crlnumber
412             $SSLMAKER_HOME/index.txt
413             $SSLMAKER_HOME/index.txt.attr
414             $SSLMAKER_HOME/serial
415              
416             # generated by "sslmaker sign"
417             $SSLMAKER_HOME/newcerts/1000.pem
418              
419             # generated by "sslmaker dhparam"
420             $SSLMAKER_HOME/dhparam.pem
421              
422             NOTE! After running "sslmaker intermediate", then it is highly suggested to
423             move "$SSLMAKER_HOME/root/" to a safe location, such as a memory stick. You can
424             revoke any of the child certificates if they are compromised, but if you loose
425             the root key, then all is lost.
426              
427             =item * SSLMAKER_OPENSSL
428              
429             Default to "openssl". Can be set to a custom path if "openssl" is not in
430             C.
431              
432             =item * SSLMAKER_SUBJECT
433              
434             Used as default subject, unless specified.
435              
436             =back
437              
438             =head2 SEE ALSO
439              
440             =over 4
441              
442             =item * L
443              
444             =item * L
445              
446             =item * L
447              
448             =item * L
449              
450             =back
451              
452             =head1 METHODS
453              
454             =head2 make_cert
455              
456             $asset = $self->make_cert({
457             key => "/path/to/private/input.key.pem",
458             passphrase => "/path/to/passphrase.txt",
459             days => $number_of_days, # default: 365
460             subject => '/C=NO/ST=Oslo', # optional
461             });
462              
463             This method will generate a SSL certificate using a C generated by
464             L. C should match the argument given to L.
465             An optional C can be provided. The subject string will be merged with the
466             L attribute. C can be used to set how many days the certificate
467             should be valid.
468              
469             The returned C<$asset> is a L object which holds the generated certificate
470             file. It is possible to specify the location of this object by passing on C to
471             this method.
472              
473             =head2 make_crl
474              
475             $asset = $self->make_crl({
476             key => "/path/to/private/input.key.pem",
477             cert => "/path/to/cefrt/input.cert.pem",
478             passphrase => "/path/to/passphrase.txt", # optional
479             });
480              
481             This method will generate a certificate revocation list (CRL) using a C generated
482             by L. C should match the argument given to L.
483              
484             The returned C<$asset> is a L object which holds the generated certificate
485             file. It is possible to specify the location of this object by passing on C to
486             this method.
487              
488             You can inspect the generated asset using the command
489             C.
490              
491             See also L.
492              
493             =head2 make_csr
494              
495             $asset = $self->make_csr({
496             key => "/path/to/private/input.key.pem",
497             passphrase => "/path/to/passphrase.txt",
498             subject => '/C=NO/ST=Oslo',
499             days => $number_of_days, # default: 365
500             });
501              
502             This method will generate a SSL certificate signing request using a C
503             generated by L. C is only required if the C was
504             generated with a C. An optional C can be provided.
505             The subject string will be merged with the L attribute.
506              
507             The returned C<$asset> is a L object which holds the generated
508             signing request file. It is possible to specify the location of this object
509             by passing on C to this method.
510              
511             =head2 make_directories
512              
513             $self->make_directories({
514             home => "/path/to/pki",
515             templates => 1, # default: false
516             });
517              
518             Used to generate a suitable file structure, which reflect what C
519             expects. Set C<$emplates> to a true value to generate L.
520              
521             $home/ # need to be writable by current user
522             $home/certs/
523             $home/crl/
524             $home/newcerts/
525             $home/private/ # will have mode 700
526             # optional templates
527             $home/index.txt
528             $home/serial
529              
530             =head2 make_key
531              
532             $asset = $self->make_key({
533             passphrase => "/path/to/passphrase.txt", # optional
534             bits => 8192, # default: 4096
535             });
536              
537             This method will generate a SSL key.
538              
539             The key will be protected with C if given as input. In addition
540             if C does not exist, it will be created with a random passphrase.
541              
542             The returned C<$asset> is a L object which holds the generated key.
543             It is possible to specify the location of this object by passing on C to
544             this method.
545              
546             =head2 new
547              
548             $self = App::sslmaker->new(%args);
549             $self = App::sslmaker->new(\%args);
550              
551             Object constructor.
552              
553             =head2 openssl
554              
555             $self->openssl(@args);
556             $self->openssl(@args, sub { ... });
557             App::sslmaker::openssl(@args);
558             App::sslmaker::openssl(@args, sub { ... });
559              
560             Used to run the application C. The callback defined at the end is
561             optional, but will be called with the complete output from the openssl
562             command. C<$?> is also available for inspection.
563              
564             The C application must exist in path or defined by setting the
565             C environment variable before loading this module.
566              
567             =head2 render_to_file
568              
569             $asset = $self->render_to_file($template, \%stash);
570             $asset = $self->render_to_file($template, $out_file, \%args);
571              
572             This method can render a C<$template> to either a temp file or C<$out_file>.
573             The C<$template> will have access to C<%stash> and C<$self>.
574              
575             See L for list of valid templates.
576              
577             =head2 revoke_cert
578              
579             $self->with_config(
580             revoke_cert => {
581             key => "/path/to/private/ca.key.pem",
582             cert => "/path/to/certs/ca.cert.pem",
583             crl => "/path/to/crl.pem",
584             revoke => "/path/to/newcerts/1000.pem",
585             },
586             );
587              
588             This method can revoke a certificate. It need to be run either with
589             C or inside L.
590              
591             =head2 sign_csr
592              
593             $asset = $self->sign_csr({
594             csr => "/path/to/certs/input.csr.pem",
595             ca_key => "/path/to/private/ca.key.pem",
596             ca_cert => "/path/to/certs/ca.cert.pem",
597             passphrase => "/path/to/passphrase.txt",
598             extensions => "v3_ca", # default: usr_cert
599             });
600              
601             This method will sign a C file generated by L. C and
602             C is the same values as you would provide L and
603             C is the output from L.
604              
605             The returned C<$asset> is a L object which holds the generated
606             certificate. It is possible to specify the location of this object by
607             passing on C to this method.
608              
609             =head2 subject
610              
611             $self = $self->subject(@subjects);
612             $self = $self->subject("/C=NO/ST=Oslo/L=Oslo/O=Example/OU=Prime/emailAddress=admin@example.com", ...);
613             $str = $self->subject;
614              
615             Holds the default subject field for the certificate. Can be set by passing in a
616             list of subject strings, hashes or paths to certificate files. The list will
617             get merged, soo the last one overrides the one before.
618              
619             =head2 with_config
620              
621             $any = $self->with_config($method => \%args);
622              
623             Used to call a L with a temp L
624             file. The C<%stash> in the template will be constructed from the C<%args>,
625             which is also passed on to the next C<$method>. Example:
626              
627             $asset = $self->with_config(make_key => {
628             home => "/path/to/pki",
629             passphrase => "/path/to/pki/private/passphrase.txt",
630             bits => 8192,
631             });
632              
633             The config file will be removed when C<$self> go out of scope.
634              
635             An alternative to this method is to set the C environment
636             variable before calling C<$method>:
637              
638             local $ENV{OPENSSL_CONF} = "/path/to/openssl.cnf";
639             $asset = $self->make_key({...});
640              
641             =head1 TEMPLATES
642              
643             L can render these templates, which is bundled with this module:
644              
645             =over 4
646              
647             =item * crlnumber
648              
649             Creates a file which stores the SSL CRL number. If C is present in
650             C<%stash>, it will be used as the start number, which defaults to 1000.
651              
652             =item * index.txt
653              
654             This is currently just an empty file.
655              
656             =item * nginx.config
657              
658             Used to render an example nginx config. C<%stash> should contain C,
659             C, C, C, C and C.
660              
661             =item * openssl.cnf
662              
663             Creates a config file for openssl. TODO: Descrive stash values.
664              
665             =item * serial
666              
667             Creates a file which stores the SSL serial number. If C is present in
668             C<%stash>, it will be used as the start number, which defaults to 1000.
669              
670             =back
671              
672             =head1 COPYRIGHT AND LICENCE
673              
674             =head2 Code
675              
676             Copyright (C) Jan Henning Thorsen
677              
678             The code is free software, you can redistribute it and/or modify it under the
679             terms of the Artistic License version 2.0.
680              
681             =head2 Documentation
682              
683             Documentation is licensed under the terms of Creative Commons
684             Attribution-ShareAlike 3.0 Unported license.
685              
686             The documentation is put together by Jan Henning Thorsen, with citations from
687             Jamie Nguyen's website L.
688              
689             =head1 AUTHOR
690              
691             Jan Henning Thorsen - C
692              
693             =cut
694              
695             __DATA__