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