From a9a6208f5c7e0f73fd8b370f99f5c8f58e6b381c Mon Sep 17 00:00:00 2001 From: Guilhem Moulin Date: Thu, 30 Jun 2016 19:57:12 +0200 Subject: Honor Retry-After headers for certificate issuance and challenge responses. --- client | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) (limited to 'client') diff --git a/client b/client index 46f388f..3bf0bad 100755 --- a/client +++ b/client @@ -257,6 +257,7 @@ elsif ($COMMAND =~ /\Areg=(\p{Print}+)\Z/) { # elsif ($COMMAND eq 'new-cert') { die unless @ARGV; + my $timeout = $CONFIG->{timeout} // 10; foreach my $domain (@ARGV) { print STDERR "Processing new DNS authz for $domain\n" if $ENV{DEBUG}; my $r = acme_resource('new-authz', identifier => {type => 'dns', value => $domain}); @@ -288,7 +289,7 @@ elsif ($COMMAND eq 'new-cert') { $content = request_json_decode($r), $status = $content->{status} // 'pending', $status ne 'valid'; - $r = request('GET' => $challenge->{uri}), $i++ ) { + $r = request('GET' => $challenge->{uri})) { if (defined (my $problem = $content->{error})) { # problem document (RFC 7807) my $msg = $problem->{status}; $msg .= " " .$problem->{title} if defined $problem->{title}; @@ -296,9 +297,16 @@ elsif ($COMMAND eq 'new-cert') { die $msg, "\n"; } die "Error: Invalid challenge for $domain (status: ".$status.")\n" if $status ne 'pending'; - die "Timeout exceeded while waiting for challenge to pass ($domain)\n" - if $i >= ($CONFIG->{timeout} // 10); - sleep 1; + + my $sleep = 1; + if (defined (my $retry_after = $r->header('Retry-After'))) { + print STDERR "Retrying after $retry_after seconds...\n"; + $sleep = $retry_after; + } + + $i += $sleep; + die "Timeout exceeded while waiting for challenge to pass ($domain)\n" if $timeout > 0 and $i >= $timeout; + sleep $sleep; } } @@ -309,12 +317,17 @@ elsif ($COMMAND eq 'new-cert') { # https://acme-v01.api.letsencrypt.org/acme/cert/$serial print STDERR "Certificate URI: $uri\n"; - # wait for the cert - for (my $i = 0; $r->decoded_content() eq ''; $r = request('GET' => $uri), $i++) { - die request_status_line($r), "\n" unless $r->is_success(); - die "Timeout exceeded while waiting for certificate\n" - if $i >= ($CONFIG->{timeout} // 10); - sleep 1; + if ($r->decoded_content() eq '') { # wait for the cert + for (my $i = 0;;) { + $r = request('GET' => $uri); + die request_status_line($r), "\n" unless $r->is_success(); + last unless $r->code == 202; # Accepted + my $retry_after = $r->header('Retry-After') // 1; + print STDERR "Retrying after $retry_after seconds...\n"; + $i += $retry_after; + die "Timeout exceeded while waiting for certificate\n" if $timeout > 0 and $i >= $timeout; + sleep $retry_after; + } } my $der = $r->decoded_content(); -- cgit v1.2.3