Compare commits

..

No commits in common. "c7677bdb704ffd5430c3bfdd14208cfcfb70549c" and "8c1add6ff114d8ad50b3a1d413d48186116e9026" have entirely different histories.

2 changed files with 63 additions and 101 deletions

View File

@ -3,7 +3,7 @@ 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::{ICryptoProvider, OpenSSLBinProvider, OpenSSLLibProvider};
pub(crate) struct Certs<T>
where
@ -93,14 +93,14 @@ pub async fn build_client_config(config: &AppConfig, vars: VarsMap) -> Result<()
let created: bool;
if let OpenSSLProviderArg::ExternalBin(_) = config.openssl {
let certs = Certs::new(config, OpenSSLExternalProvider::from_cfg(config, vars));
let certs = Certs::new(config, OpenSSLBinProvider::from_cfg(config, vars));
created = certs
.build_client_config()
.await
.context("external openssl error")?;
result_file = certs.config_file;
} else {
let certs = Certs::new(config, OpenSSLInternalProvider::from_cfg(config, vars));
let certs = Certs::new(config, OpenSSLLibProvider::from_cfg(config, vars));
created = certs
.build_client_config()
.await

View File

@ -8,10 +8,10 @@ use openssl::{
stack::Stack,
x509::{
extension::{ExtendedKeyUsage, KeyUsage, SubjectAlternativeName},
X509Extension, X509Name, X509NameBuilder, X509Req, X509ReqBuilder, X509,
X509Name, X509NameBuilder, X509Req, X509ReqBuilder, X509,
},
};
use std::path::{Path, PathBuf};
use std::path::PathBuf;
use tokio::{fs, process::Command};
@ -35,42 +35,6 @@ lazy_static! {
};
}
trait ToPemX {
fn to_pem_x(&self) -> Result<Vec<u8>>;
}
impl ToPemX for X509 {
fn to_pem_x(&self) -> Result<Vec<u8>> {
Ok(self.to_pem()?)
}
}
impl ToPemX for X509Req {
fn to_pem_x(&self) -> Result<Vec<u8>> {
Ok(self.to_pem()?)
}
}
impl ToPemX for PKey<Private> {
fn to_pem_x(&self) -> Result<Vec<u8>> {
Ok(self.private_key_to_pem_pkcs8()?)
}
}
struct Pem<'a, T: ToPemX>(&'a T);
trait WritePem {
async fn write<T: AsRef<Path>>(&self, path: T) -> Result<()>;
}
impl<'a, P: ToPemX> WritePem for Pem<'a, P> {
async fn write<T: AsRef<Path>>(&self, path: T) -> Result<()> {
let pem = self.0.to_pem_x().context("to_pem()")?;
fs::write(path, pem).await.context("write pem")?;
Ok(())
}
}
fn get_time_str_x509(days: u32) -> Result<String> {
let dt = Utc::now();
let dt = dt
@ -93,7 +57,7 @@ pub(crate) trait ICryptoProvider {
async fn sign(&self) -> Result<()>;
}
pub(crate) struct OpenSSLExternalProvider {
pub(crate) struct OpenSSLBinProvider {
vars: VarsMap,
base_dir: PathBuf,
openssl_cnf: PathBuf,
@ -105,7 +69,7 @@ pub(crate) struct OpenSSLExternalProvider {
req_days: u32,
}
impl OpenSSLExternalProvider {
impl OpenSSLBinProvider {
async fn is_ca_exists(&self) -> bool {
is_file_exist(&self.ca_file).await
}
@ -150,7 +114,7 @@ impl OpenSSLExternalProvider {
}
}
impl ICryptoProvider for OpenSSLExternalProvider {
impl ICryptoProvider for OpenSSLBinProvider {
async fn request(&self) -> Result<()> {
if self.is_req_exists().await {
return Ok(());
@ -224,7 +188,7 @@ impl ICryptoProvider for OpenSSLExternalProvider {
}
}
pub(crate) struct OpenSSLInternalProvider {
pub(crate) struct OpenSSLLibProvider {
vars: VarsMap,
#[allow(unused)]
base_dir: PathBuf,
@ -240,7 +204,7 @@ pub(crate) struct OpenSSLInternalProvider {
encoding: String,
}
impl OpenSSLInternalProvider {
impl OpenSSLLibProvider {
async fn is_ca_exists(&self) -> bool {
is_file_exist(&self.ca_file).await
}
@ -304,9 +268,9 @@ impl OpenSSLInternalProvider {
Ok(X509::from_pem(text.as_bytes())?)
}
async fn get_ca_key(&self) -> Result<PKey<Private>> {
async fn get_ca_key(&self) -> Result<Rsa<Private>> {
let text = read_file(self.ca_key_file.clone(), &self.encoding).await?;
Ok(PKey::from_rsa(Rsa::private_key_from_pem(text.as_bytes())?)?)
Ok(Rsa::private_key_from_pem(text.as_bytes())?)
}
async fn get_key(&self) -> Result<(Rsa<Private>, PKey<Private>)> {
@ -326,10 +290,8 @@ impl OpenSSLInternalProvider {
self.get_key().await
} else {
let (rsa, pkey) = self.generate_key_pair()?;
Pem(&pkey)
.write(&self.key_file)
.await
.context("key write pem")?;
let key_data = pkey.private_key_to_pem_pkcs8()?;
tokio::fs::write(self.key_file.as_path(), key_data).await?;
Ok((rsa, pkey))
}
}
@ -346,42 +308,9 @@ impl OpenSSLInternalProvider {
}
Ok(name_builder.build())
}
fn gen_x509_extensions(
context: &openssl::x509::X509v3Context,
vars: &VarsMap,
) -> Result<Vec<X509Extension>> {
let key_usage = KeyUsage::new()
.key_agreement()
.digital_signature()
.build()?;
let key_extended_ext = ExtendedKeyUsage::new().client_auth().build()?;
let mut san_extension = SubjectAlternativeName::new();
if let Some(name) = vars.get("KEY_NAME") {
san_extension.dns(name);
}
if let Some(email) = vars.get("KEY_EMAIL") {
san_extension.email(email);
}
let san_ext = san_extension.build(context).context("build san")?;
Ok(vec![san_ext, key_usage, key_extended_ext])
}
fn gen_x509_extensions_stack(
context: &openssl::x509::X509v3Context,
vars: &VarsMap,
) -> Result<Stack<X509Extension>> {
let mut stack = Stack::new()?;
for extension in Self::gen_x509_extensions(context, vars)?.into_iter() {
stack.push(extension).context("push ext")?;
}
Ok(stack)
}
}
impl ICryptoProvider for OpenSSLInternalProvider {
impl ICryptoProvider for OpenSSLLibProvider {
async fn request(&self) -> Result<()> {
if self.is_req_exists().await {
return Ok(());
@ -397,25 +326,37 @@ impl ICryptoProvider for OpenSSLInternalProvider {
let (_, pkey) = self.ensure_key().await?;
let name = self.build_x509_name()?;
let key_usage = KeyUsage::new()
.key_agreement()
.digital_signature()
.build()?;
let key_extended_ext = ExtendedKeyUsage::new().client_auth().build()?;
let mut st = Stack::new()?;
st.push(key_usage).context("push key usage")?;
st.push(key_extended_ext).context("push key_extended_ext")?;
let conf = Conf::new(ConfMethod::default()).context("conf new")?;
// Create certificate signing request (CSR)
let mut csr_builder = X509ReqBuilder::new()?;
csr_builder.set_version(2).context("set version")?;
csr_builder.set_pubkey(&pkey).context("set pubkey")?;
csr_builder.set_version(2).context("set version")?;
let context = csr_builder.x509v3_context(Some(&conf));
let mut san_extension = SubjectAlternativeName::new();
san_extension.dns(self.vars.get("KEY_NAME").unwrap());
let san_ext = san_extension.build(&context).context("build san")?;
st.push(san_ext).context("push san")?;
csr_builder
.set_subject_name(&name)
.context("set subject name")?;
let context = csr_builder.x509v3_context(Some(&conf));
let extensions = Self::gen_x509_extensions_stack(&context, &self.vars)?;
csr_builder.add_extensions(&extensions)?;
csr_builder.add_extensions(&st)?;
csr_builder.sign(&pkey, MessageDigest::sha512())?;
let csr = csr_builder.build();
let pem = csr.to_pem()?;
fs::write(self.req_file.as_path(), pem).await?;
Pem(&csr)
.write(&self.req_file)
.await
.context("req write pem")?;
Ok(())
}
@ -440,11 +381,22 @@ impl ICryptoProvider for OpenSSLInternalProvider {
let ca_key = self.get_ca_key().await?;
let ca_cert = self.get_ca_cert().await?;
let ca_pkey = PKey::from_rsa(ca_key.clone())?;
let req = self.get_req().await?;
let pub_key = req.public_key()?;
let subject_name = req.subject_name();
let key_usage = KeyUsage::new()
.key_agreement()
.digital_signature()
.build()
.context("new key_usage")?;
let key_extended_ext = ExtendedKeyUsage::new()
.client_auth()
.build()
.context("new key_extended_ext")?;
let mut builder = openssl::x509::X509Builder::new().context("new builder")?;
let not_before = Asn1Time::days_from_now(0).context("days_from_now 0")?;
let na_s = get_time_str_x509(self.req_days).context("na_s get_time_str_x509")?;
@ -464,19 +416,29 @@ impl ICryptoProvider for OpenSSLInternalProvider {
.context("set_subject_name")?;
let context = builder.x509v3_context(Some(&ca_cert), None);
for extension in Self::gen_x509_extensions(&context, &self.vars)? {
builder.append_extension(extension).context("append ext")?;
}
let mut san_extension = SubjectAlternativeName::new();
san_extension.dns(self.vars.get("KEY_NAME").unwrap());
let san_ext = san_extension.build(&context).context("build san")?;
builder
.append_extension(san_ext)
.context("append san ext")?;
builder
.append_extension(key_usage)
.context("append key_usage ext")?;
builder
.append_extension(key_extended_ext)
.context("append key_extended_ext ext")?;
builder
.sign(&ca_key, MessageDigest::sha512())
.sign(&ca_pkey, MessageDigest::sha512())
.context("builder.sign")?;
let cert = builder.build();
Pem(&cert)
.write(&self.cert_file)
let pem = cert.to_pem().context("cert.to_pem()")?;
fs::write(self.cert_file.as_path(), pem)
.await
.context("cert.to_pem()")?;
.context("fs::write")?;
Ok(())
}
}