X-Git-Url: https://git.rapsys.eu/acme/blobdiff_plain/a30d412c8f8f1a4522ced824779770de5b8c1513..ae17b69d70ec7ca1df4ed65a70b365d6c838f381:/acmecert diff --git a/acmecert b/acmecert index f8694cb..3f8a559 100755 --- a/acmecert +++ b/acmecert @@ -19,7 +19,13 @@ use strict; use warnings; -# Load Acme +# Fix use of acl +use filetest qw(access); + +# Load dependancies +use File::stat qw(stat); +use File::Slurp qw(read_file); +use JSON qw(decode_json); use Acme; # Load POSIX @@ -28,44 +34,119 @@ use POSIX qw(EXIT_SUCCESS EXIT_FAILURE); # Init debug my $debug = 0; -# Init prod -my $prod = 0; +# Init config +my $config = undef; + +# Init config file name +my $configFilename = '/etc/acme/config'; + +# Init domains +my @domains = (); # Strip and enable debug @ARGV = map { if ($_ eq '-d') { $debug = 1; (); } else { $_; } } @ARGV; -# Strip and enable prod -@ARGV = map { if ($_ eq '-p') { $prod = 1; (); } else { $_; } } @ARGV; +# Strip and enable debug +for (my $i = 0; $i <= $#ARGV; $i++) { + # Match redhat types + if ($ARGV[$i] =~ /^(?:(\-c|\-\-config)(?:=(.+))?)$/) { + if (defined($2) && -f $2) { + $configFilename = $2; + splice(@ARGV, $i, 1); + $i--; + # Extract next parameter + } elsif(defined($ARGV[$i+1]) && $ARGV[$i+1] =~ /^(.+)$/ && -f $1) { + $configFilename = $1; + splice(@ARGV, $i, 2); + $i--; + # Set default + } else { + print 'Config parameter without valid file name'."\n"; + exit EXIT_FAILURE; + } + } +} + +# Load config +unless ( + #XXX: use eval to workaround a fatal in decode_json + eval { + # Check file + (-f $configFilename) && + # Read it + ($config = read_file($configFilename)) && + # Decode it + ($config = decode_json($config)) && + # Check hash validity + defined($config->{certificates}) && + # Check not empty + scalar($config->{certificates}) && + # Check hash validity + defined($config->{thumbprint}) && + # Check certificates array + ! scalar map {unless(defined($_->{cert}) && defined($_->{key}) && defined($_->{mail}) && defined($_->{domain}) && defined($_->{domains})) {1;} else {();}} @{$config->{certificates}} + } +) { + print 'Config file '.$configFilename.' is not readable or invalid'."\n"; + exit EXIT_FAILURE; +} + +# Deal with specified domains +if (scalar(@ARGV) > 0) { + # Check that domains are present in config + foreach my $domain (@ARGV) { + my $found = undef; + foreach my $certificate (@{$config->{certificates}}) { + if ($certificate->{domain} eq $domain) { + push(@domains, $certificate); + $found = 1; + } + } + unless($found) { + print 'Domain '.$domain.' not found in config file '.$configFilename."\n"; + exit EXIT_FAILURE; + } + } +# Without it +} else { + # Populate domains array with available ones + foreach my $certificate (@{$config->{certificates}}) { + push(@domains, $certificate); + } +} # Show usage -if (scalar(@ARGV) < 2) { - print "Usage: $0 user\@example.com www.example.com [example.com] [...]\n"; +if (scalar(@domains) < 1) { + print "Usage: $0 [-(c|-config)[=/etc/acme/config]] [example.com] [...]\n"; exit EXIT_FAILURE; } -# Create new object -my $acme = Acme->new(shift @ARGV, $debug, $prod, @ARGV); +# Deal with each domain +foreach my $domain (@domains) { + # Create new object + my $acme = Acme->new($debug, $domain, {thumbprint => $config->{thumbprint}, pending => $config->{pending}, term => $config->{term}}); -# Prepare environement -$acme->prepare(); + # Prepare environement + $acme->prepare(); -# Generate required keys -$acme->genKeys(); + # Generate required keys + $acme->genKeys(); -# Generate csr -$acme->genCsr(); + # Generate csr + $acme->genCsr(); -# Directory -$acme->directory(); + # Directory + $acme->directory(); -# Register -$acme->register(); + # Register + $acme->register(); -# Authorize -$acme->authorize(); + # Authorize + $acme->authorize(); -# Issue -$acme->issue(); + # Issue + $acme->issue(); +} # Exit with success exit EXIT_SUCCESS;