MappingBackendUserSecrets

Trait MappingBackendUserSecrets 

Source
pub trait MappingBackendUserSecrets: MappingSystemUserId + MappingBackendUserIds {
    // Provided methods
    fn create_non_admin_backend_user_secrets(
        &self,
        secret_handling: NonAdministrativeSecretHandling,
    ) -> Result<Option<Vec<Box<dyn UserWithPassphrase>>>, Error> { ... }
    fn load_non_admin_backend_user_secrets(
        &self,
        secret_handling: NonAdministrativeSecretHandling,
        filter: NonAdminBackendUserIdFilter,
    ) -> Result<Option<Vec<Box<dyn UserWithPassphrase>>>, Error> { ... }
}
Expand description

An interface to create and load secrets for backend users in user mapping implementations.

Implementations are required to also implement MappingBackendUserIds and MappingSystemUserId

§Example

use signstar_config::{
    Error,
    SystemUserId,
    config::{
        BackendUserIdFilter,
        BackendUserIdKind,
        MappingBackendUserIds,
        MappingBackendUserSecrets,
        MappingSystemUserId,
    },
};
use signstar_crypto::{passphrase::Passphrase, traits::UserWithPassphrase};

#[derive(Debug)]
struct ExampleCreds {
    pub id: u8,
    pub passphrase: Passphrase,
}

impl UserWithPassphrase for ExampleCreds {
    fn user(&self) -> String {
        self.id.to_string()
    }

    fn passphrase(&self) -> &Passphrase {
        &self.passphrase
    }
}

#[derive(Debug)]
enum ExampleUserMapping {
    Admin {
        backend_id: u8,
    },
    Backup {
        backend_id: u8,
        system_user: SystemUserId,
    },
    Metrics {
        backend_id: u8,
        system_user: SystemUserId,
    },
    Signer {
        backend_id: u8,
        system_user: SystemUserId,
    },
}

impl ExampleUserMapping {
    pub fn backend_user_id(&self) -> u8 {
        match self {
            Self::Admin { backend_id }
            | Self::Backup { backend_id, .. }
            | Self::Metrics { backend_id, .. }
            | Self::Signer { backend_id, .. } => *backend_id,
        }
    }
}

impl MappingBackendUserIds for ExampleUserMapping {
    fn backend_user_ids(&self, filter: BackendUserIdFilter) -> Vec<String> {
        match self {
            Self::Admin { backend_id, .. } => {
                if [BackendUserIdKind::Admin, BackendUserIdKind::Any]
                    .contains(&filter.backend_user_id_kind)
                {
                    return vec![backend_id.to_string()];
                }
            }
            Self::Backup { backend_id, .. } => {
                if [
                    BackendUserIdKind::Any,
                    BackendUserIdKind::Backup,
                    BackendUserIdKind::NonAdmin,
                ]
                .contains(&filter.backend_user_id_kind)
                {
                    return vec![backend_id.to_string()];
                }
            }
            Self::Metrics { backend_id, .. } => {
                if [
                    BackendUserIdKind::Any,
                    BackendUserIdKind::Metrics,
                    BackendUserIdKind::NonAdmin,
                ]
                .contains(&filter.backend_user_id_kind)
                {
                    return vec![backend_id.to_string()];
                }
            }
            Self::Signer { backend_id, .. } => {
                if [
                    BackendUserIdKind::Any,
                    BackendUserIdKind::Signing,
                    BackendUserIdKind::NonAdmin,
                ]
                .contains(&filter.backend_user_id_kind)
                {
                    return vec![backend_id.to_string()];
                }
            }
        }

        Vec::new()
    }

    fn backend_user_with_passphrase(
        &self,
        name: &str,
        passphrase: Passphrase,
    ) -> Result<Box<dyn UserWithPassphrase>, Error> {
        let backend_user_id = self.backend_user_id();
        if backend_user_id.to_string() != name {
            return Err(
                signstar_config::config::TraitsError::BackendUserIdMismatch {
                    expected: name.to_string(),
                    actual: backend_user_id.to_string(),
                }
                .into(),
            );
        }

        Ok(Box::new(ExampleCreds {
            id: backend_user_id,
            passphrase,
        }))
    }

    fn backend_users_with_new_passphrase(
        &self,
        filter: BackendUserIdFilter,
    ) -> Vec<Box<dyn UserWithPassphrase>> {
        if let Some(backend_id) = match self {
            Self::Admin { backend_id, .. } => {
                if [BackendUserIdKind::Admin, BackendUserIdKind::Any]
                    .contains(&filter.backend_user_id_kind)
                {
                    Some(*backend_id)
                } else {
                    None
                }
            }
            Self::Backup { backend_id, .. } => {
                if [
                    BackendUserIdKind::Any,
                    BackendUserIdKind::Backup,
                    BackendUserIdKind::NonAdmin,
                ]
                .contains(&filter.backend_user_id_kind)
                {
                    Some(*backend_id)
                } else {
                    None
                }
            }
            Self::Metrics { backend_id, .. } => {
                if [
                    BackendUserIdKind::Any,
                    BackendUserIdKind::Metrics,
                    BackendUserIdKind::NonAdmin,
                ]
                .contains(&filter.backend_user_id_kind)
                {
                    Some(*backend_id)
                } else {
                    None
                }
            }
            Self::Signer { backend_id, .. } => {
                if [
                    BackendUserIdKind::Any,
                    BackendUserIdKind::Signing,
                    BackendUserIdKind::NonAdmin,
                ]
                .contains(&filter.backend_user_id_kind)
                {
                    Some(*backend_id)
                } else {
                    None
                }
            }
        } {
            vec![Box::new(ExampleCreds {
                id: backend_id,
                passphrase: Passphrase::generate(None),
            })]
        } else {
            Vec::new()
        }
    }
}

impl MappingSystemUserId for ExampleUserMapping {
    fn system_user_id(&self) -> Option<&SystemUserId> {
        match self {
            Self::Admin { .. } => None,
            Self::Backup { system_user, .. }
            | Self::Metrics { system_user, .. }
            | Self::Signer { system_user, .. } => Some(system_user),
        }
    }
}

impl MappingBackendUserSecrets for ExampleUserMapping {}

Provided Methods§

Source

fn create_non_admin_backend_user_secrets( &self, secret_handling: NonAdministrativeSecretHandling, ) -> Result<Option<Vec<Box<dyn UserWithPassphrase>>>, Error>

Creates on-disk secrets for non-administrative backend users of the mapping.

Returns a list of the created credentials as UserWithPassphrase implementations.

§Note

Returns Ok(None), if the mapping implementation tracks no system user.

§Errors

Returns an error if

  • the system user in the user mapping does not match an existing Unix user
  • the user calling this function is not root
  • write_passphrase_to_secrets_file fails for one of the newly generated passphrases
Source

fn load_non_admin_backend_user_secrets( &self, secret_handling: NonAdministrativeSecretHandling, filter: NonAdminBackendUserIdFilter, ) -> Result<Option<Vec<Box<dyn UserWithPassphrase>>>, Error>

Loads secrets from on-disk files for each non-administrative backend user matching a filter.

Returns a list of the loaded credentials as UserWithPassphrase implementations.

§Notes

Returns Ok(None), if the mapping implementation tracks no system user.

The system user of the user mapping implementation must match the effective user of the current process.

Delegates to load_passphrase_from_secrets_file for the loading of a single Passphrase from a secrets file.

§Errors

Returns an error if

  • the system user in the user mapping does not match the currently calling Unix user
  • load_passphrase_from_secrets_file fails for one of the secret files of the system user of the mapping

Implementors§