viceroy_lib/wiggle_abi/
secret_store_impl.rs

1use {
2    crate::{
3        error::Error,
4        secret_store::SecretLookup,
5        session::Session,
6        wiggle_abi::{
7            fastly_secret_store::FastlySecretStore,
8            types::{FastlyStatus, SecretHandle, SecretStoreHandle},
9        },
10    },
11    std::convert::TryFrom,
12    wiggle::{GuestMemory, GuestPtr},
13};
14
15#[derive(Debug, thiserror::Error)]
16pub enum SecretStoreError {
17    /// A secret store with the given name was not found.
18    #[error("Unknown secret store: {0}")]
19    UnknownSecretStore(String),
20
21    /// A secret with the given name was not found.
22    #[error("Unknown secret: {0}")]
23    UnknownSecret(String),
24
25    /// An invalid secret store handle was provided.
26    #[error("Invalid secret store handle: {0}")]
27    InvalidSecretStoreHandle(SecretStoreHandle),
28
29    /// An invalid secret handle was provided.
30    #[error("Invalid secret handle: {0}")]
31    InvalidSecretHandle(SecretHandle),
32}
33
34impl From<&SecretStoreError> for FastlyStatus {
35    fn from(err: &SecretStoreError) -> Self {
36        use SecretStoreError::*;
37        match err {
38            UnknownSecretStore(_) => FastlyStatus::None,
39            UnknownSecret(_) => FastlyStatus::None,
40            InvalidSecretStoreHandle(_) => FastlyStatus::Badf,
41            InvalidSecretHandle(_) => FastlyStatus::Badf,
42        }
43    }
44}
45
46#[wiggle::async_trait]
47impl FastlySecretStore for Session {
48    fn open(
49        &mut self,
50        memory: &mut GuestMemory<'_>,
51        name: GuestPtr<str>,
52    ) -> Result<SecretStoreHandle, Error> {
53        let name = memory.as_str(name)?.ok_or(Error::SharedMemory)?;
54        self.secret_store_handle(&name)
55            .ok_or(Error::SecretStoreError(
56                SecretStoreError::UnknownSecretStore(name.to_string()),
57            ))
58    }
59
60    fn get(
61        &mut self,
62        memory: &mut GuestMemory<'_>,
63        secret_store_handle: SecretStoreHandle,
64        secret_name: GuestPtr<str>,
65    ) -> Result<SecretHandle, Error> {
66        let store_name =
67            self.secret_store_name(secret_store_handle)
68                .ok_or(Error::SecretStoreError(
69                    SecretStoreError::InvalidSecretStoreHandle(secret_store_handle),
70                ))?;
71        let secret_name = memory.as_str(secret_name)?.ok_or(Error::SharedMemory)?;
72        self.secret_handle(store_name.as_str(), &secret_name)
73            .ok_or(Error::SecretStoreError(SecretStoreError::UnknownSecret(
74                secret_name.to_string(),
75            )))
76    }
77
78    fn plaintext(
79        &mut self,
80        memory: &mut GuestMemory<'_>,
81        secret_handle: SecretHandle,
82        plaintext_buf: GuestPtr<u8>,
83        plaintext_max_len: u32,
84        nwritten_out: GuestPtr<u32>,
85    ) -> Result<(), Error> {
86        let lookup = self
87            .secret_lookup(secret_handle)
88            .ok_or(Error::SecretStoreError(
89                SecretStoreError::InvalidSecretHandle(secret_handle),
90            ))?;
91
92        let plaintext = match &lookup {
93            SecretLookup::Standard {
94                store_name,
95                secret_name,
96            } => self
97                .secret_stores()
98                .get_store(store_name)
99                .ok_or(Error::SecretStoreError(
100                    SecretStoreError::InvalidSecretHandle(secret_handle),
101                ))?
102                .get_secret(secret_name)
103                .ok_or(Error::SecretStoreError(
104                    SecretStoreError::InvalidSecretHandle(secret_handle),
105                ))?
106                .plaintext(),
107
108            SecretLookup::Injected { plaintext } => plaintext,
109        };
110
111        if plaintext.len() > plaintext_max_len as usize {
112            // Write out the number of bytes necessary to fit the
113            // plaintext, so client implementations can adapt their
114            // buffer sizes.
115            memory.write(nwritten_out, plaintext.len() as u32)?;
116            return Err(Error::BufferLengthError {
117                buf: "plaintext_buf",
118                len: "plaintext_max_len",
119            });
120        }
121        let plaintext_len = u32::try_from(plaintext.len())
122            .expect("smaller than plaintext_max_len means it must fit");
123
124        memory.copy_from_slice(plaintext, plaintext_buf.as_array(plaintext_len))?;
125        memory.write(nwritten_out, plaintext_len)?;
126
127        Ok(())
128    }
129
130    fn from_bytes(
131        &mut self,
132        memory: &mut GuestMemory<'_>,
133        plaintext_buf: GuestPtr<u8>,
134        plaintext_len: u32,
135    ) -> Result<SecretHandle, Error> {
136        let plaintext = memory.to_vec(plaintext_buf.as_array(plaintext_len))?;
137        Ok(self.add_secret(plaintext))
138    }
139}