Skip to content

Commit 43b6a1c

Browse files
committed
update dependencies and apply security fixes
This replaces two security updates flagged by GitHub Dependabot: * #95 * #89 All dependencies were updated, including a significant Rama upgrade. The Rama update simplifies type erased error handling. OpaqueError is now intended only for edge cases where higher rank lifetime limitations require it. In most cases BoxError should be used, unless a strongly typed error is more appropriate. Error context traits now make it easy to attach structured fields to errors. This replaces manual string formatting and is both easier to use and lazier, as formatting is deferred until the error is actually displayed. This continues Rama’s incremental improvements driven by real world usage and feedback. Upcoming work includes a new Uri type and follow up improvements enabled by it.
1 parent 46f9cb5 commit 43b6a1c

File tree

28 files changed

+522
-371
lines changed

28 files changed

+522
-371
lines changed

Cargo.lock

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

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@ resolver = "3"
44

55
[workspace.dependencies.rama]
66
git = "https://github.com/plabayo/rama"
7-
rev = "a87a7f9ec68e76ef12156b6278b132f847f03d56"
7+
rev = "79f83e843cfb45060e30ac2af44f3f3db4970ce2"

proxy/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ serde_test = "1"
2525
radix_trie = "0.3"
2626
serde_json = "1"
2727
moka = "0.12"
28-
rand = "0.9"
28+
rand = "0.10"
2929
parking_lot = "0.12.5"
3030
serde_html_form = "0.4"
3131
rustls-platform-verifier = "0.6"

