Skip to content

Commit c73de14

Browse files
committed
kms: add prometheus metrics endpoint
1 parent 5e4ec90 commit c73de14

2 files changed

Lines changed: 79 additions & 4 deletions

File tree

kms/src/main.rs

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ use ra_rpc::rocket_helper::QuoteVerifier;
1010
use rocket::{
1111
fairing::AdHoc,
1212
figment::{providers::Serialized, Figment},
13-
response::content::RawHtml,
14-
Shutdown,
13+
response::content::{RawHtml, RawText},
14+
Shutdown, State,
1515
};
1616
use tracing::{info, warn};
1717

@@ -77,6 +77,34 @@ async fn run_onboard_service(kms_config: KmsConfig, figment: Figment) -> Result<
7777
Ok(())
7878
}
7979

80+
#[rocket::get("/metrics")]
81+
fn metrics(state: &State<KmsState>) -> RawText<String> {
82+
RawText(state.metrics().render_prometheus())
83+
}
84+
85+
// Count only RPCs whose primary job is to verify caller/app attestation.
86+
// Recording in a response fairing also catches failures that happen before
87+
// RpcHandler is constructed, such as malformed RA-TLS attestation.
88+
fn is_attestation_rpc_path(path: &str) -> bool {
89+
let Some(method) = path.strip_prefix("/prpc/") else {
90+
return false;
91+
};
92+
let method = method.trim_start_matches("KMS.");
93+
matches!(method, "GetAppKey" | "GetKmsKey" | "SignCert")
94+
}
95+
96+
fn record_attestation_metrics(req: &rocket::Request<'_>, res: &rocket::Response<'_>) {
97+
if !is_attestation_rpc_path(req.uri().path().as_str()) {
98+
return;
99+
}
100+
let Some(state) = req.rocket().state::<KmsState>() else {
101+
return;
102+
};
103+
state
104+
.metrics()
105+
.record_attestation_request(res.status().code >= 400);
106+
}
107+
80108
#[rocket::main]
81109
async fn main() -> Result<()> {
82110
{
@@ -119,10 +147,15 @@ async fn main() -> Result<()> {
119147
res.set_raw_header("X-App-Version", app_version());
120148
})
121149
}))
150+
.attach(AdHoc::on_response(
151+
"Record KMS attestation metrics",
152+
|req, res| Box::pin(async move { record_attestation_metrics(req, res) }),
153+
))
122154
.mount(
123155
"/prpc",
124156
ra_rpc::prpc_routes!(KmsState, RpcHandler, trim: "KMS."),
125157
)
158+
.mount("/", rocket::routes![metrics])
126159
.manage(state);
127160

128161
let verifier = QuoteVerifier::new(pccs_url);

kms/src/main_service.rs

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@
44

55
use std::{
66
path::{Path, PathBuf},
7-
sync::Arc,
7+
sync::{
8+
atomic::{AtomicU64, Ordering},
9+
Arc,
10+
},
811
};
912

1013
use anyhow::{bail, Context, Result};
@@ -57,6 +60,38 @@ pub struct KmsStateInner {
5760
temp_ca_key: String,
5861
verifier: CvmVerifier,
5962
self_boot_info: OnceCell<BootInfo>,
63+
metrics: KmsMetrics,
64+
}
65+
66+
#[derive(Default)]
67+
pub(crate) struct KmsMetrics {
68+
attestation_requests_total: AtomicU64,
69+
attestation_failures_total: AtomicU64,
70+
}
71+
72+
impl KmsMetrics {
73+
pub(crate) fn record_attestation_request(&self, failed: bool) {
74+
self.attestation_requests_total
75+
.fetch_add(1, Ordering::Relaxed);
76+
if failed {
77+
self.attestation_failures_total
78+
.fetch_add(1, Ordering::Relaxed);
79+
}
80+
}
81+
82+
pub(crate) fn render_prometheus(&self) -> String {
83+
let attestation_requests_total = self.attestation_requests_total.load(Ordering::Relaxed);
84+
let attestation_failures_total = self.attestation_failures_total.load(Ordering::Relaxed);
85+
86+
format!(
87+
"# HELP dstack_kms_attestation_requests_total Total number of KMS attestation requests.\n\
88+
# TYPE dstack_kms_attestation_requests_total counter\n\
89+
dstack_kms_attestation_requests_total {attestation_requests_total}\n\
90+
# HELP dstack_kms_attestation_failures_total Total number of failed KMS attestation requests.\n\
91+
# TYPE dstack_kms_attestation_failures_total counter\n\
92+
dstack_kms_attestation_failures_total {attestation_failures_total}\n"
93+
)
94+
}
6095
}
6196

6297
impl KmsState {
@@ -77,7 +112,9 @@ impl KmsState {
77112
config.pccs_url.clone(),
78113
);
79114
if !config.enforce_self_authorization {
80-
warn!("self-authorization is disabled; trusted RPCs will not be gated by KMS self-attestation - do not use in production TEE deployments");
115+
warn!(
116+
"self-authorization is disabled; trusted RPCs will not be gated by KMS self-attestation - do not use in production TEE deployments"
117+
);
81118
}
82119
Ok(Self {
83120
inner: Arc::new(KmsStateInner {
@@ -88,9 +125,14 @@ impl KmsState {
88125
temp_ca_key,
89126
verifier,
90127
self_boot_info: OnceCell::new(),
128+
metrics: KmsMetrics::default(),
91129
}),
92130
})
93131
}
132+
133+
pub(crate) fn metrics(&self) -> &KmsMetrics {
134+
&self.inner.metrics
135+
}
94136
}
95137

96138
pub struct RpcHandler {

0 commit comments

Comments
 (0)