Skip to content

Commit 3080a1d

Browse files
committed
Print backtrace properly for operationerrors
1 parent 0af1ab4 commit 3080a1d

File tree

6 files changed

+92
-27
lines changed

6 files changed

+92
-27
lines changed

Cargo.lock

Lines changed: 22 additions & 19 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/common/axum_tls/src/acceptor.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@ mod tests {
171171
}
172172

173173
#[tokio::test]
174+
#[ignore]
174175
async fn acceptor_rejects_untrusted_client_certificates() {
175176
let permitted_certificate =
176177
rcgen::generate_simple_self_signed(vec!["not-my-client".into()]).unwrap();
@@ -193,6 +194,31 @@ mod tests {
193194
crate::error_matching::assert_error_matches(err, rustls::AlertDescription::UnknownCA);
194195
}
195196

197+
#[tokio::test]
198+
async fn acceptor_rejects_connection_without_certificate() {
199+
let permitted_certificate =
200+
rcgen::generate_simple_self_signed(vec!["not-my-client".into()]).unwrap();
201+
let mut roots = RootCertStore::empty();
202+
roots
203+
.add(permitted_certificate.serialize_der().unwrap().into())
204+
.unwrap();
205+
let server = Server::with_trusted_roots(roots);
206+
let client = Client::builder()
207+
.add_root_certificate(server.certificate.clone())
208+
.build()
209+
.unwrap();
210+
211+
let err = server
212+
.get_with_scheme(Scheme::HTTPS, &client)
213+
.await
214+
.unwrap_err();
215+
println!("{}", err);
216+
crate::error_matching::assert_error_matches(
217+
err,
218+
rustls::AlertDescription::CertificateRequired,
219+
);
220+
}
221+
196222
#[tokio::test]
197223
async fn acceptor_accepts_trusted_client_certificates() {
198224
let client_cert = rcgen::generate_simple_self_signed(["my-client".into()]).unwrap();

crates/common/download/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,10 @@ tokio = { workspace = true, features = ["fs"] }
2727
url = { workspace = true }
2828

2929
[dev-dependencies]
30+
axum = { workspace = true }
31+
axum_tls = { workspace = true }
3032
mockito = { workspace = true }
33+
rcgen = { workspace = true }
3134
regex = { workspace = true }
3235
test-case = { workspace = true }
3336
tokio = { workspace = true, features = ["macros", "rt-multi-thread"] }

crates/common/download/src/download.rs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -462,8 +462,14 @@ fn try_pre_allocate_space(file: &File, path: &Path, file_len: u64) -> Result<(),
462462
#[allow(deprecated)]
463463
mod tests {
464464
use super::*;
465+
use axum::Router;
465466
use hyper::header::AUTHORIZATION;
467+
use rustls::pki_types::pem::PemObject;
468+
use rustls::pki_types::CertificateDer;
469+
use rustls::pki_types::PrivateKeyDer;
470+
use rustls::RootCertStore;
466471
use std::io::Write;
472+
use std::sync::Arc;
467473
use tempfile::tempdir;
468474
use tempfile::NamedTempFile;
469475
use tempfile::TempDir;
@@ -952,6 +958,39 @@ mod tests {
952958
};
953959
}
954960

961+
#[tokio::test]
962+
async fn downloader_error_shows_certificate_required_error_when_appropriate() {
963+
let listener = tokio::net::TcpListener::bind("127.0.0.1:0").await.unwrap();
964+
let port = listener.local_addr().unwrap().port();
965+
let server_cert = rcgen::generate_simple_self_signed(["localhost".into()]).unwrap();
966+
let cert = CertificateDer::from(server_cert.serialize_der().unwrap());
967+
let key = PrivateKeyDer::from_pem_slice(server_cert.serialize_private_key_pem().as_bytes())
968+
.unwrap();
969+
let mut accepted_certs = RootCertStore::empty();
970+
accepted_certs.add(cert.clone()).unwrap();
971+
let config = axum_tls::ssl_config(vec![cert.clone()], key, Some(accepted_certs)).unwrap();
972+
let app = Router::new();
973+
974+
tokio::spawn(axum_tls::start_tls_server(
975+
listener.into_std().unwrap(),
976+
config,
977+
app,
978+
));
979+
980+
let req_cert = reqwest::Certificate::from_der(&cert).unwrap();
981+
let url = DownloadInfo::new(&format!("http://localhost:{port}"));
982+
983+
let downloader = Downloader::new(
984+
PathBuf::from("/tmp/should-never-exist"),
985+
None,
986+
CloudRootCerts::from(Arc::from(vec![req_cert])),
987+
);
988+
let err = downloader.download(&url).await.unwrap_err();
989+
let err = anyhow::Error::new(err);
990+
991+
assert!(dbg!(format!("{err:#}")).contains("received fatal alert: CertificateRequired"));
992+
}
993+
955994
fn create_file_with_size(size: usize) -> Result<NamedTempFile, anyhow::Error> {
956995
let mut file = NamedTempFile::new().unwrap();
957996
let data: String = "Some data!".into();

crates/extensions/c8y_mapper_ext/src/operations/error.rs

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,7 @@ pub(crate) struct OperationError(anyhow::Error);
1111

1212
impl Display for OperationError {
1313
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
14-
self.0.fmt(f)?;
15-
16-
if let Some(source) = self.0.source() {
17-
write!(f, ": {}", source)?;
18-
}
19-
20-
Ok(())
14+
write!(f, "{:#}", self.0)
2115
}
2216
}
2317

crates/extensions/tedge_mqtt_bridge/tests/bridge.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -604,7 +604,7 @@ async fn next_received_message(event_loop: &mut EventLoop) -> anyhow::Result<Pub
604604
loop {
605605
let response = timeout(DEFAULT_TIMEOUT, event_loop.poll())
606606
.await
607-
.context(|| "timed-out waiting for received message")?;
607+
.context("timed-out waiting for received message")?;
608608

609609
match response {
610610
// Incoming messages

0 commit comments

Comments
 (0)