Skip to content

Commit

Permalink
Merge pull request #257 from biscuit-auth/authorizer-debug
Browse files Browse the repository at this point in the history
fix snapshot de-serializing
  • Loading branch information
divarvel authored Dec 9, 2024
2 parents c8057ce + e50cddc commit 2c75eaf
Show file tree
Hide file tree
Showing 3 changed files with 210 additions and 2 deletions.
2 changes: 1 addition & 1 deletion biscuit-auth/src/datalog/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -733,7 +733,7 @@ impl World {
}

/// runtime limits for the Datalog engine
#[derive(Debug, Clone)]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct RunLimits {
/// maximum number of Datalog facts (memory usage)
pub max_facts: u64,
Expand Down
208 changes: 208 additions & 0 deletions biscuit-auth/src/token/authorizer/snapshot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,46 @@ impl super::Authorizer {
authorizer.blocks = Some(blocks);
}

let mut authorizer_origin = Origin::default();
authorizer_origin.insert(usize::MAX);

let authorizer_scopes: Vec<crate::token::Scope> = authorizer
.authorizer_block_builder
.scopes
.clone()
.iter()
.map(|s| s.convert(&mut authorizer.symbols))
.collect();

let authorizer_trusted_origins = TrustedOrigins::from_scopes(
&authorizer_scopes,
&TrustedOrigins::default(),
usize::MAX,
&authorizer.public_key_to_block_id,
);
for fact in &authorizer.authorizer_block_builder.facts {
authorizer
.world
.facts
.insert(&authorizer_origin, fact.convert(&mut authorizer.symbols));
}

for rule in &authorizer.authorizer_block_builder.rules {
let rule = rule.convert(&mut authorizer.symbols);

let rule_trusted_origins = TrustedOrigins::from_scopes(
&rule.scopes,
&authorizer_trusted_origins,
usize::MAX,
&authorizer.public_key_to_block_id,
);

authorizer
.world
.rules
.insert(usize::MAX, &rule_trusted_origins, rule);
}

