1use crate::be::dbvalue::{DbValueKeyInternal, DbValueKeyStatus, DbValueKeyUsage};
2use crate::prelude::*;
3use crate::server::keys::KeyId;
4use crate::value::{KeyStatus, KeyUsage};
5use crate::valueset::ScimResolveStatus;
6use crate::valueset::{DbValueSetV2, ValueSet};
7use kanidm_proto::scim_v1::server::ScimKeyInternal;
8use std::collections::BTreeMap;
9use std::fmt;
10use time::OffsetDateTime;
11
12#[derive(Clone, PartialEq, Eq)]
13pub struct KeyInternalData {
14 pub usage: KeyUsage,
15 pub valid_from: u64,
16 pub status: KeyStatus,
17 pub status_cid: Cid,
18 pub der: Vec<u8>,
19}
20
21impl fmt::Debug for KeyInternalData {
22 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
23 f.debug_struct("KeyInternalData")
24 .field("usage", &self.usage)
25 .field("valid_from", &self.valid_from)
26 .field("status", &self.status)
27 .field("status_cid", &self.status_cid)
28 .finish()
29 }
30}
31
32#[derive(Debug, Clone)]
33pub struct ValueSetKeyInternal {
34 map: BTreeMap<KeyId, KeyInternalData>,
35}
36
37impl ValueSetKeyInternal {
38 pub fn new(
39 id: KeyId,
40 usage: KeyUsage,
41 valid_from: u64,
42 status: KeyStatus,
43 status_cid: Cid,
44 der: Vec<u8>,
45 ) -> Box<Self> {
46 let map = BTreeMap::from([(
47 id,
48 KeyInternalData {
49 usage,
50 valid_from,
51 status,
52 status_cid,
53 der,
54 },
55 )]);
56
57 Box::new(ValueSetKeyInternal { map })
58 }
59
60 pub fn from_key_iter(
61 keys: impl Iterator<Item = (KeyId, KeyInternalData)>,
62 ) -> Result<ValueSet, OperationError> {
63 let map = keys.collect();
64
65 Ok(Box::new(ValueSetKeyInternal { map }))
66 }
67
68 fn from_dbv_iter(
69 keys: impl Iterator<Item = DbValueKeyInternal>,
70 ) -> Result<ValueSet, OperationError> {
71 let map = keys
72 .map(|dbv_key| {
73 match dbv_key {
74 DbValueKeyInternal::V1 {
75 id,
76 usage,
77 valid_from,
78 status,
79 status_cid,
80 der,
81 } => {
82 let id: KeyId = id;
84 let usage = match usage {
85 DbValueKeyUsage::JwsEs256 => KeyUsage::JwsEs256,
86 DbValueKeyUsage::JwsRs256 => KeyUsage::JwsRs256,
87 DbValueKeyUsage::JweA128GCM => KeyUsage::JweA128GCM,
88 };
89 let status_cid = status_cid.into();
90 let status = match status {
91 DbValueKeyStatus::Valid => KeyStatus::Valid,
92 DbValueKeyStatus::Retained => KeyStatus::Retained,
93 DbValueKeyStatus::Revoked => KeyStatus::Revoked,
94 };
95
96 Ok((
97 id,
98 KeyInternalData {
99 usage,
100 valid_from,
101 status,
102 status_cid,
103 der,
104 },
105 ))
106 }
107 }
108 })
109 .collect::<Result<BTreeMap<_, _>, _>>()?;
110
111 Ok(Box::new(ValueSetKeyInternal { map }))
112 }
113
114 pub fn from_dbvs2(keys: Vec<DbValueKeyInternal>) -> Result<ValueSet, OperationError> {
115 Self::from_dbv_iter(keys.into_iter())
116 }
117
118 fn to_vec_dbvs(&self) -> Vec<DbValueKeyInternal> {
119 self.map
120 .iter()
121 .map(
122 |(
123 id,
124 KeyInternalData {
125 usage,
126 status,
127 status_cid,
128 valid_from,
129 der,
130 },
131 )| {
132 let id: String = id.clone();
133 let usage = match usage {
134 KeyUsage::JwsEs256 => DbValueKeyUsage::JwsEs256,
135 KeyUsage::JwsRs256 => DbValueKeyUsage::JwsRs256,
136 KeyUsage::JweA128GCM => DbValueKeyUsage::JweA128GCM,
137 };
138 let status_cid = status_cid.into();
139 let status = match status {
140 KeyStatus::Valid => DbValueKeyStatus::Valid,
141 KeyStatus::Retained => DbValueKeyStatus::Retained,
142 KeyStatus::Revoked => DbValueKeyStatus::Revoked,
143 };
144
145 DbValueKeyInternal::V1 {
146 id,
147 usage,
148 status,
149 status_cid,
150 der: der.clone(),
151 valid_from: *valid_from,
152 }
153 },
154 )
155 .collect()
156 }
157}
158
159impl ValueSetT for ValueSetKeyInternal {
160 fn insert_checked(&mut self, _value: crate::value::Value) -> Result<bool, OperationError> {
161 debug_assert!(false);
176 Err(OperationError::InvalidValueState)
177 }
180
181 fn clear(&mut self) {
182 debug_assert!(false);
184 self.map.clear();
185 }
186
187 fn remove(&mut self, pv: &crate::value::PartialValue, _cid: &Cid) -> bool {
188 match pv {
189 PartialValue::HexString(kid) => {
190 if let Some(key_object) = self.map.get_mut(kid) {
191 if !matches!(key_object.status, KeyStatus::Revoked) {
192 key_object.status = KeyStatus::Revoked;
194 true
195 } else {
196 false
197 }
198 } else {
199 false
200 }
201 }
202 _ => false,
203 }
204 }
205
206 fn purge(&mut self, cid: &Cid) -> bool {
207 for key_object in self.map.values_mut() {
208 if !matches!(key_object.status, KeyStatus::Revoked) {
209 key_object.status_cid = cid.clone();
210 key_object.status = KeyStatus::Revoked;
211 }
212 }
213 false
214 }
215
216 fn trim(&mut self, trim_cid: &Cid) {
217 self.map.retain(|_, key_internal| {
218 match &key_internal.status {
219 KeyStatus::Revoked if &key_internal.status_cid < trim_cid => {
220 false
223 }
224 _ => true,
226 }
227 });
228 }
229
230 fn contains(&self, pv: &crate::value::PartialValue) -> bool {
231 match pv {
232 PartialValue::HexString(kid) => self.map.contains_key(kid),
233 _ => false,
234 }
235 }
236
237 fn substring(&self, _pv: &crate::value::PartialValue) -> bool {
238 false
239 }
240
241 fn startswith(&self, _pv: &PartialValue) -> bool {
242 false
243 }
244
245 fn endswith(&self, _pv: &PartialValue) -> bool {
246 false
247 }
248
249 fn lessthan(&self, _pv: &crate::value::PartialValue) -> bool {
250 false
251 }
252
253 fn len(&self) -> usize {
254 self.map.len()
255 }
256
257 fn generate_idx_eq_keys(&self) -> Vec<String> {
258 self.map.keys().map(hex::encode).collect()
259 }
260
261 fn syntax(&self) -> SyntaxType {
262 SyntaxType::KeyInternal
263 }
264
265 fn validate(&self, _schema_attr: &crate::schema::SchemaAttribute) -> bool {
266 self.map.keys().all(|s| {
268 Value::validate_str_escapes(s)
270 && Value::validate_singleline(s)
271 && Value::validate_hexstr(s.as_str())
272 })
273 }
274
275 fn to_proto_string_clone_iter(&self) -> Box<dyn Iterator<Item = String> + '_> {
276 Box::new(self.map.iter().map(|(kid, key_object)| {
277 format!(
278 "{}: {} {} {}",
279 kid, key_object.status, key_object.usage, key_object.valid_from
280 )
281 }))
282 }
283
284 fn to_scim_value(&self) -> Option<ScimResolveStatus> {
285 Some(ScimResolveStatus::Resolved(ScimValueKanidm::from(
286 self.map
287 .iter()
288 .map(|(kid, key_object)| {
289 let odt: OffsetDateTime =
290 OffsetDateTime::UNIX_EPOCH + Duration::from_secs(key_object.valid_from);
291
292 ScimKeyInternal {
293 key_id: kid.clone(),
294 status: key_object.status.to_string(),
295 usage: key_object.usage.to_string(),
296 valid_from: odt,
297 }
298 })
299 .collect::<Vec<_>>(),
300 )))
301 }
302
303 fn to_db_valueset_v2(&self) -> DbValueSetV2 {
304 let keys = self.to_vec_dbvs();
305 DbValueSetV2::KeyInternal(keys)
306 }
307
308 fn to_partialvalue_iter(&self) -> Box<dyn Iterator<Item = crate::value::PartialValue> + '_> {
309 Box::new(self.map.keys().cloned().map(PartialValue::HexString))
310 }
311
312 fn to_value_iter(&self) -> Box<dyn Iterator<Item = crate::value::Value> + '_> {
313 debug_assert!(false);
314 Box::new(self.map.iter().map(
315 |(
316 id,
317 KeyInternalData {
318 usage,
319 status,
320 status_cid,
321 der,
322 valid_from,
323 },
324 )| {
325 Value::KeyInternal {
326 id: id.clone(),
327 usage: *usage,
328 status: *status,
329 status_cid: status_cid.clone(),
330 der: der.clone(),
331 valid_from: *valid_from,
332 }
333 },
334 ))
335 }
336
337 fn equal(&self, other: &super::ValueSet) -> bool {
338 if let Some(other) = other.as_key_internal_map() {
339 &self.map == other
340 } else {
341 debug_assert!(false);
342 false
343 }
344 }
345
346 fn merge(&mut self, other: &ValueSet) -> Result<(), OperationError> {
347 let Some(b) = other.as_key_internal_map() else {
348 debug_assert!(false);
349 return Err(OperationError::InvalidValueState);
350 };
351
352 for (k_other, v_other) in b.iter() {
353 if let Some(v_self) = self.map.get_mut(k_other) {
354 if v_other.status > v_self.status {
356 *v_self = v_other.clone();
357 }
358 } else {
359 self.map.insert(k_other.clone(), v_other.clone());
361 }
362 }
363
364 Ok(())
365 }
366
367 fn as_key_internal_map(&self) -> Option<&BTreeMap<KeyId, KeyInternalData>> {
368 Some(&self.map)
369 }
370
371 fn repl_merge_valueset(&self, older: &ValueSet, trim_cid: &Cid) -> Option<ValueSet> {
372 let b = older.as_key_internal_map()?;
373
374 let mut map = self.map.clone();
375
376 for (k_other, v_other) in b.iter() {
377 if let Some(v_self) = map.get_mut(k_other) {
378 if v_other.status > v_self.status {
380 *v_self = v_other.clone();
381 }
382 } else {
383 map.insert(k_other.clone(), v_other.clone());
385 }
386 }
387
388 let mut vs = Box::new(ValueSetKeyInternal { map });
389
390 vs.trim(trim_cid);
391
392 Some(vs)
393 }
394}
395
396#[cfg(test)]
397mod tests {
398 use super::{KeyInternalData, ValueSetKeyInternal};
399 use crate::prelude::*;
400 use crate::value::*;
401
402 #[test]
403 fn test_valueset_key_internal_purge_trim() {
404 let kid = "test".to_string();
405 let usage = KeyUsage::JwsEs256;
406 let valid_from = 0;
407 let status = KeyStatus::Valid;
408 let status_cid = Cid::new_zero();
409 let der = Vec::with_capacity(0);
410
411 let mut vs_a: ValueSet =
412 ValueSetKeyInternal::new(kid.clone(), usage, valid_from, status, status_cid, der);
413
414 let one_cid = Cid::new_count(1);
415
416 vs_a.purge(&one_cid);
418
419 assert_eq!(vs_a.len(), 1);
420
421 let key_internal = vs_a
422 .as_key_internal_map()
423 .and_then(|map| map.get(&kid))
424 .expect("Unable to locate session");
425
426 assert_eq!(key_internal.status, KeyStatus::Revoked);
427 assert_eq!(key_internal.status_cid, one_cid);
428
429 let two_cid = Cid::new_count(2);
431
432 vs_a.trim(&two_cid);
433
434 assert!(vs_a.is_empty());
435 }
436
437 #[test]
438 fn test_valueset_key_internal_merge_left() {
439 let kid = "test".to_string();
440 let usage = KeyUsage::JwsEs256;
441 let valid_from = 0;
442 let status = KeyStatus::Valid;
443 let status_cid = Cid::new_zero();
444 let der = Vec::with_capacity(0);
445
446 let mut vs_a: ValueSet = ValueSetKeyInternal::new(
447 kid.clone(),
448 usage,
449 valid_from,
450 status,
451 status_cid.clone(),
452 der.clone(),
453 );
454
455 let status = KeyStatus::Revoked;
456
457 let vs_b: ValueSet =
458 ValueSetKeyInternal::new(kid.clone(), usage, valid_from, status, status_cid, der);
459
460 vs_a.merge(&vs_b).expect("Failed to merge");
461
462 assert_eq!(vs_a.len(), 1);
463 let key_internal = vs_a
464 .as_key_internal_map()
465 .and_then(|map| map.get(&kid))
466 .expect("Unable to locate session");
467
468 assert_eq!(key_internal.status, KeyStatus::Revoked);
469 }
470
471 #[test]
472 fn test_valueset_key_internal_merge_right() {
473 let kid = "test".to_string();
474 let usage = KeyUsage::JwsEs256;
475 let valid_from = 0;
476 let status = KeyStatus::Valid;
477 let status_cid = Cid::new_zero();
478 let der = Vec::with_capacity(0);
479
480 let vs_a: ValueSet = ValueSetKeyInternal::new(
481 kid.clone(),
482 usage,
483 valid_from,
484 status,
485 status_cid.clone(),
486 der.clone(),
487 );
488
489 let status = KeyStatus::Revoked;
490
491 let mut vs_b: ValueSet =
492 ValueSetKeyInternal::new(kid.clone(), usage, valid_from, status, status_cid, der);
493
494 vs_b.merge(&vs_a).expect("Failed to merge");
495
496 assert_eq!(vs_b.len(), 1);
497
498 let key_internal = vs_b
499 .as_key_internal_map()
500 .and_then(|map| map.get(&kid))
501 .expect("Unable to locate session");
502
503 assert_eq!(key_internal.status, KeyStatus::Revoked);
504 }
505
506 #[test]
507 fn test_valueset_key_internal_repl_merge_left() {
508 let kid = "test".to_string();
509 let usage = KeyUsage::JwsEs256;
510 let valid_from = 0;
511 let status = KeyStatus::Valid;
512 let zero_cid = Cid::new_zero();
513 let one_cid = Cid::new_count(1);
514 let two_cid = Cid::new_count(2);
515 let der = Vec::with_capacity(0);
516
517 let kid_2 = "key_2".to_string();
518
519 let vs_a: ValueSet = ValueSetKeyInternal::from_key_iter(
520 [
521 (
522 kid.clone(),
523 KeyInternalData {
524 usage,
525 valid_from,
526 status,
527 status_cid: two_cid.clone(),
528 der: der.clone(),
529 },
530 ),
531 (
532 kid_2.clone(),
533 KeyInternalData {
534 usage,
535 valid_from,
536 status: KeyStatus::Revoked,
537 status_cid: zero_cid.clone(),
538 der: der.clone(),
539 },
540 ),
541 ]
542 .into_iter(),
543 )
544 .expect("Failed to build valueset");
545
546 let status = KeyStatus::Revoked;
547
548 let vs_b: ValueSet =
549 ValueSetKeyInternal::new(kid.clone(), usage, valid_from, status, two_cid, der);
550
551 let vs_r = vs_a
552 .repl_merge_valueset(&vs_b, &one_cid)
553 .expect("Failed to merge");
554
555 let key_internal_map = vs_r.as_key_internal_map().expect("Unable to access map");
556
557 eprintln!("{:?}", key_internal_map);
558
559 assert_eq!(vs_r.len(), 1);
560
561 let key_internal = key_internal_map.get(&kid).expect("Unable to access key");
562
563 assert_eq!(key_internal.status, KeyStatus::Revoked);
564
565 assert!(!key_internal_map.contains_key(&kid_2));
567 }
568
569 #[test]
570 fn test_valueset_key_internal_repl_merge_right() {
571 let kid = "test".to_string();
572 let usage = KeyUsage::JwsEs256;
573 let valid_from = 0;
574 let status = KeyStatus::Valid;
575 let zero_cid = Cid::new_zero();
576 let one_cid = Cid::new_count(1);
577 let two_cid = Cid::new_count(2);
578 let der = Vec::with_capacity(0);
579
580 let kid_2 = "key_2".to_string();
581
582 let vs_a: ValueSet = ValueSetKeyInternal::from_key_iter(
583 [
584 (
585 kid.clone(),
586 KeyInternalData {
587 usage,
588 valid_from,
589 status,
590 status_cid: two_cid.clone(),
591 der: der.clone(),
592 },
593 ),
594 (
595 kid_2.clone(),
596 KeyInternalData {
597 usage,
598 valid_from,
599 status: KeyStatus::Revoked,
600 status_cid: zero_cid.clone(),
601 der: der.clone(),
602 },
603 ),
604 ]
605 .into_iter(),
606 )
607 .expect("Failed to build valueset");
608
609 let status = KeyStatus::Revoked;
610
611 let vs_b: ValueSet =
612 ValueSetKeyInternal::new(kid.clone(), usage, valid_from, status, two_cid, der);
613
614 let vs_r = vs_b
615 .repl_merge_valueset(&vs_a, &one_cid)
616 .expect("Failed to merge");
617
618 let key_internal_map = vs_r.as_key_internal_map().expect("Unable to access map");
619
620 eprintln!("{:?}", key_internal_map);
621
622 assert_eq!(vs_r.len(), 1);
623
624 let key_internal = key_internal_map.get(&kid).expect("Unable to access key");
625
626 assert_eq!(key_internal.status, KeyStatus::Revoked);
627
628 assert!(!key_internal_map.contains_key(&kid_2));
630 }
631
632 #[test]
633 fn test_scim_key_internal() {
634 let kid = "test".to_string();
635 let usage = KeyUsage::JwsEs256;
636 let valid_from = 0;
637 let status = KeyStatus::Valid;
638 let status_cid = Cid::new_zero();
639 let der = Vec::with_capacity(0);
640
641 let vs: ValueSet =
642 ValueSetKeyInternal::new(kid.clone(), usage, valid_from, status, status_cid, der);
643
644 let data = r#"
645[
646 {
647 "keyId": "test",
648 "status": "valid",
649 "usage": "jws_es256",
650 "validFrom": "1970-01-01T00:00:00Z"
651 }
652]
653 "#;
654 crate::valueset::scim_json_reflexive(&vs, data);
655 }
656}