kanidmd_lib/be/
keystorage.rs

1use crate::rusqlite::OptionalExtension;
2use kanidm_lib_crypto::prelude::{PKey, Private, X509};
3use kanidm_lib_crypto::serialise::{pkeyb64, x509b64};
4use serde::{Deserialize, Serialize};
5use std::collections::BTreeMap;
6use std::hash::Hash;
7
8use super::idl_arc_sqlite::IdlArcSqliteWriteTransaction;
9use super::idl_sqlite::IdlSqliteTransaction;
10use super::idl_sqlite::IdlSqliteWriteTransaction;
11use super::idl_sqlite::{serde_json_error, sqlite_error};
12use super::BackendWriteTransaction;
13use crate::prelude::OperationError;
14
15/// These are key handles for storing keys related to various cryptographic components
16/// within Kanidm. Generally these are for keys that are "static", as in have known
17/// long term uses. This could be the servers private replication key, a TPM Storage
18/// Root Key, or the Duplicable Storage Key. In future these may end up being in
19/// a HSM or similar, but we'll always need a way to persist serialised forms of these.
20#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Hash, Ord, PartialOrd)]
21pub enum KeyHandleId {
22    ReplicationKey,
23}
24
25/// This is a key handle that contains the actual data that is persisted in the DB.
26#[derive(Debug, Clone, Serialize, Deserialize)]
27pub enum KeyHandle {
28    X509Key {
29        #[serde(with = "pkeyb64")]
30        private: PKey<Private>,
31        #[serde(with = "x509b64")]
32        x509: X509,
33    },
34}
35
36impl BackendWriteTransaction<'_> {
37    /// Retrieve a key stored in the database by it's key handle. This
38    /// handle may require further processing for the key to be usable
39    /// in higher level contexts as this is simply the storage layer
40    /// for these keys.
41    pub(crate) fn get_key_handle(
42        &mut self,
43        handle: KeyHandleId,
44    ) -> Result<Option<KeyHandle>, OperationError> {
45        self.idlayer.get_key_handle(handle)
46    }
47
48    /// Update the content of a keyhandle with this new data.
49    pub(crate) fn set_key_handle(
50        &mut self,
51        handle: KeyHandleId,
52        data: KeyHandle,
53    ) -> Result<(), OperationError> {
54        self.idlayer.set_key_handle(handle, data)
55    }
56}
57
58impl IdlArcSqliteWriteTransaction<'_> {
59    pub(crate) fn get_key_handle(
60        &mut self,
61        handle: KeyHandleId,
62    ) -> Result<Option<KeyHandle>, OperationError> {
63        if let Some(kh) = self.keyhandles.get(&handle) {
64            Ok(Some(kh.clone()))
65        } else {
66            let r = self.db.get_key_handle(handle);
67
68            if let Ok(Some(kh)) = &r {
69                self.keyhandles.insert(handle, kh.clone());
70            }
71
72            r
73        }
74    }
75
76    /// Update the content of a keyhandle with this new data.
77    #[instrument(level = "debug", skip(self, data))]
78    pub(crate) fn set_key_handle(
79        &mut self,
80        handle: KeyHandleId,
81        data: KeyHandle,
82    ) -> Result<(), OperationError> {
83        self.db.set_key_handle(handle, &data)?;
84        self.keyhandles.insert(handle, data);
85        Ok(())
86    }
87
88    pub(super) fn set_key_handles(
89        &mut self,
90        keyhandles: BTreeMap<KeyHandleId, KeyHandle>,
91    ) -> Result<(), OperationError> {
92        self.db.set_key_handles(&keyhandles)?;
93        self.keyhandles.clear();
94        self.keyhandles.extend(keyhandles);
95        Ok(())
96    }
97}
98
99impl IdlSqliteWriteTransaction {
100    pub(crate) fn get_key_handle(
101        &mut self,
102        handle: KeyHandleId,
103    ) -> Result<Option<KeyHandle>, OperationError> {
104        let s_handle = serde_json::to_vec(&handle).map_err(serde_json_error)?;
105
106        let mut stmt = self
107            .get_conn()?
108            .prepare(&format!(
109                "SELECT data FROM {}.keyhandles WHERE id = :id",
110                self.get_db_name()
111            ))
112            .map_err(sqlite_error)?;
113        let data_raw: Option<Vec<u8>> = stmt
114            .query_row(&[(":id", &s_handle)], |row| row.get(0))
115            // We don't mind if it doesn't exist
116            .optional()
117            .map_err(sqlite_error)?;
118
119        let data: Option<KeyHandle> = match data_raw {
120            Some(d) => serde_json::from_slice(d.as_slice())
121                .map(Some)
122                .map_err(serde_json_error)?,
123            None => None,
124        };
125
126        Ok(data)
127    }
128
129    pub(super) fn get_key_handles(
130        &mut self,
131    ) -> Result<BTreeMap<KeyHandleId, KeyHandle>, OperationError> {
132        let mut stmt = self
133            .get_conn()?
134            .prepare(&format!(
135                "SELECT id, data FROM {}.keyhandles",
136                self.get_db_name()
137            ))
138            .map_err(sqlite_error)?;
139
140        let kh_iter = stmt
141            .query_map([], |row| Ok((row.get(0)?, row.get(1)?)))
142            .map_err(sqlite_error)?;
143
144        kh_iter
145            .map(|v| {
146                let (id, data): (Vec<u8>, Vec<u8>) = v.map_err(sqlite_error)?;
147                let id = serde_json::from_slice(id.as_slice()).map_err(serde_json_error)?;
148                let data = serde_json::from_slice(data.as_slice()).map_err(serde_json_error)?;
149                Ok((id, data))
150            })
151            .collect()
152    }
153
154    /// Update the content of a keyhandle with this new data.
155    #[instrument(level = "debug", skip(self, data))]
156    pub(crate) fn set_key_handle(
157        &mut self,
158        handle: KeyHandleId,
159        data: &KeyHandle,
160    ) -> Result<(), OperationError> {
161        let s_handle = serde_json::to_vec(&handle).map_err(serde_json_error)?;
162        let s_data = serde_json::to_vec(&data).map_err(serde_json_error)?;
163
164        self.get_conn()?
165            .prepare(&format!(
166                "INSERT OR REPLACE INTO {}.keyhandles (id, data) VALUES(:id, :data)",
167                self.get_db_name()
168            ))
169            .and_then(|mut stmt| stmt.execute(&[(":id", &s_handle), (":data", &s_data)]))
170            .map(|_| ())
171            .map_err(sqlite_error)
172    }
173
174    pub(super) fn set_key_handles(
175        &mut self,
176        keyhandles: &BTreeMap<KeyHandleId, KeyHandle>,
177    ) -> Result<(), OperationError> {
178        self.get_conn()?
179            .execute(
180                &format!("DELETE FROM {}.keyhandles", self.get_db_name()),
181                [],
182            )
183            .map(|_| ())
184            .map_err(sqlite_error)?;
185
186        for (handle, data) in keyhandles {
187            self.set_key_handle(*handle, data)?;
188        }
189        Ok(())
190    }
191}