Update rcgen dependency + cargo update.

This commit is contained in:
Orne Brocaar 2024-04-10 11:52:23 +01:00
parent 9207effb5b
commit 378b314a32
5 changed files with 229 additions and 241 deletions

379
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -15,8 +15,5 @@ lto = true
codegen-units = 1
[patch.crates-io]
# Remove if diesel > 2.1.4
diesel = { git = "https://github.com/diesel-rs/diesel.git", rev = "566dcccc6df6adb6ceddef8df5e1806e2a065c40" }
# Remove if diesel-async > 0.4.1
diesel-async = { git = "https://github.com/weiznich/diesel_async.git", rev = "017ebe2fb7a2709ab5db92148dea5ce812a35e09" }

View File

@ -8,7 +8,7 @@ dist:
# Install dev dependencies
dev-dependencies:
cargo install cross --version 0.2.5
cargo install diesel_cli --version 2.1.0 --no-default-features --features postgres
cargo install diesel_cli --version 2.1.1 --no-default-features --features postgres
cargo install cargo-deb --version 1.43.1
cargo install cargo-generate-rpm --version 0.12.1

View File

@ -104,10 +104,12 @@ jsonwebtoken = "9.2"
rustls = "0.22"
rustls-native-certs = "0.7"
rustls-pemfile = "2.1"
pem = "3.0"
x509-parser = "0.16"
rsa = "0.9"
elliptic-curve = { version = "0.13", features = ["pem"] }
p256 = "0.13"
rcgen = { version = "0.12", features = [ "x509-parser" ] }
rcgen = { version = "0.13.1", features = [ "x509-parser" ] }
openidconnect = { version = "3.5", features = ["accept-rfc3339-timestamps"] }
oauth2 = "4.4"

View File

