Optimizations of RPC and delivery
ci/woodpecker/push/ociImagePush Pipeline was successful Details

This commit is contained in:
Natty 2024-12-19 16:58:10 +01:00
parent 82945279de
commit 3e4ae86c38
Signed by: natty
GPG Key ID: BF6CB659ADEE60EC
8 changed files with 60 additions and 54 deletions

1
Cargo.lock generated
View File

@ -2028,6 +2028,7 @@ dependencies = [
"miette 7.2.0", "miette 7.2.0",
"percent-encoding", "percent-encoding",
"quick-xml", "quick-xml",
"rand",
"reqwest", "reqwest",
"rsa", "rsa",
"serde", "serde",

View File

@ -62,6 +62,7 @@ quick-xml = "0.36"
redis = "0.26" redis = "0.26"
regex = "1.9" regex = "1.9"
rmp-serde = "1.3" rmp-serde = "1.3"
rand = "0.8"
rsa = "0.9" rsa = "0.9"
reqwest = "0.12" reqwest = "0.12"
sea-orm = "1" sea-orm = "1"

View File

@ -40,6 +40,7 @@ hyper = { workspace = true, features = ["full"] }
percent-encoding = { workspace = true } percent-encoding = { workspace = true }
reqwest = { workspace = true, features = ["stream", "hickory-dns"] } reqwest = { workspace = true, features = ["stream", "hickory-dns"] }
rand = { workspace = true }
ed25519-dalek = { workspace = true, features = [ ed25519-dalek = { workspace = true, features = [
"pem", "pem",
"pkcs8", "pkcs8",

View File

@ -4,6 +4,7 @@ use http::{HeaderMap, HeaderName, HeaderValue, Method};
use indexmap::IndexSet; use indexmap::IndexSet;
use serde_json::Value; use serde_json::Value;
use sha2::Digest; use sha2::Digest;
use std::fmt::Write;
use std::{fmt::Display, string::FromUtf8Error, sync::Arc}; use std::{fmt::Display, string::FromUtf8Error, sync::Arc};
use thiserror::Error; use thiserror::Error;
use tokio::task; use tokio::task;
@ -257,16 +258,17 @@ impl ApClientService for ApClientServiceDefaultProvider {
let message = components let message = components
.iter() .iter()
.map(|(k, v)| format!("{}: {}", k.as_ref(), v)) .fold(String::new(), |mut acc, (k, v)| {
.collect::<Vec<_>>() writeln!(&mut acc, "{}: {}", k.as_ref(), v).unwrap();
.join("\n"); acc
});
let key_id = signing_key.key_id.clone().into_owned(); let key_id = signing_key.key_id.clone().into_owned();
let key = signing_key.into_owned(); let key = signing_key.into_owned();
let signature = task::spawn_blocking(move || { let signature = task::spawn_blocking(move || {
key key
.key .key
.sign_base64(signing_algorithm, &message.into_bytes()) .sign_base64(signing_algorithm, message.trim_end().as_bytes())
}).await??; }).await??;
Ok(ApSignature { Ok(ApSignature {
@ -329,7 +331,7 @@ impl ApClientService for ApClientServiceDefaultProvider {
} }
headers.insert( headers.insert(
HeaderName::from_lowercase(b"signature").unwrap(), HeaderName::from_static("signature"),
HeaderValue::try_from(signed.to_string())?, HeaderValue::try_from(signed.to_string())?,
); );
@ -350,10 +352,9 @@ impl ApClientService for ApClientServiceDefaultProvider {
signing_algorithm: SigningAlgorithm, signing_algorithm: SigningAlgorithm,
expires: Option<chrono::DateTime<Utc>>, expires: Option<chrono::DateTime<Utc>>,
url: &str, url: &str,
body: &Value, body_bytes: Vec<u8>,
) -> Result<String, Self::Error> { ) -> Result<String, Self::Error> {
let url = url.parse()?; let url = url.parse()?;
let body_bytes = serde_json::to_vec(body)?;
// Move in, move out :3 // Move in, move out :3
let (digest_raw, body_bytes) = task::spawn_blocking(move || { let (digest_raw, body_bytes) = task::spawn_blocking(move || {
let mut sha = sha2::Sha256::new(); let mut sha = sha2::Sha256::new();
@ -406,12 +407,12 @@ impl ApClientService for ApClientServiceDefaultProvider {
} }
headers.insert( headers.insert(
HeaderName::from_lowercase(b"digest").unwrap(), HeaderName::from_static("digest"),
HeaderValue::try_from(digest_base64)?, HeaderValue::try_from(digest_base64)?,
); );
headers.insert( headers.insert(
HeaderName::from_lowercase(b"signature").unwrap(), HeaderName::from_static("signature"),
HeaderValue::try_from(signed.to_string())?, HeaderValue::try_from(signed.to_string())?,
); );

View File

@ -2,7 +2,7 @@ use rsa::pkcs1::DecodeRsaPrivateKey;
use rsa::pkcs1::DecodeRsaPublicKey; use rsa::pkcs1::DecodeRsaPublicKey;
use rsa::pkcs8::DecodePrivateKey; use rsa::pkcs8::DecodePrivateKey;
use rsa::pkcs8::DecodePublicKey; use rsa::pkcs8::DecodePublicKey;
use rsa::signature::Verifier; use rsa::signature::{RandomizedSigner, Verifier};
use rsa::{ use rsa::{
sha2::{Sha256, Sha512}, sha2::{Sha256, Sha512},
signature::Signer, signature::Signer,
@ -268,10 +268,10 @@ impl ApHttpSigningKey<'_> {
) -> Result<Vec<u8>, ApSigningError> { ) -> Result<Vec<u8>, ApSigningError> {
match (self, algorithm) { match (self, algorithm) {
(Self::RsaSha256(key), SigningAlgorithm::RsaSha256 | SigningAlgorithm::Hs2019) => { (Self::RsaSha256(key), SigningAlgorithm::RsaSha256 | SigningAlgorithm::Hs2019) => {
Ok(Box::<[u8]>::from(key.sign(message)).into_vec()) Ok(Box::<[u8]>::from(key.sign_with_rng(&mut rand::thread_rng(), message)).into_vec())
} }
(Self::RsaSha512(key), SigningAlgorithm::Hs2019) => { (Self::RsaSha512(key), SigningAlgorithm::Hs2019) => {
Ok(Box::<[u8]>::from(key.sign(message)).into_vec()) Ok(Box::<[u8]>::from(key.sign_with_rng(&mut rand::thread_rng(), message)).into_vec())
} }
(Self::Ed25519(key), SigningAlgorithm::Hs2019) => { (Self::Ed25519(key), SigningAlgorithm::Hs2019) => {
Ok(key.sign(message).to_bytes().to_vec()) Ok(key.sign(message).to_bytes().to_vec())

View File

@ -171,6 +171,6 @@ pub trait ApClientService: Send + Sync {
signing_algorithm: SigningAlgorithm, signing_algorithm: SigningAlgorithm,
expires: Option<chrono::DateTime<Utc>>, expires: Option<chrono::DateTime<Utc>>,
url: &str, url: &str,
body: &Value, body: Vec<u8>,
) -> Result<String, Self::Error>; ) -> Result<String, Self::Error>;
} }

View File

@ -23,7 +23,7 @@ struct RpcApGet {
struct RpcApPost { struct RpcApPost {
user_id: String, user_id: String,
url: String, url: String,
body: serde_json::Value, body: String,
} }
pub fn create_rpc_router() -> MagRpc { pub fn create_rpc_router() -> MagRpc {
@ -90,7 +90,7 @@ pub fn create_rpc_router() -> MagRpc {
.create_signing_key(&key_id, SigningAlgorithm::RsaSha256)?; .create_signing_key(&key_id, SigningAlgorithm::RsaSha256)?;
let result = service let result = service
.ap_client .ap_client
.signed_post(signing_key, SigningAlgorithm::RsaSha256, None, &url, &body) .signed_post(signing_key, SigningAlgorithm::RsaSha256, None, &url, body.into_bytes())
.await?; .await?;
Result::<_, DeliveryError>::Ok(result) Result::<_, DeliveryError>::Ok(result)
}, },

View File

@ -12,7 +12,7 @@ use std::net::SocketAddr;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::pin::Pin; use std::pin::Pin;
use std::sync::Arc; use std::sync::Arc;
use tokio::io::{AsyncRead, AsyncReadExt, AsyncWriteExt, BufReader}; use tokio::io::{AsyncRead, AsyncReadExt, AsyncWriteExt, BufReader, BufWriter};
use tokio::net::{TcpListener, UnixSocket}; use tokio::net::{TcpListener, UnixSocket};
use tokio::select; use tokio::select;
use tokio::task::JoinSet; use tokio::task::JoinSet;
@ -223,15 +223,16 @@ impl MagRpc {
debug!("RPC TCP connection accepted: {:?}", remote_addr); debug!("RPC TCP connection accepted: {:?}", remote_addr);
let (cancel_send, cancel_recv) = tokio::sync::oneshot::channel::<()>(); let (cancel_send, cancel_recv) = tokio::sync::oneshot::channel::<()>();
let (read_half, mut write_half) = stream.into_split(); let (read_half, write_half) = stream.into_split();
let buf_read = BufReader::new(read_half); let buf_read = BufReader::new(read_half);
let mut buf_write = BufWriter::new(write_half);
let context = context.clone(); let context = context.clone();
let rx_dec = rx_dec.clone(); let rx_dec = rx_dec.clone();
let fut = async move { let fut = async move {
let src = rx_dec let src = rx_dec
.stream_decode(buf_read, cancel_recv) .stream_decode(buf_read, cancel_recv)
.map_ok(process(context)) .map_ok(process(context))
.try_buffer_unordered(100) .try_buffer_unordered(400)
.boxed(); .boxed();
futures::pin_mut!(src); futures::pin_mut!(src);
@ -241,14 +242,14 @@ impl MagRpc {
continue; continue;
}; };
write_half.write_u8(b'M').await.into_diagnostic()?; buf_write.write_u8(b'M').await.into_diagnostic()?;
write_half.write_u64(serial).await.into_diagnostic()?; buf_write.write_u64(serial).await.into_diagnostic()?;
write_half buf_write
.write_u32(bytes.len() as u32) .write_u32(bytes.len() as u32)
.await .await
.into_diagnostic()?; .into_diagnostic()?;
write_half.write_all(&bytes).await.into_diagnostic()?; buf_write.write_all(&bytes).await.into_diagnostic()?;
write_half.flush().await.into_diagnostic()?; buf_write.flush().await.into_diagnostic()?;
} }
Ok(remote_addr) Ok(remote_addr)
@ -313,15 +314,16 @@ impl MagRpc {
debug!("RPC Unix connection accepted: {:?}", remote_addr); debug!("RPC Unix connection accepted: {:?}", remote_addr);
let (cancel_send, cancel_recv) = tokio::sync::oneshot::channel::<()>(); let (cancel_send, cancel_recv) = tokio::sync::oneshot::channel::<()>();
let (read_half, mut write_half) = stream.into_split(); let (read_half, write_half) = stream.into_split();
let buf_read = BufReader::new(read_half); let buf_read = BufReader::new(read_half);
let mut buf_write = BufWriter::new(write_half);
let context = context.clone(); let context = context.clone();
let rx_dec = rx_dec.clone(); let rx_dec = rx_dec.clone();
let fut = async move { let fut = async move {
let src = rx_dec let src = rx_dec
.stream_decode(buf_read, cancel_recv) .stream_decode(buf_read, cancel_recv)
.map_ok(process(context)) .map_ok(process(context))
.try_buffer_unordered(100) .try_buffer_unordered(400)
.boxed(); .boxed();
futures::pin_mut!(src); futures::pin_mut!(src);
@ -331,14 +333,14 @@ impl MagRpc {
continue; continue;
}; };
write_half.write_u8(b'M').await.into_diagnostic()?; buf_write.write_u8(b'M').await.into_diagnostic()?;
write_half.write_u64(serial).await.into_diagnostic()?; buf_write.write_u64(serial).await.into_diagnostic()?;
write_half buf_write
.write_u32(bytes.len() as u32) .write_u32(bytes.len() as u32)
.await .await
.into_diagnostic()?; .into_diagnostic()?;
write_half.write_all(&bytes).await.into_diagnostic()?; buf_write.write_all(&bytes).await.into_diagnostic()?;
write_half.flush().await.into_diagnostic()?; buf_write.flush().await.into_diagnostic()?;
} }
miette::Result::<()>::Ok(()) miette::Result::<()>::Ok(())