biscuit_auth/token/
authorizer.rs

1//! Authorizer structure and associated functions
2use super::builder::{
3    constrained_rule, date, fact, pred, rule, string, var, Binary, BlockBuilder, Check, Expression,
4    Fact, Op, Policy, PolicyKind, Rule, Scope, Term,
5};
6use super::builder_ext::{AuthorizerExt, BuilderExt};
7use super::{Biscuit, Block};
8use crate::builder::{self, CheckKind, Convert};
9use crate::crypto::PublicKey;
10use crate::datalog::{self, Origin, RunLimits, SymbolTable, TrustedOrigins};
11use crate::error;
12use crate::time::Instant;
13use crate::token;
14use biscuit_parser::parser::parse_source;
15use prost::Message;
16use std::collections::{BTreeMap, HashSet};
17use std::time::Duration;
18use std::{
19    collections::HashMap,
20    convert::{TryFrom, TryInto},
21    default::Default,
22    fmt::Write,
23    time::SystemTime,
24};
25
26mod snapshot;
27
28/// used to check authorization policies on a token
29///
30/// can be created from [Biscuit::authorizer] or [Authorizer::new]
31#[derive(Clone)]
32pub struct Authorizer {
33    authorizer_block_builder: BlockBuilder,
34    world: datalog::World,
35    pub(crate) symbols: datalog::SymbolTable,
36    token_origins: TrustedOrigins,
37    policies: Vec<Policy>,
38    blocks: Option<Vec<Block>>,
39    public_key_to_block_id: HashMap<usize, Vec<usize>>,
40    limits: AuthorizerLimits,
41    execution_time: Duration,
42}
43
44impl Authorizer {
45    pub(crate) fn from_token(token: &Biscuit) -> Result<Self, error::Token> {
46        let mut v = Authorizer::new();
47        v.add_token(token)?;
48
49        Ok(v)
50    }
51
52    /// creates a new empty authorizer
53    ///
54    /// this can be used to check policies when:
55    /// * there is no token (unauthenticated case)
56    /// * there is a lot of data to load in the authorizer on each check
57    ///
58    /// In the latter case, we can create an empty authorizer, load it
59    /// with the facts, rules and checks, and each time a token must be checked,
60    /// clone the authorizer and load the token with [`Authorizer::add_token`]
61    pub fn new() -> Self {
62        let world = datalog::World::new();
63        let symbols = super::default_symbol_table();
64        let authorizer_block_builder = BlockBuilder::new();
65
66        Authorizer {
67            authorizer_block_builder,
68            world,
69            symbols,
70            token_origins: TrustedOrigins::default(),
71            policies: vec![],
72            blocks: None,
73            public_key_to_block_id: HashMap::new(),
74            limits: AuthorizerLimits::default(),
75            execution_time: Duration::default(),
76        }
77    }
78
79    /// creates an `Authorizer` from a serialized [crate::format::schema::AuthorizerPolicies]
80    pub fn from(data: &[u8]) -> Result<Self, error::Token> {
81        AuthorizerPolicies::deserialize(data)?.try_into()
82    }
83
84    /// add a token to an empty authorizer
85    pub fn add_token(&mut self, token: &Biscuit) -> Result<(), error::Token> {
86        if self.blocks.is_some() {
87            return Err(error::Logic::AuthorizerNotEmpty.into());
88        }
89
90        for (i, block) in token.container.blocks.iter().enumerate() {
91            if let Some(sig) = block.external_signature.as_ref() {
92                let new_key_id = self.symbols.public_keys.insert(&sig.public_key);
93
94                self.public_key_to_block_id
95                    .entry(new_key_id as usize)
96                    .or_default()
97                    .push(i + 1);
98            }
99        }
100
101        let mut blocks = Vec::new();
102
103        for i in 0..token.block_count() {
104            let mut block = token.block(i)?;
105
106            self.load_and_translate_block(&mut block, i, &token.symbols)?;
107
108            blocks.push(block);
109        }
110
111        self.blocks = Some(blocks);
112        self.token_origins = TrustedOrigins::from_scopes(
113            &[token::Scope::Previous],
114            &TrustedOrigins::default(),
115            token.block_count(),
116            &self.public_key_to_block_id,
117        );
118
119        Ok(())
120    }
121
122    /// we need to modify the block loaded from the token, because the authorizer's and the token's symbol table can differ
123    fn load_and_translate_block(
124        &mut self,
125        block: &mut Block,
126        i: usize,
127        token_symbols: &SymbolTable,
128    ) -> Result<(), error::Token> {
129        // if it is a 3rd party block, it should not affect the main symbol table
130        let block_symbols = if i == 0 || block.external_key.is_none() {
131            token_symbols.clone()
132        } else {
133            block.symbols.clone()
134        };
135
136        let mut block_origin = Origin::default();
137        block_origin.insert(i);
138
139        for scope in block.scopes.iter_mut() {
140            *scope = builder::Scope::convert_from(scope, &block_symbols)
141                .map(|s| s.convert(&mut self.symbols))?;
142        }
143
144        let block_trusted_origins = TrustedOrigins::from_scopes(
145            &block.scopes,
146            &TrustedOrigins::default(),
147            i,
148            &self.public_key_to_block_id,
149        );
150
151        for fact in block.facts.iter_mut() {
152            *fact = Fact::convert_from(fact, &block_symbols)?.convert(&mut self.symbols);
153            self.world.facts.insert(&block_origin, fact.clone());
154        }
155
156        for rule in block.rules.iter_mut() {
157            if let Err(_message) = rule.validate_variables(&block_symbols) {
158                return Err(
159                    error::Logic::InvalidBlockRule(0, block_symbols.print_rule(rule)).into(),
160                );
161            }
162            *rule = rule.translate(&block_symbols, &mut self.symbols)?;
163
164            let rule_trusted_origins = TrustedOrigins::from_scopes(
165                &rule.scopes,
166                &block_trusted_origins,
167                i,
168                &self.public_key_to_block_id,
169            );
170
171            self.world
172                .rules
173                .insert(i, &rule_trusted_origins, rule.clone());
174        }
175
176        for check in block.checks.iter_mut() {
177            let c = Check::convert_from(check, &block_symbols)?;
178            *check = c.convert(&mut self.symbols);
179        }
180
181        Ok(())
182    }
183
184    /// serializes a authorizer's content
185    ///
186    /// you can use this to save a set of policies and load them quickly before
187    /// verification. This will not store data obtained or generated from a token.
188    pub fn save(&self) -> Result<AuthorizerPolicies, error::Token> {
189        let facts = self.authorizer_block_builder.facts.to_vec();
190
191        let rules = self.authorizer_block_builder.rules.to_vec();
192
193        let checks = self.authorizer_block_builder.checks.to_vec();
194
195        Ok(AuthorizerPolicies {
196            version: crate::token::MAX_SCHEMA_VERSION,
197            facts,
198            rules,
199            checks,
200            policies: self.policies.clone(),
201        })
202    }
203
204    /// Add the rules, facts, checks, and policies of another `Authorizer`.
205    /// If a token has already been added to `other`, it is not merged into `self`.
206    pub fn merge(&mut self, mut other: Authorizer) {
207        self.merge_block(other.authorizer_block_builder);
208        self.policies.append(&mut other.policies);
209    }
210
211    /// Add the rules, facts, and checks of another `BlockBuilder`.
212    pub fn merge_block(&mut self, other: BlockBuilder) {
213        self.authorizer_block_builder.merge(other)
214    }
215
216    pub fn add_fact<F: TryInto<Fact>>(&mut self, fact: F) -> Result<(), error::Token>
217    where
218        error::Token: From<<F as TryInto<Fact>>::Error>,
219    {
220        self.authorizer_block_builder.add_fact(fact)
221    }
222
223    pub fn add_rule<Ru: TryInto<Rule>>(&mut self, rule: Ru) -> Result<(), error::Token>
224    where
225        error::Token: From<<Ru as TryInto<Rule>>::Error>,
226    {
227        self.authorizer_block_builder.add_rule(rule)
228    }
229
230    pub fn add_check<C: TryInto<Check>>(&mut self, check: C) -> Result<(), error::Token>
231    where
232        error::Token: From<<C as TryInto<Check>>::Error>,
233    {
234        self.authorizer_block_builder.add_check(check)
235    }
236
237    /// adds some datalog code to the authorizer
238    ///
239    /// ```rust
240    /// extern crate biscuit_auth as biscuit;
241    ///
242    /// use biscuit::Authorizer;
243    ///
244    /// let mut authorizer = Authorizer::new();
245    ///
246    /// authorizer.add_code(r#"
247    ///   resource("/file1.txt");
248    ///
249    ///   check if user(1234);
250    ///
251    ///   // default allow
252    ///   allow if true;
253    /// "#).expect("should parse correctly");
254    /// ```
255    pub fn add_code<T: AsRef<str>>(&mut self, source: T) -> Result<(), error::Token> {
256        self.add_code_with_params(source, HashMap::new(), HashMap::new())
257    }
258
259    pub fn add_code_with_params<T: AsRef<str>>(
260        &mut self,
261        source: T,
262        params: HashMap<String, Term>,
263        scope_params: HashMap<String, PublicKey>,
264    ) -> Result<(), error::Token> {
265        let source = source.as_ref();
266
267        let source_result = parse_source(source).map_err(|e| {
268            let e2: biscuit_parser::error::LanguageError = e.into();
269            e2
270        })?;
271
272        for (_, fact) in source_result.facts.into_iter() {
273            let mut fact: Fact = fact.into();
274            for (name, value) in &params {
275                let res = match fact.set(name, value) {
276                    Ok(_) => Ok(()),
277                    Err(error::Token::Language(
278                        biscuit_parser::error::LanguageError::Parameters {
279                            missing_parameters, ..
280                        },
281                    )) if missing_parameters.is_empty() => Ok(()),
282                    Err(e) => Err(e),
283                };
284                res?;
285            }
286            fact.validate()?;
287            self.authorizer_block_builder.facts.push(fact);
288        }
289
290        for (_, rule) in source_result.rules.into_iter() {
291            let mut rule: Rule = rule.into();
292            for (name, value) in &params {
293                let res = match rule.set(name, value) {
294                    Ok(_) => Ok(()),
295                    Err(error::Token::Language(
296                        biscuit_parser::error::LanguageError::Parameters {
297                            missing_parameters, ..
298                        },
299                    )) if missing_parameters.is_empty() => Ok(()),
300                    Err(e) => Err(e),
301                };
302                res?;
303            }
304            for (name, value) in &scope_params {
305                let res = match rule.set_scope(name, *value) {
306                    Ok(_) => Ok(()),
307                    Err(error::Token::Language(
308                        biscuit_parser::error::LanguageError::Parameters {
309                            missing_parameters, ..
310                        },
311                    )) if missing_parameters.is_empty() => Ok(()),
312                    Err(e) => Err(e),
313                };
314                res?;
315            }
316            rule.validate_parameters()?;
317            self.authorizer_block_builder.rules.push(rule);
318        }
319
320        for (_, check) in source_result.checks.into_iter() {
321            let mut check: Check = check.into();
322            for (name, value) in &params {
323                let res = match check.set(name, value) {
324                    Ok(_) => Ok(()),
325                    Err(error::Token::Language(
326                        biscuit_parser::error::LanguageError::Parameters {
327                            missing_parameters, ..
328                        },
329                    )) if missing_parameters.is_empty() => Ok(()),
330                    Err(e) => Err(e),
331                };
332                res?;
333            }
334            for (name, value) in &scope_params {
335                let res = match check.set_scope(name, *value) {
336                    Ok(_) => Ok(()),
337                    Err(error::Token::Language(
338                        biscuit_parser::error::LanguageError::Parameters {
339                            missing_parameters, ..
340                        },
341                    )) if missing_parameters.is_empty() => Ok(()),
342                    Err(e) => Err(e),
343                };
344                res?;
345            }
346            check.validate_parameters()?;
347            self.authorizer_block_builder.checks.push(check);
348        }
349        for (_, policy) in source_result.policies.into_iter() {
350            let mut policy: Policy = policy.into();
351            for (name, value) in &params {
352                let res = match policy.set(name, value) {
353                    Ok(_) => Ok(()),
354                    Err(error::Token::Language(
355                        biscuit_parser::error::LanguageError::Parameters {
356                            missing_parameters, ..
357                        },
358                    )) if missing_parameters.is_empty() => Ok(()),
359                    Err(e) => Err(e),
360                };
361                res?;
362            }
363            for (name, value) in &scope_params {
364                let res = match policy.set_scope(name, *value) {
365                    Ok(_) => Ok(()),
366                    Err(error::Token::Language(
367                        biscuit_parser::error::LanguageError::Parameters {
368                            missing_parameters, ..
369                        },
370                    )) if missing_parameters.is_empty() => Ok(()),
371                    Err(e) => Err(e),
372                };
373                res?;
374            }
375            policy.validate_parameters()?;
376            self.policies.push(policy);
377        }
378
379        Ok(())
380    }
381
382    pub fn add_scope(&mut self, scope: Scope) {
383        self.authorizer_block_builder.add_scope(scope);
384    }
385
386    /// Returns the runtime limits of the authorizer
387    ///
388    /// Those limits cover all the executions under the `authorize`, `query` and `query_all` methods
389    pub fn limits(&self) -> &AuthorizerLimits {
390        &self.limits
391    }
392
393    /// Sets the runtime limits of the authorizer
394    ///
395    /// Those limits cover all the executions under the `authorize`, `query` and `query_all` methods
396    pub fn set_limits(&mut self, limits: AuthorizerLimits) {
397        self.limits = limits;
398    }
399
400    /// run a query over the authorizer's Datalog engine to gather data
401    ///
402    /// ```rust
403    /// # use biscuit_auth::KeyPair;
404    /// # use biscuit_auth::Biscuit;
405    /// let keypair = KeyPair::new();
406    /// let mut builder = Biscuit::builder();
407    /// builder.add_fact("user(\"John Doe\", 42)");
408    ///
409    /// let biscuit = builder.build(&keypair).unwrap();
410    ///
411    /// let mut authorizer = biscuit.authorizer().unwrap();
412    /// let res: Vec<(String, i64)> = authorizer.query("data($name, $id) <- user($name, $id)").unwrap();
413    /// # assert_eq!(res.len(), 1);
414    /// # assert_eq!(res[0].0, "John Doe");
415    /// # assert_eq!(res[0].1, 42);
416    /// ```
417    // TODO rename as `query_token`
418    pub fn query<R: TryInto<Rule>, T: TryFrom<Fact, Error = E>, E: Into<error::Token>>(
419        &mut self,
420        rule: R,
421    ) -> Result<Vec<T>, error::Token>
422    where
423        error::Token: From<<R as TryInto<Rule>>::Error>,
424    {
425        let mut limits = self.limits.clone();
426        limits.max_iterations -= self.world.iterations;
427        if self.execution_time >= limits.max_time {
428            return Err(error::Token::RunLimit(error::RunLimit::Timeout));
429        }
430        limits.max_time -= self.execution_time;
431
432        self.query_with_limits(rule, limits)
433    }
434
435    /// run a query over the authorizer's Datalog engine to gather data
436    ///
437    /// this only sees facts from the authorizer and the authority block
438    ///
439    /// this method overrides the authorizer's runtime limits, just for this calls
440    pub fn query_with_limits<R: TryInto<Rule>, T: TryFrom<Fact, Error = E>, E: Into<error::Token>>(
441        &mut self,
442        rule: R,
443        limits: AuthorizerLimits,
444    ) -> Result<Vec<T>, error::Token>
445    where
446        error::Token: From<<R as TryInto<Rule>>::Error>,
447    {
448        let rule = rule.try_into()?.convert(&mut self.symbols);
449
450        let start = Instant::now();
451        let result = self.query_inner(rule, limits);
452        self.execution_time += start.elapsed();
453
454        result
455    }
456
457    fn query_inner<T: TryFrom<Fact, Error = E>, E: Into<error::Token>>(
458        &mut self,
459        rule: datalog::Rule,
460        limits: AuthorizerLimits,
461    ) -> Result<Vec<T>, error::Token> {
462        let rule_trusted_origins = TrustedOrigins::from_scopes(
463            &rule.scopes,
464            &TrustedOrigins::default(), // for queries, we don't want to default on the authorizer trust
465            // queries are there to explore the final state of the world,
466            // whereas authorizer contents are there to authorize or not
467            // a token
468            usize::MAX,
469            &self.public_key_to_block_id,
470        );
471
472        self.world.run_with_limits(&self.symbols, limits)?;
473        let res = self
474            .world
475            .query_rule(rule, usize::MAX, &rule_trusted_origins, &self.symbols)?;
476
477        res.inner
478            .into_iter()
479            .flat_map(|(_, set)| set.into_iter())
480            .map(|f| Fact::convert_from(&f, &self.symbols))
481            .map(|fact| {
482                fact.map_err(error::Token::Format)
483                    .and_then(|f| f.try_into().map_err(Into::into))
484            })
485            .collect()
486    }
487
488    /// run a query over the authorizer's Datalog engine to gather data
489    ///
490    /// this has access to the facts generated when evaluating all the blocks
491    ///
492    /// ```rust
493    /// # use biscuit_auth::KeyPair;
494    /// # use biscuit_auth::Biscuit;
495    /// let keypair = KeyPair::new();
496    /// let mut builder = Biscuit::builder();
497    /// builder.add_fact("user(\"John Doe\", 42)");
498    ///
499    /// let biscuit = builder.build(&keypair).unwrap();
500    ///
501    /// let mut authorizer = biscuit.authorizer().unwrap();
502    /// let res: Vec<(String, i64)> = authorizer.query_all("data($name, $id) <- user($name, $id)").unwrap();
503    /// # assert_eq!(res.len(), 1);
504    /// # assert_eq!(res[0].0, "John Doe");
505    /// # assert_eq!(res[0].1, 42);
506    /// ```
507    pub fn query_all<R: TryInto<Rule>, T: TryFrom<Fact, Error = E>, E: Into<error::Token>>(
508        &mut self,
509        rule: R,
510    ) -> Result<Vec<T>, error::Token>
511    where
512        error::Token: From<<R as TryInto<Rule>>::Error>,
513    {
514        let mut limits = self.limits.clone();
515        limits.max_iterations -= self.world.iterations;
516        if self.execution_time >= limits.max_time {
517            return Err(error::Token::RunLimit(error::RunLimit::Timeout));
518        }
519        limits.max_time -= self.execution_time;
520
521        self.query_all_with_limits(rule, limits)
522    }
523
524    /// run a query over the authorizer's Datalog engine to gather data
525    ///
526    /// this has access to the facts generated when evaluating all the blocks
527    ///
528    /// this method overrides the authorizer's runtime limits, just for this calls
529    pub fn query_all_with_limits<
530        R: TryInto<Rule>,
531        T: TryFrom<Fact, Error = E>,
532        E: Into<error::Token>,
533    >(
534        &mut self,
535        rule: R,
536        limits: AuthorizerLimits,
537    ) -> Result<Vec<T>, error::Token>
538    where
539        error::Token: From<<R as TryInto<Rule>>::Error>,
540    {
541        let rule = rule.try_into()?.convert(&mut self.symbols);
542
543        let start = Instant::now();
544        let result = self.query_all_inner(rule, limits);
545        self.execution_time += start.elapsed();
546
547        result
548    }
549
550    fn query_all_inner<T: TryFrom<Fact, Error = E>, E: Into<error::Token>>(
551        &mut self,
552        rule: datalog::Rule,
553        limits: AuthorizerLimits,
554    ) -> Result<Vec<T>, error::Token> {
555        self.world.run_with_limits(&self.symbols, limits)?;
556
557        let rule_trusted_origins = if rule.scopes.is_empty() {
558            self.token_origins.clone()
559        } else {
560            TrustedOrigins::from_scopes(
561                &rule.scopes,
562                &TrustedOrigins::default(), // for queries, we don't want to default on the authorizer trust
563                // queries are there to explore the final state of the world,
564                // whereas authorizer contents are there to authorize or not
565                // a token
566                usize::MAX,
567                &self.public_key_to_block_id,
568            )
569        };
570
571        let res = self
572            .world
573            .query_rule(rule, 0, &rule_trusted_origins, &self.symbols)?;
574
575        let r: HashSet<_> = res.into_iter().map(|(_, fact)| fact).collect();
576
577        r.into_iter()
578            .map(|f| Fact::convert_from(&f, &self.symbols))
579            .map(|fact| {
580                fact.map_err(error::Token::Format)
581                    .and_then(|f| f.try_into().map_err(Into::into))
582            })
583            .collect::<Result<Vec<T>, _>>()
584    }
585
586    /// adds a fact with the current time
587    pub fn set_time(&mut self) {
588        let fact = fact("time", &[date(&SystemTime::now())]);
589        self.authorizer_block_builder.add_fact(fact).unwrap();
590    }
591
592    /// add a policy to the authorizer
593    pub fn add_policy<P: TryInto<Policy>>(&mut self, policy: P) -> Result<(), error::Token>
594    where
595        error::Token: From<<P as TryInto<Policy>>::Error>,
596    {
597        let policy = policy.try_into()?;
598        policy.validate_parameters()?;
599        self.policies.push(policy);
600        Ok(())
601    }
602
603    /// todo remove, it's covered in BuilderExt
604    /// adds a `allow if true` policy
605    pub fn allow(&mut self) -> Result<(), error::Token> {
606        self.add_policy("allow if true")
607    }
608
609    /// adds a `deny if true` policy
610    pub fn deny(&mut self) -> Result<(), error::Token> {
611        self.add_policy("deny if true")
612    }
613
614    /// returns the elapsed execution time
615    pub fn execution_time(&self) -> Duration {
616        self.execution_time
617    }
618
619    /// returns the number of fact generation iterations
620    pub fn iterations(&self) -> u64 {
621        self.world.iterations
622    }
623
624    /// returns the number of facts
625    pub fn fact_count(&self) -> usize {
626        self.world.facts.len()
627    }
628
629    /// verifies the checks and policies
630    ///
631    /// on error, this can return a list of all the failed checks or deny policy
632    /// on success, it returns the index of the policy that matched
633    pub fn authorize(&mut self) -> Result<usize, error::Token> {
634        let mut limits = self.limits.clone();
635        limits.max_iterations -= self.world.iterations;
636        if self.execution_time >= limits.max_time {
637            return Err(error::Token::RunLimit(error::RunLimit::Timeout));
638        }
639        limits.max_time -= self.execution_time;
640
641        self.authorize_with_limits(limits)
642    }
643
644    /// TODO: consume the input to prevent further direct use
645    /// verifies the checks and policies
646    ///
647    /// on error, this can return a list of all the failed checks or deny policy
648    ///
649    /// this method overrides the authorizer's runtime limits, just for this calls
650    pub fn authorize_with_limits(
651        &mut self,
652        limits: AuthorizerLimits,
653    ) -> Result<usize, error::Token> {
654        let start = Instant::now();
655        let result = self.authorize_inner(limits);
656        self.execution_time += start.elapsed();
657
658        result
659    }
660
661    fn authorize_inner(&mut self, mut limits: AuthorizerLimits) -> Result<usize, error::Token> {
662        let start = Instant::now();
663        let time_limit = start + limits.max_time;
664        let mut current_iterations = self.world.iterations;
665
666        let mut errors = vec![];
667        let mut policy_result: Option<Result<usize, usize>> = None;
668
669        let mut authorizer_origin = Origin::default();
670        authorizer_origin.insert(usize::MAX);
671
672        let authorizer_scopes: Vec<token::Scope> = self
673            .authorizer_block_builder
674            .scopes
675            .clone()
676            .iter()
677            .map(|s| s.convert(&mut self.symbols))
678            .collect();
679
680        let authorizer_trusted_origins = TrustedOrigins::from_scopes(
681            &authorizer_scopes,
682            &TrustedOrigins::default(),
683            usize::MAX,
684            &self.public_key_to_block_id,
685        );
686
687        for fact in &self.authorizer_block_builder.facts {
688            self.world
689                .facts
690                .insert(&authorizer_origin, fact.convert(&mut self.symbols));
691        }
692
693        for rule in &self.authorizer_block_builder.rules {
694            let rule = rule.convert(&mut self.symbols);
695
696            let rule_trusted_origins = TrustedOrigins::from_scopes(
697                &rule.scopes,
698                &authorizer_trusted_origins,
699                usize::MAX,
700                &self.public_key_to_block_id,
701            );
702
703            self.world
704                .rules
705                .insert(usize::MAX, &rule_trusted_origins, rule);
706        }
707
708        limits.max_time = time_limit - Instant::now();
709        self.world.run_with_limits(&self.symbols, limits.clone())?;
710
711        let authorizer_scopes: Vec<token::Scope> = self
712            .authorizer_block_builder
713            .scopes
714            .clone()
715            .iter()
716            .map(|s| s.convert(&mut self.symbols))
717            .collect();
718
719        let authorizer_trusted_origins = TrustedOrigins::from_scopes(
720            &authorizer_scopes,
721            &TrustedOrigins::default(),
722            usize::MAX,
723            &self.public_key_to_block_id,
724        );
725
726        for (i, check) in self.authorizer_block_builder.checks.iter().enumerate() {
727            let c = check.convert(&mut self.symbols);
728            let mut successful = false;
729
730            for query in check.queries.iter() {
731                let query = query.convert(&mut self.symbols);
732                let rule_trusted_origins = TrustedOrigins::from_scopes(
733                    &query.scopes,
734                    &authorizer_trusted_origins,
735                    usize::MAX,
736                    &self.public_key_to_block_id,
737                );
738                let res = match check.kind {
739                    CheckKind::One => self.world.query_match(
740                        query,
741                        usize::MAX,
742                        &rule_trusted_origins,
743                        &self.symbols,
744                    )?,
745                    CheckKind::All => {
746                        self.world
747                            .query_match_all(query, &rule_trusted_origins, &self.symbols)?
748                    }
749                };
750
751                let now = Instant::now();
752                if now >= time_limit {
753                    return Err(error::Token::RunLimit(error::RunLimit::Timeout));
754                }
755
756                if res {
757                    successful = true;
758                    break;
759                }
760            }
761
762            if !successful {
763                errors.push(error::FailedCheck::Authorizer(
764                    error::FailedAuthorizerCheck {
765                        check_id: i as u32,
766                        rule: self.symbols.print_check(&c),
767                    },
768                ));
769            }
770        }
771
772        if let Some(blocks) = self.blocks.as_ref() {
773            for (j, check) in blocks[0].checks.iter().enumerate() {
774                let mut successful = false;
775
776                let authority_trusted_origins = TrustedOrigins::from_scopes(
777                    &blocks[0].scopes,
778                    &TrustedOrigins::default(),
779                    0,
780                    &self.public_key_to_block_id,
781                );
782
783                for query in check.queries.iter() {
784                    let rule_trusted_origins = TrustedOrigins::from_scopes(
785                        &query.scopes,
786                        &authority_trusted_origins,
787                        0,
788                        &self.public_key_to_block_id,
789                    );
790                    let res = match check.kind {
791                        CheckKind::One => self.world.query_match(
792                            query.clone(),
793                            0,
794                            &rule_trusted_origins,
795                            &self.symbols,
796                        )?,
797                        CheckKind::All => self.world.query_match_all(
798                            query.clone(),
799                            &rule_trusted_origins,
800                            &self.symbols,
801                        )?,
802                    };
803
804                    let now = Instant::now();
805                    if now >= time_limit {
806                        return Err(error::Token::RunLimit(error::RunLimit::Timeout));
807                    }
808
809                    if res {
810                        successful = true;
811                        break;
812                    }
813                }
814
815                if !successful {
816                    errors.push(error::FailedCheck::Block(error::FailedBlockCheck {
817                        block_id: 0u32,
818                        check_id: j as u32,
819                        rule: self.symbols.print_check(check),
820                    }));
821                }
822            }
823        }
824
825        'policies_test: for (i, policy) in self.policies.iter().enumerate() {
826            for query in policy.queries.iter() {
827                let query = query.convert(&mut self.symbols);
828                let rule_trusted_origins = TrustedOrigins::from_scopes(
829                    &query.scopes,
830                    &authorizer_trusted_origins,
831                    usize::MAX,
832                    &self.public_key_to_block_id,
833                );
834
835                let res = self.world.query_match(
836                    query,
837                    usize::MAX,
838                    &rule_trusted_origins,
839                    &self.symbols,
840                )?;
841
842                let now = Instant::now();
843                if now >= time_limit {
844                    return Err(error::Token::RunLimit(error::RunLimit::Timeout));
845                }
846
847                if res {
848                    match policy.kind {
849                        PolicyKind::Allow => policy_result = Some(Ok(i)),
850                        PolicyKind::Deny => policy_result = Some(Err(i)),
851                    };
852                    break 'policies_test;
853                }
854            }
855        }
856
857        if let Some(blocks) = self.blocks.as_ref() {
858            for (i, block) in (blocks[1..]).iter().enumerate() {
859                let block_trusted_origins = TrustedOrigins::from_scopes(
860                    &block.scopes,
861                    &TrustedOrigins::default(),
862                    i + 1,
863                    &self.public_key_to_block_id,
864                );
865
866                limits.max_time = time_limit - Instant::now();
867                limits.max_iterations -= self.world.iterations - current_iterations;
868                current_iterations = self.world.iterations;
869
870                self.world.run_with_limits(&self.symbols, limits.clone())?;
871
872                for (j, check) in block.checks.iter().enumerate() {
873                    let mut successful = false;
874
875                    for query in check.queries.iter() {
876                        let rule_trusted_origins = TrustedOrigins::from_scopes(
877                            &query.scopes,
878                            &block_trusted_origins,
879                            i + 1,
880                            &self.public_key_to_block_id,
881                        );
882
883                        let res = match check.kind {
884                            CheckKind::One => self.world.query_match(
885                                query.clone(),
886                                i + 1,
887                                &rule_trusted_origins,
888                                &self.symbols,
889                            )?,
890                            CheckKind::All => self.world.query_match_all(
891                                query.clone(),
892                                &rule_trusted_origins,
893                                &self.symbols,
894                            )?,
895                        };
896
897                        let now = Instant::now();
898                        if now >= time_limit {
899                            return Err(error::Token::RunLimit(error::RunLimit::Timeout));
900                        }
901
902                        if res {
903                            successful = true;
904                            break;
905                        }
906                    }
907
908                    if !successful {
909                        errors.push(error::FailedCheck::Block(error::FailedBlockCheck {
910                            block_id: (i + 1) as u32,
911                            check_id: j as u32,
912                            rule: self.symbols.print_check(check),
913                        }));
914                    }
915                }
916            }
917        }
918
919        match (policy_result, errors.is_empty()) {
920            (Some(Ok(i)), true) => Ok(i),
921            (None, _) => Err(error::Token::FailedLogic(error::Logic::NoMatchingPolicy {
922                checks: errors,
923            })),
924            (Some(Ok(i)), _) => Err(error::Token::FailedLogic(error::Logic::Unauthorized {
925                policy: error::MatchedPolicy::Allow(i),
926                checks: errors,
927            })),
928            (Some(Err(i)), _) => Err(error::Token::FailedLogic(error::Logic::Unauthorized {
929                policy: error::MatchedPolicy::Deny(i),
930                checks: errors,
931            })),
932        }
933    }
934
935    /// prints the content of the authorizer
936    pub fn print_world(&self) -> String {
937        self.to_string()
938    }
939
940    /// returns all of the data loaded in the authorizer
941    pub fn dump(&self) -> (Vec<Fact>, Vec<Rule>, Vec<Check>, Vec<Policy>) {
942        let mut checks = self.authorizer_block_builder.checks.clone();
943        if let Some(blocks) = &self.blocks {
944            for block in blocks {
945                checks.extend(
946                    block
947                        .checks
948                        .iter()
949                        .map(|c| Check::convert_from(c, &self.symbols).unwrap()),
950                );
951            }
952        }
953
954        let mut facts = self
955            .world
956            .facts
957            .iter_all()
958            .map(|f| Fact::convert_from(f.1, &self.symbols))
959            .collect::<Result<Vec<_>, error::Format>>()
960            .unwrap();
961        facts.extend(self.authorizer_block_builder.facts.clone());
962
963        let mut rules = self
964            .world
965            .rules
966            .iter_all()
967            .map(|r| Rule::convert_from(r.1, &self.symbols))
968            .collect::<Result<Vec<_>, error::Format>>()
969            .unwrap();
970        rules.extend(self.authorizer_block_builder.rules.clone());
971
972        (facts, rules, checks, self.policies.clone())
973    }
974
975    pub fn dump_code(&self) -> String {
976        let (facts, rules, checks, policies) = self.dump();
977        let mut f = String::new();
978        for fact in &facts {
979            let _ = writeln!(f, "{fact};");
980        }
981        if !facts.is_empty() {
982            let _ = writeln!(f);
983        }
984
985        for rule in &rules {
986            let _ = writeln!(f, "{rule};");
987        }
988        if !rules.is_empty() {
989            let _ = writeln!(f);
990        }
991
992        for check in &checks {
993            let _ = writeln!(f, "{check};");
994        }
995        if !checks.is_empty() {
996            let _ = writeln!(f);
997        }
998
999        for policy in &policies {
1000            let _ = writeln!(f, "{policy};");
1001        }
1002        f
1003    }
1004}
1005
1006impl std::fmt::Display for Authorizer {
1007    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1008        let mut has_facts = false;
1009        let mut all_facts = BTreeMap::new();
1010        for (origin, factset) in &self.world.facts.inner {
1011            let mut facts = HashSet::new();
1012            for fact in factset {
1013                facts.insert(self.symbols.print_fact(fact));
1014            }
1015
1016            has_facts = has_facts || !facts.is_empty();
1017            all_facts.insert(origin, facts);
1018        }
1019
1020        let builder_facts = self
1021            .authorizer_block_builder
1022            .facts
1023            .iter()
1024            .map(|f| f.to_string())
1025            .collect::<HashSet<_>>();
1026        has_facts = has_facts || !builder_facts.is_empty();
1027        let mut authorizer_origin = Origin::default();
1028        authorizer_origin.insert(usize::MAX);
1029        match all_facts.get_mut(&authorizer_origin) {
1030            Some(e) => {
1031                e.extend(builder_facts);
1032            }
1033            None => {
1034                all_facts.insert(&authorizer_origin, builder_facts);
1035            }
1036        }
1037
1038        if has_facts {
1039            writeln!(f, "// Facts:")?;
1040        }
1041
1042        for (origin, factset) in &all_facts {
1043            let mut facts = factset.iter().collect::<Vec<_>>();
1044            facts.sort();
1045
1046            if !facts.is_empty() {
1047                writeln!(f, "// origin: {origin}")?;
1048            }
1049
1050            for fact in facts {
1051                writeln!(f, "{};", fact)?;
1052            }
1053        }
1054
1055        if has_facts {
1056            writeln!(f)?;
1057        }
1058
1059        let mut has_rules = false;
1060        let mut rules_map: BTreeMap<usize, HashSet<String>> = BTreeMap::new();
1061        for ruleset in self.world.rules.inner.values() {
1062            has_rules = has_rules || !ruleset.is_empty();
1063            for (origin, rule) in ruleset {
1064                rules_map
1065                    .entry(*origin)
1066                    .or_default()
1067                    .insert(self.symbols.print_rule(rule));
1068            }
1069        }
1070
1071        let builder_rules = self
1072            .authorizer_block_builder
1073            .rules
1074            .iter()
1075            .map(|rule| rule.to_string())
1076            .collect::<HashSet<_>>();
1077        has_rules = has_rules || !builder_rules.is_empty();
1078
1079        rules_map
1080            .entry(usize::MAX)
1081            .or_default()
1082            .extend(builder_rules);
1083
1084        if has_rules {
1085            writeln!(f, "// Rules:")?;
1086        }
1087
1088        for (origin, rule_list) in &rules_map {
1089            if !rule_list.is_empty() {
1090                if *origin == usize::MAX {
1091                    writeln!(f, "// origin: authorizer")?;
1092                } else {
1093                    writeln!(f, "// origin: {origin}")?;
1094                }
1095            }
1096
1097            let mut sorted_rule_list = rule_list.iter().collect::<Vec<_>>();
1098            sorted_rule_list.sort();
1099            for rule in sorted_rule_list {
1100                writeln!(f, "{};", rule)?;
1101            }
1102        }
1103
1104        if has_rules {
1105            writeln!(f)?;
1106        }
1107
1108        let mut has_checks = false;
1109        let mut checks_map: BTreeMap<usize, Vec<String>> = Default::default();
1110
1111        if let Some(blocks) = &self.blocks {
1112            for (i, block) in blocks.iter().enumerate() {
1113                let entry = checks_map.entry(i).or_default();
1114                has_checks = has_checks || !&block.checks.is_empty();
1115                for check in &block.checks {
1116                    entry.push(self.symbols.print_check(check));
1117                }
1118            }
1119        }
1120
1121        let authorizer_entry = checks_map.entry(usize::MAX).or_default();
1122
1123        has_checks = has_checks || !&self.authorizer_block_builder.checks.is_empty();
1124        for check in &self.authorizer_block_builder.checks {
1125            authorizer_entry.push(check.to_string());
1126        }
1127
1128        if has_checks {
1129            writeln!(f, "// Checks:")?;
1130        }
1131
1132        for (origin, checks) in checks_map {
1133            if !checks.is_empty() {
1134                if origin == usize::MAX {
1135                    writeln!(f, "// origin: authorizer")?;
1136                } else {
1137                    writeln!(f, "// origin: {origin}")?;
1138                }
1139            }
1140
1141            for check in checks {
1142                writeln!(f, "{};", &check)?;
1143            }
1144        }
1145
1146        if has_checks {
1147            writeln!(f)?;
1148        }
1149
1150        if !self.policies.is_empty() {
1151            writeln!(f, "// Policies:")?;
1152        }
1153        for policy in self.policies.iter() {
1154            writeln!(f, "{policy};")?;
1155        }
1156
1157        Ok(())
1158    }
1159}
1160
1161impl TryFrom<AuthorizerPolicies> for Authorizer {
1162    type Error = error::Token;
1163
1164    fn try_from(authorizer_policies: AuthorizerPolicies) -> Result<Self, Self::Error> {
1165        let AuthorizerPolicies {
1166            version: _,
1167            facts,
1168            rules,
1169            checks,
1170            policies,
1171        } = authorizer_policies;
1172
1173        let mut authorizer = Self::new();
1174
1175        for fact in facts.into_iter() {
1176            authorizer.authorizer_block_builder.add_fact(fact)?;
1177        }
1178
1179        for rule in rules.into_iter() {
1180            authorizer.authorizer_block_builder.add_rule(rule)?;
1181        }
1182
1183        for check in checks.into_iter() {
1184            authorizer.authorizer_block_builder.add_check(check)?;
1185        }
1186
1187        for policy in policies {
1188            authorizer.policies.push(policy);
1189        }
1190
1191        Ok(authorizer)
1192    }
1193}
1194
1195#[derive(Debug, Clone)]
1196pub struct AuthorizerPolicies {
1197    pub version: u32,
1198    /// list of facts provided by this block
1199    pub facts: Vec<Fact>,
1200    /// list of rules provided by blocks
1201    pub rules: Vec<Rule>,
1202    /// checks that the token and ambient data must validate
1203    pub checks: Vec<Check>,
1204    pub policies: Vec<Policy>,
1205}
1206
1207impl AuthorizerPolicies {
1208    pub fn serialize(&self) -> Result<Vec<u8>, error::Token> {
1209        let proto = crate::format::convert::authorizer_to_proto_authorizer(self);
1210
1211        let mut v = Vec::new();
1212
1213        proto
1214            .encode(&mut v)
1215            .map(|_| v)
1216            .map_err(|e| error::Format::SerializationError(format!("serialization error: {:?}", e)))
1217            .map_err(error::Token::Format)
1218    }
1219
1220    pub fn deserialize(data: &[u8]) -> Result<Self, error::Token> {
1221        let data = crate::format::schema::AuthorizerPolicies::decode(data).map_err(|e| {
1222            error::Format::DeserializationError(format!("deserialization error: {:?}", e))
1223        })?;
1224
1225        Ok(crate::format::convert::proto_authorizer_to_authorizer(
1226            &data,
1227        )?)
1228    }
1229}
1230
1231pub type AuthorizerLimits = RunLimits;
1232
1233impl BuilderExt for Authorizer {
1234    fn add_resource(&mut self, name: &str) {
1235        let f = fact("resource", &[string(name)]);
1236        self.add_fact(f).unwrap();
1237    }
1238    fn check_resource(&mut self, name: &str) {
1239        self.add_check(Check {
1240            queries: vec![rule(
1241                "resource_check",
1242                &[string("resource_check")],
1243                &[pred("resource", &[string(name)])],
1244            )],
1245            kind: CheckKind::One,
1246        })
1247        .unwrap();
1248    }
1249    fn add_operation(&mut self, name: &str) {
1250        let f = fact("operation", &[string(name)]);
1251        self.add_fact(f).unwrap();
1252    }
1253    fn check_operation(&mut self, name: &str) {
1254        self.add_check(Check {
1255            queries: vec![rule(
1256                "operation_check",
1257                &[string("operation_check")],
1258                &[pred("operation", &[string(name)])],
1259            )],
1260            kind: CheckKind::One,
1261        })
1262        .unwrap();
1263    }
1264    fn check_resource_prefix(&mut self, prefix: &str) {
1265        let check = constrained_rule(
1266            "prefix",
1267            &[var("resource")],
1268            &[pred("resource", &[var("resource")])],
1269            &[Expression {
1270                ops: vec![
1271                    Op::Value(var("resource")),
1272                    Op::Value(string(prefix)),
1273                    Op::Binary(Binary::Prefix),
1274                ],
1275            }],
1276        );
1277
1278        self.add_check(Check {
1279            queries: vec![check],
1280            kind: CheckKind::One,
1281        })
1282        .unwrap();
1283    }
1284
1285    fn check_resource_suffix(&mut self, suffix: &str) {
1286        let check = constrained_rule(
1287            "suffix",
1288            &[var("resource")],
1289            &[pred("resource", &[var("resource")])],
1290            &[Expression {
1291                ops: vec![
1292                    Op::Value(var("resource")),
1293                    Op::Value(string(suffix)),
1294                    Op::Binary(Binary::Suffix),
1295                ],
1296            }],
1297        );
1298
1299        self.add_check(Check {
1300            queries: vec![check],
1301            kind: CheckKind::One,
1302        })
1303        .unwrap();
1304    }
1305
1306    fn check_expiration_date(&mut self, exp: SystemTime) {
1307        let check = constrained_rule(
1308            "expiration",
1309            &[var("time")],
1310            &[pred("time", &[var("time")])],
1311            &[Expression {
1312                ops: vec![
1313                    Op::Value(var("time")),
1314                    Op::Value(date(&exp)),
1315                    Op::Binary(Binary::LessOrEqual),
1316                ],
1317            }],
1318        );
1319
1320        self.add_check(Check {
1321            queries: vec![check],
1322            kind: CheckKind::One,
1323        })
1324        .unwrap();
1325    }
1326}
1327
1328impl AuthorizerExt for Authorizer {
1329    fn add_allow_all(&mut self) {
1330        self.add_policy("allow if true").unwrap();
1331    }
1332    fn add_deny_all(&mut self) {
1333        self.add_policy("deny if true").unwrap();
1334    }
1335}
1336
1337#[cfg(test)]
1338mod tests {
1339    use std::time::Duration;
1340
1341    use crate::{
1342        builder::{BiscuitBuilder, BlockBuilder},
1343        KeyPair,
1344    };
1345
1346    use super::*;
1347
1348    #[test]
1349    fn empty_authorizer() {
1350        let mut authorizer = Authorizer::new();
1351        authorizer.add_policy("allow if true").unwrap();
1352        assert_eq!(
1353            authorizer.authorize_with_limits(AuthorizerLimits {
1354                max_time: Duration::from_secs(10),
1355                ..Default::default()
1356            }),
1357            Ok(0)
1358        );
1359    }
1360
1361    #[test]
1362    fn parameter_substitution() {
1363        let mut authorizer = Authorizer::new();
1364        let mut params = HashMap::new();
1365        params.insert("p1".to_string(), "value".into());
1366        params.insert("p2".to_string(), 0i64.into());
1367        params.insert("p3".to_string(), true.into());
1368        let mut scope_params = HashMap::new();
1369        scope_params.insert(
1370            "pk".to_string(),
1371            PublicKey::from_bytes(
1372                &hex::decode("6e9e6d5a75cf0c0e87ec1256b4dfed0ca3ba452912d213fcc70f8516583db9db")
1373                    .unwrap(),
1374            )
1375            .unwrap(),
1376        );
1377        authorizer
1378            .add_code_with_params(
1379                r#"
1380                  fact({p1}, "value");
1381                  rule($var, {p2}) <- fact($var, {p2});
1382                  check if {p3};
1383                  allow if {p3} trusting {pk};
1384              "#,
1385                params,
1386                scope_params,
1387            )
1388            .unwrap();
1389    }
1390
1391    #[test]
1392    fn forbid_unbound_parameters() {
1393        let mut builder = Authorizer::new();
1394
1395        let mut fact = Fact::try_from("fact({p1}, {p4})").unwrap();
1396        fact.set("p1", "hello").unwrap();
1397        let res = builder.add_fact(fact);
1398        assert_eq!(
1399            res,
1400            Err(error::Token::Language(
1401                biscuit_parser::error::LanguageError::Parameters {
1402                    missing_parameters: vec!["p4".to_string()],
1403                    unused_parameters: vec![],
1404                }
1405            ))
1406        );
1407        let mut rule = Rule::try_from(
1408            "fact($var1, {p2}) <- f1($var1, $var3), f2({p2}, $var3, {p4}), $var3.starts_with({p2})",
1409        )
1410        .unwrap();
1411        rule.set("p2", "hello").unwrap();
1412        let res = builder.add_rule(rule);
1413        assert_eq!(
1414            res,
1415            Err(error::Token::Language(
1416                biscuit_parser::error::LanguageError::Parameters {
1417                    missing_parameters: vec!["p4".to_string()],
1418                    unused_parameters: vec![],
1419                }
1420            ))
1421        );
1422        let mut check = Check::try_from("check if {p4}, {p3}").unwrap();
1423        check.set("p3", true).unwrap();
1424        let res = builder.add_check(check);
1425        assert_eq!(
1426            res,
1427            Err(error::Token::Language(
1428                biscuit_parser::error::LanguageError::Parameters {
1429                    missing_parameters: vec!["p4".to_string()],
1430                    unused_parameters: vec![],
1431                }
1432            ))
1433        );
1434        let mut policy = Policy::try_from("allow if {p4}, {p3}").unwrap();
1435        policy.set("p3", true).unwrap();
1436
1437        let res = builder.add_policy(policy);
1438        assert_eq!(
1439            res,
1440            Err(error::Token::Language(
1441                biscuit_parser::error::LanguageError::Parameters {
1442                    missing_parameters: vec!["p4".to_string()],
1443                    unused_parameters: vec![],
1444                }
1445            ))
1446        );
1447    }
1448
1449    #[test]
1450    fn forbid_unbound_parameters_in_add_code() {
1451        let mut builder = Authorizer::new();
1452        let mut params = HashMap::new();
1453        params.insert("p1".to_string(), "hello".into());
1454        params.insert("p2".to_string(), 1i64.into());
1455        params.insert("p4".to_string(), "this will be ignored".into());
1456        let res = builder.add_code_with_params(
1457            r#"fact({p1}, "value");
1458             rule($head_var) <- f1($head_var), {p2} > 0;
1459             check if {p3};
1460             allow if {p3};
1461            "#,
1462            params,
1463            HashMap::new(),
1464        );
1465
1466        assert_eq!(
1467            res,
1468            Err(error::Token::Language(
1469                biscuit_parser::error::LanguageError::Parameters {
1470                    missing_parameters: vec!["p3".to_string()],
1471                    unused_parameters: vec![],
1472                }
1473            ))
1474        )
1475    }
1476
1477    #[test]
1478    fn query_authorizer_from_token_tuple() {
1479        use crate::Biscuit;
1480        use crate::KeyPair;
1481        let keypair = KeyPair::new();
1482        let mut builder = Biscuit::builder();
1483        builder.add_fact("user(\"John Doe\", 42)").unwrap();
1484
1485        let biscuit = builder.build(&keypair).unwrap();
1486
1487        let mut authorizer = biscuit.authorizer().unwrap();
1488        let res: Vec<(String, i64)> = authorizer
1489            .query("data($name, $id) <- user($name, $id)")
1490            .unwrap();
1491
1492        assert_eq!(res.len(), 1);
1493        assert_eq!(res[0].0, "John Doe");
1494        assert_eq!(res[0].1, 42);
1495    }
1496
1497    #[test]
1498    fn query_authorizer_from_token_string() {
1499        use crate::Biscuit;
1500        use crate::KeyPair;
1501        let keypair = KeyPair::new();
1502        let mut builder = Biscuit::builder();
1503        builder.add_fact("user(\"John Doe\")").unwrap();
1504
1505        let biscuit = builder.build(&keypair).unwrap();
1506
1507        let mut authorizer = biscuit.authorizer().unwrap();
1508        let res: Vec<(String,)> = authorizer.query("data($name) <- user($name)").unwrap();
1509
1510        assert_eq!(res.len(), 1);
1511        assert_eq!(res[0].0, "John Doe");
1512    }
1513
1514    #[test]
1515    fn authorizer_with_scopes() {
1516        let root = KeyPair::new();
1517        let external = KeyPair::new();
1518
1519        let mut builder = Biscuit::builder();
1520        let mut scope_params = HashMap::new();
1521        scope_params.insert("external_pub".to_string(), external.public());
1522        builder
1523            .add_code_with_params(
1524                r#"right("read");
1525               check if group("admin") trusting {external_pub};
1526            "#,
1527                HashMap::new(),
1528                scope_params,
1529            )
1530            .unwrap();
1531
1532        let biscuit1 = builder.build(&root).unwrap();
1533
1534        let req = biscuit1.third_party_request().unwrap();
1535
1536        let mut builder = BlockBuilder::new();
1537        builder
1538            .add_code(
1539                r#"group("admin");
1540             check if right("read");
1541            "#,
1542            )
1543            .unwrap();
1544        let res = req.create_block(&external.private(), builder).unwrap();
1545        let biscuit2 = biscuit1.append_third_party(external.public(), res).unwrap();
1546
1547        let mut authorizer = Authorizer::new();
1548        let external2 = KeyPair::new();
1549
1550        let mut scope_params = HashMap::new();
1551        scope_params.insert("external".to_string(), external.public());
1552        scope_params.insert("external2".to_string(), external2.public());
1553
1554        authorizer
1555            .add_code_with_params(
1556                r#"
1557            // this rule trusts both the third-party block and the authority, and can access facts
1558            // from both
1559            possible(true) <- right($right), group("admin") trusting authority, {external};
1560
1561            // this rule only trusts the third-party block and can't access authority facts
1562            // it should _not_ generate a fact
1563            impossible(true) <- right("read") trusting {external2};
1564
1565            authorizer(true);
1566
1567            check if possible(true) trusting authority, {external};
1568            deny if impossible(true) trusting {external2};
1569            allow if true;
1570            "#,
1571                HashMap::new(),
1572                scope_params,
1573            )
1574            .unwrap();
1575
1576        authorizer.add_token(&biscuit2).unwrap();
1577
1578        println!("token:\n{}", biscuit2);
1579        println!("world:\n{}", authorizer.print_world());
1580
1581        authorizer.set_limits(AuthorizerLimits {
1582            max_time: Duration::from_millis(10), //Set 10 milliseconds as the maximum time allowed for the authorization due to "cheap" worker on GitHub Actions
1583            ..Default::default()
1584        });
1585
1586        let res = authorizer.authorize_with_limits(AuthorizerLimits {
1587            max_time: Duration::from_secs(10),
1588            ..Default::default()
1589        });
1590        println!("world after:\n{}", authorizer.print_world());
1591
1592        res.unwrap();
1593
1594        // authorizer facts are always visible, no matter what
1595        let authorizer_facts: Vec<Fact> = authorizer
1596            .query_with_limits(
1597                "authorizer(true) <- authorizer(true)",
1598                AuthorizerLimits {
1599                    max_time: Duration::from_secs(10),
1600                    ..Default::default()
1601                },
1602            )
1603            .unwrap();
1604
1605        assert_eq!(authorizer_facts.len(), 1);
1606
1607        // authority facts are visible by default
1608        let authority_facts: Vec<Fact> = authorizer
1609            .query_with_limits(
1610                "right($right) <- right($right)",
1611                AuthorizerLimits {
1612                    max_time: Duration::from_secs(10),
1613                    ..Default::default()
1614                },
1615            )
1616            .unwrap();
1617        assert_eq!(authority_facts.len(), 1);
1618
1619        // authority facts are not visible if
1620        // there is an explicit rule scope annotation that does
1621        // not cover previous or authority
1622        let authority_facts_untrusted: Vec<Fact> = authorizer
1623            .query_with_limits(
1624                {
1625                    let mut r: Rule = "right($right) <- right($right) trusting {external}"
1626                        .try_into()
1627                        .unwrap();
1628                    r.set_scope("external", external.public()).unwrap();
1629                    r
1630                },
1631                AuthorizerLimits {
1632                    max_time: Duration::from_secs(10),
1633                    ..Default::default()
1634                },
1635            )
1636            .unwrap();
1637        assert_eq!(authority_facts_untrusted.len(), 0);
1638
1639        // block facts are not visible by default
1640        let block_facts_untrusted: Vec<Fact> = authorizer
1641            .query_with_limits(
1642                "group($group) <- group($group)",
1643                AuthorizerLimits {
1644                    max_time: Duration::from_secs(10),
1645                    ..Default::default()
1646                },
1647            )
1648            .unwrap();
1649        assert_eq!(block_facts_untrusted.len(), 0);
1650
1651        // block facts are visible if trusted
1652        let block_facts_trusted: Vec<Fact> = authorizer
1653            .query_with_limits(
1654                {
1655                    let mut r: Rule = "group($group) <- group($group) trusting {external}"
1656                        .try_into()
1657                        .unwrap();
1658                    r.set_scope("external", external.public()).unwrap();
1659                    r
1660                },
1661                AuthorizerLimits {
1662                    max_time: Duration::from_secs(10),
1663                    ..Default::default()
1664                },
1665            )
1666            .unwrap();
1667        assert_eq!(block_facts_trusted.len(), 1);
1668
1669        // block facts are visible by default with query_all
1670        let block_facts_query_all: Vec<Fact> = authorizer
1671            .query_all_with_limits(
1672                "group($group) <- group($group)",
1673                AuthorizerLimits {
1674                    max_time: Duration::from_secs(10),
1675                    ..Default::default()
1676                },
1677            )
1678            .unwrap();
1679        assert_eq!(block_facts_query_all.len(), 1);
1680
1681        // block facts are not visible with query_all if the query has an explicit
1682        // scope annotation that does not trust them
1683        let block_facts_query_all_explicit: Vec<Fact> = authorizer
1684            .query_all_with_limits(
1685                "group($group) <- group($group) trusting authority",
1686                AuthorizerLimits {
1687                    max_time: Duration::from_secs(10),
1688                    ..Default::default()
1689                },
1690            )
1691            .unwrap();
1692        assert_eq!(block_facts_query_all_explicit.len(), 0);
1693    }
1694
1695    #[test]
1696    fn authorizer_display_before_and_after_authorization() {
1697        let root = KeyPair::new();
1698
1699        let mut token_builder = BiscuitBuilder::new();
1700        token_builder
1701            .add_code(
1702                r#"
1703            authority_fact(true);
1704            authority_rule($v) <- authority_fact($v);
1705            check if authority_fact(true), authority_rule(true);
1706        "#,
1707            )
1708            .unwrap();
1709        let token = token_builder.build(&root).unwrap();
1710
1711        let mut authorizer = token.authorizer().unwrap();
1712        authorizer
1713            .add_code(
1714                r#"
1715          authorizer_fact(true);
1716          authorizer_rule($v) <- authorizer_fact($v);
1717          check if authorizer_fact(true), authorizer_rule(true);
1718          allow if true;
1719        "#,
1720            )
1721            .unwrap();
1722        let output_before_authorization = authorizer.to_string();
1723
1724        assert!(
1725            output_before_authorization.contains("authorizer_fact(true)"),
1726            "Authorizer.to_string() displays authorizer facts even before running authorize()"
1727        );
1728
1729        authorizer
1730            .authorize_with_limits(AuthorizerLimits {
1731                max_time: Duration::from_secs(10),
1732                ..Default::default()
1733            })
1734            .unwrap();
1735
1736        let output_after_authorization = authorizer.to_string();
1737        assert!(
1738            output_after_authorization.contains("authorizer_rule(true)"),
1739            "Authorizer.to_string() displays generated facts after running authorize()"
1740        );
1741
1742        assert_eq!(
1743            r#"// Facts:
1744// origin: 0
1745authority_fact(true);
1746authority_rule(true);
1747// origin: authorizer
1748authorizer_fact(true);
1749authorizer_rule(true);
1750
1751// Rules:
1752// origin: 0
1753authority_rule($v) <- authority_fact($v);
1754// origin: authorizer
1755authorizer_rule($v) <- authorizer_fact($v);
1756
1757// Checks:
1758// origin: 0
1759check if authority_fact(true), authority_rule(true);
1760// origin: authorizer
1761check if authorizer_fact(true), authorizer_rule(true);
1762
1763// Policies:
1764allow if true;
1765"#,
1766            output_after_authorization
1767        );
1768    }
1769
1770    #[test]
1771    fn empty_authorizer_display() {
1772        let authorizer = Authorizer::new();
1773        assert_eq!("", authorizer.to_string())
1774    }
1775}