Skip to content

Commit 7a5e27a

Browse files
committed
Tests: ACME profile support tests.
1 parent 1d9a91b commit 7a5e27a

File tree

1 file changed

+200
-0
lines changed

1 file changed

+200
-0
lines changed

t/acme_profiles.t

Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
#!/usr/bin/perl
2+
3+
# Copyright (c) F5, Inc.
4+
#
5+
# This source code is licensed under the Apache License, Version 2.0 license
6+
# found in the LICENSE file in the root directory of this source tree.
7+
8+
# Tests for ACME client: ACME Profiles Extension.
9+
10+
###############################################################################
11+
12+
use warnings;
13+
use strict;
14+
15+
use Test::More;
16+
17+
BEGIN { use FindBin; chdir($FindBin::Bin); }
18+
19+
use lib 'lib';
20+
use Test::Nginx;
21+
use Test::Nginx::ACME;
22+
use Test::Nginx::DNS;
23+
24+
###############################################################################
25+
26+
select STDERR; $| = 1;
27+
select STDOUT; $| = 1;
28+
29+
my $t = Test::Nginx->new()->has(qw/http http_ssl socket_ssl/)
30+
->has_daemon('openssl');
31+
32+
eval { require Date::Parse; };
33+
plan(skip_all => 'Date::Parse is not installed') if $@;
34+
35+
eval { defined &Net::SSLeay::P_ASN1_TIME_get_isotime or die; };
36+
plan(skip_all => 'no P_ASN1_TIME_get_isotime, old Net::SSLeay') if $@;
37+
38+
$t->write_file_expand('nginx.conf', <<'EOF');
39+
40+
%%TEST_GLOBALS%%
41+
42+
daemon off;
43+
44+
events {
45+
}
46+
47+
http {
48+
%%TEST_GLOBALS_HTTP%%
49+
50+
resolver 127.0.0.1:%%PORT_8980_UDP%%;
51+
52+
acme_issuer default {
53+
uri https://acme.test:%%PORT_9000%%/dir;
54+
profile default;
55+
ssl_trusted_certificate acme.test.crt;
56+
state_path %%TESTDIR%%/acme_default;
57+
accept_terms_of_service;
58+
}
59+
60+
acme_issuer shortlived {
61+
uri https://acme.test:%%PORT_9000%%/dir;
62+
profile shortlived require;
63+
ssl_trusted_certificate acme.test.crt;
64+
state_path %%TESTDIR%%/acme_shortlived;
65+
accept_terms_of_service;
66+
}
67+
68+
server {
69+
listen 127.0.0.1:8080;
70+
server_name example.test;
71+
}
72+
73+
server {
74+
listen 127.0.0.1:8443 ssl;
75+
server_name example.test;
76+
77+
acme_certificate default;
78+
79+
ssl_certificate $acme_certificate;
80+
ssl_certificate_key $acme_certificate_key;
81+
}
82+
83+
server {
84+
listen 127.0.0.1:8444 ssl;
85+
server_name shortlived.test;
86+
87+
acme_certificate shortlived;
88+
89+
ssl_certificate $acme_certificate;
90+
ssl_certificate_key $acme_certificate_key;
91+
}
92+
}
93+
94+
EOF
95+
96+
$t->write_file('openssl.conf', <<EOF);
97+
[ req ]
98+
default_bits = 2048
99+
encrypt_key = no
100+
distinguished_name = req_distinguished_name
101+
[ req_distinguished_name ]
102+
EOF
103+
104+
my $d = $t->testdir();
105+
106+
foreach my $name ('acme.test') {
107+
system('openssl req -x509 -new '
108+
. "-config $d/openssl.conf -subj /CN=$name/ "
109+
. "-out $d/$name.crt -keyout $d/$name.key "
110+
. ">>$d/openssl.out 2>&1") == 0
111+
or die "Can't create certificate for $name: $!\n";
112+
}
113+
114+
my $dp = port(8980, udp=>1);
115+
my @dc = (
116+
{ name => 'acme.test', A => '127.0.0.1' },
117+
{ name => 'example.test', A => '127.0.0.1' },
118+
{ name => 'shortlived.test', A => '127.0.0.1' },
119+
);
120+
121+
my $acme = Test::Nginx::ACME->new($t, port(9000), port(9001),
122+
$t->testdir . '/acme.test.crt',
123+
$t->testdir . '/acme.test.key',
124+
http_port => port(8080),
125+
dns_port => $dp,
126+
nosleep => 1,
127+
conf => {
128+
profiles => {
129+
default => {
130+
description => "The default profile",
131+
validityPeriod => 777600,
132+
},
133+
shortlived => {
134+
description => "A short-lived cert profile",
135+
validityPeriod => 86400,
136+
},
137+
},
138+
},
139+
)->has(qw/profile/);
140+
141+
$t->run_daemon(\&Test::Nginx::DNS::dns_test_daemon, $t, $dp, \@dc);
142+
$t->waitforfile($t->testdir . '/' . $dp);
143+
144+
$t->run_daemon(\&Test::Nginx::ACME::acme_test_daemon, $t, $acme);
145+
$t->waitforsocket('127.0.0.1:' . $acme->port());
146+
$t->write_file('acme-root.crt', $acme->trusted_ca());
147+
148+
$t->write_file('index.html', 'SUCCESS');
149+
$t->plan(2)->run();
150+
151+
###############################################################################
152+
153+
$acme->wait_certificate('acme_default/example.test') or die "no certificate";
154+
$acme->wait_certificate('acme_shortlived/shortlived.test')
155+
or die "no certificate";
156+
157+
my $valid = get(8443, 'example.test', 'acme-root');
158+
159+
ok(defined $valid && $valid > 2 * 86400, 'default profile');
160+
161+
$valid = get(8444, 'shortlived.test', 'acme-root');
162+
163+
ok(defined $valid && $valid < 86400, 'shortlived profile');
164+
165+
###############################################################################
166+
167+
sub get {
168+
my ($port, $host, $ca) = @_;
169+
170+
$ca = undef if $IO::Socket::SSL::VERSION < 2.062
171+
|| !eval { Net::SSLeay::X509_V_FLAG_PARTIAL_CHAIN() };
172+
173+
my $s = http_get(
174+
'/', start => 1, PeerAddr => '127.0.0.1:' . port($port),
175+
SSL => 1,
176+
$ca ? (
177+
SSL_ca_file => "$d/$ca.crt",
178+
SSL_verifycn_name => $host,
179+
SSL_verify_mode => IO::Socket::SSL::SSL_VERIFY_PEER(),
180+
) : ()
181+
);
182+
183+
return $s unless $s;
184+
185+
my $ssl = $s->_get_ssl_object();
186+
my $cert = Net::SSLeay::get_peer_certificate($ssl);
187+
188+
return cert_validity($cert);
189+
}
190+
191+
sub cert_validity {
192+
my ($cert) = @_;
193+
194+
my $notAfter = Net::SSLeay::X509_get_notAfter($cert) or return;
195+
$notAfter = Net::SSLeay::P_ASN1_TIME_get_isotime($notAfter) or return;
196+
$notAfter = Date::Parse::str2time($notAfter) or return;
197+
return $notAfter - time();
198+
}
199+
200+
###############################################################################

0 commit comments

Comments
 (0)