proxy/src/client/mock_client/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use std::sync::{Arc, LazyLock};
33
use rama::{
44
Layer as _, Service,
55
cli::service::echo::EchoServiceBuilder,
6-
error::OpaqueError,
6+
error::BoxError,
77
http::{
88
Request, Response,
99
matcher::HttpMatcher,
@@ -24,7 +24,7 @@ static ASSERT_ENDPOINT_STATE: LazyLock<assert_endpoint::MockState> =
2424
LazyLock::new(assert_endpoint::MockState::new);
2525

2626
pub fn new_mock_client()
27-
-> Result<impl Service<Request, Output = Response, Error = OpaqueError> + Clone, OpaqueError> {
27+
-> Result<impl Service<Request, Output = Response, Error = BoxError> + Clone, BoxError> {
2828
let echo_svc_builder = EchoServiceBuilder::default();
2929
let echo_svc = Arc::new(echo_svc_builder.build_http(Executor::default()));
3030
let not_found_svc = service_fn(move |req| {
@@ -52,6 +52,6 @@ pub fn new_mock_client()
5252
"Mock (web) client created: do not use in production, only meant for automated testing!"
5353
);
5454
Ok(Arc::new(
55-
MapErrLayer::new(OpaqueError::from_std).into_layer(mock_server),
55+
MapErrLayer::into_box_error().into_layer(mock_server),
5656
))
5757
}

proxy/src/client/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
#[cfg(not(test))]
1313
use rama::{
1414
Service,
15-
error::{ErrorContext as _, OpaqueError},
15+
error::{BoxError, ErrorContext as _},
1616
http::{Request, Response, Version, client::EasyHttpWebClient},
1717
rt::Executor,
1818
};
@@ -26,7 +26,7 @@ pub use self::mock_client::new_mock_client as new_web_client;
2626
/// Create a new web client that can be cloned and shared.
2727
#[cfg(not(test))]
2828
pub fn new_web_client()
29-
-> Result<impl Service<Request, Output = Response, Error = OpaqueError> + Clone, OpaqueError> {
29+
-> Result<impl Service<Request, Output = Response, Error = BoxError> + Clone, BoxError> {
3030
use rama::tls::rustls::dep::rustls::ClientConfig;
3131
use rustls_platform_verifier::ConfigVerifierExt;
3232

proxy/src/diagnostics/har.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use std::path::Path;
22
use std::sync::Arc;
33
use std::sync::atomic::AtomicBool;
44

5-
use rama::error::{ErrorContext, OpaqueError};
5+
use rama::error::{BoxError, ErrorContext};
66
use rama::graceful::ShutdownGuard;
77
use rama::http::layer::har;
88
use rama::http::layer::har::recorder::FileRecorder;
@@ -18,7 +18,7 @@ pub struct HarClient {
1818

1919
impl HarClient {
2020
/// Toggles the har recording status and returns previous state of toggle.
21-
pub async fn toggle(&self) -> Result<bool, OpaqueError> {
21+
pub async fn toggle(&self) -> Result<bool, BoxError> {
2222
let previous = self.toggle_state.load(std::sync::atomic::Ordering::Relaxed);
2323
self.toggle_tx
2424
.send(())

proxy/src/firewall/layer/evaluate_req.rs

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use rama::{
22
Layer, Service,
3-
error::{BoxError, OpaqueError},
3+
error::{BoxError, ErrorContext},
44
http::{Request, Response},
55
telemetry::tracing,
66
};
@@ -22,15 +22,11 @@ where
2222
S: Service<Request, Output = Response, Error: Into<BoxError>>,
2323
{
2424
type Output = Response;
25-
type Error = OpaqueError;
25+
type Error = BoxError;
2626

2727
async fn serve(&self, req: Request) -> Result<Self::Output, Self::Error> {
2828
match self.firewall.evaluate_request(req).await? {
29-
RequestAction::Allow(req) => self
30-
.inner
31-
.serve(req)
32-
.await
33-
.map_err(|err| OpaqueError::from_boxed(err.into())),
29+
RequestAction::Allow(req) => self.inner.serve(req).await.into_box_error(),
3430
RequestAction::Block(blocked) => {
3531
tracing::trace!(
3632
"EvaluateRequestService: firewall blocked request with self-generated response"

proxy/src/firewall/layer/evaluate_resp.rs

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use rama::{
22
Layer, Service,
3-
error::{BoxError, OpaqueError},
3+
error::{BoxError, ErrorContext},
44
http::{Request, Response},
55
telemetry::tracing,
66
};
@@ -22,14 +22,10 @@ where
2222
S: Service<Request, Output = Response, Error: Into<BoxError>>,
2323
{
2424
type Output = Response;
25-
type Error = OpaqueError;
25+
type Error = BoxError;
2626

2727
async fn serve(&self, req: Request) -> Result<Self::Output, Self::Error> {
28-
let resp = self
29-
.inner
30-
.serve(req)
31-
.await
32-
.map_err(|err| OpaqueError::from_boxed(err.into()))?;
28+
let resp = self.inner.serve(req).await.into_box_error()?;
3329

3430
tracing::trace!("EvaluateResponseService: evaluating response");
3531
self.firewall.evaluate_response(resp).await

proxy/src/firewall/malware_list.rs

Lines changed: 21 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use std::{fmt, sync::Arc, time::Duration};
22

33
use rama::{
44
Service,
5-
error::{ErrorContext, OpaqueError},
5+
error::{BoxError, ErrorContext},
66
graceful::ShutdownGuard,
77
http::{
88
BodyExtractExt, Request, Response, StatusCode, Uri, service::client::HttpClientExt as _,
@@ -13,7 +13,7 @@ use rama::{
1313

1414
use arc_swap::{ArcSwap, Guard};
1515
use radix_trie::Trie;
16-
use rand::Rng;
16+
use rand::RngExt as _;
1717
use serde::{Deserialize, Serialize};
1818
use tokio::time::Instant;
1919

@@ -55,9 +55,9 @@ impl RemoteMalwareList {
5555
sync_storage: SyncCompactDataStorage,
5656
client: C,
5757
formatter: Option<EntryFormatter>,
58-
) -> Result<Self, OpaqueError>
58+
) -> Result<Self, BoxError>
5959
where
60-
C: Service<Request, Output = Response, Error = OpaqueError>,
60+
C: Service<Request, Output = Response, Error = BoxError>,
6161
{
6262
let entry_formatter = formatter.unwrap_or_else(|| Arc::new(IdentityEntryFormatter));
6363

@@ -132,12 +132,12 @@ struct RemoteMalwareListClient<C> {
132132

133133
impl<C> RemoteMalwareListClient<C>
134134
where
135-
C: Service<Request, Output = Response, Error = OpaqueError>,
135+
C: Service<Request, Output = Response, Error = BoxError>,
136136
{
137137
async fn download_malware_trie(
138138
&self,
139139
e_tag: Option<&str>,
140-
) -> Result<Option<(MalwareTrie, Option<ArcStr>)>, OpaqueError> {
140+
) -> Result<Option<(MalwareTrie, Option<ArcStr>)>, BoxError> {
141141
let Some((malware_list, new_e_tag)) =
142142
self.fetch_remote_malware_list_and_e_tag(e_tag).await?
143143
else {
@@ -159,7 +159,7 @@ where
159159
async fn fetch_remote_malware_list_and_e_tag(
160160
&self,
161161
previous_e_tag: Option<&str>,
162-
) -> Result<Option<(Vec<ListDataEntry>, Option<ArcStr>)>, OpaqueError> {
162+
) -> Result<Option<(Vec<ListDataEntry>, Option<ArcStr>)>, BoxError> {
163163
let start = Instant::now();
164164

165165
let req_builder = self.client.get(self.uri.clone());
@@ -170,13 +170,12 @@ where
170170
req_builder
171171
};
172172

173-
let resp = req_builder.send().await.with_context(|| {
174-
format!(
175-
"fetch malware list from remote endpoint '{}'; (tt: {:?})",
176-
self.uri,
177-
start.elapsed()
178-
)
179-
})?;
173+
let resp = req_builder
174+
.send()
175+
.await
176+
.context("fetch malware list from remote endpoint")
177+
.context_debug_field("tt", start.elapsed())
178+
.with_context_field("uri", || self.uri.clone())?;
180179

181180
if resp.status() == StatusCode::NOT_MODIFIED {
182181
tracing::debug!(
@@ -195,13 +194,9 @@ where
195194
let malware_list: Vec<ListDataEntry> = resp
196195
.try_into_json()
197196
.await
198-
.with_context(|| {
199-
format!(
200-
"collect and json-decode malware list response payload from remote endpoint '{}'; (tt: {:?})",
201-
self.uri,
202-
start.elapsed(),
203-
)
204-
})?;
197+
.context("collect and json-decode malware list response payload from remote endpoint")
198+
.with_context_field("uri", || self.uri.clone())
199+
.with_context_debug_field("tt", || start.elapsed())?;
205200

206201
tracing::debug!(
207202
"fetched and decoded and new malware list from remote endpoint '{}', with {} entries (tt: {:?})",
@@ -239,34 +234,24 @@ where
239234

240235
async fn load_cached_malware_trie(
241236
&self,
242-
) -> Result<Option<(MalwareTrie, Option<ArcStr>)>, OpaqueError> {
237+
) -> Result<Option<(MalwareTrie, Option<ArcStr>)>, BoxError> {
243238
tokio::task::spawn_blocking({
244239
let storage = self.sync_storage.clone();
245240
let filename = self.filename.clone();
246241
let formatter = self.formatter.clone();
247242
move || load_cached_malware_trie_sync_inner(storage, filename, formatter.as_ref())
248243
})
249244
.await
250-
.with_context(|| {
251-
format!(
252-
"wait for blocking task to use cached malware list for creating new remote malware list (failure endpoint: {})",
253-
self.uri
254-
)
255-
})?
256-
.with_context(|| {
257-
format!(
258-
"try to use cached malware list for creating new remote malware list (failure endpoint: {})",
259-
self.uri
260-
)
261-
})
245+
.context("wait for blocking task to use cached malware list for creating new remote malware list")
246+
.with_context_field("uri", || self.uri.clone())?
262247
}
263248
}
264249

265250
fn load_cached_malware_trie_sync_inner(
266251
storage: SyncCompactDataStorage,
267252
filename: ArcStr,
268253
formatter: &dyn MalwareListEntryFormatter,
269-
) -> Result<Option<(MalwareTrie, Option<ArcStr>)>, OpaqueError> {
254+
) -> Result<Option<(MalwareTrie, Option<ArcStr>)>, BoxError> {
270255
let cached_malware_trie: Option<CachedMalwareTrie> =
271256
storage.load(&filename).context("storage failure")?;
272257

@@ -285,7 +270,7 @@ async fn remote_list_update_loop<C>(
285270
e_tag: Option<ArcStr>,
286271
shared_malware_trie: Arc<ArcSwap<MalwareTrie>>,
287272
) where
288-
C: Service<Request, Output = Response, Error = OpaqueError>,
273+
C: Service<Request, Output = Response, Error = BoxError>,
289274
{
290275
tracing::debug!(
291276
"remote malware list (uri = {}), update loop task up and running",

proxy/src/firewall/mod.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@ use std::{sync::Arc, time::Duration};
22

33
use rama::{
44
Layer as _, Service as _,
5-
error::{ErrorContext as _, OpaqueError},
5+
error::{BoxError, ErrorContext as _},
66
graceful::ShutdownGuard,
77
http::{
8-
Body, HeaderValue, Request, Response,
8+
HeaderValue, Request, Response,
99
header::CONTENT_TYPE,
1010
layer::{
1111
decompression::DecompressionLayer,
@@ -52,13 +52,13 @@ impl Firewall {
5252
guard: ShutdownGuard,
5353
data: SyncCompactDataStorage,
5454
reporting_endpoint: Option<rama::http::Uri>,
55-
) -> Result<Self, OpaqueError> {
55+
) -> Result<Self, BoxError> {
5656
let inner_https_client = crate::client::new_web_client()?;
5757

5858
let shared_remote_malware_client = (
59-
MapResponseBodyLayer::new(Body::new),
59+
MapResponseBodyLayer::new_boxed_streaming_body(),
6060
DecompressionLayer::new(),
61-
MapErrLayer::new(OpaqueError::from_std),
61+
MapErrLayer::into_box_error(),
6262
TimeoutLayer::new(Duration::from_secs(60)), // NOTE: if you have slow servers this might need to be more
6363
RetryLayer::new(
6464
ManagedPolicy::default().with_backoff(
@@ -74,7 +74,7 @@ impl Firewall {
7474
AddRequiredRequestHeadersLayer::new().with_user_agent_header_value(
7575
HeaderValue::from_static(network_service_identifier()),
7676
),
77-
MapRequestBodyLayer::new(Body::new),
77+
MapRequestBodyLayer::new_boxed_streaming_body(),
7878
)
7979
.into_layer(inner_https_client)
8080
.boxed();
@@ -153,7 +153,7 @@ impl Firewall {
153153
self::layer::evaluate_resp::EvaluateResponseLayer(self)
154154
}
155155

156-
async fn evaluate_request(&self, req: Request) -> Result<RequestAction, OpaqueError> {
156+
async fn evaluate_request(&self, req: Request) -> Result<RequestAction, BoxError> {
157157
let mut mod_req = req;
158158

159159
for rule in self.block_rules.iter() {
@@ -169,7 +169,7 @@ impl Firewall {
169169
Ok(RequestAction::Allow(mod_req))
170170
}
171171

172-
async fn evaluate_response(&self, resp: Response) -> Result<Response, OpaqueError> {
172+
async fn evaluate_response(&self, resp: Response) -> Result<Response, BoxError> {
173173
let mut mod_resp = resp;
174174

175175
// Iterate rules in reverse order for symmetry with request evaluation

0 commit comments

Comments
 (0)