openssl providers in separate files
This commit is contained in:
parent
f5e207654c
commit
cdac6d2aa5
@ -3,7 +3,8 @@ use anyhow::{anyhow, Context, Result};
|
|||||||
use std::{path::PathBuf, sync::Arc};
|
use std::{path::PathBuf, sync::Arc};
|
||||||
|
|
||||||
use crate::common::{is_file_exist, read_file, write_file, AppConfig, OpenSSLProviderArg, VarsMap};
|
use crate::common::{is_file_exist, read_file, write_file, AppConfig, OpenSSLProviderArg, VarsMap};
|
||||||
use crate::crypto::{ICryptoProvider, OpenSSLExternalProvider, OpenSSLInternalProvider};
|
use crate::crypto_provider::ICryptoProvider;
|
||||||
|
use crate::openssl::{external::OpenSSLExternalProvider, internal::OpenSSLInternalProvider};
|
||||||
|
|
||||||
pub(crate) struct Certs<T>
|
pub(crate) struct Certs<T>
|
||||||
where
|
where
|
||||||
|
6
src/crypto_provider.rs
Normal file
6
src/crypto_provider.rs
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
use anyhow::Result;
|
||||||
|
|
||||||
|
pub(crate) trait ICryptoProvider {
|
||||||
|
async fn request(&self) -> Result<()>;
|
||||||
|
async fn sign(&self) -> Result<()>;
|
||||||
|
}
|
@ -3,7 +3,8 @@ use clap::Parser;
|
|||||||
|
|
||||||
mod certs;
|
mod certs;
|
||||||
mod common;
|
mod common;
|
||||||
mod crypto;
|
mod crypto_provider;
|
||||||
|
mod openssl;
|
||||||
mod vars;
|
mod vars;
|
||||||
|
|
||||||
use crate::certs::build_client_config;
|
use crate::certs::build_client_config;
|
||||||
|
138
src/openssl/external.rs
Normal file
138
src/openssl/external.rs
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
use anyhow::{anyhow, Result};
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
use tokio::process::Command;
|
||||||
|
|
||||||
|
use crate::common::{is_file_exist, AppConfig, VarsMap};
|
||||||
|
use crate::crypto_provider::ICryptoProvider;
|
||||||
|
|
||||||
|
pub(crate) struct OpenSSLExternalProvider {
|
||||||
|
vars: VarsMap,
|
||||||
|
base_dir: PathBuf,
|
||||||
|
openssl_cnf: PathBuf,
|
||||||
|
openssl: String,
|
||||||
|
ca_file: PathBuf,
|
||||||
|
req_file: PathBuf,
|
||||||
|
key_file: PathBuf,
|
||||||
|
cert_file: PathBuf,
|
||||||
|
req_days: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OpenSSLExternalProvider {
|
||||||
|
async fn is_ca_exists(&self) -> bool {
|
||||||
|
is_file_exist(&self.ca_file).await
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn is_cert_exists(&self) -> bool {
|
||||||
|
is_file_exist(&self.cert_file).await
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn is_req_exists(&self) -> bool {
|
||||||
|
is_file_exist(&self.req_file).await
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn from_cfg(cfg: &AppConfig, vars: VarsMap) -> 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.to_string(),
|
||||||
|
ca_file,
|
||||||
|
req_file,
|
||||||
|
key_file,
|
||||||
|
cert_file,
|
||||||
|
req_days: cfg.req_days,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ICryptoProvider for OpenSSLExternalProvider {
|
||||||
|
async fn request(&self) -> Result<()> {
|
||||||
|
if self.is_req_exists().await {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
if !self.is_ca_exists().await {
|
||||||
|
return Err(anyhow!(
|
||||||
|
"ca file not found: {}",
|
||||||
|
&self.ca_file.to_str().unwrap()
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
let status = Command::new(&self.openssl)
|
||||||
|
.args([
|
||||||
|
"req",
|
||||||
|
"-nodes",
|
||||||
|
"-new",
|
||||||
|
"-keyout",
|
||||||
|
self.key_file.to_str().unwrap(),
|
||||||
|
"-out",
|
||||||
|
self.req_file.to_str().unwrap(),
|
||||||
|
"-config",
|
||||||
|
self.openssl_cnf.to_str().unwrap(),
|
||||||
|
"-batch",
|
||||||
|
])
|
||||||
|
.current_dir(&self.base_dir)
|
||||||
|
.envs(&self.vars)
|
||||||
|
.status()
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
match status.success() {
|
||||||
|
true => Ok(()),
|
||||||
|
false => Err(anyhow!("openssl req execution failed")),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn sign(&self) -> Result<()> {
|
||||||
|
if self.is_cert_exists().await {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
if !self.is_ca_exists().await {
|
||||||
|
return Err(anyhow!(
|
||||||
|
"ca file not found: {}",
|
||||||
|
&self.ca_file.to_str().unwrap()
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
let status = Command::new(&self.openssl)
|
||||||
|
.args([
|
||||||
|
"ca",
|
||||||
|
"-days",
|
||||||
|
format!("{}", self.req_days).as_str(),
|
||||||
|
"-out",
|
||||||
|
self.cert_file.to_str().unwrap(),
|
||||||
|
"-in",
|
||||||
|
self.req_file.to_str().unwrap(),
|
||||||
|
"-config",
|
||||||
|
self.openssl_cnf.to_str().unwrap(),
|
||||||
|
"-batch",
|
||||||
|
])
|
||||||
|
.current_dir(&self.base_dir)
|
||||||
|
.envs(&self.vars)
|
||||||
|
.status()
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
match status.success() {
|
||||||
|
true => Ok(()),
|
||||||
|
false => Err(anyhow!("ssl ca execution failed")),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -13,9 +13,12 @@ use openssl::{
|
|||||||
};
|
};
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
use tokio::{fs, process::Command};
|
use tokio::fs;
|
||||||
|
|
||||||
use crate::common::{is_file_exist, read_file, AppConfig, VarsMap};
|
use crate::{
|
||||||
|
common::{is_file_exist, read_file, AppConfig, VarsMap},
|
||||||
|
crypto_provider::ICryptoProvider,
|
||||||
|
};
|
||||||
|
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
@ -88,142 +91,6 @@ fn get_time_str_x509(days: u32) -> Result<String> {
|
|||||||
Ok(s)
|
Ok(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) trait ICryptoProvider {
|
|
||||||
async fn request(&self) -> Result<()>;
|
|
||||||
async fn sign(&self) -> Result<()>;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) struct OpenSSLExternalProvider {
|
|
||||||
vars: VarsMap,
|
|
||||||
base_dir: PathBuf,
|
|
||||||
openssl_cnf: PathBuf,
|
|
||||||
openssl: String,
|
|
||||||
ca_file: PathBuf,
|
|
||||||
req_file: PathBuf,
|
|
||||||
key_file: PathBuf,
|
|
||||||
cert_file: PathBuf,
|
|
||||||
req_days: u32,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl OpenSSLExternalProvider {
|
|
||||||
async fn is_ca_exists(&self) -> bool {
|
|
||||||
is_file_exist(&self.ca_file).await
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn is_cert_exists(&self) -> bool {
|
|
||||||
is_file_exist(&self.cert_file).await
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn is_req_exists(&self) -> bool {
|
|
||||||
is_file_exist(&self.req_file).await
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn from_cfg(cfg: &AppConfig, vars: VarsMap) -> 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.to_string(),
|
|
||||||
ca_file,
|
|
||||||
req_file,
|
|
||||||
key_file,
|
|
||||||
cert_file,
|
|
||||||
req_days: cfg.req_days,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ICryptoProvider for OpenSSLExternalProvider {
|
|
||||||
async fn request(&self) -> Result<()> {
|
|
||||||
if self.is_req_exists().await {
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
if !self.is_ca_exists().await {
|
|
||||||
return Err(anyhow!(
|
|
||||||
"ca file not found: {}",
|
|
||||||
&self.ca_file.to_str().unwrap()
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
let status = Command::new(&self.openssl)
|
|
||||||
.args([
|
|
||||||
"req",
|
|
||||||
"-nodes",
|
|
||||||
"-new",
|
|
||||||
"-keyout",
|
|
||||||
self.key_file.to_str().unwrap(),
|
|
||||||
"-out",
|
|
||||||
self.req_file.to_str().unwrap(),
|
|
||||||
"-config",
|
|
||||||
self.openssl_cnf.to_str().unwrap(),
|
|
||||||
"-batch",
|
|
||||||
])
|
|
||||||
.current_dir(&self.base_dir)
|
|
||||||
.envs(&self.vars)
|
|
||||||
.status()
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
match status.success() {
|
|
||||||
true => Ok(()),
|
|
||||||
false => Err(anyhow!("openssl req execution failed")),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn sign(&self) -> Result<()> {
|
|
||||||
if self.is_cert_exists().await {
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
if !self.is_ca_exists().await {
|
|
||||||
return Err(anyhow!(
|
|
||||||
"ca file not found: {}",
|
|
||||||
&self.ca_file.to_str().unwrap()
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
let status = Command::new(&self.openssl)
|
|
||||||
.args([
|
|
||||||
"ca",
|
|
||||||
"-days",
|
|
||||||
format!("{}", self.req_days).as_str(),
|
|
||||||
"-out",
|
|
||||||
self.cert_file.to_str().unwrap(),
|
|
||||||
"-in",
|
|
||||||
self.req_file.to_str().unwrap(),
|
|
||||||
"-config",
|
|
||||||
self.openssl_cnf.to_str().unwrap(),
|
|
||||||
"-batch",
|
|
||||||
])
|
|
||||||
.current_dir(&self.base_dir)
|
|
||||||
.envs(&self.vars)
|
|
||||||
.status()
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
match status.success() {
|
|
||||||
true => Ok(()),
|
|
||||||
false => Err(anyhow!("ssl ca execution failed")),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) struct OpenSSLInternalProvider {
|
pub(crate) struct OpenSSLInternalProvider {
|
||||||
vars: VarsMap,
|
vars: VarsMap,
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
2
src/openssl/mod.rs
Normal file
2
src/openssl/mod.rs
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
pub(crate) mod external;
|
||||||
|
pub(crate) mod internal;
|
Loading…
Reference in New Issue
Block a user