in key-rotation/src/main/scala/CryptoConfForRotation.scala [24:89]
@main def run(settingsFilePath: String) = {
val base64Encoder = Base64.getEncoder
generateForExistingConf(settingsFilePath)
def generateForExistingConf(pathForCurrentConf: String): Unit = {
val keyPairGenerator: KeyPairGenerator = {
val g = KeyPairGenerator.getInstance("RSA")
g.initialize(4096)
g
}
val newTargetKeyPair = {
val kp = keyPairGenerator.generateKeyPair
KeyPair(kp.getPublic, kp.getPrivate)
}
println(s"Loading current conf from $pathForCurrentConf")
val loader = new Settings.Loader(
_ => new FileInputStream(pathForCurrentConf),
""
)
val originalConfigOrFailure = loader.loadAndParseSettingsMap().flatMap(CryptoConf.SettingsReader(_).signingAndVerificationConf)
val originalConf = originalConfigOrFailure match {
case Right(conf) => conf
case Left(failure) =>
Console.err.println(failure.description)
sys.exit(1)
}
val rotationInProgressConf = originalConf.copy(activeKeyPair = newTargetKeyPair, alsoAccepted = Seq(originalConf.activePublicKey))
val tempDirWithPrefix = Files.createTempDirectory("panda-rotation")
val timeStamp = s"Generated at ${ZonedDateTime.now(UTC).truncatedTo(SECONDS).format(ISO_LOCAL_DATE_TIME)}Z"
println(s"$timeStamp - files are in:\n\n$tempDirWithPrefix\n")
for {
((description, conf), index) <- Seq(
"upcoming" -> originalConf.copy(alsoAccepted = Seq(newTargetKeyPair.publicKey)),
"in-progress" -> rotationInProgressConf,
"complete" -> rotationInProgressConf.copy(alsoAccepted = Nil)
).zipWithIndex
} {
val filename = s"${1 + index}.rotation-$description.settings"
println(filename)
Files.writeString(tempDirWithPrefix.resolve(filename), s"# $filename - $timeStamp\n\n${textFor(conf)}")
}
}
def textFor(conf: SigningAndVerification): String = {
def base64For(key: Key): String = base64Encoder.encodeToString(key.getEncoded)
val keyValues = Seq(
"privateKey" -> base64For(conf.activePrivateKey),
"publicKey" -> base64For(conf.activePublicKey)
) ++ conf.alsoAccepted.zipWithIndex.map {
case (key, index) => s"alsoAccept.$index.publicKey" -> base64For(key)
}
assert(CryptoConf.SettingsReader(keyValues.toMap).signingAndVerificationConf == Right(conf))
keyValues.map {
case (key, value) => s"$key=$value\n"
}.mkString("\n")
}
}