openssl providers in separate files
All checks were successful
Docker Image CI / test (push) Successful in 2m34s
Docker Image CI / push (push) Successful in 14m47s

This commit is contained in:
Dmitry Belyaev 2024-10-22 16:23:53 +03:00
parent f5e207654c
commit cdac6d2aa5
Signed by: b4tman
GPG Key ID: 41A00BF15EA7E5F3
6 changed files with 155 additions and 140 deletions

View File

@ -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
View File

@ -0,0 +1,6 @@
use anyhow::Result;
pub(crate) trait ICryptoProvider {
async fn request(&self) -> Result<()>;
async fn sign(&self) -> Result<()>;
}

View File

@ -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
View 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")),
}
}
}

View File

@ -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
View File

@ -0,0 +1,2 @@
pub(crate) mod external;
pub(crate) mod internal;