-
Notifications
You must be signed in to change notification settings - Fork 580
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
util-security: Introduce X509CrlFile for Loading CRLs
Summary: Problem / Solution CRL (Certificate Revocation List) files should be as easy to load as X.509v3 certificate files. This commit adds support to util-security for loading CRL files via `X509CrlFile`. JIRA Issues: CSL-5819 Differential Revision: https://phabricator.twitter.biz/D127700
- Loading branch information
1 parent
073c2d3
commit 32d8cc8
Showing
6 changed files
with
158 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
44 changes: 44 additions & 0 deletions
44
util-security/src/main/scala/com/twitter/util/security/X509CrlFile.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
package com.twitter.util.security | ||
|
||
import com.twitter.logging.Logger | ||
import com.twitter.util.Try | ||
import com.twitter.util.security.X509CrlFile._ | ||
import java.io.{ByteArrayInputStream, File} | ||
import java.security.cert.{CertificateFactory, X509CRL} | ||
|
||
/** | ||
* A representation of an X.509 Certificate Revocation List (CRL) | ||
* PEM-encoded and stored in a file. | ||
* | ||
* @example | ||
* -----BEGIN X509 CRL----- | ||
* base64encodedbytes | ||
* -----END X509 CRL----- | ||
*/ | ||
class X509CrlFile(file: File) { | ||
|
||
private[this] def logException(ex: Throwable): Unit = | ||
log.warning(s"X509Crl (${file.getName}) failed to load: ${ex.getMessage}.") | ||
|
||
def readX509Crl(): Try[X509CRL] = { | ||
val pemFile = new PemFile(file) | ||
pemFile | ||
.readMessage(MessageType) | ||
.map(generateX509Crl) | ||
.onFailure(logException) | ||
} | ||
|
||
} | ||
|
||
private object X509CrlFile { | ||
private val MessageType: String = "X509 CRL" | ||
|
||
private val log = Logger.get("com.twitter.util.security") | ||
|
||
private def generateX509Crl(decodedMessage: Array[Byte]): X509CRL = { | ||
val certFactory = CertificateFactory.getInstance("X.509") | ||
certFactory | ||
.generateCRL(new ByteArrayInputStream(decodedMessage)) | ||
.asInstanceOf[X509CRL] | ||
} | ||
} |
14 changes: 14 additions & 0 deletions
14
util-security/src/test/resources/crl/csl-intermediate-garbage.crl
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
-----BEGIN X509 CRL----- | ||
MIIDKTCCARECAQEwDQYJKoZIhvcNAQELBQAwgZUxCzAJBgNVBAYTAlVTMRMwEQYD | ||
VQQIDApDYWxpZm9ybmlhMRAwDgYDVQQKDAdUd2l0dGVyMR8wHQYDVQQLDBZDb3Jl | ||
IFN5c3RlbXMgTGlicmFyaWVzMRwwGgYDVQQDDBNDU0wgSW50ZXJtZWRpYXRlIENB | ||
MSAwHgYJKoZIhvcNAQkBFhFyeWFub0B0d2l0dGVyLmNvbRcNMTgwMTEyMTkzMTQ0 | ||
1jNNCn+9h0GfQniDxxE8Vd7zolky7uO5lLQHzLEuqXrCein9TqKTgE4X54XrJrZH | ||
BMMKGYomoPqLhoocqHMSyJs0a0PYlbvL6VIFRpWdaczeZZrP5/wAsbUs6bNsprvZ | ||
81Nx7XFPTo746aRyMFXUOOJQMfS7hu38sxSBk04+jTY/+3dn+VrGIcRCXB5i2HjZ | ||
kdkHcBXPib/Hl5fKIWAIa0FDJ6Kq6+6iLqX+WjW35sQW3V81ZAi34vTagtPj9TcO | ||
b9SdxkkHO0VBGXzKd0aBrdQNKe/yrNNAz7l1/RbUp8CrIG58GDoXs+wr3yubSUwU | ||
WNoMe+STHFIQD6o1AQkmbXFqaRO71L/sTbTQzzlraqugo9bv1T4RZOIbENexNX50 | ||
nF/B4RRNM38+YgcXEc7TegCh866WAsiIfO4ejtveGNigQqYbDfmsZknDlSqthRxi | ||
Rdhk0MG4Vuo/wBo5/F5JIm3viNj2SLE2LxEKpFAEneEXhkWKhCDmRjas0F/5 | ||
-----END X509 CRL----- |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
-----BEGIN X509 CRL----- | ||
MIIDKTCCARECAQEwDQYJKoZIhvcNAQELBQAwgZUxCzAJBgNVBAYTAlVTMRMwEQYD | ||
VQQIDApDYWxpZm9ybmlhMRAwDgYDVQQKDAdUd2l0dGVyMR8wHQYDVQQLDBZDb3Jl | ||
IFN5c3RlbXMgTGlicmFyaWVzMRwwGgYDVQQDDBNDU0wgSW50ZXJtZWRpYXRlIENB | ||
MSAwHgYJKoZIhvcNAQkBFhFyeWFub0B0d2l0dGVyLmNvbRcNMTgwMTEyMTkzMTQ0 | ||
WhcNMTgwMjExMTkzMTQ0WjAVMBMCAhAMFw0xODAxMTIxOTMxMjFaoDAwLjAfBgNV | ||
HSMEGDAWgBRaEYAYDZMHjVdH+tBvLkOSFMKF8TALBgNVHRQEBAICEAEwDQYJKoZI | ||
hvcNAQELBQADggIBAKzuybkOzirP09GhJpZ86gdkL/uB1TF8SlMLeFEZCr/Ng5sm | ||
1jNNCn+9h0GfQniDxxE8Vd7zolky7uO5lLQHzLEuqXrCein9TqKTgE4X54XrJrZH | ||
BMMKGYomoPqLhoocqHMSyJs0a0PYlbvL6VIFRpWdaczeZZrP5/wAsbUs6bNsprvZ | ||
81Nx7XFPTo746aRyMFXUOOJQMfS7hu38sxSBk04+jTY/+3dn+VrGIcRCXB5i2HjZ | ||
p82AdrUQQjnsOyIlUgGOjv6ayzMro7c/FWCfLqqbD6sViuAoXWU2ODKjDqeNlMhq | ||
vVakF8iDSNLYXVbxOdnTk+/yw1h1SFmBnpF64xBGqWp4bda3mvwBzhD/pezQa2M7 | ||
kdkHcBXPib/Hl5fKIWAIa0FDJ6Kq6+6iLqX+WjW35sQW3V81ZAi34vTagtPj9TcO | ||
b9SdxkkHO0VBGXzKd0aBrdQNKe/yrNNAz7l1/RbUp8CrIG58GDoXs+wr3yubSUwU | ||
WNoMe+STHFIQD6o1AQkmbXFqaRO71L/sTbTQzzlraqugo9bv1T4RZOIbENexNX50 | ||
nF/B4RRNM38+YgcXEc7TegCh866WAsiIfO4ejtveGNigQqYbDfmsZknDlSqthRxi | ||
Rdhk0MG4Vuo/wBo5/F5JIm3viNj2SLE2LxEKpFAEneEXhkWKhCDmRjas0F/5 | ||
-----END X509 CRL----- |
66 changes: 66 additions & 0 deletions
66
util-security/src/test/scala/com/twitter/util/security/X509CrlFileTest.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
package com.twitter.util.security | ||
|
||
import com.twitter.io.TempFile | ||
import com.twitter.util.Try | ||
import java.io.File | ||
import java.security.cert.{CRLException, X509CRL} | ||
import org.scalatest.FunSuite | ||
|
||
class X509CrlFileTest extends FunSuite { | ||
|
||
private[this] val assertLogMessage = | ||
PemFileTestUtils.assertLogMessage("X509Crl") _ | ||
|
||
private[this] def assertCrlException(tryCrl: Try[X509CRL]): Unit = | ||
PemFileTestUtils.assertException[CRLException, X509CRL](tryCrl) | ||
|
||
private[this] val readCrlFromFile: File => Try[X509CRL] = | ||
(tempFile) => { | ||
val crlFile = new X509CrlFile(tempFile) | ||
crlFile.readX509Crl() | ||
} | ||
|
||
test("File path doesn't exist") { | ||
PemFileTestUtils.testFileDoesntExist("X509Crl", readCrlFromFile) | ||
} | ||
|
||
test("File path isn't a file") { | ||
PemFileTestUtils.testFilePathIsntFile("X509Crl", readCrlFromFile) | ||
} | ||
|
||
test("File isn't a crl") { | ||
PemFileTestUtils.testEmptyFile[InvalidPemFormatException, X509CRL]( | ||
"X509Crl", | ||
readCrlFromFile | ||
) | ||
} | ||
|
||
test("File is garbage") { | ||
val handler = PemFileTestUtils.newHandler() | ||
// Lines were manually deleted from a real crl file | ||
val tempFile = TempFile.fromResourcePath("/crl/csl-intermediate-garbage.crl") | ||
// deleteOnExit is handled by TempFile | ||
|
||
val crlFile = new X509CrlFile(tempFile) | ||
val tryCrl = crlFile.readX509Crl() | ||
|
||
assertLogMessage(handler.get, tempFile.getName, "Incomplete BER/DER data.") | ||
assertCrlException(tryCrl) | ||
} | ||
|
||
test("File is a Certificate Revocation List") { | ||
val tempFile = TempFile.fromResourcePath("/crl/csl-intermediate.crl") | ||
// deleteOnExit is handled by TempFile | ||
|
||
val crlFile = new X509CrlFile(tempFile) | ||
val tryCrl = crlFile.readX509Crl() | ||
|
||
assert(tryCrl.isReturn) | ||
val crl = tryCrl.get() | ||
|
||
val principalInfo = new X500PrincipalInfo(crl.getIssuerX500Principal) | ||
assert(principalInfo.organizationalUnitName.isDefined) | ||
assert(principalInfo.organizationalUnitName.get == "Core Systems Libraries") | ||
} | ||
|
||
} |