1extern crate biscuit_auth as biscuit;
2
3use biscuit::macros::{authorizer, check};
4use biscuit::{Algorithm, Biscuit, PublicKey};
5use chrono::Utc;
6use serde::Deserialize;
7
8use crate::error::TokenError;
9
10fn build_base_authorizer(
11 subject: String,
12 resource: String,
13 operation: String,
14) -> Result<biscuit::AuthorizerBuilder, TokenError> {
15 let now = Utc::now().timestamp();
16
17 let authz = authorizer!(
18 r#"
19 time({now});
20 resource({resource});
21 subject({subject});
22 operation({operation});
23 allow if subject($sub), resource($res), operation($op), right($sub, $res, $op);
24 "#
25 );
26 Ok(authz)
27}
28
29fn verify_raw_biscuit(
30 biscuit: Biscuit,
31 subject: String,
32 resource: String,
33 operation: String,
34) -> Result<(), TokenError> {
35 let authz = build_base_authorizer(subject, resource, operation)?;
36 if authz.build(&biscuit)?.authorize().is_ok() {
37 Ok(())
38 } else {
39 Err(TokenError::authorization_error(
40 "Token does not grant required access rights",
41 ))
42 }
43}
44
45pub fn verify_biscuit_local(
71 token: Vec<u8>,
72 public_key: PublicKey,
73 subject: String,
74 resource: String,
75 operation: String,
76) -> Result<(), TokenError> {
77 let biscuit = Biscuit::from(&token, public_key)?;
78 verify_raw_biscuit(biscuit, subject, resource, operation)
79}
80
81pub fn verify_token_local(
107 token: &str,
108 public_key: PublicKey,
109 subject: &str,
110 resource: &str,
111 operation: &str,
112) -> Result<(), TokenError> {
113 let biscuit = Biscuit::from_base64(token, public_key)?;
114 verify_raw_biscuit(
115 biscuit,
116 subject.to_string(),
117 resource.to_string(),
118 operation.to_string(),
119 )
120}
121
122pub fn biscuit_key_from_string(key: String) -> Result<PublicKey, TokenError> {
125 println!("Key: {:?}", key);
126 let parts = key.split('/').collect::<Vec<&str>>();
128 if parts.len() != 2 {
129 return Err(TokenError::invalid_key_format(
130 "Key must be in format 'algorithm/hexkey'",
131 ));
132 }
133
134 let alg = match parts[0] {
135 "ed25519" => Algorithm::Ed25519,
136 "secp256r1" => Algorithm::Secp256r1,
137 _ => {
138 return Err(TokenError::invalid_key_format(
139 "Unsupported algorithm, must be ed25519 or secp256r1",
140 ))
141 }
142 };
143
144 let key_bytes = hex::decode(parts[1])?;
146
147 let key = PublicKey::from_bytes(&key_bytes, alg)
149 .map_err(|e| TokenError::invalid_key_format(e.to_string()))?;
150
151 Ok(key)
152}
153
154#[derive(Debug, Deserialize, Clone)]
155pub struct ServiceNode {
156 pub component: String,
157 pub public_key: String,
158}
159
160fn verify_raw_service_chain_biscuit(
161 biscuit: Biscuit,
162 subject: String,
163 resource: String,
164 operation: String,
165 service_nodes: Vec<ServiceNode>,
166 component: Option<String>,
167) -> Result<(), TokenError> {
168 let mut authz = build_base_authorizer(subject, resource.clone(), operation)?;
169
170 let mut component_found = false;
171 if component.is_none() {
172 component_found = true;
173 }
174 for service_node in service_nodes {
175 if let Some(ref component) = component {
176 if component == &service_node.component {
177 component_found = true;
178 break;
179 }
180 }
181 let service = resource.clone();
182 let node_name = service_node.component;
183 let node_key = biscuit_key_from_string(service_node.public_key)?;
184 authz = authz.check(check!(
185 r#"
186 check if node({service}, {node_name}) trusting authority, {node_key};
187 "#
188 ))?;
189 }
190
191 if let Some(ref component) = component {
192 if !component_found {
193 return Err(TokenError::authorization_error(format!(
194 "Token does not grant required access rights. missing {}",
195 component.clone()
196 )));
197 }
198 }
199
200 if authz.build(&biscuit)?.authorize().is_ok() {
201 Ok(())
202 } else {
203 Err(TokenError::authorization_error(
204 "Token does not grant required access rights",
205 ))
206 }
207}
208
209pub fn verify_service_chain_biscuit_local(
210 token: Vec<u8>,
211 public_key: PublicKey,
212 subject: String,
213 resource: String,
214 operation: String,
215 service_nodes: Vec<ServiceNode>,
216 component: Option<String>,
217) -> Result<(), TokenError> {
218 let biscuit = Biscuit::from(&token, public_key).map_err(TokenError::biscuit_error)?;
219 verify_raw_service_chain_biscuit(
220 biscuit,
221 subject,
222 resource,
223 operation,
224 service_nodes,
225 component,
226 )
227}
228
229pub fn verify_service_chain_token_local(
230 token: &str,
231 public_key: PublicKey,
232 subject: &str,
233 resource: &str,
234 operation: &str,
235 service_nodes: Vec<ServiceNode>,
236 component: Option<String>,
237) -> Result<(), TokenError> {
238 let biscuit = Biscuit::from_base64(token, public_key).map_err(TokenError::biscuit_error)?;
239 verify_raw_service_chain_biscuit(
240 biscuit,
241 subject.to_string(),
242 resource.to_string(),
243 operation.to_string(),
244 service_nodes,
245 component,
246 )
247}