Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/Skidbladnir

.nornir/pki-guide.md

pki — guide

Class: guide · audience: a techie setting up per-machine PKI. The what is in pki-design.md; the why in 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:

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):

let ca = MachineCa::from_seed("target-host", [0u8; 32]);   // same seed → same CA

Drive it from a PkiSource

use skidbladnir::pki::{PkiSource, provision};
provision(&PkiSource::SelfGenerated, None)?;               // materialise self-signed PKI

Use an existing Vault (feature vault)

# #[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:

# #[cfg(feature = "vault")] {
let client = skidbladnir::pki::vault::TempVaultClient::spawn("nordisk")?;   // needs the `vault` binary
// … issue … ; teardown happens on drop
# }

Gotchas