diff --git a/Cargo.toml b/Cargo.toml index 85b440d0..4ed130e0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [workspace] -members = ["biscuit-auth", "biscuit-quote", "biscuit-parser", "biscuit-capi"] +members = ["biscuit-auth", "biscuit-proto", "biscuit-quote", "biscuit-parser", "biscuit-capi"] resolver = "2" # Used by capi crate diff --git a/biscuit-auth/CHANGELOG.md b/biscuit-auth/CHANGELOG.md index 2b51e035..68ca451e 100644 --- a/biscuit-auth/CHANGELOG.md +++ b/biscuit-auth/CHANGELOG.md @@ -8,6 +8,9 @@ - `Term` implements `From` with the `uuid` feature. - Scope parameters are `Into` so they can take anything which can be converted into a public key (including `&K: SerializePublicKey`). +- `Authorizer` gains inspection methods that don't require going through a snapshot: + `dump_facts_with_origins`, `dump_rules_with_origins`, `dump_checks_with_origins` and + `dump_policies` ## Breaking changes @@ -15,7 +18,7 @@ keypair are replaced with APIs that take a `PrivateKey` (i.e. `append_with_keypair` -> `append_with_key`, `append_third_party_with_keypair` -> `append_third_party_with_key`). - `Biscuit` and `UnverifiedBiscuit` are generic over the private key type contained in their - proof. These are defaulted to `PrivateKey`, so this change should be transparent for most users + proof. These are defaulted to `PrivateKey`, so this change should be transpfarent for most users who use the default crypto types. - `RootKeyProvider` has an associated `Key` type, which is the type of the root key that is provided. @@ -26,6 +29,11 @@ for custom types should implement `From for Term` instead. - The `set_macro_param` and `set_macro_scope_param` methods are removed; macros now call `set_lenient` and `set_scope_lenient`. +- Protobuf generated code is no longer part of the public API of this crate. The protobuf generated + schema is now available at the crate `biscuit-proto` and versioned independently of + `biscuit-rust`. The `format::schema` and `format::convert` modules are no longer part of the + public API of this crate and the protobuf conversion methods are no longer public. Types can still + be serialized/deserialized to and from their binary representation. # `6.0.0` diff --git a/biscuit-auth/Cargo.toml b/biscuit-auth/Cargo.toml index a7756e39..28758d1b 100644 --- a/biscuit-auth/Cargo.toml +++ b/biscuit-auth/Cargo.toml @@ -4,7 +4,6 @@ version = "6.0.0" description = "an authorization token with decentralized verification and offline attenuation" authors = ["Geoffroy Couprie "] edition = "2018" -build = "build.rs" license = "Apache-2.0" documentation = "https://docs.rs/biscuit-auth" homepage = "https://github.com/biscuit-auth/biscuit" @@ -29,7 +28,7 @@ pem = ["ed25519-dalek/pem", "ed25519-dalek/pkcs8"] rand_core = "^0.6" sha2 = "^0.9" prost = "0.10" -prost-types = "0.10" +biscuit-proto = { version = "0.1.0", path = "../biscuit-proto" } regex = { version = "1.5", default-features = false, features = ["std"] } nom = { version = "7", default-features = false, features = ["std"] } hex = "0.4" @@ -59,14 +58,10 @@ bencher = "0.1.5" rand = "0.8" chrono = { version = "0.4.26", features = ["serde", "clock"] } colored-diff = "0.2.3" -prost-build = "0.10" serde = { version = "1.0.130", features = ["derive"] } serde_json = "1.0.67" codspeed-bencher-compat = "2.6.0" -#[build-dependencies] -#prost-build = "0.10" - [[example]] name = "testcases" required-features = ["serde-error"] diff --git a/biscuit-auth/build.rs b/biscuit-auth/build.rs deleted file mode 100644 index cd7b954b..00000000 --- a/biscuit-auth/build.rs +++ /dev/null @@ -1,8 +0,0 @@ -/* - * Copyright (c) 2019 Geoffroy Couprie and Contributors to the Eclipse Foundation. - * SPDX-License-Identifier: Apache-2.0 - */ -fn main() { - println!("cargo:rerun-if-changed=src/format/schema.proto"); - //prost_build::compile_protos(&["src/format/schema.proto"], &["src/"]).unwrap(); -} diff --git a/biscuit-auth/examples/testcases.rs b/biscuit-auth/examples/testcases.rs index 721f078c..b3a5611d 100644 --- a/biscuit-auth/examples/testcases.rs +++ b/biscuit-auth/examples/testcases.rs @@ -9,7 +9,6 @@ extern crate biscuit_auth as biscuit; use biscuit::builder::BlockBuilder; use biscuit::datalog::SymbolTable; use biscuit::error; -use biscuit::format::convert; use biscuit::macros::*; use biscuit::public_keys::PublicKeyData; use biscuit::{builder::*, builder_ext::*, Biscuit}; @@ -23,12 +22,7 @@ use rand::prelude::*; use serde::Serialize; use std::collections::HashMap; use std::sync::Arc; -use std::{ - collections::{BTreeMap, BTreeSet}, - fs::File, - io::Write, - time::*, -}; +use std::{collections::BTreeMap, fs::File, io::Write, time::*}; fn main() { let mut args = std::env::args(); @@ -295,7 +289,7 @@ struct AuthorizerWorld { #[derive(Debug, Serialize, PartialEq, Eq, PartialOrd, Ord)] struct Facts { - origin: BTreeSet>, + origin: Vec>, facts: Vec, } @@ -372,102 +366,37 @@ fn validate_token_with_limits_and_external_functions( let res = authorizer.authorize_with_limits(run_limits); //println!("authorizer world:\n{}", authorizer.print_world()); - let (_, _, _, policies) = authorizer.dump(); - let snapshot = authorizer.snapshot().unwrap(); - - let symbols = SymbolTable::from_symbols_and_public_keys( - snapshot.world.symbols, - snapshot - .world - .public_keys - .iter() - .map(PublicKeyData::from_proto) - .collect(), - ) - .unwrap(); + let facts_with_origin = authorizer.dump_facts_with_origins(); + let rules_with_origin = authorizer.dump_rules_with_origins(); + let checks_with_origin = authorizer.dump_checks_with_origins(); + let policies = authorizer.dump_policies(); let mut authorizer_facts = Vec::new(); let mut authorizer_rules = Vec::new(); let mut authorizer_checks = Vec::new(); - for (i, block) in snapshot.world.blocks.iter().enumerate() { - let mut rules: Vec = Vec::new(); - for rule in block.rules.iter() { - let r = - convert::proto_rule_to_token_rule(rule, snapshot.world.version.unwrap()).unwrap(); - rules.push(symbols.print_rule(&r.0)); - } - if !rules.is_empty() { - rules.sort(); - authorizer_rules.push(Rules { - origin: Some(i), - rules, - }); - } - - let mut checks = Vec::new(); - for check in block.checks.iter() { - let c = convert::proto_check_to_token_check(check, snapshot.world.version.unwrap()) - .unwrap(); - checks.push(symbols.print_check(&c)); - } - if !checks.is_empty() { - checks.sort(); - authorizer_checks.push(Checks { - origin: Some(i), - checks, - }); - } - } - - let mut rules: Vec = Vec::new(); - for rule in snapshot.world.authorizer_block.rules { - let r = convert::proto_rule_to_token_rule(&rule, snapshot.world.version.unwrap()).unwrap(); - rules.push(symbols.print_rule(&r.0)); - } - if !rules.is_empty() { + for (origin, rules) in rules_with_origin { + let mut rules: Vec = rules.into_iter().map(|r| r.to_string()).collect(); rules.sort(); authorizer_rules.push(Rules { - origin: Some(usize::MAX), + origin: Some(origin.unwrap_or(usize::MAX)), rules, }); } - let mut checks = Vec::new(); - for check in snapshot.world.authorizer_block.checks { - let c = - convert::proto_check_to_token_check(&check, snapshot.world.version.unwrap()).unwrap(); - checks.push(symbols.print_check(&c)); - } - if !checks.is_empty() { + for (origin, checks) in checks_with_origin { + let mut checks: Vec = checks.into_iter().map(|c| c.to_string()).collect(); checks.sort(); authorizer_checks.push(Checks { - origin: Some(usize::MAX), + origin: Some(origin.unwrap_or(usize::MAX)), checks, }); } - for factset in snapshot.world.generated_facts { - use biscuit_auth::format::schema::origin::Content; - let mut origin = BTreeSet::new(); - - for o in factset.origins { - match o.content.unwrap() { - Content::Authorizer(_) => origin.insert(None), - Content::Origin(i) => origin.insert(Some(i as usize)), - }; - } - - let mut facts = Vec::new(); - - for fact in factset.facts { - let f = convert::proto_fact_to_token_fact(&fact).unwrap(); - facts.push(symbols.print_fact(&f)); - } - if !facts.is_empty() { - facts.sort(); - authorizer_facts.push(Facts { origin, facts }); - } + for (origin, facts) in facts_with_origin { + let mut facts: Vec = facts.into_iter().map(|f| f.to_string()).collect(); + facts.sort(); + authorizer_facts.push(Facts { origin, facts }); } authorizer_facts.sort(); @@ -664,8 +593,8 @@ fn invalid_signature_format(target: &str, root: &PrivateKey, test: bool) -> Test let data = if test { load_testcase(target, &filename) } else { - let serialized = biscuit2.container(); - let mut proto = serialized.to_proto(); + let serialized = biscuit2.to_vec().unwrap(); + let mut proto = biscuit_proto::Biscuit::decode(&serialized[..]).unwrap(); proto.authority.signature.truncate(16); let mut data = Vec::new(); proto.encode(&mut data).unwrap(); @@ -715,8 +644,8 @@ fn random_block(target: &str, root: &PrivateKey, test: bool) -> TestResult { let data = if test { load_testcase(target, &filename) } else { - let serialized = biscuit2.container(); - let mut proto = serialized.to_proto(); + let serialized = biscuit2.to_vec().unwrap(); + let mut proto = biscuit_proto::Biscuit::decode(&serialized[..]).unwrap(); let arr: [u8; 32] = rng.gen(); proto.blocks[0].block = Vec::from(&arr[..]); let mut data = Vec::new(); @@ -767,8 +696,8 @@ fn invalid_signature(target: &str, root: &PrivateKey, test: bool) -> TestResult let data = if test { load_testcase(target, &filename) } else { - let serialized = biscuit2.container(); - let mut proto = serialized.to_proto(); + let serialized = biscuit2.to_vec().unwrap(); + let mut proto = biscuit_proto::Biscuit::decode(&serialized[..]).unwrap(); proto.authority.signature[0] += 1; let mut data = Vec::new(); proto.encode(&mut data).unwrap(); diff --git a/biscuit-auth/src/crypto/ed25519.rs b/biscuit-auth/src/crypto/ed25519.rs index 5ffcb574..2b2e8797 100644 --- a/biscuit-auth/src/crypto/ed25519.rs +++ b/biscuit-auth/src/crypto/ed25519.rs @@ -238,7 +238,7 @@ impl PartialEq for PublicKey { impl Hash for PublicKey { fn hash(&self, state: &mut H) { - (crate::format::schema::public_key::Algorithm::Ed25519 as i32).hash(state); + (biscuit_proto::public_key::Algorithm::Ed25519 as i32).hash(state); self.0.to_bytes().hash(state); } } diff --git a/biscuit-auth/src/crypto/mod.rs b/biscuit-auth/src/crypto/mod.rs index f96dd19e..7be670a9 100644 --- a/biscuit-auth/src/crypto/mod.rs +++ b/biscuit-auth/src/crypto/mod.rs @@ -24,7 +24,6 @@ use rand_core::{CryptoRng, RngCore}; use zeroize::Zeroizing; use crate::builder::Algorithm; -use crate::format::schema; use crate::format::ThirdPartyVerificationMode; use super::error; @@ -308,28 +307,6 @@ impl PublicKey { Self::from_bytes(&bytes, algorithm) } - pub fn from_proto(key: &schema::PublicKey) -> Result { - if key.algorithm == schema::public_key::Algorithm::Ed25519 as i32 { - Ok(PublicKey::Ed25519(ed25519::PublicKey::from_bytes( - &key.key, - )?)) - } else if key.algorithm == schema::public_key::Algorithm::Secp256r1 as i32 { - Ok(PublicKey::P256(p256::PublicKey::from_bytes(&key.key)?)) - } else { - Err(error::Format::DeserializationError(format!( - "deserialization error: unexpected key algorithm {}", - key.algorithm - ))) - } - } - - pub fn to_proto(&self) -> schema::PublicKey { - schema::PublicKey { - algorithm: self.algorithm() as i32, - key: self.to_bytes(), - } - } - #[cfg(feature = "pem")] pub fn from_der_with_algorithm( bytes: &[u8], diff --git a/biscuit-auth/src/crypto/p256.rs b/biscuit-auth/src/crypto/p256.rs index f41b572e..13f3cc2a 100644 --- a/biscuit-auth/src/crypto/p256.rs +++ b/biscuit-auth/src/crypto/p256.rs @@ -253,7 +253,7 @@ impl PublicKey { impl Hash for PublicKey { fn hash(&self, state: &mut H) { - (crate::format::schema::public_key::Algorithm::Secp256r1 as i32).hash(state); + (biscuit_proto::public_key::Algorithm::Secp256r1 as i32).hash(state); self.to_bytes().hash(state); } } diff --git a/biscuit-auth/src/datalog/expression.rs b/biscuit-auth/src/datalog/expression.rs index 4d57984a..8df63c44 100644 --- a/biscuit-auth/src/datalog/expression.rs +++ b/biscuit-auth/src/datalog/expression.rs @@ -8,10 +8,7 @@ use super::{MapKey, SymbolIndex, Term}; use super::{SymbolTable, TemporarySymbolTable}; use regex::Regex; use std::sync::Arc; -use std::{ - collections::HashMap, - convert::TryFrom, -}; +use std::{collections::HashMap, convert::TryFrom}; #[derive(Clone)] pub struct ExternFunc( diff --git a/biscuit-auth/src/datalog/mod.rs b/biscuit-auth/src/datalog/mod.rs index b951deaf..395bbd50 100644 --- a/biscuit-auth/src/datalog/mod.rs +++ b/biscuit-auth/src/datalog/mod.rs @@ -151,46 +151,48 @@ impl Rule { let variables = MatchedVariables::new(self.variables_set()); CombineIt::new(variables, &self.body, facts, symbols) - .map(move |(origin, variables)| { - let mut temporary_symbols = TemporarySymbolTable::new(symbols); - for e in self.expressions.iter() { - match e.evaluate(&variables, &mut temporary_symbols, extern_funcs) { - Ok(Term::Bool(true)) => {} - Ok(Term::Bool(false)) => return Ok((origin, variables, false)), - Ok(_) => return Err(error::Expression::InvalidType), - Err(e) => { - //println!("expr returned {:?}", res); - return Err(e); - } + .map(move |(origin, variables)| { + let mut temporary_symbols = TemporarySymbolTable::new(symbols); + for e in self.expressions.iter() { + match e.evaluate(&variables, &mut temporary_symbols, extern_funcs) { + Ok(Term::Bool(true)) => {} + Ok(Term::Bool(false)) => return Ok((origin, variables, false)), + Ok(_) => return Err(error::Expression::InvalidType), + Err(e) => { + //println!("expr returned {:?}", res); + return Err(e); } } - Ok((origin, variables, true)) - }).filter_map(move |res/*(mut origin,h, expression_res)*/| { - match res { - Ok((mut origin,h , expression_res)) => { - if expression_res { - let mut p = head.clone(); - for index in 0..p.terms.len() { - match &p.terms[index] { - Term::Variable(i) => match h.get(i) { - Some(val) => p.terms[index] = val.clone(), - None => { - // head variables should be bound in the body predicates - return None; - } - }, - _ => continue, - }; - } - - origin.insert(rule_origin); - Some(Ok((origin, Fact { predicate: p }))) - } else {None} - }, - Err(e) => Some(Err(e)) - } + } + Ok((origin, variables, true)) + }) + .filter_map(move |res /*(mut origin,h, expression_res)*/| { + match res { + Ok((mut origin, h, expression_res)) => { + if expression_res { + let mut p = head.clone(); + for index in 0..p.terms.len() { + match &p.terms[index] { + Term::Variable(i) => match h.get(i) { + Some(val) => p.terms[index] = val.clone(), + None => { + // head variables should be bound in the body predicates + return None; + } + }, + _ => continue, + }; + } - }) + origin.insert(rule_origin); + Some(Ok((origin, Fact { predicate: p }))) + } else { + None + } + } + Err(e) => Some(Err(e)), + } + }) } pub fn find_match( diff --git a/biscuit-auth/src/format/convert.rs b/biscuit-auth/src/format/convert.rs index a511b6ae..584e08ba 100644 --- a/biscuit-auth/src/format/convert.rs +++ b/biscuit-auth/src/format/convert.rs @@ -3,14 +3,12 @@ * SPDX-License-Identifier: Apache-2.0 */ //! helper functions for conversion between internal structures and Protobuf +use biscuit_proto::{Empty, MapEntry}; -use super::schema; use crate::builder::Convert; use crate::crypto::SerializePublicKey; use crate::datalog::*; use crate::error; -use crate::format::schema::Empty; -use crate::format::schema::MapEntry; use crate::token::public_keys::{PublicKeyData, PublicKeys}; use crate::token::Scope; use crate::token::{authorizer::AuthorizerPolicies, Block}; @@ -19,8 +17,8 @@ use crate::token::{DATALOG_3_1, DATALOG_3_2, DATALOG_3_3, MAX_SCHEMA_VERSION, MI use std::collections::BTreeMap; use std::collections::BTreeSet; -pub fn token_block_to_proto_block(input: &Block) -> schema::Block { - schema::Block { +pub fn token_block_to_proto_block(input: &Block) -> biscuit_proto::Block { + biscuit_proto::Block { symbols: input.symbols.strings(), context: input.context.clone(), version: Some(input.version), @@ -46,7 +44,7 @@ pub fn token_block_to_proto_block(input: &Block) -> schema::Block { } pub fn proto_block_to_token_block( - input: &schema::Block, + input: &biscuit_proto::Block, external_key: Option<&EK>, ) -> Result { let version = input.version.unwrap_or(0); @@ -77,7 +75,9 @@ pub fn proto_block_to_token_block( "deserialization error: check kinds are only supported on datalog v3.1+ blocks" .to_string(), )); - } else if version < DATALOG_3_3 && c.kind == Some(schema::check::Kind::Reject as i32) { + } else if version < DATALOG_3_3 + && c.kind == Some(biscuit_proto::check::Kind::Reject as i32) + { return Err(error::Format::DeserializationError( "deserialization error: reject if is only supported in datalog v3.3+" .to_string(), @@ -126,8 +126,8 @@ pub fn proto_block_to_token_block( }) } -pub fn token_block_to_proto_snapshot_block(input: &Block) -> schema::SnapshotBlock { - schema::SnapshotBlock { +pub fn token_block_to_proto_snapshot_block(input: &Block) -> biscuit_proto::SnapshotBlock { + biscuit_proto::SnapshotBlock { context: input.context.clone(), version: Some(input.version), facts: input.facts.iter().map(token_fact_to_proto_fact).collect(), @@ -147,7 +147,7 @@ pub fn token_block_to_proto_snapshot_block(input: &Block) -> schema::SnapshotBlo } pub fn proto_snapshot_block_to_token_block( - input: &schema::SnapshotBlock, + input: &biscuit_proto::SnapshotBlock, ) -> Result { let version = input.version.unwrap_or(0); if !(MIN_SCHEMA_VERSION..=MAX_SCHEMA_VERSION).contains(&version) { @@ -206,7 +206,9 @@ pub fn proto_snapshot_block_to_token_block( scopes, }) } -pub fn authorizer_to_proto_authorizer(input: &AuthorizerPolicies) -> schema::AuthorizerPolicies { +pub fn authorizer_to_proto_authorizer( + input: &AuthorizerPolicies, +) -> biscuit_proto::AuthorizerPolicies { let mut symbols = SymbolTable::default(); let facts = input @@ -236,7 +238,7 @@ pub fn authorizer_to_proto_authorizer(input: &AuthorizerPolicies) -> schema::Aut .map(|p| policy_to_proto_policy(p, &mut symbols)) .collect(); - schema::AuthorizerPolicies { + biscuit_proto::AuthorizerPolicies { symbols: symbols.strings(), version: Some(input.version), facts, @@ -247,7 +249,7 @@ pub fn authorizer_to_proto_authorizer(input: &AuthorizerPolicies) -> schema::Aut } pub fn proto_authorizer_to_authorizer( - input: &schema::AuthorizerPolicies, + input: &biscuit_proto::AuthorizerPolicies, ) -> Result { let version = input.version.unwrap_or(0); if !(MIN_SCHEMA_VERSION..=MAX_SCHEMA_VERSION).contains(&version) { @@ -299,22 +301,22 @@ pub fn proto_authorizer_to_authorizer( }) } -pub fn token_fact_to_proto_fact(input: &Fact) -> schema::Fact { - schema::Fact { +pub fn token_fact_to_proto_fact(input: &Fact) -> biscuit_proto::Fact { + biscuit_proto::Fact { predicate: token_predicate_to_proto_predicate(&input.predicate), } } -pub fn proto_fact_to_token_fact(input: &schema::Fact) -> Result { +pub fn proto_fact_to_token_fact(input: &biscuit_proto::Fact) -> Result { Ok(Fact { predicate: proto_predicate_to_token_predicate(&input.predicate)?, }) } -pub fn token_check_to_proto_check(input: &Check) -> schema::Check { - use schema::check::Kind; +pub fn token_check_to_proto_check(input: &Check) -> biscuit_proto::Check { + use biscuit_proto::check::Kind; - schema::Check { + biscuit_proto::Check { queries: input.queries.iter().map(token_rule_to_proto_rule).collect(), kind: match input.kind { crate::token::builder::CheckKind::One => None, @@ -325,7 +327,7 @@ pub fn token_check_to_proto_check(input: &Check) -> schema::Check { } pub fn proto_check_to_token_check( - input: &schema::Check, + input: &biscuit_proto::Check, version: u32, ) -> Result { let mut queries = vec![]; @@ -351,8 +353,8 @@ pub fn proto_check_to_token_check( pub fn policy_to_proto_policy( input: &crate::token::builder::Policy, symbols: &mut SymbolTable, -) -> schema::Policy { - schema::Policy { +) -> biscuit_proto::Policy { + biscuit_proto::Policy { queries: input .queries .iter() @@ -360,18 +362,18 @@ pub fn policy_to_proto_policy( .map(|r| token_rule_to_proto_rule(&r)) .collect(), kind: match input.kind { - crate::token::builder::PolicyKind::Allow => schema::policy::Kind::Allow as i32, - crate::token::builder::PolicyKind::Deny => schema::policy::Kind::Deny as i32, + crate::token::builder::PolicyKind::Allow => biscuit_proto::policy::Kind::Allow as i32, + crate::token::builder::PolicyKind::Deny => biscuit_proto::policy::Kind::Deny as i32, }, } } pub fn proto_policy_to_policy( - input: &schema::Policy, + input: &biscuit_proto::Policy, symbols: &SymbolTable, version: u32, ) -> Result { - use schema::policy::Kind; + use biscuit_proto::policy::Kind; let mut queries = vec![]; for q in input.queries.iter() { @@ -396,8 +398,8 @@ pub fn proto_policy_to_policy( Ok(crate::token::builder::Policy { queries, kind }) } -pub fn token_rule_to_proto_rule(input: &Rule) -> schema::Rule { - schema::Rule { +pub fn token_rule_to_proto_rule(input: &Rule) -> biscuit_proto::Rule { + biscuit_proto::Rule { head: token_predicate_to_proto_predicate(&input.head), body: input .body @@ -418,7 +420,7 @@ pub fn token_rule_to_proto_rule(input: &Rule) -> schema::Rule { } pub fn proto_rule_to_token_rule( - input: &schema::Rule, + input: &biscuit_proto::Rule, version: u32, ) -> Result<(Rule, Vec), error::Format> { let mut body = vec![]; @@ -453,15 +455,15 @@ pub fn proto_rule_to_token_rule( )) } -pub fn token_predicate_to_proto_predicate(input: &Predicate) -> schema::Predicate { - schema::Predicate { +pub fn token_predicate_to_proto_predicate(input: &Predicate) -> biscuit_proto::Predicate { + biscuit_proto::Predicate { name: input.name, terms: input.terms.iter().map(token_term_to_proto_id).collect(), } } pub fn proto_predicate_to_token_predicate( - input: &schema::Predicate, + input: &biscuit_proto::Predicate, ) -> Result { let mut terms = vec![]; @@ -475,55 +477,55 @@ pub fn proto_predicate_to_token_predicate( }) } -pub fn token_term_to_proto_id(input: &Term) -> schema::Term { - use schema::term::Content; +pub fn token_term_to_proto_id(input: &Term) -> biscuit_proto::Term { + use biscuit_proto::term::Content; match input { - Term::Variable(v) => schema::Term { + Term::Variable(v) => biscuit_proto::Term { content: Some(Content::Variable(*v)), }, - Term::Integer(i) => schema::Term { + Term::Integer(i) => biscuit_proto::Term { content: Some(Content::Integer(*i)), }, - Term::Str(s) => schema::Term { + Term::Str(s) => biscuit_proto::Term { content: Some(Content::String(*s)), }, - Term::Date(d) => schema::Term { + Term::Date(d) => biscuit_proto::Term { content: Some(Content::Date(*d)), }, - Term::Bytes(s) => schema::Term { + Term::Bytes(s) => biscuit_proto::Term { content: Some(Content::Bytes(s.clone())), }, - Term::Bool(b) => schema::Term { + Term::Bool(b) => biscuit_proto::Term { content: Some(Content::Bool(*b)), }, - Term::Set(s) => schema::Term { - content: Some(Content::Set(schema::TermSet { + Term::Set(s) => biscuit_proto::Term { + content: Some(Content::Set(biscuit_proto::TermSet { set: s.iter().map(token_term_to_proto_id).collect(), })), }, - Term::Null => schema::Term { + Term::Null => biscuit_proto::Term { content: Some(Content::Null(Empty {})), }, - Term::Array(a) => schema::Term { - content: Some(Content::Array(schema::Array { + Term::Array(a) => biscuit_proto::Term { + content: Some(Content::Array(biscuit_proto::Array { array: a.iter().map(token_term_to_proto_id).collect(), })), }, - Term::Map(m) => schema::Term { - content: Some(Content::Map(schema::Map { + Term::Map(m) => biscuit_proto::Term { + content: Some(Content::Map(biscuit_proto::Map { entries: m .iter() .map(|(key, term)| { let key = match key { - MapKey::Integer(i) => schema::MapKey { - content: Some(schema::map_key::Content::Integer(*i)), + MapKey::Integer(i) => biscuit_proto::MapKey { + content: Some(biscuit_proto::map_key::Content::Integer(*i)), }, - MapKey::Str(s) => schema::MapKey { - content: Some(schema::map_key::Content::String(*s)), + MapKey::Str(s) => biscuit_proto::MapKey { + content: Some(biscuit_proto::map_key::Content::String(*s)), }, }; - schema::MapEntry { + biscuit_proto::MapEntry { key, value: token_term_to_proto_id(term), } @@ -534,8 +536,8 @@ pub fn token_term_to_proto_id(input: &Term) -> schema::Term { } } -pub fn proto_id_to_token_term(input: &schema::Term) -> Result { - use schema::term::Content; +pub fn proto_id_to_token_term(input: &biscuit_proto::Term) -> Result { + use biscuit_proto::term::Content; match &input.content { None => Err(error::Format::DeserializationError( @@ -609,8 +611,8 @@ pub fn proto_id_to_token_term(input: &schema::Term) -> Result MapKey::Integer(i), - Some(schema::map_key::Content::String(s)) => MapKey::Str(s), + Some(biscuit_proto::map_key::Content::Integer(i)) => MapKey::Integer(i), + Some(biscuit_proto::map_key::Content::String(s)) => MapKey::Str(s), None => { return Err(error::Format::DeserializationError( "deserialization error: ID content enum is empty".to_string(), @@ -626,13 +628,13 @@ pub fn proto_id_to_token_term(input: &schema::Term) -> Result schema::Op { +fn token_op_to_proto_op(op: &Op) -> biscuit_proto::Op { let content = match op { - Op::Value(i) => schema::op::Content::Value(token_term_to_proto_id(i)), + Op::Value(i) => biscuit_proto::op::Content::Value(token_term_to_proto_id(i)), Op::Unary(u) => { - use schema::op_unary::Kind; + use biscuit_proto::op_unary::Kind; - schema::op::Content::Unary(schema::OpUnary { + biscuit_proto::op::Content::Unary(biscuit_proto::OpUnary { kind: match u { Unary::Negate => Kind::Negate, Unary::Parens => Kind::Parens, @@ -647,9 +649,9 @@ fn token_op_to_proto_op(op: &Op) -> schema::Op { }) } Op::Binary(b) => { - use schema::op_binary::Kind; + use biscuit_proto::op_binary::Kind; - schema::op::Content::Binary(schema::OpBinary { + biscuit_proto::op::Content::Binary(biscuit_proto::OpBinary { kind: match b { Binary::LessThan => Kind::LessThan, Binary::GreaterThan => Kind::GreaterThan, @@ -688,25 +690,25 @@ fn token_op_to_proto_op(op: &Op) -> schema::Op { }, }) } - Op::Closure(params, ops) => schema::op::Content::Closure(schema::OpClosure { + Op::Closure(params, ops) => biscuit_proto::op::Content::Closure(biscuit_proto::OpClosure { params: params.clone(), ops: ops.iter().map(token_op_to_proto_op).collect(), }), }; - schema::Op { + biscuit_proto::Op { content: Some(content), } } -pub fn token_expression_to_proto_expression(input: &Expression) -> schema::Expression { - schema::Expression { +pub fn token_expression_to_proto_expression(input: &Expression) -> biscuit_proto::Expression { + biscuit_proto::Expression { ops: input.ops.iter().map(token_op_to_proto_op).collect(), } } -fn proto_op_to_token_op(op: &schema::Op) -> Result { - use schema::{op, op_binary, op_unary}; +fn proto_op_to_token_op(op: &biscuit_proto::Op) -> Result { + use biscuit_proto::{op, op_binary, op_unary}; Ok(match op.content.as_ref() { Some(op::Content::Value(id)) => Op::Value(proto_id_to_token_term(id)?), Some(op::Content::Unary(u)) => { @@ -805,7 +807,7 @@ fn proto_op_to_token_op(op: &schema::Op) -> Result { } pub fn proto_expression_to_token_expression( - input: &schema::Expression, + input: &biscuit_proto::Expression, ) -> Result { let mut ops = Vec::new(); @@ -816,28 +818,29 @@ pub fn proto_expression_to_token_expression( Ok(Expression { ops }) } -pub fn token_scope_to_proto_scope(input: &Scope) -> schema::Scope { - schema::Scope { +pub fn token_scope_to_proto_scope(input: &Scope) -> biscuit_proto::Scope { + use biscuit_proto::scope; + biscuit_proto::Scope { content: Some(match input { crate::token::Scope::Authority => { - schema::scope::Content::ScopeType(schema::scope::ScopeType::Authority as i32) + scope::Content::ScopeType(scope::ScopeType::Authority as i32) } crate::token::Scope::Previous => { - schema::scope::Content::ScopeType(schema::scope::ScopeType::Previous as i32) + scope::Content::ScopeType(scope::ScopeType::Previous as i32) } - crate::token::Scope::PublicKey(i) => schema::scope::Content::PublicKey(*i as i64), + crate::token::Scope::PublicKey(i) => scope::Content::PublicKey(*i as i64), }), } } -pub fn proto_scope_to_token_scope(input: &schema::Scope) -> Result { +pub fn proto_scope_to_token_scope(input: &biscuit_proto::Scope) -> Result { //FIXME: check that the referenced public key index exists in the public key table match input.content.as_ref() { Some(content) => match content { - schema::scope::Content::ScopeType(i) => { - if *i == schema::scope::ScopeType::Authority as i32 { + biscuit_proto::scope::Content::ScopeType(i) => { + if *i == biscuit_proto::scope::ScopeType::Authority as i32 { Ok(Scope::Authority) - } else if *i == schema::scope::ScopeType::Previous as i32 { + } else if *i == biscuit_proto::scope::ScopeType::Previous as i32 { Ok(Scope::Previous) } else { Err(error::Format::DeserializationError(format!( @@ -845,7 +848,7 @@ pub fn proto_scope_to_token_scope(input: &schema::Scope) -> Result Ok(Scope::PublicKey(*i as u64)), + biscuit_proto::scope::Content::PublicKey(i) => Ok(Scope::PublicKey(*i as u64)), }, None => Err(error::Format::DeserializationError( "deserialization error: expected `content` field in Scope".to_string(), @@ -853,14 +856,16 @@ pub fn proto_scope_to_token_scope(input: &schema::Scope) -> Result(key: &K) -> schema::PublicKey { - schema::PublicKey { - algorithm: schema::public_key::Algorithm::from(key.algorithm()) as i32, +pub fn public_key_to_proto(key: &K) -> biscuit_proto::PublicKey { + biscuit_proto::PublicKey { + algorithm: biscuit_proto::public_key::Algorithm::from(key.algorithm()) as i32, key: key.to_bytes(), } } -pub fn public_key_from_proto(key: &schema::PublicKey) -> Result { +pub fn public_key_from_proto( + key: &biscuit_proto::PublicKey, +) -> Result { let algorithm = crate::Algorithm::from(key.algorithm()); K::from_bytes_and_algorithm(algorithm, &key.key) } diff --git a/biscuit-auth/src/format/mod.rs b/biscuit-auth/src/format/mod.rs index 32f5af4c..e23bde5c 100644 --- a/biscuit-auth/src/format/mod.rs +++ b/biscuit-auth/src/format/mod.rs @@ -24,12 +24,7 @@ use crate::token::RootKeyProvider; use crate::token::DATALOG_3_3; use crate::token::public_keys::PublicKeyData; -/// Structures generated from the Protobuf schema -pub mod schema; /*{ - include!(concat!(env!("OUT_DIR"), "/biscuit.format.schema.rs")); - }*/ - -pub mod convert; +pub(crate) mod convert; use self::convert::*; @@ -85,7 +80,7 @@ impl SerializedBiscuit { slice: &[u8], verification_mode: ThirdPartyVerificationMode, ) -> Result { - let data = schema::Biscuit::decode(slice).map_err(|e| { + let data = biscuit_proto::Biscuit::decode(slice).map_err(|e| { error::Format::DeserializationError(format!("deserialization error: {e:?}")) })?; @@ -150,10 +145,10 @@ impl SerializedBiscuit { "could not find proof".to_string(), )) } - Some(schema::proof::Content::NextSecret(v)) => { + Some(biscuit_proto::proof::Content::NextSecret(v)) => { Proof::Secret(K::from_bytes_and_algorithm(next_key_algorithm, &v)?) } - Some(schema::proof::Content::FinalSignature(v)) => { + Some(biscuit_proto::proof::Content::FinalSignature(v)) => { let signature = Signature::from_vec(v); Proof::Seal(signature) @@ -173,8 +168,8 @@ impl SerializedBiscuit { pub(crate) fn extract_blocks( &self, symbols: &mut SymbolTable, - ) -> Result<(schema::Block, Vec), error::Token> { - let authority = schema::Block::decode(&self.authority.data[..]).map_err(|e| { + ) -> Result<(biscuit_proto::Block, Vec), error::Token> { + let authority = biscuit_proto::Block::decode(&self.authority.data[..]).map_err(|e| { error::Token::Format(error::Format::BlockDeserializationError(format!( "error deserializing authority block: {e:?}" ))) @@ -190,7 +185,7 @@ impl SerializedBiscuit { let mut blocks = vec![]; for block in self.blocks.iter() { - let deser = schema::Block::decode(&block.data[..]).map_err(|e| { + let deser = biscuit_proto::Block::decode(&block.data[..]).map_err(|e| { error::Token::Format(error::Format::BlockDeserializationError(format!( "error deserializing block: {e:?}" ))) @@ -211,8 +206,8 @@ impl SerializedBiscuit { } /// serializes the token - pub fn to_proto(&self) -> schema::Biscuit { - let authority = schema::SignedBlock { + pub(crate) fn to_proto(&self) -> biscuit_proto::Biscuit { + let authority = biscuit_proto::SignedBlock { block: self.authority.data.clone(), next_key: convert::public_key_to_proto(&self.authority.next_key), signature: self.authority.signature.to_bytes().to_vec(), @@ -226,12 +221,12 @@ impl SerializedBiscuit { let mut blocks = Vec::new(); for block in &self.blocks { - let b = schema::SignedBlock { + let b = biscuit_proto::SignedBlock { block: block.data.clone(), next_key: convert::public_key_to_proto(&block.next_key), signature: block.signature.to_bytes().to_vec(), external_signature: block.external_signature.as_ref().map(|external_signature| { - schema::ExternalSignature { + biscuit_proto::ExternalSignature { signature: external_signature.signature.to_bytes().to_vec(), public_key: convert::public_key_to_proto(&external_signature.public_key), } @@ -246,16 +241,16 @@ impl SerializedBiscuit { blocks.push(b); } - schema::Biscuit { + biscuit_proto::Biscuit { root_key_id: self.root_key_id, authority, blocks, - proof: schema::Proof { + proof: biscuit_proto::Proof { content: match &self.proof { - Proof::Seal(signature) => Some(schema::proof::Content::FinalSignature( + Proof::Seal(signature) => Some(biscuit_proto::proof::Content::FinalSignature( signature.to_bytes().to_vec(), )), - Proof::Secret(private) => Some(schema::proof::Content::NextSecret( + Proof::Secret(private) => Some(biscuit_proto::proof::Content::NextSecret( private.to_bytes().to_vec(), )), }, @@ -582,8 +577,6 @@ where #[cfg(test)] mod tests { - use std::io::Read; - use crate::{ builder::Algorithm, crypto::{ExternalSignature, Signature}, @@ -592,32 +585,6 @@ mod tests { PrivateKey, }; - #[test] - fn proto() { - // somehow when building under cargo-tarpaulin, OUT_DIR is not set - let out_dir = match std::env::var("OUT_DIR") { - Ok(dir) => dir, - Err(_) => return, - }; - prost_build::compile_protos(&["src/format/schema.proto"], &["src/"]).unwrap(); - let mut file = std::fs::File::open(format!("{out_dir}/biscuit.format.schema.rs")).unwrap(); - let mut contents = String::new(); - file.read_to_string(&mut contents).unwrap(); - - let commited_schema = include_str!("schema.rs"); - - if contents != commited_schema { - println!( - "{}", - colored_diff::PrettyDifference { - expected: &contents, - actual: commited_schema - } - ); - panic!(); - } - } - #[test] fn test_block_signature_version() { assert_eq!( diff --git a/biscuit-auth/src/token/authorizer.rs b/biscuit-auth/src/token/authorizer.rs index 437374eb..dbdf4cdf 100644 --- a/biscuit-auth/src/token/authorizer.rs +++ b/biscuit-auth/src/token/authorizer.rs @@ -88,7 +88,7 @@ impl Authorizer { } } - /// creates an `Authorizer` from a serialized [crate::format::schema::AuthorizerPolicies] + /// creates an `Authorizer` from a serialized authorizer pub fn from(data: &[u8]) -> Result { AuthorizerPolicies::deserialize(data)?.try_into() } @@ -641,12 +641,12 @@ impl Authorizer { } } - /// prints the content of the authorizer + /// Prints the content of the authorizer. pub fn print_world(&self) -> String { self.to_string() } - /// returns all of the data loaded in the authorizer + /// Returns all of the data loaded in the authorizer. pub fn dump(&self) -> (Vec, Vec, Vec, Vec) { let mut checks = self.authorizer_block_builder.checks.clone(); if let Some(blocks) = &self.blocks { @@ -679,6 +679,79 @@ impl Authorizer { (facts, rules, checks, self.policies.clone()) } + /// Returns all facts loaded in the authorizer, grouped by origin. + pub fn dump_facts_with_origins(&self) -> Vec<(Vec>, Vec)> { + self.world + .facts + .inner + .iter() + .filter_map(|(origin, facts)| { + if facts.is_empty() { + return None; + } + let origin_set: Vec> = origin + .inner + .iter() + .map(|o| if *o == usize::MAX { None } else { Some(*o) }) + .collect(); + let converted: Vec = facts + .iter() + .map(|f| Fact::convert_from(f, &self.symbols).unwrap()) + .collect(); + Some((origin_set, converted)) + }) + .collect() + } + + /// Returns all rules loaded in the authorizer, grouped by origin block index + pub fn dump_rules_with_origins(&self) -> Vec<(Option, Vec)> { + let mut rules = Vec::new(); + if let Some(blocks) = &self.blocks { + for (i, block) in blocks.iter().enumerate() { + let block_rules: Vec = block + .rules + .iter() + .map(|r| Rule::convert_from(r, &self.symbols).unwrap()) + .collect(); + if !block_rules.is_empty() { + rules.push((Some(i), block_rules)); + } + } + } + let authorizer_rules = self.authorizer_block_builder.rules.clone(); + if !authorizer_rules.is_empty() { + rules.push((None, authorizer_rules)); + } + rules + } + + /// Returns all checks loaded in the authorizer, grouped by origin block index + pub fn dump_checks_with_origins(&self) -> Vec<(Option, Vec)> { + let mut checks = Vec::new(); + if let Some(blocks) = &self.blocks { + for (i, block) in blocks.iter().enumerate() { + let block_checks: Vec = block + .checks + .iter() + .map(|c| Check::convert_from(c, &self.symbols).unwrap()) + .collect(); + if !block_checks.is_empty() { + checks.push((Some(i), block_checks)); + } + } + } + let authorizer_checks = self.authorizer_block_builder.checks.clone(); + if !authorizer_checks.is_empty() { + checks.push((None, authorizer_checks)); + } + checks + } + + /// Returns all policies loaded in the authorizer. + pub fn dump_policies(&self) -> Vec { + self.policies.clone() + } + pub fn dump_code(&self) -> String { let (facts, rules, checks, policies) = self.dump(); let mut f = String::new(); @@ -898,7 +971,7 @@ impl AuthorizerPolicies { } pub fn deserialize(data: &[u8]) -> Result { - let data = crate::format::schema::AuthorizerPolicies::decode(data).map_err(|e| { + let data = biscuit_proto::AuthorizerPolicies::decode(data).map_err(|e| { error::Format::DeserializationError(format!("deserialization error: {e:?}")) })?; diff --git a/biscuit-auth/src/token/authorizer/snapshot.rs b/biscuit-auth/src/token/authorizer/snapshot.rs index e87f7a3b..a06d00c0 100644 --- a/biscuit-auth/src/token/authorizer/snapshot.rs +++ b/biscuit-auth/src/token/authorizer/snapshot.rs @@ -2,6 +2,7 @@ * Copyright (c) 2019 Geoffroy Couprie and Contributors to the Eclipse Foundation. * SPDX-License-Identifier: Apache-2.0 */ +use biscuit_proto::GeneratedFacts; use prost::Message; use std::{collections::HashMap, time::Duration}; @@ -9,21 +10,20 @@ use crate::{ builder::{load_and_translate_block, BlockBuilder, Convert, Policy}, datalog::{Origin, RunLimits, TrustedOrigins}, error, - format::{ - convert::{ - policy_to_proto_policy, proto_fact_to_token_fact, proto_policy_to_policy, - proto_snapshot_block_to_token_block, token_block_to_proto_snapshot_block, - token_fact_to_proto_fact, - }, - schema::{self, GeneratedFacts}, + format::convert::{ + policy_to_proto_policy, proto_fact_to_token_fact, proto_policy_to_policy, + proto_snapshot_block_to_token_block, token_block_to_proto_snapshot_block, + token_fact_to_proto_fact, }, token::{default_symbol_table, MAX_SCHEMA_VERSION, MIN_SCHEMA_VERSION}, }; use crate::token::public_keys::PublicKeyData; impl super::Authorizer { - pub fn from_snapshot(input: schema::AuthorizerSnapshot) -> Result { - let schema::AuthorizerSnapshot { + pub(crate) fn from_snapshot( + input: biscuit_proto::AuthorizerSnapshot, + ) -> Result { + let biscuit_proto::AuthorizerSnapshot { limits, execution_time, world, @@ -171,7 +171,7 @@ impl super::Authorizer { } pub fn from_raw_snapshot(input: &[u8]) -> Result { - let snapshot = schema::AuthorizerSnapshot::decode(input).map_err(|e| { + let snapshot = biscuit_proto::AuthorizerSnapshot::decode(input).map_err(|e| { error::Format::DeserializationError(format!("deserialization error: {e:?}")) })?; Self::from_snapshot(snapshot) @@ -182,7 +182,7 @@ impl super::Authorizer { Self::from_raw_snapshot(&bytes) } - pub fn snapshot(&self) -> Result { + pub(crate) fn snapshot(&self) -> Result { let mut symbols = default_symbol_table(); let authorizer_policies = self @@ -233,7 +233,7 @@ impl super::Authorizer { }) .collect::, error::Format>>()?; - let world = schema::AuthorizerWorld { + let world = biscuit_proto::AuthorizerWorld { version: Some(MAX_SCHEMA_VERSION), symbols: symbols.strings(), public_keys: symbols @@ -249,10 +249,10 @@ impl super::Authorizer { iterations: self.world.iterations, }; - Ok(schema::AuthorizerSnapshot { + Ok(biscuit_proto::AuthorizerSnapshot { world, execution_time: self.execution_time.unwrap_or_default().as_nanos() as u64, - limits: schema::RunLimits { + limits: biscuit_proto::RunLimits { max_facts: self.limits.max_facts, max_iterations: self.limits.max_iterations, max_time: self.limits.max_time.as_nanos() as u64, @@ -275,18 +275,20 @@ impl super::Authorizer { } } -pub(crate) fn authorizer_origin_to_proto_origin(origin: &Origin) -> Vec { +pub(crate) fn authorizer_origin_to_proto_origin(origin: &Origin) -> Vec { origin .inner .iter() .map(|o| { if *o == usize::MAX { - schema::Origin { - content: Some(schema::origin::Content::Authorizer(schema::Empty {})), + biscuit_proto::Origin { + content: Some(biscuit_proto::origin::Content::Authorizer( + biscuit_proto::Empty {}, + )), } } else { - schema::Origin { - content: Some(schema::origin::Content::Origin(*o as u32)), + biscuit_proto::Origin { + content: Some(biscuit_proto::origin::Content::Origin(*o as u32)), } } }) @@ -294,16 +296,16 @@ pub(crate) fn authorizer_origin_to_proto_origin(origin: &Origin) -> Vec Result { let mut new_origin = Origin::default(); for origin in origins { match origin.content { - Some(schema::origin::Content::Authorizer(schema::Empty {})) => { + Some(biscuit_proto::origin::Content::Authorizer(biscuit_proto::Empty {})) => { new_origin.insert(usize::MAX) } - Some(schema::origin::Content::Origin(o)) => new_origin.insert(o as usize), + Some(biscuit_proto::origin::Content::Origin(o)) => new_origin.insert(o as usize), _ => { return Err(error::Format::DeserializationError( "invalid origin".to_string(), diff --git a/biscuit-auth/src/token/builder/algorithm.rs b/biscuit-auth/src/token/builder/algorithm.rs index 3d5d956a..b0c84070 100644 --- a/biscuit-auth/src/token/builder/algorithm.rs +++ b/biscuit-auth/src/token/builder/algorithm.rs @@ -76,20 +76,20 @@ impl From for biscuit_parser::builder::Algorithm { } } -impl From for Algorithm { - fn from(value: crate::format::schema::public_key::Algorithm) -> Algorithm { +impl From for Algorithm { + fn from(value: biscuit_proto::public_key::Algorithm) -> Algorithm { match value { - crate::format::schema::public_key::Algorithm::Ed25519 => Algorithm::Ed25519, - crate::format::schema::public_key::Algorithm::Secp256r1 => Algorithm::Secp256r1, + biscuit_proto::public_key::Algorithm::Ed25519 => Algorithm::Ed25519, + biscuit_proto::public_key::Algorithm::Secp256r1 => Algorithm::Secp256r1, } } } -impl From for crate::format::schema::public_key::Algorithm { - fn from(value: Algorithm) -> crate::format::schema::public_key::Algorithm { +impl From for biscuit_proto::public_key::Algorithm { + fn from(value: Algorithm) -> biscuit_proto::public_key::Algorithm { match value { - Algorithm::Ed25519 => crate::format::schema::public_key::Algorithm::Ed25519, - Algorithm::Secp256r1 => crate::format::schema::public_key::Algorithm::Secp256r1, + Algorithm::Ed25519 => biscuit_proto::public_key::Algorithm::Ed25519, + Algorithm::Secp256r1 => biscuit_proto::public_key::Algorithm::Secp256r1, } } } diff --git a/biscuit-auth/src/token/builder/authorizer.rs b/biscuit-auth/src/token/builder/authorizer.rs index 8ca2b56c..48c56c98 100644 --- a/biscuit-auth/src/token/builder/authorizer.rs +++ b/biscuit-auth/src/token/builder/authorizer.rs @@ -20,12 +20,9 @@ use crate::{ builder_ext::{AuthorizerExt, BuilderExt}, datalog::{ExternFunc, Origin, RunLimits, SymbolTable, TrustedOrigins, World}, error, - format::{ - convert::{ - policy_to_proto_policy, proto_policy_to_policy, proto_snapshot_block_to_token_block, - token_block_to_proto_snapshot_block, - }, - schema, + format::convert::{ + policy_to_proto_policy, proto_policy_to_policy, proto_snapshot_block_to_token_block, + token_block_to_proto_snapshot_block, }, token::{self, default_symbol_table, Block, MAX_SCHEMA_VERSION, MIN_SCHEMA_VERSION}, Authorizer, AuthorizerLimits, Biscuit, @@ -552,8 +549,10 @@ impl AuthorizerExt for AuthorizerBuilder { } impl AuthorizerBuilder { - pub fn from_snapshot(input: schema::AuthorizerSnapshot) -> Result { - let schema::AuthorizerSnapshot { + pub(crate) fn from_snapshot( + input: biscuit_proto::AuthorizerSnapshot, + ) -> Result { + let biscuit_proto::AuthorizerSnapshot { limits, execution_time, world, @@ -633,7 +632,7 @@ impl AuthorizerBuilder { } pub fn from_raw_snapshot(input: &[u8]) -> Result { - let snapshot = schema::AuthorizerSnapshot::decode(input).map_err(|e| { + let snapshot = biscuit_proto::AuthorizerSnapshot::decode(input).map_err(|e| { error::Format::DeserializationError(format!("deserialization error: {e:?}")) })?; Self::from_snapshot(snapshot) @@ -644,7 +643,7 @@ impl AuthorizerBuilder { Self::from_raw_snapshot(&bytes) } - pub fn snapshot(&self) -> Result { + pub(crate) fn snapshot(&self) -> Result { let mut symbols = default_symbol_table(); let authorizer_policies = self @@ -666,7 +665,7 @@ impl AuthorizerBuilder { let generated_facts = vec![]; - let world = schema::AuthorizerWorld { + let world = biscuit_proto::AuthorizerWorld { version: Some(MAX_SCHEMA_VERSION), symbols: symbols.strings(), public_keys: symbols @@ -682,10 +681,10 @@ impl AuthorizerBuilder { iterations: 0, }; - Ok(schema::AuthorizerSnapshot { + Ok(biscuit_proto::AuthorizerSnapshot { world, execution_time: 0u64, - limits: schema::RunLimits { + limits: biscuit_proto::RunLimits { max_facts: self.limits.max_facts, max_iterations: self.limits.max_iterations, max_time: self.limits.max_time.as_nanos() as u64, diff --git a/biscuit-auth/src/token/mod.rs b/biscuit-auth/src/token/mod.rs index 76419d14..71d40c5b 100644 --- a/biscuit-auth/src/token/mod.rs +++ b/biscuit-auth/src/token/mod.rs @@ -8,6 +8,7 @@ use std::iter::once; use std::rc::Rc; use std::sync::Arc; +use biscuit_proto::ThirdPartyBlockContents; use builder::{BiscuitBuilder, BlockBuilder}; use prost::Message; use rand_core::{CryptoRng, RngCore}; @@ -18,7 +19,6 @@ use super::error; use super::format::SerializedBiscuit; use crate::crypto::{self, PrivateKey, PublicKey, Signature, SerializePrivateKey, Verify, Sign}; use crate::format::convert::{proto_block_to_token_block, public_key_from_proto}; -use crate::format::schema::{self, ThirdPartyBlockContents}; use crate::format::{ThirdPartyVerificationMode, THIRD_PARTY_SIGNATURE_VERSION}; use authorizer::Authorizer; @@ -84,8 +84,8 @@ pub fn default_symbol_table() -> SymbolTable { #[derive(Clone)] pub struct Biscuit { pub(crate) root_key_id: Option, - pub(crate) authority: schema::Block, - pub(crate) blocks: Vec, + pub(crate) authority: biscuit_proto::Block, + pub(crate) blocks: Vec, pub(crate) symbols: SymbolTable, pub(crate) container: SerializedBiscuit, } @@ -294,11 +294,12 @@ impl Biscuit { symbols.public_keys.extend(&authority.public_keys)?; - let authority = schema::Block::decode(&container.authority.data[..]).map_err(|e| { - error::Token::Format(error::Format::BlockDeserializationError(format!( - "error deserializing block: {e:?}" - ))) - })?; + let authority = + biscuit_proto::Block::decode(&container.authority.data[..]).map_err(|e| { + error::Token::Format(error::Format::BlockDeserializationError(format!( + "error deserializing block: {e:?}" + ))) + })?; Ok(Biscuit { root_key_id, @@ -385,7 +386,7 @@ impl Biscuit { symbols.extend(&block.symbols)?; symbols.public_keys.extend(&block.public_keys)?; - let deser = schema::Block::decode( + let deser = biscuit_proto::Block::decode( &container .blocks .last() @@ -469,7 +470,7 @@ impl Biscuit { ThirdPartyVerificationMode::PreviousSignatureHashing, )?; - let block = schema::Block::decode(&payload[..]).map_err(|e| { + let block = biscuit_proto::Block::decode(&payload[..]).map_err(|e| { error::Token::Format(error::Format::DeserializationError(format!( "deserialization error: {e:?}" ))) diff --git a/biscuit-auth/src/token/public_keys.rs b/biscuit-auth/src/token/public_keys.rs index aa0cefd3..82ea1630 100644 --- a/biscuit-auth/src/token/public_keys.rs +++ b/biscuit-auth/src/token/public_keys.rs @@ -9,7 +9,6 @@ use std::str::FromStr; use nom::Finish; use crate::crypto::SerializePublicKey; -use crate::format::schema; use crate::{Algorithm, error}; #[derive(Default, Clone, Debug, PartialEq, Eq)] @@ -109,16 +108,16 @@ impl PublicKeyData { PublicKeyData { algorithm, key } } - pub fn from_proto(key: &schema::PublicKey) -> PublicKeyData { + pub(crate) fn from_proto(key: &biscuit_proto::PublicKey) -> PublicKeyData { PublicKeyData { algorithm: key.algorithm().into(), key: key.key.clone(), } } - pub(crate) fn to_proto(&self) -> schema::PublicKey { - schema::PublicKey { - algorithm: schema::public_key::Algorithm::from(self.algorithm) as i32, + pub(crate) fn to_proto(&self) -> biscuit_proto::PublicKey { + biscuit_proto::PublicKey { + algorithm: biscuit_proto::public_key::Algorithm::from(self.algorithm) as i32, key: self.key.clone(), } } diff --git a/biscuit-auth/src/token/third_party.rs b/biscuit-auth/src/token/third_party.rs index 6709adc3..5564cd50 100644 --- a/biscuit-auth/src/token/third_party.rs +++ b/biscuit-auth/src/token/third_party.rs @@ -15,7 +15,7 @@ use crate::{ error, format::{ convert::{public_key_to_proto, token_block_to_proto_block}, - schema, SerializedBiscuit, + SerializedBiscuit, }, }; @@ -48,7 +48,7 @@ impl ThirdPartyRequest { pub fn serialize(&self) -> Result, error::Token> { let previous_signature = self.previous_signature.clone(); - let request = schema::ThirdPartyBlockRequest { + let request = biscuit_proto::ThirdPartyBlockRequest { legacy_previous_key: None, legacy_public_keys: Vec::new(), previous_signature, @@ -67,7 +67,7 @@ impl ThirdPartyRequest { } pub fn deserialize(slice: &[u8]) -> Result { - let data = schema::ThirdPartyBlockRequest::decode(slice).map_err(|e| { + let data = biscuit_proto::ThirdPartyBlockRequest::decode(slice).map_err(|e| { error::Format::DeserializationError(format!("deserialization error: {e:?}")) })?; @@ -122,9 +122,9 @@ impl ThirdPartyRequest { let signature = private_key.sign(&signed_payload)?; let public_key = private_key.public(); - let content = schema::ThirdPartyBlockContents { + let content = biscuit_proto::ThirdPartyBlockContents { payload, - external_signature: schema::ExternalSignature { + external_signature: biscuit_proto::ExternalSignature { signature: signature.to_bytes().to_vec(), public_key: public_key_to_proto(&public_key), }, @@ -139,7 +139,7 @@ impl ThirdPartyRequest { /// this must be integrated with the token that created the [`ThirdPartyRequest`] /// using [`Biscuit::append_third_party`](crate::Biscuit::append_third_party) #[derive(Clone, Debug)] -pub struct ThirdPartyBlock(pub(crate) schema::ThirdPartyBlockContents); +pub struct ThirdPartyBlock(pub(crate) biscuit_proto::ThirdPartyBlockContents); impl ThirdPartyBlock { pub fn serialize(&self) -> Result, error::Token> { diff --git a/biscuit-auth/src/token/unverified.rs b/biscuit-auth/src/token/unverified.rs index 64917460..0cfd6278 100644 --- a/biscuit-auth/src/token/unverified.rs +++ b/biscuit-auth/src/token/unverified.rs @@ -4,6 +4,7 @@ */ use std::fmt::{self, Debug, Formatter}; +use biscuit_proto::public_key::Algorithm; use prost::Message; use super::{default_symbol_table, Biscuit, Block}; @@ -14,11 +15,7 @@ use crate::{ crypto::{self, PrivateKey, PublicKey, Signature}, datalog::SymbolTable, error, - format::{ - convert::proto_block_to_token_block, - schema::{self, public_key::Algorithm}, - SerializedBiscuit, - }, + format::{convert::proto_block_to_token_block, SerializedBiscuit}, token::{ThirdPartyBlockContents, ThirdPartyRequest}, RootKeyProvider, }; @@ -32,8 +29,8 @@ use crate::{ /// and then used for authorization #[derive(Clone)] pub struct UnverifiedBiscuit { - pub(crate) authority: schema::Block, - pub(crate) blocks: Vec, + pub(crate) authority: biscuit_proto::Block, + pub(crate) blocks: Vec, pub(crate) symbols: SymbolTable, container: SerializedBiscuit, } @@ -192,7 +189,7 @@ impl UnverifiedBiscuit { symbols.extend(&block.symbols)?; symbols.public_keys.extend(&block.public_keys)?; - let deser = schema::Block::decode( + let deser = biscuit_proto::Block::decode( &container .blocks .last() @@ -332,7 +329,7 @@ impl UnverifiedBiscuit { let ThirdPartyBlockContents { payload, external_signature, - } = schema::ThirdPartyBlockContents::decode(slice).map_err(|e| { + } = biscuit_proto::ThirdPartyBlockContents::decode(slice).map_err(|e| { error::Format::DeserializationError(format!("deserialization error: {e:?}")) })?; @@ -353,7 +350,7 @@ impl UnverifiedBiscuit { let signature = Signature::from_vec(external_signature.signature); - let block = schema::Block::decode(&payload[..]).map_err(|e| { + let block = biscuit_proto::Block::decode(&payload[..]).map_err(|e| { error::Token::Format(error::Format::DeserializationError(format!( "deserialization error: {e:?}" ))) diff --git a/biscuit-capi/src/lib.rs b/biscuit-capi/src/lib.rs index 15e8f1be..ae6bf3aa 100644 --- a/biscuit-capi/src/lib.rs +++ b/biscuit-capi/src/lib.rs @@ -374,10 +374,8 @@ pub unsafe extern "C" fn key_pair_deserialize( let input_slice = std::slice::from_raw_parts_mut(buffer_ptr, 32); let algorithm = match algorithm { - SignatureAlgorithm::Ed25519 => biscuit_auth::format::schema::public_key::Algorithm::Ed25519, - SignatureAlgorithm::Secp256r1 => { - biscuit_auth::format::schema::public_key::Algorithm::Secp256r1 - } + SignatureAlgorithm::Ed25519 => biscuit_auth::builder::Algorithm::Ed25519, + SignatureAlgorithm::Secp256r1 => biscuit_auth::builder::Algorithm::Secp256r1, }; match biscuit_auth::PrivateKey::from_bytes(input_slice, algorithm.into()).ok() { diff --git a/biscuit-proto/Cargo.toml b/biscuit-proto/Cargo.toml new file mode 100644 index 00000000..75623d5a --- /dev/null +++ b/biscuit-proto/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "biscuit-proto" +version = "0.1.0" +description = "Protobuf types for biscuits" +authors = ["Geoffroy Couprie "] +edition = "2018" +license = "Apache-2.0" +homepage = "https://github.com/biscuit-auth/biscuit" +repository = "https://github.com/biscuit-auth/biscuit-rust" + +[dependencies] +prost = "0.10" + +[dev-dependencies] +prost-build = "0.10" +colored-diff = "0.2.3" diff --git a/biscuit-auth/src/format/schema.rs b/biscuit-proto/src/lib.rs similarity index 67% rename from biscuit-auth/src/format/schema.rs rename to biscuit-proto/src/lib.rs index 45dc20a7..c33a4d95 100644 --- a/biscuit-auth/src/format/schema.rs +++ b/biscuit-proto/src/lib.rs @@ -1,39 +1,39 @@ #[derive(Clone, PartialEq, ::prost::Message)] pub struct Biscuit { - #[prost(uint32, optional, tag="1")] + #[prost(uint32, optional, tag = "1")] pub root_key_id: ::core::option::Option, - #[prost(message, required, tag="2")] + #[prost(message, required, tag = "2")] pub authority: SignedBlock, - #[prost(message, repeated, tag="3")] + #[prost(message, repeated, tag = "3")] pub blocks: ::prost::alloc::vec::Vec, - #[prost(message, required, tag="4")] + #[prost(message, required, tag = "4")] pub proof: Proof, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct SignedBlock { - #[prost(bytes="vec", required, tag="1")] + #[prost(bytes = "vec", required, tag = "1")] pub block: ::prost::alloc::vec::Vec, - #[prost(message, required, tag="2")] + #[prost(message, required, tag = "2")] pub next_key: PublicKey, - #[prost(bytes="vec", required, tag="3")] + #[prost(bytes = "vec", required, tag = "3")] pub signature: ::prost::alloc::vec::Vec, - #[prost(message, optional, tag="4")] + #[prost(message, optional, tag = "4")] pub external_signature: ::core::option::Option, - #[prost(uint32, optional, tag="5")] + #[prost(uint32, optional, tag = "5")] pub version: ::core::option::Option, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct ExternalSignature { - #[prost(bytes="vec", required, tag="1")] + #[prost(bytes = "vec", required, tag = "1")] pub signature: ::prost::alloc::vec::Vec, - #[prost(message, required, tag="2")] + #[prost(message, required, tag = "2")] pub public_key: PublicKey, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct PublicKey { - #[prost(enumeration="public_key::Algorithm", required, tag="1")] + #[prost(enumeration = "public_key::Algorithm", required, tag = "1")] pub algorithm: i32, - #[prost(bytes="vec", required, tag="2")] + #[prost(bytes = "vec", required, tag = "2")] pub key: ::prost::alloc::vec::Vec, } /// Nested message and enum types in `PublicKey`. @@ -47,41 +47,41 @@ pub mod public_key { } #[derive(Clone, PartialEq, ::prost::Message)] pub struct Proof { - #[prost(oneof="proof::Content", tags="1, 2")] + #[prost(oneof = "proof::Content", tags = "1, 2")] pub content: ::core::option::Option, } /// Nested message and enum types in `Proof`. pub mod proof { #[derive(Clone, PartialEq, ::prost::Oneof)] pub enum Content { - #[prost(bytes, tag="1")] + #[prost(bytes, tag = "1")] NextSecret(::prost::alloc::vec::Vec), - #[prost(bytes, tag="2")] + #[prost(bytes, tag = "2")] FinalSignature(::prost::alloc::vec::Vec), } } #[derive(Clone, PartialEq, ::prost::Message)] pub struct Block { - #[prost(string, repeated, tag="1")] + #[prost(string, repeated, tag = "1")] pub symbols: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, - #[prost(string, optional, tag="2")] + #[prost(string, optional, tag = "2")] pub context: ::core::option::Option<::prost::alloc::string::String>, - #[prost(uint32, optional, tag="3")] + #[prost(uint32, optional, tag = "3")] pub version: ::core::option::Option, - #[prost(message, repeated, tag="4")] + #[prost(message, repeated, tag = "4")] pub facts: ::prost::alloc::vec::Vec, - #[prost(message, repeated, tag="5")] + #[prost(message, repeated, tag = "5")] pub rules: ::prost::alloc::vec::Vec, - #[prost(message, repeated, tag="6")] + #[prost(message, repeated, tag = "6")] pub checks: ::prost::alloc::vec::Vec, - #[prost(message, repeated, tag="7")] + #[prost(message, repeated, tag = "7")] pub scope: ::prost::alloc::vec::Vec, - #[prost(message, repeated, tag="8")] + #[prost(message, repeated, tag = "8")] pub public_keys: ::prost::alloc::vec::Vec, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct Scope { - #[prost(oneof="scope::Content", tags="1, 2")] + #[prost(oneof = "scope::Content", tags = "1, 2")] pub content: ::core::option::Option, } /// Nested message and enum types in `Scope`. @@ -94,33 +94,33 @@ pub mod scope { } #[derive(Clone, PartialEq, ::prost::Oneof)] pub enum Content { - #[prost(enumeration="ScopeType", tag="1")] + #[prost(enumeration = "ScopeType", tag = "1")] ScopeType(i32), - #[prost(int64, tag="2")] + #[prost(int64, tag = "2")] PublicKey(i64), } } #[derive(Clone, PartialEq, ::prost::Message)] pub struct Fact { - #[prost(message, required, tag="1")] + #[prost(message, required, tag = "1")] pub predicate: Predicate, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct Rule { - #[prost(message, required, tag="1")] + #[prost(message, required, tag = "1")] pub head: Predicate, - #[prost(message, repeated, tag="2")] + #[prost(message, repeated, tag = "2")] pub body: ::prost::alloc::vec::Vec, - #[prost(message, repeated, tag="3")] + #[prost(message, repeated, tag = "3")] pub expressions: ::prost::alloc::vec::Vec, - #[prost(message, repeated, tag="4")] + #[prost(message, repeated, tag = "4")] pub scope: ::prost::alloc::vec::Vec, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct Check { - #[prost(message, repeated, tag="1")] + #[prost(message, repeated, tag = "1")] pub queries: ::prost::alloc::vec::Vec, - #[prost(enumeration="check::Kind", optional, tag="2")] + #[prost(enumeration = "check::Kind", optional, tag = "2")] pub kind: ::core::option::Option, } /// Nested message and enum types in `Check`. @@ -135,108 +135,108 @@ pub mod check { } #[derive(Clone, PartialEq, ::prost::Message)] pub struct Predicate { - #[prost(uint64, required, tag="1")] + #[prost(uint64, required, tag = "1")] pub name: u64, - #[prost(message, repeated, tag="2")] + #[prost(message, repeated, tag = "2")] pub terms: ::prost::alloc::vec::Vec, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct Term { - #[prost(oneof="term::Content", tags="1, 2, 3, 4, 5, 6, 7, 8, 9, 10")] + #[prost(oneof = "term::Content", tags = "1, 2, 3, 4, 5, 6, 7, 8, 9, 10")] pub content: ::core::option::Option, } /// Nested message and enum types in `Term`. pub mod term { #[derive(Clone, PartialEq, ::prost::Oneof)] pub enum Content { - #[prost(uint32, tag="1")] + #[prost(uint32, tag = "1")] Variable(u32), - #[prost(int64, tag="2")] + #[prost(int64, tag = "2")] Integer(i64), - #[prost(uint64, tag="3")] + #[prost(uint64, tag = "3")] String(u64), - #[prost(uint64, tag="4")] + #[prost(uint64, tag = "4")] Date(u64), - #[prost(bytes, tag="5")] + #[prost(bytes, tag = "5")] Bytes(::prost::alloc::vec::Vec), - #[prost(bool, tag="6")] + #[prost(bool, tag = "6")] Bool(bool), - #[prost(message, tag="7")] + #[prost(message, tag = "7")] Set(super::TermSet), - #[prost(message, tag="8")] + #[prost(message, tag = "8")] Null(super::Empty), - #[prost(message, tag="9")] + #[prost(message, tag = "9")] Array(super::Array), - #[prost(message, tag="10")] + #[prost(message, tag = "10")] Map(super::Map), } } #[derive(Clone, PartialEq, ::prost::Message)] pub struct TermSet { - #[prost(message, repeated, tag="1")] + #[prost(message, repeated, tag = "1")] pub set: ::prost::alloc::vec::Vec, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct Array { - #[prost(message, repeated, tag="1")] + #[prost(message, repeated, tag = "1")] pub array: ::prost::alloc::vec::Vec, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct Map { - #[prost(message, repeated, tag="1")] + #[prost(message, repeated, tag = "1")] pub entries: ::prost::alloc::vec::Vec, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct MapEntry { - #[prost(message, required, tag="1")] + #[prost(message, required, tag = "1")] pub key: MapKey, - #[prost(message, required, tag="2")] + #[prost(message, required, tag = "2")] pub value: Term, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct MapKey { - #[prost(oneof="map_key::Content", tags="1, 2")] + #[prost(oneof = "map_key::Content", tags = "1, 2")] pub content: ::core::option::Option, } /// Nested message and enum types in `MapKey`. pub mod map_key { #[derive(Clone, PartialEq, ::prost::Oneof)] pub enum Content { - #[prost(int64, tag="1")] + #[prost(int64, tag = "1")] Integer(i64), - #[prost(uint64, tag="2")] + #[prost(uint64, tag = "2")] String(u64), } } #[derive(Clone, PartialEq, ::prost::Message)] pub struct Expression { - #[prost(message, repeated, tag="1")] + #[prost(message, repeated, tag = "1")] pub ops: ::prost::alloc::vec::Vec, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct Op { - #[prost(oneof="op::Content", tags="1, 2, 3, 4")] + #[prost(oneof = "op::Content", tags = "1, 2, 3, 4")] pub content: ::core::option::Option, } /// Nested message and enum types in `Op`. pub mod op { #[derive(Clone, PartialEq, ::prost::Oneof)] pub enum Content { - #[prost(message, tag="1")] + #[prost(message, tag = "1")] Value(super::Term), - #[prost(message, tag="2")] + #[prost(message, tag = "2")] Unary(super::OpUnary), - #[prost(message, tag="3")] + #[prost(message, tag = "3")] Binary(super::OpBinary), - #[prost(message, tag="4")] + #[prost(message, tag = "4")] Closure(super::OpClosure), } } #[derive(Clone, PartialEq, ::prost::Message)] pub struct OpUnary { - #[prost(enumeration="op_unary::Kind", required, tag="1")] + #[prost(enumeration = "op_unary::Kind", required, tag = "1")] pub kind: i32, - #[prost(uint64, optional, tag="2")] + #[prost(uint64, optional, tag = "2")] pub ffi_name: ::core::option::Option, } /// Nested message and enum types in `OpUnary`. @@ -253,9 +253,9 @@ pub mod op_unary { } #[derive(Clone, PartialEq, ::prost::Message)] pub struct OpBinary { - #[prost(enumeration="op_binary::Kind", required, tag="1")] + #[prost(enumeration = "op_binary::Kind", required, tag = "1")] pub kind: i32, - #[prost(uint64, optional, tag="2")] + #[prost(uint64, optional, tag = "2")] pub ffi_name: ::core::option::Option, } /// Nested message and enum types in `OpBinary`. @@ -297,16 +297,16 @@ pub mod op_binary { } #[derive(Clone, PartialEq, ::prost::Message)] pub struct OpClosure { - #[prost(uint32, repeated, packed="false", tag="1")] + #[prost(uint32, repeated, packed = "false", tag = "1")] pub params: ::prost::alloc::vec::Vec, - #[prost(message, repeated, tag="2")] + #[prost(message, repeated, tag = "2")] pub ops: ::prost::alloc::vec::Vec, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct Policy { - #[prost(message, repeated, tag="1")] + #[prost(message, repeated, tag = "1")] pub queries: ::prost::alloc::vec::Vec, - #[prost(enumeration="policy::Kind", required, tag="2")] + #[prost(enumeration = "policy::Kind", required, tag = "2")] pub kind: i32, } /// Nested message and enum types in `Policy`. @@ -320,111 +320,110 @@ pub mod policy { } #[derive(Clone, PartialEq, ::prost::Message)] pub struct AuthorizerPolicies { - #[prost(string, repeated, tag="1")] + #[prost(string, repeated, tag = "1")] pub symbols: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, - #[prost(uint32, optional, tag="2")] + #[prost(uint32, optional, tag = "2")] pub version: ::core::option::Option, - #[prost(message, repeated, tag="3")] + #[prost(message, repeated, tag = "3")] pub facts: ::prost::alloc::vec::Vec, - #[prost(message, repeated, tag="4")] + #[prost(message, repeated, tag = "4")] pub rules: ::prost::alloc::vec::Vec, - #[prost(message, repeated, tag="5")] + #[prost(message, repeated, tag = "5")] pub checks: ::prost::alloc::vec::Vec, - #[prost(message, repeated, tag="6")] + #[prost(message, repeated, tag = "6")] pub policies: ::prost::alloc::vec::Vec, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct ThirdPartyBlockRequest { - #[prost(message, optional, tag="1")] + #[prost(message, optional, tag = "1")] pub legacy_previous_key: ::core::option::Option, - #[prost(message, repeated, tag="2")] + #[prost(message, repeated, tag = "2")] pub legacy_public_keys: ::prost::alloc::vec::Vec, - #[prost(bytes="vec", required, tag="3")] + #[prost(bytes = "vec", required, tag = "3")] pub previous_signature: ::prost::alloc::vec::Vec, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct ThirdPartyBlockContents { - #[prost(bytes="vec", required, tag="1")] + #[prost(bytes = "vec", required, tag = "1")] pub payload: ::prost::alloc::vec::Vec, - #[prost(message, required, tag="2")] + #[prost(message, required, tag = "2")] pub external_signature: ExternalSignature, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct AuthorizerSnapshot { - #[prost(message, required, tag="1")] + #[prost(message, required, tag = "1")] pub limits: RunLimits, - #[prost(uint64, required, tag="2")] + #[prost(uint64, required, tag = "2")] pub execution_time: u64, - #[prost(message, required, tag="3")] + #[prost(message, required, tag = "3")] pub world: AuthorizerWorld, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct RunLimits { - #[prost(uint64, required, tag="1")] + #[prost(uint64, required, tag = "1")] pub max_facts: u64, - #[prost(uint64, required, tag="2")] + #[prost(uint64, required, tag = "2")] pub max_iterations: u64, - #[prost(uint64, required, tag="3")] + #[prost(uint64, required, tag = "3")] pub max_time: u64, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct AuthorizerWorld { - #[prost(uint32, optional, tag="1")] + #[prost(uint32, optional, tag = "1")] pub version: ::core::option::Option, - #[prost(string, repeated, tag="2")] + #[prost(string, repeated, tag = "2")] pub symbols: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, - #[prost(message, repeated, tag="3")] + #[prost(message, repeated, tag = "3")] pub public_keys: ::prost::alloc::vec::Vec, - #[prost(message, repeated, tag="4")] + #[prost(message, repeated, tag = "4")] pub blocks: ::prost::alloc::vec::Vec, - #[prost(message, required, tag="5")] + #[prost(message, required, tag = "5")] pub authorizer_block: SnapshotBlock, - #[prost(message, repeated, tag="6")] + #[prost(message, repeated, tag = "6")] pub authorizer_policies: ::prost::alloc::vec::Vec, - #[prost(message, repeated, tag="7")] + #[prost(message, repeated, tag = "7")] pub generated_facts: ::prost::alloc::vec::Vec, - #[prost(uint64, required, tag="8")] + #[prost(uint64, required, tag = "8")] pub iterations: u64, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct Origin { - #[prost(oneof="origin::Content", tags="1, 2")] + #[prost(oneof = "origin::Content", tags = "1, 2")] pub content: ::core::option::Option, } /// Nested message and enum types in `Origin`. pub mod origin { #[derive(Clone, PartialEq, ::prost::Oneof)] pub enum Content { - #[prost(message, tag="1")] + #[prost(message, tag = "1")] Authorizer(super::Empty), - #[prost(uint32, tag="2")] + #[prost(uint32, tag = "2")] Origin(u32), } } #[derive(Clone, PartialEq, ::prost::Message)] -pub struct Empty { -} +pub struct Empty {} #[derive(Clone, PartialEq, ::prost::Message)] pub struct GeneratedFacts { - #[prost(message, repeated, tag="1")] + #[prost(message, repeated, tag = "1")] pub origins: ::prost::alloc::vec::Vec, - #[prost(message, repeated, tag="2")] + #[prost(message, repeated, tag = "2")] pub facts: ::prost::alloc::vec::Vec, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct SnapshotBlock { - #[prost(string, optional, tag="1")] + #[prost(string, optional, tag = "1")] pub context: ::core::option::Option<::prost::alloc::string::String>, - #[prost(uint32, optional, tag="2")] + #[prost(uint32, optional, tag = "2")] pub version: ::core::option::Option, - #[prost(message, repeated, tag="3")] + #[prost(message, repeated, tag = "3")] pub facts: ::prost::alloc::vec::Vec, - #[prost(message, repeated, tag="4")] + #[prost(message, repeated, tag = "4")] pub rules: ::prost::alloc::vec::Vec, - #[prost(message, repeated, tag="5")] + #[prost(message, repeated, tag = "5")] pub checks: ::prost::alloc::vec::Vec, - #[prost(message, repeated, tag="6")] + #[prost(message, repeated, tag = "6")] pub scope: ::prost::alloc::vec::Vec, - #[prost(message, optional, tag="7")] + #[prost(message, optional, tag = "7")] pub external_key: ::core::option::Option, } diff --git a/biscuit-auth/src/format/schema.proto b/biscuit-proto/src/schema.proto similarity index 100% rename from biscuit-auth/src/format/schema.proto rename to biscuit-proto/src/schema.proto diff --git a/biscuit-proto/tests/schema_up_to_date.rs b/biscuit-proto/tests/schema_up_to_date.rs new file mode 100644 index 00000000..c9d830b5 --- /dev/null +++ b/biscuit-proto/tests/schema_up_to_date.rs @@ -0,0 +1,28 @@ +use std::io::Read; + +#[test] +fn schema_up_to_date() { + let out_dir = match std::env::var("OUT_DIR") { + Ok(dir) => dir, + Err(_) => return, + }; + prost_build::compile_protos(&["src/schema.proto"], &["src/"]).unwrap(); + let mut generated = String::new(); + std::fs::File::open(format!("{out_dir}/biscuit.format.schema.rs")) + .unwrap() + .read_to_string(&mut generated) + .unwrap(); + + let committed = include_str!("../src/lib.rs"); + + if generated != committed { + println!( + "{}", + colored_diff::PrettyDifference { + expected: &generated, + actual: committed, + } + ); + panic!("biscuit-proto/src/lib.rs is out of date with biscuit-proto/src/schema.proto"); + } +}