1
0
Fork 0
This repository has been archived on 2024-01-05. You can view files and clone it, but cannot push or open issues or pull requests.
command_gateway/src/daemon/server.rs

85 lines
No EOL
3 KiB
Rust

#![cfg_attr(not(unix), allow(unused_imports))]
use tonic::{Code, Request, Response, Status};
use libcommand::Command;
use libcommand::interpreter::{
unix_server::Unix,
AuthorizeRequest, AuthorizeResponse,
TerminateRequest, TerminateResponse
};
#[derive(Default)]
pub struct DaemonServer;
#[tonic::async_trait]
impl Unix for DaemonServer {
async fn authorize(
&self,
request: Request<AuthorizeRequest>,
) -> Result<Response<AuthorizeResponse>, Status> {
let session = libcommand::Session::from(request.get_ref().pid);
let cmd_arg = request.get_ref().command_arg.clone();
let cmd = Command::from(cmd_arg.as_str());
let endpoint = {
let conf_mutex = super::CONFIGURATION.lock()
.map_err(|e| Status::internal(e.to_string()))?;
let conf = conf_mutex.as_ref().ok_or_else(|| Status::internal("Configuration not loaded"))?;
if !conf.command_allowed(&cmd.command) {
return Err(Status::permission_denied("Command not authorized"));
}
conf.get_endpoint()
.and_then(|endpoint| Some(endpoint.clone()))
};
if let Some(endpoint) = endpoint {
let client = reqwest::Client::new();
let res = client.post(endpoint)
.body(cmd_arg.clone())
.send()
.await
.map_err(|_| Status::internal("ENDPOINT: Not reachable"))?;
let status = res.status();
if status.is_client_error() {
return match status {
reqwest::StatusCode::UNAUTHORIZED => {
Err(Status::unauthenticated("ENDPOINT: Not authorized"))
},
reqwest::StatusCode::BAD_REQUEST => {
Err(Status::unauthenticated("ENDPOINT: Invalid metadata"))
},
_ => {
Err(Status::permission_denied("ENDPOINT: Permission denied"))
}
}
} else if status.is_server_error() {
return Err(Status::internal("ENDPOINT: Internal error"));
} else if status.is_informational() || status.is_redirection() {
return Err(Status::unimplemented("ENDPOINT: Status code not supported"));
}
}
let session_id = session.id.clone();
super::SESSIONS.lock().unwrap().push(session);
Ok(Response::new(AuthorizeResponse {
command_arg: cmd_arg,
session_id
}))
}
async fn terminate(
&self,
request: Request<TerminateRequest>,
) -> Result<Response<TerminateResponse>, Status> {
let mut lock = super::get_sessions_lock()
.map_err(|e| Status::new(Code::Internal, e))?;
super::remove_session_by_id(&mut lock, &request.get_ref().session_id)
.map_err(|e| Status::new(Code::NotFound, e))?;
Ok(Response::new(TerminateResponse {}))
}
}