1
1
#![ allow( dead_code) ]
2
2
3
- use std:: {
4
- env, fs,
5
- io:: { self , Write } ,
6
- net:: SocketAddr ,
7
- path:: PathBuf ,
8
- process,
9
- thread:: sleep,
10
- time:: Duration ,
11
- } ;
3
+ use std:: { env, fs, io, net:: SocketAddr , path:: PathBuf , process, thread:: sleep, time:: Duration } ;
12
4
13
5
use futures:: Future ;
14
6
use redis:: Value ;
@@ -51,7 +43,6 @@ enum ServerType {
51
43
52
44
pub struct RedisServer {
53
45
pub process : process:: Child ,
54
- stunnel_process : Option < process:: Child > ,
55
46
tempdir : Option < tempfile:: TempDir > ,
56
47
addr : redis:: ConnectionAddr ,
57
48
}
@@ -131,77 +122,126 @@ impl RedisServer {
131
122
132
123
RedisServer {
133
124
process : spawner ( & mut redis_cmd) ,
134
- stunnel_process : None ,
135
125
tempdir : None ,
136
126
addr,
137
127
}
138
128
}
139
129
redis:: ConnectionAddr :: TcpTls { ref host, port, .. } => {
140
- // prepare redis with unix socket
141
- redis_cmd
142
- . arg ( "--port" )
143
- . arg ( "0" )
144
- . arg ( "--unixsocket" )
145
- . arg ( tempdir. path ( ) . join ( "redis.sock" ) ) ;
130
+ // Based on shell script in redis's server tests
131
+ // https://github.com/redis/redis/blob/8c291b97b95f2e011977b522acf77ead23e26f55/utils/gen-test-certs.sh
132
+ let tls_ca_crt_path = tempdir. path ( ) . join ( "ca.crt" ) ;
133
+ let tls_ca_key_path = tempdir. path ( ) . join ( "ca.key" ) ;
134
+ let tls_ca_serial_path = tempdir. path ( ) . join ( "ca.txt" ) ;
135
+ let tls_redis_crt_path = tempdir. path ( ) . join ( "redis.crt" ) ;
136
+ let tls_redis_key_path = tempdir. path ( ) . join ( "redis.key" ) ;
137
+
138
+ fn make_key < S : AsRef < std:: ffi:: OsStr > > ( name : S , size : usize ) {
139
+ process:: Command :: new ( "openssl" )
140
+ . arg ( "genrsa" )
141
+ . arg ( "-out" )
142
+ . arg ( name)
143
+ . arg ( & format ! ( "{}" , size) )
144
+ . stdout ( process:: Stdio :: null ( ) )
145
+ . stderr ( process:: Stdio :: null ( ) )
146
+ . spawn ( )
147
+ . expect ( "failed to spawn openssl" )
148
+ . wait ( )
149
+ . expect ( "failed to create key" ) ;
150
+ }
146
151
147
- // create a self-signed TLS server cert
148
- let tls_key_path = tempdir. path ( ) . join ( "key.pem" ) ;
149
- let tls_cert_path = tempdir. path ( ) . join ( "cert.crt" ) ;
152
+ // Build CA Key
153
+ make_key ( & tls_ca_key_path, 4096 ) ;
154
+
155
+ // Build redis key
156
+ make_key ( & tls_redis_key_path, 2048 ) ;
157
+
158
+ // Build CA Cert
150
159
process:: Command :: new ( "openssl" )
151
160
. arg ( "req" )
152
- . arg ( "-nodes" )
153
- . arg ( "-new" )
154
161
. arg ( "-x509" )
155
- . arg ( "-keyout" )
156
- . arg ( & tls_key_path)
162
+ . arg ( "-new" )
163
+ . arg ( "-nodes" )
164
+ . arg ( "-sha256" )
165
+ . arg ( "-key" )
166
+ . arg ( & tls_ca_key_path)
167
+ . arg ( "-days" )
168
+ . arg ( "3650" )
169
+ . arg ( "-subj" )
170
+ . arg ( "/O=Redis Test/CN=Certificate Authority" )
157
171
. arg ( "-out" )
158
- . arg ( & tls_cert_path)
172
+ . arg ( & tls_ca_crt_path)
173
+ . stdout ( process:: Stdio :: null ( ) )
174
+ . stderr ( process:: Stdio :: null ( ) )
175
+ . spawn ( )
176
+ . expect ( "failed to spawn openssl" )
177
+ . wait ( )
178
+ . expect ( "failed to create CA cert" ) ;
179
+
180
+ // Read redis key
181
+ let mut key_cmd = process:: Command :: new ( "openssl" )
182
+ . arg ( "req" )
183
+ . arg ( "-new" )
184
+ . arg ( "-sha256" )
159
185
. arg ( "-subj" )
160
- . arg ( "/C=XX/ST=crates/L=redis-rs/O=testing/CN=localhost" )
186
+ . arg ( "/O=Redis Test/CN=Generic-cert" )
187
+ . arg ( "-key" )
188
+ . arg ( & tls_redis_key_path)
189
+ . stdout ( process:: Stdio :: piped ( ) )
190
+ . stderr ( process:: Stdio :: null ( ) )
191
+ . spawn ( )
192
+ . expect ( "failed to spawn openssl" ) ;
193
+
194
+ // build redis cert
195
+ process:: Command :: new ( "openssl" )
196
+ . arg ( "x509" )
197
+ . arg ( "-req" )
198
+ . arg ( "-sha256" )
199
+ . arg ( "-CA" )
200
+ . arg ( & tls_ca_crt_path)
201
+ . arg ( "-CAkey" )
202
+ . arg ( & tls_ca_key_path)
203
+ . arg ( "-CAserial" )
204
+ . arg ( & tls_ca_serial_path)
205
+ . arg ( "-CAcreateserial" )
206
+ . arg ( "-days" )
207
+ . arg ( "365" )
208
+ . arg ( "-out" )
209
+ . arg ( & tls_redis_crt_path)
210
+ . stdin ( key_cmd. stdout . take ( ) . expect ( "should have stdout" ) )
161
211
. stdout ( process:: Stdio :: null ( ) )
162
212
. stderr ( process:: Stdio :: null ( ) )
163
213
. spawn ( )
164
214
. expect ( "failed to spawn openssl" )
165
215
. wait ( )
166
- . expect ( "failed to create self-signed TLS certificate" ) ;
167
-
168
- let stunnel_config_path = tempdir. path ( ) . join ( "stunnel.conf" ) ;
169
- let mut stunnel_config_file = fs:: File :: create ( & stunnel_config_path) . unwrap ( ) ;
170
- stunnel_config_file
171
- . write_all (
172
- format ! (
173
- r#"
174
- pid = {tempdir}/stunnel.pid
175
- cert = {tempdir}/cert.crt
176
- key = {tempdir}/key.pem
177
- verify = 0
178
- foreground = yes
179
- [redis]
180
- accept = {host}:{stunnel_port}
181
- connect = {tempdir}/redis.sock
182
- "# ,
183
- tempdir = tempdir. path( ) . display( ) ,
184
- host = host,
185
- stunnel_port = port,
186
- )
187
- . as_bytes ( ) ,
188
- )
189
- . expect ( "could not write stunnel config file" ) ;
216
+ . expect ( "failed to create redis cert" ) ;
217
+
218
+ key_cmd. wait ( ) . expect ( "failed to create redis key" ) ;
219
+
220
+ // prepare redis with TLS
221
+ redis_cmd
222
+ . arg ( "--tls-port" )
223
+ . arg ( & port. to_string ( ) )
224
+ . arg ( "--port" )
225
+ . arg ( "0" )
226
+ . arg ( "--tls-cert-file" )
227
+ . arg ( & tls_redis_crt_path)
228
+ . arg ( "--tls-key-file" )
229
+ . arg ( & tls_redis_key_path)
230
+ . arg ( "--tls-ca-cert-file" )
231
+ . arg ( & tls_ca_crt_path)
232
+ . arg ( "--tls-auth-clients" ) // Make it so client doesn't have to send cert
233
+ . arg ( "no" )
234
+ . arg ( "--bind" )
235
+ . arg ( host) ;
190
236
191
237
let addr = redis:: ConnectionAddr :: TcpTls {
192
- host : "127.0.0.1" . to_string ( ) ,
238
+ host : host . clone ( ) ,
193
239
port,
194
240
insecure : true ,
195
241
} ;
196
- let mut stunnel_cmd = process:: Command :: new ( "stunnel" ) ;
197
- stunnel_cmd
198
- . stdout ( process:: Stdio :: null ( ) )
199
- . stderr ( process:: Stdio :: null ( ) )
200
- . arg ( & stunnel_config_path) ;
201
242
202
243
RedisServer {
203
244
process : spawner ( & mut redis_cmd) ,
204
- stunnel_process : Some ( stunnel_cmd. spawn ( ) . expect ( "could not start stunnel" ) ) ,
205
245
tempdir : Some ( tempdir) ,
206
246
addr,
207
247
}
@@ -214,32 +254,20 @@ impl RedisServer {
214
254
. arg ( & path) ;
215
255
RedisServer {
216
256
process : spawner ( & mut redis_cmd) ,
217
- stunnel_process : None ,
218
257
tempdir : Some ( tempdir) ,
219
258
addr,
220
259
}
221
260
}
222
261
}
223
262
}
224
263
225
- pub fn wait ( & mut self ) {
226
- self . process . wait ( ) . unwrap ( ) ;
227
- if let Some ( p) = self . stunnel_process . as_mut ( ) {
228
- p. wait ( ) . unwrap ( ) ;
229
- } ;
230
- }
231
-
232
264
pub fn get_client_addr ( & self ) -> & redis:: ConnectionAddr {
233
265
& self . addr
234
266
}
235
267
236
268
pub fn stop ( & mut self ) {
237
269
let _ = self . process . kill ( ) ;
238
270
let _ = self . process . wait ( ) ;
239
- if let Some ( p) = self . stunnel_process . as_mut ( ) {
240
- let _ = p. kill ( ) ;
241
- let _ = p. wait ( ) ;
242
- }
243
271
if let redis:: ConnectionAddr :: Unix ( ref path) = * self . get_client_addr ( ) {
244
272
fs:: remove_file ( & path) . ok ( ) ;
245
273
}
0 commit comments