ICryptoProvider trait
This commit is contained in:
		
							
								
								
									
										143
									
								
								src/main.rs
									
									
									
									
									
								
							
							
						
						
									
										143
									
								
								src/main.rs
									
									
									
									
									
								
							@@ -6,6 +6,7 @@ use std::{
 | 
				
			|||||||
    collections::BTreeMap,
 | 
					    collections::BTreeMap,
 | 
				
			||||||
    path::{Path, PathBuf},
 | 
					    path::{Path, PathBuf},
 | 
				
			||||||
    pin::Pin,
 | 
					    pin::Pin,
 | 
				
			||||||
 | 
					    sync::Arc,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
use tokio::{
 | 
					use tokio::{
 | 
				
			||||||
    fs::{self, File},
 | 
					    fs::{self, File},
 | 
				
			||||||
@@ -288,61 +289,28 @@ impl VarsFile {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct Certs {
 | 
					trait ICryptoProvider {
 | 
				
			||||||
 | 
					    async fn request(&self) -> Result<()>;
 | 
				
			||||||
 | 
					    async fn sign(&self) -> Result<()>;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct OpenSSLProvider {
 | 
				
			||||||
 | 
					    vars: BTreeMap<String, String>,
 | 
				
			||||||
    base_dir: PathBuf,
 | 
					    base_dir: PathBuf,
 | 
				
			||||||
    encoding: String,
 | 
					    openssl_cnf: PathBuf,
 | 
				
			||||||
    req_days: u32,
 | 
					    openssl: String,
 | 
				
			||||||
    ca_file: PathBuf,
 | 
					    ca_file: PathBuf,
 | 
				
			||||||
    req_file: PathBuf,
 | 
					    req_file: PathBuf,
 | 
				
			||||||
    key_file: PathBuf,
 | 
					    key_file: PathBuf,
 | 
				
			||||||
    cert_file: PathBuf,
 | 
					    cert_file: PathBuf,
 | 
				
			||||||
    config_file: PathBuf,
 | 
					    req_days: u32,
 | 
				
			||||||
    template_file: PathBuf,
 | 
					 | 
				
			||||||
    openssl_cnf: PathBuf,
 | 
					 | 
				
			||||||
    openssl: String,
 | 
					 | 
				
			||||||
    vars: BTreeMap<String, String>,
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl Certs {
 | 
					 | 
				
			||||||
    fn new(cfg: &AppConfig, vars: BTreeMap<String, String>) -> Self {
 | 
					 | 
				
			||||||
        let base_dir = PathBuf::from(&cfg.base_directory);
 | 
					 | 
				
			||||||
        let keys_dir = base_dir.clone().join(cfg.keys_subdir.clone());
 | 
					 | 
				
			||||||
        let config_dir = base_dir.clone().join(cfg.config_subdir.clone());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        let mut vars = vars;
 | 
					 | 
				
			||||||
        let name = cfg.name.clone();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        vars.insert("KEY_CN".into(), name.clone());
 | 
					 | 
				
			||||||
        vars.insert("KEY_NAME".into(), name.clone());
 | 
					 | 
				
			||||||
        vars.insert("KEY_EMAIL".into(), cfg.email.clone());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        Self {
 | 
					 | 
				
			||||||
            base_dir: base_dir.clone(),
 | 
					 | 
				
			||||||
            encoding: cfg.encoding.clone(),
 | 
					 | 
				
			||||||
            req_days: cfg.req_days,
 | 
					 | 
				
			||||||
            ca_file: keys_dir.join(cfg.ca_filename.clone()),
 | 
					 | 
				
			||||||
            req_file: keys_dir.join(format!("{}.csr", &name)),
 | 
					 | 
				
			||||||
            key_file: keys_dir.join(format!("{}.key", &name)),
 | 
					 | 
				
			||||||
            cert_file: keys_dir.join(format!("{}.crt", &name)),
 | 
					 | 
				
			||||||
            config_file: config_dir.join(format!("{}.ovpn", &name)),
 | 
					 | 
				
			||||||
            template_file: base_dir.clone().join(cfg.template_file.clone()),
 | 
					 | 
				
			||||||
            openssl_cnf: base_dir.clone().join(
 | 
					 | 
				
			||||||
                std::env::var(cfg.openssl_cnf_env.clone())
 | 
					 | 
				
			||||||
                    .unwrap_or(cfg.openssl_default_cnf.clone()),
 | 
					 | 
				
			||||||
            ),
 | 
					 | 
				
			||||||
            openssl: cfg.openssl.clone(),
 | 
					 | 
				
			||||||
            vars,
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl OpenSSLProvider {
 | 
				
			||||||
    async fn is_ca_exists(&self) -> bool {
 | 
					    async fn is_ca_exists(&self) -> bool {
 | 
				
			||||||
        is_file_exist(&self.ca_file).await
 | 
					        is_file_exist(&self.ca_file).await
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async fn is_config_exists(&self) -> bool {
 | 
					 | 
				
			||||||
        is_file_exist(&self.config_file).await
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    async fn is_cert_exists(&self) -> bool {
 | 
					    async fn is_cert_exists(&self) -> bool {
 | 
				
			||||||
        is_file_exist(&self.cert_file).await
 | 
					        is_file_exist(&self.cert_file).await
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -351,6 +319,39 @@ impl Certs {
 | 
				
			|||||||
        is_file_exist(&self.req_file).await
 | 
					        is_file_exist(&self.req_file).await
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn from_cfg(cfg: &AppConfig, vars: BTreeMap<String, String>) -> Self {
 | 
				
			||||||
 | 
					        let base_dir = PathBuf::from(&cfg.base_directory);
 | 
				
			||||||
 | 
					        let keys_dir = base_dir.clone().join(cfg.keys_subdir.clone());
 | 
				
			||||||
 | 
					        let name = cfg.name.clone();
 | 
				
			||||||
 | 
					        let mut vars = vars;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        vars.insert("KEY_CN".into(), name.clone());
 | 
				
			||||||
 | 
					        vars.insert("KEY_NAME".into(), name.clone());
 | 
				
			||||||
 | 
					        vars.insert("KEY_EMAIL".into(), cfg.email.clone());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let ca_file = keys_dir.join(cfg.ca_filename.clone());
 | 
				
			||||||
 | 
					        let req_file = keys_dir.join(format!("{}.csr", &name));
 | 
				
			||||||
 | 
					        let key_file = keys_dir.join(format!("{}.key", &name));
 | 
				
			||||||
 | 
					        let cert_file = keys_dir.join(format!("{}.crt", &name));
 | 
				
			||||||
 | 
					        let openssl_cnf = base_dir.clone().join(
 | 
				
			||||||
 | 
					            std::env::var(cfg.openssl_cnf_env.clone()).unwrap_or(cfg.openssl_default_cnf.clone()),
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Self {
 | 
				
			||||||
 | 
					            vars,
 | 
				
			||||||
 | 
					            base_dir,
 | 
				
			||||||
 | 
					            openssl_cnf,
 | 
				
			||||||
 | 
					            openssl: cfg.openssl.clone(),
 | 
				
			||||||
 | 
					            ca_file,
 | 
				
			||||||
 | 
					            req_file,
 | 
				
			||||||
 | 
					            key_file,
 | 
				
			||||||
 | 
					            cert_file,
 | 
				
			||||||
 | 
					            req_days: cfg.req_days,
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl ICryptoProvider for OpenSSLProvider {
 | 
				
			||||||
    async fn request(&self) -> Result<()> {
 | 
					    async fn request(&self) -> Result<()> {
 | 
				
			||||||
        if self.is_req_exists().await {
 | 
					        if self.is_req_exists().await {
 | 
				
			||||||
            return Ok(());
 | 
					            return Ok(());
 | 
				
			||||||
@@ -422,6 +423,57 @@ impl Certs {
 | 
				
			|||||||
            false => Err(anyhow!("ssl ca execution failed")),
 | 
					            false => Err(anyhow!("ssl ca execution failed")),
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct Certs<T>
 | 
				
			||||||
 | 
					where
 | 
				
			||||||
 | 
					    T: ICryptoProvider,
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    encoding: String,
 | 
				
			||||||
 | 
					    ca_file: PathBuf,
 | 
				
			||||||
 | 
					    key_file: PathBuf,
 | 
				
			||||||
 | 
					    cert_file: PathBuf,
 | 
				
			||||||
 | 
					    config_file: PathBuf,
 | 
				
			||||||
 | 
					    template_file: PathBuf,
 | 
				
			||||||
 | 
					    provider: Arc<T>,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn make_certs_provider(cfg: &AppConfig, vars: BTreeMap<String, String>) -> impl ICryptoProvider {
 | 
				
			||||||
 | 
					    OpenSSLProvider::from_cfg(cfg, vars)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl<T> Certs<T>
 | 
				
			||||||
 | 
					where
 | 
				
			||||||
 | 
					    T: ICryptoProvider,
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    fn new(cfg: &AppConfig, provider: T) -> Self {
 | 
				
			||||||
 | 
					        let base_dir = PathBuf::from(&cfg.base_directory);
 | 
				
			||||||
 | 
					        let keys_dir = base_dir.clone().join(cfg.keys_subdir.clone());
 | 
				
			||||||
 | 
					        let config_dir = base_dir.clone().join(cfg.config_subdir.clone());
 | 
				
			||||||
 | 
					        let name = cfg.name.clone();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Certs {
 | 
				
			||||||
 | 
					            encoding: cfg.encoding.clone(),
 | 
				
			||||||
 | 
					            ca_file: keys_dir.join(cfg.ca_filename.clone()),
 | 
				
			||||||
 | 
					            key_file: keys_dir.join(format!("{}.key", &name)),
 | 
				
			||||||
 | 
					            cert_file: keys_dir.join(format!("{}.crt", &name)),
 | 
				
			||||||
 | 
					            config_file: config_dir.join(format!("{}.ovpn", &name)),
 | 
				
			||||||
 | 
					            template_file: base_dir.clone().join(cfg.template_file.clone()),
 | 
				
			||||||
 | 
					            provider: Arc::new(provider),
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    async fn is_config_exists(&self) -> bool {
 | 
				
			||||||
 | 
					        is_file_exist(&self.config_file).await
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    async fn request(&self) -> Result<()> {
 | 
				
			||||||
 | 
					        self.provider.request().await
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    async fn sign(&self) -> Result<()> {
 | 
				
			||||||
 | 
					        self.provider.sign().await
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async fn build_client_config(&self) -> Result<bool> {
 | 
					    async fn build_client_config(&self) -> Result<bool> {
 | 
				
			||||||
        if self.is_config_exists().await {
 | 
					        if self.is_config_exists().await {
 | 
				
			||||||
@@ -470,7 +522,8 @@ async fn main() -> Result<()> {
 | 
				
			|||||||
    println!("found vars: {}", vars.filepath.to_str().expect("fff"));
 | 
					    println!("found vars: {}", vars.filepath.to_str().expect("fff"));
 | 
				
			||||||
    println!("loaded: {:#?}", &vars.vars);
 | 
					    println!("loaded: {:#?}", &vars.vars);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let certs = Certs::new(&config, vars.vars.unwrap());
 | 
					    let provider = make_certs_provider(&config, vars.vars.unwrap());
 | 
				
			||||||
 | 
					    let certs = Certs::new(&config, provider);
 | 
				
			||||||
    let created = certs.build_client_config().await?;
 | 
					    let created = certs.build_client_config().await?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let result_file = certs.config_file.to_str().unwrap();
 | 
					    let result_file = certs.config_file.to_str().unwrap();
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user