biscuit_auth/token/
mod.rs

1//! main structures to interact with Biscuit tokens
2use std::fmt::Display;
3use std::iter::once;
4
5use builder::{BiscuitBuilder, BlockBuilder};
6use prost::Message;
7use rand_core::{CryptoRng, RngCore};
8
9use self::public_keys::PublicKeys;
10use super::crypto::{KeyPair, PublicKey, Signature};
11use super::datalog::SymbolTable;
12use super::error;
13use super::format::SerializedBiscuit;
14use crate::crypto::{self};
15use crate::format::convert::proto_block_to_token_block;
16use crate::format::schema::{self, ThirdPartyBlockContents};
17use crate::format::{ThirdPartyVerificationMode, THIRD_PARTY_SIGNATURE_VERSION};
18use authorizer::Authorizer;
19
20pub mod authorizer;
21pub(crate) mod block;
22pub mod builder;
23pub mod builder_ext;
24pub(crate) mod public_keys;
25pub(crate) mod third_party;
26pub mod unverified;
27pub use block::Block;
28pub use third_party::*;
29
30/// minimum supported version of the serialization format
31pub const MIN_SCHEMA_VERSION: u32 = 3;
32/// maximum supported version of the serialization format
33pub const MAX_SCHEMA_VERSION: u32 = 6;
34/// starting version for datalog 3.1 features (check all, bitwise operators, !=, …)
35pub const DATALOG_3_1: u32 = 4;
36/// starting version for 3rd party blocks (datalog 3.2)
37pub const DATALOG_3_2: u32 = 5;
38/// starting version for datalog 3.3 features (reject if, closures, array/map, null, external functions, …)
39pub const DATALOG_3_3: u32 = 6;
40
41/// some symbols are predefined and available in every implementation, to avoid
42/// transmitting them with every token
43pub fn default_symbol_table() -> SymbolTable {
44    SymbolTable::new()
45}
46
47/// This structure represents a valid Biscuit token
48///
49/// It contains multiple `Block` elements, the associated symbol table,
50/// and a serialized version of this data
51///
52/// ```rust
53/// extern crate biscuit_auth as biscuit;
54///
55/// use biscuit::{KeyPair, Biscuit, builder::*, builder_ext::*};
56///
57/// fn main() -> Result<(), biscuit::error::Token> {
58///   let root = KeyPair::new();
59///
60///   // first we define the authority block for global data,
61///   // like access rights
62///   // data from the authority block cannot be created in any other block
63///   let token1 = Biscuit::builder()
64///       .fact(fact("right", &[string("/a/file1.txt"), string("read")]))?
65///
66///       // facts and rules can also be parsed from a string
67///       .fact("right(\"/a/file1.txt\", \"read\")")?
68///       .build(&root)?;
69///
70///   // we can create a new block builder from that token
71///   let builder2 = BlockBuilder::new()
72///       .check_operation("read");
73///
74///   let token2 = token1.append(builder2)?;
75///
76///   Ok(())
77/// }
78/// ```
79#[derive(Clone, Debug)]
80pub struct Biscuit {
81    pub(crate) root_key_id: Option<u32>,
82    pub(crate) authority: schema::Block,
83    pub(crate) blocks: Vec<schema::Block>,
84    pub(crate) symbols: SymbolTable,
85    pub(crate) container: SerializedBiscuit,
86}
87
88impl Biscuit {
89    /// create the first block's builder
90    ///
91    /// call [`builder::BiscuitBuilder::build`] to create the token
92    pub fn builder() -> BiscuitBuilder {
93        BiscuitBuilder::new()
94    }
95
96    /// deserializes a token and validates the signature using the root public key
97    pub fn from<T, KP>(slice: T, key_provider: KP) -> Result<Self, error::Token>
98    where
99        T: AsRef<[u8]>,
100        KP: RootKeyProvider,
101    {
102        Biscuit::from_with_symbols(slice.as_ref(), key_provider, default_symbol_table())
103    }
104
105    /// deserializes a token and validates the signature using the root public key
106    pub fn from_base64<T, KP>(slice: T, key_provider: KP) -> Result<Self, error::Token>
107    where
108        T: AsRef<[u8]>,
109        KP: RootKeyProvider,
110    {
111        Biscuit::from_base64_with_symbols(slice, key_provider, default_symbol_table())
112    }
113
114    /// deserializes a token and validates the signature using the root public key
115    ///
116    /// This allows the deprecated 3rd party block format
117    pub fn unsafe_deprecated_deserialize<T, KP>(
118        slice: T,
119        key_provider: KP,
120    ) -> Result<Self, error::Token>
121    where
122        T: AsRef<[u8]>,
123        KP: RootKeyProvider,
124    {
125        let container = SerializedBiscuit::unsafe_from_slice(slice.as_ref(), key_provider)
126            .map_err(error::Token::Format)?;
127
128        Biscuit::from_serialized_container(container, default_symbol_table())
129    }
130
131    /// serializes the token
132    pub fn to_vec(&self) -> Result<Vec<u8>, error::Token> {
133        self.container.to_vec().map_err(error::Token::Format)
134    }
135
136    /// serializes the token and encode it to a (URL safe) base64 string
137    pub fn to_base64(&self) -> Result<String, error::Token> {
138        self.container
139            .to_vec()
140            .map_err(error::Token::Format)
141            .map(|v| base64::encode_config(v, base64::URL_SAFE))
142    }
143
144    /// serializes the token
145    pub fn serialized_size(&self) -> Result<usize, error::Token> {
146        Ok(self.container.serialized_size())
147    }
148
149    /// creates a sealed version of the token
150    ///
151    /// sealed tokens cannot be attenuated
152    pub fn seal(&self) -> Result<Biscuit, error::Token> {
153        let container = self.container.seal()?;
154
155        let mut token = self.clone();
156        token.container = container;
157
158        Ok(token)
159    }
160
161    /// creates an authorizer from this token
162    pub fn authorizer(&self) -> Result<Authorizer, error::Token> {
163        Authorizer::from_token(self)
164    }
165
166    /// adds a new block to the token
167    ///
168    /// since the public key is integrated into the token, the keypair can be
169    /// discarded right after calling this function
170    pub fn append(&self, block_builder: BlockBuilder) -> Result<Self, error::Token> {
171        let keypair = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rand::rngs::OsRng);
172        self.append_with_keypair(&keypair, block_builder)
173    }
174
175    /// returns the list of context elements of each block
176    ///
177    /// the context is a free form text field in which application specific data
178    /// can be stored
179    pub fn context(&self) -> Vec<Option<String>> {
180        let mut res = vec![self.authority.context.clone()];
181
182        for b in self.blocks.iter() {
183            res.push(b.context.clone());
184        }
185
186        res
187    }
188
189    /// returns an (optional) root key identifier. It provides a hint for public key selection during verification
190    pub fn root_key_id(&self) -> Option<u32> {
191        self.root_key_id
192    }
193
194    /// returns a list of revocation identifiers for each block, in order
195    ///
196    /// revocation identifiers are unique: tokens generated separately with
197    /// the same contents will have different revocation ids
198    pub fn revocation_identifiers(&self) -> Vec<Vec<u8>> {
199        let mut res = vec![self.container.authority.signature.to_bytes().to_vec()];
200
201        for block in self.container.blocks.iter() {
202            res.push(block.signature.to_bytes().to_vec());
203        }
204
205        res
206    }
207
208    /// returns a list of external key for each block, in order
209    ///
210    /// Blocks carrying an external public key are _third-party blocks_
211    /// and their contents can be trusted as coming from the holder of
212    /// the corresponding private key
213    pub fn external_public_keys(&self) -> Vec<Option<PublicKey>> {
214        let mut res = vec![None];
215
216        for block in self.container.blocks.iter() {
217            res.push(block.external_signature.as_ref().map(|sig| sig.public_key));
218        }
219
220        res
221    }
222
223    /// pretty printer for this token
224    pub fn print(&self) -> String {
225        format!("{}", &self)
226    }
227
228    /// prints the content of a block as Datalog source code
229    pub fn print_block_source(&self, index: usize) -> Result<String, error::Token> {
230        self.block(index).map(|block| {
231            let symbols = if block.external_key.is_some() {
232                &block.symbols
233            } else {
234                &self.symbols
235            };
236            block.print_source(symbols)
237        })
238    }
239
240    /// gets the datalog version for a given block
241    pub fn block_version(&self, index: usize) -> Result<u32, error::Token> {
242        self.block(index).map(|block| block.version)
243    }
244
245    /// creates a new token, using a provided CSPRNG
246    ///
247    /// the public part of the root keypair must be used for verification
248    pub(crate) fn new_with_rng<T: RngCore + CryptoRng>(
249        rng: &mut T,
250        root_key_id: Option<u32>,
251        root: &KeyPair,
252        symbols: SymbolTable,
253        authority: Block,
254    ) -> Result<Biscuit, error::Token> {
255        Self::new_with_key_pair(
256            root_key_id,
257            root,
258            &KeyPair::new_with_rng(builder::Algorithm::Ed25519, rng),
259            symbols,
260            authority,
261        )
262    }
263
264    /// creates a new token, using provided keypairs (the root keypair, and the keypair used to sign the next block)
265    ///
266    /// the public part of the root keypair must be used for verification
267    pub(crate) fn new_with_key_pair(
268        root_key_id: Option<u32>,
269        root: &KeyPair,
270        next_keypair: &KeyPair,
271        mut symbols: SymbolTable,
272        authority: Block,
273    ) -> Result<Biscuit, error::Token> {
274        if !symbols.is_disjoint(&authority.symbols) {
275            return Err(error::Token::Format(error::Format::SymbolTableOverlap));
276        }
277
278        symbols.extend(&authority.symbols)?;
279
280        let blocks = vec![];
281
282        let container = SerializedBiscuit::new(root_key_id, root, next_keypair, &authority)?;
283
284        symbols.public_keys.extend(&authority.public_keys)?;
285
286        let authority = schema::Block::decode(&container.authority.data[..]).map_err(|e| {
287            error::Token::Format(error::Format::BlockDeserializationError(format!(
288                "error deserializing block: {:?}",
289                e
290            )))
291        })?;
292
293        Ok(Biscuit {
294            root_key_id,
295            authority,
296            blocks,
297            symbols,
298            container,
299        })
300    }
301
302    /// deserializes a token and validates the signature using the root public key, with a custom symbol table
303    fn from_with_symbols<KP>(
304        slice: &[u8],
305        key_provider: KP,
306        symbols: SymbolTable,
307    ) -> Result<Self, error::Token>
308    where
309        KP: RootKeyProvider,
310    {
311        let container =
312            SerializedBiscuit::from_slice(slice, key_provider).map_err(error::Token::Format)?;
313
314        Biscuit::from_serialized_container(container, symbols)
315    }
316
317    fn from_serialized_container(
318        container: SerializedBiscuit,
319        mut symbols: SymbolTable,
320    ) -> Result<Self, error::Token> {
321        let (authority, blocks) = container.extract_blocks(&mut symbols)?;
322
323        let root_key_id = container.root_key_id;
324
325        Ok(Biscuit {
326            root_key_id,
327            authority,
328            blocks,
329            symbols,
330            container,
331        })
332    }
333
334    /// deserializes a token and validates the signature using the root public key, with a custom symbol table
335    fn from_base64_with_symbols<T, KP>(
336        slice: T,
337        key_provider: KP,
338        symbols: SymbolTable,
339    ) -> Result<Self, error::Token>
340    where
341        T: AsRef<[u8]>,
342        KP: RootKeyProvider,
343    {
344        let decoded = base64::decode_config(slice, base64::URL_SAFE)?;
345        Biscuit::from_with_symbols(&decoded, key_provider, symbols)
346    }
347
348    /// returns the internal representation of the token
349    pub fn container(&self) -> &SerializedBiscuit {
350        &self.container
351    }
352
353    /// adds a new block to the token, using the provided CSPRNG
354    ///
355    /// since the public key is integrated into the token, the keypair can be
356    /// discarded right after calling this function
357    pub fn append_with_keypair(
358        &self,
359        keypair: &KeyPair,
360        block_builder: BlockBuilder,
361    ) -> Result<Self, error::Token> {
362        let block = block_builder.build(self.symbols.clone());
363
364        if !self.symbols.is_disjoint(&block.symbols) {
365            return Err(error::Token::Format(error::Format::SymbolTableOverlap));
366        }
367
368        let authority = self.authority.clone();
369        let mut blocks = self.blocks.clone();
370        let mut symbols = self.symbols.clone();
371
372        let container = self.container.append(keypair, &block, None)?;
373
374        symbols.extend(&block.symbols)?;
375        symbols.public_keys.extend(&block.public_keys)?;
376
377        let deser = schema::Block::decode(
378            &container
379                .blocks
380                .last()
381                .expect("a new block was just added so the list is not empty")
382                .data[..],
383        )
384        .map_err(|e| {
385            error::Token::Format(error::Format::BlockDeserializationError(format!(
386                "error deserializing block: {:?}",
387                e
388            )))
389        })?;
390        blocks.push(deser);
391
392        Ok(Biscuit {
393            root_key_id: self.root_key_id,
394            authority,
395            blocks,
396            symbols,
397            container,
398        })
399    }
400
401    pub fn third_party_request(&self) -> Result<ThirdPartyRequest, error::Token> {
402        ThirdPartyRequest::from_container(&self.container)
403    }
404
405    pub fn append_third_party(
406        &self,
407        external_key: PublicKey,
408        response: ThirdPartyBlock,
409    ) -> Result<Self, error::Token> {
410        let next_keypair =
411            KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rand::rngs::OsRng);
412
413        self.append_third_party_with_keypair(external_key, response, next_keypair)
414    }
415    pub fn append_third_party_with_keypair(
416        &self,
417        external_key: PublicKey,
418        response: ThirdPartyBlock,
419        next_keypair: KeyPair,
420    ) -> Result<Self, error::Token> {
421        let ThirdPartyBlockContents {
422            payload,
423            external_signature,
424        } = response.0;
425
426        let provided_key = PublicKey::from_proto(&external_signature.public_key)?;
427        if external_key != provided_key {
428            return Err(error::Token::Format(error::Format::DeserializationError(
429                format!(
430                    "deserialization error: unexpected key {}",
431                    provided_key.print()
432                ),
433            )));
434        }
435
436        let signature = Signature::from_vec(external_signature.signature);
437
438        let previous_key = self
439            .container
440            .blocks
441            .last()
442            .unwrap_or(&self.container.authority)
443            .next_key;
444
445        let external_signature = crypto::ExternalSignature {
446            public_key: external_key,
447            signature,
448        };
449        crypto::verify_external_signature(
450            &payload,
451            &previous_key,
452            &self
453                .container
454                .blocks
455                .last()
456                .unwrap_or(&self.container.authority)
457                .signature,
458            &external_signature,
459            THIRD_PARTY_SIGNATURE_VERSION,
460            ThirdPartyVerificationMode::PreviousSignatureHashing,
461        )?;
462
463        let block = schema::Block::decode(&payload[..]).map_err(|e| {
464            error::Token::Format(error::Format::DeserializationError(format!(
465                "deserialization error: {:?}",
466                e
467            )))
468        })?;
469
470        let symbols = self.symbols.clone();
471        let mut blocks = self.blocks.clone();
472
473        let container =
474            self.container
475                .append_serialized(&next_keypair, payload, Some(external_signature))?;
476
477        blocks.push(block);
478
479        Ok(Biscuit {
480            root_key_id: self.root_key_id,
481            authority: self.authority.clone(),
482            blocks,
483            symbols,
484            container,
485        })
486    }
487
488    /// gets the list of symbols from a block
489    pub fn block_symbols(&self, index: usize) -> Result<Vec<String>, error::Token> {
490        let block = if index == 0 {
491            &self.authority
492        } else {
493            match self.blocks.get(index - 1) {
494                None => return Err(error::Token::Format(error::Format::InvalidBlockId(index))),
495                Some(block) => block,
496            }
497        };
498
499        Ok(block.symbols.clone())
500    }
501
502    /// gets the list of public keys from a block
503    pub fn block_public_keys(&self, index: usize) -> Result<PublicKeys, error::Token> {
504        let block = if index == 0 {
505            &self.authority
506        } else {
507            match self.blocks.get(index - 1) {
508                None => return Err(error::Token::Format(error::Format::InvalidBlockId(index))),
509                Some(block) => block,
510            }
511        };
512
513        let mut public_keys = PublicKeys::new();
514
515        for pk in &block.public_keys {
516            public_keys.insert(&PublicKey::from_proto(pk)?);
517        }
518        Ok(public_keys)
519    }
520
521    /// gets the list of public keys from a block
522    pub fn block_external_key(&self, index: usize) -> Result<Option<PublicKey>, error::Token> {
523        let block = if index == 0 {
524            &self.container.authority
525        } else {
526            match self.container.blocks.get(index - 1) {
527                None => return Err(error::Token::Format(error::Format::InvalidBlockId(index))),
528                Some(block) => block,
529            }
530        };
531
532        Ok(block
533            .external_signature
534            .as_ref()
535            .map(|signature| signature.public_key))
536    }
537
538    /// returns the number of blocks (at least 1)
539    pub fn block_count(&self) -> usize {
540        1 + self.blocks.len()
541    }
542
543    pub(crate) fn block(&self, index: usize) -> Result<Block, error::Token> {
544        let block = if index == 0 {
545            proto_block_to_token_block(
546                &self.authority,
547                self.container
548                    .authority
549                    .external_signature
550                    .as_ref()
551                    .map(|ex| ex.public_key),
552            )
553            .map_err(error::Token::Format)?
554        } else {
555            if index > self.blocks.len() + 1 {
556                return Err(error::Token::Format(
557                    error::Format::BlockDeserializationError("invalid block index".to_string()),
558                ));
559            }
560
561            proto_block_to_token_block(
562                &self.blocks[index - 1],
563                self.container.blocks[index - 1]
564                    .external_signature
565                    .as_ref()
566                    .map(|ex| ex.public_key),
567            )
568            .map_err(error::Token::Format)?
569        };
570
571        Ok(block)
572    }
573
574    pub(crate) fn blocks(&self) -> impl Iterator<Item = Result<Block, error::Token>> + use<'_> {
575        once(
576            proto_block_to_token_block(
577                &self.authority,
578                self.container
579                    .authority
580                    .external_signature
581                    .as_ref()
582                    .map(|ex| ex.public_key),
583            )
584            .map_err(error::Token::Format),
585        )
586        .chain(self.blocks.iter().zip(self.container.blocks.iter()).map(
587            |(block, container)| {
588                proto_block_to_token_block(
589                    block,
590                    container
591                        .external_signature
592                        .as_ref()
593                        .map(|ex| ex.public_key),
594                )
595                .map_err(error::Token::Format)
596            },
597        ))
598    }
599}
600
601impl Display for Biscuit {
602    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
603        let authority = self
604            .block(0)
605            .as_ref()
606            .map(|block| print_block(&self.symbols, block))
607            .unwrap_or_else(|_| String::new());
608        let blocks: Vec<_> = (1..self.block_count())
609            .map(|i| {
610                self.block(i)
611                    .as_ref()
612                    .map(|block| print_block(&self.symbols, block))
613                    .unwrap_or_else(|_| String::new())
614            })
615            .collect();
616
617        write!(f, "Biscuit {{\n    symbols: {:?}\n    public keys: {:?}\n    authority: {}\n    blocks: [\n        {}\n    ]\n}}",
618        self.symbols.strings(),
619        self.symbols.public_keys.keys.iter().map(|pk| hex::encode(pk.to_bytes())).collect::<Vec<_>>(),
620        authority,
621        blocks.join(",\n\t")
622    )
623    }
624}
625fn print_block(symbols: &SymbolTable, block: &Block) -> String {
626    let facts: Vec<_> = block.facts.iter().map(|f| symbols.print_fact(f)).collect();
627    let rules: Vec<_> = block.rules.iter().map(|r| symbols.print_rule(r)).collect();
628    let checks: Vec<_> = block
629        .checks
630        .iter()
631        .map(|r| symbols.print_check(r))
632        .collect();
633
634    let facts = if facts.is_empty() {
635        String::new()
636    } else {
637        format!(
638            "\n                {}\n            ",
639            facts.join(",\n                ")
640        )
641    };
642    let rules = if rules.is_empty() {
643        String::new()
644    } else {
645        format!(
646            "\n                {}\n            ",
647            rules.join(",\n                ")
648        )
649    };
650    let checks = if checks.is_empty() {
651        String::new()
652    } else {
653        format!(
654            "\n                {}\n            ",
655            checks.join(",\n                ")
656        )
657    };
658
659    format!(
660        "Block {{\n            symbols: {:?}\n            version: {}\n            context: \"{}\"\n            external key: {}\n            public keys: {:?}\n            scopes: {:?}\n            facts: [{}]\n            rules: [{}]\n            checks: [{}]\n        }}",
661        block.symbols.strings(),
662        block.version,
663        block.context.as_deref().unwrap_or(""),
664        block.external_key.as_ref().map(|k| hex::encode(k.to_bytes())).unwrap_or_default(),
665        block.public_keys.keys.iter().map(|k | hex::encode(k.to_bytes())).collect::<Vec<_>>(),
666        block.scopes,
667        facts,
668        rules,
669        checks,
670    )
671}
672
673#[derive(Clone, Debug, Hash, PartialEq, Eq)]
674pub enum Scope {
675    Authority,
676    Previous,
677    // index of the public key in the symbol table
678    PublicKey(u64),
679}
680
681/// Chooses a root public key to verify the token
682///
683/// In case of key rotation, it is possible to add a root key id
684/// to the token with [`BiscuitBuilder::set_root_key_id`]. This
685/// value will be passed to the implementor of `RootKeyProvider`
686/// to choose which key will be used.
687pub trait RootKeyProvider {
688    fn choose(&self, key_id: Option<u32>) -> Result<PublicKey, error::Format>;
689}
690
691impl RootKeyProvider for Box<dyn RootKeyProvider> {
692    fn choose(&self, key_id: Option<u32>) -> Result<PublicKey, error::Format> {
693        self.as_ref().choose(key_id)
694    }
695}
696
697impl RootKeyProvider for std::rc::Rc<dyn RootKeyProvider> {
698    fn choose(&self, key_id: Option<u32>) -> Result<PublicKey, error::Format> {
699        self.as_ref().choose(key_id)
700    }
701}
702
703impl RootKeyProvider for std::sync::Arc<dyn RootKeyProvider> {
704    fn choose(&self, key_id: Option<u32>) -> Result<PublicKey, error::Format> {
705        self.as_ref().choose(key_id)
706    }
707}
708
709impl RootKeyProvider for PublicKey {
710    fn choose(&self, _: Option<u32>) -> Result<PublicKey, error::Format> {
711        Ok(*self)
712    }
713}
714
715impl RootKeyProvider for &PublicKey {
716    fn choose(&self, _: Option<u32>) -> Result<PublicKey, error::Format> {
717        Ok(**self)
718    }
719}
720
721impl<F: Fn(Option<u32>) -> Result<PublicKey, error::Format>> RootKeyProvider for F {
722    fn choose(&self, root_key_id: Option<u32>) -> Result<PublicKey, error::Format> {
723        self(root_key_id)
724    }
725}
726
727#[cfg(test)]
728mod tests {
729    use super::builder::{check, fact, pred, rule, string, var};
730    use super::builder_ext::BuilderExt;
731    use super::*;
732    use crate::builder::CheckKind;
733    use crate::crypto::KeyPair;
734    use crate::{error::*, AuthorizerLimits, UnverifiedBiscuit};
735    use builder::AuthorizerBuilder;
736    use builder_ext::AuthorizerExt;
737    use rand::prelude::*;
738    use std::time::{Duration, SystemTime};
739
740    #[test]
741    fn basic() {
742        let mut rng: StdRng = SeedableRng::seed_from_u64(0);
743        let root = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng);
744
745        let serialized1 = {
746            let biscuit1 = Biscuit::builder()
747                .fact("right(\"file1\", \"read\")")
748                .unwrap()
749                .fact("right(\"file2\", \"read\")")
750                .unwrap()
751                .fact("right(\"file1\", \"write\")")
752                .unwrap()
753                .build_with_rng(&root, default_symbol_table(), &mut rng)
754                .unwrap();
755
756            println!("biscuit1 (authority): {}", biscuit1);
757
758            biscuit1.to_vec().unwrap()
759        };
760
761        //println!("generated biscuit token: {} bytes:\n{}", serialized1.len(), serialized1.to_hex(16));
762        println!("generated biscuit token: {} bytes", serialized1.len());
763        //panic!();
764
765        /*
766        for i in 0..9 {
767            let biscuit1_deser = Biscuit::from(&serialized1, root.public).unwrap();
768
769            // new check: can only have read access1
770            let mut block2 = BlockBuilder::new();
771
772            block2.add_check(&rule(
773                "check1",
774                &[var(0)],
775                &[
776                    pred("resource", &[var(0)]),
777                    pred("operation", &[string("read")]),
778                    pred("right", &[var(0), string("read")]),
779                ],
780            ));
781
782            let keypair2 = KeyPair::new_with_rng(&mut rng);
783            let biscuit2 = biscuit1_deser.append(&keypair2, block2.to_block()).unwrap();
784
785            println!("biscuit2 (1 check): {}", biscuit2);
786
787            serialized1 = biscuit2.to_vec().unwrap();
788
789        }
790        println!("generated biscuit token 2: {} bytes", serialized1.len());
791        panic!();
792        */
793
794        let serialized2 = {
795            let biscuit1_deser = Biscuit::from(&serialized1, root.public()).unwrap();
796
797            // new check: can only have read access1
798            let block2 = BlockBuilder::new()
799                .check(rule(
800                    "check1",
801                    &[var("resource")],
802                    &[
803                        pred("resource", &[var("resource")]),
804                        pred("operation", &[string("read")]),
805                        pred("right", &[var("resource"), string("read")]),
806                    ],
807                ))
808                .unwrap();
809
810            let keypair2 = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng);
811            let biscuit2 = biscuit1_deser
812                .append_with_keypair(&keypair2, block2)
813                .unwrap();
814
815            println!("biscuit2 (1 check): {}", biscuit2);
816
817            biscuit2.to_vec().unwrap()
818        };
819
820        //println!("generated biscuit token 2: {} bytes\n{}", serialized2.len(), serialized2.to_hex(16));
821        println!("generated biscuit token 2: {} bytes", serialized2.len());
822
823        let serialized3 = {
824            let biscuit2_deser = Biscuit::from(&serialized2, root.public()).unwrap();
825
826            // new check: can only access file1
827            let block3 = BlockBuilder::new()
828                .check(rule(
829                    "check2",
830                    &[string("file1")],
831                    &[pred("resource", &[string("file1")])],
832                ))
833                .unwrap();
834
835            let keypair3 = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng);
836            let biscuit3 = biscuit2_deser
837                .append_with_keypair(&keypair3, block3)
838                .unwrap();
839
840            biscuit3.to_vec().unwrap()
841        };
842
843        //println!("generated biscuit token 3: {} bytes\n{}", serialized3.len(), serialized3.to_hex(16));
844        println!("generated biscuit token 3: {} bytes", serialized3.len());
845        //panic!();
846
847        let final_token = Biscuit::from(&serialized3, root.public()).unwrap();
848        println!("final token:\n{}", final_token);
849        {
850            let mut builder = AuthorizerBuilder::new();
851
852            let mut facts = vec![
853                fact("resource", &[string("file1")]),
854                fact("operation", &[string("read")]),
855            ];
856
857            for fact in facts.drain(..) {
858                builder = builder.fact(fact).unwrap();
859            }
860
861            //println!("final token: {:#?}", final_token);
862
863            let mut authorizer = builder.allow_all().build(&final_token).unwrap();
864
865            let res = authorizer.authorize();
866            println!("res1: {:?}", res);
867            res.unwrap();
868        }
869
870        {
871            let mut builder = AuthorizerBuilder::new();
872
873            let mut facts = vec![
874                fact("resource", &[string("file2")]),
875                fact("operation", &[string("write")]),
876            ];
877
878            for fact in facts.drain(..) {
879                builder = builder.fact(fact).unwrap();
880            }
881            builder = builder.allow_all();
882
883            let mut authorizer = builder.build(&final_token).unwrap();
884
885            let res = authorizer.authorize_with_limits(AuthorizerLimits {
886                max_time: Duration::from_secs(10),
887                ..Default::default()
888            });
889            println!("res2: {:#?}", res);
890            assert_eq!(res,
891              Err(Token::FailedLogic(Logic::Unauthorized {
892                  policy: MatchedPolicy::Allow(0),
893                  checks: vec![
894                FailedCheck::Block(FailedBlockCheck { block_id: 1, check_id: 0, rule: String::from("check if resource($resource), operation(\"read\"), right($resource, \"read\")") }),
895                FailedCheck::Block(FailedBlockCheck { block_id: 2, check_id: 0, rule: String::from("check if resource(\"file1\")") })
896              ]
897              })));
898        }
899    }
900
901    #[test]
902    fn folders() {
903        let mut rng: StdRng = SeedableRng::seed_from_u64(0);
904        let root = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng);
905
906        let biscuit1 = Biscuit::builder()
907            .right("/folder1/file1", "read")
908            .right("/folder1/file1", "write")
909            .right("/folder1/file2", "read")
910            .right("/folder1/file2", "write")
911            .right("/folder2/file3", "read")
912            .build_with_rng(&root, default_symbol_table(), &mut rng)
913            .unwrap();
914
915        println!("biscuit1 (authority): {}", biscuit1);
916
917        let block2 = BlockBuilder::new()
918            .check_resource_prefix("/folder1/")
919            .check_right("read")
920            .unwrap();
921
922        let keypair2 = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng);
923        let biscuit2 = biscuit1.append_with_keypair(&keypair2, block2).unwrap();
924
925        {
926            let mut authorizer = AuthorizerBuilder::new()
927                .fact("resource(\"/folder1/file1\")")
928                .unwrap()
929                .fact("operation(\"read\")")
930                .unwrap()
931                .allow_all()
932                .build(&biscuit2)
933                .unwrap();
934
935            let res = authorizer.authorize_with_limits(AuthorizerLimits {
936                max_time: Duration::from_secs(10),
937                ..Default::default()
938            });
939            println!("res1: {:?}", res);
940            println!("authorizer:\n{}", authorizer.print_world());
941            res.unwrap();
942        }
943
944        {
945            let mut authorizer = AuthorizerBuilder::new()
946                .fact("resource(\"/folder2/file3\")")
947                .unwrap()
948                .fact("operation(\"read\")")
949                .unwrap()
950                .allow_all()
951                .build(&biscuit2)
952                .unwrap();
953
954            let res = authorizer.authorize_with_limits(AuthorizerLimits {
955                max_time: Duration::from_secs(10),
956                ..Default::default()
957            });
958            println!("res2: {:?}", res);
959            assert_eq!(
960                res,
961                Err(Token::FailedLogic(Logic::Unauthorized {
962                    policy: MatchedPolicy::Allow(0),
963                    checks: vec![FailedCheck::Block(FailedBlockCheck {
964                        block_id: 1,
965                        check_id: 0,
966                        rule: String::from(
967                            "check if resource($resource), $resource.starts_with(\"/folder1/\")"
968                        )
969                    }),]
970                }))
971            );
972        }
973
974        {
975            let mut authorizer = AuthorizerBuilder::new()
976                .fact("resource(\"/folder2/file1\")")
977                .unwrap()
978                .fact("operation(\"write\")")
979                .unwrap()
980                .build(&biscuit2)
981                .unwrap();
982
983            let res = authorizer.authorize();
984            println!("res3: {:?}", res);
985            assert_eq!(res,
986              Err(Token::FailedLogic(Logic::NoMatchingPolicy {
987                  checks: vec![
988                FailedCheck::Block(FailedBlockCheck { block_id: 1, check_id: 0, rule: String::from("check if resource($resource), $resource.starts_with(\"/folder1/\")") }),
989                FailedCheck::Block(FailedBlockCheck { block_id: 1, check_id: 1, rule: String::from("check if resource($resource_name), operation(\"read\"), right($resource_name, \"read\")") }),
990              ]})));
991        }
992    }
993
994    #[test]
995    fn constraints() {
996        let mut rng: StdRng = SeedableRng::seed_from_u64(0);
997        let root = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng);
998
999        let biscuit1 = Biscuit::builder()
1000            .right("file1", "read")
1001            .right("file2", "read")
1002            .build_with_rng(&root, default_symbol_table(), &mut rng)
1003            .unwrap();
1004
1005        println!("biscuit1 (authority): {}", biscuit1);
1006
1007        let block2 = BlockBuilder::new()
1008            .check_expiration_date(SystemTime::now() + Duration::from_secs(30))
1009            .fact("key(1234)")
1010            .unwrap();
1011
1012        let keypair2 = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng);
1013        let biscuit2 = biscuit1.append_with_keypair(&keypair2, block2).unwrap();
1014
1015        {
1016            let mut authorizer = AuthorizerBuilder::new()
1017                .fact("resource(\"file1\")")
1018                .unwrap()
1019                .fact("operation(\"read\")")
1020                .unwrap()
1021                .time()
1022                .allow_all()
1023                .build(&biscuit2)
1024                .unwrap();
1025
1026            let res = authorizer.authorize_with_limits(AuthorizerLimits {
1027                max_time: Duration::from_secs(10),
1028                ..Default::default()
1029            });
1030            println!("res1: {:?}", res);
1031            res.unwrap();
1032        }
1033
1034        {
1035            println!("biscuit2: {}", biscuit2);
1036            let mut authorizer = AuthorizerBuilder::new()
1037                .fact("resource(\"file1\")")
1038                .unwrap()
1039                .fact("operation(\"read\")")
1040                .unwrap()
1041                .time()
1042                .allow_all()
1043                .build(&biscuit2)
1044                .unwrap();
1045
1046            let res = authorizer.authorize_with_limits(AuthorizerLimits {
1047                max_time: Duration::from_secs(10),
1048                ..Default::default()
1049            });
1050            println!("res3: {:?}", res);
1051
1052            // error message should be like this:
1053            //"authorizer check 0 failed: check if revocation_id($0), $0 not in [2, 1234, 1, 5, 0]"
1054            assert!(res.is_ok());
1055        }
1056    }
1057
1058    #[test]
1059    fn sealed_token() {
1060        let mut rng: StdRng = SeedableRng::seed_from_u64(0);
1061        let root = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng);
1062        let biscuit1 = Biscuit::builder()
1063            .right("/folder1/file1", "read")
1064            .right("/folder1/file1", "write")
1065            .right("/folder1/file2", "read")
1066            .right("/folder1/file2", "write")
1067            .right("/folder2/file3", "read")
1068            .build_with_rng(&root, default_symbol_table(), &mut rng)
1069            .unwrap();
1070
1071        println!("biscuit1 (authority): {}", biscuit1);
1072
1073        let block2 = BlockBuilder::new()
1074            .check_resource_prefix("/folder1/")
1075            .check_right("read")
1076            .unwrap();
1077
1078        let keypair2 = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng);
1079        let biscuit2 = biscuit1.append_with_keypair(&keypair2, block2).unwrap();
1080
1081        //println!("biscuit2:\n{:#?}", biscuit2);
1082        //panic!();
1083        {
1084            let mut authorizer = AuthorizerBuilder::new()
1085                .fact("resource(\"/folder1/file1\")")
1086                .unwrap()
1087                .fact("operation(\"read\")")
1088                .unwrap()
1089                .allow_all()
1090                .build(&biscuit2)
1091                .unwrap();
1092
1093            let res = authorizer.authorize_with_limits(AuthorizerLimits {
1094                max_time: Duration::from_secs(10),
1095                ..Default::default()
1096            });
1097            println!("res1: {:?}", res);
1098            res.unwrap();
1099        }
1100
1101        let _serialized = biscuit2.to_vec().unwrap();
1102        //println!("biscuit2 serialized ({} bytes):\n{}", serialized.len(), serialized.to_hex(16));
1103
1104        let sealed = biscuit2.seal().unwrap().to_vec().unwrap();
1105        //println!("biscuit2 sealed ({} bytes):\n{}", sealed.len(), sealed.to_hex(16));
1106
1107        let biscuit3 = Biscuit::from(sealed, root.public()).unwrap();
1108
1109        {
1110            let mut authorizer = AuthorizerBuilder::new()
1111                .fact("resource(\"/folder1/file1\")")
1112                .unwrap()
1113                .fact("operation(\"read\")")
1114                .unwrap()
1115                .allow_all()
1116                .build(&biscuit3)
1117                .unwrap();
1118
1119            let res = authorizer.authorize();
1120            println!("res1: {:?}", res);
1121            res.unwrap();
1122        }
1123    }
1124
1125    #[test]
1126    fn verif_no_blocks() {
1127        use crate::token::builder::*;
1128
1129        let mut rng: StdRng = SeedableRng::seed_from_u64(1234);
1130        let root = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng);
1131
1132        let biscuit1 = Biscuit::builder()
1133            .fact(fact("right", &[string("file1"), string("read")]))
1134            .unwrap()
1135            .fact(fact("right", &[string("file2"), string("read")]))
1136            .unwrap()
1137            .fact(fact("right", &[string("file1"), string("write")]))
1138            .unwrap()
1139            .build_with_rng(&root, default_symbol_table(), &mut rng)
1140            .unwrap();
1141        println!("{}", biscuit1);
1142
1143        let mut authorizer = AuthorizerBuilder::new()
1144            .check(rule(
1145                "right",
1146                &[string("right")],
1147                &[pred("right", &[string("file2"), string("write")])],
1148            ))
1149            .unwrap()
1150            .build(&biscuit1)
1151            .unwrap();
1152
1153        //assert!(v.verify().is_err());
1154        let res = authorizer.authorize_with_limits(AuthorizerLimits {
1155            max_time: Duration::from_secs(10),
1156            ..Default::default()
1157        });
1158        println!("res: {:?}", res);
1159        assert_eq!(
1160            res,
1161            Err(Token::FailedLogic(Logic::NoMatchingPolicy {
1162                checks: vec![FailedCheck::Authorizer(FailedAuthorizerCheck {
1163                    check_id: 0,
1164                    rule: String::from("check if right(\"file2\", \"write\")")
1165                }),]
1166            }))
1167        );
1168    }
1169
1170    #[test]
1171    fn authorizer_queries() {
1172        let mut rng: StdRng = SeedableRng::seed_from_u64(0);
1173        let root = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng);
1174
1175        let biscuit1 = Biscuit::builder()
1176            .right("file1", "read")
1177            .right("file2", "read")
1178            .fact("key(0000)")
1179            .unwrap()
1180            .build_with_rng(&root, default_symbol_table(), &mut rng)
1181            .unwrap();
1182
1183        println!("biscuit1 (authority): {}", biscuit1);
1184
1185        let block2 = BlockBuilder::new()
1186            .check_expiration_date(SystemTime::now() + Duration::from_secs(30))
1187            .fact("key(1234)")
1188            .unwrap();
1189
1190        let keypair2 = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng);
1191        let biscuit2 = biscuit1.append_with_keypair(&keypair2, block2).unwrap();
1192
1193        let block3 = BlockBuilder::new()
1194            .check_expiration_date(SystemTime::now() + Duration::from_secs(10))
1195            .fact("key(5678)")
1196            .unwrap();
1197
1198        let keypair3 = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng);
1199        let biscuit3 = biscuit2.append_with_keypair(&keypair3, block3).unwrap();
1200        {
1201            println!("biscuit3: {}", biscuit3);
1202
1203            let mut authorizer = AuthorizerBuilder::new()
1204                .fact("resource(\"file1\")")
1205                .unwrap()
1206                .fact("operation(\"read\")")
1207                .unwrap()
1208                .time()
1209                .build(&biscuit3)
1210                .unwrap();
1211
1212            // test that cloning correctly embeds the first block's facts
1213            let mut other_authorizer = authorizer.clone();
1214
1215            let authorization_res = authorizer.authorize_with_limits(AuthorizerLimits {
1216                max_time: Duration::from_secs(10),
1217                ..Default::default()
1218            });
1219            println!("authorization result: {:?}", authorization_res);
1220
1221            println!("world:\n{}", authorizer.print_world());
1222            let res2: Result<Vec<builder::Fact>, crate::error::Token> = authorizer
1223                .query_all_with_limits(
1224                    "key_verif($id) <- key($id)",
1225                    AuthorizerLimits {
1226                        max_time: Duration::from_secs(10),
1227                        ..Default::default()
1228                    },
1229                );
1230
1231            println!("res2: {:?}", res2);
1232            let mut res2 = res2
1233                .unwrap()
1234                .iter()
1235                .map(|f| f.to_string())
1236                .collect::<Vec<_>>();
1237            res2.sort();
1238            assert_eq!(
1239                res2,
1240                vec![
1241                    "key_verif(0)".to_string(),
1242                    "key_verif(1234)".to_string(),
1243                    "key_verif(5678)".to_string(),
1244                ]
1245            );
1246
1247            let res1: Result<Vec<builder::Fact>, crate::error::Token> =
1248                other_authorizer.query("key_verif($id) <- key($id)");
1249            println!("res1: {:?}", res1);
1250            assert_eq!(
1251                res1.unwrap()
1252                    .into_iter()
1253                    .map(|f| f.to_string())
1254                    .collect::<Vec<_>>(),
1255                vec!["key_verif(0)".to_string()]
1256            );
1257        }
1258    }
1259
1260    #[test]
1261    fn check_head_name() {
1262        let mut rng: StdRng = SeedableRng::seed_from_u64(0);
1263        let root = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng);
1264
1265        let biscuit1 = Biscuit::builder()
1266            .check(check(
1267                &[pred("resource", &[string("hello")])],
1268                CheckKind::One,
1269            ))
1270            .unwrap()
1271            .build_with_rng(&root, default_symbol_table(), &mut rng)
1272            .unwrap();
1273
1274        println!("biscuit1 (authority): {}", biscuit1);
1275
1276        // new check: can only have read access1
1277        let block2 = BlockBuilder::new()
1278            .fact(fact("check1", &[string("test")]))
1279            .unwrap();
1280
1281        let keypair2 = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng);
1282        let biscuit2 = biscuit1.append_with_keypair(&keypair2, block2).unwrap();
1283
1284        println!("biscuit2: {}", biscuit2);
1285
1286        //println!("generated biscuit token 2: {} bytes\n{}", serialized2.len(), serialized2.to_hex(16));
1287        {
1288            let mut authorizer = AuthorizerBuilder::new()
1289                .fact("resource(\"file1\")")
1290                .unwrap()
1291                .fact("operation(\"read\")")
1292                .unwrap()
1293                .time()
1294                .build(&biscuit2)
1295                .unwrap();
1296
1297            println!("world:\n{}", authorizer.print_world());
1298            println!("symbols: {:?}", authorizer.symbols);
1299
1300            let res = authorizer.authorize_with_limits(AuthorizerLimits {
1301                max_time: Duration::from_secs(10),
1302                ..Default::default()
1303            });
1304            println!("res1: {:?}", res);
1305
1306            assert_eq!(
1307                res,
1308                Err(Token::FailedLogic(Logic::NoMatchingPolicy {
1309                    checks: vec![FailedCheck::Block(FailedBlockCheck {
1310                        block_id: 0,
1311                        check_id: 0,
1312                        rule: String::from("check if resource(\"hello\")"),
1313                    }),]
1314                }))
1315            );
1316        }
1317    }
1318
1319    /*
1320    #[test]
1321    fn check_requires_fact_in_future_block() {
1322        let mut rng: StdRng = SeedableRng::seed_from_u64(0);
1323        let root = KeyPair::new_with_rng(&mut rng);
1324
1325        let mut builder = Biscuit::builder(&root);
1326
1327        builder
1328            .add_authority_check(check(&[pred("name", &[var("name")])]))
1329            .unwrap();
1330
1331        let biscuit1 = builder.build_with_rng(&mut rng).unwrap();
1332
1333        println!("biscuit1 (authority): {}", biscuit1);
1334        let mut authorizer1 = biscuit1.verify().unwrap();
1335        authorizer1.allow().unwrap();
1336        let res1 = authorizer1.verify();
1337        println!("res1: {:?}", res1);
1338        assert_eq!(
1339            res1,
1340            Err(Token::FailedLogic(Logic::FailedChecks(vec![
1341                FailedCheck::Block(FailedBlockCheck {
1342                    block_id: 0,
1343                    check_id: 0,
1344                    rule: String::from("check if name($name)"),
1345                }),
1346            ])))
1347        );
1348
1349        let mut block2 = BlockBuilder::new();
1350        block2.add_fact(fact("name", &[string("test")])).unwrap();
1351
1352        let keypair2 = KeyPair::new_with_rng(&mut rng);
1353        let biscuit2 = biscuit1
1354            .append_with_keypair(&keypair2, block2)
1355            .unwrap();
1356
1357        println!("biscuit2 (with name fact): {}", biscuit2);
1358        let mut authorizer2 = biscuit2.verify().unwrap();
1359        authorizer2.allow().unwrap();
1360        let res2 = authorizer2.verify();
1361        assert_eq!(res2, Ok(0));
1362    }*/
1363
1364    #[test]
1365    fn bytes_constraints() {
1366        let mut rng: StdRng = SeedableRng::seed_from_u64(0);
1367        let root = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng);
1368
1369        let biscuit1 = Biscuit::builder()
1370            .fact("bytes(hex:0102AB)")
1371            .unwrap()
1372            .build_with_rng(&root, default_symbol_table(), &mut rng)
1373            .unwrap();
1374
1375        println!("biscuit1 (authority): {}", biscuit1);
1376
1377        let block2 = BlockBuilder::new()
1378            .rule("has_bytes($0) <- bytes($0), { hex:00000000, hex:0102AB }.contains($0)")
1379            .unwrap();
1380        let keypair2 = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng);
1381        let biscuit2 = biscuit1.append_with_keypair(&keypair2, block2).unwrap();
1382
1383        let mut authorizer = AuthorizerBuilder::new()
1384            .check("check if bytes($0), { hex:00000000, hex:0102AB }.contains($0)")
1385            .unwrap()
1386            .allow_all()
1387            .set_limits(AuthorizerLimits {
1388                max_time: Duration::from_secs(10),
1389                ..Default::default()
1390            })
1391            .build(&biscuit2)
1392            .unwrap();
1393
1394        let res = authorizer.authorize_with_limits(AuthorizerLimits {
1395            max_time: Duration::from_secs(10),
1396            ..Default::default()
1397        });
1398        println!("res1: {:?}", res);
1399        res.unwrap();
1400
1401        let res: Vec<(Vec<u8>,)> = authorizer
1402            .query_with_limits(
1403                "data($0) <- bytes($0)",
1404                AuthorizerLimits {
1405                    max_time: Duration::from_secs(10),
1406                    ..Default::default()
1407                },
1408            )
1409            .unwrap();
1410        println!("query result: {:x?}", res);
1411        println!("query result: {:?}", res[0]);
1412    }
1413
1414    #[test]
1415    fn block1_generates_authority_or_ambient() {
1416        let mut rng: StdRng = SeedableRng::seed_from_u64(0);
1417        let root = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng);
1418
1419        let serialized1 = {
1420            let biscuit1 = Biscuit::builder()
1421                .fact("right(\"/folder1/file1\", \"read\")")
1422                .unwrap()
1423                .fact("right(\"/folder1/file1\", \"write\")")
1424                .unwrap()
1425                .fact("right(\"/folder2/file1\", \"read\")")
1426                .unwrap()
1427                .check("check if operation(\"read\")")
1428                .unwrap()
1429                .build_with_rng(&root, default_symbol_table(), &mut rng)
1430                .unwrap();
1431
1432            println!("biscuit1 (authority): {}", biscuit1);
1433
1434            biscuit1.to_vec().unwrap()
1435        };
1436
1437        //println!("generated biscuit token: {} bytes:\n{}", serialized1.len(), serialized1.to_hex(16));
1438        println!("generated biscuit token: {} bytes", serialized1.len());
1439        //panic!();
1440
1441        let serialized2 = {
1442            let biscuit1_deser = Biscuit::from(&serialized1, |_| Ok(root.public())).unwrap();
1443
1444            // new check: can only have read access1
1445            let  block2 = BlockBuilder::new()
1446
1447            // Bypass `check if operation("read")` from authority block
1448                .rule("operation(\"read\") <- operation($any)")
1449                .unwrap()
1450
1451            // Bypass `check if resource($file), $file.starts_with("/folder1/")` from block #1
1452                .rule("resource(\"/folder1/\") <- resource($any)")
1453                .unwrap()
1454
1455            // Add missing rights
1456          .rule("right($file, $right) <- right($any1, $any2), resource($file), operation($right)")
1457                .unwrap();
1458
1459            let keypair2 = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng);
1460            let biscuit2 = biscuit1_deser
1461                .append_with_keypair(&keypair2, block2)
1462                .unwrap();
1463
1464            println!("biscuit2 (1 check): {}", biscuit2);
1465
1466            biscuit2.to_vec().unwrap()
1467        };
1468
1469        //println!("generated biscuit token 2: {} bytes\n{}", serialized2.len(), serialized2.to_hex(16));
1470        println!("generated biscuit token 2: {} bytes", serialized2.len());
1471
1472        let final_token = Biscuit::from(&serialized2, root.public()).unwrap();
1473        println!("final token:\n{}", final_token);
1474
1475        let mut authorizer = AuthorizerBuilder::new()
1476            .fact("resource(\"/folder2/file1\")")
1477            .unwrap()
1478            .fact("operation(\"write\")")
1479            .unwrap()
1480            .policy("allow if resource($file), operation($op), right($file, $op)")
1481            .unwrap()
1482            .deny_all()
1483            .build(&final_token)
1484            .unwrap();
1485
1486        let res = authorizer.authorize_with_limits(crate::token::authorizer::AuthorizerLimits {
1487            max_time: Duration::from_secs(1),
1488            ..Default::default()
1489        });
1490        println!("res1: {:?}", res);
1491        println!("authorizer:\n{}", authorizer.print_world());
1492
1493        assert!(res.is_err());
1494    }
1495
1496    #[test]
1497    fn check_all() {
1498        let mut rng: StdRng = SeedableRng::seed_from_u64(0);
1499        let root = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng);
1500
1501        let biscuit1 = Biscuit::builder()
1502            .check("check if fact($v), $v < 1")
1503            .unwrap()
1504            .build_with_rng(&root, default_symbol_table(), &mut rng)
1505            .unwrap();
1506
1507        println!("biscuit1 (authority): {}", biscuit1);
1508
1509        let biscuit2 = Biscuit::builder()
1510            .check("check all fact($v), $v < 1")
1511            .unwrap()
1512            .build_with_rng(&root, default_symbol_table(), &mut rng)
1513            .unwrap();
1514
1515        println!("biscuit2 (authority): {}", biscuit2);
1516
1517        {
1518            let mut authorizer = AuthorizerBuilder::new()
1519                .fact("fact(0)")
1520                .unwrap()
1521                .fact("fact(1)")
1522                .unwrap()
1523                //println!("final token: {:#?}", final_token);
1524                .allow_all()
1525                .build(&biscuit1)
1526                .unwrap();
1527
1528            let res = authorizer.authorize_with_limits(AuthorizerLimits {
1529                max_time: Duration::from_secs(10),
1530                ..Default::default()
1531            });
1532            println!("res1: {:?}", res);
1533            res.unwrap();
1534        }
1535
1536        {
1537            let mut authorizer = AuthorizerBuilder::new()
1538                .fact("fact(0)")
1539                .unwrap()
1540                .fact("fact(1)")
1541                .unwrap()
1542                //println!("final token: {:#?}", final_token);
1543                .allow_all()
1544                .build(&biscuit2)
1545                .unwrap();
1546
1547            let res = authorizer.authorize_with_limits(AuthorizerLimits {
1548                max_time: Duration::from_secs(10),
1549                ..Default::default()
1550            });
1551            println!("res2: {:?}", res);
1552
1553            assert_eq!(
1554                res,
1555                Err(Token::FailedLogic(Logic::Unauthorized {
1556                    policy: MatchedPolicy::Allow(0),
1557                    checks: vec![FailedCheck::Block(FailedBlockCheck {
1558                        block_id: 0,
1559                        check_id: 0,
1560                        rule: String::from("check all fact($v), $v < 1"),
1561                    }),]
1562                }))
1563            );
1564        }
1565    }
1566
1567    // check that we can still allow the verification of the old 3rd party block signature
1568    #[test]
1569    fn third_party_unsafe_deserialize() {
1570        // this is a token generated with the old third party signature, that does not include the previous block's signature
1571        let token_bytes = include_bytes!("../../tests/fixtures/unsafe_third_party.bc");
1572        let _ = UnverifiedBiscuit::unsafe_deprecated_deserialize(token_bytes).unwrap();
1573        assert_eq!(
1574            UnverifiedBiscuit::from(token_bytes).unwrap_err(),
1575            error::Token::Format(error::Format::DeserializationError(
1576                "Unsupported third party block version".to_string()
1577            ))
1578        );
1579
1580        let root_key = PublicKey::from_bytes_hex(
1581            "1055c750b1a1505937af1537c626ba3263995c33a64758aaafb1275b0312e284",
1582            builder::Algorithm::Ed25519,
1583        )
1584        .unwrap();
1585        let _ = Biscuit::unsafe_deprecated_deserialize(token_bytes, root_key).unwrap();
1586        assert_eq!(
1587            Biscuit::from(token_bytes, root_key).unwrap_err(),
1588            error::Token::Format(error::Format::DeserializationError(
1589                "Unsupported third party block version".to_string()
1590            ))
1591        );
1592    }
1593
1594    // tests that the authority block signature version 1 works
1595    #[test]
1596    fn authority_signature_v1() {
1597        let mut rng: StdRng = SeedableRng::seed_from_u64(0);
1598        let root = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng);
1599
1600        let authority_block = Block {
1601            symbols: default_symbol_table(),
1602            facts: vec![],
1603            rules: vec![],
1604            checks: vec![],
1605            context: None,
1606            version: 0,
1607            external_key: None,
1608            public_keys: PublicKeys::new(),
1609            scopes: vec![],
1610        };
1611
1612        let next_keypair = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng);
1613        let token =
1614            SerializedBiscuit::new_inner(None, &root, &next_keypair, &authority_block, 1).unwrap();
1615        let serialized = token.to_vec().unwrap();
1616
1617        let _ = Biscuit::from(&serialized, root.public()).unwrap();
1618    }
1619
1620    #[test]
1621    fn verified_unverified_consistency() {
1622        let mut rng: StdRng = SeedableRng::seed_from_u64(0);
1623        let root = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng);
1624        let biscuit1 = Biscuit::builder()
1625            .fact("right(\"file1\", \"read\")")
1626            .unwrap()
1627            .fact("right(\"file2\", \"read\")")
1628            .unwrap()
1629            .fact("right(\"file1\", \"write\")")
1630            .unwrap()
1631            .build_with_rng(&root, default_symbol_table(), &mut rng)
1632            .unwrap();
1633
1634        println!("biscuit1 (authority): {}", biscuit1);
1635
1636        let serialized = biscuit1.to_vec().unwrap();
1637
1638        let parsed = UnverifiedBiscuit::from(serialized).unwrap();
1639
1640        for i in 0..parsed.block_count() {
1641            assert_eq!(parsed.print_block_source(i), biscuit1.print_block_source(i));
1642            assert_eq!(parsed.block_version(i), biscuit1.block_version(i));
1643        }
1644    }
1645}