From 27cdf71e71477b3551643ccc20a4c7eef285e702 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Rapha=C3=ABl=20Gertz?= Date: Wed, 1 Mar 2017 10:35:19 +0100 Subject: [PATCH] Add letscron script Letsconf is now generating the config template Add license gpl3 everywhere --- acme.pm | 20 ++++- letscert | 16 +++- letsconf | 225 ++++++++++++++++++++++++++++++++----------------------- letscron | 18 ++++- 4 files changed, 182 insertions(+), 97 deletions(-) diff --git a/acme.pm b/acme.pm index 6a17c3c..ab1a55b 100644 --- a/acme.pm +++ b/acme.pm @@ -1,3 +1,20 @@ +# This file is part of Acmepl +# +# Acmepl is is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# Copyright (C) 2016 - 2017 Raphaël Gertz + # acme package package acme; @@ -12,7 +29,6 @@ our @EXPORT_OK = qw(DS CERT_DIR KEY_DIR REQUEST_CSR ACCOUNT_KEY SERVER_KEY SERVE # Load dependancies use Carp qw(carp confess); -use Data::Dumper; use Date::Parse qw(str2time); use Digest::SHA qw(sha256_base64); use Email::Valid; @@ -636,7 +652,6 @@ sub authorize { # my $res = $self->_post($self->{challenges}{$_}{http_uri}, {resource => 'authz', status => 'deactivated'}); # # Handle error # unless ($res->is_success) { - # print Dumper($res); # confess 'POST '.$self->{challenges}{$_}{http_uri}.' failed: '.$res->status_line; # } #} map { $self->{challenges}{$_}{status} eq 'valid' ? $_ : () } keys %{$self->{challenges}}; @@ -669,7 +684,6 @@ sub issue { # Handle error unless ($res->is_success) { - #print Dumper($res); confess 'POST '.$self->{'new-cert'}.' failed: '.$res->status_line; } diff --git a/letscert b/letscert index ff77f24..dbf245e 100755 --- a/letscert +++ b/letscert @@ -1,5 +1,20 @@ #! /usr/bin/perl +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# Copyright (C) 2016 - 2017 Raphaël Gertz + # Best practice use strict; use warnings; @@ -54,4 +69,3 @@ $acme->issue(); # Exit with success exit EXIT_SUCCESS; - diff --git a/letsconf b/letsconf index 7d9c0cf..869c90b 100755 --- a/letsconf +++ b/letsconf @@ -1,102 +1,143 @@ -#! /usr/bin/php -. +# +# Copyright (C) 2016 - 2017 Raphaël Gertz -# Directory do not exists -if (!is_dir(dirname($argv[1]))) { - echo 'Directory '.dirname($argv[1]).' do not exists'."\n"; - exit(1); -} +# Best practice +use strict; +use warnings; + +# Load required modules +use JSON; +use Tie::IxHash; + +# Load POSIX +use POSIX qw(EXIT_SUCCESS EXIT_FAILURE); + +# XXX: Debug +use Data::Dumper; + +# Init redhat +my @redhat = (); -# Directory do not exists -if (file_exists($argv[1]) && !in_array(filetype($argv[1]), array('file','link'))) { - echo 'File '.$argv[1].' exists and is not a file'."\n"; - exit(1); +# Init debian +my @debian = (); + +# Init root +my %root = (); +tie(%root, 'Tie::IxHash', thumbprint => '/etc/acmepl/thumbprint', certificates => []); + +# Init prod +my $prod = 0; + +# 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] =~ /^(?:(\-d|\-\-redhat)(?:=([^-][a-zA-Z0-9_\.,-]+))?)$/) { + if (defined($2)) { + push(@redhat, split(',', $2)); + # Extract next parameter + } elsif(defined($ARGV[$i+1]) && $ARGV[$i+1] =~ /^([^-][a-zA-Z0-9_\.,-]+)$/) { + push(@redhat, split(',', $1)); + $i++; + # Set default + } else { + push(@redhat, ('example.com')); + } + # Match debian types + } elsif ($ARGV[$i] =~ /^(?:(\-r|\-\-debian)(?:=([^-][a-zA-Z0-9_\.,-]+))?)$/) { + if (defined($2)) { + push(@debian, split(',', $2)); + # Extract next parameter + } elsif(defined($ARGV[$i+1]) && $ARGV[$i+1] =~ /^([^-][a-zA-Z0-9_\.,-]+)$/) { + push(@debian, split(',', $1)); + $i++; + # Set default + } else { + push(@debian, ('example.com')); + } + } } -# Symlink target do not exists -if (is_link($argv[1]) && !file_exists($argv[1])) { - # Read final link - $target = $argv[1]; - # Extract last link - do { - # Update to next link - $target = readlink($target); - } while (is_link($target)); - echo 'Symlink '.$argv[1].' target '.$target.' do not exists'."\n"; - exit(1); +# Show usage +if (scalar(@ARGV) < 1) { + print "Usage: $0 [(-d|--debian)[=example.com[,...]] [(-r|--redhat)[=example.com[,...]]] [...]\n"; + exit EXIT_FAILURE; } -# Not writable -if ( - (is_file($argv[1]) && !is_writable($argv[1])) || - (!file_exists($argv[1]) && !is_writable(dirname($argv[1]))) -) { - echo 'Unable to open '.$argv[1].' for writing'."\n"; - exit(1); +# Append redhat style examples +foreach my $key (@redhat) { + tie(%{$root{certificates}[$#{$root{certificates}}+1]}, 'Tie::IxHash', ( + # Public cert + #XXX: required + cert => '/etc/pki/tls/certs/'.$key.'.pem', + # Private key + #XXX: required + key => '/etc/pki/tls/private/'.$key.'.pem', + # Mail address + #XXX: required + mail => 'webmaster@'.$key, + # Root domain + #XXX: required + domain => 'www.'.$key, + # Domain list + #XXX: required + domains => [ + $key, + '...' + ], + # Production certificate + #XXX: optional + #XXX: set to 1 for production + prod => $prod + )); } -// Generate config -$config = json_encode( - // Root array - array( - //Thumbprint file - 'thumbprint' => '/etc/acmepl/thumbprint', - //Certificate array - 'certificates' => array( - // Certificate object - array( - // Public cert - //XXX: required - 'cert' => '/etc/pki/tls/certs/httpd.pem', - // Private key - //XXX: required - 'key' => '/etc/pki/tls/private/httpd.pem', - // Mail address - //XXX: required - 'mail' => 'webmaster@example.com', - // Root domain - //XXX: required - 'domain' => 'www.example.com', - // Domain list - //XXX: required - 'domains' => array( - 'example.com', - #... - ), - // Production certificate - //XXX: optional - //XXX: set to 1 for production - 'prod' => 0 - ), - // Other certificate - array( - 'cert' => '/etc/ssl/certs/apache.crt', - 'key' => '/etc/ssl/private/apache.key', - 'mail' => 'postmaster@example.com', - 'domain' => 'mail.example.com', - 'domains' => array( - 'imap.example.com', - 'smtp.example.com' - ), - 'prod' => 0 - ), - #... - ) - ), - // Product a nice result - JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES -); - -# Send to stdout -if ($argv[1] == '-') { - echo $config; -# Save to file -} else { - file_put_contents($argv[1], $config); +# Append debian style examples +foreach my $key (@debian) { + tie(%{$root{certificates}[$#{$root{certificates}}+1]}, 'Tie::IxHash', ( + # Public cert + #XXX: required + cert => '/etc/ssl/certs/'.$key.'.crt', + # Private key + #XXX: required + key => '/etc/ssl/private/'.$key.'.key', + # Mail address + #XXX: required + mail => 'webmaster@'.$key, + # Root domain + #XXX: required + domain => 'www.'.$key, + # Domain list + #XXX: required + domains => [ + $key, + '...' + ], + # Production certificate + #XXX: optional + #XXX: set to 1 for production + prod => $prod + )); } + +# Display configuration template +print to_json(\%root, {pretty => 1}); + +# Exit with success +exit EXIT_SUCCESS; diff --git a/letscron b/letscron index b566bae..2a68110 100755 --- a/letscron +++ b/letscron @@ -1,5 +1,20 @@ #! /usr/bin/perl +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# Copyright (C) 2016 - 2017 Raphaël Gertz + # Best practice use strict; use warnings; @@ -107,7 +122,7 @@ foreach (@{$config->{certificates}}) { } # Run letscert with args - my @out = capturex([0..1], './letscert', @args); + my @out = capturex([0..1], 'letscert', @args); # Deal with error if ($EXITVAL != 0) { @@ -142,4 +157,5 @@ foreach (@{$config->{certificates}}) { } } +# Exit with success exit EXIT_SUCCESS; -- 2.41.0