Skip to content

Commit

Permalink
feat: include claims as capability handler parameter
Browse files Browse the repository at this point in the history
Signed-off-by: Roman Volosatovs <[email protected]>
  • Loading branch information
rvolosatovs committed Mar 10, 2023
1 parent 909e04f commit 3d19c94
Show file tree
Hide file tree
Showing 9 changed files with 105 additions and 50 deletions.
19 changes: 12 additions & 7 deletions src/actor/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -240,19 +240,19 @@ mod tests {
impl capability::Logging for Logging {
type Error = Infallible;

fn debug(&self, text: String) -> Result<(), Self::Error> {
fn debug(&self, _: &jwt::Claims<jwt::Actor>, text: String) -> Result<(), Self::Error> {
assert_eq!(text, "debug");
Ok(())
}
fn info(&self, text: String) -> Result<(), Self::Error> {
fn info(&self, _: &jwt::Claims<jwt::Actor>, text: String) -> Result<(), Self::Error> {
assert_eq!(text, "info");
Ok(())
}
fn warn(&self, text: String) -> Result<(), Self::Error> {
fn warn(&self, _: &jwt::Claims<jwt::Actor>, text: String) -> Result<(), Self::Error> {
assert_eq!(text, "warn");
Ok(())
}
fn error(&self, text: String) -> Result<(), Self::Error> {
fn error(&self, _: &jwt::Claims<jwt::Actor>, text: String) -> Result<(), Self::Error> {
assert_eq!(text, "error");
Ok(())
}
Expand All @@ -262,15 +262,20 @@ mod tests {
impl capability::Numbergen for Numbergen {
type Error = Infallible;

fn generate_guid(&self) -> Result<Uuid, Self::Error> {
fn generate_guid(&self, _: &jwt::Claims<jwt::Actor>) -> Result<Uuid, Self::Error> {
Ok(*UUID)
}
fn random_in_range(&self, min: u32, max: u32) -> Result<u32, Self::Error> {
fn random_in_range(
&self,
_: &jwt::Claims<jwt::Actor>,
min: u32,
max: u32,
) -> Result<u32, Self::Error> {
assert_eq!(min, 42);
assert_eq!(max, 4242);
Ok(42)
}
fn random_32(&self) -> Result<u32, Self::Error> {
fn random_32(&self, _: &jwt::Claims<jwt::Actor>) -> Result<u32, Self::Error> {
Ok(4242)
}
}
Expand Down
5 changes: 4 additions & 1 deletion src/actor/wasmbus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,10 @@ fn host_call<H: capability::Handler>(
);

match trace_span!("capability::Handler::handle", bd, ns, op, ?pld)
.in_scope(|| store.data().wasmbus.handler.handle(bd, ns, op, pld))
.in_scope(|| {
let ctx = store.data();
ctx.wasmbus.handler.handle(ctx.claims, bd, ns, op, pld)
})
.context("failed to handle provider invocation")?
{
Ok(buf) => {
Expand Down
10 changes: 6 additions & 4 deletions src/capability/logging/discard.rs
Original file line number Diff line number Diff line change
@@ -1,24 +1,26 @@
use core::convert::Infallible;

use wascap::jwt;

/// A logging capability, which discards all logging statements
pub struct Logging;

impl super::Logging for Logging {
type Error = Infallible;

fn debug(&self, _: String) -> Result<(), Self::Error> {
fn debug(&self, _: &jwt::Claims<jwt::Actor>, _: String) -> Result<(), Self::Error> {
Ok(())
}

fn info(&self, _: String) -> Result<(), Self::Error> {
fn info(&self, _: &jwt::Claims<jwt::Actor>, _: String) -> Result<(), Self::Error> {
Ok(())
}

fn warn(&self, _: String) -> Result<(), Self::Error> {
fn warn(&self, _: &jwt::Claims<jwt::Actor>, _: String) -> Result<(), Self::Error> {
Ok(())
}

fn error(&self, _: String) -> Result<(), Self::Error> {
fn error(&self, _: &jwt::Claims<jwt::Actor>, _: String) -> Result<(), Self::Error> {
Ok(())
}
}
20 changes: 11 additions & 9 deletions src/capability/logging/log.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use core::convert::Infallible;
use core::ops::Deref;

use log::{Level, Log, Record};
use wascap::jwt;

/// A logging capability wrapping an arbitrary [`log::Log`] implementation.
pub struct Logging<T>(T);
Expand All @@ -23,11 +24,12 @@ impl<T> Deref for Logging<T> {
}

impl<T: Log> Logging<T> {
fn log_text(&self, level: Level, text: impl AsRef<str>) {
fn log_text(&self, level: Level, claims: &jwt::Claims<jwt::Actor>, text: impl AsRef<str>) {
let text = text.as_ref();
self.log(
&Record::builder()
.level(level)
.target(&claims.subject)
.args(format_args!("{text}"))
.build(),
);
Expand All @@ -37,23 +39,23 @@ impl<T: Log> Logging<T> {
impl<T: Log> super::Logging for Logging<T> {
type Error = Infallible;

fn debug(&self, text: String) -> Result<(), Self::Error> {
self.log_text(Level::Debug, text);
fn debug(&self, claims: &jwt::Claims<jwt::Actor>, text: String) -> Result<(), Self::Error> {
self.log_text(Level::Debug, claims, text);
Ok(())
}

fn info(&self, text: String) -> Result<(), Self::Error> {
self.log_text(Level::Info, text);
fn info(&self, claims: &jwt::Claims<jwt::Actor>, text: String) -> Result<(), Self::Error> {
self.log_text(Level::Info, claims, text);
Ok(())
}

fn warn(&self, text: String) -> Result<(), Self::Error> {
self.log_text(Level::Warn, text);
fn warn(&self, claims: &jwt::Claims<jwt::Actor>, text: String) -> Result<(), Self::Error> {
self.log_text(Level::Warn, claims, text);
Ok(())
}

fn error(&self, text: String) -> Result<(), Self::Error> {
self.log_text(Level::Error, text);
fn error(&self, claims: &jwt::Claims<jwt::Actor>, text: String) -> Result<(), Self::Error> {
self.log_text(Level::Error, claims, text);
Ok(())
}
}
10 changes: 6 additions & 4 deletions src/capability/logging/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ pub use self::log::Logging as LogLogging;

use core::fmt::Debug;

use wascap::jwt;

/// Builtin logging capability available within `wasmcloud:builtin:logging` namespace
pub trait Logging {
/// Error returned by logging operations
Expand All @@ -20,26 +22,26 @@ pub trait Logging {
/// # Errors
///
/// Returns [`Self::Error`] if the operation fails
fn debug(&self, text: String) -> Result<(), Self::Error>;
fn debug(&self, claims: &jwt::Claims<jwt::Actor>, text: String) -> Result<(), Self::Error>;

/// Log at info level
///
/// # Errors
///
/// Returns [`Self::Error`] if the operation fails
fn info(&self, text: String) -> Result<(), Self::Error>;
fn info(&self, claims: &jwt::Claims<jwt::Actor>, text: String) -> Result<(), Self::Error>;

/// Log at warn level
///
/// # Errors
///
/// Returns [`Self::Error`] if the operation fails
fn warn(&self, text: String) -> Result<(), Self::Error>;
fn warn(&self, claims: &jwt::Claims<jwt::Actor>, text: String) -> Result<(), Self::Error>;

/// Log at error level
///
/// # Errors
///
/// Returns [`Self::Error`] if the operation fails
fn error(&self, text: String) -> Result<(), Self::Error>;
fn error(&self, claims: &jwt::Claims<jwt::Actor>, text: String) -> Result<(), Self::Error>;
}
53 changes: 36 additions & 17 deletions src/capability/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use core::fmt::Debug;

use anyhow::{bail, Context};
use tracing::{instrument, trace_span};
use wascap::jwt;
use wasmbus_rpc::common::{deserialize, serialize};
use wasmcloud_interface_logging::LogEntry;
use wasmcloud_interface_numbergen::RangeLimit;
Expand All @@ -29,6 +30,7 @@ pub trait Handler {
/// guest as an application-layer error.
fn handle(
&self,
claims: &jwt::Claims<jwt::Actor>,
binding: String,
namespace: String,
operation: String,
Expand All @@ -54,6 +56,7 @@ impl Handler for () {

fn handle(
&self,
_: &jwt::Claims<jwt::Actor>,
_: String,
_: String,
_: String,
Expand All @@ -67,18 +70,25 @@ impl<T, E, F> Handler for F
where
T: Into<Vec<u8>>,
E: ToString + Debug,
F: Fn(String, String, String, Vec<u8>) -> anyhow::Result<Result<T, E>>,
F: Fn(
&jwt::Claims<jwt::Actor>,
String,
String,
String,
Vec<u8>,
) -> anyhow::Result<Result<T, E>>,
{
type Error = E;

fn handle(
&self,
claims: &jwt::Claims<jwt::Actor>,
binding: String,
namespace: String,
operation: String,
payload: Vec<u8>,
) -> anyhow::Result<Result<Vec<u8>, Self::Error>> {
match self(binding, namespace, operation, payload) {
match self(claims, binding, namespace, operation, payload) {
Ok(Ok(res)) => Ok(Ok(res.into())),
Ok(Err(err)) => Ok(Err(err)),
Err(err) => Err(err),
Expand All @@ -97,6 +107,7 @@ where
#[instrument(skip(self))]
fn handle(
&self,
claims: &jwt::Claims<jwt::Actor>,
binding: String,
namespace: String,
operation: String,
Expand All @@ -106,23 +117,28 @@ where
(_, "wasmcloud:builtin:logging", "Logging.WriteLog") => {
let LogEntry { level, text } =
deserialize(&payload).context("failed to deserialize log entry")?;
let res = match level.as_str() {
"debug" => trace_span!("Logging::debug").in_scope(|| self.logging.debug(text)),
"info" => trace_span!("Logging::info").in_scope(|| self.logging.info(text)),
"warn" => trace_span!("Logging::warn").in_scope(|| self.logging.warn(text)),
"error" => trace_span!("Logging::error").in_scope(|| self.logging.error(text)),
_ => {
bail!("log level `{level}` is not supported")
}
};
let res =
match level.as_str() {
"debug" => trace_span!("Logging::debug")
.in_scope(|| self.logging.debug(claims, text)),
"info" => trace_span!("Logging::info")
.in_scope(|| self.logging.info(claims, text)),
"warn" => trace_span!("Logging::warn")
.in_scope(|| self.logging.warn(claims, text)),
"error" => trace_span!("Logging::error")
.in_scope(|| self.logging.error(claims, text)),
_ => {
bail!("log level `{level}` is not supported")
}
};
match res {
Ok(()) => Ok(Ok(vec![])),
Err(err) => Ok(Err(err.to_string())),
}
}
(_, "wasmcloud:builtin:numbergen", "NumberGen.GenerateGuid") => {
match trace_span!("Numbergen::generate_guid")
.in_scope(|| self.numbergen.generate_guid())
.in_scope(|| self.numbergen.generate_guid(claims))
{
Ok(guid) => serialize(&guid.to_string())
.context("failed to serialize UUID")
Expand All @@ -134,21 +150,24 @@ where
let RangeLimit { min, max } =
deserialize(&payload).context("failed to deserialize range limit")?;
match trace_span!("Numbergen::random_in_range")
.in_scope(|| self.numbergen.random_in_range(min, max))
.in_scope(|| self.numbergen.random_in_range(claims, min, max))
{
Ok(v) => serialize(&v).context("failed to serialize number").map(Ok),
Err(err) => Ok(Err(err.to_string())),
}
}
(_, "wasmcloud:builtin:numbergen", "NumberGen.Random32") => {
match trace_span!("Numbergen::random_32").in_scope(|| self.numbergen.random_32()) {
match trace_span!("Numbergen::random_32")
.in_scope(|| self.numbergen.random_32(claims))
{
Ok(v) => serialize(&v).context("failed to serialize number").map(Ok),
Err(err) => Ok(Err(err.to_string())),
}
}
_ => match trace_span!("Handler::handle")
.in_scope(|| self.external.handle(binding, namespace, operation, payload))
{
_ => match trace_span!("Handler::handle").in_scope(|| {
self.external
.handle(claims, binding, namespace, operation, payload)
}) {
Ok(Ok(res)) => Ok(Ok(res)),
Ok(Err(err)) => Ok(Err(err.to_string())),
Err(err) => Err(err),
Expand Down
13 changes: 10 additions & 3 deletions src/capability/numbergen/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ pub use uuid::Uuid;

use core::fmt::Debug;

use wascap::jwt;

/// Builtin random number generation capability available within `wasmcloud:builtin:numbergen` namespace
pub trait Numbergen {
/// Error returned by random number generation operations
Expand All @@ -20,19 +22,24 @@ pub trait Numbergen {
/// # Errors
///
/// Returns [`Self::Error`] if the operation fails
fn generate_guid(&self) -> Result<Uuid, Self::Error>;
fn generate_guid(&self, claims: &jwt::Claims<jwt::Actor>) -> Result<Uuid, Self::Error>;

/// Returns a random [u32] within inclusive range from `min` to `max`
///
/// # Errors
///
/// Returns [`Self::Error`] if the operation fails
fn random_in_range(&self, min: u32, max: u32) -> Result<u32, Self::Error>;
fn random_in_range(
&self,
claims: &jwt::Claims<jwt::Actor>,
min: u32,
max: u32,
) -> Result<u32, Self::Error>;

/// Returns a random [u32]
///
/// # Errors
///
/// Returns [`Self::Error`] if the operation fails
fn random_32(&self) -> Result<u32, Self::Error>;
fn random_32(&self, claims: &jwt::Claims<jwt::Actor>) -> Result<u32, Self::Error>;
}
12 changes: 9 additions & 3 deletions src/capability/numbergen/rand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use super::{uuid, Uuid};
use std::sync::{Mutex, MutexGuard};

use rand::{CryptoRng, Rng};
use wascap::jwt;

/// A random number generation capability wrapping an arbitrary [`rand::Rng`] implementation.
/// Note, that the underlying random number generator MUST implement [`rand::CryptoRng`] as an
Expand All @@ -26,18 +27,23 @@ impl<T> Numbergen<T> {
impl<T: Rng + CryptoRng> super::Numbergen for Numbergen<T> {
type Error = &'static str;

fn generate_guid(&self) -> Result<Uuid, Self::Error> {
fn generate_guid(&self, _: &jwt::Claims<jwt::Actor>) -> Result<Uuid, Self::Error> {
let mut buf = uuid::Bytes::default();
self.lock()?.fill_bytes(&mut buf);
Ok(uuid::Builder::from_random_bytes(buf).into_uuid())
}

fn random_in_range(&self, min: u32, max: u32) -> Result<u32, Self::Error> {
fn random_in_range(
&self,
_: &jwt::Claims<jwt::Actor>,
min: u32,
max: u32,
) -> Result<u32, Self::Error> {
let v = self.lock()?.gen_range(min..=max);
Ok(v)
}

fn random_32(&self) -> Result<u32, Self::Error> {
fn random_32(&self, _: &jwt::Claims<jwt::Actor>) -> Result<u32, Self::Error> {
let v = self.lock()?.gen();
Ok(v)
}
Expand Down
Loading

0 comments on commit 3d19c94

Please sign in to comment.