Commit 391d46d1 authored by Nigel Kukard's avatar Nigel Kukard
Browse files

Major code cleanup regarding error handling

parent 7f745403
Pipeline #902 passed with stages
in 2 minutes and 44 seconds
...@@ -47,7 +47,7 @@ package AWIT::CertMaster; ...@@ -47,7 +47,7 @@ package AWIT::CertMaster;
use strict; use strict;
use warnings; use warnings;
our $VERSION = '1.03'; our $VERSION = '1.04';
BEGIN { BEGIN {
...@@ -120,7 +120,7 @@ sub accountInit ...@@ -120,7 +120,7 @@ sub accountInit
# Check if the dir was created # Check if the dir was created
if (! -d $dir) { if (! -d $dir) {
$self->logger("ERROR","Failed to create directory '%s'",$dir); $self->logger("ERROR","Failed to create directory '%s'",$dir);
exit 1; return;
} }
# Check if the file exists, if it does, we need to create else login # Check if the file exists, if it does, we need to create else login
...@@ -136,16 +136,14 @@ sub accountInit ...@@ -136,16 +136,14 @@ sub accountInit
close($FH); close($FH);
} else { } else {
$self->logger("ERROR","Failed to read account key file '%s': %s",$keyFile,$!); $self->logger("ERROR","Failed to read account key file '%s': %s",$keyFile,$!);
exit 1; return;
} }
return $self->accountLogin($keyPEM); return $self->accountLogin($keyPEM);
} }
# Create an account # Create an account
$self->accountCreate({ $self->accountCreate({ 'contact' => sprintf('root@%s',hostname()) }) or return;
'contact' => sprintf('root@%s',hostname())
});
# Open keyfile and read it in # Open keyfile and read it in
umask(0177); umask(0177);
...@@ -155,7 +153,7 @@ sub accountInit ...@@ -155,7 +153,7 @@ sub accountInit
close($FH); close($FH);
} else { } else {
$self->logger("ERROR","Failed to read account key file '%s': %s",$keyFile,$!); $self->logger("ERROR","Failed to read account key file '%s': %s",$keyFile,$!);
exit 1; return;
} }
return $self; return $self;
...@@ -232,7 +230,7 @@ sub webserverCheckApache ...@@ -232,7 +230,7 @@ sub webserverCheckApache
} else { } else {
# Fail if we cannot open the configuration directory # Fail if we cannot open the configuration directory
$self->logger("ERROR","APACHE: Failed to open configuration directory '%s': %s",$dataDir,$!); $self->logger("ERROR","APACHE: Failed to open configuration directory '%s': %s",$dataDir,$!);
exit 1; return;
} }
# Loop with config files found # Loop with config files found
...@@ -301,7 +299,7 @@ sub webserverCheckApache ...@@ -301,7 +299,7 @@ sub webserverCheckApache
# Reload Apache # Reload Apache
$self->_webserverReloadApache(); $self->_webserverReloadApache() or return;
return $self; return $self;
} }
...@@ -335,7 +333,7 @@ sub webserverCheckNginx ...@@ -335,7 +333,7 @@ sub webserverCheckNginx
} else { } else {
# Fail if we cannot open the configuration directory # Fail if we cannot open the configuration directory
$self->logger("ERROR","NGINX: Failed to open configuration directory '%s': %s",$dataDir,$!); $self->logger("ERROR","NGINX: Failed to open configuration directory '%s': %s",$dataDir,$!);
exit 1; return;
} }
# Loop with config files found # Loop with config files found
...@@ -398,7 +396,7 @@ sub webserverCheckNginx ...@@ -398,7 +396,7 @@ sub webserverCheckNginx
} }
# Reload NGINX # Reload NGINX
$self->_webserverReloadNginx(); $self->_webserverReloadNginx() or return;
return $self; return $self;
} }
...@@ -600,19 +598,20 @@ SKIP: ...@@ -600,19 +598,20 @@ SKIP:
# If we still have entries, we need to start processing! # If we still have entries, we need to start processing!
$self->accountInit(); $self->accountInit() or return;
# Verify domains # Verify domains
foreach my $vhostName (keys %{$vhostConfig}) { foreach my $vhostName (keys %{$vhostConfig}) {
my $vhost = $vhostConfig->{$vhostName}; my $vhost = $vhostConfig->{$vhostName};
foreach my $domain (keys %{$vhost->{'server_names'}}) { foreach my $domain (keys %{$vhost->{'server_names'}}) {
$self->domainAdd($domain); $self->domainAdd($domain) or return;
$self->domainVerify($domain); $self->domainVerify($domain) or return;
} }
# Retrieve certificate # Retrieve certificate
my $certs = $self->certificateRetrieve($vhostName); my $certs = $self->certificateRetrieve($vhostName);
return if (!$certs);
$self->logger("INFO","WEBSERVER: Writing certificates"); $self->logger("INFO","WEBSERVER: Writing certificates");
...@@ -857,7 +856,7 @@ sub _parse_x509_datetime ...@@ -857,7 +856,7 @@ sub _parse_x509_datetime
# Regex string # Regex string
if ($string !~ /(...) (..) (..):(..):(..) (....) (...)/) { if ($string !~ /(...) (..) (..):(..):(..) (....) (...)/) {
$self->logger("ERROR","CORE: The X509 date provided is invalid '%s'",$string); $self->logger("ERROR","CORE: The X509 date provided is invalid '%s'",$string);
exit 1; return;
} }
# Grab components # Grab components
my ( $b, $d, $H, $M, $S, $Y, $Z ) = ($1, $2, $3, $4, $5, $6, $7); my ( $b, $d, $H, $M, $S, $Y, $Z ) = ($1, $2, $3, $4, $5, $6, $7);
...@@ -881,13 +880,13 @@ sub _parse_x509_datetime ...@@ -881,13 +880,13 @@ sub _parse_x509_datetime
my $month = $month_by_name->{$b}; my $month = $month_by_name->{$b};
if (!defined($month)) { if (!defined($month)) {
$self->logger("ERROR","CORE: Invalid month in X509 date '%s'",$string); $self->logger("ERROR","CORE: Invalid month in X509 date '%s'",$string);
exit 1; return;
} }
# Check timezone is right # Check timezone is right
if ($Z ne 'GMT' && $Z ne 'UTC') { if ($Z ne 'GMT' && $Z ne 'UTC') {
$self->logger("ERROR","CORE: Invalid timezone in X509 date '%s'",$string); $self->logger("ERROR","CORE: Invalid timezone in X509 date '%s'",$string);
exit 1; return;
} }
# Build DateTime object # Build DateTime object
...@@ -935,7 +934,7 @@ use MIME::Base64 qw( ...@@ -935,7 +934,7 @@ use MIME::Base64 qw(
our $VERSION = '1.00'; our $VERSION = '1.01';
# Take care of created files # Take care of created files
my @_created_files = (); my @_created_files = ();
...@@ -1005,28 +1004,28 @@ sub accountCreate ...@@ -1005,28 +1004,28 @@ sub accountCreate
# Make sure we have args # Make sure we have args
if (!defined($args)) { if (!defined($args)) {
$self->logger("ERROR",'LE: createAccount: $args is required'); $self->logger("ERROR",'LE: createAccount: $args is required');
exit 1; return;
} }
if (!exists($args->{'contact'})) { if (!exists($args->{'contact'})) {
$self->logger("ERROR","LE: createAccount: 'contact' is required"); $self->logger("ERROR","LE: createAccount: 'contact' is required");
exit 1; return;
} }
# Create RSA key # Create RSA key
my $key = $self->_createKeyRSA(); my $key = $self->_createKeyRSA();
# Load key # Load key
$self->loadKey($key); $self->loadKey($key) or return;
# Load resource directory # Load resource directory
$self->leDirectory(); $self->leDirectory() or return;
# Register account # Register account
$self->leRegister('contact' => $args->{'contact'}); $self->leRegister('contact' => $args->{'contact'}) or return;
# Accept TOS # Accept TOS
$self->leAcceptTOS(); $self->leAcceptTOS() or return;
$self->{'ready'} = 1; $self->{'ready'} = 1;
...@@ -1042,16 +1041,16 @@ sub accountLogin ...@@ -1042,16 +1041,16 @@ sub accountLogin
# Load key # Load key
$self->loadKey($key); $self->loadKey($key) or return;
# Load resource directory # Load resource directory
$self->leDirectory(); $self->leDirectory() or return;
# Register account # Register account
$self->leRegister(); $self->leRegister() or return;
# Accept TOS # Accept TOS
$self->leAcceptTOS(); $self->leAcceptTOS() or return;
$self->{'ready'} = 1; $self->{'ready'} = 1;
...@@ -1069,7 +1068,7 @@ sub domainAdd ...@@ -1069,7 +1068,7 @@ sub domainAdd
# Check that we're ready # Check that we're ready
if (!$self->{'ready'}) { if (!$self->{'ready'}) {
$self->logger("ERROR","LE: A call to accountLogin/Create must be made before domainAdd()"); $self->logger("ERROR","LE: A call to accountLogin/Create must be made before domainAdd()");
exit 1; return;
} }
return $self->leAuthz($domain); return $self->leAuthz($domain);
...@@ -1086,10 +1085,10 @@ sub domainVerify ...@@ -1086,10 +1085,10 @@ sub domainVerify
# Check that we're ready # Check that we're ready
if (!$self->{'ready'}) { if (!$self->{'ready'}) {
$self->logger("ERROR","LE: A call to accountLogin/Create must be made before domainVerify()"); $self->logger("ERROR","LE: A call to accountLogin/Create must be made before domainVerify()");
exit 1; return;
} }
$self->leHandleChallenge($domain); $self->leHandleChallenge($domain) or return;
push(@{$self->{'domains_verified'}},$domain); push(@{$self->{'domains_verified'}},$domain);
...@@ -1107,7 +1106,7 @@ sub certificateRetrieve ...@@ -1107,7 +1106,7 @@ sub certificateRetrieve
# Check that we're ready # Check that we're ready
if (!$self->{'ready'}) { if (!$self->{'ready'}) {
$self->logger("ERROR","LE: A call to accountLogin/Create must be made before certificateCSR()"); $self->logger("ERROR","LE: A call to accountLogin/Create must be made before certificateCSR()");
exit 1; return;
} }
$self->logger("INFO","LE: Generating CSR"); $self->logger("INFO","LE: Generating CSR");
...@@ -1126,7 +1125,7 @@ sub certificateRetrieve ...@@ -1126,7 +1125,7 @@ sub certificateRetrieve
my $rsa = Crypt::OpenSSL::RSA->new_private_key($certKeyPEM); my $rsa = Crypt::OpenSSL::RSA->new_private_key($certKeyPEM);
if (!$rsa) { if (!$rsa) {
$self->logger("ERROR","LE: certificateRetrieve: Failed to load certificate key into OpenSSL"); $self->logger("ERROR","LE: certificateRetrieve: Failed to load certificate key into OpenSSL");
exit 1; return;
} }
# Padding for PKCS10 # Padding for PKCS10
...@@ -1162,6 +1161,7 @@ sub certificateRetrieve ...@@ -1162,6 +1161,7 @@ sub certificateRetrieve
# Convert CSR PEM into DER # Convert CSR PEM into DER
my $csrDER = $self->_pem_to_der($csrPEM); my $csrDER = $self->_pem_to_der($csrPEM);
return if (!$csrDER);
# Build the request we are about to send # Build the request we are about to send
my $json = $self->_encode_json({ my $json = $self->_encode_json({
...@@ -1176,24 +1176,24 @@ sub certificateRetrieve ...@@ -1176,24 +1176,24 @@ sub certificateRetrieve
# And post it... # And post it...
my $resp = $self->_leRequestPost($self->{'directory'}->{'new-cert'}, $jws); my $resp = $self->_leRequestPost($self->{'directory'}->{'new-cert'}, $jws);
# Make sure result code is right # Make sure result code is right
if ($resp->code() != 201) { if ($resp->code() != 201) {
$self->logger("ERROR","LE: An invalid response was received from resource 'new-cert': %s",$resp->content()); $self->logger("ERROR","LE: An invalid response was received from resource 'new-cert': %s",$resp->content());
exit 1; return;
} }
# Grab certificate DER # Grab certificate DER
my $certDER = $resp->content(); my $certDER = $resp->content();
return if (!$certDER);
# Grab resources from header # Grab resources from header
my $resources = {}; my $resources = {};
$self->_leDirectoryLinks($resources,$resp->header('link')); $self->_leDirectoryLinks($resources,$resp->header('link')) or return;
# Make sure we got a chain URL # Make sure we got a chain URL
if (!defined($resources->{'up'})) { if (!defined($resources->{'up'})) {
$self->logger("ERROR","LE: No certificate chain was received",$resp->content()); $self->logger("ERROR","LE: No certificate chain was received",$resp->content());
exit 1; return;
} }
# Pull out the chain # Pull out the chain
...@@ -1205,7 +1205,7 @@ sub certificateRetrieve ...@@ -1205,7 +1205,7 @@ sub certificateRetrieve
$resp = $self->{'user_agent'}->get($certChainURL); $resp = $self->{'user_agent'}->get($certChainURL);
if ($resp->code() != 200) { if ($resp->code() != 200) {
$self->logger("ERROR","LE: An invalid response was received from resource 'up', certificate chain URL: %s",$resp->content()); $self->logger("ERROR","LE: An invalid response was received from resource 'up', certificate chain URL: %s",$resp->content());
exit 1; return;
} }
# Grab the certificate chain in DER format # Grab the certificate chain in DER format
...@@ -1243,10 +1243,9 @@ sub loadKey ...@@ -1243,10 +1243,9 @@ sub loadKey
my $rsa = Crypt::OpenSSL::RSA->new_private_key($key); my $rsa = Crypt::OpenSSL::RSA->new_private_key($key);
if (!$rsa) { if (!$rsa) {
$self->logger("ERROR","LE: loadKey: Failed to load key into OpenSSL"); $self->logger("ERROR","LE: loadKey: Failed to load key into OpenSSL");
exit 1; return;
} }
# Use SHA256 hashing # Use SHA256 hashing
$rsa->use_sha256_hash(); $rsa->use_sha256_hash();
...@@ -1272,11 +1271,10 @@ sub leDirectory ...@@ -1272,11 +1271,10 @@ sub leDirectory
# Make a request for the server directory # Make a request for the server directory
my $resp = $self->_leRequestGet( $self->{'server'} ); my $resp = $self->_leRequestGet( $self->{'server'} );
# Make sure we got a success # Make sure we got a success
if ($resp->code() != 200) { if ($resp->code() != 200) {
$self->logger("ERROR","LE: Failed to fetch the server resource direcotry '%s': %s",$self->{'server'},$resp->status_line()); $self->logger("ERROR","LE: Failed to fetch the server resource direcotry '%s': %s",$self->{'server'},$resp->status_line());
exit 1; return;
} }
# Decode the directory response # Decode the directory response
...@@ -1313,12 +1311,8 @@ sub leRegister ...@@ -1313,12 +1311,8 @@ sub leRegister
# Do the actual post... # Do the actual post...
my $resp = $self->_leRequestPost($self->{'directory'}->{'new-reg'}, $jws); my $resp = $self->_leRequestPost($self->{'directory'}->{'new-reg'}, $jws);
# Grab response code
my $respCode = $resp->code();
# Error code 409 means 'already registered' # Error code 409 means 'already registered'
if ($respCode == 409) { if ($resp->code() == 409) {
$self->logger("NOTICE","LE: Known key used, refetching with 'reg' resource"); $self->logger("NOTICE","LE: Known key used, refetching with 'reg' resource");
...@@ -1332,10 +1326,10 @@ sub leRegister ...@@ -1332,10 +1326,10 @@ sub leRegister
# Check result # Check result
if ($resp->code() != 202) { if ($resp->code() != 202) {
$self->logger("ERROR","LE: Problem when refetching with 'reg' resource: %s",$resp->content()); $self->logger("ERROR","LE: Problem when refetching with 'reg' resource: %s",$resp->content());
exit 1; return;
} }
$self->_leDirectoryLinks($self->{'directory'},$resp->header('link')); $self->_leDirectoryLinks($self->{'directory'},$resp->header('link')) or return;
# Error code 201 is a success # Error code 201 is a success
} elsif ($resp->code() == 201) { } elsif ($resp->code() == 201) {
...@@ -1343,12 +1337,12 @@ sub leRegister ...@@ -1343,12 +1337,12 @@ sub leRegister
# Save 'reg' resource # Save 'reg' resource
$self->{'directory'}->{'reg'} = $resp->header('location'); $self->{'directory'}->{'reg'} = $resp->header('location');
$self->_leDirectoryLinks($self->{'directory'},$resp->header('link')); $self->_leDirectoryLinks($self->{'directory'},$resp->header('link')) or return;
# Any other code is a problem # Any other code is a problem
} else { } else {
$self->logger("ERROR","LE: Problem when refetching with 'reg' resource: %s",$resp->content()); $self->logger("ERROR","LE: Problem when refetching with 'reg' resource: %s",$resp->content());
exit 1; return;
} }
return $self; return $self;
...@@ -1384,11 +1378,10 @@ sub leAcceptTOS ...@@ -1384,11 +1378,10 @@ sub leAcceptTOS
my $jws = $self->_leCreateJWS($json); my $jws = $self->_leCreateJWS($json);
my $resp = $self->_leRequestPost($self->{'directory'}->{'reg'}, $jws); my $resp = $self->_leRequestPost($self->{'directory'}->{'reg'}, $jws);
# Check if we got a success code back # Check if we got a success code back
if ($resp->code() != 202) { if ($resp->code() != 202) {
$self->logger("ERROR",'LE: Failed to accept TOS: %s',$resp->content()); $self->logger("ERROR",'LE: Failed to accept TOS: %s',$resp->content());
exit 1; return;
} }
# Remove 'reg' resource # Remove 'reg' resource
...@@ -1408,7 +1401,7 @@ sub leAuthz ...@@ -1408,7 +1401,7 @@ sub leAuthz
# Make sure that our next resource is present # Make sure that our next resource is present
if (!exists($self->{'directory'}->{'next'})) { if (!exists($self->{'directory'}->{'next'})) {
$self->logger("ERROR","LE: Resource 'next' does not exist"); $self->logger("ERROR","LE: Resource 'next' does not exist");
exit 1; return;
} }
$self->logger("INFO","LE: Authorizing domain '%s'",$domain); $self->logger("INFO","LE: Authorizing domain '%s'",$domain);
...@@ -1424,11 +1417,10 @@ sub leAuthz ...@@ -1424,11 +1417,10 @@ sub leAuthz
my $jws = $self->_leCreateJWS($json); my $jws = $self->_leCreateJWS($json);
my $resp = $self->_leRequestPost($self->{'directory'}->{'next'}, $jws); my $resp = $self->_leRequestPost($self->{'directory'}->{'next'}, $jws);
# Check if we got a positive response back or not # Check if we got a positive response back or not
if ($resp->code() != 201) { if ($resp->code() != 201) {
$self->logger("ERROR","LE: Error with resource 'new-authz': %s",$resp->content()); $self->logger("ERROR","LE: Error with resource 'new-authz': %s",$resp->content());
exit 1; return;
} }
# Grab the JSON reply # Grab the JSON reply
...@@ -1440,7 +1432,7 @@ sub leAuthz ...@@ -1440,7 +1432,7 @@ sub leAuthz
# Make sure we actually got challenges back # Make sure we actually got challenges back
if (!exists($jsonRef->{'challenges'})) { if (!exists($jsonRef->{'challenges'})) {
$self->logger("ERROR","LE: Error with resource 'new-authz': %s",$resp->content()); $self->logger("ERROR","LE: Error with resource 'new-authz': %s",$resp->content());
exit 1; return;
} }
# Load challenges into ourself for this domain # Load challenges into ourself for this domain
...@@ -1461,7 +1453,7 @@ sub leHandleChallenge ...@@ -1461,7 +1453,7 @@ sub leHandleChallenge
# Check challenge exists # Check challenge exists
if (!exists($self->{'challenges'}->{$domain})) { if (!exists($self->{'challenges'}->{$domain})) {
$self->logger("ERROR","LE: Challenges for domain '%s' does not exist",$domain); $self->logger("ERROR","LE: Challenges for domain '%s' does not exist",$domain);
exit 1; return;
} }
# Check if any of the challenges were already validated # Check if any of the challenges were already validated
...@@ -1539,19 +1531,19 @@ sub leHandleChallenge ...@@ -1539,19 +1531,19 @@ sub leHandleChallenge
# If there was no http-01 challenge, then its an error # If there was no http-01 challenge, then its an error
if (!defined($challenge)) { if (!defined($challenge)) {
$self->logger("ERROR","LE: No 'http-01' challenge was received for domain '%s'",$domain); $self->logger("ERROR","LE: No 'http-01' challenge was received for domain '%s'",$domain);
exit 1; return;
} }
# Check we have a 'token' # Check we have a 'token'
if (!defined($challenge->{'token'})) { if (!defined($challenge->{'token'})) {
$self->logger("ERROR","LE: The 'http-01' challenge for domain '%s' does not contain 'token'",$domain); $self->logger("ERROR","LE: The 'http-01' challenge for domain '%s' does not contain 'token'",$domain);
exit 1; return;
} }
# Check we have a 'uri' # Check we have a 'uri'
if (!defined($challenge->{'uri'})) { if (!defined($challenge->{'uri'})) {
$self->logger("ERROR","LE: The 'http-01' challenge for domain '%s' does not contain 'uri'",$domain); $self->logger("ERROR","LE: The 'http-01' challenge for domain '%s' does not contain 'uri'",$domain);
exit 1; return;
} }
...@@ -1567,7 +1559,7 @@ sub leHandleChallenge ...@@ -1567,7 +1559,7 @@ sub leHandleChallenge
# Check if the dir was created # Check if the dir was created
if (! -d $dir) { if (! -d $dir) {
$self->logger("ERROR","LE: Failed to create directory '%s'",$dir); $self->logger("ERROR","LE: Failed to create directory '%s'",$dir);
exit 1; return;
} }
# Create file... # Create file...
...@@ -1580,7 +1572,7 @@ sub leHandleChallenge ...@@ -1580,7 +1572,7 @@ sub leHandleChallenge
# If the open failed, ERR out # If the open failed, ERR out
} else { } else {
$self->logger("ERROR","LE: Failed to create file '%s': %s",$dir,$!); $self->logger("ERROR","LE: Failed to create file '%s': %s",$dir,$!);
exit 1; return;
} }
# Add file to get cleaned up # Add file to get cleaned up
...@@ -1602,12 +1594,11 @@ sub leHandleChallenge ...@@ -1602,12 +1594,11 @@ sub leHandleChallenge
my $jws = $self->_leCreateJWS($json); my $jws = $self->_leCreateJWS($json);
my $resp = $self->_leRequestPost($challenge->{'uri'}, $jws); my $resp = $self->_leRequestPost($challenge->{'uri'}, $jws);
# Make sure if we got the wrong code we abort