File Coverage

blib/lib/App/sslmaker.pm
Criterion Covered Total %
statement 167 170 98.2
branch 60 82 73.1
condition 25 42 59.5
subroutine 33 33 100.0
pod 12 12 100.0
total 297 339 87.6


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