1use std::{
6 collections::HashMap,
7 convert::TryInto,
8 fmt::{self, Write},
9 time::{Duration, SystemTime},
10};
11
12use biscuit_parser::parser::parse_source;
13use prost::Message;
14
15use crate::{
16 builder::Convert,
17 builder_ext::{AuthorizerExt, BuilderExt},
18 datalog::{ExternFunc, Origin, RunLimits, SymbolTable, TrustedOrigins, World},
19 error,
20 format::{
21 convert::{
22 policy_to_proto_policy, proto_policy_to_policy, proto_snapshot_block_to_token_block,
23 token_block_to_proto_snapshot_block,
24 },
25 schema,
26 },
27 token::{self, default_symbol_table, Block, MAX_SCHEMA_VERSION, MIN_SCHEMA_VERSION},
28 Authorizer, AuthorizerLimits, Biscuit, PublicKey,
29};
30
31use super::{date, fact, BlockBuilder, Check, Fact, Policy, Rule, Scope, Term};
32
33#[derive(Clone, Debug, Default)]
34pub struct AuthorizerBuilder {
35 authorizer_block_builder: BlockBuilder,
36 policies: Vec<Policy>,
37 extern_funcs: HashMap<String, ExternFunc>,
38 pub(crate) limits: AuthorizerLimits,
39}
40
41impl AuthorizerBuilder {
42 pub fn new() -> AuthorizerBuilder {
43 AuthorizerBuilder::default()
44 }
45
46 pub fn merge_block(mut self, other: BlockBuilder) -> Self {
48 self.authorizer_block_builder = self.authorizer_block_builder.merge(other);
49 self
50 }
51
52 pub fn merge(mut self, mut other: AuthorizerBuilder) -> Self {
58 self.policies.append(&mut other.policies);
59 self.extern_funcs.extend(other.extern_funcs);
60 self.authorizer_block_builder = self
61 .authorizer_block_builder
62 .merge(other.authorizer_block_builder);
63 self
64 }
65
66 pub fn fact<F: TryInto<Fact>>(mut self, fact: F) -> Result<Self, error::Token>
67 where
68 error::Token: From<<F as TryInto<Fact>>::Error>,
69 {
70 self.authorizer_block_builder = self.authorizer_block_builder.fact(fact)?;
71 Ok(self)
72 }
73
74 pub fn rule<R: TryInto<Rule>>(mut self, rule: R) -> Result<Self, error::Token>
75 where
76 error::Token: From<<R as TryInto<Rule>>::Error>,
77 {
78 self.authorizer_block_builder = self.authorizer_block_builder.rule(rule)?;
79 Ok(self)
80 }
81
82 pub fn check<C: TryInto<Check>>(mut self, check: C) -> Result<Self, error::Token>
83 where
84 error::Token: From<<C as TryInto<Check>>::Error>,
85 {
86 self.authorizer_block_builder = self.authorizer_block_builder.check(check)?;
87 Ok(self)
88 }
89
90 pub fn code<T: AsRef<str>>(self, source: T) -> Result<Self, error::Token> {
110 self.code_with_params(source, HashMap::new(), HashMap::new())
111 }
112
113 pub fn code_with_params<T: AsRef<str>>(
116 mut self,
117 source: T,
118 params: HashMap<String, Term>,
119 scope_params: HashMap<String, PublicKey>,
120 ) -> Result<Self, error::Token> {
121 let source = source.as_ref();
122
123 let source_result = parse_source(source).map_err(|e| {
124 let e2: biscuit_parser::error::LanguageError = e.into();
125 e2
126 })?;
127
128 for (_, fact) in source_result.facts.into_iter() {
129 let mut fact: Fact = fact.into();
130 for (name, value) in ¶ms {
131 let res = match fact.set(name, value) {
132 Ok(_) => Ok(()),
133 Err(error::Token::Language(
134 biscuit_parser::error::LanguageError::Parameters {
135 missing_parameters, ..
136 },
137 )) if missing_parameters.is_empty() => Ok(()),
138 Err(e) => Err(e),
139 };
140 res?;
141 }
142 fact.validate()?;
143 self.authorizer_block_builder.facts.push(fact);
144 }
145
146 for (_, rule) in source_result.rules.into_iter() {
147 let mut rule: Rule = rule.into();
148 for (name, value) in ¶ms {
149 let res = match rule.set(name, value) {
150 Ok(_) => Ok(()),
151 Err(error::Token::Language(
152 biscuit_parser::error::LanguageError::Parameters {
153 missing_parameters, ..
154 },
155 )) if missing_parameters.is_empty() => Ok(()),
156 Err(e) => Err(e),
157 };
158 res?;
159 }
160 for (name, value) in &scope_params {
161 let res = match rule.set_scope(name, *value) {
162 Ok(_) => Ok(()),
163 Err(error::Token::Language(
164 biscuit_parser::error::LanguageError::Parameters {
165 missing_parameters, ..
166 },
167 )) if missing_parameters.is_empty() => Ok(()),
168 Err(e) => Err(e),
169 };
170 res?;
171 }
172 rule.validate_parameters()?;
173 self.authorizer_block_builder.rules.push(rule);
174 }
175
176 for (_, check) in source_result.checks.into_iter() {
177 let mut check: Check = check.into();
178 for (name, value) in ¶ms {
179 let res = match check.set(name, value) {
180 Ok(_) => Ok(()),
181 Err(error::Token::Language(
182 biscuit_parser::error::LanguageError::Parameters {
183 missing_parameters, ..
184 },
185 )) if missing_parameters.is_empty() => Ok(()),
186 Err(e) => Err(e),
187 };
188 res?;
189 }
190 for (name, value) in &scope_params {
191 let res = match check.set_scope(name, *value) {
192 Ok(_) => Ok(()),
193 Err(error::Token::Language(
194 biscuit_parser::error::LanguageError::Parameters {
195 missing_parameters, ..
196 },
197 )) if missing_parameters.is_empty() => Ok(()),
198 Err(e) => Err(e),
199 };
200 res?;
201 }
202 check.validate_parameters()?;
203 self.authorizer_block_builder.checks.push(check);
204 }
205 for (_, policy) in source_result.policies.into_iter() {
206 let mut policy: Policy = policy.into();
207 for (name, value) in ¶ms {
208 let res = match policy.set(name, value) {
209 Ok(_) => Ok(()),
210 Err(error::Token::Language(
211 biscuit_parser::error::LanguageError::Parameters {
212 missing_parameters, ..
213 },
214 )) if missing_parameters.is_empty() => Ok(()),
215 Err(e) => Err(e),
216 };
217 res?;
218 }
219 for (name, value) in &scope_params {
220 let res = match policy.set_scope(name, *value) {
221 Ok(_) => Ok(()),
222 Err(error::Token::Language(
223 biscuit_parser::error::LanguageError::Parameters {
224 missing_parameters, ..
225 },
226 )) if missing_parameters.is_empty() => Ok(()),
227 Err(e) => Err(e),
228 };
229 res?;
230 }
231 policy.validate_parameters()?;
232 self.policies.push(policy);
233 }
234
235 Ok(self)
236 }
237
238 pub fn scope(mut self, scope: Scope) -> Self {
239 self.authorizer_block_builder = self.authorizer_block_builder.scope(scope);
240 self
241 }
242
243 pub fn policy<P: TryInto<Policy>>(mut self, policy: P) -> Result<Self, error::Token>
245 where
246 error::Token: From<<P as TryInto<Policy>>::Error>,
247 {
248 let policy = policy.try_into()?;
249 policy.validate_parameters()?;
250 self.policies.push(policy);
251 Ok(self)
252 }
253
254 pub fn time(mut self) -> Self {
256 let fact = fact("time", &[date(&SystemTime::now())]);
257 self.authorizer_block_builder = self.authorizer_block_builder.fact(fact).unwrap();
258 self
259 }
260
261 pub fn set_limits(mut self, limits: AuthorizerLimits) -> Self {
265 self.limits = limits;
266 self
267 }
268
269 pub fn limits(&self) -> &AuthorizerLimits {
270 &self.limits
271 }
272
273 pub fn set_extern_funcs(mut self, extern_funcs: HashMap<String, ExternFunc>) -> Self {
275 self.extern_funcs = extern_funcs;
276 self
277 }
278
279 pub fn register_extern_funcs(mut self, extern_funcs: HashMap<String, ExternFunc>) -> Self {
281 self.extern_funcs.extend(extern_funcs);
282 self
283 }
284
285 pub fn register_extern_func(mut self, name: String, func: ExternFunc) -> Self {
287 self.extern_funcs.insert(name, func);
288 self
289 }
290
291 pub fn dump_code(&self) -> String {
292 let mut f = String::new();
293 for fact in &self.authorizer_block_builder.facts {
294 let _ = writeln!(f, "{fact};");
295 }
296 if !self.authorizer_block_builder.facts.is_empty() {
297 let _ = writeln!(f);
298 }
299
300 for rule in &self.authorizer_block_builder.rules {
301 let _ = writeln!(f, "{rule};");
302 }
303 if !self.authorizer_block_builder.rules.is_empty() {
304 let _ = writeln!(f);
305 }
306
307 for check in &self.authorizer_block_builder.checks {
308 let _ = writeln!(f, "{check};");
309 }
310 if !self.authorizer_block_builder.checks.is_empty() {
311 let _ = writeln!(f);
312 }
313
314 for policy in &self.policies {
315 let _ = writeln!(f, "{policy};");
316 }
317 f
318 }
319
320 pub fn build(self, token: &Biscuit) -> Result<Authorizer, error::Token> {
322 self.build_inner(Some(token))
323 }
324
325 pub fn build_unauthenticated(self) -> Result<Authorizer, error::Token> {
327 self.build_inner(None)
328 }
329
330 fn build_inner(self, token: Option<&Biscuit>) -> Result<Authorizer, error::Token> {
331 let mut world = World::new();
332 world.extern_funcs = self.extern_funcs;
333
334 let mut symbols = SymbolTable::new();
335 let mut public_key_to_block_id: HashMap<usize, Vec<usize>> = HashMap::new();
336 let mut token_origins = TrustedOrigins::default();
337 let mut blocks: Option<Vec<Block>> = None;
338
339 if let Some(token) = token {
341 for (i, block) in token.container.blocks.iter().enumerate() {
342 if let Some(sig) = block.external_signature.as_ref() {
343 let new_key_id = symbols.public_keys.insert(&sig.public_key);
344
345 public_key_to_block_id
346 .entry(new_key_id as usize)
347 .or_default()
348 .push(i + 1);
349 }
350 }
351
352 blocks = Some(
353 token
354 .blocks()
355 .enumerate()
356 .map(|(i, block)| {
357 block.and_then(|mut b| {
358 load_and_translate_block(
359 &mut b,
360 i,
361 &token.symbols,
362 &mut symbols,
363 &mut public_key_to_block_id,
364 &mut world,
365 )?;
366 Ok(b)
367 })
368 })
369 .collect::<Result<Vec<_>, _>>()?,
370 );
371
372 token_origins = TrustedOrigins::from_scopes(
373 &[token::Scope::Previous],
374 &TrustedOrigins::default(),
375 token.block_count(),
376 &public_key_to_block_id,
377 );
378 }
379 let mut authorizer_origin = Origin::default();
380 authorizer_origin.insert(usize::MAX);
381
382 let authorizer_scopes: Vec<token::Scope> = self
383 .authorizer_block_builder
384 .scopes
385 .clone()
386 .iter()
387 .map(|s| s.convert(&mut symbols))
388 .collect();
389
390 let authorizer_trusted_origins = TrustedOrigins::from_scopes(
391 &authorizer_scopes,
392 &TrustedOrigins::default(),
393 usize::MAX,
394 &public_key_to_block_id,
395 );
396 for fact in &self.authorizer_block_builder.facts {
397 world
398 .facts
399 .insert(&authorizer_origin, fact.convert(&mut symbols));
400 }
401
402 for rule in &self.authorizer_block_builder.rules {
403 let rule = rule.convert(&mut symbols);
404
405 let rule_trusted_origins = TrustedOrigins::from_scopes(
406 &rule.scopes,
407 &authorizer_trusted_origins,
408 usize::MAX,
409 &public_key_to_block_id,
410 );
411
412 world.rules.insert(usize::MAX, &rule_trusted_origins, rule);
413 }
414
415 Ok(Authorizer {
422 authorizer_block_builder: self.authorizer_block_builder,
423 world,
424 symbols,
425 token_origins,
426 policies: self.policies,
427 blocks,
428 public_key_to_block_id,
429 limits: self.limits,
430 execution_time: None,
431 })
432 }
433}
434
435impl fmt::Display for AuthorizerBuilder {
436 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
437 self.authorizer_block_builder.fmt(f)?;
438 for mut policy in self.policies.clone().into_iter() {
439 policy.apply_parameters();
440 writeln!(f, "{policy};")?;
441 }
442
443 Ok(())
444 }
445}
446
447pub(crate) fn load_and_translate_block(
449 block: &mut Block,
450 i: usize,
451 token_symbols: &SymbolTable,
452 authorizer_symbols: &mut SymbolTable,
453 public_key_to_block_id: &mut HashMap<usize, Vec<usize>>,
454 world: &mut World,
455) -> Result<(), error::Token> {
456 let block_symbols = if i == 0 || block.external_key.is_none() {
458 token_symbols.clone()
459 } else {
460 block.symbols.clone()
461 };
462
463 let mut block_origin = Origin::default();
464 block_origin.insert(i);
465
466 for scope in block.scopes.iter_mut() {
467 *scope = crate::token::builder::Scope::convert_from(scope, &block_symbols)
468 .map(|s| s.convert(authorizer_symbols))?;
469 }
470
471 let block_trusted_origins = TrustedOrigins::from_scopes(
472 &block.scopes,
473 &TrustedOrigins::default(),
474 i,
475 public_key_to_block_id,
476 );
477
478 for fact in block.facts.iter_mut() {
479 *fact = Fact::convert_from(fact, &block_symbols)?.convert(authorizer_symbols);
480 world.facts.insert(&block_origin, fact.clone());
481 }
482
483 for rule in block.rules.iter_mut() {
484 if let Err(_message) = rule.validate_variables(&block_symbols) {
485 return Err(error::Logic::InvalidBlockRule(0, block_symbols.print_rule(rule)).into());
486 }
487 *rule = rule.translate(&block_symbols, authorizer_symbols)?;
488
489 let rule_trusted_origins = TrustedOrigins::from_scopes(
490 &rule.scopes,
491 &block_trusted_origins,
492 i,
493 public_key_to_block_id,
494 );
495
496 world.rules.insert(i, &rule_trusted_origins, rule.clone());
497 }
498
499 for check in block.checks.iter_mut() {
500 let c = Check::convert_from(check, &block_symbols)?;
501 *check = c.convert(authorizer_symbols);
502 }
503
504 Ok(())
505}
506
507impl BuilderExt for AuthorizerBuilder {
508 fn resource(mut self, name: &str) -> Self {
509 self.authorizer_block_builder = self.authorizer_block_builder.resource(name);
510 self
511 }
512 fn check_resource(mut self, name: &str) -> Self {
513 self.authorizer_block_builder = self.authorizer_block_builder.check_resource(name);
514 self
515 }
516 fn operation(mut self, name: &str) -> Self {
517 self.authorizer_block_builder = self.authorizer_block_builder.operation(name);
518 self
519 }
520 fn check_operation(mut self, name: &str) -> Self {
521 self.authorizer_block_builder = self.authorizer_block_builder.check_operation(name);
522 self
523 }
524 fn check_resource_prefix(mut self, prefix: &str) -> Self {
525 self.authorizer_block_builder = self.authorizer_block_builder.check_resource_prefix(prefix);
526 self
527 }
528
529 fn check_resource_suffix(mut self, suffix: &str) -> Self {
530 self.authorizer_block_builder = self.authorizer_block_builder.check_resource_suffix(suffix);
531 self
532 }
533
534 fn check_expiration_date(mut self, exp: SystemTime) -> Self {
535 self.authorizer_block_builder = self.authorizer_block_builder.check_expiration_date(exp);
536 self
537 }
538}
539
540impl AuthorizerExt for AuthorizerBuilder {
541 fn allow_all(self) -> Self {
542 self.policy("allow if true").unwrap()
543 }
544 fn deny_all(self) -> Self {
545 self.policy("deny if true").unwrap()
546 }
547}
548
549impl AuthorizerBuilder {
550 pub fn from_snapshot(input: schema::AuthorizerSnapshot) -> Result<Self, error::Token> {
551 let schema::AuthorizerSnapshot {
552 limits,
553 execution_time,
554 world,
555 } = input;
556
557 let limits = RunLimits {
558 max_facts: limits.max_facts,
559 max_iterations: limits.max_iterations,
560 max_time: Duration::from_nanos(limits.max_time),
561 };
562
563 let version = world.version.unwrap_or(0);
564 if !(MIN_SCHEMA_VERSION..=MAX_SCHEMA_VERSION).contains(&version) {
565 return Err(error::Format::Version {
566 minimum: crate::token::MIN_SCHEMA_VERSION,
567 maximum: crate::token::MAX_SCHEMA_VERSION,
568 actual: version,
569 }
570 .into());
571 }
572
573 if !world.blocks.is_empty() {
574 return Err(error::Format::DeserializationError(
575 "cannot deserialize an AuthorizerBuilder fro a snapshot with blocks".to_string(),
576 )
577 .into());
578 }
579
580 if !world.generated_facts.is_empty() {
581 return Err(error::Format::DeserializationError(
582 "cannot deserialize an AuthorizerBuilder from a snapshot with generated facts"
583 .to_string(),
584 )
585 .into());
586 }
587
588 if world.iterations != 0 {
589 return Err(error::Format::DeserializationError(
590 "cannot deserialize an AuthorizerBuilder from a snapshot with non-zero iterations"
591 .to_string(),
592 )
593 .into());
594 }
595
596 if execution_time != 0 {
597 return Err(error::Format::DeserializationError(
598 "cannot deserialize an AuthorizerBuilder from a snapshot with non-zero execution time".to_string(),
599 )
600 .into());
601 }
602
603 let mut symbols = default_symbol_table();
604 for symbol in world.symbols {
605 symbols.insert(&symbol);
606 }
607 for public_key in world.public_keys {
608 symbols
609 .public_keys
610 .insert(&PublicKey::from_proto(&public_key)?);
611 }
612
613 let authorizer_block = proto_snapshot_block_to_token_block(&world.authorizer_block)?;
614
615 let authorizer_block_builder = BlockBuilder::convert_from(&authorizer_block, &symbols)?;
616 let policies = world
617 .authorizer_policies
618 .iter()
619 .map(|policy| proto_policy_to_policy(policy, &symbols, version))
620 .collect::<Result<Vec<Policy>, error::Format>>()?;
621
622 let mut authorizer = AuthorizerBuilder::new();
623 authorizer.authorizer_block_builder = authorizer_block_builder;
624 authorizer.policies = policies;
625 authorizer.limits = limits;
626
627 Ok(authorizer)
628 }
629
630 pub fn from_raw_snapshot(input: &[u8]) -> Result<Self, error::Token> {
631 let snapshot = schema::AuthorizerSnapshot::decode(input).map_err(|e| {
632 error::Format::DeserializationError(format!("deserialization error: {:?}", e))
633 })?;
634 Self::from_snapshot(snapshot)
635 }
636
637 pub fn from_base64_snapshot(input: &str) -> Result<Self, error::Token> {
638 let bytes = base64::decode_config(input, base64::URL_SAFE)?;
639 Self::from_raw_snapshot(&bytes)
640 }
641
642 pub fn snapshot(&self) -> Result<schema::AuthorizerSnapshot, error::Format> {
643 let mut symbols = default_symbol_table();
644
645 let authorizer_policies = self
646 .policies
647 .iter()
648 .map(|policy| policy_to_proto_policy(policy, &mut symbols))
649 .collect();
650
651 let authorizer_block = self.authorizer_block_builder.clone().build(symbols.clone());
652 symbols.extend(&authorizer_block.symbols)?;
653 symbols.public_keys.extend(&authorizer_block.public_keys)?;
654
655 let authorizer_block = token_block_to_proto_snapshot_block(&authorizer_block);
656
657 let blocks = vec![];
658
659 let generated_facts = vec![];
660
661 let world = schema::AuthorizerWorld {
662 version: Some(MAX_SCHEMA_VERSION),
663 symbols: symbols.strings(),
664 public_keys: symbols
665 .public_keys
666 .into_inner()
667 .into_iter()
668 .map(|key| key.to_proto())
669 .collect(),
670 blocks,
671 authorizer_block,
672 authorizer_policies,
673 generated_facts,
674 iterations: 0,
675 };
676
677 Ok(schema::AuthorizerSnapshot {
678 world,
679 execution_time: 0u64,
680 limits: schema::RunLimits {
681 max_facts: self.limits.max_facts,
682 max_iterations: self.limits.max_iterations,
683 max_time: self.limits.max_time.as_nanos() as u64,
684 },
685 })
686 }
687
688 pub fn to_raw_snapshot(&self) -> Result<Vec<u8>, error::Format> {
689 let snapshot = self.snapshot()?;
690 let mut bytes = Vec::new();
691 snapshot.encode(&mut bytes).map_err(|e| {
692 error::Format::SerializationError(format!("serialization error: {:?}", e))
693 })?;
694 Ok(bytes)
695 }
696
697 pub fn to_base64_snapshot(&self) -> Result<String, error::Format> {
698 let snapshot_bytes = self.to_raw_snapshot()?;
699 Ok(base64::encode_config(snapshot_bytes, base64::URL_SAFE))
700 }
701}