JavaScript is disabled, refresh for a better experience. ambee/giterated

ambee/giterated

Git repository hosting, collaboration, and discovery for the Fediverse.

Change forwarding

Amber - ⁨2⁩ years ago

parent: tbd commit: ⁨2556801

Showing ⁨⁨8⁩ changed files⁩ with ⁨⁨79⁩ insertions⁩ and ⁨⁨17⁩ deletions⁩

giterated-daemon/src/connection/authentication.rs

View file
@@ -1,9 +1,15 @@
1 use std::sync::Arc;
2
1 3 use anyhow::Error;
2 4 use thiserror::Error;
5 use tokio::{fs::File, io::AsyncReadExt};
3 6
4 7 use crate::message::{AuthenticatedInstance, Message, MessageHandler, NetworkMessage, State};
5 use giterated_models::messages::authentication::{
6 AuthenticationTokenRequest, RegisterAccountRequest, TokenExtensionRequest,
8 use giterated_models::{
9 messages::authentication::{
10 AuthenticationTokenRequest, RegisterAccountRequest, TokenExtensionRequest, AuthenticationTokenResponse,
11 },
12 model::authenticated::InstanceAuthenticator,
7 13 };
8 14
9 15 use super::wrapper::ConnectionState;
@@ -69,6 +75,38 @@ async fn authentication_token_request(
69 75 Message(request): Message<AuthenticationTokenRequest>,
70 76 instance: AuthenticatedInstance,
71 77 ) -> Result<(), AuthenticationConnectionError> {
78 if request.instance != connection_state.instance {
79 // We need to perform the authentication request on behalf of
80 // the user. TODO: Oauth-style flow
81 let mut connections = connection_state.instance_connections.lock().await;
82
83 let connection = connections.get_or_open(&request.instance).unwrap();
84
85 let private_key = {
86 let mut file = File::open(connection_state.config["giterated"]["keys"]["private"].as_str().unwrap()).await.unwrap();
87
88 let mut key = String::new();
89 file.read_to_string(&mut key).await.unwrap();
90
91 key
92 };
93
94 let authenticator = InstanceAuthenticator {
95 instance: connection_state.instance.clone(),
96 private_key,
97 };
98
99 let response = giterated_api::request::request_local(request)
100 .authenticate(authenticator)
101 .execute_expect::<AuthenticationTokenResponse>(&connection)
102 .await.unwrap();
103 drop(connection);
104
105 connection_state.send(response).await.map_err(|e| AuthenticationConnectionError::Sending(e))?;
106
107 return Ok(());
108 }
109
72 110 let issued_for = instance.inner().clone();
73 111
74 112 let mut token_granter = connection_state.auth_granter.lock().await;
@@ -121,3 +159,12 @@ pub enum AuthenticationConnectionError {
121 159 #[error("error issuing token")]
122 160 TokenIssuance(Error),
123 161 }
162
163 async fn private_key(path: &str) -> Vec<u8> {
164 let mut file = File::open(path).await.unwrap();
165
166 let mut key = vec![];
167 file.read_to_end(&mut key).await.unwrap();
168
169 key
170 }

giterated-daemon/src/connection/forwarded.rs

View file
@@ -55,6 +55,4 @@ pub async fn wrap_forwarded(pool: &DaemonConnectionPool, message: AuthenticatedP
55 55 }
56 56 }
57 57 }
58
59 todo!()
60 58 }

giterated-daemon/src/connection/wrapper.rs

