java-client-api
java-client-api copied to clipboard
Automate Server certificate test.
Here is the test that runs in "develop" branch on Windows.
/*
* Copyright 2014-2017 MarkLogic Corporation
*
* Licensed 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 com.marklogic.client.functionaltest;
import static org.junit.Assert.*;
import java.net.InetAddress;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.concurrent.atomic.AtomicReference;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLException;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import com.marklogic.client.DatabaseClient;
import com.marklogic.client.DatabaseClientFactory;
import com.marklogic.client.DatabaseClientFactory.Authentication;
import com.marklogic.client.DatabaseClientFactory.SSLHostnameVerifier;
import com.marklogic.client.document.TextDocumentManager;
import com.marklogic.client.io.StringHandle;
public class TestDatabaseWithServerCert extends BasicJavaClientREST {
public static String newLine = System.getProperty("line.separator");
public static String temp = System.getProperty("java.io.tmpdir");
public static String java_home = System.getProperty("java.home");
private static String dbName = "TestServerCertDB";
private static String [] fNames = {"TestServerCertDB-1"};
private static String restServerName = "REST-Java-Client-API-Server";
public static String setupServer = "App-Services";
private static int restPort = 8011;
public static String host = "localhost";
public static DatabaseClient secClient;
public static DatabaseClient secClientVerifier;
public static String localHostname = null;
// Server Certificate: hpzbook-3884Server.crt
/*
-----BEGIN CERTIFICATE-----
MIID0DCCArigAwIBAgIDATuTMA0GCSqGSIb3DQEBCwUAMIGWMQswCQYDVQQGEwJV
UzELMAkGA1UECBMCQ0ExEzARBgNVBAcTClNhbiBDYXJsb3MxEjAQBgNVBAoTCU1h
cmtMb2dpYzEUMBIGA1UECxMLRW5naW5lZXJpbmcxFDASBgNVBAMTC01hcmtMb2dp
Y0NBMSUwIwYJKoZIhvcNAQkBFhZmYmVybXVkZUBtYXJrbG9naWMuY29tMB4XDTE3
MDcyNDE3MTAyN1oXDTI2MDcyNzE3MTAyN1owgZsxCzAJBgNVBAYTAlVTMQswCQYD
VQQIDAJDQTETMBEGA1UEBwwKU2FuIENhcmxvczESMBAGA1UECgwJTWFya0xvZ2lj
MQswCQYDVQQLDAJRQTEjMCEGA1UEAwwaaHB6Ym9vay0zODg0Lm1hcmtsb2dpYy5j
b20xJDAiBgkqhkiG9w0BCQEWFWFnZW9yZ2VAbWFya2xvZ2ljLmNvbTCCASIwDQYJ
KoZIhvcNAQEBBQADggEPADCCAQoCggEBAKbEztMjUx1WEGgFLfTYhIZpq7VNlxV1
yQV3kA9CA1ssFqDyBUTkN/heg8/W2SWdWbDKoyLzWSMrCxFddPxaKNH25pNQhH+y
Kz6zS/hQmLAvEL0kAzzhL7ySK3x/EWE0ojhiuwby9Nfs+m6gvnAh49Y19iz+bi7g
/LNX9evn1CtNEEhL5LGzYASH0NgnEOk/XW6ZWaR41jVaF35vjiPcgXMgjKHTYx4J
KZZBeOjv6BEqmXHMoL6j0PVB5aIVjfSXQUdE8dnN7ervr4quKflv51iSz9Ey/aL6
pYXXIP/41Yn2b/TehBt+K35dRlYRS2JcB5dRWuvcFCVJC1Bu+fIleLcCAwEAAaMg
MB4wCQYDVR0TBAIwADARBglghkgBhvhCAQEEBAMCBkAwDQYJKoZIhvcNAQELBQAD
ggEBADlGPmapeDj349vXcwMeoqk5dqVEM/qt/EhJVyT5f+7T2+Jn0wB2NDIdFd3S
tWpaBJ6/kW87BP+5Y+er3dc6reHGZiFm0fIwRrz0UoO0YghuxZxpoykab3mwtpyJ
sF4CovI5L9QYvGW84IP65vBfkMmvC0NbSDFA1v2sFSL1UcJjUu6vpI5seBBfNHaK
2OkXvNI+34k8ghLCOgdt13D3NrnPePMslSwcISmirjbFhwP62AduqHNT+gqaYoIy
+doTIMBP5moDIFJ5RNW8eOdTs5QDHEkA/8h5RGGfkoaXfV52Y9lGeDjeLiIgdhSG
mfn0dQ6qXRGGsdZIN6IOWq805LQ=
-----END CERTIFICATE-----
*/
/*
Steps
On the server
1) Generate a private key using openssl in cygwin - openssl genrsa -out kmip-key.pem 2048
2) Generate a CSR - openssl req -out "MLServer_hostname.csr" -key kmip-key.pem -new -sha256
3) Open the Local CA in SafeNet for MarkLogic and copy the certificate from SafeNet into
ML Security-Certificate Authorities and paste into the Textbox. Click OK.
4) To Sign the CSRfrom 2) go to SafeNet-Local CA- MarkLogic link. Select" Server" radio button.
Open the CSR in "vi" or text editor copy all lines into SafeNet testbox for signing. Click "Sign Request".
5) Copy the generated text (cert) from SafeNet GUI back into file system into a text editor or vi
and save it as **.crt file.
6) Create a Template in ML Admin GUI with proper fields values (enter same as those given in the CSR in command line)
7) Associate the template with private key, certificate file using these XQuery scripts on Security Database in QConsole.
xquery version "1.0-ml";
import module namespace pki = "http://marklogic.com/xdmp/pki" at "/MarkLogic/pki.xqy";
let $temp as element(pki:template) := pki:get-template-by-name("OpsDirector-SSL-Template")
let $id := pki:template-get-id($temp)
let $opts := <options xmlns="xdmp:document-get"><format>text</format></options>
let $cert := xdmp:document-get("/share/certs/builder-server.crt", $opts)
let $key := xdmp:document-get("/share/certs/builder.key", $opts)
return
pki:insert-host-certificate($id, $cert, $key)
8) Create a REST App Server. Associate security template to it. Set require client certificate to false.
Pass in the Template name, private key file name and certificate name.
Note: Create separate templates for each of the cert files and run XQuery scripts. Restart ML Server if possible.
*/
@BeforeClass
public static void setUpBeforeClass() throws Exception {
loadGradleProperties();
localHostname = getBootStrapHostFromML();
setupJavaRESTServer(dbName, fNames[0], restServerName,restPort);
setupAppServicesConstraint(dbName);
createRESTUser("portal", "seekrit", "admin", "rest-admin", "rest-writer", "rest-reader");
}
@AfterClass
public static void tearDownAfterClass() throws Exception {
tearDownJavaRESTServer(dbName, fNames, restServerName);
}
/*
* This test verifies that
* a valid server certificate is available (Note: Server certificate CN=FQDN of the ML Server)
* client can NOT write/read a document to DB with localhost (client and server on same machine)
* Expected result : Exception
* validate the Server certificate's hostname is null
* validate the Server certificate's CN is null
* validate the Server certificate's SAN (Subject Alternative Names) is null
*
* Server certificate name used in this test: hpzbook-3884Server.crt
*/
@Test
public void testClientAcceptCertificateLocalHost() throws Exception {
System.out.println("Running testClientAcceptCertificateLocalHost");
final AtomicReference<String> certHostNames = new AtomicReference<String>();
final AtomicReference<String[]> certCommontNames = new AtomicReference<String[]>();
final AtomicReference<String[]> certSubjectAltNames = new AtomicReference<String[]>();
String exptdException = "java.net.ConnectException: Failed to connect to localhost";
InetAddress addr = java.net.InetAddress.getLocalHost();
System.out.println("Hostname is : " + addr.getHostName());
TrustManager naiveTrustMgr = new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) {
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
};
// create an SSL context
SSLContext sslContext = SSLContext.getInstance("SSLv3");
sslContext.init(null, new TrustManager[] { naiveTrustMgr }, null);
SSLHostnameVerifier verifier = new SSLHostnameVerifier() {
public void verify(String host, String[] cns, String[] alts) {
System.out.println("SSLHostnameVerifier verify is called.");
//Verify the Certificate details
certHostNames.set(host);
certCommontNames.set(cns);
certSubjectAltNames.set(alts);
}
};
DatabaseClient client = null;
try {
client = DatabaseClientFactory.newClient(host,
restPort,
"admin",
"admin",
Authentication.DIGEST,
sslContext,
verifier);
TextDocumentManager docMgr = client.newTextDocumentManager();
String docId = "/testClientAcceptCertificateLocalHost.txt";
StringHandle handle = new StringHandle();
handle.set("A simple text document");
docMgr.write(docId, handle);
}
catch(Exception ex) {
String str = ex.getMessage();
String[] cns = certCommontNames.get();
String[] dns = certSubjectAltNames.get();
System.out.println("Exception thrown " + str);
assertTrue("Exception expected is incorrect", str.contains(exptdException));
assertTrue("Verifier hostname should have been null", certHostNames.get() == null);
assertTrue("Verifier CNs should have been null", cns == null);
assertTrue("Verifier SANs should have been null", dns == null);
}
finally {
client.release();
}
}
/*
* This test verifies that
* a valid server certificate is available (Note: Server certificate CN=FQDN of the ML Server)
* client can write and read a document to DB with localhost (client and server on diff machines)
* validate the Server certificate's hostname
* validate the Server certificate's CN
* validate the Server certificate's SAN (Subject Alternative Names
*
* OkHttp tests coved: verifyCn()
* assertTrue(verifier.verify("foo.com", session));
* assertFalse(verifier.verify("a.foo.com", session));
* assertFalse(verifier.verify("bar.com", session));
*
* Server certificate name used in this test: hpzbook-3884Server.crt
*/
@Test
public void testClientAcceptCertificateFQDN() throws Exception {
System.out.println("Running testClientAcceptCertificateFQDN");
final AtomicReference<String> certHostNames = new AtomicReference<String>();
final AtomicReference<String[]> certCommontNames = new AtomicReference<String[]>();
final AtomicReference<String[]> certSubjectAltNames = new AtomicReference<String[]>();
InetAddress addr = java.net.InetAddress.getLocalHost();
System.out.println("Hostname is : " + addr.getHostName());
TrustManager naiveTrustMgr = new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) {
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
};
// create an SSL context
SSLContext sslContext = SSLContext.getInstance("SSLv3");
sslContext.init(null, new TrustManager[] { naiveTrustMgr }, null);
SSLHostnameVerifier verifier = new SSLHostnameVerifier() {
public void verify(String host, String[] cns, String[] alts) {
System.out.println("SSLHostnameVerifier verify is called.");
//Verify the Certificate details
certHostNames.set(host);
certCommontNames.set(cns);
certSubjectAltNames.set(alts);
}
};
DatabaseClient client = null;
try {
client = DatabaseClientFactory.newClient(localHostname,
restPort,
"admin",
"admin",
Authentication.DIGEST,
sslContext,
verifier);
TextDocumentManager docMgr = client.newTextDocumentManager();
String docId = "/testClientAcceptCertificateFQDN1.txt";
StringHandle handle = new StringHandle();
handle.set("A simple text document");
docMgr.write(docId, handle);
System.out.println("Doc written");
assertEquals("Text document write difference", "A simple text document",docMgr.read(docId, new StringHandle()).get());
//Verify the Certificate details
String hName = certHostNames.get();
assertTrue(hName.equalsIgnoreCase(localHostname));
String[] altCN = certCommontNames.get();
assertTrue(altCN[0].contains("hpzbook-3884.marklogic.com"));
assertTrue(certSubjectAltNames.get().length == 0);
}
catch(Exception ex) {
System.out.println("Exception thrown " + ex.getMessage());
fail("Unexpected Failure . A DBClient with FQDN and valid server certificate has failed.");
}
finally {
client.release();
}
// Test for "with" methods
try {
client = DatabaseClientFactory.newClient(localHostname, restPort,
new DatabaseClientFactory.DigestAuthContext("admin","admin")
.withSSLContext(sslContext, (X509TrustManager) naiveTrustMgr)
.withSSLHostnameVerifier(verifier)
);
TextDocumentManager docMgr = client.newTextDocumentManager();
String docId = "/testClientAcceptCertificateFQDN2.txt";
StringHandle handle = new StringHandle();
handle.set("A simple text document");
docMgr.write(docId, handle);
System.out.println("Doc written");
assertEquals("Text document write difference", "A simple text document",docMgr.read(docId, new StringHandle()).get());
//Verify the Certificate details
String hName = certHostNames.get();
assertTrue(hName.equalsIgnoreCase(localHostname));
String[] altCN = certCommontNames.get();
assertTrue(altCN[0].contains("hpzbook-3884.marklogic.com"));
assertTrue(certSubjectAltNames.get().length == 0);
}
catch(Exception ex) {
System.out.println("Exception thrown " + ex.getMessage());
fail("Unexpected Failure . A DBClient with FQDN and valid server certificate has failed.");
}
finally {
client.release();
}
try {
client = DatabaseClientFactory.newClient(localHostname, restPort, dbName,
new DatabaseClientFactory.DigestAuthContext("admin","admin")
.withSSLContext(sslContext, (X509TrustManager) naiveTrustMgr)
.withSSLHostnameVerifier(verifier)
);
TextDocumentManager docMgr = client.newTextDocumentManager();
String docId = "/testClientAcceptCertificateFQDN3.txt";
StringHandle handle = new StringHandle();
handle.set("A simple text document");
docMgr.write(docId, handle);
System.out.println("Doc written");
assertEquals("Text document write difference", "A simple text document",docMgr.read(docId, new StringHandle()).get());
//Verify the Certificate details
String hName = certHostNames.get();
assertTrue(hName.equalsIgnoreCase(localHostname));
String[] altCN = certCommontNames.get();
assertTrue(altCN[0].contains("hpzbook-3884.marklogic.com"));
assertTrue(certSubjectAltNames.get().length == 0);
}
catch(Exception ex) {
System.out.println("Exception thrown " + ex.getMessage());
fail("Unexpected Failure . A DBClient with FQDN and valid server certificate has failed.");
}
finally {
client.release();
}
}
/*
* This test with no end user implementation of a verifier instance and using STRICT verifies that
* a valid server certificate is available (Note: Server certificate CN=FQDN of the ML Server)
* client can write and read a document to DB
* Test 1 - DBClient has localhost. Expected Result: Exception.
* Test 2 - DBClient has FQDN. Expected Result: Document written to DB.
* Server certificate name used in this test: hpzbook-3884Server.crt
*/
@Test
public void testClientWithSTRICTAcceptCertificate() throws Exception {
System.out.println("Running testClientWithSTRICTAcceptCertificate");
String expException1 = "javax.net.ssl.SSLPeerUnverifiedException";
String expException2 = "Hostname localhost not verified";
InetAddress addr = java.net.InetAddress.getLocalHost();
System.out.println("Hostname is : " + addr.getHostName());
TrustManager naiveTrustMgr = new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) {
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
};
// create an SSL context
SSLContext sslContext = SSLContext.getInstance("SSLv3");
sslContext.init(null, new TrustManager[] { naiveTrustMgr }, null);
DatabaseClient client = null;
// Pass in the localhost string. Should throw Exception during the write request.
client = DatabaseClientFactory.newClient(host,
restPort,
"admin",
"admin",
Authentication.DIGEST,
sslContext);
TextDocumentManager docMgr = client.newTextDocumentManager();
String docId = "/testClientWithSTRICTAcceptCertificate.txt";
StringHandle handle = new StringHandle();
handle.set("A simple text document");
try {
docMgr.write(docId, handle);
}
catch(Exception ex) {
System.out.println("Exception occurred as expected when localhost is the host with STRICT verifier.");
String msg = ex.getMessage();
System.out.println("Exception thrown " + msg);
assertTrue("Expected exception not thrown", msg.contains(expException1));
assertTrue("Expected exception not thrown", msg.contains(expException2));
}
finally {
client.release();
}
try {
// Use FQDN as entered in the server certificate now.
client = DatabaseClientFactory.newClient(localHostname,
restPort,
"admin",
"admin",
Authentication.DIGEST,
sslContext);
docMgr = client.newTextDocumentManager();
System.out.println("Before Exception");
docMgr.write(docId, handle);
System.out.println("Doc written");
assertEquals("Text document write difference", "A simple text document",docMgr.read(docId, new StringHandle()).get());
}
catch(Exception ex) {
System.out.println("Unexpected exception occurred when host is the FQDN localHostname with STRICT verifier.");
System.out.println(ex.getMessage());
fail("Unexpected exception occurred when host is the FQDN localHostname with STRICT verifier.");
}
finally {
client.release();
}
}
/*
* This test with no end user implementation of a verifier instance and using COMMON verifies that
* a valid server certificate is available (Note: Server certificate CN=FQDN of the ML Server)
* client can write and read a document to DB
*
* Test 1 - DBClient has localhost. Expected Result: Exception.
* Test 2 - DBClient has FQDN. Expected Result: Document written to DB.
*
* Server certificate name used in this test: hpzbook-3884Server.crt
*/
@Test
public void testClientWithCOMMONAcceptCertificate() throws Exception {
System.out.println("Running testClientWithCOMMONAcceptCertificate");
String expException1 = "javax.net.ssl.SSLPeerUnverifiedException";
String expException2 = "Hostname localhost not verified";
InetAddress addr = java.net.InetAddress.getLocalHost();
System.out.println("Hostname is : " + addr.getHostName());
TrustManager naiveTrustMgr = new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) {
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
};
// create an SSL context
SSLContext sslContext = SSLContext.getInstance("SSLv3");
sslContext.init(null, new TrustManager[] { naiveTrustMgr }, null);
DatabaseClient client = null;
// Pass in the localhost string. Should throw Exception during the write request.
client = DatabaseClientFactory.newClient(host,
restPort,
"admin",
"admin",
Authentication.DIGEST,
sslContext,
SSLHostnameVerifier.COMMON);
TextDocumentManager docMgr = client.newTextDocumentManager();
String docId = "/testClientWithCOMMONAcceptCertificate.txt";
StringHandle handle = new StringHandle();
handle.set("A simple text document");
try {
docMgr.write(docId, handle);
}
catch(Exception ex) {
System.out.println("Exception occurred as expected when localhost is the host with COMMON verifier.");
String msg = ex.getMessage();
System.out.println("Exception thrown " + msg);
assertTrue("Expected exception not thrown", msg.contains(expException1));
assertTrue("Expected exception not thrown", msg.contains(expException2));
}
finally {
client.release();
}
try {
// Use FQDN as entered in the server certificate now.
client = DatabaseClientFactory.newClient(localHostname,
restPort,
"admin",
"admin",
Authentication.DIGEST,
sslContext,
SSLHostnameVerifier.COMMON);
docMgr = client.newTextDocumentManager();
docMgr.write(docId, handle);
System.out.println("Doc written");
assertEquals("Text document write difference", "A simple text document",docMgr.read(docId, new StringHandle()).get());
}
catch(Exception ex) {
System.out.println("Unexpected exception occurred when host is the FQDN localHostname with COMMON verifier.");
System.out.println(ex.getMessage());
fail("Unexpected exception occurred when host is the FQDN localHostname with COMMON verifier.");
}
finally {
client.release();
}
}
/*
* This test with no end user implementation of a verifier instance and using STRICT verifies the
* exception message.
* a valid server certificate is available (Note: Server certificate CN=FQDN of the ML Server)
* Test is using a bad hostname. Expected Result: java.net.UnknownHostException
* Server certificate name used in this test: hpzbook-3884Server.crt
*/
@Test
public void testClientWithSTRICTRejectCertificate() throws Exception {
System.out.println("Running testClientWithSTRICTRejectCertificate");
InetAddress addr = java.net.InetAddress.getLocalHost();
System.out.println("Hostname is : " + addr.getHostName());
TrustManager naiveTrustMgr = new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) {
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
};
// create an SSL context
SSLContext sslContext = SSLContext.getInstance("SSLv3");
sslContext.init(null, new TrustManager[] { naiveTrustMgr }, null);
DatabaseClient client = null;
try {
client = DatabaseClientFactory.newClient("BadHostName",
restPort,
"admin",
"admin",
Authentication.DIGEST,
sslContext,
SSLHostnameVerifier.STRICT);
TextDocumentManager docMgr = client.newTextDocumentManager();
String docId = "/testClientWithSTRICTRejectCertificate.txt";
StringHandle handle = new StringHandle();
handle.set("A simple text document");
docMgr.write(docId, handle);
}
catch(Exception ex) {
System.out.println("Exception occurred when host name is BadHostName with STRICT verifier.");
String message = ex.getMessage();
System.out.println(message);
assertTrue("Exception message incorrect", message.contains("java.net.UnknownHostException: badhostname"));
}
finally {
client.release();
}
}
/*
* This test with no end user implementation of a verifier instance and using COMMON verifies the
* exception message.
* a valid server certificate is available (Note: Server certificate CN=FQDN of the ML Server)
* Test is using a bad hostname. Expected Result: java.net.UnknownHostException
* Server certificate name used in this test: hpzbook-3884Server.crt
*/
@Test
public void testClientWithCOMMONTRejectCertificate() throws Exception {
System.out.println("Running testClientWithCOMMONTRejectCertificate");
InetAddress addr = java.net.InetAddress.getLocalHost();
System.out.println("Hostname is : " + addr.getHostName());
TrustManager naiveTrustMgr = new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) {
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
};
// create an SSL context
SSLContext sslContext = SSLContext.getInstance("SSLv3");
sslContext.init(null, new TrustManager[] { naiveTrustMgr }, null);
DatabaseClient client = null;
try {
client = DatabaseClientFactory.newClient("BadHostName",
restPort,
"admin",
"admin",
Authentication.DIGEST,
sslContext,
SSLHostnameVerifier.COMMON);
TextDocumentManager docMgr = client.newTextDocumentManager();
String docId = "/testClientWithCOMMONTRejectCertificate.txt";
StringHandle handle = new StringHandle();
handle.set("A simple text document");
docMgr.write(docId, handle);
}
catch(Exception ex) {
System.out.println("Exception occurred when host name is BadHostName with COMMON verifier.");
String message = ex.getMessage();
System.out.println(message);
assertTrue("Exception message incorrect", message.contains("java.net.UnknownHostException: badhostname"));
}
finally {
client.release();
}
}
/*
* This test verifies that
* a valid WILDCARD server certificate is available (Note: Server certificate CN=*.marklogic.com of the ML Server)
* Test 1: Use marklogic.com in DBClient
* Test 2: Use FQDN of the server in DBClient
* Test 3: Use "'Flower Character'.marklogic.com" in DBClient
* Test 4: Use abc.xyz.machinename.marklogic.com in DBClient
* TEST 5: Use localhost in DBClient
* TEST 6: Throw exception in SSLHostnameVerifier verify method.
* validate the Server certificate's hostname
* validate the Server certificate's CN
* validate the Server certificate's SAN (Subject Alternative Names
*
* Server certificate name used in this test: wildcard-3884Server.crt
* For CN=*.foo.com
* OKHttp test cases covered here are: verifyWilcardCn()
*
* TEST 1 - assertFalse(verifier.verify("foo.com", session));
* TEST 2 - assertTrue(verifier.verify("www.foo.com", session));
* TEST 3 - assertTrue(verifier.verify("\u82b1\u5b50.foo.com", session));
* TEST 4 - assertFalse(verifier.verify("a.b.foo.com", session));
*/
@Test
public void testClientWithWildCardCertificate() throws Exception {
System.out.println("Running testClientWithWildCardCertificate");
final AtomicReference<String> certHostNames1 = new AtomicReference<String>();
final AtomicReference<String[]> certCommontNames1 = new AtomicReference<String[]>();
final AtomicReference<String[]> certSubjectAltNames1 = new AtomicReference<String[]>();
InetAddress addr = java.net.InetAddress.getLocalHost();
System.out.println("Hostname is : " + addr.getHostName());
TrustManager naiveTrustMgr = new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) {
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
};
// create an SSL context
SSLContext sslContext = SSLContext.getInstance("SSLv3");
sslContext.init(null, new TrustManager[] { naiveTrustMgr }, null);
SSLHostnameVerifier verifier1 = new SSLHostnameVerifier() {
public void verify(String host, String[] cns, String[] alts) {
System.out.println("SSLHostnameVerifier verify is called.");
//Verify the Certificate details
certHostNames1.set(host);
certCommontNames1.set(cns);
certSubjectAltNames1.set(alts);
}
};
DatabaseClient client = null;
String test1_expException = "java.net.SocketTimeoutException: connect timed out";
try {
// TEST 1 - DBClient has host = "marklogic.com"
// Expected Result: Doc not written to database java.net.SocketTimeoutException: connect timed out.
client = DatabaseClientFactory.newClient("marklogic.com",
restPort,
"admin",
"admin",
Authentication.DIGEST,
sslContext,
verifier1);
TextDocumentManager docMgr = client.newTextDocumentManager();
String docId = "/testClientWithWildCardCertificate1.txt";
StringHandle handle = new StringHandle();
handle.set("A simple text document");
docMgr.write(docId, handle);
}
catch(Exception ex) {
String msg = ex.getMessage();
System.out.println("Exception thrown " + msg);
assertTrue("Expected exception not thrown ", msg.contains(test1_expException));
}
finally {
client.release();
}
final AtomicReference<String> certHostNames2 = new AtomicReference<String>();
final AtomicReference<String[]> certCommontNames2 = new AtomicReference<String[]>();
final AtomicReference<String[]> certSubjectAltNames2 = new AtomicReference<String[]>();
try {
// TEST 2 - DBClient has host = "FQDN of the server". localHostname = machineName.marklogic.com
// Expected Result: Doc written to database and verifier populates with WILD CARD server certificate details.
SSLHostnameVerifier verifier2 = new SSLHostnameVerifier() {
public void verify(String host, String[] cns, String[] alts) {
System.out.println("SSLHostnameVerifier verify is called.");
//Verify the Certificate details
certHostNames2.set(host);
certCommontNames2.set(cns);
certSubjectAltNames2.set(alts);
}
};
client = DatabaseClientFactory.newClient(localHostname,
restPort,
"admin",
"admin",
Authentication.DIGEST,
sslContext,
verifier2);
TextDocumentManager docMgr = client.newTextDocumentManager();
String docId = "/testClientWithWildCardCertificate2.txt";
StringHandle handle = new StringHandle();
handle.set("A simple text document");
docMgr.write(docId, handle);
System.out.println("Doc with URI /testClientWithWildCardCertificate2.txt written");
assertEquals("Text document write difference", "A simple text document",docMgr.read(docId, new StringHandle()).get());
//Verify the Certificate details
String hName = certHostNames2.get();
assertTrue(hName.equalsIgnoreCase("hpzbook-3884.marklogic.com"));
String[] CN = certCommontNames2.get();
assertTrue(CN[0].contains("*.marklogic.com"));
assertTrue(certSubjectAltNames2.get().length == 0);
}
catch(Exception ex) {
System.out.println("Exception thrown " + ex.getMessage());
fail("Unexpected exception occurred when host DBClient has host = FQDN of the server, with wildcard server certificate.");
}
finally {
client.release();
}
final AtomicReference<String> certHostNames3 = new AtomicReference<String>();
final AtomicReference<String[]> certCommontNames3 = new AtomicReference<String[]>();
final AtomicReference<String[]> certSubjectAltNames3 = new AtomicReference<String[]>();
String test3_expException = "java.net.UnknownHostException";
try {
// TEST 3 - DBClient has host = "'Flower Character'.marklogic.com".
// Expected Result: Doc written to database and verifier populates with WILD CARD server certificate details.
String test3_HostName = "\u82b1\u5b50" + ".marklogic.com";
SSLHostnameVerifier verifier3 = new SSLHostnameVerifier() {
public void verify(String host, String[] cns, String[] alts) {
System.out.println("SSLHostnameVerifier verify is called.");
//Verify the Certificate details
certHostNames3.set(host);
certCommontNames3.set(cns);
certSubjectAltNames3.set(alts);
}
};
client = DatabaseClientFactory.newClient(test3_HostName,
restPort,
"admin",
"admin",
Authentication.DIGEST,
sslContext,
verifier3);
TextDocumentManager docMgr = client.newTextDocumentManager();
String docId = "/testClientWithWildCardCertificate3.txt";
StringHandle handle = new StringHandle();
handle.set("A simple text document");
docMgr.write(docId, handle);
}
catch(Exception ex) {
String msgException = ex.getMessage();
System.out.println("Exception thrown " + msgException);
assertTrue("Expected exception not thrown ", msgException.contains(test3_expException));
}
finally {
client.release();
}
final AtomicReference<String> certHostNames4 = new AtomicReference<String>();
final AtomicReference<String[]> certCommontNames4 = new AtomicReference<String[]>();
final AtomicReference<String[]> certSubjectAltNames4 = new AtomicReference<String[]>();
String test4_expException = "java.net.UnknownHostException";
try {
// TEST 4 - DBClient has host = "abc.xyz.machinename.marklogic.com". localHostname = machineName.marklogic.com
// Expected Result: Doc not written to database and verifier does not populates with WILD CARD server certificate details.
String test4_HostName = "abc.xyz." + localHostname;
SSLHostnameVerifier verifier4 = new SSLHostnameVerifier() {
public void verify(String host, String[] cns, String[] alts) {
System.out.println("SSLHostnameVerifier verify is called.");
//Verify the Certificate details
certHostNames4.set(host);
certCommontNames4.set(cns);
certSubjectAltNames4.set(alts);
}
};
client = DatabaseClientFactory.newClient(test4_HostName,
restPort,
"admin",
"admin",
Authentication.DIGEST,
sslContext,
verifier4);
TextDocumentManager docMgr = client.newTextDocumentManager();
String docId = "/testClientWithWildCardCertificate4.txt";
StringHandle handle = new StringHandle();
handle.set("A simple text document");
docMgr.write(docId, handle);
System.out.println("Doc with URI /testClientWithWildCardCertificate4.txt written");
assertEquals("Text document write difference", "A simple text document",docMgr.read(docId, new StringHandle()).get());
//Verify the Certificate details
String hName = certHostNames4.get();
assertTrue(hName.equalsIgnoreCase("*.marklogic.com"));
String[] CN = certCommontNames4.get();
assertTrue(CN[0].contains("*.marklogic.com"));
assertTrue(certSubjectAltNames4.get().length == 0);
}
catch(Exception ex) {
String msgException = ex.getMessage();
System.out.println("Exception thrown " + msgException);
assertTrue("Expected exception not thrown ", msgException.contains(test4_expException));
}
finally {
client.release();
}
// TEST 5 - localhost
final AtomicReference<String> certHostNames5 = new AtomicReference<String>();
final AtomicReference<String[]> certCommontNames5 = new AtomicReference<String[]>();
final AtomicReference<String[]> certSubjectAltNames5 = new AtomicReference<String[]>();
String test5_expException = "java.net.UnknownHostException";
try {
// TEST 5 - DBClient has "localhost".
String test5_HostName = "localhost";
SSLHostnameVerifier verifier5 = new SSLHostnameVerifier() {
public void verify(String host, String[] cns, String[] alts) {
System.out.println("SSLHostnameVerifier verify is called.");
//Verify the Certificate details
certHostNames5.set(host);
certCommontNames5.set(cns);
certSubjectAltNames5.set(alts);
}
};
client = DatabaseClientFactory.newClient(test5_HostName,
restPort,
"admin",
"admin",
Authentication.DIGEST,
sslContext,
verifier5);
TextDocumentManager docMgr = client.newTextDocumentManager();
String docId = "/testClientWithWildCardCertificate5.txt";
StringHandle handle = new StringHandle();
handle.set("A simple text document");
docMgr.write(docId, handle);
System.out.println("Doc with URI /testClientWithWildCardCertificate5.txt written");
assertEquals("Text document write difference", "A simple text document",docMgr.read(docId, new StringHandle()).get());
//Verify the Certificate details
String hName = certHostNames5.get();
assertTrue(hName.equalsIgnoreCase("localhost"));
String[] CN = certCommontNames5.get();
assertTrue(CN[0].contains("*.marklogic.com"));
assertTrue(certSubjectAltNames5.get().length == 0);
}
catch(Exception ex) {
String msgException = ex.getMessage();
System.out.println("Exception thrown " + msgException);
fail("Unexpected exception occurred when host DBClient has host = FQDN of the server, with wildcard server certificate.");
}
finally {
client.release();
}
// TEST 6 Verifier throws exception.
// Expected Result: Doc not written to database and verifier does not populates with WILD CARD server certificate details.
final AtomicReference<String> certHostNames6 = new AtomicReference<String>();
final AtomicReference<String[]> certCommontNames6 = new AtomicReference<String[]>();
final AtomicReference<String[]> certSubjectAltNames6 = new AtomicReference<String[]>();
try {
SSLHostnameVerifier verifier6 = new SSLHostnameVerifier() {
public void verify(String host, String[] cns, String[] alts) throws SSLException {
System.out.println("SSLHostnameVerifier verify is called in TEST 6.");
//Verify the Certificate details
certHostNames6.set(host);
certCommontNames6.set(cns);
certSubjectAltNames6.set(alts);
throw new SSLException("An exception occurred");
// Initiate a NPE
/*String str = null;
int nLen = str.length();*/
}
};
client = DatabaseClientFactory.newClient(localHostname,
restPort,
"admin",
"admin",
Authentication.DIGEST,
sslContext,
verifier6);
TextDocumentManager docMgr = client.newTextDocumentManager();
String docId = "/testClientWithWildCardCertificate6.txt";
StringHandle handle = new StringHandle();
handle.set("A simple text document");
docMgr.write(docId, handle);
}
catch(Exception ex) {
String msgException = ex.getMessage();
System.out.println("Exception thrown " + msgException);
assertTrue("Expected exception not thrown ", msgException.contains("javax.net.ssl.SSLPeerUnverifiedException"));
assertTrue("Expected exception not thrown ", msgException.contains("DN: [email protected], CN=*.marklogic.com, OU=QA, O=MarkLogic, L=San Carlos, ST=CA, C=US"));
assertTrue("Expected exception not thrown ", msgException.contains("subjectAltNames: []"));
}
finally {
client.release();
}
}
/* oneSAN.conf
* Command to get Subject Alt Names into CSR:
* openssl req -out onesubjalt-3884Server.csr -key kmip-key.pem -new -sha256 -config oneSAN.conf
*
[ req ]
default_bits = 2048
distinguished_name = req_distinguished_name
req_extensions = req_ext
[ req_distinguished_name ]
countryName = Country Name (2 letter code)
stateOrProvinceName = State or Province Name (full name)
localityName = Locality Name (eg, city)
organizationName = Organization Name (eg, company)
organizationalUnitName = Organizational Unit Name (department, division)
emailAddress = Email Address
commonName = Common Name (e.g. server FQDN or YOUR name)
[ req_ext ]
subjectAltName = @alt_names
[alt_names]
DNS.1 = hpzbook-3884.marklogic.com
*/
/*
* This test with end user implementation of a verifier instance verifies that
* a valid server certificate is available (Note: Server certificate CN=foo.com SAN = hpzbook-3884.marklogic.com )
* client can write and read a document to DB.
*
* CN is set to be foo.com and SAN has valid FQDN of the server.
*
* OKHttp Tests covered: verifySubjectAlt()
* CN=foo.com, subjectAlt=bar.com
* assertFalse(verifier.verify("foo.com", session));
* assertFalse(verifier.verify("a.foo.com", session));
* assertTrue(verifier.verify("bar.com", session));
* assertFalse(verifier.verify("a.bar.com", session));
*
* Test 1 - DBClient has FQDN. Expected Result: Doc written, since SAN has the Domain Name (fully FQDN of the server).
* Test 2 - DBClient has foo.com. Expected Result: Exception expected.
* Test 3 - DBClient has abc.FQDN. Expected Result: Exception expected.
* Server certificate name used in this test: onesubjalt-3884Server.crt
* CN=foo.com (from command line)
* SAN (DNS.1)=FQDN of ML Server (from conf file)
*/
@Test
public void testOneInvalidCNOneValidSubjectAlt() throws Exception {
System.out.println("Running testOneInvalidCNOneValidSubjectAlt");
final AtomicReference<String> certHostNames = new AtomicReference<String>();
final AtomicReference<String[]> certCommontNames = new AtomicReference<String[]>();
final AtomicReference<String[]> certSubjectAltNames = new AtomicReference<String[]>();
InetAddress addr = java.net.InetAddress.getLocalHost();
System.out.println("Hostname is : " + addr.getHostName());
TrustManager naiveTrustMgr = new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) {
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
};
// create an SSL context
SSLContext sslContext = SSLContext.getInstance("SSLv3");
sslContext.init(null, new TrustManager[] { naiveTrustMgr }, null);
SSLHostnameVerifier verifier = new SSLHostnameVerifier() {
public void verify(String host, String[] cns, String[] alts) {
System.out.println("SSLHostnameVerifier verify is called in TEST 1.");
//Verify the Certificate details
certHostNames.set(host);
certCommontNames.set(cns);
certSubjectAltNames.set(alts);
}
};
DatabaseClient client = null;
try {
client = DatabaseClientFactory.newClient(localHostname,
restPort,
"admin",
"admin",
Authentication.DIGEST,
sslContext,
verifier);
TextDocumentManager docMgr = client.newTextDocumentManager();
String docId = "/testOneInvalidCNOneValidSubjectAlt1.txt";
StringHandle handle = new StringHandle();
handle.set("A simple text document");
docMgr.write(docId, handle);
System.out.println("Doc written");
assertEquals("Text document write difference", "A simple text document",docMgr.read(docId, new StringHandle()).get());
//Verify the Certificate details
String hName = certHostNames.get();
assertTrue(hName.equalsIgnoreCase(localHostname));
String[] CN = certCommontNames.get();
assertTrue(CN[0].contains("foo.com"));
String[] SAN = certSubjectAltNames.get();
assertTrue(SAN.length == 1);
assertTrue(SAN[0].contains(localHostname));
}
catch(Exception ex) {
System.out.println("Exception thrown " + ex.getMessage());
fail("Unexpected Failure . A DBClient with FQDN in SAN and valid server certificate has failed.");
}
finally {
client.release();
}
//Test 2 - DBClient has foo.com. Expected Result: Exception expected.
final AtomicReference<String> certHostNames2 = new AtomicReference<String>();
final AtomicReference<String[]> certCommontNames2 = new AtomicReference<String[]>();
final AtomicReference<String[]> certSubjectAltNames2 = new AtomicReference<String[]>();
SSLHostnameVerifier verifier2 = new SSLHostnameVerifier() {
public void verify(String host, String[] cns, String[] alts) {
System.out.println("SSLHostnameVerifier verify is called in TEST 2.");
//Verify the Certificate details
certHostNames2.set(host);
certCommontNames2.set(cns);
certSubjectAltNames2.set(alts);
}
};
String expException1 = "java.net.SocketTimeoutException";
String expException2 = "connect timed out";
try {
client = DatabaseClientFactory.newClient("foo.com",
restPort,
"admin",
"admin",
Authentication.DIGEST,
sslContext,
verifier2);
TextDocumentManager docMgr = client.newTextDocumentManager();
String docId = "/testOneInvalidCNOneValidSubjectAlt2.txt";
StringHandle handle = new StringHandle();
handle.set("A simple text document");
docMgr.write(docId, handle);
}
catch(Exception ex) {
String msg = ex.getMessage();
System.out.println("Exception thrown " + msg);
assertTrue("Expected exception not thrown ", msg.contains(expException1));
assertTrue("Expected exception not thrown ", msg.contains(expException2));
}
finally {
client.release();
}
//Test 3 - DBClient has abc.FQDN. Expected Result: Exception expected.
final AtomicReference<String> certHostNames3 = new AtomicReference<String>();
final AtomicReference<String[]> certCommontNames3 = new AtomicReference<String[]>();
final AtomicReference<String[]> certSubjectAltNames3 = new AtomicReference<String[]>();
SSLHostnameVerifier verifier3 = new SSLHostnameVerifier() {
public void verify(String host, String[] cns, String[] alts) {
System.out.println("SSLHostnameVerifier verify is called in TEST 2.");
//Verify the Certificate details
certHostNames3.set(host);
certCommontNames3.set(cns);
certSubjectAltNames3.set(alts);
}
};
String expException31 = "java.net.UnknownHostException";
String hN = "abc." + localHostname;
try {
client = DatabaseClientFactory.newClient(hN,
restPort,
"admin",
"admin",
Authentication.DIGEST,
sslContext,
verifier3);
TextDocumentManager docMgr = client.newTextDocumentManager();
String docId = "/testOneInvalidCNOneValidSubjectAlt3.txt";
StringHandle handle = new StringHandle();
handle.set("A simple text document");
docMgr.write(docId, handle);
}
catch(Exception ex) {
String msg = ex.getMessage();
System.out.println("Exception thrown " + msg);
assertTrue("Expected exception not thrown ", msg.contains(expException31));
assertTrue("Expected exception not thrown ", msg.contains(hN));
}
finally {
client.release();
}
}
/* oneSAN.conf
* Command to get Subject Alt Names into CSR:
* openssl req -out onesubjalt-3884Server.csr -key kmip-key.pem -new -sha256 -config oneSAN.conf
*
[ req ]
default_bits = 2048
distinguished_name = req_distinguished_name
req_extensions = req_ext
[ req_distinguished_name ]
countryName = Country Name (2 letter code)
stateOrProvinceName = State or Province Name (full name)
localityName = Locality Name (eg, city)
organizationName = Organization Name (eg, company)
organizationalUnitName = Organizational Unit Name (department, division)
emailAddress = Email Address
commonName = Common Name (e.g. server FQDN or YOUR name)
[ req_ext ]
subjectAltName = @alt_names
[alt_names]
DNS.1 = hpzbook-3884.marklogic.com
*/
/*
* This test with end user implementation of a verifier instance verifies that
* a valid server certificate is available (Note: Server certificate CN=hpzbook-3884.marklogic.com SAN = hpzbook-3884.marklogic.com)
* client can write and read a document to DB.
*
* CN is set to be hpzbook-3884.marklogic.com and SAN has valid FQDN of the server.
*
* Test 1 - DBClient has FQDN. Expected Result: Doc written, since SAN DNS.1 has the Domain Name (fully FQDN of the server).
* Test 2 - DBClient has foo.com. Expected Result: Exception expected.
* Server certificate name used in this test: cnAndSubjSame-3884Server.crt
* CN=hpzbook-3884.marklogic.com (from command line)
* SAN (DNS.1)=hpzbook-3884.marklogic.com (from conf file)
*/
@Test
public void testCNEqualSubject() throws Exception {
System.out.println("Running testCNEqualSubject");
final AtomicReference<String> certHostNames = new AtomicReference<String>();
final AtomicReference<String[]> certCommontNames = new AtomicReference<String[]>();
final AtomicReference<String[]> certSubjectAltNames = new AtomicReference<String[]>();
InetAddress addr = java.net.InetAddress.getLocalHost();
System.out.println("Hostname is : " + addr.getHostName());
TrustManager naiveTrustMgr = new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) {
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
};
// create an SSL context
SSLContext sslContext = SSLContext.getInstance("SSLv3");
sslContext.init(null, new TrustManager[] { naiveTrustMgr }, null);
SSLHostnameVerifier verifier = new SSLHostnameVerifier() {
public void verify(String host, String[] cns, String[] alts) {
System.out.println("SSLHostnameVerifier verify is called in testCNEqualSubject.");
//Verify the Certificate details
certHostNames.set(host);
certCommontNames.set(cns);
certSubjectAltNames.set(alts);
}
};
DatabaseClient client = null;
try {
client = DatabaseClientFactory.newClient(localHostname,
restPort,
"admin",
"admin",
Authentication.DIGEST,
sslContext,
verifier);
TextDocumentManager docMgr = client.newTextDocumentManager();
String docId = "/testCNEqualSubject1.txt";
StringHandle handle = new StringHandle();
handle.set("A simple text document");
docMgr.write(docId, handle);
System.out.println("Doc written");
assertEquals("Text document write difference", "A simple text document",docMgr.read(docId, new StringHandle()).get());
//Verify the Certificate details
String hName = certHostNames.get();
assertTrue(hName.equalsIgnoreCase(localHostname));
String[] CN = certCommontNames.get();
assertTrue(CN[0].contains(localHostname));
String[] SAN = certSubjectAltNames.get();
assertTrue(SAN.length == 1);
assertTrue(SAN[0].contains(localHostname));
}
catch(Exception ex) {
System.out.println("Exception thrown " + ex.getMessage());
fail("Unexpected Failure . A DBClient with FQDN in SAN and valid server certificate has failed.");
}
finally {
client.release();
}
// TEST 2 - DBClient has foo.com. Expected Result: Exception expected.
final AtomicReference<String> certHostNames2 = new AtomicReference<String>();
final AtomicReference<String[]> certCommontNames2 = new AtomicReference<String[]>();
final AtomicReference<String[]> certSubjectAltNames2 = new AtomicReference<String[]>();
SSLHostnameVerifier verifier2 = new SSLHostnameVerifier() {
public void verify(String host, String[] cns, String[] alts) {
System.out.println("SSLHostnameVerifier verify is called in TEST 2.");
//Verify the Certificate details
certHostNames2.set(host);
certCommontNames2.set(cns);
certSubjectAltNames2.set(alts);
}
};
String expException21 = "java.net.SocketTimeoutException";
String expException22 = "connect timed out";
try {
client = DatabaseClientFactory.newClient("foo.com",
restPort,
"admin",
"admin",
Authentication.DIGEST,
sslContext,
verifier2);
TextDocumentManager docMgr = client.newTextDocumentManager();
String docId = "/testCNEqualSubject2.txt";
StringHandle handle = new StringHandle();
handle.set("A simple text document");
docMgr.write(docId, handle);
}
catch(Exception ex) {
String msg = ex.getMessage();
System.out.println("Exception thrown " + msg);
assertTrue("Expected exception not thrown ", msg.contains(expException21));
assertTrue("Expected exception not thrown ", msg.contains(expException22));
}
finally {
client.release();
}
// TEST 3 - DBClient has abc.FQDN. Expected Result: Exception expected.
final AtomicReference<String> certHostNames3 = new AtomicReference<String>();
final AtomicReference<String[]> certCommontNames3 = new AtomicReference<String[]>();
final AtomicReference<String[]> certSubjectAltNames3 = new AtomicReference<String[]>();
SSLHostnameVerifier verifier3 = new SSLHostnameVerifier() {
public void verify(String host, String[] cns, String[] alts) {
System.out.println("SSLHostnameVerifier verify is called in TEST 2.");
//Verify the Certificate details
certHostNames3.set(host);
certCommontNames3.set(cns);
certSubjectAltNames3.set(alts);
}
};
String expException31 = "java.net.UnknownHostException:";
String hN = "abc." + localHostname;
try {
client = DatabaseClientFactory.newClient(hN,
restPort,
"admin",
"admin",
Authentication.DIGEST,
sslContext,
verifier2);
TextDocumentManager docMgr = client.newTextDocumentManager();
String docId = "/testCNEqualSubject2.txt";
StringHandle handle = new StringHandle();
handle.set("A simple text document");
docMgr.write(docId, handle);
}
catch(Exception ex) {
String msg = ex.getMessage();
System.out.println("Exception thrown " + msg);
assertTrue("Expected exception not thrown ", msg.contains(expException31));
assertTrue("Expected exception not thrown ", msg.contains(hN));
}
finally {
client.release();
}
}
// multiSAN.conf
/*
[ req ]
default_bits = 2048
distinguished_name = req_distinguished_name
req_extensions = req_ext
[ req_distinguished_name ]
countryName = Country Name (2 letter code)
stateOrProvinceName = State or Province Name (full name)
localityName = Locality Name (eg, city)
organizationName = Organization Name (eg, company)
organizationalUnitName = Organizational Unit Name (department, division)
emailAddress = Email Address
commonName = Common Name (e.g. server FQDN or YOUR name)
[ req_ext ]
subjectAltName = @alt_names
[alt_names]
DNS.1 = 3884.marklogic.com
DNS.2 = bar.com
DNS.3 = hpzbook-3884.marklogic.com
*/
// openssl req -out multiSubj-3884Server.csr -key kmip-key.pem -new -sha256 -config multiSAN.conf
/*
* This test with end user implementation of a verifier instance verifies that
* a valid server certificate is available (Note: Server certificate CN=*.marklogic.com SAN DNS.3 = hpzbook-3884.marklogic.com)
* client can write and read a document to DB.
*
* CN is set to be *.marklogic.com and SAN DNS.3 has valid FQDN of the server.
*
* Test 1 - DBClient has FQDN. Expected Result: Doc written, since SAN DNS.3 has the Domain Name (fully FQDN of the server).
* Test 2 - DBClient has foo.marklogic.com. Expected Result: Exception expected.
* Server certificate name used in this test: multiSubj-3884Server.crt
* CN=*.marklogic.com (from command line)
* SAN (DNS.3)=hpzbook-3884.marklogic.com (from conf file)
*/
@Test
public void testWildCnAndMultiSubject() throws Exception {
System.out.println("Running testWildCnAndMultiSubject");
final AtomicReference<String> certHostNames = new AtomicReference<String>();
final AtomicReference<String[]> certCommontNames = new AtomicReference<String[]>();
final AtomicReference<String[]> certSubjectAltNames = new AtomicReference<String[]>();
InetAddress addr = java.net.InetAddress.getLocalHost();
System.out.println("Hostname is : " + addr.getHostName());
TrustManager naiveTrustMgr = new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) {
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
};
// create an SSL context
SSLContext sslContext = SSLContext.getInstance("SSLv3");
sslContext.init(null, new TrustManager[] { naiveTrustMgr }, null);
SSLHostnameVerifier verifier = new SSLHostnameVerifier() {
public void verify(String host, String[] cns, String[] alts) {
System.out.println("SSLHostnameVerifier verify is called in testWildCnAndMultiSubject.");
//Verify the Certificate details
certHostNames.set(host);
certCommontNames.set(cns);
certSubjectAltNames.set(alts);
}
};
DatabaseClient client = null;
try {
client = DatabaseClientFactory.newClient(localHostname,
restPort,
"admin",
"admin",
Authentication.DIGEST,
sslContext,
verifier);
TextDocumentManager docMgr = client.newTextDocumentManager();
String docId = "/testWildCnAndMultiSubject1.txt";
StringHandle handle = new StringHandle();
handle.set("A simple text document");
docMgr.write(docId, handle);
System.out.println("Doc written");
assertEquals("Text document write difference", "A simple text document",docMgr.read(docId, new StringHandle()).get());
//Verify the Certificate details
String hName = certHostNames.get();
assertTrue(hName.equalsIgnoreCase(localHostname));
String[] CN = certCommontNames.get();
assertTrue(CN[0].contains("*.marklogic.com"));
String[] SAN = certSubjectAltNames.get();
Arrays.sort(SAN);
assertTrue(SAN.length == 3);
assertTrue(SAN[0].contains("3884.marklogic.com"));
assertTrue(SAN[1].contains("bar.com"));
assertTrue(SAN[2].contains(localHostname));
}
catch(Exception ex) {
System.out.println("Exception thrown " + ex.getMessage());
fail("Unexpected Failure . A DBClient with FQDN in SAN DNS.3 and valid server certificate has failed.");
}
finally {
client.release();
}
// TEST 2 - DBClient has foo.marklogic.com. Expected Result: Exception expected.
final AtomicReference<String> certHostNames2 = new AtomicReference<String>();
final AtomicReference<String[]> certCommontNames2 = new AtomicReference<String[]>();
final AtomicReference<String[]> certSubjectAltNames2 = new AtomicReference<String[]>();
SSLHostnameVerifier verifier2 = new SSLHostnameVerifier() {
public void verify(String host, String[] cns, String[] alts) {
System.out.println("SSLHostnameVerifier verify is called in TEST 2.");
//Verify the Certificate details
certHostNames2.set(host);
certCommontNames2.set(cns);
certSubjectAltNames2.set(alts);
}
};
String expException21 = "java.net.UnknownHostException";
String expException22 = "foo.marklogic.com";
try {
client = DatabaseClientFactory.newClient("foo.marklogic.com",
restPort,
"admin",
"admin",
Authentication.DIGEST,
sslContext,
verifier2);
TextDocumentManager docMgr = client.newTextDocumentManager();
String docId = "/testWildCnAndMultiSubject2.txt";
StringHandle handle = new StringHandle();
handle.set("A simple text document");
docMgr.write(docId, handle);
}
catch(Exception ex) {
String msg = ex.getMessage();
System.out.println("Exception thrown " + msg);
assertTrue("Expected exception not thrown ", msg.contains(expException21));
assertTrue("Expected exception not thrown ", msg.contains(expException22));
}
finally {
client.release();
}
// TEST 3 - DBClient has abc.FQDN. Expected Result: Exception expected.
final AtomicReference<String> certHostNames3 = new AtomicReference<String>();
final AtomicReference<String[]> certCommontNames3 = new AtomicReference<String[]>();
final AtomicReference<String[]> certSubjectAltNames3 = new AtomicReference<String[]>();
SSLHostnameVerifier verifier3 = new SSLHostnameVerifier() {
public void verify(String host, String[] cns, String[] alts) {
System.out.println("SSLHostnameVerifier verify is called in TEST 2.");
//Verify the Certificate details
certHostNames3.set(host);
certCommontNames3.set(cns);
certSubjectAltNames3.set(alts);
}
};
String expException31 = "java.net.UnknownHostException:";
String hN = "abc." + localHostname;
try {
client = DatabaseClientFactory.newClient(hN,
restPort,
"admin",
"admin",
Authentication.DIGEST,
sslContext,
verifier2);
TextDocumentManager docMgr = client.newTextDocumentManager();
String docId = "/testCNEqualSubject2.txt";
StringHandle handle = new StringHandle();
handle.set("A simple text document");
docMgr.write(docId, handle);
}
catch(Exception ex) {
String msg = ex.getMessage();
System.out.println("Exception thrown " + msg);
assertTrue("Expected exception not thrown ", msg.contains(expException31));
assertTrue("Expected exception not thrown ", msg.contains(hN));
}
finally {
client.release();
}
}
}
The above tests has some of the combinations that can be run on one-on-one basis (manually).
Hi @georgeajit . can you please confirm this. Thanks.!
Closing since it has a label of "Closed"