Compare commits
3 Commits
c7677bdb70
...
cdac6d2aa5
Author | SHA1 | Date | |
---|---|---|---|
cdac6d2aa5 | |||
f5e207654c | |||
232ad335fa |
12
Cargo.lock
generated
12
Cargo.lock
generated
@ -153,9 +153,9 @@ checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
|
||||
|
||||
[[package]]
|
||||
name = "bytes"
|
||||
version = "1.7.2"
|
||||
version = "1.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3"
|
||||
checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
@ -690,9 +690,9 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.79"
|
||||
version = "2.0.82"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590"
|
||||
checksum = "83540f837a8afc019423a8edb95b52a8effe46957ee402287f4292fae35be021"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@ -701,9 +701,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.40.0"
|
||||
version = "1.41.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998"
|
||||
checksum = "145f3413504347a2be84393cc8a7d2fb4d863b375909ea59f2158261aa258bbb"
|
||||
dependencies = [
|
||||
"backtrace",
|
||||
"bytes",
|
||||
|
@ -15,7 +15,7 @@ futures-util = "0.3.31"
|
||||
lazy_static = "1.5.0"
|
||||
openssl = { version="0.10.68" }
|
||||
regex = "1.11.0"
|
||||
tokio = { version = "1.40.0", features = ["fs", "rt", "process", "macros", "io-util"] }
|
||||
tokio = { version = "1.41.0", features = ["fs", "rt", "process", "macros", "io-util"] }
|
||||
|
||||
[profile.release]
|
||||
opt-level = 3
|
||||
|
@ -1,5 +1,6 @@
|
||||
FROM lukemathwalker/cargo-chef:latest-rust-1 AS chef
|
||||
WORKDIR /app
|
||||
RUN apt --no-install-recommends update && apt install -y libssl-dev
|
||||
|
||||
FROM chef AS planner
|
||||
COPY . .
|
||||
|
@ -3,7 +3,8 @@ use anyhow::{anyhow, Context, Result};
|
||||
use std::{path::PathBuf, sync::Arc};
|
||||
|
||||
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>
|
||||
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 common;
|
||||
mod crypto;
|
||||
mod crypto_provider;
|
||||
mod openssl;
|
||||
mod vars;
|
||||
|
||||
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 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 std::collections::HashMap;
|
||||
@ -88,142 +91,6 @@ fn get_time_str_x509(days: u32) -> Result<String> {
|
||||
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 {
|
||||
vars: VarsMap,
|
||||
#[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