Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support Multiple Key Types #901

Open
kevinmeziere opened this issue Feb 8, 2024 · 3 comments
Open

Support Multiple Key Types #901

kevinmeziere opened this issue Feb 8, 2024 · 3 comments

Comments

@kevinmeziere
Copy link

Currently Dropshot ConfigTls expects a key that matches Item::Pkcs8Key. Some certificate authorities do not provide a key pair that matches this.

A concrete example is using a key pair obtained from tailscale cert. Today the only key proved by tailscale is an EC key.

@davepacheco
Copy link
Collaborator

Thanks. In the latest release, I think you could use ConfigTls::Dynamic with your own rustls::ServerConfig to do this, right? (The fix in #902 looks simple enough, too.)

@kevinmeziere
Copy link
Author

Yea thats the idea, get the key/cert and create a Some ConfigTls::AsBytes. I didn't go the ConfigTls::Dynamic route as it looked like that was maybe looking for its own TLS handler... but I could misunderstanding the usage.

@davepacheco
Copy link
Collaborator

Dropshot always constructs a rustls::ServerConfig. When you use ConfigTls::Dynamic, we use the one the caller provides directly:

return Ok(raw.clone());

ConfigTls::AsBytes or ConfigTls::AsFile are just shortcuts for a common case. They boil down to:

ConfigTls::AsBytes { certs, key } => (
Box::new(std::io::BufReader::new(certs.as_slice())),
Box::new(std::io::BufReader::new(key.as_slice())),
),
ConfigTls::AsFile { cert_file, key_file } => {
let certfile = Box::new(std::io::BufReader::new(
std::fs::File::open(cert_file).map_err(|e| {
std::io::Error::new(
std::io::ErrorKind::Other,
format!(
"failed to open {}: {}",
cert_file.display(),
e
),
)
})?,
));
let keyfile = Box::new(std::io::BufReader::new(
std::fs::File::open(key_file).map_err(|e| {
std::io::Error::new(
std::io::ErrorKind::Other,
format!(
"failed to open {}: {}",
key_file.display(),
e
),
)
})?,
));
(certfile, keyfile)
}
};
let certs = rustls_pemfile::certs(&mut cert_reader)
.collect::<Result<Vec<_>, _>>()
.map_err(|err| {
io_error(format!("failed to load certificate: {err}"))
})?;
let keys = rustls_pemfile::pkcs8_private_keys(&mut key_reader)
.collect::<Result<Vec<_>, _>>()
.map_err(|err| {
io_error(format!("failed to load private key: {err}"))
})?;
let mut keys_iter = keys.into_iter();
let (Some(private_key), None) = (keys_iter.next(), keys_iter.next())
else {
return Err(io_error("expected a single private key".into()));
};
let mut cfg = rustls::ServerConfig::builder()
.with_no_client_auth()
.with_single_cert(certs, private_key.into())
.expect("bad certificate/key");
cfg.alpn_protocols = vec![b"h2".to_vec(), b"http/1.1".to_vec()];
Ok(cfg)

So if you need a workaround, you can make your own rustls::ServerConfig using similar code, modified in the way you did in #902 to accept the kind of key you need.

#902 still seems worth doing. I just wanted to let you know in case this unblocks you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants