You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nifi.apache.org by al...@apache.org on 2018/08/07 03:02:48 UTC
nifi git commit: NIFI-5400 - Changed the hostname verifier from the
custom NiFi verifier to the Apache http-client DefaultHostnameVerifier
Removed NiFiHostnameVerifier. Removed NiFi WebUtils usage of
NiFiHostnameVerifier. Added unit tests for the Default
Repository: nifi
Updated Branches:
refs/heads/master a19134f32 -> 8106af699
NIFI-5400 - Changed the hostname verifier from the custom NiFi verifier to the Apache http-client DefaultHostnameVerifier
Removed NiFiHostnameVerifier. Removed NiFi WebUtils usage of NiFiHostnameVerifier.
Added unit tests for the DefaultHostnameVerifier to WebUtils.java
Added groovy-eclipse-compiler definition to nifi-web-utils/pom.xml to execute Groovy unit tests.
This closes #2919.
Co-authored-by: Andy LoPresto <al...@apache.org>
Signed-off-by: Andy LoPresto <al...@apache.org>
Project: http://git-wip-us.apache.org/repos/asf/nifi/repo
Commit: http://git-wip-us.apache.org/repos/asf/nifi/commit/8106af69
Tree: http://git-wip-us.apache.org/repos/asf/nifi/tree/8106af69
Diff: http://git-wip-us.apache.org/repos/asf/nifi/diff/8106af69
Branch: refs/heads/master
Commit: 8106af699c4dba21c03b1d8ba6c3e702dc7b1380
Parents: a19134f
Author: thenatog <th...@gmail.com>
Authored: Thu Jul 26 16:33:52 2018 -0400
Committer: Andy LoPresto <al...@apache.org>
Committed: Mon Aug 6 19:57:49 2018 -0700
----------------------------------------------------------------------
nifi-commons/nifi-web-utils/pom.xml | 54 ++++++
.../nifi/web/util/NiFiHostnameVerifier.java | 61 ------
.../java/org/apache/nifi/web/util/WebUtils.java | 5 +-
.../apache/nifi/web/util/WebUtilsTest.groovy | 188 ++++++++++++++++++-
.../admin/client/NiFiClientFactory.groovy | 57 +-----
.../admin/client/NiFiClientFactorySpec.groovy | 88 ++++++++-
6 files changed, 326 insertions(+), 127 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/nifi/blob/8106af69/nifi-commons/nifi-web-utils/pom.xml
----------------------------------------------------------------------
diff --git a/nifi-commons/nifi-web-utils/pom.xml b/nifi-commons/nifi-web-utils/pom.xml
index b87dce5..2830e58 100644
--- a/nifi-commons/nifi-web-utils/pom.xml
+++ b/nifi-commons/nifi-web-utils/pom.xml
@@ -85,5 +85,59 @@
<artifactId>javax.servlet-api</artifactId>
<scope>provided</scope>
</dependency>
+ <dependency>
+ <groupId>org.apache.httpcomponents</groupId>
+ <artifactId>httpclient</artifactId>
+ <version>4.5.6</version>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.httpcomponents</groupId>
+ <artifactId>httpclient</artifactId>
+ <version>4.5.6</version>
+ <scope>compile</scope>
+ </dependency>
</dependencies>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <executions>
+ <!-- Only run for tests -->
+ <execution>
+ <id>groovy-tests</id>
+ <goals>
+ <goal>testCompile</goal>
+ </goals>
+ <configuration>
+ <compilerId>groovy-eclipse-compiler</compilerId>
+ </configuration>
+ </execution>
+ </executions>
+ <configuration>
+ <source>1.8</source>
+ <target>1.8</target>
+ </configuration>
+ <dependencies>
+ <dependency>
+ <groupId>org.codehaus.groovy</groupId>
+ <artifactId>groovy-eclipse-compiler</artifactId>
+ <version>2.9.2-01</version>
+ </dependency>
+ <dependency>
+ <groupId>org.codehaus.groovy</groupId>
+ <artifactId>groovy-eclipse-batch</artifactId>
+ <version>2.4.3-01</version>
+ </dependency>
+ </dependencies>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.groovy</groupId>
+ <artifactId>groovy-eclipse-compiler</artifactId>
+ <version>2.9.2-01</version>
+ <extensions>true</extensions>
+ </plugin>
+ </plugins>
+ </build>
</project>
http://git-wip-us.apache.org/repos/asf/nifi/blob/8106af69/nifi-commons/nifi-web-utils/src/main/java/org/apache/nifi/web/util/NiFiHostnameVerifier.java
----------------------------------------------------------------------
diff --git a/nifi-commons/nifi-web-utils/src/main/java/org/apache/nifi/web/util/NiFiHostnameVerifier.java b/nifi-commons/nifi-web-utils/src/main/java/org/apache/nifi/web/util/NiFiHostnameVerifier.java
deleted file mode 100644
index 960af58..0000000
--- a/nifi-commons/nifi-web-utils/src/main/java/org/apache/nifi/web/util/NiFiHostnameVerifier.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.nifi.web.util;
-
-import java.security.cert.Certificate;
-import java.security.cert.CertificateParsingException;
-import java.security.cert.X509Certificate;
-import java.util.List;
-
-import javax.net.ssl.HostnameVerifier;
-import javax.net.ssl.SSLPeerUnverifiedException;
-import javax.net.ssl.SSLSession;
-
-import org.apache.nifi.security.util.CertificateUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class NiFiHostnameVerifier implements HostnameVerifier {
- private static final Logger logger = LoggerFactory.getLogger(NiFiHostnameVerifier.class);
-
- @Override
- public boolean verify(final String hostname, final SSLSession ssls) {
- try {
- for (final Certificate peerCertificate : ssls.getPeerCertificates()) {
- if (peerCertificate instanceof X509Certificate) {
- final X509Certificate x509Cert = (X509Certificate) peerCertificate;
- final String dn = x509Cert.getSubjectDN().getName();
- final String commonName = CertificateUtils.extractUsername(dn);
- if (commonName.equals(hostname)) {
- return true;
- }
-
- final List<String> subjectAltNames = CertificateUtils.getSubjectAlternativeNames(x509Cert);
- if (subjectAltNames.contains(hostname.toLowerCase())) {
- return true;
- }
- }
- }
- } catch (final SSLPeerUnverifiedException | CertificateParsingException ex) {
- logger.warn("Hostname Verification encountered exception verifying hostname due to: " + ex, ex);
- }
-
- return false;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/nifi/blob/8106af69/nifi-commons/nifi-web-utils/src/main/java/org/apache/nifi/web/util/WebUtils.java
----------------------------------------------------------------------
diff --git a/nifi-commons/nifi-web-utils/src/main/java/org/apache/nifi/web/util/WebUtils.java b/nifi-commons/nifi-web-utils/src/main/java/org/apache/nifi/web/util/WebUtils.java
index cbf64e6..90a83a9 100644
--- a/nifi-commons/nifi-web-utils/src/main/java/org/apache/nifi/web/util/WebUtils.java
+++ b/nifi-commons/nifi-web-utils/src/main/java/org/apache/nifi/web/util/WebUtils.java
@@ -32,6 +32,7 @@ import org.glassfish.jersey.client.ClientConfig;
import org.glassfish.jersey.jackson.internal.jackson.jaxrs.json.JacksonJaxbJsonProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.apache.http.conn.ssl.DefaultHostnameVerifier;
/**
* Common utilities related to web development.
@@ -93,8 +94,8 @@ public final class WebUtils {
if (ctx != null) {
- // custom hostname verifier that checks subject alternative names against the hostname of the URI
- clientBuilder = clientBuilder.sslContext(ctx).hostnameVerifier(new NiFiHostnameVerifier());
+ // Apache http DefaultHostnameVerifier that checks subject alternative names against the hostname of the URI
+ clientBuilder = clientBuilder.sslContext(ctx).hostnameVerifier(new DefaultHostnameVerifier());
}
clientBuilder = clientBuilder.register(ObjectMapperResolver.class).register(JacksonJaxbJsonProvider.class);
http://git-wip-us.apache.org/repos/asf/nifi/blob/8106af69/nifi-commons/nifi-web-utils/src/test/groovy/org/apache/nifi/web/util/WebUtilsTest.groovy
----------------------------------------------------------------------
diff --git a/nifi-commons/nifi-web-utils/src/test/groovy/org/apache/nifi/web/util/WebUtilsTest.groovy b/nifi-commons/nifi-web-utils/src/test/groovy/org/apache/nifi/web/util/WebUtilsTest.groovy
index 62755a1..b0a1191 100644
--- a/nifi-commons/nifi-web-utils/src/test/groovy/org/apache/nifi/web/util/WebUtilsTest.groovy
+++ b/nifi-commons/nifi-web-utils/src/test/groovy/org/apache/nifi/web/util/WebUtilsTest.groovy
@@ -16,17 +16,27 @@
*/
package org.apache.nifi.web.util
+import org.glassfish.jersey.client.ClientConfig
import org.junit.After
import org.junit.Before
import org.junit.BeforeClass
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
+import org.mockito.Mockito
import org.slf4j.Logger
import org.slf4j.LoggerFactory
-
+import org.apache.http.conn.ssl.DefaultHostnameVerifier
+import sun.security.tools.keytool.CertAndKeyGen
+import sun.security.x509.X500Name
+import javax.net.ssl.SSLPeerUnverifiedException
import javax.servlet.http.HttpServletRequest
import javax.ws.rs.core.UriBuilderException
+import javax.ws.rs.client.Client;
+import javax.net.ssl.SSLContext
+import javax.net.ssl.HostnameVerifier;
+import java.security.cert.X509Certificate;
+
@RunWith(JUnit4.class)
class WebUtilsTest extends GroovyTestCase {
@@ -36,6 +46,7 @@ class WebUtilsTest extends GroovyTestCase {
static final String FC_HEADER = "X-Forwarded-Context"
static final String WHITELISTED_PATH = "/some/context/path"
+ private static final String OCSP_REQUEST_CONTENT_TYPE = "application/ocsp-request";
@BeforeClass
static void setUpOnce() throws Exception {
@@ -272,4 +283,179 @@ class WebUtilsTest extends GroovyTestCase {
assert msg =~ " was not whitelisted "
}
}
+
+ @Test
+ void testHostnameVerifierType() {
+
+ // Arrange
+ SSLContext sslContext = Mockito.mock(SSLContext.class)
+ final ClientConfig clientConfig = new ClientConfig()
+
+ // Act
+ Client client = WebUtils.createClient(clientConfig, sslContext)
+ HostnameVerifier hostnameVerifier = client.getHostnameVerifier()
+
+ // Assert
+ assertTrue(hostnameVerifier instanceof DefaultHostnameVerifier)
+ }
+
+ @Test
+ void testHostnameVerifierWildcard() {
+
+ // Arrange
+ final String EXPECTED_DN = "CN=*.apache.com,OU=Security,O=Apache,ST=CA,C=US"
+ final String hostname = "nifi.apache.com"
+ X509Certificate cert = generateCertificate(EXPECTED_DN)
+ SSLContext sslContext = Mockito.mock(SSLContext.class)
+ final ClientConfig clientConfig = new ClientConfig()
+
+ // Act
+ Client client = WebUtils.createClient(clientConfig, sslContext)
+ DefaultHostnameVerifier hostnameVerifier = (DefaultHostnameVerifier) client.getHostnameVerifier()
+
+ // Verify
+ hostnameVerifier.verify(hostname, cert)
+ }
+
+ @Test
+ void testHostnameVerifierDNWildcardFourthLevelDomain() {
+
+ // Arrange
+ final String EXPECTED_DN = "CN=*.nifi.apache.org,OU=Security,O=Apache,ST=CA,C=US"
+ final String clientHostname = "client.nifi.apache.org"
+ final String serverHostname = "server.nifi.apache.org"
+ X509Certificate cert = generateCertificate(EXPECTED_DN)
+ SSLContext sslContext = Mockito.mock(SSLContext.class)
+ final ClientConfig clientConfig = new ClientConfig()
+
+
+ // Act
+ Client client = WebUtils.createClient(clientConfig, sslContext)
+ DefaultHostnameVerifier hostnameVerifier = client.getHostnameVerifier()
+
+ // Verify
+ hostnameVerifier.verify(clientHostname, cert)
+ hostnameVerifier.verify(serverHostname, cert)
+ }
+
+ @Test(expected = SSLPeerUnverifiedException)
+ void testHostnameVerifierDomainLevelMismatch() {
+
+ // Arrange
+ final String EXPECTED_DN = "CN=*.nifi.apache.org,OU=Security,O=Apache,ST=CA,C=US"
+ final String hostname = "nifi.apache.org"
+ X509Certificate cert = generateCertificate(EXPECTED_DN)
+ SSLContext sslContext = Mockito.mock(SSLContext.class)
+ final ClientConfig clientConfig = new ClientConfig()
+
+ // Act
+ Client client = WebUtils.createClient(clientConfig, sslContext)
+ DefaultHostnameVerifier hostnameVerifier = client.getHostnameVerifier()
+
+ // Verify
+ hostnameVerifier.verify(hostname, cert)
+ }
+
+ @Test(expected = SSLPeerUnverifiedException)
+ void testHostnameVerifierEmptyHostname() {
+
+ // Arrange
+ final String EXPECTED_DN = "CN=nifi.apache.org,OU=Security,O=Apache,ST=CA,C=US"
+ final String hostname = ""
+ X509Certificate cert = generateCertificate(EXPECTED_DN)
+ SSLContext sslContext = Mockito.mock(SSLContext.class)
+ final ClientConfig clientConfig = new ClientConfig()
+
+ // Act
+ Client client = WebUtils.createClient(clientConfig, sslContext)
+ DefaultHostnameVerifier hostnameVerifier = client.getHostnameVerifier()
+
+ // Verify
+ hostnameVerifier.verify(hostname, cert)
+ }
+
+ @Test(expected = SSLPeerUnverifiedException)
+ void testHostnameVerifierDifferentSubdomain() {
+
+ // Arrange
+ final String EXPECTED_DN = "CN=nifi.apache.org,OU=Security,O=Apache,ST=CA,C=US"
+ final String hostname = "egg.apache.org"
+ X509Certificate cert = generateCertificate(EXPECTED_DN)
+ SSLContext sslContext = Mockito.mock(SSLContext.class)
+ final ClientConfig clientConfig = new ClientConfig()
+
+ // Act
+ Client client = WebUtils.createClient(clientConfig, sslContext)
+ DefaultHostnameVerifier hostnameVerifier = client.getHostnameVerifier()
+
+ // Verify
+ hostnameVerifier.verify(hostname, cert)
+ }
+
+ @Test(expected = SSLPeerUnverifiedException)
+ void testHostnameVerifierDifferentTLD() {
+
+ // Arrange
+ final String EXPECTED_DN = "CN=nifi.apache.org,OU=Security,O=Apache,ST=CA,C=US"
+ final String hostname = "nifi.apache.com"
+ X509Certificate cert = generateCertificate(EXPECTED_DN)
+ SSLContext sslContext = Mockito.mock(SSLContext.class)
+ final ClientConfig clientConfig = new ClientConfig()
+
+ // Act
+ Client client = WebUtils.createClient(clientConfig, sslContext)
+ DefaultHostnameVerifier hostnameVerifier = client.getHostnameVerifier()
+
+ // Verify
+ hostnameVerifier.verify(hostname, cert)
+ }
+
+ @Test
+ void testHostnameVerifierWildcardTLD() {
+
+ // Arrange
+ final String EXPECTED_DN = "CN=nifi.apache.*,OU=Security,O=Apache,ST=CA,C=US"
+ final String comTLDhostname = "nifi.apache.com"
+ final String orgTLDHostname = "nifi.apache.org"
+ X509Certificate cert = generateCertificate(EXPECTED_DN)
+ SSLContext sslContext = Mockito.mock(SSLContext.class)
+ final ClientConfig clientConfig = new ClientConfig()
+
+ // Act
+ Client client = WebUtils.createClient(clientConfig, sslContext)
+ DefaultHostnameVerifier hostnameVerifier = client.getHostnameVerifier()
+
+ // Verify
+ hostnameVerifier.verify(comTLDhostname, cert)
+ hostnameVerifier.verify(orgTLDHostname, cert)
+ }
+
+ @Test
+ void testHostnameVerifierWildcardDomain() {
+
+ // Arrange
+ final String EXPECTED_DN = "CN=nifi.*.com,OU=Security,O=Apache,ST=CA,C=US"
+ final String hostname = "nifi.apache.com"
+ X509Certificate cert = generateCertificate(EXPECTED_DN)
+ SSLContext sslContext = Mockito.mock(SSLContext.class)
+ final ClientConfig clientConfig = new ClientConfig()
+
+ // Act
+ Client client = WebUtils.createClient(clientConfig, sslContext)
+ DefaultHostnameVerifier hostnameVerifier = client.getHostnameVerifier()
+
+ // Verify
+ hostnameVerifier.verify(hostname, cert)
+ }
+
+
+ X509Certificate generateCertificate(String DN) {
+ CertAndKeyGen certGenerator = new CertAndKeyGen("RSA", "SHA256WithRSA", null)
+ certGenerator.generate(2048)
+
+
+ long validityPeriod = (long) 365 * 24 * 60 * 60 // 1 YEAR
+ X509Certificate cert = certGenerator.getSelfCertificate(new X500Name(DN), validityPeriod)
+ return cert
+ }
}
http://git-wip-us.apache.org/repos/asf/nifi/blob/8106af69/nifi-toolkit/nifi-toolkit-admin/src/main/groovy/org/apache/nifi/toolkit/admin/client/NiFiClientFactory.groovy
----------------------------------------------------------------------
diff --git a/nifi-toolkit/nifi-toolkit-admin/src/main/groovy/org/apache/nifi/toolkit/admin/client/NiFiClientFactory.groovy b/nifi-toolkit/nifi-toolkit-admin/src/main/groovy/org/apache/nifi/toolkit/admin/client/NiFiClientFactory.groovy
index abafbf0..27f75c2 100644
--- a/nifi-toolkit/nifi-toolkit-admin/src/main/groovy/org/apache/nifi/toolkit/admin/client/NiFiClientFactory.groovy
+++ b/nifi-toolkit/nifi-toolkit-admin/src/main/groovy/org/apache/nifi/toolkit/admin/client/NiFiClientFactory.groovy
@@ -17,18 +17,13 @@
package org.apache.nifi.toolkit.admin.client
import org.apache.commons.lang3.StringUtils
-import org.apache.nifi.security.util.CertificateUtils
+import org.apache.http.conn.ssl.DefaultHostnameVerifier
import org.apache.nifi.util.NiFiProperties
import org.slf4j.Logger
import org.slf4j.LoggerFactory
-import javax.naming.ldap.LdapName
-import javax.naming.ldap.Rdn
-import javax.net.ssl.HostnameVerifier
import javax.net.ssl.KeyManagerFactory
import javax.net.ssl.SSLContext
-import javax.net.ssl.SSLPeerUnverifiedException
-import javax.net.ssl.SSLSession
import javax.net.ssl.TrustManagerFactory
import javax.ws.rs.client.Client
import javax.ws.rs.client.ClientBuilder
@@ -38,10 +33,7 @@ import java.security.KeyStoreException
import java.security.NoSuchAlgorithmException
import java.security.SecureRandom
import java.security.UnrecoverableKeyException
-import java.security.cert.Certificate
import java.security.cert.CertificateException
-import java.security.cert.CertificateParsingException
-import java.security.cert.X509Certificate
class NiFiClientFactory implements ClientFactory{
@@ -83,14 +75,13 @@ class NiFiClientFactory implements ClientFactory{
final ClientBuilder clientBuilder = ClientBuilder.newBuilder();
if (sslContext != null) {
- clientBuilder.sslContext(sslContext).hostnameVerifier(new NiFiHostnameVerifier());
+ clientBuilder.sslContext(sslContext).hostnameVerifier(new DefaultHostnameVerifier());
}
return clientBuilder.build();
}
-
static SSLContext createSslContext(
final String keystore, final char[] keystorePasswd, final String keystoreType,
final String truststore, final char[] truststorePasswd, final String truststoreType,
@@ -121,50 +112,6 @@ class NiFiClientFactory implements ClientFactory{
return sslContext;
}
- static class NiFiHostnameVerifier implements HostnameVerifier {
-
- @Override
- public boolean verify(final String hostname, final SSLSession ssls) {
-
- if (ssls.getPeerCertificates() != null && ssls.getPeerCertificates().length > 0) {
-
- try {
- final Certificate peerCertificate = ssls.getPeerCertificates()[0]
- final X509Certificate x509Cert = CertificateUtils.convertAbstractX509Certificate(peerCertificate)
- final String dn = x509Cert.getSubjectDN().getName().trim()
-
- final LdapName ln = new LdapName(dn)
- final boolean match = ln.getRdns().any { Rdn rdn -> rdn.getType().equalsIgnoreCase("CN") && rdn.getValue().toString().equalsIgnoreCase(hostname)}
- return match || getSubjectAlternativeNames(x509Cert).any { String san -> san.equalsIgnoreCase(hostname) }
- } catch (final SSLPeerUnverifiedException | CertificateParsingException ex ) {
- logger.warn("Hostname Verification encountered exception verifying hostname due to: " + ex, ex);
- }
-
- }else{
- logger.warn("Peer certificates not found on ssl session ");
- }
-
- return false
- }
-
- private List<String> getSubjectAlternativeNames(final X509Certificate certificate) throws CertificateParsingException {
- final Collection<List<?>> altNames = certificate.getSubjectAlternativeNames()
-
- if (altNames == null) {
- return new ArrayList<>()
- }
-
- final List<String> result = new ArrayList<>()
- for (final List<?> generalName : altNames) {
- final Object value = generalName.get(1)
- if (value instanceof String) {
- result.add(((String) value).toLowerCase())
- }
- }
-
- return result
- }
- }
}
http://git-wip-us.apache.org/repos/asf/nifi/blob/8106af69/nifi-toolkit/nifi-toolkit-admin/src/test/groovy/org/apache/nifi/toolkit/admin/client/NiFiClientFactorySpec.groovy
----------------------------------------------------------------------
diff --git a/nifi-toolkit/nifi-toolkit-admin/src/test/groovy/org/apache/nifi/toolkit/admin/client/NiFiClientFactorySpec.groovy b/nifi-toolkit/nifi-toolkit-admin/src/test/groovy/org/apache/nifi/toolkit/admin/client/NiFiClientFactorySpec.groovy
index a37b1c1..ddb445f 100644
--- a/nifi-toolkit/nifi-toolkit-admin/src/test/groovy/org/apache/nifi/toolkit/admin/client/NiFiClientFactorySpec.groovy
+++ b/nifi-toolkit/nifi-toolkit-admin/src/test/groovy/org/apache/nifi/toolkit/admin/client/NiFiClientFactorySpec.groovy
@@ -18,6 +18,7 @@
package org.apache.nifi.toolkit.admin.client
import org.apache.commons.lang3.SystemUtils
+import org.apache.http.conn.ssl.DefaultHostnameVerifier
import org.apache.nifi.properties.NiFiPropertiesLoader
import org.apache.nifi.security.util.CertificateUtils
import org.apache.nifi.toolkit.tls.standalone.TlsToolkitStandalone
@@ -110,7 +111,7 @@ class NiFiClientFactorySpec extends Specification {
final String EXPECTED_DN = "CN=client.nifi.apache.org,OU=Security,O=Apache,ST=CA,C=US"
Certificate[] certificateChain = generateCertificateChain(EXPECTED_DN,ISSUER_DN)
def mockSession = Mock(SSLSession)
- NiFiClientFactory.NiFiHostnameVerifier verifier = new NiFiClientFactory.NiFiHostnameVerifier()
+ DefaultHostnameVerifier verifier = new DefaultHostnameVerifier()
mockSession.getPeerCertificates() >> certificateChain
when:
@@ -121,21 +122,88 @@ class NiFiClientFactorySpec extends Specification {
}
+ def "should verify wildcard in CN in certificate based on subjectDN"(){
+
+ given:
+ final String EXPECTED_DN = "CN=*.nifi.apache.org,OU=Security,O=Apache,ST=CA,C=US"
+ Certificate[] certificateChain = generateCertificateChain(EXPECTED_DN,ISSUER_DN)
+ def mockSession = Mock(SSLSession)
+ DefaultHostnameVerifier verifier = new DefaultHostnameVerifier()
+ mockSession.getPeerCertificates() >> certificateChain
+
+ when:
+ def validSubdomainIsVerified = verifier.verify("client.nifi.apache.org",mockSession)
+ def validSubdomainIsVerified2 = verifier.verify("server.nifi.apache.org",mockSession)
+ def invalidSubdomainIsNotVerified = !verifier.verify("client.hive.apache.org",mockSession)
+
+ then:
+ validSubdomainIsVerified
+ validSubdomainIsVerified2
+ invalidSubdomainIsNotVerified
+ }
+
+ def "should verify appropriately CN in certificate based on TLD wildcard in SAN"(){
+
+ given:
+ final String EXPECTED_DN = "CN=client.nifi.apache.*,OU=Security,O=Apache,ST=CA,C=US"
+ final String wildcardHostname = "client.nifi.apache.com"
+ byte[] subjectAltName = new GeneralNames(new GeneralName(GeneralName.dNSName, wildcardHostname)).getEncoded()
+ Extensions extensions = new Extensions(new Extension(Extension.subjectAlternativeName, false, subjectAltName))
+ Certificate[] certificateChain = generateCertificateChain(EXPECTED_DN, ISSUER_DN, extensions)
+ def mockSession = Mock(SSLSession)
+ DefaultHostnameVerifier verifier = new DefaultHostnameVerifier()
+ mockSession.getPeerCertificates() >> certificateChain
+
+ when:
+ def validTLDIsVerified = verifier.verify("client.nifi.apache.org",mockSession)
+ def validTLDIsVerified2 = verifier.verify("client.nifi.apache.com",mockSession)
+ def validTLDIsNotVerified = !verifier.verify("client.hive.apache.org",mockSession)
+
+ then:
+ //validTLDIsVerified
+ validTLDIsVerified2
+ validTLDIsNotVerified
+ }
+
+ def "should verify appropriately CN in certificate based on subdomain wildcard in SAN"(){
+
+ given:
+ final String EXPECTED_DN = "CN=client.nifi.apache.org,OU=Security,O=Apache,ST=CA,C=US"
+ final String wildcardHostname = "*.nifi.apache.org"
+ byte[] subjectAltName = new GeneralNames(new GeneralName(GeneralName.dNSName, wildcardHostname)).getEncoded()
+ Extensions extensions = new Extensions(new Extension(Extension.subjectAlternativeName, false, subjectAltName))
+ Certificate[] certificateChain = generateCertificateChain(EXPECTED_DN, ISSUER_DN, extensions)
+ def mockSession = Mock(SSLSession)
+ DefaultHostnameVerifier verifier = new DefaultHostnameVerifier()
+ mockSession.getPeerCertificates() >> certificateChain
+
+ when:
+ def validSubdomainIsVerified = verifier.verify("client.nifi.apache.org", mockSession)
+ def validSubdomainIsVerified1 = verifier.verify("egg.nifi.apache.org", mockSession)
+ def invalidSubdomainIsNotVerified = !verifier.verify("client.hive.apache.org", mockSession)
+ def invalidDomainIsNotVerified = !verifier.verify("egg.com", mockSession)
+
+ then:
+ validSubdomainIsVerified
+ validSubdomainIsVerified1
+ invalidSubdomainIsNotVerified
+ invalidDomainIsNotVerified
+ }
+
def "should not verify based on no certificate chain"(){
given:
final String EXPECTED_DN = "CN=client.nifi.apache.org, OU=Security, O=Apache, ST=CA, C=US"
Certificate[] certificateChain = [] as Certificate[]
def mockSession = Mock(SSLSession)
- NiFiClientFactory.NiFiHostnameVerifier verifier = new NiFiClientFactory.NiFiHostnameVerifier()
+ DefaultHostnameVerifier verifier = new DefaultHostnameVerifier()
mockSession.getPeerCertificates() >> certificateChain
when:
def notVerified = !verifier.verify("client.nifi.apache.org",mockSession)
then:
- notVerified
-
+ final ArrayIndexOutOfBoundsException exception = thrown()
}
def "should not verify based on multiple CN values"(){
@@ -163,7 +231,7 @@ class NiFiClientFactorySpec extends Specification {
Certificate[] certificateChain = [certificate,issuerCertificate] as Certificate[]
def mockSession = Mock(SSLSession)
- NiFiClientFactory.NiFiHostnameVerifier verifier = new NiFiClientFactory.NiFiHostnameVerifier()
+ DefaultHostnameVerifier verifier = new DefaultHostnameVerifier()
mockSession.getPeerCertificates() >> certificateChain
@@ -175,7 +243,7 @@ class NiFiClientFactorySpec extends Specification {
}
- def "should verify appropriately CN in certificate based on SAN"(){
+ def "should verify appropriately CN in certificate based on SAN"() {
given:
@@ -194,7 +262,7 @@ class NiFiClientFactorySpec extends Specification {
final X509Certificate certificate = generateIssuedCertificate(EXPECTED_DN, issuerCertificate,extensions, issuerKeyPair)
Certificate[] certificateChain = [certificate, issuerCertificate] as X509Certificate[]
def mockSession = Mock(SSLSession)
- NiFiClientFactory.NiFiHostnameVerifier verifier = new NiFiClientFactory.NiFiHostnameVerifier()
+ DefaultHostnameVerifier verifier = new DefaultHostnameVerifier()
mockSession.getPeerCertificates() >> certificateChain
when:
@@ -220,9 +288,13 @@ class NiFiClientFactorySpec extends Specification {
}
def X509Certificate[] generateCertificateChain(String dn,String issuerDn) {
+ generateCertificateChain(dn, issuerDn, null)
+ }
+
+ def X509Certificate[] generateCertificateChain(String dn,String issuerDn, Extensions extensions) {
final KeyPair issuerKeyPair = generateKeyPair()
final X509Certificate issuerCertificate = CertificateUtils.generateSelfSignedX509Certificate(issuerKeyPair, issuerDn, SIGNATURE_ALGORITHM, DAYS_IN_YEAR)
- final X509Certificate certificate = generateIssuedCertificate(dn, issuerCertificate,null, issuerKeyPair)
+ final X509Certificate certificate = generateIssuedCertificate(dn, issuerCertificate, extensions, issuerKeyPair)
[certificate, issuerCertificate] as X509Certificate[]
}