View file
@@ -17,6 +17,7 @@ use serde::Serialize;
17 17
18 18 use tokio::{net::TcpStream, sync::Mutex};
19 19 use tokio_tungstenite::{tungstenite::Message, WebSocketStream};
20 use toml::Table;
20 21
21 22 use crate::{
22 23 authentication::AuthenticationTokenGranter,
@@ -42,6 +43,7 @@ pub async fn connection_wrapper(
42 43 addr: SocketAddr,
43 44 instance: impl ToOwned<Owned = Instance>,
44 45 instance_connections: Arc<Mutex<InstanceConnections>>,
46 config: Table,
45 47 ) {
46 48 let connection_state = ConnectionState {
47 49 socket: Arc::new(Mutex::new(socket)),
@@ -54,6 +56,8 @@ pub async fn connection_wrapper(
54 56 instance: instance.to_owned(),
55 57 handshaked: Arc::new(AtomicBool::new(false)),
56 58 key_cache: Arc::default(),
59 instance_connections: instance_connections.clone(),
60 config,
57 61 };
58 62
59 63 let mut handshaked = false;
@@ -179,6 +183,8 @@ pub struct ConnectionState {
179 183 pub instance: Instance,
180 184 pub handshaked: Arc<AtomicBool>,
181 185 pub key_cache: Arc<Mutex<PublicKeyCache>>,
186 pub instance_connections: Arc<Mutex<InstanceConnections>>,
187 pub config: Table,
182 188 }
183 189
184 190 impl ConnectionState {

giterated-daemon/src/main.rs

View file
@@ -26,15 +26,15 @@ extern crate tracing;
26 26 #[tokio::main]
27 27 async fn main() -> Result<(), Error> {
28 28 tracing_subscriber::fmt::init();
29 let mut listener = TcpListener::bind("0.0.0.0:7270").await?;
30 let connections: Arc<Mutex<Connections>> = Arc::default();
31 let instance_connections: Arc<Mutex<InstanceConnections>> = Arc::default();
32 29 let config: Table = {
33 30 let mut file = File::open("Giterated.toml").await?;
34 31 let mut text = String::new();
35 32 file.read_to_string(&mut text).await?;
36 33 text.parse()?
37 34 };
35 let mut listener = TcpListener::bind(config["giterated"]["bind"].as_str().unwrap()).await?;
36 let connections: Arc<Mutex<Connections>> = Arc::default();
37 let instance_connections: Arc<Mutex<InstanceConnections>> = Arc::default();
38 38 let db_conn_options = PgConnectOptions::new()
39 39 .host(config["postgres"]["host"].as_str().unwrap())
40 40 .port(config["postgres"]["port"].as_integer().unwrap() as u16)
@@ -117,6 +117,7 @@ async fn main() -> Result<(), Error> {
117 117 address,
118 118 Instance::from_str("giterated.dev").unwrap(),
119 119 instance_connections.clone(),
120 config.clone(),
120 121 )),
121 122 };
122 123

giterated-models/src/messages/authentication.rs

View file
@@ -1,6 +1,6 @@
1 1 use serde::{Deserialize, Serialize};
2 2
3 use crate::model::authenticated::UserAuthenticationToken;
3 use crate::model::{authenticated::UserAuthenticationToken, instance::Instance};
4 4
5 5 /// An account registration request.
6 6 ///
@@ -32,6 +32,7 @@ pub struct RegisterAccountResponse {
32 32 /// - Decrypts user private key to issue to
33 33 #[derive(Clone, Debug, Serialize, Deserialize)]
34 34 pub struct AuthenticationTokenRequest {
35 pub instance: Instance,
35 36 pub username: String,
36 37 pub password: String,
37 38 }

giterated-models/src/messages/repository.rs

View file
@@ -149,7 +149,6 @@ pub struct RepositoryInfoRequest {
149 149 pub path: Option<String>,
150 150 }
151 151
152
153 152 #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
154 153 pub struct RepositorySettingsRequest {
155 154 pub repository: Repository,

giterated-models/src/model/authenticated.rs

View file
@@ -22,7 +22,7 @@ pub struct UserTokenMetadata {
22 22 #[derive(Debug)]
23 23 pub struct Authenticated<T: Serialize> {
24 24 pub target_instance: Option<Instance>,
25 pub source: Vec<Box<dyn AuthenticationSourceProvider>>,
25 pub source: Vec<Box<dyn AuthenticationSourceProvider + Send + Sync>>,
26 26 pub message_type: String,
27 27 pub message: T,
28 28 }
@@ -109,7 +109,10 @@ impl<T: Serialize + Debug> Authenticated<T> {
109 109 }
110 110 }
111 111
112 pub fn append_authentication<P: AuthenticationSourceProvider + 'static>(&mut self, authentication: P) {
112 pub fn append_authentication<P: AuthenticationSourceProvider + 'static + Send + Sync>(
113 &mut self,
114 authentication: P,
115 ) {
113 116 let message_payload = serde_json::to_vec(&self.message).unwrap();
114 117
115 118 info!(
@@ -117,7 +120,8 @@ impl<T: Serialize + Debug> Authenticated<T> {
117 120 std::str::from_utf8(&message_payload).unwrap()
118 121 );
119 122
120 self.source.push(Box::new(authentication) as Box<dyn AuthenticationSourceProvider>);
123 self.source
124 .push(Box::new(authentication) as Box<dyn AuthenticationSourceProvider + Send + Sync>);
121 125 }
122 126
123 127 pub fn into_payload(self) -> AuthenticatedPayload {
@@ -143,16 +147,16 @@ impl AuthenticationSourceProvider for UserAuthenticator {
143 147 }
144 148
145 149 #[derive(Debug, Clone)]
146 pub struct InstanceAuthenticator<'a> {
150 pub struct InstanceAuthenticator {
147 151 pub instance: Instance,
148 pub private_key: &'a str,
152 pub private_key: String,
149 153 }
150 154
151 impl AuthenticationSourceProvider for InstanceAuthenticator<'_> {
155 impl AuthenticationSourceProvider for InstanceAuthenticator {
152 156 fn authenticate(&self, payload: &Vec<u8>) -> AuthenticationSource {
153 157 let mut rng = rand::thread_rng();
154 158
155 let private_key = RsaPrivateKey::from_pkcs1_pem(self.private_key).unwrap();
159 let private_key = RsaPrivateKey::from_pkcs1_pem(&self.private_key).unwrap();
156 160 let signing_key = SigningKey::<Sha256>::new(private_key);
157 161 let signature = signing_key.sign_with_rng(&mut rng, &payload);
158 162

giterated-models/src/model/repository.rs

View file
@@ -174,7 +174,13 @@ impl From<git2::Commit<'_>> for Commit {
174 174 Self {
175 175 oid: commit.id().to_string(),
176 176 // This shouldn't ever fail, as we already know the object has an oid.
177 short_oid: commit.as_object().short_id().unwrap().as_str().unwrap().to_string(),
177 short_oid: commit
178 .as_object()
179 .short_id()
180 .unwrap()
181 .as_str()
182 .unwrap()
183 .to_string(),
178 184 message: commit.message().map(|message| message.to_string()),
179 185 author: commit.author().into(),
180 186 committer: commit.committer().into(),