rusty_vault 0.2.1

RustyVault is a powerful identity-based secrets management software, providing features such as cryptographic key management, encryption as a service, public key cryptography, certificates management, identity credentials management and so forth. RustyVault's RESTful API is designed to be fully compatible with Hashicorp Vault.
Documentation
use std::{collections::HashMap, sync::Arc};

use serde_json::{json, Value};

use super::{field, util, PkiBackend, PkiBackendInner};
use crate::{
    context::Context,
    errors::RvError,
    logical::{Backend, Operation, Path, PathOperation, Request, Response},
    new_path, new_path_internal, utils,
};

impl PkiBackend {
    pub fn root_generate_path(&self) -> Path {
        let pki_backend_ref = Arc::clone(&self.inner);

        let mut path = new_path!({
            pattern: r"root/generate/(?P<exported>.+)",
            operations: [
                {op: Operation::Write, handler: pki_backend_ref.generate_root}
            ],
            help: "Generate a new CA certificate and private key used for signing."
        });

        path.fields.extend(field::ca_common_fields());
        path.fields.extend(field::ca_key_generation_fields());
        path.fields.extend(field::ca_issue_fields());

        path
    }

    pub fn root_delete_path(&self) -> Path {
        let pki_backend_ref = Arc::clone(&self.inner);

        let path = new_path!({
            pattern: r"root",
            operations: [
                {op: Operation::Delete, handler: pki_backend_ref.delete_root}
            ],
            help: "Deletes the root CA key to allow a new one to be generated."
        });

        path
    }
}

impl PkiBackendInner {
    pub fn generate_root(&self, _backend: &dyn Backend, req: &mut Request) -> Result<Option<Response>, RvError> {
        let mut export_private_key = false;
        if req.get_data_or_default("exported")?.as_str().ok_or(RvError::ErrRequestFieldInvalid)? == "exported" {
            export_private_key = true;
        }

        let role_entry = util::get_role_params(req)?;

        let mut cert = util::generate_certificate(&role_entry, req)?;

        cert.is_ca = true;

        let cert_bundle = cert.to_cert_bundle(None, None)?;

        self.store_ca_bundle(req, &cert_bundle)?;

        let cert_expiration = utils::asn1time_to_timestamp(cert_bundle.certificate.not_after().to_string().as_str())?;

        let mut resp_data = json!({
            "expiration": cert_expiration,
            "issuing_ca": String::from_utf8_lossy(&cert_bundle.certificate.to_pem()?),
            "certificate": String::from_utf8_lossy(&cert_bundle.certificate.to_pem()?),
            "serial_number": cert_bundle.serial_number.clone(),
        })
        .as_object()
        .unwrap()
        .clone();

        if export_private_key {
            resp_data.insert(
                "private_key".to_string(),
                Value::String(
                    String::from_utf8_lossy(&cert_bundle.private_key.private_key_to_pem_pkcs8()?).to_string(),
                ),
            );
            resp_data.insert("private_key_type".to_string(), Value::String(cert_bundle.private_key_type.clone()));
        }

        Ok(Some(Response::data_response(Some(resp_data))))
    }

    pub fn delete_root(&self, _backend: &dyn Backend, req: &mut Request) -> Result<Option<Response>, RvError> {
        self.delete_ca_bundle(req)?;
        Ok(None)
    }
}