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

nordisk/edda

.nornir/vault-guide.md

nornir-vault — guide

Class: guide · How to drive nornir-vault. Sibling: vault-design.md.

Create, store, lock

use nornir_vault::{Vault, PinProvider, SecretEntry, SecretString};

let mut v = Vault::create("~/.korp/korp.vault", &PinProvider::new("4913"))?;
v.set("spark", SecretEntry::SparkToken(SecretString::new(token)))?;
v.set("mtls", SecretEntry::MtlsClientIdentity {
    cert_pem: SecretString::new(cert),
    key_pem:  SecretString::new(key),
})?;
v.lock(); // drops the DEK + all decrypted entries (zeroized)

create returns the vault unlocked and writes the encrypted header (0600). set re-seals under the DEK and persists.

Open and unlock

let mut v = Vault::open(path)?;      // locked: only the header is in memory
v.unlock(&PinProvider::new(pin))?;   // decrypts DEK + every entry into RAM
match v.get("spark")? {              // Err(Locked) if still locked
    Some(SecretEntry::SparkToken(t)) => use_token(t.expose()),
    _ => {}
}

A wrong PIN returns VaultError::Unlock { remaining } and burns one attempt (persisted). Once the budget is spent, unlock returns VaultError::LockedOut — even for the correct PIN. A successful unlock resets the counter.

OS keyring (feature os-keyring)

# #[cfg(feature = "os-keyring")]
let p = nornir_vault::OsKeyringProvider::new("korp-vault", "kek");
let mut v = Vault::create(path, &p)?;   // stores a random KEK in the OS keyring
// later: Vault::open(path)?.unlock(&p)?  // fetches it back — no PIN prompt

The consumer must enable a keyring backend for the platform (KDE Plasma thin client → keyring/sync-secret-service or the pure-Rust keyring/async-secret-service).

Showing state in a UI (the safe view)

let s = v.state();      // VaultState — NO secret bytes
serde_json::to_string(&s)?;  // safe to embed in state_json

VaultState carries locked, locked_out, method, attempts_remaining, and each entry's name + kind. Never put a SecretEntry/SecretString in a state_json, a log, or a Debug dump — the types refuse to serialize, and their Debug is redacted, but do not defeat that with .expose().

Rules of thumb