Skip to main content

bitwarden_pam/rotation/
registration.rs

1//! The cryptographic half of connector registration. Key material is minted by
2//! `bitwarden-access-token`.
3
4use bitwarden_access_token::{AccessTokenKind, AccessTokenSecrets, make_access_token_secrets};
5use bitwarden_core::{OrganizationId, key_management::SymmetricKeySlotId};
6
7use super::{connectors::AccessConnectorsClient, error::RotationError};
8
9impl AccessConnectorsClient {
10    /// Generates the key material a connector registration needs.
11    ///
12    /// Fails with [`MissingOrganizationKey`](RotationError::MissingOrganizationKey) for a caller
13    /// whose key store holds no key for the organization (not a member, or an unpopulated store).
14    pub(super) fn registration_secrets(
15        &self,
16        organization_id: OrganizationId,
17    ) -> Result<AccessTokenSecrets, RotationError> {
18        let organization_key = SymmetricKeySlotId::Organization(organization_id);
19        let mut ctx = self.key_store.context_mut();
20
21        if !ctx.has_symmetric_key(organization_key) {
22            return Err(RotationError::MissingOrganizationKey);
23        }
24
25        Ok(make_access_token_secrets(
26            &mut ctx,
27            organization_key,
28            AccessTokenKind::AccessConnector,
29        )?)
30    }
31}
32
33#[cfg(test)]
34mod tests {
35    use std::sync::Arc;
36
37    use bitwarden_api_api::apis::ApiClient;
38    use bitwarden_core::{
39        client::ApiConfigurations, key_management::create_test_crypto_with_user_key,
40    };
41    use bitwarden_crypto::{SymmetricCryptoKey, SymmetricKeyAlgorithm};
42    use uuid::uuid;
43
44    use super::*;
45
46    fn organization_id() -> OrganizationId {
47        OrganizationId::new(uuid!("11111111-1111-1111-1111-111111111111"))
48    }
49
50    #[test]
51    fn registering_without_the_organization_key_fails_before_any_network_call() {
52        let client = AccessConnectorsClient {
53            // A store with a user key but no organization key, as for a non-member.
54            key_store: create_test_crypto_with_user_key(SymmetricCryptoKey::make(
55                SymmetricKeyAlgorithm::Aes256CbcHmac,
56            )),
57            api_configurations: Arc::new(ApiConfigurations::from_api_client(
58                ApiClient::new_mocked(|_| {}),
59            )),
60        };
61
62        let result = client.registration_secrets(organization_id());
63
64        assert!(matches!(result, Err(RotationError::MissingOrganizationKey)));
65    }
66}