Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

authorizer builder #250

Merged
merged 29 commits into from
Nov 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
511 changes: 291 additions & 220 deletions biscuit-auth/benches/token.rs

Large diffs are not rendered by default.

41 changes: 19 additions & 22 deletions biscuit-auth/examples/testcases.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ use biscuit::datalog::SymbolTable;
use biscuit::error;
use biscuit::format::convert::v2 as convert;
use biscuit::macros::*;
use biscuit::Authorizer;
use biscuit::{builder::*, builder_ext::*, Biscuit};
use biscuit::{KeyPair, PrivateKey, PublicKey};
use biscuit_auth::builder;
Expand Down Expand Up @@ -344,12 +343,13 @@ fn validate_token_with_limits_and_external_functions(
revocation_ids.push(hex::encode(&bytes));
}

let mut authorizer = Authorizer::new();
authorizer.set_extern_funcs(extern_funcs);
authorizer.add_code(authorizer_code).unwrap();
let authorizer_code = authorizer.dump_code();
let builder = AuthorizerBuilder::new()
.set_extern_funcs(extern_funcs)
.code(authorizer_code)
.unwrap();
let authorizer_code = builder.dump_code();

match authorizer.add_token(&token) {
let mut authorizer = match builder.build(&token) {
Ok(v) => v,
Err(e) => {
return Validation {
Expand Down Expand Up @@ -878,9 +878,9 @@ fn scoped_rules(target: &str, root: &KeyPair, test: bool) -> TestResult {
)
.unwrap();

let mut block3 = BlockBuilder::new();

block3.add_fact(r#"owner("alice", "file2")"#).unwrap();
let block3 = BlockBuilder::new()
.fact(r#"owner("alice", "file2")"#)
.unwrap();

let keypair3 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng);
let biscuit3 = biscuit2.append_with_keypair(&keypair3, block3).unwrap();
Expand Down Expand Up @@ -973,14 +973,13 @@ fn expired_token(target: &str, root: &KeyPair, test: bool) -> TestResult {
.build_with_rng(&root, SymbolTable::default(), &mut rng)
.unwrap();

let mut block2 = block!(r#"check if resource("file1");"#);

// January 1 2019
block2.check_expiration_date(
UNIX_EPOCH
.checked_add(Duration::from_secs(49 * 365 * 24 * 3600))
.unwrap(),
);
let block2 = block!(r#"check if resource("file1");"#)
// January 1 2019
.check_expiration_date(
UNIX_EPOCH
.checked_add(Duration::from_secs(49 * 365 * 24 * 3600))
.unwrap(),
);

let keypair2 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng);
let biscuit2 = biscuit1.append_with_keypair(&keypair2, block2).unwrap();
Expand Down Expand Up @@ -1410,11 +1409,9 @@ fn unbound_variables_in_rule(target: &str, root: &KeyPair, test: bool) -> TestRe
.build_with_rng(&root, SymbolTable::default(), &mut rng)
.unwrap();

let mut block2 = BlockBuilder::new();

// this one does not go through the parser because it checks for unused variables
block2
.add_rule(rule(
let block2 = BlockBuilder::new()
// this one does not go through the parser because it checks for unused variables
.rule(rule(
"operation",
&[var("unbound"), string("read")],
&[pred("operation", &[var("any1"), var("any2")])],
Expand Down
35 changes: 20 additions & 15 deletions biscuit-auth/examples/third_party.rs
Original file line number Diff line number Diff line change
@@ -1,24 +1,22 @@
use biscuit_auth::{
builder::Algorithm, builder::BlockBuilder, datalog::SymbolTable, Biscuit, KeyPair,
builder::{Algorithm, AuthorizerBuilder, BlockBuilder},
builder_ext::AuthorizerExt,
datalog::SymbolTable,
Biscuit, KeyPair,
};
use rand::{prelude::StdRng, SeedableRng};

fn main() {
let mut rng: StdRng = SeedableRng::seed_from_u64(0);
let root = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng);
let external = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng);

let mut builder = Biscuit::builder();

let external_pub = hex::encode(external.public().to_bytes());

builder
.add_check(
let biscuit1 = Biscuit::builder()
.check(
format!("check if external_fact(\"hello\") trusting ed25519/{external_pub}").as_str(),
)
.unwrap();

let biscuit1 = builder
.unwrap()
.build_with_rng(&root, SymbolTable::default(), &mut rng)
.unwrap();

Expand All @@ -27,21 +25,28 @@ fn main() {
let serialized_req = biscuit1.third_party_request().unwrap().serialize().unwrap();

let req = biscuit_auth::ThirdPartyRequest::deserialize(&serialized_req).unwrap();
let mut builder = BlockBuilder::new();
builder.add_fact("external_fact(\"hello\")").unwrap();
let builder = BlockBuilder::new()
.fact("external_fact(\"hello\")")
.unwrap();
let res = req.create_block(&external.private(), builder).unwrap();

let biscuit2 = biscuit1.append_third_party(external.public(), res).unwrap();

println!("biscuit2: {}", biscuit2);

let mut authorizer = biscuit1.authorizer().unwrap();
authorizer.allow().unwrap();
let mut authorizer = AuthorizerBuilder::new()
.allow_all()
.build(&biscuit1)
.unwrap();

println!("authorize biscuit1:\n{:?}", authorizer.authorize());
println!("world:\n{}", authorizer.print_world());

let mut authorizer = biscuit2.authorizer().unwrap();
authorizer.allow().unwrap();
let mut authorizer = AuthorizerBuilder::new()
.allow_all()
.build(&biscuit2)
.unwrap();

println!("authorize biscuit2:\n{:?}", authorizer.authorize());
println!("world:\n{}", authorizer.print_world());
}
5 changes: 2 additions & 3 deletions biscuit-auth/examples/verifying_printer.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use biscuit_auth::PublicKey;
use biscuit_auth::{builder::AuthorizerBuilder, builder_ext::AuthorizerExt, PublicKey};

fn main() {
let mut args = std::env::args();
Expand All @@ -25,8 +25,7 @@ fn main() {
}
println!("token:\n{}", token);

let mut authorizer = token.authorizer().unwrap();
authorizer.allow().unwrap();
let mut authorizer = AuthorizerBuilder::new().allow_all().build(&token).unwrap();

println!("authorizer result: {:?}", authorizer.authorize());
println!("authorizer world:\n{}", authorizer.print_world());
Expand Down
2 changes: 1 addition & 1 deletion biscuit-auth/src/datalog/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -783,7 +783,7 @@ impl FactSet {
pub fn iterator<'a>(
&'a self,
block_ids: &'a TrustedOrigins,
) -> impl Iterator<Item = (&Origin, &Fact)> + Clone {
) -> impl Iterator<Item = (&'a Origin, &'a Fact)> + Clone {
self.inner
.iter()
.filter_map(move |(ids, facts)| {
Expand Down
19 changes: 11 additions & 8 deletions biscuit-auth/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@
//! // - one for /a/file1.txt and a write operation
//! // - one for /a/file2.txt and a read operation
//!
//! let v1 = authorizer!(r#"
//! let mut v1 = authorizer!(r#"
//! resource("/a/file1.txt");
//! operation("read");
//!
Expand All @@ -101,26 +101,29 @@
//! // explicit catch-all deny. here it is not necessary: if no policy
//! // matches, a default deny applies
//! deny if true;
//! "#);
//! "#)
//! .build(&biscuit2)?;
//!
//! let mut v2 = authorizer!(r#"
//! resource("/a/file1.txt");
//! operation("write");
//! allow if right("/a/file1.txt", "write");
//! "#);
//!
//! "#)
//! .build(&biscuit2)?;
//!
//! let mut v3 = authorizer!(r#"
//! resource("/a/file2.txt");
//! operation("read");
//! allow if right("/a/file2.txt", "read");
//! "#);
//! "#)
//! .build(&biscuit2)?;
//!
//! // the token restricts to read operations:
//! assert!(biscuit2.authorize(&v1).is_ok());
//! assert!(v1.authorize().is_ok());
//! // the second verifier requested a read operation
//! assert!(biscuit2.authorize(&v2).is_err());
//! assert!(v2.authorize().is_err());
//! // the third verifier requests /a/file2.txt
//! assert!(biscuit2.authorize(&v3).is_err());
//! assert!(v3.authorize().is_err());
//!
//! Ok(())
//! }
Expand Down
20 changes: 12 additions & 8 deletions biscuit-auth/src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
//! expiration = SystemTime::now() + Duration::from_secs(86_400),
//! )).expect("Failed to append block");
//!
//! new_biscuit.authorize(&authorizer!(
//! authorizer!(
//! r#"
//! time({now});
//! operation({operation});
Expand All @@ -42,7 +42,11 @@
//! operation = "read",
//! resource = "file1",
//! user_id = "1234",
//! )).expect("Failed to authorize biscuit");
//! )
//! .build(&new_biscuit)
//! .expect("failed to build the authorizer")
//! .authorize()
//! .expect("Failed to authorize biscuit");
//! ```

/// Create an `Authorizer` from a datalog string and optional parameters.
Expand Down Expand Up @@ -78,8 +82,8 @@ pub use biscuit_quote::authorizer;
/// now = SystemTime::now()
/// );
///
/// authorizer_merge!(
/// &mut b,
/// b = authorizer_merge!(
/// b,
/// r#"
/// allow if true;
/// "#
Expand Down Expand Up @@ -128,8 +132,8 @@ pub use biscuit_quote::biscuit;
/// user_id = "1234"
/// );
///
/// biscuit_merge!(
/// &mut b,
/// b = biscuit_merge!(
/// b,
/// r#"
/// check if time($time), $time < {expiration}
/// "#,
Expand Down Expand Up @@ -173,8 +177,8 @@ pub use biscuit_quote::block;
/// user_id = "1234"
/// );
///
/// block_merge!(
/// &mut b,
/// b = block_merge!(
/// b,
/// r#"
/// check if user($id);
/// "#
Expand Down
Loading
Loading