1use crate::errors;
2use crate::{Host, Result, WasccEntity};
3use std::collections::HashMap;
4use std::sync::Arc;
5use std::sync::RwLock;
6use wascap::jwt::Token;
7use wascap::prelude::*;
8
9pub(crate) type ClaimsMap = Arc<RwLock<HashMap<String, Claims<wascap::jwt::Actor>>>>;
10
11pub trait Authorizer: Sync + Send {
17 fn can_load(&self, claims: &Claims<Actor>) -> bool;
20 fn can_invoke(&self, claims: &Claims<Actor>, target: &WasccEntity, operation: &str) -> bool;
24}
25
26pub(crate) struct DefaultAuthorizer {}
27
28impl DefaultAuthorizer {
29 pub fn new() -> impl Authorizer {
30 DefaultAuthorizer {}
31 }
32}
33
34impl Authorizer for DefaultAuthorizer {
35 fn can_load(&self, _claims: &Claims<Actor>) -> bool {
36 true
37 }
38
39 fn can_invoke(&self, _claims: &Claims<Actor>, target: &WasccEntity, _operation: &str) -> bool {
43 match target {
44 WasccEntity::Actor(_a) => true,
45 WasccEntity::Capability { .. } => true,
46 }
47 }
48}
49
50pub(crate) fn get_all_claims(map: ClaimsMap) -> Vec<(String, Claims<wascap::jwt::Actor>)> {
51 map.read()
52 .unwrap()
53 .iter()
54 .map(|(pk, claims)| (pk.clone(), claims.clone()))
55 .collect()
56}
57
58pub(crate) fn can_invoke(
61 claims: &Claims<wascap::jwt::Actor>,
62 capability_id: &str,
63 _operation: &str,
64) -> bool {
65 if claims.subject == capability_id {
68 return true;
69 }
70 claims
71 .metadata
72 .as_ref()
73 .unwrap()
74 .caps
75 .as_ref()
76 .map_or(false, |caps| caps.contains(&capability_id.to_string()))
77}
78
79pub(crate) fn extract_claims(buf: &[u8]) -> Result<wascap::jwt::Token<wascap::jwt::Actor>> {
81 let token = wascap::wasm::extract_claims(buf)?;
82 match token {
83 Some(token) => {
84 let claims = token.claims.clone();
85 let caps = claims.metadata.as_ref().unwrap().caps.clone();
86 info!(
87 "Actor claims loaded for {} - {}",
88 &claims.subject,
89 caps.unwrap_or(vec![]).join(",")
90 );
91 Ok(token)
92 }
93 None => Err(errors::new(errors::ErrorKind::Authorization(
94 "No embedded JWT in actor module".to_string(),
95 ))),
96 }
97}
98
99pub(crate) fn enforce_validation(jwt: &str) -> Result<()> {
100 let v = validate_token::<wascap::jwt::Actor>(jwt)?;
101 if v.expired {
102 Err(errors::new(errors::ErrorKind::Authorization(
103 "Expired token".to_string(),
104 )))
105 } else if v.cannot_use_yet {
106 Err(errors::new(errors::ErrorKind::Authorization(format!(
107 "Module cannot be used before {}",
108 v.not_before_human
109 ))))
110 } else {
111 Ok(())
112 }
113}
114
115pub(crate) fn register_claims(
116 claims_map: ClaimsMap,
117 subject: &str,
118 claims: Claims<wascap::jwt::Actor>,
119) {
120 claims_map
121 .write()
122 .unwrap()
123 .insert(subject.to_string(), claims);
124}
125
126pub(crate) fn unregister_claims(claims_map: ClaimsMap, subject: &str) {
127 {
128 let mut lock = claims_map.write().unwrap();
129 let _ = lock.remove(subject);
130 }
131}
132
133impl Host {
134 pub(crate) fn check_auth(&self, token: &Token<wascap::jwt::Actor>) -> bool {
135 self.authorizer.read().unwrap().can_load(&token.claims)
136 }
137}