biscuit_ssh_core/
token.rs1use biscuit_auth::{AuthorizerBuilder, Biscuit, BlockBuilder, KeyPair, PublicKey, UnverifiedBiscuit};
4
5use crate::revocation::hex;
6use crate::{Error, Restriction, Right};
7
8pub fn mint(root: &KeyPair, rights: &[Right], restrictions: &[Restriction]) -> Result<String, Error> {
11 if rights.is_empty() {
12 return Err(Error::invalid("rights", "a token needs at least one right"));
13 }
14 let mut builder = Biscuit::builder();
15 for right in rights {
16 builder = builder.fact(right.to_fact()).map_err(Error::Datalog)?;
17 }
18 for restriction in restrictions {
19 builder = builder.check(restriction.to_check()?).map_err(Error::Datalog)?;
20 }
21 builder
22 .build(root)
23 .and_then(|token| token.to_base64())
24 .map_err(Error::Datalog)
25}
26
27pub fn attenuate(token: &str, restrictions: &[Restriction]) -> Result<String, Error> {
32 if restrictions.is_empty() {
33 return Err(Error::invalid(
34 "restrictions",
35 "attenuating needs at least one restriction",
36 ));
37 }
38 let token = UnverifiedBiscuit::from_base64(token.trim()).map_err(Error::InvalidToken)?;
39 let mut block = BlockBuilder::new();
40 for restriction in restrictions {
41 block = block.check(restriction.to_check()?).map_err(Error::Datalog)?;
42 }
43 token
44 .append(block)
45 .and_then(|token| token.to_base64())
46 .map_err(Error::Datalog)
47}
48
49pub fn granted_rights(root_key: PublicKey, token: &str) -> Result<Vec<Right>, Error> {
52 let token = Biscuit::from_base64(token.trim(), root_key).map_err(Error::InvalidToken)?;
53 let mut authorizer = AuthorizerBuilder::new().build(&token).map_err(Error::Datalog)?;
54 let rights: Vec<(String, String)> = authorizer
55 .query("granted($s, $u) <- right($s, $u)")
56 .map_err(Error::Datalog)?;
57 let mut rights = rights
58 .into_iter()
59 .map(|(server, user)| {
60 Ok(Right {
61 server: server.parse()?,
62 user: user.parse()?,
63 })
64 })
65 .collect::<Result<Vec<_>, Error>>()?;
66 rights.sort();
67 Ok(rights)
68}
69
70#[derive(Debug)]
72pub struct BlockInfo {
73 pub revocation_id: String,
76 pub source: String,
78}
79
80pub fn inspect(token: &str) -> Result<Vec<BlockInfo>, Error> {
82 let token = UnverifiedBiscuit::from_base64(token.trim()).map_err(Error::InvalidToken)?;
83 token
84 .revocation_identifiers()
85 .iter()
86 .enumerate()
87 .map(|(index, id)| {
88 let source = token.print_block_source(index).map_err(Error::InvalidToken)?;
89 Ok(BlockInfo {
90 revocation_id: hex(id),
91 source,
92 })
93 })
94 .collect()
95}