Skip to content

Commit d263519

Browse files
committed
remove stunnel as a dep, use redis native tls
1 parent c7e39cb commit d263519

File tree

2 files changed

+97
-70
lines changed

2 files changed

+97
-70
lines changed

.github/workflows/rust.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ jobs:
3636
if: steps.cache-redis.outputs.cache-hit != 'true'
3737
run: |
3838
sudo apt-get update
39-
sudo apt-get install stunnel -y
4039
wget https://github.com/redis/redis/archive/${{ env.REDIS_VERSION }}.tar.gz;
4140
tar -xzvf ${{ env.REDIS_VERSION }}.tar.gz;
4241
pushd redis-${{ env.REDIS_VERSION }} && BUILD_TLS=yes make && sudo mv src/redis-server src/redis-cli /usr/bin/ && popd;

tests/support/mod.rs

Lines changed: 97 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,6 @@
11
#![allow(dead_code)]
22

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};
124

135
use futures::Future;
146
use redis::Value;
@@ -51,7 +43,6 @@ enum ServerType {
5143

5244
pub struct RedisServer {
5345
pub process: process::Child,
54-
stunnel_process: Option<process::Child>,
5546
tempdir: Option<tempfile::TempDir>,
5647
addr: redis::ConnectionAddr,
5748
}
@@ -131,77 +122,126 @@ impl RedisServer {
131122

132123
RedisServer {
133124
process: spawner(&mut redis_cmd),
134-
stunnel_process: None,
135125
tempdir: None,
136126
addr,
137127
}
138128
}
139129
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+
}
146151

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
150159
process::Command::new("openssl")
151160
.arg("req")
152-
.arg("-nodes")
153-
.arg("-new")
154161
.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")
157171
.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")
159185
.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"))
161211
.stdout(process::Stdio::null())
162212
.stderr(process::Stdio::null())
163213
.spawn()
164214
.expect("failed to spawn openssl")
165215
.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);
190236

191237
let addr = redis::ConnectionAddr::TcpTls {
192-
host: "127.0.0.1".to_string(),
238+
host: host.clone(),
193239
port,
194240
insecure: true,
195241
};
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);
201242

202243
RedisServer {
203244
process: spawner(&mut redis_cmd),
204-
stunnel_process: Some(stunnel_cmd.spawn().expect("could not start stunnel")),
205245
tempdir: Some(tempdir),
206246
addr,
207247
}
@@ -214,32 +254,20 @@ impl RedisServer {
214254
.arg(&path);
215255
RedisServer {
216256
process: spawner(&mut redis_cmd),
217-
stunnel_process: None,
218257
tempdir: Some(tempdir),
219258
addr,
220259
}
221260
}
222261
}
223262
}
224263

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-
232264
pub fn get_client_addr(&self) -> &redis::ConnectionAddr {
233265
&self.addr
234266
}
235267

236268
pub fn stop(&mut self) {
237269
let _ = self.process.kill();
238270
let _ = self.process.wait();
239-
if let Some(p) = self.stunnel_process.as_mut() {
240-
let _ = p.kill();
241-
let _ = p.wait();
242-
}
243271
if let redis::ConnectionAddr::Unix(ref path) = *self.get_client_addr() {
244272
fs::remove_file(&path).ok();
245273
}

0 commit comments

Comments
 (0)