From d8f531717a3faec40a9b4770bfa96aae8b2fc035 Mon Sep 17 00:00:00 2001 From: Benjamin Naecker Date: Wed, 9 Jul 2025 12:45:37 -0700 Subject: [PATCH] Add auth{n,z} USDT probes to Nexus Partial fix for #8424 --- Cargo.lock | 1 + nexus/auth/Cargo.toml | 1 + nexus/auth/src/authn/external/mod.rs | 11 +++++++++++ nexus/auth/src/context.rs | 11 +++++++++++ nexus/auth/src/lib.rs | 28 +++++++++++++++++++++++++++ tools/dtrace/nexus/trace-authn.d | 29 ++++++++++++++++++++++++++++ tools/dtrace/nexus/trace-authz.d | 29 ++++++++++++++++++++++++++++ 7 files changed, 110 insertions(+) create mode 100755 tools/dtrace/nexus/trace-authn.d create mode 100755 tools/dtrace/nexus/trace-authz.d diff --git a/Cargo.lock b/Cargo.lock index f28c5c6bfe0..761185f7726 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6101,6 +6101,7 @@ dependencies = [ "strum", "thiserror 2.0.12", "tokio", + "usdt", "uuid", ] diff --git a/nexus/auth/Cargo.toml b/nexus/auth/Cargo.toml index 71e16eafbef..ceef298ae9c 100644 --- a/nexus/auth/Cargo.toml +++ b/nexus/auth/Cargo.toml @@ -33,6 +33,7 @@ slog.workspace = true strum.workspace = true thiserror.workspace = true tokio = { workspace = true, features = ["full"] } +usdt.workspace = true uuid.workspace = true authz-macros.workspace = true diff --git a/nexus/auth/src/authn/external/mod.rs b/nexus/auth/src/authn/external/mod.rs index 2f09e73f790..16dbd419691 100644 --- a/nexus/auth/src/authn/external/mod.rs +++ b/nexus/auth/src/authn/external/mod.rs @@ -7,6 +7,7 @@ use super::Details; use super::SiloAuthnPolicy; use crate::authn; +use crate::probes; use async_trait::async_trait; use authn::Reason; use slog::trace; @@ -72,8 +73,18 @@ where for scheme_impl in &self.allowed_schemes { let scheme_name = scheme_impl.name(); trace!(log, "authn: trying {:?}", scheme_name); + let id = usdt::UniqueId::new(); + probes::authn__start!(|| { + ( + &id, + scheme_name.to_string(), + request.method().to_string(), + request.uri().to_string(), + ) + }); schemes_tried.push(scheme_name); let result = scheme_impl.authn(ctx, log, request).await; + probes::authn__done!(|| (id, format!("{result:?}"))); match result { // TODO-security If the user explicitly failed one // authentication scheme (i.e., a signature that didn't match, diff --git a/nexus/auth/src/context.rs b/nexus/auth/src/context.rs index 5aab22b762e..8066b4a0f0b 100644 --- a/nexus/auth/src/context.rs +++ b/nexus/auth/src/context.rs @@ -8,6 +8,7 @@ use super::authz; use crate::authn::ConsoleSessionWithSiloId; use crate::authn::external::session_cookie::Session; use crate::authz::AuthorizedResource; +use crate::probes; use crate::storage::Storage; use chrono::{DateTime, Utc}; use omicron_common::api::external::Error; @@ -275,7 +276,17 @@ impl OpContext { "action" => ?action, "resource" => ?*resource ); + let id = usdt::UniqueId::new(); + probes::authz__start!(|| { + ( + &id, + format!("{:?}", self.authn.actor()), + format!("{action:?}"), + format!("{resource:?}"), + ) + }); let result = self.authz.authorize(self, action, resource.clone()).await; + probes::authz__done!(|| (&id, format!("{result:?}"))); debug!(self.log, "authorize result"; "actor" => ?self.authn.actor(), "action" => ?action, diff --git a/nexus/auth/src/lib.rs b/nexus/auth/src/lib.rs index 0f0b9064b23..051c1cc86c6 100644 --- a/nexus/auth/src/lib.rs +++ b/nexus/auth/src/lib.rs @@ -9,3 +9,31 @@ extern crate newtype_derive; #[allow(unused_imports)] #[macro_use] extern crate slog; + +#[usdt::provider(provider = "nexus")] +mod probes { + /// Fires just before attempting to authenticate a request using the given + /// scheme. + fn authn__start( + id: &usdt::UniqueId, + scheme: &str, + method: &str, + uri: &str, + ) { + } + + /// Fires just after completing the authentication, with the result. + fn authn__done(id: &usdt::UniqueId, result: &str) {} + + /// Fires just before attempting to authorize an action on a resource. + fn authz__start( + id: &usdt::UniqueId, + actor: &str, + action: &str, + resource: &str, + ) { + } + + /// Fires just after completing an authorization check on a resource. + fn authz__done(id: &usdt::UniqueId, result: &str) {} +} diff --git a/tools/dtrace/nexus/trace-authn.d b/tools/dtrace/nexus/trace-authn.d new file mode 100755 index 00000000000..5abf9dea0a5 --- /dev/null +++ b/tools/dtrace/nexus/trace-authn.d @@ -0,0 +1,29 @@ +#!/usr/sbin/dtrace -qZs + +#pragma D option strsize=4k + +nexus*:::authn-start +{ + ts[arg0] = timestamp; + schemes[arg0] = copyinstr(arg1); + methods[arg0] = copyinstr(arg2); + uris[arg0] = copyinstr(arg3); +} + +nexus*:::authn-done +/ts[arg0]/ +{ + this->t = (timestamp - ts[arg0]) / 1000; + printf( + "scheme=%s method=%s URI=%s result=%s duration=%dus\n", + schemes[arg0], + methods[arg0], + uris[arg0], + copyinstr(arg1), + this->t + ); + ts[arg0] = 0; + schemes[arg0] = 0; + methods[arg0] = 0; + uris[arg0] = 0; +} diff --git a/tools/dtrace/nexus/trace-authz.d b/tools/dtrace/nexus/trace-authz.d new file mode 100755 index 00000000000..cbefe367694 --- /dev/null +++ b/tools/dtrace/nexus/trace-authz.d @@ -0,0 +1,29 @@ +#!/usr/sbin/dtrace -qZs + +#pragma D option strsize=4k + +nexus*:::authz-start +{ + ts[arg0] = timestamp; + actors[arg0] = copyinstr(arg1); + actions[arg0] = copyinstr(arg2); + resources[arg0] = copyinstr(arg3); +} + +nexus*:::authz-done +/ts[arg0]/ +{ + t = (timestamp - ts[arg0]); + printf( + "actor=%s action=%s resource=%s result=%s duration=%dus\n", + actors[arg0], + actions[arg0], + resources[arg0], + copyinstr(arg1), + t / 1000 + ); + ts[arg0] = 0; + actors[arg0] = 0; + actions[arg0] = 0; + resources[arg0] = 0; +}