#!/usr/bin/env perl

# A quick script to help explore what certificate lifetimes mean for
# rollover events in the CA.  Plug in maximum certificate liftimes and
# it will show you what types of events you have to contend with.

use warnings;
use strict;

# what's the longest a leaf cert is good for (years)?
my $max_leaf = 5;
# what's the longest an intermediate cert is good for (years)?
my $max_int = $max_leaf + 2;
# what's the longest a root cert is good for (years)?
my $max_root = 29;

# how long should server/scep certs last?  Recommend to match however
# often you roll the intermediates
my $max_server = $max_int - $max_leaf;

# what year are you starting in?
my $year = (localtime)[5] + 1900;

# how many years into the future do you want to print?
my $range = $max_root * 2;

#####################################
### don't need to edit below here ###
#####################################

# how often must we start issuing new certs?
my $new_int = $max_int - $max_leaf;
my $new_root = $max_root - $max_int;

# Here's a fun one: clients that are configured with a particular
# intermediate will never learn about "future" intermediate certs.
# Thus, you have to keep using a previous intermediate when a new root
# is issued until all the certificates on that intermediate have
# expired.  We keep track of which intermediate signs the server certs
# for this purpose.
my $prev_int = 0;
my $prev_int_until = 0;

# keep track of how long until we deconfigure an old root
my $root_prev = -1;

# Version numbers for the root/intermediates
my $r = 0;
my $i = 0;

print <<"EOF";
Showing certificate events for years $year + $range
         Root CA max lifetime: $max_root
 Intermediate CA max lifetime: $max_int
Leaf certificate max lifetime: $max_leaf

EOF

for my $y (0 .. $range) {
  my $cy = $y + $year;
  print "$cy:\n";
  if ($prev_int_until && $y >= $prev_int_until) {
    $prev_int_until = 0;
  }
  if ($root_prev == $y) {
    printf "     Remove old root r%02d\n", ($r-1);
  }
  if ($y % $new_root == 0) {
    $prev_int = $i;
    $prev_int_until = $y + $max_leaf unless $y == 0;
    $root_prev = $y + $max_leaf unless $y == 0;
    $r++;
    printf "     New root r%02d %d-%d\n",
      $r, $cy, ($cy+$max_root);
  }
  if ($y % $new_int == 0) {
    $i++;
    printf "     r%02d signs new int i%02d %d-%d\n",
      $r, $i, $cy, ($cy+$max_int);
  }
  if ($prev_int_until) {
    printf "     i%02d signs server\n", $prev_int;
    printf "     i%02d signs leaf and scep\n", $i;
  }
  else {
    printf "     i%02d signs server, leaf, and scep\n", $i;
  }

}
