Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
New major release with bug fixes and enhancements. Highlight: - reload TLS certificate Changelog for v4.5.0..v4.6.0 * [2861259b] [maven-release-plugin] prepare for next development iteration * [fd22f60c] xrootd4j: do not release buffer of unconsumed message in AuthenticationHandler * [7924276f] xrootd4j: correct regression in NoAuthenticationProvider * [f2090745] Motivation: * [7d03e489] xrootd4j: support kXR_prefname in kXR_locate request * [c76a766d] build(deps): bump netty-codec-haproxy from 4.1.5.Final to 4.1.86.Final * [6551be9a] xrootd4j: fix bug in goToTLS value * [1ac4ee31] build: update Copyright (C) 2011-2022 to Copyright (C) 2011-2023 * [88922f05] xrootd4j: fix source TLS check for TPC client * [e09debe9] xrootd4j: turn off TLS and ZTN for pre-5+ clients * [555a7500] xrootd4j: fix byte buffer leak in ZTNCredentialUtils * [7abf228d] xrootd4j: provide better info on SSLExceptions * [b62cb25d] core: don't manually update writeIndex in ReadResponse#writeTo * [75ae03b8] standalone: don't use ByteBuffer wrapper for read file chunk * [9f27e279] core: don't allocate AuthenticationRequest buffer from memory pool * [422d1a72] tls: update SSLHandlerFactory to use SSLContext supplier * [8af2965a] [maven-release-plugin] prepare branch 4.6 * [99c727fb] pom: fix license year * [e84edf92] [maven-release-plugin] prepare release v4.6.0 Ticket: #10562 Acked-by: Lea Morschel Target: master Require-book: no Require-notes: yes (cherry picked from commit 030d5ce) Signed-off-by: Tigran Mkrtchyan <tigran.mkrtchyan@desy.de>
- Loading branch information
1 parent
3eeefe0
commit 973a063
Showing
3 changed files
with
205 additions
and
11 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
183 changes: 183 additions & 0 deletions
183
...ache-xrootd/src/test/java/org/dcache/xrootd/plugins/tls/CDCCanlTLSHandlerFactoryTest.java
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,183 @@ | ||
package org.dcache.xrootd.plugins.tls; | ||
|
||
import static java.nio.file.StandardOpenOption.CREATE; | ||
import static java.nio.file.StandardOpenOption.TRUNCATE_EXISTING; | ||
import static java.nio.file.StandardOpenOption.WRITE; | ||
import static org.dcache.xrootd.plugins.tls.CDCCanlTLSHandlerFactory.*; | ||
import static org.dcache.xrootd.plugins.tls.CDCCanlTLSHandlerFactory.OCSP_MODE; | ||
|
||
import static org.hamcrest.MatcherAssert.assertThat; | ||
import static org.junit.Assert.assertNotSame; | ||
import static org.junit.Assert.assertSame; | ||
import static org.junit.Assert.assertThrows; | ||
import static org.junit.Assume.assumeTrue; | ||
import eu.emi.security.authn.x509.impl.CertificateUtils; | ||
import org.bouncycastle.asn1.x500.X500Name; | ||
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; | ||
import org.bouncycastle.cert.X509CertificateHolder; | ||
import org.bouncycastle.cert.X509v3CertificateBuilder; | ||
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter; | ||
import org.bouncycastle.jce.provider.BouncyCastleProvider; | ||
import org.bouncycastle.operator.ContentSigner; | ||
import org.bouncycastle.operator.OperatorCreationException; | ||
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder; | ||
import org.junit.After; | ||
import org.junit.Before; | ||
import org.junit.BeforeClass; | ||
import org.junit.Test; | ||
|
||
import java.io.File; | ||
import java.io.FileNotFoundException; | ||
import java.io.IOException; | ||
import java.io.OutputStream; | ||
import java.math.BigInteger; | ||
import java.nio.file.Files; | ||
import java.security.GeneralSecurityException; | ||
import java.security.KeyPair; | ||
import java.security.KeyPairGenerator; | ||
import java.security.SecureRandom; | ||
import java.security.Security; | ||
import java.util.Date; | ||
import java.util.Properties; | ||
import java.util.concurrent.TimeUnit; | ||
|
||
public class CDCCanlTLSHandlerFactoryTest { | ||
|
||
|
||
// whatever slow test should run | ||
private static final boolean RUN_SLOW_TESTS = System.getProperty("run.slow.tests") != null; | ||
|
||
@BeforeClass | ||
public static void setupClass() { | ||
Security.addProvider(new BouncyCastleProvider()); | ||
} | ||
private File keyFile; | ||
private File certFile; | ||
private File ca; | ||
|
||
private Properties configProperties; | ||
|
||
@Before | ||
public void setUp() throws Exception { | ||
keyFile = File.createTempFile("hostkey-", ".pem"); | ||
certFile = File.createTempFile("hostcert-", ".pem"); | ||
ca = Files.createTempDirectory("ca-").toFile(); | ||
|
||
configProperties = new Properties(); | ||
configProperties.setProperty(SERVICE_KEY, keyFile.getAbsolutePath()); | ||
configProperties.setProperty(SERVICE_CERT, certFile.getAbsolutePath()); | ||
configProperties.setProperty(SERVICE_CACERTS, ca.getAbsolutePath()); | ||
configProperties.setProperty(NAMESPACE_MODE, "IGNORE"); | ||
configProperties.setProperty(OCSP_MODE, "IGNORE"); | ||
configProperties.setProperty(CRL_MODE, "IGNORE"); | ||
} | ||
|
||
@After | ||
public void tearDown() throws Exception { | ||
keyFile.delete(); | ||
certFile.delete(); | ||
ca.delete(); | ||
} | ||
|
||
@Test | ||
public void shouldReturnCachedContextIfFilesAreNotChanged() throws Exception { | ||
|
||
assumeTrue("Skip slow running test", RUN_SLOW_TESTS); | ||
|
||
generateSelfSignedCert(); | ||
|
||
var contextSupplierFactory = new CDCCanlTLSHandlerFactory(); | ||
var contextSupplier = contextSupplierFactory.buildContextSupplier(configProperties); | ||
|
||
var c1 = contextSupplier.get(); | ||
|
||
TimeUnit.SECONDS.sleep(62); // 1 min is hard coded in org.dcache.ssl.CanlContextFactory.Builder.Builder | ||
|
||
var c2 = contextSupplier.get(); | ||
assertSame(c1, c2); | ||
} | ||
|
||
@Test | ||
public void shouldReturnNewContextIfFilesChanged() throws Exception { | ||
|
||
assumeTrue("Skip slow running test", RUN_SLOW_TESTS); | ||
|
||
generateSelfSignedCert(); | ||
var contextSupplierFactory = new CDCCanlTLSHandlerFactory(); | ||
var contextSupplier = contextSupplierFactory.buildContextSupplier(configProperties); | ||
|
||
var c1 = contextSupplier.get(); | ||
|
||
TimeUnit.SECONDS.sleep(62); // 1 min is hard coded in org.dcache.ssl.CanlContextFactory.Builder.Builder | ||
|
||
generateSelfSignedCert(); | ||
var c2 = contextSupplier.get(); | ||
|
||
assertNotSame(c1, c2); | ||
} | ||
|
||
// ensue that files are re-read | ||
@Test//(expected = FileNotFoundException.class) | ||
public void shouldFailToCreateContextIfFilesRemoved() throws Exception { | ||
|
||
assumeTrue("Skip slow running test", RUN_SLOW_TESTS); | ||
|
||
generateSelfSignedCert(); | ||
var contextSupplierFactory = new CDCCanlTLSHandlerFactory(); | ||
var contextSupplier = contextSupplierFactory.buildContextSupplier(configProperties); | ||
|
||
contextSupplier.get(); | ||
|
||
TimeUnit.SECONDS.sleep(62); // 1 min is hard coded in org.dcache.ssl.CanlContextFactory.Builder.Builder | ||
|
||
keyFile.delete(); | ||
certFile.delete(); | ||
|
||
var t = assertThrows(RuntimeException.class, contextSupplier::get); | ||
assertThat(t.getCause(), new org.hamcrest.core.IsInstanceOf(FileNotFoundException.class)); | ||
} | ||
|
||
private void generateSelfSignedCert() | ||
throws GeneralSecurityException, OperatorCreationException, IOException { | ||
|
||
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA", "BC"); | ||
keyPairGenerator.initialize(2048, new SecureRandom()); | ||
KeyPair keyPair = keyPairGenerator.generateKeyPair(); | ||
|
||
long notBefore = System.currentTimeMillis(); | ||
long notAfter = notBefore + TimeUnit.DAYS.toMillis(1); | ||
|
||
X500Name subjectDN = new X500Name("CN=localhost, O=dCache.org"); | ||
// explicit self-signed certificate | ||
X500Name issuerDN = subjectDN; | ||
|
||
SubjectPublicKeyInfo subjectPublicKeyInfo = | ||
SubjectPublicKeyInfo.getInstance(keyPair.getPublic().getEncoded()); | ||
|
||
X509v3CertificateBuilder certificateBuilder = new X509v3CertificateBuilder(issuerDN, | ||
BigInteger.ONE, | ||
new Date(notBefore), | ||
new Date(notAfter), subjectDN, | ||
subjectPublicKeyInfo); | ||
|
||
String signatureAlgorithm = "SHA256WithRSA"; | ||
|
||
// sign with own key | ||
ContentSigner contentSigner = new JcaContentSignerBuilder(signatureAlgorithm) | ||
.build(keyPair.getPrivate()); | ||
|
||
X509CertificateHolder certificateHolder = certificateBuilder.build(contentSigner); | ||
var cert = new JcaX509CertificateConverter().getCertificate(certificateHolder); | ||
|
||
try (OutputStream certOut = Files.newOutputStream( | ||
certFile.toPath(), CREATE, TRUNCATE_EXISTING, | ||
WRITE); OutputStream keyOut = Files.newOutputStream(keyFile.toPath(), CREATE, | ||
TRUNCATE_EXISTING, WRITE)) { | ||
|
||
CertificateUtils.saveCertificate(certOut, cert, CertificateUtils.Encoding.PEM); | ||
CertificateUtils.savePrivateKey(keyOut, keyPair.getPrivate(), CertificateUtils.Encoding.PEM, null, null); | ||
} | ||
} | ||
|
||
} | ||
|
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