est-ca 0.1.0

RFC 7030 Enrollment over Secure Transport (EST) — client, server, and an internal X.509 CA in pure Rust.
docs.rs failed to build est-ca-0.1.0
Please check the build logs for more information.
See Builds for ideas on how to fix a failed build, or Metadata for how to configure docs.rs builds.
If you believe this is docs.rs' fault, open an issue.

est-ca

RFC 7030 Enrollment over Secure Transport (EST) + an internal X.509 CA, in pure Rust.

Three things commonly needed together when running an internal PKI that issues short-lived client certificates to programmatic callers (devices, services, tenants, CI runners):

  • Internal X.509 CA — load a signing key+cert, apply a strict profile, and issue leaves from PKCS#10 CSRs via rcgen.
  • EST serveraxum handlers for /cacerts, /simpleenroll, and /simplereenroll with pluggable authentication.
  • EST client — generate a CSR and enroll; renew via /simplereenroll over mTLS.

Feature flags

Feature Purpose
client (default) EST client: CSR generation + enroll + renew.
server EST server handlers (implies ca).
ca Internal CA primitives (issuer, profile, serial).
full All of the above.

Quick start (server)

# #[cfg(all(feature = "server", feature = "ca"))]
# async fn _doc() -> anyhow::Result<()> {
use std::sync::Arc;
use est_ca::auth::{AuthBackend, Principal};
use est_ca::ca::{CertProfile, Issuer, serial::InMemorySerialStore};
use est_ca::est::server::EstServer;

struct OpenAuth;
impl AuthBackend for OpenAuth {
    fn verify_bootstrap(&self, user: &str, _pass: &str) -> Result<Principal, String> {
        Ok(Principal::new(user))
    }
}

let issuer = Issuer::generate_self_signed(
    "my dev CA",
    CertProfile::client_auth_for_days(7),
    Arc::new(InMemorySerialStore::new()),
)?;
let app = EstServer::new(issuer, Arc::new(OpenAuth)).router();
// Bind with your preferred TLS-enabled axum setup:
axum::Server::bind(&"0.0.0.0:4440".parse()?)
    .serve(app.into_make_service()).await?;
# Ok(()) }

Quick start (client)

# #[cfg(feature = "client")]
# async fn _doc() -> anyhow::Result<()> {
use est_ca::est::client;
let http = reqwest::Client::new();
let (csr_der, key_pem) = client::make_csr("my-device")?;
let cert_der = client::simpleenroll(
    &http, "https://est.example.com", "my-device", "bootstrap-token", &csr_der,
).await?;
// Persist `cert_der` and `key_pem`; use for mTLS to your upstream server.
# Ok(()) }

Transport

RFC 7030 mandates TLS. This crate provides the protocol layer only — the consumer puts a TLS listener in front of the server router and, for /simplereenroll, verifies the client cert and forwards the verified Common Name via the x-est-principal request header.

Non-goals

  • Public-web CA compliance (CA/B Forum Baseline Requirements, WebTrust).
  • CRL / OCSP publication — short-lived certs are the revocation story.
  • EST's optional endpoints (/fullcmc, /serverkeygen, /csrattrs).

License

Licensed under either of Apache-2.0 or MIT, at your option.