mithril_aggregator/http_server/routes/
signatures_routes.rs1use warp::Filter;
2
3use crate::http_server::routes::router::RouterState;
4use crate::http_server::routes::{MAX_CONTENT_LENGTH, middlewares};
5
6pub fn routes(
7 router_state: &RouterState,
8) -> impl Filter<Extract = (impl warp::Reply + use<>,), Error = warp::Rejection> + Clone + use<> {
9 register_signatures(router_state)
10}
11
12fn register_signatures(
14 router_state: &RouterState,
15) -> impl Filter<Extract = (impl warp::Reply + use<>,), Error = warp::Rejection> + Clone + use<> {
16 warp::path!("register-signatures")
17 .and(warp::post())
18 .and(middlewares::json_with_max_length(MAX_CONTENT_LENGTH))
19 .and(middlewares::with_logger(router_state))
20 .and(middlewares::with_certifier_service(router_state))
21 .and(middlewares::with_single_signature_authenticator(
22 router_state,
23 ))
24 .and(middlewares::with_metrics_service(router_state))
25 .and_then(handlers::register_signatures)
26}
27
28mod handlers {
29 use slog::{Logger, debug, warn};
30 use std::convert::Infallible;
31 use std::sync::Arc;
32 use warp::http::StatusCode;
33
34 use mithril_common::messages::{RegisterSignatureMessageHttp, TryFromMessageAdapter};
35
36 use crate::{
37 MetricsService, SingleSignatureAuthenticator,
38 http_server::routes::reply,
39 message_adapters::FromRegisterSingleSignatureAdapter,
40 services::{CertifierService, CertifierServiceError, SignatureRegistrationStatus},
41 unwrap_to_internal_server_error,
42 };
43
44 const METRICS_HTTP_ORIGIN: &str = "HTTP";
45
46 pub async fn register_signatures(
48 message: RegisterSignatureMessageHttp,
49 logger: Logger,
50 certifier_service: Arc<dyn CertifierService>,
51 single_signer_authenticator: Arc<SingleSignatureAuthenticator>,
52 metrics_service: Arc<MetricsService>,
53 ) -> Result<impl warp::Reply, Infallible> {
54 debug!(logger, ">> register_signatures"; "payload" => ?message);
55
56 metrics_service
57 .get_signature_registration_total_received_since_startup()
58 .increment(&[METRICS_HTTP_ORIGIN]);
59
60 let payload = message.clone();
61 let signed_entity_type = message.signed_entity_type.clone();
62 let signed_message = message.signed_message.clone();
63
64 let mut single_signature = match FromRegisterSingleSignatureAdapter::try_adapt(message) {
65 Ok(signature) => signature,
66 Err(err) => {
67 warn!(logger,"register_signatures::payload decoding error"; "full_payload" => #?payload,"error" => ?err);
68
69 return Ok(reply::bad_request(
70 "Could not decode signature payload".to_string(),
71 err.to_string(),
72 ));
73 }
74 };
75
76 unwrap_to_internal_server_error!(
77 single_signer_authenticator
78 .authenticate(&mut single_signature, &signed_message)
79 .await,
80 logger => "single_signer_authenticator::error"
81 );
82
83 if !single_signature.is_authenticated() {
84 debug!(logger, "register_signatures::unauthenticated_signature");
85 return Ok(reply::bad_request(
86 "Could not authenticate signature".to_string(),
87 "Signature could not be authenticated".to_string(),
88 ));
89 }
90
91 match certifier_service
92 .register_single_signature(&signed_entity_type, &single_signature)
93 .await
94 {
95 Err(err) => match err.downcast_ref::<CertifierServiceError>() {
96 Some(CertifierServiceError::AlreadyCertified(signed_entity_type)) => {
97 debug!(logger, "register_signatures::open_message_already_certified"; "signed_entity_type" => ?signed_entity_type, "party_id" => &single_signature.party_id);
98 Ok(reply::gone(
99 "already_certified".to_string(),
100 err.to_string(),
101 ))
102 }
103 Some(CertifierServiceError::Expired(signed_entity_type)) => {
104 debug!(logger, "register_signatures::open_message_expired"; "signed_entity_type" => ?signed_entity_type, "party_id" => &single_signature.party_id);
105 Ok(reply::gone("expired".to_string(), err.to_string()))
106 }
107 Some(CertifierServiceError::NotFound(signed_entity_type)) => {
108 debug!(logger, "register_signatures::not_found"; "signed_entity_type" => ?signed_entity_type, "party_id" => &single_signature.party_id);
109 Ok(reply::empty(StatusCode::NOT_FOUND))
110 }
111 Some(_) | None => {
112 warn!(logger,"register_signatures::error"; "full_payload" => #?payload, "error" => ?err);
113 Ok(reply::server_error(err))
114 }
115 },
116 Ok(registration_status) => {
117 metrics_service
118 .get_signature_registration_total_successful_since_startup()
119 .increment(&[METRICS_HTTP_ORIGIN]);
120
121 match registration_status {
122 SignatureRegistrationStatus::Registered => {
123 Ok(reply::empty(StatusCode::CREATED))
124 }
125 SignatureRegistrationStatus::Buffered => Ok(reply::empty(StatusCode::ACCEPTED)),
126 }
127 }
128 }
129 }
130}
131
132#[cfg(test)]
133mod tests {
134 use anyhow::anyhow;
135 use mithril_common::entities::ClientError;
136 use std::sync::Arc;
137 use warp::http::{Method, StatusCode};
138 use warp::test::request;
139
140 use mithril_api_spec::APISpec;
141 use mithril_common::test::mock_extensions::MockBuilder;
142 use mithril_common::{
143 entities::SignedEntityType, messages::RegisterSignatureMessageHttp, test::double::Dummy,
144 };
145
146 use crate::{
147 SingleSignatureAuthenticator, initialize_dependencies,
148 services::{CertifierServiceError, MockCertifierService, SignatureRegistrationStatus},
149 };
150
151 use super::*;
152
153 fn setup_router(
154 state: RouterState,
155 ) -> impl Filter<Extract = (impl warp::Reply,), Error = warp::Rejection> + Clone {
156 let cors = warp::cors()
157 .allow_any_origin()
158 .allow_headers(vec!["content-type"])
159 .allow_methods(vec![Method::GET, Method::POST, Method::OPTIONS]);
160
161 warp::any().and(routes(&state).with(cors))
162 }
163
164 #[tokio::test]
165 async fn test_register_signatures_increments_signature_registration_total_received_and_successful_since_startup_metric_if_successful()
166 {
167 let method = Method::POST.as_str();
168 let path = "/register-signatures";
169 let dependency_manager = {
170 let mut deps = initialize_dependencies!().await;
171 deps.certifier_service = MockBuilder::<MockCertifierService>::configure(|mock| {
172 mock.expect_register_single_signature()
173 .returning(|_, _| Ok(SignatureRegistrationStatus::Registered));
174 });
175 deps.single_signer_authenticator =
176 Arc::new(SingleSignatureAuthenticator::new_that_authenticate_everything());
177 Arc::new(deps)
178 };
179 let initial_received_counter_value = dependency_manager
180 .metrics_service
181 .get_signature_registration_total_received_since_startup()
182 .get(&["HTTP"]);
183 let initial_successful_counter_value = dependency_manager
184 .metrics_service
185 .get_signature_registration_total_successful_since_startup()
186 .get(&["HTTP"]);
187
188 request()
189 .method(method)
190 .path(path)
191 .json(&RegisterSignatureMessageHttp::dummy())
192 .reply(&setup_router(RouterState::new_with_dummy_config(
193 dependency_manager.clone(),
194 )))
195 .await;
196
197 assert_eq!(
198 initial_received_counter_value + 1,
199 dependency_manager
200 .metrics_service
201 .get_signature_registration_total_received_since_startup()
202 .get(&["HTTP"])
203 );
204 assert_eq!(
205 initial_successful_counter_value + 1,
206 dependency_manager
207 .metrics_service
208 .get_signature_registration_total_successful_since_startup()
209 .get(&["HTTP"])
210 );
211 }
212
213 #[tokio::test]
214 async fn test_register_signatures_only_increments_signature_registration_total_received_since_startup_metric_if_failure()
215 {
216 let method = Method::POST.as_str();
217 let path = "/register-signatures";
218 let dependency_manager = {
219 let mut deps = initialize_dependencies!().await;
220 deps.single_signer_authenticator =
221 Arc::new(SingleSignatureAuthenticator::new_that_reject_everything());
222 Arc::new(deps)
223 };
224
225 let initial_received_counter_value = dependency_manager
226 .metrics_service
227 .get_signature_registration_total_received_since_startup()
228 .get(&["HTTP"]);
229 let initial_successful_counter_value = dependency_manager
230 .metrics_service
231 .get_signature_registration_total_successful_since_startup()
232 .get(&["HTTP"]);
233
234 request()
235 .method(method)
236 .path(path)
237 .json(&RegisterSignatureMessageHttp::dummy())
238 .reply(&setup_router(RouterState::new_with_dummy_config(
239 dependency_manager.clone(),
240 )))
241 .await;
242
243 assert_eq!(
244 initial_received_counter_value + 1,
245 dependency_manager
246 .metrics_service
247 .get_signature_registration_total_received_since_startup()
248 .get(&["HTTP"])
249 );
250 assert_eq!(
251 initial_successful_counter_value,
252 dependency_manager
253 .metrics_service
254 .get_signature_registration_total_successful_since_startup()
255 .get(&["HTTP"])
256 );
257 }
258
259 #[tokio::test]
260 async fn test_register_signatures_try_to_authenticate_signature_with_signed_message() {
261 let mut mock_certifier_service = MockCertifierService::new();
262 mock_certifier_service
263 .expect_register_single_signature()
264 .withf(|_, signature| signature.is_authenticated())
265 .once()
266 .return_once(move |_, _| Ok(SignatureRegistrationStatus::Registered));
267 let mut dependency_manager = initialize_dependencies!().await;
268 dependency_manager.certifier_service = Arc::new(mock_certifier_service);
269 dependency_manager.single_signer_authenticator =
270 Arc::new(SingleSignatureAuthenticator::new_that_authenticate_everything());
271
272 let message = RegisterSignatureMessageHttp {
273 signed_message: "message".to_string(),
274 ..RegisterSignatureMessageHttp::dummy()
275 };
276
277 let method = Method::POST.as_str();
278 let path = "/register-signatures";
279
280 request()
281 .method(method)
282 .path(path)
283 .json(&message)
284 .reply(&setup_router(RouterState::new_with_dummy_config(Arc::new(
285 dependency_manager,
286 ))))
287 .await;
288 }
289
290 #[tokio::test]
291 async fn test_register_signatures_return_400_if_authentication_fail() {
292 let mut mock_certifier_service = MockCertifierService::new();
293 mock_certifier_service.expect_register_single_signature().never();
294 let mut dependency_manager = initialize_dependencies!().await;
295 dependency_manager.certifier_service = Arc::new(mock_certifier_service);
296 dependency_manager.single_signer_authenticator =
297 Arc::new(SingleSignatureAuthenticator::new_that_reject_everything());
298
299 let message = RegisterSignatureMessageHttp {
300 signed_message: "message".to_string(),
301 ..RegisterSignatureMessageHttp::dummy()
302 };
303
304 let method = Method::POST.as_str();
305 let path = "/register-signatures";
306
307 let response = request()
308 .method(method)
309 .path(path)
310 .json(&message)
311 .reply(&setup_router(RouterState::new_with_dummy_config(Arc::new(
312 dependency_manager,
313 ))))
314 .await;
315
316 APISpec::verify_conformity(
317 APISpec::get_default_spec_file_from(crate::http_server::API_SPEC_LOCATION),
318 method,
319 path,
320 "application/json",
321 &message,
322 &response,
323 &StatusCode::BAD_REQUEST,
324 )
325 .unwrap();
326 }
327
328 #[tokio::test]
329 async fn test_register_signatures_post_ok_201() {
330 let mut mock_certifier_service = MockCertifierService::new();
331 mock_certifier_service
332 .expect_register_single_signature()
333 .return_once(move |_, _| Ok(SignatureRegistrationStatus::Registered));
334 let mut dependency_manager = initialize_dependencies!().await;
335 dependency_manager.certifier_service = Arc::new(mock_certifier_service);
336 dependency_manager.single_signer_authenticator =
337 Arc::new(SingleSignatureAuthenticator::new_that_authenticate_everything());
338
339 let message = RegisterSignatureMessageHttp::dummy();
340
341 let method = Method::POST.as_str();
342 let path = "/register-signatures";
343
344 let response = request()
345 .method(method)
346 .path(path)
347 .json(&message)
348 .reply(&setup_router(RouterState::new_with_dummy_config(Arc::new(
349 dependency_manager,
350 ))))
351 .await;
352
353 APISpec::verify_conformity(
354 APISpec::get_default_spec_file_from(crate::http_server::API_SPEC_LOCATION),
355 method,
356 path,
357 "application/json",
358 &message,
359 &response,
360 &StatusCode::CREATED,
361 )
362 .unwrap();
363 }
364
365 #[tokio::test]
366 async fn test_register_signatures_post_ok_202() {
367 let mut mock_certifier_service = MockCertifierService::new();
368 mock_certifier_service
369 .expect_register_single_signature()
370 .return_once(move |_, _| Ok(SignatureRegistrationStatus::Buffered));
371 let mut dependency_manager = initialize_dependencies!().await;
372 dependency_manager.certifier_service = Arc::new(mock_certifier_service);
373 dependency_manager.single_signer_authenticator =
374 Arc::new(SingleSignatureAuthenticator::new_that_authenticate_everything());
375
376 let message = RegisterSignatureMessageHttp::dummy();
377
378 let method = Method::POST.as_str();
379 let path = "/register-signatures";
380
381 let response = request()
382 .method(method)
383 .path(path)
384 .json(&message)
385 .reply(&setup_router(RouterState::new_with_dummy_config(Arc::new(
386 dependency_manager,
387 ))))
388 .await;
389
390 APISpec::verify_conformity(
391 APISpec::get_default_spec_file_from(crate::http_server::API_SPEC_LOCATION),
392 method,
393 path,
394 "application/json",
395 &message,
396 &response,
397 &StatusCode::ACCEPTED,
398 )
399 .unwrap();
400 }
401
402 #[tokio::test]
403 async fn test_register_signatures_post_ko_400() {
404 let mut mock_certifier_service = MockCertifierService::new();
405 mock_certifier_service
406 .expect_register_single_signature()
407 .return_once(move |_, _| Ok(SignatureRegistrationStatus::Registered));
408 let mut dependency_manager = initialize_dependencies!().await;
409 dependency_manager.certifier_service = Arc::new(mock_certifier_service);
410 dependency_manager.single_signer_authenticator =
411 Arc::new(SingleSignatureAuthenticator::new_that_authenticate_everything());
412
413 let mut message = RegisterSignatureMessageHttp::dummy();
414 message.signature = "invalid-signature".to_string();
415
416 let method = Method::POST.as_str();
417 let path = "/register-signatures";
418
419 let response = request()
420 .method(method)
421 .path(path)
422 .json(&message)
423 .reply(&setup_router(RouterState::new_with_dummy_config(Arc::new(
424 dependency_manager,
425 ))))
426 .await;
427
428 APISpec::verify_conformity(
429 APISpec::get_default_spec_file_from(crate::http_server::API_SPEC_LOCATION),
430 method,
431 path,
432 "application/json",
433 &message,
434 &response,
435 &StatusCode::BAD_REQUEST,
436 )
437 .unwrap();
438 }
439
440 #[tokio::test]
441 async fn test_register_signatures_post_ko_404() {
442 let signed_entity_type = SignedEntityType::dummy();
443 let message = RegisterSignatureMessageHttp::dummy();
444 let mut mock_certifier_service = MockCertifierService::new();
445 mock_certifier_service
446 .expect_register_single_signature()
447 .return_once(move |_, _| {
448 Err(CertifierServiceError::NotFound(signed_entity_type).into())
449 });
450 let mut dependency_manager = initialize_dependencies!().await;
451 dependency_manager.certifier_service = Arc::new(mock_certifier_service);
452 dependency_manager.single_signer_authenticator =
453 Arc::new(SingleSignatureAuthenticator::new_that_authenticate_everything());
454
455 let method = Method::POST.as_str();
456 let path = "/register-signatures";
457
458 let response = request()
459 .method(method)
460 .path(path)
461 .json(&message)
462 .reply(&setup_router(RouterState::new_with_dummy_config(Arc::new(
463 dependency_manager,
464 ))))
465 .await;
466
467 APISpec::verify_conformity(
468 APISpec::get_default_spec_file_from(crate::http_server::API_SPEC_LOCATION),
469 method,
470 path,
471 "application/json",
472 &message,
473 &response,
474 &StatusCode::NOT_FOUND,
475 )
476 .unwrap();
477 }
478
479 #[tokio::test]
480 async fn test_register_signatures_post_ko_410_when_already_certified() {
481 let signed_entity_type = SignedEntityType::dummy();
482 let message = RegisterSignatureMessageHttp::dummy();
483 let mut mock_certifier_service = MockCertifierService::new();
484 mock_certifier_service
485 .expect_register_single_signature()
486 .return_once(move |_, _| {
487 Err(CertifierServiceError::AlreadyCertified(signed_entity_type).into())
488 });
489 let mut dependency_manager = initialize_dependencies!().await;
490 dependency_manager.certifier_service = Arc::new(mock_certifier_service);
491 dependency_manager.single_signer_authenticator =
492 Arc::new(SingleSignatureAuthenticator::new_that_authenticate_everything());
493
494 let method = Method::POST.as_str();
495 let path = "/register-signatures";
496
497 let response = request()
498 .method(method)
499 .path(path)
500 .json(&message)
501 .reply(&setup_router(RouterState::new_with_dummy_config(Arc::new(
502 dependency_manager,
503 ))))
504 .await;
505
506 let response_body: ClientError = serde_json::from_slice(response.body()).unwrap();
507 assert_eq!(
508 response_body,
509 ClientError::new(
510 "already_certified",
511 CertifierServiceError::AlreadyCertified(SignedEntityType::dummy()).to_string()
512 )
513 );
514
515 APISpec::verify_conformity(
516 APISpec::get_default_spec_file_from(crate::http_server::API_SPEC_LOCATION),
517 method,
518 path,
519 "application/json",
520 &message,
521 &response,
522 &StatusCode::GONE,
523 )
524 .unwrap();
525 }
526
527 #[tokio::test]
528 async fn test_register_signatures_post_ko_410_when_expired() {
529 let message = RegisterSignatureMessageHttp::dummy();
530 let mut mock_certifier_service = MockCertifierService::new();
531 mock_certifier_service
532 .expect_register_single_signature()
533 .return_once(move |_, _| {
534 Err(CertifierServiceError::Expired(SignedEntityType::dummy()).into())
535 });
536 let mut dependency_manager = initialize_dependencies!().await;
537 dependency_manager.certifier_service = Arc::new(mock_certifier_service);
538 dependency_manager.single_signer_authenticator =
539 Arc::new(SingleSignatureAuthenticator::new_that_authenticate_everything());
540
541 let method = Method::POST.as_str();
542 let path = "/register-signatures";
543
544 let response = request()
545 .method(method)
546 .path(path)
547 .json(&message)
548 .reply(&setup_router(RouterState::new_with_dummy_config(Arc::new(
549 dependency_manager,
550 ))))
551 .await;
552
553 let response_body: ClientError = serde_json::from_slice(response.body()).unwrap();
554 assert_eq!(
555 response_body,
556 ClientError::new(
557 "expired",
558 CertifierServiceError::Expired(SignedEntityType::dummy()).to_string()
559 )
560 );
561
562 APISpec::verify_conformity(
563 APISpec::get_default_spec_file_from(crate::http_server::API_SPEC_LOCATION),
564 method,
565 path,
566 "application/json",
567 &message,
568 &response,
569 &StatusCode::GONE,
570 )
571 .unwrap();
572 }
573
574 #[tokio::test]
575 async fn test_register_signatures_post_ko_500() {
576 let mut mock_certifier_service = MockCertifierService::new();
577 mock_certifier_service
578 .expect_register_single_signature()
579 .return_once(move |_, _| Err(anyhow!("an error occurred")));
580 let mut dependency_manager = initialize_dependencies!().await;
581 dependency_manager.certifier_service = Arc::new(mock_certifier_service);
582 dependency_manager.single_signer_authenticator =
583 Arc::new(SingleSignatureAuthenticator::new_that_authenticate_everything());
584
585 let message = RegisterSignatureMessageHttp::dummy();
586
587 let method = Method::POST.as_str();
588 let path = "/register-signatures";
589
590 let response = request()
591 .method(method)
592 .path(path)
593 .json(&message)
594 .reply(&setup_router(RouterState::new_with_dummy_config(Arc::new(
595 dependency_manager,
596 ))))
597 .await;
598
599 APISpec::verify_conformity(
600 APISpec::get_default_spec_file_from(crate::http_server::API_SPEC_LOCATION),
601 method,
602 path,
603 "application/json",
604 &message,
605 &response,
606 &StatusCode::INTERNAL_SERVER_ERROR,
607 )
608 .unwrap();
609 }
610}