1 use std::{cmp::Ordering, collections::HashMap, fmt, ops::Deref, str::FromStr};
2 
3 use chrono::Duration;
4 use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
5 
6 use rpki::repository::{
7     roa::{Roa, RoaBuilder},
8     sigobj::SignedObjectBuilder,
9     x509::Time,
10 };
11 
12 use crate::{
13     commons::{
14         api::{ObjectName, ResourceSet, RoaAggregateKey, RoaDefinition, RoaDefinitionUpdates},
15         crypto::{KrillSigner, SignSupport},
16         error::Error,
17         KrillResult,
18     },
19     daemon::{
20         ca::events::RoaUpdates,
21         ca::CertifiedKey,
22         config::{Config, IssuanceTimingConfig},
23     },
24 };
25 
26 //------------ RouteAuthorization ------------------------------------------
27 
28 /// This type defines a prefix and optional maximum length (other than the
29 /// prefix length) which is to be authorized for the given origin ASN.
30 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
31 pub struct RouteAuthorization(RoaDefinition);
32 
33 impl fmt::Display for RouteAuthorization {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result34     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
35         self.0.fmt(f)
36     }
37 }
38 
39 impl RouteAuthorization {
new(definition: RoaDefinition) -> Self40     pub fn new(definition: RoaDefinition) -> Self {
41         RouteAuthorization(definition)
42     }
43 
explicit_length(self) -> Self44     pub fn explicit_length(self) -> Self {
45         RouteAuthorization(self.0.explicit_max_length())
46     }
47 }
48 
49 impl AsRef<RoaDefinition> for RouteAuthorization {
as_ref(&self) -> &RoaDefinition50     fn as_ref(&self) -> &RoaDefinition {
51         &self.0
52     }
53 }
54 
55 impl Deref for RouteAuthorization {
56     type Target = RoaDefinition;
57 
deref(&self) -> &Self::Target58     fn deref(&self) -> &Self::Target {
59         &self.0
60     }
61 }
62 
63 /// Ordering is based on the ordering implemented by RoaDefinition
64 impl Ord for RouteAuthorization {
cmp(&self, other: &Self) -> Ordering65     fn cmp(&self, other: &Self) -> Ordering {
66         self.0.cmp(&other.0)
67     }
68 }
69 
70 impl PartialOrd for RouteAuthorization {
partial_cmp(&self, other: &Self) -> Option<Ordering>71     fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
72         Some(self.cmp(other))
73     }
74 }
75 
76 /// We use RouteAuthorization as (json) map keys and therefore we need it
77 /// to be serializable to a single simple string.
78 impl Serialize for RouteAuthorization {
serialize<S>(&self, s: S) -> Result<S::Ok, S::Error> where S: Serializer,79     fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>
80     where
81         S: Serializer,
82     {
83         self.to_string().serialize(s)
84     }
85 }
86 
87 /// We use RouteAuthorization as (json) map keys and therefore we need it
88 /// to be deserializable from a single simple string.
89 impl<'de> Deserialize<'de> for RouteAuthorization {
deserialize<D>(d: D) -> Result<RouteAuthorization, D::Error> where D: Deserializer<'de>,90     fn deserialize<D>(d: D) -> Result<RouteAuthorization, D::Error>
91     where
92         D: Deserializer<'de>,
93     {
94         let string = String::deserialize(d)?;
95         let def = RoaDefinition::from_str(string.as_str()).map_err(de::Error::custom)?;
96         Ok(RouteAuthorization(def))
97     }
98 }
99 
100 impl From<RoaDefinition> for RouteAuthorization {
from(def: RoaDefinition) -> Self101     fn from(def: RoaDefinition) -> Self {
102         RouteAuthorization(def)
103     }
104 }
105 
106 impl From<RouteAuthorization> for RoaDefinition {
from(auth: RouteAuthorization) -> Self107     fn from(auth: RouteAuthorization) -> Self {
108         auth.0
109     }
110 }
111 
112 //------------ RouteAuthorizationUpdates -----------------------------------
113 
114 ///
115 #[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
116 pub struct RouteAuthorizationUpdates {
117     added: Vec<RouteAuthorization>,
118     removed: Vec<RouteAuthorization>,
119 }
120 
121 impl Default for RouteAuthorizationUpdates {
default() -> Self122     fn default() -> Self {
123         RouteAuthorizationUpdates {
124             added: vec![],
125             removed: vec![],
126         }
127     }
128 }
129 
130 impl RouteAuthorizationUpdates {
131     /// Use this when receiving updates through the API, until the v0.7 ROA clean up can be deprecated,
132     /// which would imply that pre-0.7 versions can not longer be directly updated.
into_explicit(self) -> Self133     pub fn into_explicit(self) -> Self {
134         let added = self.added.into_iter().map(|a| a.explicit_length()).collect();
135         let removed = self.removed.into_iter().map(|r| r.explicit_length()).collect();
136         RouteAuthorizationUpdates { added, removed }
137     }
138 
new(added: Vec<RouteAuthorization>, removed: Vec<RouteAuthorization>) -> Self139     pub fn new(added: Vec<RouteAuthorization>, removed: Vec<RouteAuthorization>) -> Self {
140         RouteAuthorizationUpdates { added, removed }
141     }
142 
added(&self) -> &Vec<RouteAuthorization>143     pub fn added(&self) -> &Vec<RouteAuthorization> {
144         &self.added
145     }
146 
removed(&self) -> &Vec<RouteAuthorization>147     pub fn removed(&self) -> &Vec<RouteAuthorization> {
148         &self.removed
149     }
150 
unpack(self) -> (Vec<RouteAuthorization>, Vec<RouteAuthorization>)151     pub fn unpack(self) -> (Vec<RouteAuthorization>, Vec<RouteAuthorization>) {
152         (self.added, self.removed)
153     }
154 
filter(&self, resources: &ResourceSet) -> Self155     pub fn filter(&self, resources: &ResourceSet) -> Self {
156         let added = self
157             .added()
158             .iter()
159             .filter(|auth| resources.contains_roa_address(&auth.as_roa_ip_address()))
160             .cloned()
161             .collect();
162 
163         let removed = self
164             .removed()
165             .iter()
166             .filter(|auth| resources.contains_roa_address(&auth.as_roa_ip_address()))
167             .cloned()
168             .collect();
169 
170         RouteAuthorizationUpdates { added, removed }
171     }
172 
affected_prefixes(&self) -> ResourceSet173     pub fn affected_prefixes(&self) -> ResourceSet {
174         let mut resources = ResourceSet::default();
175         for roa in &self.added {
176             resources = resources.union(&roa.prefix().into());
177         }
178         for roa in &self.removed {
179             resources = resources.union(&roa.prefix().into());
180         }
181         resources
182     }
183 }
184 
185 impl From<RoaDefinitionUpdates> for RouteAuthorizationUpdates {
from(definitions: RoaDefinitionUpdates) -> Self186     fn from(definitions: RoaDefinitionUpdates) -> Self {
187         let (added, removed) = definitions.unpack();
188         let mut added: Vec<RouteAuthorization> = added.into_iter().map(RoaDefinition::into).collect();
189         added.sort();
190         added.dedup();
191 
192         let mut removed: Vec<RouteAuthorization> = removed.into_iter().map(RoaDefinition::into).collect();
193         removed.sort();
194         removed.dedup();
195 
196         RouteAuthorizationUpdates { added, removed }
197     }
198 }
199 
200 impl fmt::Display for RouteAuthorizationUpdates {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result201     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
202         if !self.added.is_empty() {
203             write!(f, "added:")?;
204             for a in &self.added {
205                 write!(f, " {}", a)?;
206             }
207             write!(f, " ")?;
208         }
209         if !self.removed.is_empty() {
210             write!(f, "removed:")?;
211             for r in &self.removed {
212                 write!(f, " {}", r)?;
213             }
214         }
215         Ok(())
216     }
217 }
218 
219 //------------ Routes ------------------------------------------------------
220 
221 /// The current authorizations and corresponding meta-information for a CA.
222 #[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
223 pub struct Routes {
224     map: HashMap<RouteAuthorization, RouteInfo>,
225 }
226 
227 impl Default for Routes {
default() -> Self228     fn default() -> Self {
229         Routes { map: HashMap::new() }
230     }
231 }
232 
233 impl Routes {
filter(&self, resources: &ResourceSet) -> Self234     pub fn filter(&self, resources: &ResourceSet) -> Self {
235         let filtered = self
236             .map
237             .iter()
238             .flat_map(|(auth, info)| {
239                 if resources.contains_roa_address(&auth.as_roa_ip_address()) {
240                     Some((*auth, info.clone()))
241                 } else {
242                     None
243                 }
244             })
245             .collect();
246         Routes { map: filtered }
247     }
248 
all(&self) -> impl Iterator<Item = (&RouteAuthorization, &RouteInfo)>249     pub fn all(&self) -> impl Iterator<Item = (&RouteAuthorization, &RouteInfo)> {
250         self.map.iter()
251     }
252 
authorizations(&self) -> impl Iterator<Item = &RouteAuthorization>253     pub fn authorizations(&self) -> impl Iterator<Item = &RouteAuthorization> {
254         self.map.keys()
255     }
256 
into_authorizations(self) -> Vec<RouteAuthorization>257     pub fn into_authorizations(self) -> Vec<RouteAuthorization> {
258         self.map.into_iter().map(|(auth, _)| auth).collect()
259     }
260 
as_aggregates(&self) -> HashMap<RoaAggregateKey, Vec<RouteAuthorization>>261     pub fn as_aggregates(&self) -> HashMap<RoaAggregateKey, Vec<RouteAuthorization>> {
262         let mut map: HashMap<RoaAggregateKey, Vec<RouteAuthorization>> = HashMap::new();
263 
264         for auth in self.map.keys() {
265             let key = RoaAggregateKey::new(auth.asn(), None);
266             if let Some(authorizations) = map.get_mut(&key) {
267                 authorizations.push(*auth);
268                 authorizations.sort();
269             } else {
270                 map.insert(key, vec![*auth]);
271             }
272         }
273         map
274     }
275 
len(&self) -> usize276     pub fn len(&self) -> usize {
277         self.map.len()
278     }
279 
is_empty(&self) -> bool280     pub fn is_empty(&self) -> bool {
281         self.map.is_empty()
282     }
283 
info(&self, auth: &RouteAuthorization) -> Option<&RouteInfo>284     pub fn info(&self, auth: &RouteAuthorization) -> Option<&RouteInfo> {
285         self.map.get(auth)
286     }
287 
has(&self, auth: &RouteAuthorization) -> bool288     pub fn has(&self, auth: &RouteAuthorization) -> bool {
289         self.map.contains_key(auth)
290     }
291 
292     /// Adds a new authorization, or updates an existing one.
add(&mut self, auth: RouteAuthorization)293     pub fn add(&mut self, auth: RouteAuthorization) {
294         self.map.insert(auth, RouteInfo::default());
295     }
296 
297     /// Removes an authorization
remove(&mut self, auth: &RouteAuthorization) -> bool298     pub fn remove(&mut self, auth: &RouteAuthorization) -> bool {
299         self.map.remove(auth).is_some()
300     }
301 }
302 
303 //------------ RouteInfo ---------------------------------------------------
304 
305 /// Meta-information about a configured RouteAuthorization.
306 #[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
307 pub struct RouteInfo {
308     since: Time, // authorization first added by user
309 
310     #[serde(skip_serializing_if = "Option::is_none")]
311     group: Option<u32>,
312 }
313 
314 impl Default for RouteInfo {
default() -> Self315     fn default() -> Self {
316         RouteInfo {
317             since: Time::now(),
318             group: None,
319         }
320     }
321 }
322 
323 //------------ AggregateRoaInfo --------------------------------------------
324 
325 #[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
326 pub struct AggregateRoaInfo {
327     authorizations: Vec<RouteAuthorization>,
328 
329     #[serde(flatten)]
330     roa: RoaInfo,
331 }
332 
333 impl AggregateRoaInfo {
new(authorizations: Vec<RouteAuthorization>, roa: RoaInfo) -> Self334     pub fn new(authorizations: Vec<RouteAuthorization>, roa: RoaInfo) -> Self {
335         AggregateRoaInfo { authorizations, roa }
336     }
337 
authorizations(&self) -> &Vec<RouteAuthorization>338     pub fn authorizations(&self) -> &Vec<RouteAuthorization> {
339         &self.authorizations
340     }
341 
roa_info(&self) -> &RoaInfo342     pub fn roa_info(&self) -> &RoaInfo {
343         &self.roa
344     }
345 }
346 
347 impl AsRef<RoaInfo> for AggregateRoaInfo {
as_ref(&self) -> &RoaInfo348     fn as_ref(&self) -> &RoaInfo {
349         &self.roa
350     }
351 }
352 
353 //------------ RoaInfo -----------------------------------------------------
354 
355 #[derive(Clone, Debug, Deserialize, Serialize)]
356 pub struct RoaInfo {
357     roa: Roa,
358     since: Time, // first ROA in RC created
359 }
360 
361 impl RoaInfo {
new(roa: Roa, since: Time) -> Self362     pub fn new(roa: Roa, since: Time) -> Self {
363         RoaInfo { roa, since }
364     }
365 
new_roa(roa: Roa) -> Self366     pub fn new_roa(roa: Roa) -> Self {
367         RoaInfo {
368             roa,
369             since: Time::now(),
370         }
371     }
372 
updated_roa(old: &RoaInfo, roa: Roa) -> Self373     pub fn updated_roa(old: &RoaInfo, roa: Roa) -> Self {
374         RoaInfo { roa, since: old.since }
375     }
376 
roa(&self) -> &Roa377     pub fn roa(&self) -> &Roa {
378         &self.roa
379     }
380 
since(&self) -> Time381     pub fn since(&self) -> Time {
382         self.since
383     }
384 
expires(&self) -> Time385     pub fn expires(&self) -> Time {
386         self.roa.cert().validity().not_after()
387     }
388 }
389 
390 impl PartialEq for RoaInfo {
eq(&self, other: &Self) -> bool391     fn eq(&self, other: &Self) -> bool {
392         self.roa.to_captured().as_slice() == other.roa.to_captured().as_slice()
393     }
394 }
395 
396 impl Eq for RoaInfo {}
397 
398 //------------ RoaMode -----------------------------------------------------
399 
400 #[derive(Clone, Debug, Eq, PartialEq)]
401 enum RoaMode {
402     Simple,           // below aggregation threshold, and currently simple
403     StopAggregating,  // below de-aggregation threshold, and currently aggregating
404     StartAggregating, // above aggregation threshold, and currently simple
405     Aggregate,        // above de-aggregation threshold, and currently aggregating
406 }
407 
408 //------------ Roas --------------------------------------------------------
409 
410 /// ROAs held by a resource class in a CA.
411 #[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
412 pub struct Roas {
413     #[serde(alias = "inner", skip_serializing_if = "HashMap::is_empty", default = "HashMap::new")]
414     simple: HashMap<RouteAuthorization, RoaInfo>,
415 
416     #[serde(skip_serializing_if = "HashMap::is_empty", default = "HashMap::new")]
417     aggregate: HashMap<RoaAggregateKey, AggregateRoaInfo>,
418 }
419 
420 impl Default for Roas {
default() -> Self421     fn default() -> Self {
422         Roas {
423             simple: HashMap::new(),
424             aggregate: HashMap::new(),
425         }
426     }
427 }
428 
429 impl Roas {
get(&self, auth: &RouteAuthorization) -> Option<&RoaInfo>430     pub fn get(&self, auth: &RouteAuthorization) -> Option<&RoaInfo> {
431         self.simple.get(auth)
432     }
433 
updated(&mut self, updates: RoaUpdates)434     pub fn updated(&mut self, updates: RoaUpdates) {
435         let (updated, removed, aggregate_updated, aggregate_removed) = updates.unpack();
436 
437         for (auth, info) in updated.into_iter() {
438             self.simple.insert(auth, info);
439         }
440 
441         for auth in removed.keys() {
442             self.simple.remove(auth);
443         }
444 
445         for (key, aggregate) in aggregate_updated.into_iter() {
446             self.aggregate.insert(key, aggregate);
447         }
448 
449         for key in aggregate_removed.keys() {
450             self.aggregate.remove(key);
451         }
452     }
453 
454     /// Returns whether ROAs are currently being aggregated. I.e. whether
455     /// there are any aggregated ROAs for which no explicit group number
456     /// was set.
is_currently_aggregating(&self) -> bool457     fn is_currently_aggregating(&self) -> bool {
458         self.aggregate.keys().any(|k| k.group().is_none())
459     }
460 
461     /// Returns the desired RoaMode based on the current situation, and
462     /// the intended changes.
mode(&self, total: usize, de_aggregation_threshold: usize, aggregation_threshold: usize) -> RoaMode463     fn mode(&self, total: usize, de_aggregation_threshold: usize, aggregation_threshold: usize) -> RoaMode {
464         let mode = {
465             if total == 0 {
466                 // if everything will be removed, make sure no strategy change is triggered
467                 if self.is_currently_aggregating() {
468                     RoaMode::Aggregate
469                 } else {
470                     RoaMode::Simple
471                 }
472             } else if self.is_currently_aggregating() {
473                 if total < de_aggregation_threshold {
474                     RoaMode::StopAggregating
475                 } else {
476                     RoaMode::Aggregate
477                 }
478             } else if total > aggregation_threshold {
479                 RoaMode::StartAggregating
480             } else {
481                 RoaMode::Simple
482             }
483         };
484 
485         debug!("Selecting ROA publication mode: {:?}", mode);
486 
487         mode
488     }
489 
490     /// Process authorization updates below the aggregation threshold
update_simple( &self, relevant_routes: &Routes, certified_key: &CertifiedKey, issuance_timing: &IssuanceTimingConfig, signer: &KrillSigner, ) -> KrillResult<RoaUpdates>491     fn update_simple(
492         &self,
493         relevant_routes: &Routes,
494         certified_key: &CertifiedKey,
495         issuance_timing: &IssuanceTimingConfig,
496         signer: &KrillSigner,
497     ) -> KrillResult<RoaUpdates> {
498         let mut roa_updates = RoaUpdates::default();
499 
500         // Add new ROAs
501         for auth in relevant_routes.authorizations() {
502             if !self.simple.contains_key(auth) {
503                 let name = ObjectName::from(auth);
504                 let roa = Self::make_roa(
505                     &[*auth],
506                     &name,
507                     certified_key,
508                     issuance_timing.timing_roa_valid_weeks,
509                     signer,
510                 )?;
511                 let info = RoaInfo::new_roa(roa);
512                 roa_updates.update(*auth, info);
513             }
514         }
515 
516         // Remove surplus ROAs
517         for (auth, info) in self.simple.iter() {
518             if !relevant_routes.has(auth) {
519                 roa_updates.remove(*auth, info.roa().into());
520             }
521         }
522 
523         Ok(roa_updates)
524     }
525 
526     /// Process authorization updates that triggered de-aggregating ROAs
update_stop_aggregating( &self, relevant_routes: &Routes, certified_key: &CertifiedKey, issuance_timing: &IssuanceTimingConfig, signer: &KrillSigner, ) -> KrillResult<RoaUpdates>527     fn update_stop_aggregating(
528         &self,
529         relevant_routes: &Routes,
530         certified_key: &CertifiedKey,
531         issuance_timing: &IssuanceTimingConfig,
532         signer: &KrillSigner,
533     ) -> KrillResult<RoaUpdates> {
534         // First trigger the simple update, this will make sure that all current routes
535         // are added as simple (one prefix) ROAs
536         let mut roa_updates = self.update_simple(relevant_routes, certified_key, issuance_timing, signer)?;
537 
538         // Then remove all aggregate ROAs
539         for (roa_key, aggregate) in self.aggregate.iter() {
540             roa_updates.remove_aggregate(*roa_key, aggregate.roa_info().roa().into());
541         }
542 
543         Ok(roa_updates)
544     }
545 
546     /// Process authorization updates that triggered aggregating ROAs
update_start_aggregating( &self, relevant_routes: &Routes, certified_key: &CertifiedKey, issuance_timing: &IssuanceTimingConfig, signer: &KrillSigner, ) -> KrillResult<RoaUpdates>547     fn update_start_aggregating(
548         &self,
549         relevant_routes: &Routes,
550         certified_key: &CertifiedKey,
551         issuance_timing: &IssuanceTimingConfig,
552         signer: &KrillSigner,
553     ) -> KrillResult<RoaUpdates> {
554         // First trigger the aggregate update, this will make sure that all current routes
555         // are added as aggregate ROAs
556         let mut roa_updates = self.update_aggregate(relevant_routes, certified_key, issuance_timing, signer)?;
557 
558         // Then remove all simple ROAs
559         for (roa_key, roa_info) in self.simple.iter() {
560             debug!("Will remove simple authorization for: {}", roa_key);
561             roa_updates.remove(*roa_key, roa_info.roa().into());
562         }
563 
564         Ok(roa_updates)
565     }
566 
567     /// Process authorization updates in aggregation mode
update_aggregate( &self, relevant_routes: &Routes, certified_key: &CertifiedKey, issuance_timing: &IssuanceTimingConfig, signer: &KrillSigner, ) -> KrillResult<RoaUpdates>568     fn update_aggregate(
569         &self,
570         relevant_routes: &Routes,
571         certified_key: &CertifiedKey,
572         issuance_timing: &IssuanceTimingConfig,
573         signer: &KrillSigner,
574     ) -> KrillResult<RoaUpdates> {
575         let mut roa_updates = RoaUpdates::default();
576 
577         let desired_aggregates = relevant_routes.as_aggregates();
578 
579         debug!("Will create '{}' aggregates", desired_aggregates.len());
580 
581         // Add new ROAs, and update ROAs with changed authorizations
582         for (key, authorizations) in desired_aggregates.iter() {
583             if let Some(existing) = self.aggregate.get(key) {
584                 // check if we need to update
585                 let mut existing_authorizations = existing.authorizations().clone();
586                 existing_authorizations.sort();
587 
588                 if authorizations != &existing_authorizations {
589                     // replace ROA
590                     let aggregate = Self::make_aggregate_roa(
591                         key,
592                         authorizations.clone(),
593                         Some(existing.roa_info()),
594                         certified_key,
595                         issuance_timing,
596                         signer,
597                     )?;
598                     roa_updates.update_aggregate(*key, aggregate);
599                 }
600             } else {
601                 // new ROA
602                 let aggregate = Self::make_aggregate_roa(
603                     key,
604                     authorizations.clone(),
605                     None,
606                     certified_key,
607                     issuance_timing,
608                     signer,
609                 )?;
610                 roa_updates.update_aggregate(*key, aggregate);
611             }
612         }
613 
614         // Remove surplus ROAs
615         for (key, aggregate) in self.aggregate.iter() {
616             if !desired_aggregates.contains_key(key) {
617                 roa_updates.remove_aggregate(*key, aggregate.roa_info().roa().into());
618             }
619         }
620 
621         Ok(roa_updates)
622     }
623 
624     /// Process updates, return [`RoaUpdates`] and create new ROA objects if
625     /// authorizations change, or if ROAs are about to expire.
update( &self, all_routes: &Routes, certified_key: &CertifiedKey, config: &Config, signer: &KrillSigner, ) -> KrillResult<RoaUpdates>626     pub fn update(
627         &self,
628         all_routes: &Routes,
629         certified_key: &CertifiedKey,
630         config: &Config,
631         signer: &KrillSigner,
632     ) -> KrillResult<RoaUpdates> {
633         let relevant_routes = all_routes.filter(certified_key.incoming_cert().resources());
634 
635         match self.mode(
636             relevant_routes.len(),
637             config.roa_deaggregate_threshold,
638             config.roa_aggregate_threshold,
639         ) {
640             RoaMode::Simple => self.update_simple(&relevant_routes, certified_key, &config.issuance_timing, signer),
641             RoaMode::StopAggregating => {
642                 self.update_stop_aggregating(&relevant_routes, certified_key, &config.issuance_timing, signer)
643             }
644             RoaMode::StartAggregating => {
645                 self.update_start_aggregating(&relevant_routes, certified_key, &config.issuance_timing, signer)
646             }
647             RoaMode::Aggregate => {
648                 self.update_aggregate(&relevant_routes, certified_key, &config.issuance_timing, signer)
649             }
650         }
651     }
652 
653     /// Re-new ROAs before they would expire, or when forced e.g. in case
654     /// ROAs need to be reissued because of a keyroll, or because of a change
655     /// in encoding (like forcing shorter subject names, see issue #700)
renew( &self, force: bool, certified_key: &CertifiedKey, issuance_timing: &IssuanceTimingConfig, signer: &KrillSigner, ) -> KrillResult<RoaUpdates>656     pub fn renew(
657         &self,
658         force: bool,
659         certified_key: &CertifiedKey,
660         issuance_timing: &IssuanceTimingConfig,
661         signer: &KrillSigner,
662     ) -> KrillResult<RoaUpdates> {
663         let mut updates = RoaUpdates::default();
664 
665         let renew_threshold = Time::now() + Duration::weeks(issuance_timing.timing_roa_reissue_weeks_before);
666 
667         for (auth, roa_info) in self.simple.iter() {
668             let name = ObjectName::from(auth);
669             if force || roa_info.expires() < renew_threshold {
670                 let roa = Self::make_roa(
671                     &[*auth],
672                     &name,
673                     certified_key,
674                     issuance_timing.timing_roa_valid_weeks,
675                     signer,
676                 )?;
677                 let roa_info = RoaInfo::updated_roa(roa_info, roa);
678                 updates.update(*auth, roa_info);
679             }
680         }
681 
682         for (roa_key, aggregate) in self.aggregate.iter() {
683             let roa_info = aggregate.roa_info();
684 
685             if force || roa_info.expires() < renew_threshold {
686                 let authorizations = aggregate.authorizations().clone();
687                 let name = ObjectName::from(roa_key);
688                 let new_roa = Self::make_roa(
689                     authorizations.as_slice(),
690                     &name,
691                     certified_key,
692                     issuance_timing.timing_roa_valid_weeks,
693                     signer,
694                 )?;
695                 let new_roa_info = RoaInfo::updated_roa(roa_info, new_roa);
696                 let aggregate = AggregateRoaInfo::new(authorizations, new_roa_info);
697 
698                 updates.update_aggregate(*roa_key, aggregate);
699             }
700         }
701 
702         Ok(updates)
703     }
704 
make_roa( authorizations: &[RouteAuthorization], name: &ObjectName, certified_key: &CertifiedKey, weeks: i64, signer: &KrillSigner, ) -> KrillResult<Roa>705     pub fn make_roa(
706         authorizations: &[RouteAuthorization],
707         name: &ObjectName,
708         certified_key: &CertifiedKey,
709         weeks: i64,
710         signer: &KrillSigner,
711     ) -> KrillResult<Roa> {
712         let incoming_cert = certified_key.incoming_cert();
713         let signing_key = certified_key.key_id();
714 
715         let crl_uri = incoming_cert.crl_uri();
716         let roa_uri = incoming_cert.uri_for_name(name);
717         let aia = incoming_cert.uri();
718 
719         let asn = authorizations
720             .first()
721             .ok_or_else(|| Error::custom("Attempt to create ROA without prefixes"))?
722             .asn();
723 
724         let mut roa_builder = RoaBuilder::new(asn.into());
725 
726         for auth in authorizations {
727             if auth.asn() != asn {
728                 return Err(Error::custom("Attempt to create ROA for multiple ASNs"));
729             }
730             let prefix = auth.prefix();
731             if auth.effective_max_length() > prefix.prefix().addr_len() {
732                 roa_builder.push_addr(prefix.ip_addr(), prefix.addr_len(), auth.max_length());
733             } else {
734                 roa_builder.push_addr(prefix.ip_addr(), prefix.addr_len(), None);
735             }
736         }
737 
738         let mut object_builder = SignedObjectBuilder::new(
739             signer.random_serial()?,
740             SignSupport::sign_validity_weeks(weeks),
741             crl_uri,
742             aia.clone(),
743             roa_uri,
744         );
745         object_builder.set_issuer(Some(incoming_cert.cert().subject().clone()));
746         object_builder.set_signing_time(Some(Time::now()));
747 
748         Ok(signer.sign_roa(roa_builder, object_builder, signing_key)?)
749     }
750 
make_aggregate_roa( key: &RoaAggregateKey, authorizations: Vec<RouteAuthorization>, old_roa: Option<&RoaInfo>, certified_key: &CertifiedKey, issuance_timing: &IssuanceTimingConfig, signer: &KrillSigner, ) -> KrillResult<AggregateRoaInfo>751     pub fn make_aggregate_roa(
752         key: &RoaAggregateKey,
753         authorizations: Vec<RouteAuthorization>,
754         old_roa: Option<&RoaInfo>,
755         certified_key: &CertifiedKey,
756         issuance_timing: &IssuanceTimingConfig,
757         signer: &KrillSigner,
758     ) -> KrillResult<AggregateRoaInfo> {
759         let name = ObjectName::from(key);
760         let roa = Self::make_roa(
761             authorizations.as_slice(),
762             &name,
763             certified_key,
764             issuance_timing.timing_roa_valid_weeks,
765             signer,
766         )?;
767         let info = match old_roa {
768             Some(old_roa) => RoaInfo::updated_roa(old_roa, roa),
769             None => RoaInfo::new_roa(roa),
770         };
771         Ok(AggregateRoaInfo::new(authorizations, info))
772     }
773 }
774 
775 //------------ Tests -------------------------------------------------------
776 
777 #[cfg(test)]
778 mod tests {
779 
780     use super::*;
781     use crate::commons::api::AsNumber;
782 
authorization(s: &str) -> RouteAuthorization783     fn authorization(s: &str) -> RouteAuthorization {
784         let def = RoaDefinition::from_str(s).unwrap();
785         RouteAuthorization(def)
786     }
787 
788     #[test]
serde_route_authorization()789     fn serde_route_authorization() {
790         fn parse_encode_authorization(s: &str) {
791             let auth = authorization(s);
792             let json = serde_json::to_string(&auth).unwrap();
793             assert_eq!(format!("\"{}\"", s), json);
794 
795             let des: RouteAuthorization = serde_json::from_str(&json).unwrap();
796             assert_eq!(des, auth);
797         }
798 
799         parse_encode_authorization("192.168.0.0/16 => 64496");
800         parse_encode_authorization("192.168.0.0/16-24 => 64496");
801         parse_encode_authorization("2001:db8::/32 => 64496");
802         parse_encode_authorization("2001:db8::/32-48 => 64496");
803     }
804 
805     #[test]
routes_as_aggregates()806     fn routes_as_aggregates() {
807         let mut routes = Routes::default();
808         let auth1_1 = authorization("192.168.0.0/16 => 64496");
809         let auth1_2 = authorization("192.168.0.0/16-24 => 64496");
810         let auth1_3 = authorization("2001:db8::/32 => 64496");
811         let auth2_1 = authorization("2001:db8::/32-48 => 64497");
812         routes.add(auth1_1);
813         routes.add(auth1_2);
814         routes.add(auth1_3);
815         routes.add(auth2_1);
816 
817         let aggregates = routes.as_aggregates();
818 
819         assert_eq!(2, aggregates.keys().len());
820 
821         let agg_1 = aggregates
822             .get(&RoaAggregateKey::new(AsNumber::new(64496), None))
823             .unwrap();
824 
825         let mut agg_1_expected = vec![auth1_1, auth1_2, auth1_3];
826         agg_1_expected.sort();
827 
828         assert_eq!(agg_1, &agg_1_expected);
829 
830         let agg_2 = aggregates
831             .get(&RoaAggregateKey::new(AsNumber::new(64497), None))
832             .unwrap();
833 
834         assert_eq!(agg_2, &vec![auth2_1])
835     }
836 }
837