From 03286631f09363dff50345cd0d09cc4903def1e4 Mon Sep 17 00:00:00 2001 From: Clement Delafargue Date: Tue, 3 Dec 2024 19:32:05 +0100 Subject: [PATCH] =?UTF-8?q?Authorizer:=20don=E2=80=99t=20run=20the=20autho?= =?UTF-8?q?rizer=20right=20after=20building=20it.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This allows taking a snapshot of the authorizer even if the datalog evaluation fails. --- biscuit-auth/src/token/authorizer.rs | 44 ++++++++++++++----- biscuit-auth/src/token/authorizer/snapshot.rs | 5 ++- biscuit-auth/src/token/builder/authorizer.rs | 6 ++- biscuit-auth/tests/macros.rs | 3 +- 4 files changed, 41 insertions(+), 17 deletions(-) diff --git a/biscuit-auth/src/token/authorizer.rs b/biscuit-auth/src/token/authorizer.rs index 670a61d0..040270a0 100644 --- a/biscuit-auth/src/token/authorizer.rs +++ b/biscuit-auth/src/token/authorizer.rs @@ -31,10 +31,24 @@ pub struct Authorizer { pub(crate) blocks: Option>, pub(crate) public_key_to_block_id: HashMap>, pub(crate) limits: AuthorizerLimits, - pub(crate) execution_time: Duration, + pub(crate) execution_time: Option, } impl Authorizer { + pub fn run(&mut self) -> Result { + match self.execution_time { + Some(execution_time) => Ok(execution_time), + None => { + let start = Instant::now(); + self.world + .run_with_limits(&self.symbols, self.limits.clone())?; + let execution_time = start.elapsed(); + self.execution_time = Some(execution_time); + Ok(execution_time) + } + } + } + pub(crate) fn from_token(token: &Biscuit) -> Result { AuthorizerBuilder::new().build(token) } @@ -62,7 +76,7 @@ impl Authorizer { blocks: None, public_key_to_block_id: HashMap::new(), limits: AuthorizerLimits::default(), - execution_time: Duration::default(), + execution_time: None, } } @@ -129,12 +143,13 @@ impl Authorizer { where error::Token: From<>::Error>, { + let execution_time = self.run()?; let mut limits = self.limits.clone(); limits.max_iterations -= self.world.iterations; - if self.execution_time >= limits.max_time { + if execution_time >= limits.max_time { return Err(error::Token::RunLimit(error::RunLimit::Timeout)); } - limits.max_time -= self.execution_time; + limits.max_time -= execution_time; self.query_with_limits(rule, limits) } @@ -152,11 +167,12 @@ impl Authorizer { where error::Token: From<>::Error>, { + let execution_time = self.run()?; let rule = rule.try_into()?.convert(&mut self.symbols); let start = Instant::now(); let result = self.query_inner(rule, limits); - self.execution_time += start.elapsed(); + self.execution_time = Some(start.elapsed() + execution_time); result } @@ -218,12 +234,13 @@ impl Authorizer { where error::Token: From<>::Error>, { + let execution_time = self.run()?; let mut limits = self.limits.clone(); limits.max_iterations -= self.world.iterations; - if self.execution_time >= limits.max_time { + if execution_time >= limits.max_time { return Err(error::Token::RunLimit(error::RunLimit::Timeout)); } - limits.max_time -= self.execution_time; + limits.max_time -= execution_time; self.query_all_with_limits(rule, limits) } @@ -245,11 +262,12 @@ impl Authorizer { where error::Token: From<>::Error>, { + let execution_time = self.run()?; let rule = rule.try_into()?.convert(&mut self.symbols); let start = Instant::now(); let result = self.query_all_inner(rule, limits); - self.execution_time += start.elapsed(); + self.execution_time = Some(execution_time + start.elapsed()); result } @@ -289,7 +307,7 @@ impl Authorizer { } /// returns the elapsed execution time - pub fn execution_time(&self) -> Duration { + pub fn execution_time(&self) -> Option { self.execution_time } @@ -308,12 +326,13 @@ impl Authorizer { /// on error, this can return a list of all the failed checks or deny policy /// on success, it returns the index of the policy that matched pub fn authorize(&mut self) -> Result { + let execution_time = self.run()?; let mut limits = self.limits.clone(); limits.max_iterations -= self.world.iterations; - if self.execution_time >= limits.max_time { + if execution_time >= limits.max_time { return Err(error::Token::RunLimit(error::RunLimit::Timeout)); } - limits.max_time -= self.execution_time; + limits.max_time -= execution_time; self.authorize_with_limits(limits) } @@ -327,9 +346,10 @@ impl Authorizer { &mut self, limits: AuthorizerLimits, ) -> Result { + let execution_time = self.run()?; let start = Instant::now(); let result = self.authorize_inner(limits); - self.execution_time += start.elapsed(); + self.execution_time = Some(execution_time + start.elapsed()); result } diff --git a/biscuit-auth/src/token/authorizer/snapshot.rs b/biscuit-auth/src/token/authorizer/snapshot.rs index 905da00d..2d523ff9 100644 --- a/biscuit-auth/src/token/authorizer/snapshot.rs +++ b/biscuit-auth/src/token/authorizer/snapshot.rs @@ -69,7 +69,8 @@ impl super::Authorizer { authorizer.authorizer_block_builder = authorizer_block_builder; authorizer.policies = policies; authorizer.limits = limits; - authorizer.execution_time = execution_time; + authorizer.execution_time = + Some(execution_time).filter(|_| execution_time > Duration::default()); let mut public_key_to_block_id: HashMap> = HashMap::new(); let mut blocks = Vec::new(); @@ -207,7 +208,7 @@ impl super::Authorizer { Ok(schema::AuthorizerSnapshot { world, - execution_time: self.execution_time.as_nanos() as u64, + execution_time: self.execution_time.unwrap_or_default().as_nanos() as u64, limits: schema::RunLimits { max_facts: self.limits.max_facts, max_iterations: self.limits.max_iterations, diff --git a/biscuit-auth/src/token/builder/authorizer.rs b/biscuit-auth/src/token/builder/authorizer.rs index 40dea490..0ff28ccb 100644 --- a/biscuit-auth/src/token/builder/authorizer.rs +++ b/biscuit-auth/src/token/builder/authorizer.rs @@ -2,7 +2,7 @@ use std::{ collections::HashMap, convert::TryInto, fmt::Write, - time::{Duration, Instant, SystemTime}, + time::{Duration, SystemTime}, }; use biscuit_parser::parser::parse_source; @@ -384,9 +384,11 @@ impl AuthorizerBuilder { world.rules.insert(usize::MAX, &rule_trusted_origins, rule); } + /* let start = Instant::now(); world.run_with_limits(&symbols, self.limits.clone())?; let execution_time = start.elapsed(); + */ Ok(Authorizer { authorizer_block_builder: self.authorizer_block_builder, @@ -397,7 +399,7 @@ impl AuthorizerBuilder { blocks, public_key_to_block_id, limits: self.limits, - execution_time, + execution_time: None, }) } } diff --git a/biscuit-auth/tests/macros.rs b/biscuit-auth/tests/macros.rs index 275cac03..bb5498af 100644 --- a/biscuit-auth/tests/macros.rs +++ b/biscuit-auth/tests/macros.rs @@ -75,13 +75,14 @@ fn authorizer_macro() { "# ); - let authorizer = b + let mut authorizer = b .limits(RunLimits { max_time: Duration::from_secs(10), ..Default::default() }) .build_unauthenticated() .unwrap(); + authorizer.run().unwrap(); assert_eq!( authorizer.dump_code(), r#"appended(true);