Skip to main content

SecretConfig

Struct SecretConfig 

Source
pub struct SecretConfig {
    pub schema_version: u32,
    pub name: String,
    pub vault_slot: String,
    pub groups: Vec<String>,
    pub description: Option<String>,
    pub encoding: SecretEncoding,
    pub access: SecretAccess,
    pub target: Option<SecretTargetDecl>,
}
Expand description

A camp’s declaration of one cluster secret, from .yah/infra/secrets/<slug>.toml.

This is the authoring side of the fleet’s cluster-secret store: it names where the value lives in the camp (a fob vault slot), what the fleet should call it, and — the point of R706 — which workloads are allowed to mount it.

The declaration is not itself the enforcement point. yah cloud secret put reads this file, seals the vault value under the cluster KEK, and ships the ciphertext with its access rule into raft; yubaba’s ClusterResolver evaluates the rule on the node at mount time. Deleting this file does not revoke anything — the record in raft is the live authority. That asymmetry is deliberate: a rule that lived only in a git-tracked camp file would be trivially bypassed by anyone who could reach the fleet without the camp.

#:schema ../../schema/secret.toml.schema.json
schema_version = 2
name = "cheers/cloud-admin/verify-key"
vault_slot = "cheers-cloud-admin-verify-key"
groups = ["prod"]
description = "Ed25519 public key yah-cloud-admin verifies operator PASETOs with"

[access]
workloads = [{ workload = "yah-cloud-admin" }]

[target]
kind = "file"
path = "/run/secrets/cheers-verify.key"
mode = 0o400

Fields§

§schema_version: u32§name: String

Logical cluster-secret key, as SecretRef::Cluster { name } spells it — e.g. "tls/yah.dev/cert", "cheers/cloud-admin/verify-key". May contain /; the file stem is a filesystem-safe slug and carries no meaning.

§vault_slot: String

The fob vault slot in this camp holding the plaintext value. Read by yah cloud secret put at ship time and never recorded anywhere else — in particular the value is not in this file, so the declaration is safe to commit.

§groups: Vec<String>

