Skip to content

Commit 8a85d59

Browse files
committed
Tests: tests for loading "store:..." keys.
1 parent 98d6acc commit 8a85d59

File tree

2 files changed

+365
-0
lines changed

2 files changed

+365
-0
lines changed

ssl_provider_keys.t

Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
#!/usr/bin/perl
2+
3+
# (C) Sergey Kandaurov
4+
# (C) Aleksei Bavshin
5+
# (C) Nginx, Inc.
6+
7+
# Tests for http ssl module, loading "store:..." keys from OpenSSL providers.
8+
9+
###############################################################################
10+
11+
use warnings;
12+
use strict;
13+
14+
use Test::More;
15+
16+
BEGIN { use FindBin; chdir($FindBin::Bin); }
17+
18+
use lib 'lib';
19+
use Test::Nginx;
20+
21+
###############################################################################
22+
23+
select STDERR; $| = 1;
24+
select STDOUT; $| = 1;
25+
26+
plan(skip_all => 'win32') if $^O eq 'MSWin32';
27+
28+
plan(skip_all => 'may not work, incompatible with sanitizers')
29+
unless $ENV{TEST_NGINX_UNSAFE};
30+
31+
my $t = Test::Nginx->new()->has(qw/http proxy http_ssl openssl:3/)
32+
->has_daemon('openssl')->has_daemon('softhsm2-util');
33+
34+
plan(skip_all => 'not yet') unless $t->has_version('1.29.0');
35+
36+
$t->write_file_expand('nginx.conf', <<'EOF');
37+
38+
%%TEST_GLOBALS%%
39+
40+
daemon off;
41+
42+
events {
43+
}
44+
45+
env SOFTHSM2_CONF;
46+
47+
http {
48+
%%TEST_GLOBALS_HTTP%%
49+
50+
server {
51+
listen 127.0.0.1:8081 ssl;
52+
listen 127.0.0.1:8080;
53+
server_name localhost;
54+
55+
ssl_certificate localhost.crt;
56+
ssl_certificate_key "store:pkcs11:token=NginxZero;object=nx_key_0";
57+
58+
ssl_password_file pin.txt;
59+
60+
location / {
61+
# index index.html by default
62+
}
63+
64+
location /proxy {
65+
proxy_pass https://127.0.0.1:8081/;
66+
}
67+
68+
location /var {
69+
proxy_pass https://127.0.0.1:8082/;
70+
proxy_ssl_name localhost;
71+
proxy_ssl_server_name on;
72+
}
73+
}
74+
75+
server {
76+
listen 127.0.0.1:8082 ssl;
77+
server_name localhost;
78+
79+
ssl_certificate $ssl_server_name.crt;
80+
ssl_certificate_key "store:pkcs11:token=NginxZero;object=nx_key_0";
81+
82+
ssl_password_file pin.txt;
83+
84+
location / {
85+
# index index.html by default
86+
}
87+
}
88+
}
89+
90+
EOF
91+
92+
# Create a SoftHSM token with a secret key, and configure OpenSSL to access it
93+
# using the pkcs11 provider (https://github.com/latchset/pkcs11-provider).
94+
#
95+
# Note that library paths vary on different systems,
96+
# and may need to be adjusted.
97+
98+
my $libsofthsm2_path;
99+
my @so_paths = (
100+
'/usr/lib/softhsm', # Debian-based
101+
'/usr/local/lib/softhsm', # FreeBSD
102+
'/opt/local/lib/softhsm', # MacPorts
103+
'/lib64', # RHEL-based
104+
split /:/, $ENV{TEST_NGINX_SOFTHSM} || ''
105+
);
106+
107+
for my $so_path (@so_paths) {
108+
$so_path .= '/libsofthsm2.so';
109+
if (-e $so_path) {
110+
$libsofthsm2_path = $so_path;
111+
last;
112+
}
113+
};
114+
115+
plan(skip_all => "libsofthsm2.so not found") unless $libsofthsm2_path;
116+
117+
my $openssl_conf = <<EOF;
118+
openssl_conf = openssl_def
119+
120+
[openssl_def]
121+
providers = provider_sect
122+
123+
[provider_sect]
124+
default = default_sect
125+
pkcs11 = pkcs11_sect
126+
127+
[default_sect]
128+
activate = 1
129+
130+
[pkcs11_sect]
131+
pkcs11-module-path = $libsofthsm2_path
132+
pkcs11-module-cache-pins = cache
133+
# https://github.com/latchset/pkcs11-provider/commit/ab6370fd
134+
pkcs11-module-quirks = no-deinit no-operation-state
135+
module = /usr/local/lib/ossl-modules/pkcs11.so
136+
activate = 1
137+
138+
[ req ]
139+
default_bits = 2048
140+
encrypt_key = no
141+
distinguished_name = req_distinguished_name
142+
[ req_distinguished_name ]
143+
EOF
144+
145+
$openssl_conf =~ s|^(?=module)|# |m if $^O ne 'freebsd';
146+
$t->write_file('openssl.conf', $openssl_conf);
147+
148+
my $d = $t->testdir();
149+
150+
$t->write_file('softhsm2.conf', <<EOF);
151+
directories.tokendir = $d/tokens/
152+
objectstore.backend = file
153+
EOF
154+
155+
mkdir($d . '/tokens');
156+
157+
$ENV{SOFTHSM2_CONF} = "$d/softhsm2.conf";
158+
$ENV{OPENSSL_CONF} = "$d/openssl.conf";
159+
160+
foreach my $name ('localhost') {
161+
system('softhsm2-util --init-token --slot 0 --label NginxZero '
162+
. '--pin 1234 --so-pin 1234 '
163+
. ">>$d/openssl.out 2>&1");
164+
165+
system("openssl genrsa -out $d/$name.key 2048 "
166+
. ">>$d/openssl.out 2>&1") == 0
167+
or die "Can't create private key: $!\n";
168+
169+
system("softhsm2-util --import $d/$name.key --id 00 --label nx_key_0 "
170+
. '--token NginxZero --pin 1234 '
171+
. ">>$d/openssl.out 2>&1") == 0
172+
or die "Can't import private key: $!\n";
173+
174+
system('openssl req -x509 -new '
175+
. "-subj /CN=$name/ -out $d/$name.crt -text -passin pass:1234 "
176+
. '-key "pkcs11:token=NginxZero;object=nx_key_0" '
177+
. ">>$d/openssl.out 2>&1") == 0
178+
or plan(skip_all => "missing pkcs11-provider");
179+
}
180+
181+
$t->write_file('pin.txt', '1234');
182+
$t->write_file('index.html', '');
183+
184+
$t->run()->plan(2);
185+
186+
###############################################################################
187+
188+
like(http_get('/proxy'), qr/200 OK/, 'ssl provider keys');
189+
like(http_get('/var'), qr/200 OK/, 'ssl_certificate with variable');
190+
191+
###############################################################################

