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