for GeneratedFacts { origins, facts } in world.generated_facts {
let origin = proto_origin_to_authorizer_origin(&origins)?;

Expand Down Expand Up @@ -271,3 +311,171 @@ pub(crate) fn proto_origin_to_authorizer_origin(

Ok(new_origin)
}

#[cfg(test)]
mod tests {
use std::collections::HashMap;
use std::time::Duration;

use crate::{datalog::RunLimits, Algorithm, AuthorizerBuilder};
use crate::{Authorizer, BiscuitBuilder, KeyPair};

#[test]
fn roundtrip_builder() {
let secp_pubkey = KeyPair::new_with_algorithm(Algorithm::Secp256r1).public();
let ed_pubkey = KeyPair::new_with_algorithm(Algorithm::Ed25519).public();
let builder = AuthorizerBuilder::new()
.limits(RunLimits {
max_facts: 42,
max_iterations: 42,
max_time: Duration::from_secs(1),
})
.code_with_params(
r#"
fact(true);
head($a) <- fact($a);
check if head(true) trusting authority, {ed_pubkey}, {secp_pubkey};
allow if head(true);
deny if head(false);
"#,
HashMap::default(),
HashMap::from([
("ed_pubkey".to_string(), ed_pubkey),
("secp_pubkey".to_string(), secp_pubkey),
]),
)
.unwrap();
let snapshot = builder.snapshot().unwrap();

let parsed = AuthorizerBuilder::from_snapshot(snapshot).unwrap();
assert_eq!(parsed.dump_code(), builder.dump_code());
assert_eq!(parsed.limits, builder.limits);
}

#[test]
fn roundtrip_with_token() {
let secp_pubkey = KeyPair::new_with_algorithm(Algorithm::Secp256r1).public();
let ed_pubkey = KeyPair::new_with_algorithm(Algorithm::Ed25519).public();
let builder = AuthorizerBuilder::new()
.limits(RunLimits {
max_facts: 42,
max_iterations: 42,
max_time: Duration::from_secs(1),
})
.code_with_params(
r#"
fact(true);
head($a) <- fact($a);
check if head(true) trusting authority, {ed_pubkey}, {secp_pubkey};
allow if head(true);
deny if head(false);
"#,
HashMap::default(),
HashMap::from([
("ed_pubkey".to_string(), ed_pubkey),
("secp_pubkey".to_string(), secp_pubkey),
]),
)
.unwrap();
let biscuit = BiscuitBuilder::new()
.code_with_params(
r#"
bfact(true);
bhead($a) <- fact($a);
check if bhead(true) trusting authority, {ed_pubkey}, {secp_pubkey};
"#,
HashMap::default(),
HashMap::from([
("ed_pubkey".to_string(), ed_pubkey),
("secp_pubkey".to_string(), secp_pubkey),
]),
)
.unwrap()
.build(&KeyPair::new())
.unwrap();

let authorizer_pre_run = builder.build(&biscuit).unwrap();

let snapshot = authorizer_pre_run.snapshot().unwrap();

let parsed = Authorizer::from_snapshot(snapshot).unwrap();
assert_eq!(parsed.dump_code(), authorizer_pre_run.dump_code());
assert_eq!(parsed.limits(), authorizer_pre_run.limits());

let mut authorizer_post_run = authorizer_pre_run.clone();
let _ = authorizer_post_run.run();

let snapshot = authorizer_post_run.snapshot().unwrap();

let parsed = Authorizer::from_snapshot(snapshot).unwrap();
assert_eq!(parsed.dump_code(), authorizer_post_run.dump_code());
assert_eq!(parsed.limits(), authorizer_post_run.limits());
}

#[test]
fn roundtrip_without_token() {
let builder = AuthorizerBuilder::new()
.limits(RunLimits {
max_facts: 42,
max_iterations: 42,
max_time: Duration::from_secs(1),
})
.code(
r#"
fact(true);
head($a) <- fact($a);
check if head(true);
allow if head(true);
deny if head(false);
"#,
)
.unwrap();
let authorizer = builder.build_unauthenticated().unwrap();
let snapshot = authorizer.snapshot().unwrap();

let parsed = Authorizer::from_snapshot(snapshot).unwrap();
assert_eq!(parsed.dump_code(), authorizer.dump_code());
assert_eq!(parsed.limits(), authorizer.limits());

let mut authorizer_post_run = authorizer.clone();
let _ = authorizer_post_run.run();
let snapshot = authorizer_post_run.snapshot().unwrap();

let parsed = Authorizer::from_snapshot(snapshot).unwrap();
assert_eq!(parsed.dump_code(), authorizer_post_run.dump_code());
assert_eq!(parsed.limits(), authorizer_post_run.limits());
}

#[test]
fn roundtrip_with_eval_error() {
let builder = AuthorizerBuilder::new()
.limits(RunLimits {
max_facts: 42,
max_iterations: 42,
max_time: Duration::from_secs(1),
})
.code(
r#"
fact(true);
head($a) <- fact($a), $a.length();
allow if head(true);
deny if head(false);
"#,
)
.unwrap();
let authorizer = builder.build_unauthenticated().unwrap();
let snapshot = authorizer.snapshot().unwrap();

let parsed = Authorizer::from_snapshot(snapshot).unwrap();
assert_eq!(parsed.dump_code(), authorizer.dump_code());
assert_eq!(parsed.limits(), authorizer.limits());

let mut authorizer_post_run = authorizer.clone();
let _ = authorizer_post_run.run();
let snapshot = authorizer_post_run.snapshot().unwrap();

let parsed = Authorizer::from_snapshot(snapshot).unwrap();
assert_eq!(parsed.dump_code(), authorizer_post_run.dump_code());
assert_eq!(parsed.limits(), authorizer_post_run.limits());
}
}
2 changes: 1 addition & 1 deletion biscuit-auth/src/token/builder/authorizer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ pub struct AuthorizerBuilder {
authorizer_block_builder: BlockBuilder,
policies: Vec<Policy>,
extern_funcs: HashMap<String, ExternFunc>,
limits: AuthorizerLimits,
pub(crate) limits: AuthorizerLimits,
}

impl AuthorizerBuilder {
Expand Down

0 comments on commit 2c75eaf

Please sign in to comment.