ssl_store_keys.t

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
#!/usr/bin/perl
2+
3+
# (C) Aleksei Bavshin
4+
# (C) Nginx, Inc.
5+
6+
# Tests for http ssl module, loading "store:..." keys.
7+
8+
###############################################################################
9+
10+
use warnings;
11+
use strict;
12+
13+
use Test::More;
14+
15+
BEGIN { use FindBin; chdir($FindBin::Bin); }
16+
17+
use lib 'lib';
18+
use Test::Nginx qw/ :DEFAULT http_end /;
19+
20+
###############################################################################
21+
22+
select STDERR; $| = 1;
23+
select STDOUT; $| = 1;
24+
25+
my $t = Test::Nginx->new()
26+
->has(qw/http http_ssl geo openssl:1.1.1 socket_ssl_sni/)
27+
->has_daemon('openssl');
28+
29+
plan(skip_all => 'BoringSSL') if $t->has_module('BoringSSL|AWS-LC');
30+
plan(skip_all => 'not yet') unless $t->has_version('1.29.0');
31+
32+
$t->write_file_expand('nginx.conf', <<'EOF');
33+
34+
%%TEST_GLOBALS%%
35+
36+
daemon off;
37+
38+
events {
39+
}
40+
41+
http {
42+
%%TEST_GLOBALS_HTTP%%
43+
44+
geo $localhost {
45+
default localhost;
46+
}
47+
48+
geo $pass {
49+
default pass;
50+
}
51+
52+
add_header X-SSL $ssl_server_name;
53+
54+
server {
55+
listen 127.0.0.1:8080 ssl;
56+
server_name default;
57+
58+
ssl_certificate localhost.crt;
59+
ssl_certificate_key store:file:%%TESTDIR%%/localhost.key;
60+
}
61+
62+
server {
63+
listen 127.0.0.1:8080 ssl;
64+
server_name variable;
65+
66+
ssl_certificate localhost.crt;
67+
ssl_certificate_key store:file:%%TESTDIR%%/$localhost.key;
68+
}
69+
70+
server {
71+
listen 127.0.0.1:8080 ssl;
72+
server_name pass;
73+
74+
ssl_certificate pass.crt;
75+
ssl_certificate_key store:file:%%TESTDIR%%/pass.key;
76+
77+
ssl_password_file password;
78+
}
79+
80+
server {
81+
listen 127.0.0.1:8080 ssl;
82+
server_name variable-pass;
83+
84+
ssl_certificate pass.crt;
85+
ssl_certificate_key store:file:%%TESTDIR%%/$pass.key;
86+
87+
ssl_password_file password;
88+
}
89+
90+
server {
91+
listen 127.0.0.1:8080 ssl;
92+
server_name variable-no-pass;
93+
94+
ssl_certificate pass.crt;
95+
ssl_certificate_key store:file:%%TESTDIR%%/$pass.key;
96+
}
97+
}
98+
99+
EOF
100+
101+
$t->write_file('openssl.conf', <<EOF);
102+
[ req ]
103+
default_bits = 2048
104+
encrypt_key = no
105+
distinguished_name = req_distinguished_name
106+
[ req_distinguished_name ]
107+
EOF
108+
109+
my $d = $t->testdir();
110+
111+
foreach my $name ('localhost') {
112+
system('openssl req -x509 -new '
113+
. "-config $d/openssl.conf -subj /CN=$name/ "
114+
. "-out $d/$name.crt -keyout $d/$name.key "
115+
. ">>$d/openssl.out 2>&1") == 0
116+
or die "Can't create certificate for $name: $!\n";
117+
}
118+
119+
foreach my $name ('pass') {
120+
system("openssl genrsa -out $d/$name.key -passout pass:$name "
121+
. "-aes128 2048 >>$d/openssl.out 2>&1") == 0
122+
or die "Can't create private key: $!\n";
123+
system('openssl req -x509 -new '
124+
. "-config $d/openssl.conf -subj /CN=$name/ "
125+
. "-out $d/$name.crt "
126+
. "-key $d/$name.key -passin pass:$name"
127+
. ">>$d/openssl.out 2>&1") == 0
128+
or die "Can't create certificate for $name: $!\n";
129+
}
130+
131+
132+
$t->write_file('password', 'pass');
133+
$t->write_file('index.html', '');
134+
135+
$t->run()->plan(9);
136+
137+
###############################################################################
138+
139+
like(cert('default'), qr/CN=localhost/, 'default key');
140+
like(get('default'), qr/default/, 'default context');
141+
142+
like(cert('variable'), qr/CN=localhost/, 'key with vars');
143+
like(get('variable'), qr/variable/, 'context with vars');
144+
145+
like(cert('pass'), qr/CN=pass/, 'encrypted key');
146+
like(get('pass'), qr/pass/, 'encrypted context');
147+
148+
like(cert('variable-pass'), qr/CN=pass/, 'encrypted key - vars');
149+
like(get('variable-pass'), qr/variable-pass/, 'encrypted context - vars');
150+
151+
is(cert('variable-no-pass'), undef, 'encrypted key - no pass');
152+
153+
###############################################################################
154+
155+
sub get {
156+
my $s = get_socket(@_) || return;
157+
return http_end($s);
158+
}
159+
160+
sub cert {
161+
my $s = get_socket(@_) || return;
162+
return $s->dump_peer_certificate();
163+
}
164+
165+
sub get_socket {
166+
my ($host) = @_;
167+
return http_get(
168+
'/', start => 1, PeerAddr => '127.0.0.1:' . port(8080),
169+
SSL => 1,
170+
SSL_hostname => $host,
171+
);
172+
}
173+
174+
###############################################################################

0 commit comments

Comments
 (0)