biscuit_auth/token/
mod.rs

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