Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions MANIFEST
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ t/Net-ACME2-Challenge-tls_alpn_01.t
t/Net-ACME2-Challenge.t
t/Net-ACME2-EAB.t
t/Net-ACME2-Error.t
t/Net-ACME2-get-certificate-guard.t
t/Net-ACME2-get_orders.t
t/Net-ACME2-HTTP.t
t/Net-ACME2-JWTMaker.t
Expand Down
12 changes: 10 additions & 2 deletions lib/Net/ACME2.pm
Original file line number Diff line number Diff line change
Expand Up @@ -852,8 +852,12 @@ protocol specification for details about this format.
sub get_certificate_chain {
my ($self, $order) = @_;

my $url = $order->certificate() or _die_generic(
'Order has no certificate URL (status: ' . $order->status() . '). Poll the order until it reaches "valid" status before fetching the certificate.',
);

return Net::ACME2::PromiseUtil::then(
$self->_post_as_get( $order->certificate() ),
$self->_post_as_get( $url ),
sub {
return shift()->content();
},
Expand Down Expand Up @@ -883,8 +887,12 @@ an empty array reference.
sub get_certificate_chains {
my ($self, $order) = @_;

my $url = $order->certificate() or _die_generic(
'Order has no certificate URL (status: ' . $order->status() . '). Poll the order until it reaches "valid" status before fetching the certificate.',
);

return Net::ACME2::PromiseUtil::then(
$self->_post_as_get( $order->certificate() ),
$self->_post_as_get( $url ),
sub {
my ($resp) = @_;

Expand Down
96 changes: 96 additions & 0 deletions t/Net-ACME2-get-certificate-guard.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
#!/usr/bin/env perl

use strict;
use warnings;

use Test::More;
use Test::Exception;
use Test::FailWarnings;

use Digest::MD5;
use HTTP::Status;
use URI;
use JSON;

use FindBin;
use lib "$FindBin::Bin/lib";
use Test::ACME2_Server;

#----------------------------------------------------------------------

{
package MyCA;

use parent qw( Net::ACME2 );

use constant {
HOST => 'acme.someca.net',
DIRECTORY_PATH => '/acme-directory',
};
}

my $_RSA_KEY = <<END;
-----BEGIN RSA PRIVATE KEY-----
MIICWwIBAAKBgQCkOYWppsEFfKHqIntkpUjmuwnBH3sRYP00YRdIhrz6ypRpxX6H
c2Q0IrSprutu9/dUy0j9a96q3kRa9Qxsa7paQj7xtlTWx9qMHvhlrG3eLMIjXT0J
4+MSCw5LwViZenh0obBWcBbnNYNLaZ9o31DopeKcYOZBMogF6YqHdpIsFQIDAQAB
AoGAN7RjSFaN5qSN73Ne05bVEZ6kAmQBRLXXbWr5kNpTQ+ZvTSl2b8+OT7jt+xig
N3XY6WRDD+MFFoRqP0gbvLMV9HiZ4tJ/gTGOHesgyeemY/CBLRjP0mvHOpgADQuA
+VBZmWpiMRN8tu6xHzKwAxIAfXewpn764v6aXShqbQEGSEkCQQDSh9lbnpB/R9+N
psqL2+gyn/7bL1+A4MJwiPqjdK3J/Fhk1Yo/UC1266MzpKoK9r7MrnGc0XjvRpMp
JX8f4MTbAkEAx7FvmEuvsD9li7ylgnPW/SNAswI6P7SBOShHYR7NzT2+FVYd6VtM
vb1WrhO85QhKgXNjOLLxYW9Uo8s1fNGtzwJAbwK9BQeGT+cZJPsm4DpzpIYi/3Zq
WG2reWVxK9Fxdgk+nuTOgfYIEyXLJ4cTNrbHAuyU8ciuiRTgshiYgLmncwJAETZx
KQ51EVsVlKrpFUqI4H72Z7esb6tObC/Vn0B5etR0mwA2SdQN1FkKrKyU3qUNTwU0
K0H5Xm2rPQcaEC0+rwJAEuvRdNQuB9+vzOW4zVig6HS38bHyJ+qLkQCDWbbwrNlj
vcVkUrsg027gA5jRttaXMk8x9shFuHB9V5/pkBFwag==
-----END RSA PRIVATE KEY-----
END

#----------------------------------------------------------------------

my $server = Test::ACME2_Server->new( ca_class => 'MyCA' );

my $acme = MyCA->new(
key => $_RSA_KEY,
directory => MyCA->DIRECTORY_PATH(),
);

$acme->create_account(
termsOfServiceAgreed => 1,
);

# Create an order — it starts in 'pending' status with no certificate URL
my @domains = ('example.com');
my $order = $acme->create_order(
identifiers => [ map { { type => 'dns', value => $_ } } @domains ],
);

is( $order->status(), 'pending', 'new order is pending' );
is( $order->certificate(), undef, 'pending order has no certificate URL' );

# get_certificate_chain() must throw when certificate URL is not set
throws_ok(
sub { $acme->get_certificate_chain($order) },
qr/certificate/i,
'get_certificate_chain() throws on order without certificate URL',
);

# get_certificate_chains() must throw the same way
throws_ok(
sub { $acme->get_certificate_chains($order) },
qr/certificate/i,
'get_certificate_chains() throws on order without certificate URL',
);

# Now also test with an explicitly non-valid status
# (Simulate an order that has status 'processing' but no cert URL)
$order->update({ status => 'processing', certificate => undef });

throws_ok(
sub { $acme->get_certificate_chain($order) },
qr/certificate/i,
'get_certificate_chain() throws for processing order',
);

done_testing();
Loading