feat: Add SSH authentication interceptor and update proto definitions
This commit is contained in:
1
crates/nxmesh-proto/src/auth/mod.rs
Normal file
1
crates/nxmesh-proto/src/auth/mod.rs
Normal file
@@ -0,0 +1 @@
|
||||
pub mod ssh_auth;
|
||||
49
crates/nxmesh-proto/src/auth/ssh_auth.rs
Normal file
49
crates/nxmesh-proto/src/auth/ssh_auth.rs
Normal file
@@ -0,0 +1,49 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use tonic::{Request, Status, async_trait, transport::CertificateDer};
|
||||
use tonic_async_interceptor::{AsyncInterceptor, AsyncInterceptorLayer, async_interceptor};
|
||||
|
||||
pub fn create_ssh_auth_interceptor(
|
||||
certificate_provider: Arc<dyn CertificateValidationProvider>,
|
||||
) -> AsyncInterceptorLayer<SshAuthInterceptor> {
|
||||
async_interceptor(SshAuthInterceptor::new(certificate_provider))
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SshAuthInterceptor {
|
||||
certificate_provider: Arc<dyn CertificateValidationProvider>,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
pub trait CertificateValidationProvider: Send + Sync {
|
||||
async fn is_authorized(&self, certs: &Arc<Vec<CertificateDer<'_>>>) -> Result<bool, Status>;
|
||||
}
|
||||
|
||||
impl AsyncInterceptor for SshAuthInterceptor {
|
||||
type Future =
|
||||
std::pin::Pin<Box<dyn std::future::Future<Output = Result<Request<()>, Status>> + Send>>;
|
||||
fn call(&mut self, req: Request<()>) -> Self::Future {
|
||||
let this = self.clone();
|
||||
Box::pin(async move { this.authenticate(req).await })
|
||||
}
|
||||
}
|
||||
|
||||
impl SshAuthInterceptor {
|
||||
pub fn new(certificate_provider: Arc<dyn CertificateValidationProvider>) -> Self {
|
||||
SshAuthInterceptor {
|
||||
certificate_provider,
|
||||
}
|
||||
}
|
||||
|
||||
async fn authenticate(&self, req: Request<()>) -> Result<Request<()>, Status> {
|
||||
let certs = req.peer_certs().ok_or(Status::unauthenticated("No cert"))?;
|
||||
|
||||
let is_authorized = self.certificate_provider.is_authorized(&certs).await?;
|
||||
|
||||
if is_authorized {
|
||||
Ok(req)
|
||||
} else {
|
||||
Err(Status::permission_denied("Blocked"))
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user