@ -3,6 +3,7 @@ use std::time::SystemTime;
use anyhow::{Context, Result};
use rcgen::{
Certificate, CertificateParams, DnType, ExtendedKeyUsagePurpose, KeyPair, KeyUsagePurpose,
SignatureAlgorithm,
};
use tokio::fs;
use uuid::Uuid;
@ -11,8 +12,14 @@ use crate::config;
use crate::helpers::tls::private_key_to_pkcs8;
use lrwn::EUI64;
fn gen_client_cert(id: &str, not_before: SystemTime, not_after: SystemTime) -> Result<Certificate> {
let mut params = CertificateParams::new(vec![id.to_string()]);
fn gen_client_cert(
id: &str,
not_before: SystemTime,
not_after: SystemTime,
issuer: &Certificate,
issuer_key: &KeyPair,
) -> Result<(Certificate, KeyPair)> {
let mut params = CertificateParams::new(vec![id.to_string()])?;
params
.distinguished_name
.push(DnType::CommonName, id.to_string());
@ -24,10 +31,11 @@ fn gen_client_cert(id: &str, not_before: SystemTime, not_after: SystemTime) -> R
.extended_key_usages
.push(ExtendedKeyUsagePurpose::ClientAuth);
Ok(Certificate::from_params(params)?)
let kp = KeyPair::generate()?;
Ok((params.signed_by(&kp, issuer, issuer_key)?, kp))
}
async fn get_ca_cert(ca_cert_file: &str, ca_key_file: &str) -> Result<Certificate> {
async fn get_ca_cert(ca_cert_file: &str, ca_key_file: &str) -> Result<(Certificate, KeyPair)> {
let ca_cert_s = fs::read_to_string(ca_cert_file)
.await
.context("Read gateway ca_cert")?;
@ -35,19 +43,14 @@ async fn get_ca_cert(ca_cert_file: &str, ca_key_file: &str) -> Result<Certificat
.await
.context("Read gateway ca_key")?;
let ca_key_s = private_key_to_pkcs8(&ca_key_s)?;
let ca_key_algo = read_algo(&ca_cert_s)?;
let ca_key = KeyPair::from_pem(&ca_key_s).context("Parse gateway CA key")?;
let params = CertificateParams::from_ca_cert_pem(&ca_cert_s, ca_key)
.context("Parse gateway CA certificate")?;
// Workaround for:
// https://github.com/rustls/rcgen/issues/193
let ca_key =
KeyPair::from_pem_and_sign_algo(&ca_key_s, params.alg).context("Parse gateway CA key")?;
let params = CertificateParams::from_ca_cert_pem(&ca_cert_s, ca_key)
.context("Parse gateway CA certificate")?;
KeyPair::from_pem_and_sign_algo(&ca_key_s, ca_key_algo).context("Parse gateway CA key")?;
let params =
CertificateParams::from_ca_cert_pem(&ca_cert_s).context("Parse gateway CA certificate")?;
Certificate::from_params(params).context("Init Certificate struct")
Ok((params.self_signed(&ca_key)?, ca_key))
}
// This returns the CA, certificate and private-key as PEM encoded strings.
@ -55,21 +58,25 @@ pub async fn client_cert_for_gateway_id(
gateway_id: &EUI64,
) -> Result<(SystemTime, String, String, String)> {
let conf = config::get();
let ca_cert = get_ca_cert(&conf.gateway.ca_cert, &conf.gateway.ca_key)
let (ca_cert, ca_key) = get_ca_cert(&conf.gateway.ca_cert, &conf.gateway.ca_key)
.await
.context("Get CA cert")?;
let not_before = SystemTime::now();
let not_after = SystemTime::now() + conf.gateway.client_cert_lifetime;
let gw_cert = gen_client_cert(&gateway_id.to_string(), not_before, not_after)
.context("Generate client certificate")?;
let (gw_cert, gw_key) = gen_client_cert(
&gateway_id.to_string(),
not_before,
not_after,
&ca_cert,
&ca_key,
)
.context("Generate client certificate")?;
Ok((
not_after,
ca_cert.serialize_pem().context("Serialize CA cert")?,
gw_cert
.serialize_pem_with_signer(&ca_cert)
.context("Serialize client cert")?,
gw_cert.serialize_private_key_pem(),
ca_cert.pem(),
gw_cert.pem(),
gw_key.serialize_pem(),
))
}
@ -77,19 +84,40 @@ pub async fn client_cert_for_application_id(
application_id: &Uuid,
) -> Result<(SystemTime, String, String, String)> {
let conf = config::get();
let ca_cert = get_ca_cert(
let (ca_cert, ca_key) = get_ca_cert(
&conf.integration.mqtt.client.ca_cert,
&conf.integration.mqtt.client.ca_key,
)
.await?;
let not_before = SystemTime::now();
let not_after = SystemTime::now() + conf.integration.mqtt.client.client_cert_lifetime;
let app_cert = gen_client_cert(&application_id.to_string(), not_before, not_after)?;
let (app_cert, app_key) = gen_client_cert(
&application_id.to_string(),
not_before,
not_after,
&ca_cert,
&ca_key,
)?;
Ok((
not_after,
ca_cert.serialize_pem()?,
app_cert.serialize_pem_with_signer(&ca_cert)?,
app_cert.serialize_private_key_pem(),
ca_cert.pem(),
app_cert.pem(),
app_key.serialize_pem(),
))
}
// we are using String here, because else we run into lifetime issues.
fn read_algo(cert: &str) -> Result<&'static SignatureAlgorithm> {
let cert = pem::parse(cert).context("Parse PEM")?;
let (_remainder, x509) =
x509_parser::parse_x509_certificate(cert.contents()).context("Parse x509")?;
let alg_oid = x509
.signature_algorithm
.algorithm
.iter()
.ok_or_else(|| anyhow!("Parse certificate error"))?
.collect::<Vec<_>>();
Ok(SignatureAlgorithm::from_oid(&alg_oid)?)
}