The sovereign groups this secret belongs to (R911-F8). Required and non-empty; each entry must be a sovereign_group that some .yah/infra/machines/*.toml declares (SecretConfig::load checks).

Cluster secrets live per group in the fleet object store (secrets/<group>/<name>.sealed), so a declaration with no group has nowhere to land and nothing to be compared against. yah cloud secret put refuses a node whose /raft/status group is not listed here, and status counts a declaration only against nodes in one of these groups.

§description: Option<String>

Human note for yah cloud secret ls. What this secret is and who minted it — the thing nobody remembers 6 months later.

§encoding: SecretEncoding

How the vault slot’s text decodes into the bytes the consumer expects.

fob slots hold strings, but plenty of real secrets are binary — an Ed25519 key is exactly 32 raw bytes, and yah-cloud-admin rejects a key file of any other length. Without this field the only way to ship such a key would be to hope its bytes happened to be valid UTF-8, which for a random key they are not.

Defaults to SecretEncoding::Utf8 — the right answer for tokens, passwords, and PEM, which is most secrets.

§access: SecretAccess

Who may mount it. Stamped onto the raft record verbatim.

Defaults to SecretAccess::default — the deny-all empty allow-list. A declaration that forgets this field produces a secret nobody can mount, which is the correct direction to fail in.

Three forms:

access = "allow_any"                              # explicit escape hatch

[access]                                          # named workloads
workloads = [{ workload = "yah-cloud-admin" }]

[access]                                          # signed recipes (R555-F5)
recipes = [{ recipe = "rusty-v8-musl", key = "3d40…" }]

Use the recipes form for a credential a dispatched build needs (the R2 write key, the cosign signing key). A remote QED run’s workload name is a fresh forge-<uuid> every time, so workloads cannot name it and allow_any over-answers — see W235 §Seam (c) secret scoping. key is the hex Ed25519 public key from the recipe’s [admission] block.

§target: Option<SecretTargetDecl>

Advisory: the mount shape a consuming workload should declare. Not enforced — yubaba honours whatever the WorkloadSpec asks for — but it lets yah cloud secret put print the exact SecretMount to paste, so the consumer and the declaration can’t drift on path or mode.

Implementations§

Source§

impl SecretConfig

Source

pub fn load(path: &Path, sovereign_groups: &[&str]) -> Result<Self>

Parse a single .yah/infra/secrets/<slug>.toml.

sovereign_groups is the camp’s group vocabulary (CloudConfig::declared_sovereign_groups); every entry in groups must be one of them.

Source

pub fn load_dir( dir: &Path, sovereign_groups: &[&str], ) -> Result<BTreeMap<String, Self>>

Load every declaration in dir, keyed by logical secret name. A missing directory is an empty map (a camp with no cluster secrets is normal).

Two files declaring the same name is a hard error, not a last-writer- wins merge: they would race to define the access rule for one record, and whichever lost would look correct in git while being inert on the fleet.

Source

pub fn validate(&self) -> Result<()>

Reject declarations that would produce an unusable or dangerous record.

Structural only: whether each of groups names a real sovereign group needs the camp’s machines, so that half is Self::validate_groups.

Source

pub fn validate_groups(&self, sovereign_groups: &[&str]) -> Result<()>

Every entry in groups must be a sovereign group the camp’s machines declare. A typo would otherwise produce a declaration no node ever matches, which put would refuse everywhere and status would never count, without either one saying why.

Trait Implementations§

Source§

impl Clone for SecretConfig

Source§

fn clone(&self) -> SecretConfig

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for SecretConfig

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<'de> Deserialize<'de> for SecretConfig

Source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl Serialize for SecretConfig

Source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Allocation for T
where T: RefUnwindSafe + Send + Sync,

Source§

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

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
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
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,

Source§

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

Source§

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.
Source§

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.
Source§

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.
Source§

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.
Source§

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

Source§

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

Converts Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>, which can then be downcast into Box<dyn ConcreteType> where ConcreteType implements Trait.
Source§

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

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

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

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

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

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

impl<T> DowncastSend for T
where T: Any + Send,

Source§

fn into_any_send(self: Box<T>) -> Box<dyn Any + Send>

Converts Box<Trait> (where Trait: DowncastSend) to Box<dyn Any + Send>, which can then be downcast into Box<ConcreteType> where ConcreteType implements Trait.
Source§

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

Source§

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> DowncastSync for T
where T: Any + Send + Sync,

Source§

fn into_any_sync(self: Box<T>) -> Box<dyn Any + Sync + Send>

Converts Box<Trait> (where Trait: DowncastSync) to Box<dyn Any + Send + Sync>, which can then be downcast into Box<ConcreteType> where ConcreteType implements Trait.
Source§

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

Converts Arc<Trait> (where Trait: DowncastSync) to Arc<Any>, which can then be downcast into Arc<ConcreteType> where ConcreteType implements Trait.
Source§

impl<T> ErasedDestructor for T
where T: 'static,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> FromRef<T> for T
where T: Clone,

Source§

fn from_ref(input: &T) -> T

Converts to this type from a reference to the input type.
Source§

impl<T> FromRef<T> for T
where T: Clone,

Source§

fn from_ref(input: &T) -> T

Converts to this type from a reference to the input type.
Source§

impl<T> Fruit for T
where T: Send + Downcast,

Source§

impl<A, B, T> HttpServerConnExec<A, B> for T
where B: Body,

Source§

impl<T> Instrument for T

Source§

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

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

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.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

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

Initializes a with the given initializer. Read more
Source§

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

Dereferences the given pointer. Read more
Source§

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

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

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

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

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + 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
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + 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> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> Serialize for T
where T: Serialize + ?Sized,

Source§

fn erased_serialize(&self, serializer: &mut dyn Serializer) -> Result<(), Error>

Source§

fn do_erased_serialize( &self, serializer: &mut dyn Serializer, ) -> Result<(), ErrorImpl>

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

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

Source§

type Error = !

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

fn try_from(value: U) -> Result<T, !>

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.
Source§

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

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

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
Source§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

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