Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions crates/signer/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ publish = false

[dependencies]
cb-common.workspace = true
cb-metrics.workspace = true

# ethereum
alloy.workspace = true
Expand All @@ -21,6 +22,7 @@ tokio.workspace = true

# telemetry
tracing.workspace = true
prometheus.workspace = true

# crypto
blst.workspace = true
Expand Down
3 changes: 3 additions & 0 deletions crates/signer/src/constants.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pub const GET_PUBKEYS_ENDPOINT_TAG: &str = "get_pubkeys";
pub const GENERATE_PROXY_KEY_ENDPOINT_TAG: &str = "generate_proxy_key";
pub const REQUEST_SIGNATURE_ENDPOINT_TAG: &str = "request_signature";
2 changes: 2 additions & 0 deletions crates/signer/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
mod constants;
pub mod error;
pub mod manager;
mod metrics;
pub mod service;
34 changes: 34 additions & 0 deletions crates/signer/src/metrics.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
//! Metrics for PBS module
use axum::http::Uri;
use cb_common::commit::constants::{
GENERATE_PROXY_KEY_PATH, GET_PUBKEYS_PATH, REQUEST_SIGNATURE_PATH,
};
use lazy_static::lazy_static;
use prometheus::{register_int_counter_vec_with_registry, IntCounterVec, Registry};

use crate::constants::{
GENERATE_PROXY_KEY_ENDPOINT_TAG, GET_PUBKEYS_ENDPOINT_TAG, REQUEST_SIGNATURE_ENDPOINT_TAG,
};

lazy_static! {
pub static ref SIGNER_METRICS_REGISTRY: Registry =
Registry::new_custom(Some("cb_signer".to_string()), None).unwrap();

/// Status code returned by endpoint
pub static ref SIGNER_STATUS: IntCounterVec = register_int_counter_vec_with_registry!(
"signer_status_code_total",
"HTTP status code returned by signer",
&["http_status_code", "endpoint"],
SIGNER_METRICS_REGISTRY
).unwrap();
}

pub fn uri_to_tag(uri: &Uri) -> &str {
match uri.path() {
GET_PUBKEYS_PATH => GET_PUBKEYS_ENDPOINT_TAG,
GENERATE_PROXY_KEY_PATH => GENERATE_PROXY_KEY_ENDPOINT_TAG,
REQUEST_SIGNATURE_PATH => REQUEST_SIGNATURE_ENDPOINT_TAG,
_ => "unknown endpoint",
}
}
27 changes: 25 additions & 2 deletions crates/signer/src/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,19 @@ use cb_common::{
constants::COMMIT_BOOST_VERSION,
types::{Jwt, ModuleId},
};
use cb_metrics::provider::MetricsProvider;
use eyre::{Context, Result};
use headers::{authorization::Bearer, Authorization};
use prometheus::core::Collector;
use tokio::{net::TcpListener, sync::RwLock};
use tracing::{debug, error, info, warn};
use uuid::Uuid;

use crate::{error::SignerModuleError, manager::SigningManager};
use crate::{
error::SignerModuleError,
manager::SigningManager,
metrics::{uri_to_tag, SIGNER_METRICS_REGISTRY, SIGNER_STATUS},
};

/// Implements the Signer API and provides a service for signing requests
pub struct SigningService;
Expand Down Expand Up @@ -70,19 +76,29 @@ impl SigningService {
info!(version = COMMIT_BOOST_VERSION, modules =? module_ids, port =? config.server_port, loaded_consensus, loaded_proxies, "Starting signing service");

let state = SigningState { manager: RwLock::new(manager).into(), jwts: config.jwts.into() };
SigningService::init_metrics()?;

let app = axum::Router::new()
.route(REQUEST_SIGNATURE_PATH, post(handle_request_signature))
.route(GET_PUBKEYS_PATH, get(handle_get_pubkeys))
.route(GENERATE_PROXY_KEY_PATH, post(handle_generate_proxy))
.with_state(state.clone())
.route_layer(middleware::from_fn_with_state(state.clone(), jwt_auth));
.route_layer(middleware::from_fn_with_state(state.clone(), jwt_auth))
.route_layer(middleware::from_fn(log_request));

let address = SocketAddr::from(([0, 0, 0, 0], config.server_port));
let listener = TcpListener::bind(address).await?;

axum::serve(listener, app).await.wrap_err("signer server exited")
}

pub fn register_metric(c: Box<dyn Collector>) {
SIGNER_METRICS_REGISTRY.register(c).expect("failed to register metric");
}

pub fn init_metrics() -> Result<()> {
MetricsProvider::load_and_run(SIGNER_METRICS_REGISTRY.clone())
}
}

/// Authentication middleware layer
Expand All @@ -104,6 +120,13 @@ async fn jwt_auth(
Ok(next.run(req).await)
}

async fn log_request(req: Request, next: Next) -> Result<Response, SignerModuleError> {
let url = &req.uri().clone();
let response = next.run(req).await;
SIGNER_STATUS.with_label_values(&[response.status().as_str(), uri_to_tag(url)]).inc();
Ok(response)
}

/// Implements get_pubkeys from the Signer API
async fn handle_get_pubkeys(
Extension(module_id): Extension<ModuleId>,
Expand Down
Loading
Loading