From 053248d1baa2708b821591e3cfc8bff92e3061d2 Mon Sep 17 00:00:00 2001 From: Matthew Dickinson Date: Tue, 31 Oct 2023 20:22:37 +0000 Subject: [PATCH] [util-security] add deserializeAndFilterOutInvalidCertificates Problem/Solution: Add `deserializeAndFilterOutInvalidCertificates` which wraps the `deserializeX509` call in a `Try` (as `certificate.checkValidity()` can return `CertificateExpiredException`, `CertificateNotYetValidException`) and separates out any expired or not yet valid certificates detected. JIRA Issues: PSEC-16977 Differential Revision: https://phabricator.twitter.biz/D1107551 --- CHANGELOG.rst | 3 +++ .../X509CertificateDeserializer.scala | 24 +++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 2c735556bf..dbd628b262 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -14,6 +14,9 @@ Runtime Behavior Changes * util: Bump version of Jackson to 2.14.3. ``PHAB_ID=D1069160`` +* util-securty: Add `deserializeAndFilterOutInvalidCertificates` Which wraps + the `deserializeX509` call in a Try. ``PHAB_ID=D1107551`` + 22.12.0 ------- diff --git a/util-security/src/main/scala/com/twitter/util/security/X509CertificateDeserializer.scala b/util-security/src/main/scala/com/twitter/util/security/X509CertificateDeserializer.scala index 9b2b36f34d..48ab081d3e 100644 --- a/util-security/src/main/scala/com/twitter/util/security/X509CertificateDeserializer.scala +++ b/util-security/src/main/scala/com/twitter/util/security/X509CertificateDeserializer.scala @@ -52,4 +52,28 @@ object X509CertificateDeserializer { messages.map(_.map(deserializeX509)) } + + /** + * Deserializes an [[InputStream]] that contains PEM-encoded X.509 + * Certificates. Wraps the `deserializeX509` call in a Try + * (as `certificate.checkValidity()` can return CertificateExpiredException, CertificateNotYetValidException) + * and separates out any expired or not yet valid certificates detected. + * + * Closes the InputStream once it has finished reading. + */ + def deserializeAndFilterOutInvalidCertificates( + rawPem: String, + name: String + ): (Seq[Try[X509Certificate]], Seq[Try[X509Certificate]]) = { + val pemBytes = new PemBytes(rawPem, name) + val messages: Try[Seq[Array[Byte]]] = pemBytes + .readMessages(MessageType) + messages + .map(certs => { + certs + .map(cert => { + Try(deserializeX509(cert)) + }).partition(_.isReturn) + }).get() + } }