Mercurial > hg > nginx-tests
comparison stream_js_fetch_https.t @ 1736:f7a8997c46c7
Tests: added fetch js tests, HTTPS support.
author | Antoine Bonavita <antoine.bonavita@gmail.com> |
---|---|
date | Mon, 04 Oct 2021 14:33:46 +0000 |
parents | |
children | 564f74bf6e4d |
comparison
equal
deleted
inserted
replaced
1735:8bdf548487f6 | 1736:f7a8997c46c7 |
---|---|
1 #!/usr/bin/perl | |
2 | |
3 # (C) Dmitry Volyntsev | |
4 # (C) Nginx, Inc. | |
5 | |
6 # Tests for stream njs module, fetch method, https support. | |
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; | |
19 use Test::Nginx::Stream qw/ stream /; | |
20 | |
21 ############################################################################### | |
22 | |
23 select STDERR; $| = 1; | |
24 select STDOUT; $| = 1; | |
25 | |
26 my $t = Test::Nginx->new()->has(qw/http http_ssl rewrite stream stream_return/) | |
27 ->write_file_expand('nginx.conf', <<'EOF'); | |
28 | |
29 %%TEST_GLOBALS%% | |
30 | |
31 daemon off; | |
32 | |
33 events { | |
34 } | |
35 | |
36 http { | |
37 %%TEST_GLOBALS_HTTP%% | |
38 | |
39 js_import test.js; | |
40 | |
41 server { | |
42 listen 127.0.0.1:8080; | |
43 server_name localhost; | |
44 | |
45 location /njs { | |
46 js_content test.njs; | |
47 } | |
48 } | |
49 | |
50 server { | |
51 listen 127.0.0.1:8081 ssl default; | |
52 server_name default.example.com; | |
53 | |
54 ssl_certificate default.example.com.chained.crt; | |
55 ssl_certificate_key default.example.com.key; | |
56 | |
57 location /loc { | |
58 return 200 "You are at default.example.com."; | |
59 } | |
60 } | |
61 | |
62 server { | |
63 listen 127.0.0.1:8081 ssl; | |
64 server_name 1.example.com; | |
65 | |
66 ssl_certificate 1.example.com.chained.crt; | |
67 ssl_certificate_key 1.example.com.key; | |
68 | |
69 location /loc { | |
70 return 200 "You are at 1.example.com."; | |
71 } | |
72 } | |
73 } | |
74 | |
75 stream { | |
76 %%TEST_GLOBALS_STREAM%% | |
77 | |
78 js_import test.js; | |
79 js_preread test.preread; | |
80 js_var $message; | |
81 | |
82 resolver 127.0.0.1:%%PORT_8981_UDP%%; | |
83 resolver_timeout 1s; | |
84 | |
85 server { | |
86 listen 127.0.0.1:8082; | |
87 return "default CA $message"; | |
88 } | |
89 | |
90 server { | |
91 listen 127.0.0.1:8083; | |
92 return "my CA $message"; | |
93 | |
94 js_fetch_ciphers HIGH:!aNull:!MD5; | |
95 js_fetch_protocols TLSv1.1 TLSv1.2; | |
96 js_fetch_trusted_certificate myca.crt; | |
97 } | |
98 | |
99 server { | |
100 listen 127.0.0.1:8084; | |
101 return "my CA with verify_depth=0 $message"; | |
102 | |
103 js_fetch_verify_depth 0; | |
104 js_fetch_trusted_certificate myca.crt; | |
105 } | |
106 } | |
107 | |
108 EOF | |
109 | |
110 my $p1 = port(8081); | |
111 my $p2 = port(8082); | |
112 my $p3 = port(8083); | |
113 my $p4 = port(8084); | |
114 | |
115 $t->write_file('test.js', <<EOF); | |
116 function test_njs(r) { | |
117 r.return(200, njs.version); | |
118 } | |
119 | |
120 function preread(s) { | |
121 s.on('upload', function (data, flags) { | |
122 if (data.startsWith('GO')) { | |
123 s.off('upload'); | |
124 ngx.fetch('https://' + data.substring(2) + ':$p1/loc') | |
125 .then(reply => { | |
126 s.variables.message = 'https OK - ' + reply.status; | |
127 s.done(); | |
128 }) | |
129 .catch(e => { | |
130 s.variables.message = 'https NOK - ' + e.message; | |
131 s.done(); | |
132 }) | |
133 | |
134 } else if (data.length) { | |
135 s.deny(); | |
136 } | |
137 }); | |
138 } | |
139 | |
140 export default {njs: test_njs, preread}; | |
141 EOF | |
142 | |
143 my $d = $t->testdir(); | |
144 | |
145 $t->write_file('openssl.conf', <<EOF); | |
146 [ req ] | |
147 default_bits = 2048 | |
148 encrypt_key = no | |
149 distinguished_name = req_distinguished_name | |
150 [ req_distinguished_name ] | |
151 EOF | |
152 | |
153 $t->write_file('myca.conf', <<EOF); | |
154 [ ca ] | |
155 default_ca = myca | |
156 | |
157 [ myca ] | |
158 new_certs_dir = $d | |
159 database = $d/certindex | |
160 default_md = sha256 | |
161 policy = myca_policy | |
162 serial = $d/certserial | |
163 default_days = 1 | |
164 x509_extensions = myca_extensions | |
165 | |
166 [ myca_policy ] | |
167 commonName = supplied | |
168 | |
169 [ myca_extensions ] | |
170 basicConstraints = critical,CA:TRUE | |
171 EOF | |
172 | |
173 system('openssl req -x509 -new ' | |
174 . "-config $d/openssl.conf -subj /CN=myca/ " | |
175 . "-out $d/myca.crt -keyout $d/myca.key " | |
176 . ">>$d/openssl.out 2>&1") == 0 | |
177 or die "Can't create self-signed certificate for CA: $!\n"; | |
178 | |
179 foreach my $name ('intermediate', 'default.example.com', '1.example.com') { | |
180 system("openssl req -new " | |
181 . "-config $d/openssl.conf -subj /CN=$name/ " | |
182 . "-out $d/$name.csr -keyout $d/$name.key " | |
183 . ">>$d/openssl.out 2>&1") == 0 | |
184 or die "Can't create certificate signing req for $name: $!\n"; | |
185 } | |
186 | |
187 $t->write_file('certserial', '1000'); | |
188 $t->write_file('certindex', ''); | |
189 | |
190 system("openssl ca -batch -config $d/myca.conf " | |
191 . "-keyfile $d/myca.key -cert $d/myca.crt " | |
192 . "-subj /CN=intermediate/ -in $d/intermediate.csr " | |
193 . "-out $d/intermediate.crt " | |
194 . ">>$d/openssl.out 2>&1") == 0 | |
195 or die "Can't sign certificate for intermediate: $!\n"; | |
196 | |
197 foreach my $name ('default.example.com', '1.example.com') { | |
198 system("openssl ca -batch -config $d/myca.conf " | |
199 . "-keyfile $d/intermediate.key -cert $d/intermediate.crt " | |
200 . "-subj /CN=$name/ -in $d/$name.csr -out $d/$name.crt " | |
201 . ">>$d/openssl.out 2>&1") == 0 | |
202 or die "Can't sign certificate for $name $!\n"; | |
203 $t->write_file("$name.chained.crt", $t->read_file("$name.crt") | |
204 . $t->read_file('intermediate.crt')); | |
205 } | |
206 | |
207 $t->try_run('no njs.fetch')->plan(4); | |
208 | |
209 $t->run_daemon(\&dns_daemon, port(8981), $t); | |
210 $t->waitforfile($t->testdir . '/' . port(8981)); | |
211 | |
212 ############################################################################### | |
213 | |
214 local $TODO = 'not yet' | |
215 unless http_get('/njs') =~ /^([.0-9]+)$/m && $1 ge '0.7.0'; | |
216 | |
217 like(stream("127.0.0.1:$p2")->io('GOdefault.example.com'), | |
218 qr/connect failed/s, 'stream non trusted CA'); | |
219 like(stream("127.0.0.1:$p3")->io('GOdefault.example.com'), | |
220 qr/https OK/s, 'stream trusted CA'); | |
221 like(stream("127.0.0.1:$p3")->io('GOlocalhost'), | |
222 qr/connect failed/s, 'stream wrong CN'); | |
223 like(stream("127.0.0.1:$p4")->io('GOdefaul.example.com'), | |
224 qr/connect failed/s, 'stream verify_depth too small'); | |
225 | |
226 ############################################################################### | |
227 | |
228 sub reply_handler { | |
229 my ($recv_data, $port, %extra) = @_; | |
230 | |
231 my (@name, @rdata); | |
232 | |
233 use constant NOERROR => 0; | |
234 use constant A => 1; | |
235 use constant IN => 1; | |
236 | |
237 # default values | |
238 | |
239 my ($hdr, $rcode, $ttl) = (0x8180, NOERROR, 3600); | |
240 | |
241 # decode name | |
242 | |
243 my ($len, $offset) = (undef, 12); | |
244 while (1) { | |
245 $len = unpack("\@$offset C", $recv_data); | |
246 last if $len == 0; | |
247 $offset++; | |
248 push @name, unpack("\@$offset A$len", $recv_data); | |
249 $offset += $len; | |
250 } | |
251 | |
252 $offset -= 1; | |
253 my ($id, $type, $class) = unpack("n x$offset n2", $recv_data); | |
254 | |
255 my $name = join('.', @name); | |
256 | |
257 if ($type == A) { | |
258 push @rdata, rd_addr($ttl, '127.0.0.1'); | |
259 } | |
260 | |
261 $len = @name; | |
262 pack("n6 (C/a*)$len x n2", $id, $hdr | $rcode, 1, scalar @rdata, | |
263 0, 0, @name, $type, $class) . join('', @rdata); | |
264 } | |
265 | |
266 sub rd_addr { | |
267 my ($ttl, $addr) = @_; | |
268 | |
269 my $code = 'split(/\./, $addr)'; | |
270 | |
271 return pack 'n3N', 0xc00c, A, IN, $ttl if $addr eq ''; | |
272 | |
273 pack 'n3N nC4', 0xc00c, A, IN, $ttl, eval "scalar $code", eval($code); | |
274 } | |
275 | |
276 sub dns_daemon { | |
277 my ($port, $t) = @_; | |
278 | |
279 my ($data, $recv_data); | |
280 my $socket = IO::Socket::INET->new( | |
281 LocalAddr => '127.0.0.1', | |
282 LocalPort => $port, | |
283 Proto => 'udp', | |
284 ) | |
285 or die "Can't create listening socket: $!\n"; | |
286 | |
287 local $SIG{PIPE} = 'IGNORE'; | |
288 | |
289 # signal we are ready | |
290 | |
291 open my $fh, '>', $t->testdir() . '/' . $port; | |
292 close $fh; | |
293 | |
294 while (1) { | |
295 $socket->recv($recv_data, 65536); | |
296 $data = reply_handler($recv_data, $port); | |
297 $socket->send($data); | |
298 } | |
299 } | |
300 | |
301 ############################################################################### |