AppLib-CreateSelfSignedSSLCert
view release on metacpan or search on metacpan
lib/AppLib/CreateSelfSignedSSLCert.pm view on Meta::CPAN
#use File::Temp;
use IPC::System::Options 'system', -log=>1;
use Proc::ChildError qw(explain_child_error);
use String::ShellQuote;
sub _sq { shell_quote($_[0]) }
our %SPEC;
$SPEC{create_self_signed_ssl_cert} = {
v => 1.1,
summary => 'Create self-signed SSL certificate',
args => {
hostname => {
schema => ['str*' => match => qr/\A\w+(\.\w+)*\z/],
req => 1,
pos => 0,
},
ca => {
summary => 'path to CA cert file',
schema => ['str*'],
'x.completion' => [filename => {file_regex_filter=>qr/\.(crt|pem)$/}],
},
ca_key => {
summary => 'path to CA key file',
schema => ['str*'],
'x.completion' => [filename => {file_regex_filter=>qr/\.(key|pem)$/}],
},
interactive => {
schema => [bool => default => 0],
cmdline_aliases => {
i => {},
},
},
wildcard => {
schema => [bool => default => 0],
summary => 'If set to 1 then Common Name is set to *.hostname',
description => 'Only when non-interactive',
},
csr_only => {
schema => [bool => default => 0],
summary => 'If set to 1 then will only generate .csr file',
description => <<'_',
Can be useful if want to create .csr and submit it to a CA.
_
},
},
deps => {
exec => 'openssl',
},
};
sub create_self_signed_ssl_cert {
my %args = @_;
my $h = $args{hostname};
system("openssl genrsa 2048 > "._sq("$h.key"));
return [500, "Can't generate key: ".explain_child_error()] if $?;
chmod 0400, "$h.key" or warn "WARN: Can't chmod 400 $h.key: $!";
my $cmd = "openssl req -new -key "._sq("$h.key")." -out "._sq("$h.csr");
if ($args{interactive}) {
system $cmd;
return [500, "Can't generate csr: ".explain_child_error()] if $?;
} else {
my $exp = Expect->spawn($cmd);
return [500, "Can't spawn openssl req"] unless $exp;
$exp->expect(
30,
[ qr!^.+\[[^\]]*\]:!m ,=> sub {
my $exp = shift;
my $prompt = $exp->exp_match;
if ($prompt =~ /common name/i) {
$exp->send(($args{wildcard} ? "*." : "") . "$h\n");
} else {
$exp->send("\n");
}
exp_continue;
} ],
);
$exp->soft_close;
}
if ($args{csr_only}) {
log_info("Your CSR has been created at $h.csr");
return [200];
}
# we can provide options later, but for now let's
system(join(
"",
"openssl x509 -req -days 3650 -in ", _sq("$h.csr"),
" -signkey ", _sq("$h.key"),
($args{ca} ? " -CA "._sq($args{ca}) : ""),
($args{ca_key} ? " -CAkey "._sq($args{ca_key}) : ""),
($args{ca} ? " -CAcreateserial" : ""),
" -out ", _sq("$h.crt"),
));
return [500, "Can't generate crt: ".explain_child_error()] if $?;
system("openssl x509 -noout -fingerprint -text < "._sq("$h.crt").
"> "._sq("$h.info"));
return [500, "Can't generate info: ".explain_child_error()] if $?;
system("cat "._sq("$h.crt")." "._sq("$h.key")." > "._sq("$h.pem"));
return [500, "Can't generate pem: ".explain_child_error()] if $?;
system("chmod 400 "._sq("$h.pem"));
log_info("Your certificate has been created at $h.pem");
[200];
}
$SPEC{create_ssl_csr} = {
v => 1.1,
args => {
hostname => {
schema => ['str*' => match => qr/\A\w+(\.\w+)*\z/],
req => 1,
pos => 0,
},
interactive => {
schema => [bool => default => 0],
cmdline_aliases => {
i => {},
},
},
wildcard => {
schema => [bool => default => 0],
summary => 'If set to 1 then Common Name is set to *.hostname',
description => 'Only when non-interactive',
},
},
deps => {
# XXX should've depended on create_self_signed_ssl_cert() func instead,
# and dependencies should be checked recursively.
exec => 'openssl',
},
};
sub create_ssl_csr {
my %args = @_;
create_self_signed_ssl_cert(%args, csr_only=>1);
}
1;
# ABSTRACT: Create self-signed SSL certificate
__END__
=pod
=encoding UTF-8
=head1 NAME
AppLib::CreateSelfSignedSSLCert - Create self-signed SSL certificate
=head1 VERSION
This document describes version 0.152 of AppLib::CreateSelfSignedSSLCert (from Perl distribution AppLib-CreateSelfSignedSSLCert), released on 2023-06-05.
=head1 SYNOPSIS
=head1 FUNCTIONS
=head2 create_self_signed_ssl_cert
( run in 0.605 second using v1.01-cache-2.11-cpan-cdf2f3d4e48 )