# pki — guide
> **Class:** `guide` · audience: a techie setting up per-machine PKI. The *what* is in
> [`pki-design.md`](pki-design.md); the *why* in [`pki-reasoning.md`](pki-reasoning.md).
## Self-generated certs (default, offline)
The default `pki` feature gives you a real ed25519 X.509 CA and leaves with no network:
```rust
use skidbladnir::pki::{MachineCa, verify_leaf};
let ca = MachineCa::generate("target-host")?; // fresh CA, CN target-host.x14.local
let (leaf, key_pem) = ca.issue_leaf("holger", &["holger.local".into(), "127.0.0.1".into()])?;
// leaf.cert_pem + key_pem load straight into a rustls ServerConfig
assert!(verify_leaf(&leaf, &ca.verifying_key())); // real signature check
```
Write `ca.ca_cert_pem()` to the target's trust store and hand each service its
`leaf.cert_pem` + `key_pem`.
For reproducible tests, seed the CA deterministically (still a real keypair):
```rust
let ca = MachineCa::from_seed("target-host", [0u8; 32]); // same seed → same CA
```
## Drive it from a PkiSource
```rust
use skidbladnir::pki::{PkiSource, provision};
provision(&PkiSource::SelfGenerated, None)?; // materialise self-signed PKI
```
## Use an existing Vault (feature `vault`)
```rust
# #[cfg(feature = "vault")] {
use skidbladnir::pki::{PkiSource, provision, vault::HttpVaultClient, VaultClient};
let client = HttpVaultClient::new("https://vault.internal:8200", token, "nordisk")?
.mount("pki").ttl("72h");
let issued = client.issue("holger", &["holger.local".into()])?; // POST /v1/pki/issue/nordisk
provision(&PkiSource::ExistingVault("nordisk".into()), Some(&client))?;
# }
```
A throwaway dev Vault for integration tests:
```rust
# #[cfg(feature = "vault")] {
let client = skidbladnir::pki::vault::TempVaultClient::spawn("nordisk")?; // needs the `vault` binary
// … issue … ; teardown happens on drop
# }
```
## Gotchas
- Certs are trusted by **signature, not clock** — validity windows are deliberately wide (airgap
targets have no reliable NTP). Do not rely on short expiries for revocation.
- The Vault variants are **seams**: without the `vault` feature (or without a `VaultClient`),
`provision` errors clearly rather than pretending to issue.
- `SelfGenerated` needs the default `pki` feature; a `--no-default-features` build must add it back
to mint certs.