product-os-server 0.0.55

Product OS : Server provides a full functioning advanced server capable of acting as a web server, command and control distributed network, authentication server, crawling server and more. Fully featured with high level of flexibility.
Documentation
//! Certificate configuration and setup module
//!
//! This module provides functionality to configure TLS certificates for the server.
//! It supports both self-signed certificates and certificates signed by a Certificate Authority (CA).
//!
//! # Certificate Types
//!
//! - **Self-Signed**: Automatically generated certificates for development or testing
//! - **CA-Signed**: Certificates signed by a trusted Certificate Authority for production use
//!
//! # Configuration
//!
//! Certificates can be configured through the `product_os_configuration::Certificate` struct,
//! which allows specifying:
//! - File paths for existing certificate and key files
//! - Subject entries (organization, common name, etc.)
//! - Subject alternative names
//! - Serial number and validity period

use alloc::{
    string::String,
    vec,
    borrow::ToOwned
};
use crate::config::{Certificate, CertificateFilesKind};
use product_os_security::certificates::Certificates;
use serde_json::Value;

pub struct ProductOSServerCertificates {}

impl ProductOSServerCertificates {
    pub fn setup_certificates(certificate_config: &Option<Certificate>) -> Certificates {
        match &certificate_config {
            None => {
                #[cfg(feature = "core")]
                tracing::info!("Generating self-signed certificate");
                Certificates::new_self_signed(
                    vec![],
                    Some(vec![
                        String::from("localhost"),
                        String::from("127.0.0.1"),
                    ]),
                    None,
                    None,
                    None,
                    None,
                )
            },
            Some(cert_config) => {
                let file_kind = match &cert_config.file_kind {
                    None => &CertificateFilesKind::SelfSigned,
                    Some(file_kind) => file_kind,
                };

                let entries = {
                    let mut entries = vec![];
                    match &cert_config.entries {
                        None => {},
                        Some(config_entries) => {
                            for entry in config_entries {
                                for (key, value) in entry {
                                    if let Value::String(val) = value { entries.push((key.to_owned(), val.to_owned())) }
                                }
                            }
                        }
                    }
                    entries
                };

                let names = cert_config.names.as_ref().map(|config_names| config_names.to_owned());

                let serial = cert_config.serial.as_ref().map(|serial| serial.to_owned());

                let valid_for = cert_config.valid_for.as_ref().map(|valid_for| valid_for.to_owned());

                match file_kind {
                    CertificateFilesKind::SelfSigned => {
                        match &cert_config.files {
                            Some(files) => {
                                #[cfg(feature = "core")]
                                tracing::info!("Using configuration file for certificate");
                                Certificates::new_self_signed_from_file(files.cert_file.to_owned(), files.key_file.to_owned(), None)
                            }
                            None => {
                                #[cfg(feature = "core")]
                                tracing::info!("Generating self-signed certificate with attributes");
                                Certificates::new_self_signed(entries, names, None, serial, valid_for, None)
                            }
                        }
                    }
                    CertificateFilesKind::CA => {
                        match &cert_config.files {
                            Some(files) => {
                                #[cfg(feature = "core")]
                                tracing::info!("Using configuration file for certificate signed by CA");
                                Certificates::new_signed_by_ca_from_file(files.cert_file.to_owned(), files.key_file.to_owned(), entries, names, None, serial, valid_for, None)
                            }
                            None => {
                                // If CA is specified but no files provided, fall back to self-signed
                                #[cfg(feature = "core")]
                                tracing::warn!("CA certificate files not provided, falling back to self-signed certificate");
                                Certificates::new_self_signed(entries, names, None, serial, valid_for, None)
                            }
                        }
                    }
                }
            }
        }
    }
}