config.rs
Overview
The config.rs file provides abstractions and utilities for managing TLS certificates and private keys within the system. It defines structures for loading, storing, serializing, and deserializing certificates and private keys from filesystem paths. It also supports the resolution of certificates and keys for TLS usage, including integration with a certificate cache or on-demand self-signed certificate generation. This file encapsulates certificate and key handling logic, ensuring safe and traceable loading and reuse of cryptographic materials.
Main Entities and Their Functionalities
CertFile
Represents a TLS certificate loaded from a file path.
Fields:
path: PathBuf— The filesystem path to the certificate file.cert: Option<CertificateDer<'static>>— The loaded certificate in DER format, optional if loading failed or path is empty.
Key Methods:
try_new(path: impl AsRef<Path>) -> anyhow::Result<Self>Loads a certificate from the specified path. If the path is empty or invalid, returns a
CertFilewith no certificate.Parameters:
path— File path to the certificate PEM file.
Returns:
Ok(CertFile)on success.Errif loading the certificate fails, with logged error information.
Usage Example:
let cert_file = CertFile::try_new("path/to/cert.pem")?;resolve(&self, key: &PrivateKeyFile, ed_keys: &[transport_layer::SigningKey], tls_cert_cache: Option<TlsCertCache>) -> anyhow::Result<(Vec<CertificateDer<'static>>, PrivateKeyDer<'static>)>Resolves the certificate and private key pair for TLS usage. It attempts to use the loaded certificate and key if available; otherwise, it tries to reuse a cached certificate or generates a new self-signed certificate with optional Ed25519 signatures.
Parameters:
key— PrivateKeyFile containing the private key.ed_keys— A slice of signing keys for Ed25519 signatures.tls_cert_cache— Optional cache to reuse existing TLS certificates.
Returns:
Tuple of
(Vec<CertificateDer<'static>>, PrivateKeyDer<'static>)representing the certificate chain and private key.
Usage Example:
let (cert_chain, private_key) = cert_file.resolve(&private_key_file, &ed_keys, tls_cert_cache)?;try_load_certs(paths: &[PathBuf]) -> anyhow::Result<Vec<Self>>Loads multiple certificates from a list of paths. If a path is a directory, it loads all
.ca.pemfiles within it.Parameters:
paths— Slice of filesystem paths (files or directories).
Returns:
Vector of loaded
CertFileinstances.
Usage Example:
let cert_files = CertFile::try_load_certs(&vec![PathBuf::from("certs/")])?;
CertStore
Represents a collection of trusted CA certificates loaded from specified paths.
Fields:
paths: Vec<PathBuf>— List of paths from which certificates were loaded.certs: Vec<CertificateDer<'static>>— Loaded certificates in DER format.
Key Methods:
try_new(paths: &[PathBuf]) -> anyhow::Result<Self>Creates a new
CertStoreby loading all certificates from the given paths, supporting directory traversal for.ca.pemfiles.Parameters:
paths— Slice of filesystem paths for certificates.
Returns:
Ok(CertStore)on successful loading.Erron failures during file system operations.
Usage Example:
let store = CertStore::try_new(&vec![PathBuf::from("trusted_certs/")])?;cert_hashes(&self) -> HashSet<CertHash>Returns a set of certificate hashes for all loaded certificates, useful for quick lookup or comparison.
Returns:
HashSet<CertHash>containing hashes of all certificates.
PrivateKeyFile
Represents a private key loaded from a file.
Fields:
path: PathBuf— Filesystem path to the private key PEM file.key: Option<PrivateKeyDer<'static>>— The loaded private key in DER format, optional if loading failed or path empty.
Key Methods:
try_new(path: impl AsRef<Path>) -> anyhow::Result<Self>Loads a private key from the specified path.
Parameters:
path— Path to the private key PEM file.
Returns:
Ok(PrivateKeyFile)on success.Errif loading fails.
Usage Example:
let key_file = PrivateKeyFile::try_new("path/to/key.pem")?;
Trait Implementations:
Implements
Cloneto deep clone the key by cloning the contained DER key.
Serialization and Deserialization
Both
CertFileandCertStoreimplementserde::Serializeandserde::Deserializeto enable serialization based on their file paths rather than the full certificate content. Deserialization attempts to load certificates or keys from the deserialized paths, returning errors if loading fails.PrivateKeyFilealso implements serialization/deserialization similarly based on the private key file path.
This design allows configuration files or other serialized forms to store just paths, deferring actual certificate/key loading to runtime.
Implementation Details and Algorithms
Certificate Loading: Uses
CertificateDer::from_pem_fileto load PEM-encoded certificates from disk, converting them to DER format internally for compatibility withrustlsand TLS operations.Private Key Loading: Uses
PrivateKeyDer::from_pem_fileto read PEM-encoded private keys, converted to DER format.Empty Path Handling: The helper function
is_empty_pathdetermines whether a given path is empty or whitespace-only, preventing attempts to load from invalid paths.Certificate Resolution: The
CertFile::resolvemethod implements a multi-step resolution:Use loaded certificate and private key if both present.
Otherwise, try to get a cached certificate and key from
TlsCertCache.If no cached certificate available, generate a new self-signed certificate (optionally signed with Ed25519 keys).
This approach optimizes reuse of existing TLS credentials while supporting fallback generation.
Directory Traversal: Both
CertFile::try_load_certsandCertStore::try_newsupport loading certificates from directories by iterating over directory entries and selecting files ending with.ca.pem.Tracing: Uses the
tracingcrate for structured logging of certificate load successes, failures, and resolution events. This aids observability during runtime.
Interactions with Other System Components
TLS Certificate Cache (
TlsCertCache): Optionally used byCertFile::resolveto retrieve or store certificates to avoid regeneration.Transport Layer (
transport_layercrate): Provides functions likegenerate_self_signed_certfor certificate creation, and types such asCertHashandSigningKey.rustls::pki_types: Provides types for certificates and private keys in DER format (CertificateDer,PrivateKeyDer), and PEM handling (PemObject).Serialization via
serde: Enables integration with external configuration or persistence mechanisms.
The file acts as a bridge between filesystem-based PEM certificate/key files and the internal TLS configuration of the application, facilitating secure communication.
Constants
DEBUG_CERTIFICATEandDEBUG_PRIVATE_KEY: Include byte slices of embedded debug TLS certificate and key files, located under../../certs/debug.ca.pemand../../certs/debug.key.pemrespectively. These can be used for testing or development purposes.
Testing
The internal tests verify that
CertFileandPrivateKeyFilewrappers correctly load paths and associate them with the expected filesystem paths.
Mermaid Diagram
classDiagram
class CertFile {
+path: PathBuf
-cert: Option<CertificateDer>
+try_new()
+resolve()
+try_load_certs()
}
class CertStore {
+paths: Vec<PathBuf>
+certs: Vec<CertificateDer>
+try_new()
+cert_hashes()
}
class PrivateKeyFile {
+path: PathBuf
+key: Option<PrivateKeyDer>
+try_new()
+clone()
}
CertFile --> CertificateDer : contains
PrivateKeyFile --> PrivateKeyDer : contains
CertStore --> CertificateDer : aggregates
CertFile ..> PrivateKeyFile : uses in resolve()
CertFile ..> TlsCertCache : optional dependency
CertFile ..> transport_layer.SigningKey : uses for Ed25519 keys