Skip to main content

CertificateManager

Struct CertificateManager 

Source
pub struct CertificateManager {
    app_id: String,
    ca_cert: Option<Vec<u8>>,
    ca_key: Option<Vec<u8>>,
    server_certs: Arc<RwLock<HashMap<String, ServerCertData>>>,
}
Expand description

Main certificate manager for TLS infrastructure

Manages a root CA certificate and generates server certificates as needed. The CA certificate is persisted in the OS keyring for security.

Fields§

§app_id: String

Application identifier for keyring storage

§ca_cert: Option<Vec<u8>>

CA certificate PEM (cached from keyring)

§ca_key: Option<Vec<u8>>

CA private key PEM (cached from keyring)

§server_certs: Arc<RwLock<HashMap<String, ServerCertData>>>

Cached server certificates (hostname -> cert data)

Implementations§

Source§

impl CertificateManager

Source

const KEYRING_SERVICE: &'static str = "CodeEditorLand-TLS"

Keyring service name for certificate storage

Source

const KEYRING_CA_CERT: &'static str = "ca_certificate"

Keyring entry name for CA certificate

Source

const KEYRING_CA_KEY: &'static str = "ca_private_key"

Keyring entry name for CA private key

Source

const CA_VALIDITY_DAYS: i64

Certificate validity period for CA (10 years)

Source

const SERVER_VALIDITY_DAYS: i64 = 365

Certificate validity period for server certs (1 year)

Source

pub const RENEWAL_THRESHOLD_DAYS: i64 = 30

Renewal threshold (renew if expiring within 30 days)

Source

pub async fn new(app_id: &str) -> Result<Self>

Create a new CertificateManager instance

§Arguments
  • app_id - Application identifier for keyring storage
§Example
let cert_manager = CertificateManager::new("myapp").await?;
Source

pub async fn initialize_ca(&mut self) -> Result<()>

Initialize or load the CA certificate

This method attempts to load the CA certificate from the keyring. If not found, it generates a new self-signed CA and stores it.

§Example
let mut cert_manager = CertificateManager::new("myapp").await?;
cert_manager.initialize_ca().await?;
Source

fn generate_ca_cert(&self) -> Result<(Vec<u8>, Vec<u8>)>

Generate a new self-signed CA certificate

Returns (certificate PEM, private key PEM) tuple.

The CA certificate:

  • Uses ECDSA P-256 curve for consistency with DNSSEC
  • Has CA:TRUE basic constraint
  • Allows keyCertSign and CRLSign key usage
  • Valid for 10 years
  • Includes proper extensions for CA functionality
Source

pub async fn get_server_cert(&self, hostname: &str) -> Result<Arc<ServerConfig>>

Get or generate a server certificate for a specific hostname

§Arguments
  • hostname - The hostname (e.g., “code.editor.land”)
§Returns

A rustls ServerConfig ready for HTTPS serving

§Example
let mut cert_manager = CertificateManager::new("myapp").await?;
cert_manager.initialize_ca().await?;
let server_config = cert_manager.get_server_cert("code.editor.land").await?;
Source

fn generate_server_cert(&self, hostname: &str) -> Result<ServerCertData>

Generate a server certificate signed by the CA

The certificate includes:

  • Specified hostname as Common Name
  • Subject Alternative Names: DNS hostname, 127.0.0.1, ::1
  • Valid for 1 year with automatic renewal
  • Server authentication EKUs
Source

fn load_ca_from_keyring(&self) -> Result<Option<(Vec<u8>, Vec<u8>)>>

Load CA certificate and key from keyring

Returns Some((cert_pem, key_pem)) if found, None otherwise.

Source

fn save_ca_to_keyring(&self, cert: &[u8], key: &[u8]) -> Result<()>

Save CA certificate and key to keyring

Source

pub fn should_renew(&self, cert_pem: &[u8]) -> bool

Check if a certificate should be renewed

Returns true if the certificate is expiring within RENEWAL_THRESHOLD_DAYS.

Source

pub async fn renew_certificate(&mut self, hostname: &str) -> Result<()>

Force renewal of a server certificate

§Arguments
  • hostname - The hostname whose certificate should be renewed
§Example
let mut cert_manager = CertificateManager::new("myapp").await?;
cert_manager.initialize_ca().await?;
cert_manager.renew_certificate("code.editor.land").await?;
Source

pub async fn build_server_config( &self, hostname: &str, ) -> Result<Arc<ServerConfig>>

Build a ServerConfig for a specific hostname

This is a convenience wrapper around get_server_cert().

§Arguments
  • hostname - The hostname (e.g., “code.editor.land”)
§Example
let mut cert_manager = CertificateManager::new("myapp").await?;
cert_manager.initialize_ca().await?;
let server_config = cert_manager.build_server_config("code.editor.land").await?;
Source

