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
impl PlatformSecretStore
Sourcepub fn standard(scope: SecretScope) -> Result<Self, SecretStoreError>
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.
Sourcepub fn for_start_mode(mode: StartMode) -> Result<Self, SecretStoreError>
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
Sourcepub fn rooted_at(
scope: SecretScope,
root: impl AsRef<Path>,
) -> Result<Self, SecretStoreError>
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.
Sourcepub fn guard(&self) -> PathBuf
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.
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.
Sourcepub fn with_credentials_directory(self, directory: impl AsRef<Path>) -> Self
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.
Sourcepub fn credential_path(&self) -> Option<&Path>
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
impl Clone for PlatformSecretStore
Source§fn clone(&self) -> PlatformSecretStore
fn clone(&self) -> PlatformSecretStore
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for PlatformSecretStore
impl Debug for PlatformSecretStore
impl Eq for PlatformSecretStore
Source§impl PartialEq for PlatformSecretStore
impl PartialEq for PlatformSecretStore
Source§impl SecretStore for PlatformSecretStore
impl SecretStore for PlatformSecretStore
Source§fn scope(&self) -> SecretScope
fn scope(&self) -> SecretScope
Source§fn location(&self) -> String
fn location(&self) -> String
host show
and service status print, and never the value itself.