Skip to main content

PlatformSecretStore

Struct PlatformSecretStore 

Source
pub struct PlatformSecretStore { /* private fields */ }
Expand description

The real store: DPAPI on Windows, a keychain on macOS, a 0600 file plus systemd credentials on Linux.

One type with three bodies rather than three types, because the choice is made by cfg at compile time and a caller never has one without the other two being impossible. The scope, by contrast, is a runtime choice and is a field.

Implementations§

Source§

impl PlatformSecretStore

Source

pub fn standard(scope: SecretScope) -> Result<Self, SecretStoreError>

Resolves the platform-standard location for scope.

This is what production uses and what host show reports. Nothing is touched on disk here; the directory, the file, and the keychain are created by the first SecretStore::store.

§Errors

SecretStoreError::Resolve when the platform cannot say where the location is — no %ProgramData% on Windows, no home directory for this account on the two Unixes. A service account configured with no profile is the way that actually happens, and the message says so.

Source

pub fn for_start_mode(mode: StartMode) -> Result<Self, SecretStoreError>

Resolves the store the configured start mode obliges.

The one constructor a daemon should use: it makes the store a function of the recorded start mode rather than of whichever constructor the call site happened to reach for.

§Errors

As PlatformSecretStore::standard.

Source

pub fn rooted_at( scope: SecretScope, root: impl AsRef<Path>, ) -> Result<Self, SecretStoreError>

Places the same backend under a root the caller names.

crate::paths::AppPaths::rooted_at is the precedent and the reasoning is the same: a test needs a disposable store, and a service installed against an explicitly configured root has to reproduce one. A relative root stays relative, which is the caller’s decision to make.

§What a rooted store does and does not exercise

Everything that makes a scope a scope, on two of the three platforms. The Windows backend picks its DPAPI flag and its DACL from the scope, not from the site, so a rooted machine-scoped store is protected and encrypted exactly as the standard one is. The Linux backend’s 0600 file, its atomic replace, and its systemd-credential read path are the same code under either root.

macOS is where a rooted store is genuinely weaker, and it is worth being precise about how. A rooted store is a keychain this program creates in the root directory, and both scopes get one; what the standard sites have and it does not is the choice of keychain — the System Keychain against the login keychain — and the System Keychain’s root-only master key. The keychain calls themselves, the item, the not-found handling and the delete are identical. The password protecting a rooted keychain is ROOTED_KEYCHAIN_PASSWORD, which is a constant in a public binary and therefore protects nothing on its own: what protects a rooted keychain is the mode of the directory it is in, which is the same protection the Linux backend relies on for a value it stores in plaintext.

§Errors

SecretStoreError::Resolve; in practice it cannot fail, because the caller supplied the root.

Source

pub fn guard(&self) -> PathBuf

The filesystem object whose access control decides who can read this store, whether or not anything is stored yet.

Separate from SecretStore::protection because the guard can be named before the store exists, which is what lets host show report the machine store’s protection on a host that has never logged in.

Source§

impl PlatformSecretStore

Systemd credentials, which exist on no other platform.

A separate impl block rather than a cross-platform method that does nothing on two of three operating systems: a caller that names PlatformSecretStore::with_credentials_directory is writing code that only means something on Linux, and it should not compile anywhere else.

Source

pub fn with_credentials_directory(self, directory: impl AsRef<Path>) -> Self

Points this store at a systemd credentials directory the caller names, instead of the one $CREDENTIALS_DIRECTORY named.

PlatformSecretStore::standard already reads the environment variable, so a daemon started by systemd needs none of this. It is here for the two callers that cannot use the environment: a test, which must not mutate a process-wide variable that every other test is reading at the same time, and service install, which resolves what the unit it is about to write will set.

Source

pub fn credential_path(&self) -> Option<&Path>

The systemd credential this store reads before it reads its own file, when it has one.

Trait Implementations§

Source§

impl Clone for PlatformSecretStore

Source§

fn clone(&self) -> PlatformSecretStore

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 PlatformSecretStore

Source§

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

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

impl Eq for PlatformSecretStore

Source§

impl PartialEq for PlatformSecretStore

Source§

fn eq(&self, other: &PlatformSecretStore) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl SecretStore for PlatformSecretStore

Source§

fn scope(&self) -> SecretScope

Which of the two stores this is.
Source§

fn location(&self) -> String

Where the value lives, in the platform’s own terms. What host show and service status print, and never the value itself.
Source§

fn store(&self, secret: &SecretString) -> Result<(), SecretStoreError>

Writes the value, replacing whatever was there. Read more
Source§

fn load(&self) -> Result<Option<SecretString>, SecretStoreError>

Reads the value back, or reports that there is none. Read more
Source§

fn delete(&self) -> Result<Removal, SecretStoreError>

Removes the value. Read more
Source§

fn protection(&self) -> Result<Protection, SecretStoreError>

What stands between the stored value and an ordinary local user. Read more
Source§

impl StructuralPartialEq for PlatformSecretStore

Auto Trait Implementations§

Blanket Implementations§

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<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<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

Source§

fn equivalent(&self, key: &K) -> bool

Checks if this value is equivalent to the given key. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

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> Same for T

Source§

type Output = T

Should always be Self
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<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