pub fn get_ca_cert_pem(&self) -> Option<Vec<u8>>

Get the CA certificate in PEM format

This can be used to install the CA in the system trust store or configure the webview to trust it.

§Returns

CA certificate PEM, or None if CA is not initialized

§Example
let mut cert_manager = CertificateManager::new("myapp").await?;
cert_manager.initialize_ca().await?;
let ca_cert = cert_manager.get_ca_cert_pem().unwrap();
println!("CA Certificate:\n{}", String::from_utf8_lossy(&ca_cert));
Source

pub fn get_server_cert_info(&self, hostname: &str) -> Option<CertificateInfo>

Get information about a server certificate

§Arguments
  • hostname - The hostname (e.g., “code.editor.land”)
§Returns

CertificateInfo if the certificate exists

§Example
let mut cert_manager = CertificateManager::new("myapp").await?;
cert_manager.initialize_ca().await?;
cert_manager.get_server_cert("code.editor.land").await?;
let info = cert_manager.get_server_cert_info("code.editor.land").unwrap();
println!("Certificate valid until: {}", info.valid_until);
Source

pub fn get_all_certs(&self) -> HashMap<String, CertificateInfo>

Get all cached server certificates

§Returns

A HashMap mapping hostnames to certificate info

§Example
let mut cert_manager = CertificateManager::new("myapp").await?;
cert_manager.initialize_ca().await?;
cert_manager.get_server_cert("code.editor.land").await?;
cert_manager.get_server_cert("api.editor.land").await?;
let all_certs = cert_manager.get_all_certs();
for (hostname, info) in all_certs {
	println!("{}: valid until {}", hostname, info.valid_until);
}
Source

fn cert_der_to_pem(der: &[u8]) -> Result<Vec<u8>>

Convert DER certificate to PEM format

Source

fn private_key_der_to_pem(der: &[u8]) -> Result<Vec<u8>>

Convert DER private key to PEM format

Source

fn pem_to_der(pem: &[u8], label: &str) -> Result<Vec<u8>>

Convert PEM to DER

Source

fn extract_cert_info( &self, cert_der: &[u8], hostname: &str, is_ca: bool, ) -> Result<CertificateInfo>

Extract certificate information from DER data

Source

fn check_cert_validity(&self, cert_pem: &[u8]) -> Result<CertValidityResult>

Check certificate validity and renewal status

Source

fn parse_not_after(not_after: &ASN1Time) -> Result<DateTime<Utc>>

Parse X.509 not_after time to chrono DateTime

Source

fn not_as_unix_timestamp(not_after: &ASN1Time) -> Option<i64>

Helper function to convert ASN1Time to Unix timestamp

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
§

impl<'a, T, E> AsTaggedExplicit<'a, E> for T
where T: 'a,

§

fn explicit(self, class: Class, tag: u32) -> TaggedParser<'a, Explicit, Self, E>

§

impl<'a, T, E> AsTaggedImplicit<'a, E> for T
where T: 'a,

§

fn implicit( self, class: Class, constructed: bool, tag: u32, ) -> TaggedParser<'a, Implicit, Self, E>

Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
§

impl<T> Downcast for T
where T: Any,

§

fn into_any(self: Box<T>) -> Box<dyn Any>

Convert Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.
§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

Convert Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
§

fn as_any(&self) -> &(dyn Any + 'static)

Convert &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &Any’s vtable from &Trait’s.
§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Convert &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
§

impl<T> DowncastSync for T
where T: Any + Send + Sync,

§

fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Sync + Send>

Convert Arc<Trait> (where Trait: Downcast) to Arc<Any>. Arc<Any> can then be further downcast into Arc<ConcreteType> where ConcreteType implements Trait.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> FutureExt for T

§

fn with_context(self, otel_cx: Context) -> WithContext<Self>

Attaches the provided Context to this type, returning a WithContext wrapper. Read more
§

fn with_current_context(self) -> WithContext<Self>

Attaches the current Context to this type, returning a WithContext wrapper. Read more
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

§

impl<T> IntoRequest<T> for T

§

fn into_request(self) -> Request<T>

Wrap the input message T in a tonic::Request
§

impl<L> LayerExt<L> for L

§

fn named_layer<S>(&self, service: S) -> Layered<<L as Layer<S>>::Service, S>
where L: Layer<S>,

Applies the layer to a service and wraps it in [Layered].
§

impl<T> Pointable for T

§

const ALIGN: usize

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
§

impl<T> PolicyExt for T
where T: ?Sized,

§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns [Action::Follow] only if self and other return Action::Follow. Read more
§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns [Action::Follow] if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more
Source§

impl<T> AutoreleaseSafe for T
where T: ?Sized,