Skip to main content

bitwarden_sm/secrets/
list.rs

1use bitwarden_api_api::models::{
2    SecretWithProjectsListResponseModel, SecretsWithProjectsInnerSecret,
3};
4use bitwarden_core::{
5    OrganizationId,
6    key_management::{KeyIds, SymmetricKeyId},
7    require,
8};
9use bitwarden_crypto::{Decryptable, EncString, KeyStoreContext};
10use schemars::JsonSchema;
11use serde::{Deserialize, Serialize};
12use uuid::Uuid;
13
14use crate::{SecretsManagerClient, error::SecretsManagerError};
15
16#[allow(missing_docs)]
17#[derive(Serialize, Deserialize, Debug, JsonSchema)]
18#[serde(rename_all = "camelCase", deny_unknown_fields)]
19pub struct SecretIdentifiersRequest {
20    /// Organization to retrieve all the secrets from
21    pub organization_id: Uuid,
22}
23
24pub(crate) async fn list_secrets(
25    client: &SecretsManagerClient,
26    input: &SecretIdentifiersRequest,
27) -> Result<SecretIdentifiersResponse, SecretsManagerError> {
28    let client = client.client();
29    let config = client.internal.get_api_configurations();
30    let res = config
31        .api_client
32        .secrets_api()
33        .list_by_organization(input.organization_id)
34        .await?;
35
36    let key_store = client.internal.get_key_store();
37
38    SecretIdentifiersResponse::process_response(res, &mut key_store.context())
39}
40
41#[allow(missing_docs)]
42#[derive(Serialize, Deserialize, Debug, JsonSchema)]
43#[serde(rename_all = "camelCase", deny_unknown_fields)]
44pub struct SecretIdentifiersByProjectRequest {
45    /// Project to retrieve all the secrets from
46    pub project_id: Uuid,
47}
48
49pub(crate) async fn list_secrets_by_project(
50    client: &SecretsManagerClient,
51    input: &SecretIdentifiersByProjectRequest,
52) -> Result<SecretIdentifiersResponse, SecretsManagerError> {
53    let client = client.client();
54    let config = client.internal.get_api_configurations();
55    let res = config
56        .api_client
57        .secrets_api()
58        .get_secrets_by_project(input.project_id)
59        .await?;
60
61    let key_store = client.internal.get_key_store();
62
63    SecretIdentifiersResponse::process_response(res, &mut key_store.context())
64}
65
66#[allow(missing_docs)]
67#[derive(Serialize, Deserialize, Debug, JsonSchema)]
68#[serde(rename_all = "camelCase", deny_unknown_fields)]
69pub struct SecretIdentifiersResponse {
70    pub data: Vec<SecretIdentifierResponse>,
71}
72
73impl SecretIdentifiersResponse {
74    pub(crate) fn process_response(
75        response: SecretWithProjectsListResponseModel,
76        ctx: &mut KeyStoreContext<KeyIds>,
77    ) -> Result<SecretIdentifiersResponse, SecretsManagerError> {
78        Ok(SecretIdentifiersResponse {
79            data: response
80                .secrets
81                .unwrap_or_default()
82                .into_iter()
83                .map(|r| SecretIdentifierResponse::process_response(r, ctx))
84                .collect::<Result<_, _>>()?,
85        })
86    }
87}
88
89#[derive(Serialize, Deserialize, Debug, JsonSchema)]
90#[serde(rename_all = "camelCase", deny_unknown_fields)]
91pub struct SecretIdentifierResponse {
92    pub id: Uuid,
93    pub organization_id: Uuid,
94
95    pub key: String,
96}
97
98impl SecretIdentifierResponse {
99    pub(crate) fn process_response(
100        response: SecretsWithProjectsInnerSecret,
101        ctx: &mut KeyStoreContext<KeyIds>,
102    ) -> Result<SecretIdentifierResponse, SecretsManagerError> {
103        let organization_id = require!(response.organization_id);
104        let enc_key = SymmetricKeyId::Organization(OrganizationId::new(organization_id));
105
106        let key = require!(response.key)
107            .parse::<EncString>()?
108            .decrypt(ctx, enc_key)?;
109
110        Ok(SecretIdentifierResponse {
111            id: require!(response.id),
112            organization_id,
113            key,
114        })
115    }
116}