134 lines
4.0 KiB
Rust
134 lines
4.0 KiB
Rust
use std::path::Path;
|
|
|
|
use async_ssh2_tokio::Config;
|
|
use reqwest::Client;
|
|
use reqwest::header::{HeaderName, HeaderValue};
|
|
use async_trait::async_trait;
|
|
use async_ssh2_tokio::client::{self, AuthMethod, Client as SSHClient, ServerCheckMethod};
|
|
use rocket::futures::TryFutureExt;
|
|
use rocket::tokio::fs;
|
|
use serde::Deserialize;
|
|
use enum_dispatch::enum_dispatch;
|
|
|
|
use crate::app_config::CONFIG;
|
|
use crate::errors::AutoDecryptError;
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
pub(crate) enum ConsentMethode {
|
|
None,
|
|
Boolean,
|
|
PassheyHash(String),
|
|
}
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
#[enum_dispatch(ProviderAction)]
|
|
pub(crate) enum ActionType {
|
|
HTTPRequest(HTTPAction),
|
|
SSHRequest(SSHAction),
|
|
EncryptedRequest(EncryptedAction)
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
pub struct Providers {
|
|
pub(crate) access_key_hash: String,
|
|
pub(crate) consent_methode: ConsentMethode,
|
|
pub(crate) execution_action: ActionType,
|
|
// if action in seperate file and constent methode is passkey, we try
|
|
// to decrypt the action file with the passkey
|
|
}
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
struct HTTPAction {
|
|
pub(crate) method: String,
|
|
pub(crate) uri: String,
|
|
pub(crate) headers: Option<Vec<(String, String)>>,
|
|
pub(crate) body: Option<String>,
|
|
}
|
|
|
|
#[async_trait]
|
|
impl ProviderAction for HTTPAction {
|
|
async fn execute(&self) -> Result<String, String> {
|
|
let client = Client::new();
|
|
let mut req_builder = client.request(
|
|
reqwest::Method::from_bytes(self.method.as_bytes())
|
|
.map_err(|e| e.to_string())?,
|
|
&self.uri,
|
|
);
|
|
if let Some(headers) = &self.headers {
|
|
for (key, value) in headers {
|
|
req_builder = req_builder.header(
|
|
HeaderName::from_bytes(key.as_bytes()).map_err(|e| e.to_string())?,
|
|
HeaderValue::from_str(value).map_err(|e| e.to_string())?,
|
|
);
|
|
}
|
|
}
|
|
let response = req_builder.send().await
|
|
.map_err(|e| e.to_string())?;
|
|
Ok(format!("Success! Server replied with: {}", response.text().await.map_err(|e| e.to_string())?))
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
struct SSHAction {
|
|
pub(crate) uri: String,
|
|
pub(crate) port: u16,
|
|
pub(crate) username: String,
|
|
pub(crate) private_key: String,
|
|
pub(crate) cmd: String,
|
|
}
|
|
|
|
#[async_trait]
|
|
impl ProviderAction for SSHAction {
|
|
async fn execute(&self) -> Result<String, String> {
|
|
let auth_method = AuthMethod::PrivateKey { key_data: self.private_key.clone(), key_pass: None };
|
|
let client = SSHClient::connect(
|
|
(&*self.uri, self.port),
|
|
&self.username,
|
|
auth_method,
|
|
ServerCheckMethod::KnownHostsFile(CONFIG.wait().ssh_known_host_file.clone()),
|
|
).await.map_err(|e| e.to_string())?;
|
|
|
|
let result = client.execute(&self.cmd).await.map_err(|e| e.to_string())?;
|
|
if result.exit_status == 0 {
|
|
Ok(result.stdout)
|
|
} else {
|
|
Err(result.stderr)
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
pub struct EncryptedAction{
|
|
pub(crate) filename: String,
|
|
pub(crate) content: Option<String>
|
|
}
|
|
impl ProviderAction for EncryptedAction {}
|
|
impl EncryptedAction {
|
|
pub(crate) fn load_from_file(&mut self, find_in_dir: &Path) -> Result<&mut Self, AutoDecryptError> {
|
|
let content = std::fs::read_to_string(find_in_dir.join(&self.filename))
|
|
.map_err(|err| AutoDecryptError::ConfigurationError { comment: err.to_string() })?;
|
|
self.content = Some(content);
|
|
Ok(self)
|
|
}
|
|
|
|
|
|
async fn to_executable_action(&self, key: &str) -> Result<ActionType, AutoDecryptError> {
|
|
todo!()
|
|
//let cleartext_toml =
|
|
//1. get Cleartext toml 2. load tomel as any other 3. return object
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
#[async_trait]
|
|
#[enum_dispatch]
|
|
pub (crate) trait ProviderAction: std::fmt::Debug + Send + Sync {
|
|
async fn execute(&self) -> Result<String, String> {
|
|
return Err("We are not directly executable!".to_string())
|
|
}
|
|
}
|