1 |
use std::{any::type_name, fmt::Debug};
|
2 |
|
3 |
use rsa::{
|
4 |
pkcs1::DecodeRsaPrivateKey,
|
5 |
pss::SigningKey,
|
6 |
sha2::Sha256,
|
7 |
signature::{RandomizedSigner, SignatureEncoding},
|
8 |
RsaPrivateKey,
|
9 |
};
|
10 |
use serde::{Deserialize, Serialize};
|
11 |
use tracing::info;
|
12 |
|
13 |
use crate::messages::MessageTarget;
|
14 |
|
15 |
use super::{instance::Instance, user::User};
|
16 |
|
17 |
#[derive(Debug, Serialize, Deserialize)]
|
18 |
pub struct UserTokenMetadata {
|
19 |
pub user: User,
|
20 |
pub generated_for: Instance,
|
21 |
pub exp: u64,
|
22 |
}
|
23 |
|
24 |
#[derive(Debug)]
|
25 |
pub struct Authenticated<T: Serialize> {
|
26 |
pub target_instance: Option<Instance>,
|
27 |
pub source: Vec<Box<dyn AuthenticationSourceProvider + Send + Sync>>,
|
28 |
pub message_type: String,
|
29 |
pub message: T,
|
30 |
}
|
31 |
|
32 |
#[derive(Debug, Hash, PartialEq, Eq, Serialize, Deserialize)]
|
33 |
pub struct AuthenticatedPayload {
|
34 |
pub target_instance: Option<Instance>,
|
35 |
pub source: Vec<AuthenticationSource>,
|
36 |
pub message_type: String,
|
37 |
pub payload: Vec<u8>,
|
38 |
}
|
39 |
|
40 |
impl<T: Serialize> From<Authenticated<T>> for AuthenticatedPayload {
|
41 |
fn from(mut value: Authenticated<T>) -> Self {
|
42 |
let payload = bincode::serialize(&value.message).unwrap();
|
43 |
|
44 |
AuthenticatedPayload {
|
45 |
target_instance: value.target_instance,
|
46 |
source: value
|
47 |
.source
|
48 |
.drain(..)
|
49 |
.map(|provider| provider.as_ref().authenticate(&payload))
|
50 |
.collect::<Vec<_>>(),
|
51 |
message_type: value.message_type,
|
52 |
payload,
|
53 |
}
|
54 |
}
|
55 |
}
|
56 |
|
57 |
pub trait AuthenticationSourceProvider: Debug {
|
58 |
fn authenticate(&self, payload: &Vec<u8>) -> AuthenticationSource;
|
59 |
}
|
60 |
|
61 |
pub trait AuthenticationSourceProviders: Debug {
|
62 |
fn authenticate_all(&self, payload: &Vec<u8>) -> Vec<AuthenticationSource>;
|
63 |
}
|
64 |
|
65 |
impl<A> AuthenticationSourceProviders for A
|
66 |
where
|
67 |
A: AuthenticationSourceProvider,
|
68 |
{
|
69 |
fn authenticate_all(&self, payload: &Vec<u8>) -> Vec<AuthenticationSource> {
|
70 |
vec![self.authenticate(payload)]
|
71 |
}
|
72 |
}
|
73 |
|
74 |
impl<A, B> AuthenticationSourceProviders for (A, B)
|
75 |
where
|
76 |
A: AuthenticationSourceProvider,
|
77 |
B: AuthenticationSourceProvider,
|
78 |
{
|
79 |
fn authenticate_all(&self, payload: &Vec<u8>) -> Vec<AuthenticationSource> {
|
80 |
let (first, second) = self;
|
81 |
|
82 |
vec![first.authenticate(payload), second.authenticate(payload)]
|
83 |
}
|
84 |
}
|
85 |
|
86 |
impl<T: Serialize + Debug + MessageTarget> Authenticated<T> {
|
87 |
pub fn new(message: T) -> Self {
|
88 |
Self {
|
89 |
source: vec![],
|
90 |
message_type: type_name::<T>().to_string(),
|
91 |
target_instance: message.target(),
|
92 |
message,
|
93 |
}
|
94 |
}
|
95 |
|
96 |
pub fn new_for(instance: impl ToOwned<Owned = Instance>, message: T) -> Self {
|
97 |
Self {
|
98 |
source: vec![],
|
99 |
message_type: type_name::<T>().to_string(),
|
100 |
message,
|
101 |
target_instance: Some(instance.to_owned()),
|
102 |
}
|
103 |
}
|
104 |
|
105 |
pub fn new_empty(message: T) -> Self {
|
106 |
Self {
|
107 |
source: vec![],
|
108 |
message_type: type_name::<T>().to_string(),
|
109 |
target_instance: message.target(),
|
110 |
message,
|
111 |
}
|
112 |
}
|
113 |
|
114 |
pub fn append_authentication<P: AuthenticationSourceProvider + 'static + Send + Sync>(
|
115 |
&mut self,
|
116 |
authentication: P,
|
117 |
) {
|
118 |
let message_payload = serde_json::to_vec(&self.message).unwrap();
|
119 |
|
120 |
info!(
|
121 |
"Verifying payload: {}",
|
122 |
std::str::from_utf8(&message_payload).unwrap()
|
123 |
);
|
124 |
|
125 |
self.source
|
126 |
.push(Box::new(authentication) as Box<dyn AuthenticationSourceProvider + Send + Sync>);
|
127 |
}
|
128 |
|
129 |
pub fn into_payload(self) -> AuthenticatedPayload {
|
130 |
self.into()
|
131 |
}
|
132 |
}
|
133 |
|
134 |
mod verified {}
|
135 |
|
136 |
#[derive(Clone, Debug)]
|
137 |
pub struct UserAuthenticator {
|
138 |
pub user: User,
|
139 |
pub token: UserAuthenticationToken,
|
140 |
}
|
141 |
|
142 |
impl AuthenticationSourceProvider for UserAuthenticator {
|
143 |
fn authenticate(&self, _payload: &Vec<u8>) -> AuthenticationSource {
|
144 |
AuthenticationSource::User {
|
145 |
user: self.user.clone(),
|
146 |
token: self.token.clone(),
|
147 |
}
|
148 |
}
|
149 |
}
|
150 |
|
151 |
#[derive(Debug, Clone)]
|
152 |
pub struct InstanceAuthenticator {
|
153 |
pub instance: Instance,
|
154 |
pub private_key: String,
|
155 |
}
|
156 |
|
157 |
impl AuthenticationSourceProvider for InstanceAuthenticator {
|
158 |
fn authenticate(&self, payload: &Vec<u8>) -> AuthenticationSource {
|
159 |
let mut rng = rand::thread_rng();
|
160 |
|
161 |
let private_key = RsaPrivateKey::from_pkcs1_pem(&self.private_key).unwrap();
|
162 |
let signing_key = SigningKey::<Sha256>::new(private_key);
|
163 |
let signature = signing_key.sign_with_rng(&mut rng, &payload);
|
164 |
|
165 |
AuthenticationSource::Instance {
|
166 |
instance: self.instance.clone(),
|
167 |
|
168 |
signature: InstanceSignature(signature.to_bytes().into_vec()),
|
169 |
}
|
170 |
}
|
171 |
}
|
172 |
|
173 |
#[repr(transparent)]
|
174 |
#[derive(Clone, Debug, Hash, PartialEq, Eq, Serialize, Deserialize)]
|
175 |
pub struct UserAuthenticationToken(String);
|
176 |
|
177 |
impl From<String> for UserAuthenticationToken {
|
178 |
fn from(value: String) -> Self {
|
179 |
Self(value)
|
180 |
}
|
181 |
}
|
182 |
|
183 |
impl ToString for UserAuthenticationToken {
|
184 |
fn to_string(&self) -> String {
|
185 |
self.0.clone()
|
186 |
}
|
187 |
}
|
188 |
|
189 |
impl AsRef<str> for UserAuthenticationToken {
|
190 |
fn as_ref(&self) -> &str {
|
191 |
&self.0
|
192 |
}
|
193 |
}
|
194 |
|
195 |
#[derive(Clone, Debug, Hash, PartialEq, Eq, Serialize, Deserialize)]
|
196 |
pub struct InstanceSignature(Vec<u8>);
|
197 |
|
198 |
impl AsRef<[u8]> for InstanceSignature {
|
199 |
fn as_ref(&self) -> &[u8] {
|
200 |
&self.0
|
201 |
}
|
202 |
}
|
203 |
|
204 |
#[derive(Clone, Debug, Hash, PartialEq, Eq, Serialize, Deserialize)]
|
205 |
pub enum AuthenticationSource {
|
206 |
User {
|
207 |
user: User,
|
208 |
token: UserAuthenticationToken,
|
209 |
},
|
210 |
Instance {
|
211 |
instance: Instance,
|
212 |
signature: InstanceSignature,
|
213 |
},
|
214 |
}
|
215 |
|