From 7019c5d5f0846e17016674d758e4b0a2692760fb Mon Sep 17 00:00:00 2001 From: remillet Date: Fri, 8 Jul 2016 16:01:47 -0700 Subject: [PATCH] CSPACE-6984: Adding support for SSL connections to Shared Authority server. --- .../vocabulary/AuthorityServiceUtils.java | 41 ++++++++------- .../nuxeo/AuthorityDocumentModelHandler.java | 49 ++++++++++++------ .../client/AbstractServiceClientImpl.java | 50 +++++++++++++++++-- .../services/client/AuthorityClient.java | 7 ++- .../services/client/AuthorityClientImpl.java | 12 +++++ .../services/client/AuthorityProxy.java | 11 ++++ .../client/CollectionSpaceClient.java | 6 ++- .../services/common/ServiceMessages.java | 2 +- 8 files changed, 138 insertions(+), 40 deletions(-) diff --git a/services/authority/service/src/main/java/org/collectionspace/services/common/vocabulary/AuthorityServiceUtils.java b/services/authority/service/src/main/java/org/collectionspace/services/common/vocabulary/AuthorityServiceUtils.java index d1d10e173..5c81fa9fc 100644 --- a/services/authority/service/src/main/java/org/collectionspace/services/common/vocabulary/AuthorityServiceUtils.java +++ b/services/authority/service/src/main/java/org/collectionspace/services/common/vocabulary/AuthorityServiceUtils.java @@ -22,7 +22,10 @@ import org.collectionspace.services.config.tenant.RemoteClientConfigurations; import org.collectionspace.services.config.tenant.TenantBindingType; import org.collectionspace.services.nuxeo.client.java.CoreSessionInterface; import org.collectionspace.services.nuxeo.util.NuxeoUtils; -import org.dom4j.DocumentException; +import org.collectionspace.services.common.document.DocumentException; + +//import org.dom4j.DocumentException; +import org.eclipse.jetty.http.HttpStatus; import org.nuxeo.ecm.core.api.DocumentModel; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -121,14 +124,16 @@ public class AuthorityServiceUtils { Response res = client.read(specifier.getURNValue()); try { int statusCode = res.getStatus(); - - // Check the status code of the response: does it match - // the expected response(s)? - if (logger.isDebugEnabled()) { - logger.debug(client.getClass().getCanonicalName() + ": status = " + statusCode); + if (statusCode == HttpStatus.OK_200) { + result = new PoxPayloadIn((String)res.readEntity(responseType)); // Get the entire response! + } else { + String errMsg = String.format("Could not retrieve authority information for '%s' on remote server '%s'. Server returned status code %d", + specifier.getURNValue(), remoteClientConfig.getUrl(), statusCode); + if (logger.isDebugEnabled()) { + logger.debug(errMsg); + } + throw new DocumentException(statusCode, errMsg); } - - result = new PoxPayloadIn((String)res.readEntity(responseType)); // Get the entire response! } finally { res.close(); } @@ -155,14 +160,16 @@ public class AuthorityServiceUtils { try { int statusCode = res.getStatus(); - - // Check the status code of the response: does it match - // the expected response(s)? - if (logger.isDebugEnabled()) { - logger.debug(client.getClass().getCanonicalName() + ": status = " + statusCode); - } - - result = new PoxPayloadIn((String)res.readEntity(responseType)); // Get the entire response! + if (statusCode == HttpStatus.OK_200) { + result = new PoxPayloadIn((String)res.readEntity(responseType)); // Get the entire response. + } else { + String errMsg = String.format("Could not retrieve authority item information for '%s:%s' on remote server '%s'. Server returned status code %d", + specifier.getParentSpecifier().getURNValue(), specifier.getItemSpecifier().getURNValue(), remoteClientConfig.getUrl(), statusCode); + if (logger.isDebugEnabled()) { + logger.debug(errMsg); + } + throw new DocumentException(statusCode, errMsg); + } } finally { res.close(); } @@ -188,7 +195,7 @@ public class AuthorityServiceUtils { * refnames with the correct domain name */ static public PoxPayloadIn filterRefnameDomains(ServiceContext ctx, - PoxPayloadIn payload) throws DocumentException { + PoxPayloadIn payload) throws org.dom4j.DocumentException { PoxPayloadIn result = null; diff --git a/services/authority/service/src/main/java/org/collectionspace/services/common/vocabulary/nuxeo/AuthorityDocumentModelHandler.java b/services/authority/service/src/main/java/org/collectionspace/services/common/vocabulary/nuxeo/AuthorityDocumentModelHandler.java index 87b6720f4..30016a379 100644 --- a/services/authority/service/src/main/java/org/collectionspace/services/common/vocabulary/nuxeo/AuthorityDocumentModelHandler.java +++ b/services/authority/service/src/main/java/org/collectionspace/services/common/vocabulary/nuxeo/AuthorityDocumentModelHandler.java @@ -63,8 +63,8 @@ import org.collectionspace.services.nuxeo.client.java.NuxeoDocumentModelHandler; import org.collectionspace.services.nuxeo.client.java.CoreSessionInterface; import org.collectionspace.services.nuxeo.client.java.RepositoryClientImpl; import org.collectionspace.services.nuxeo.util.NuxeoUtils; - import org.dom4j.Element; +import org.eclipse.jetty.http.HttpStatus; import org.nuxeo.ecm.core.api.ClientException; import org.nuxeo.ecm.core.api.DocumentModel; import org.slf4j.Logger; @@ -144,7 +144,7 @@ public abstract class AuthorityDocumentModelHandler // // Long sasRev = getRevision(sasPayloadIn); - if (sasRev > localRev) { + if (sasRev > localRev || true) { // FIXME: Along with the revision number, we need to use other meta information to determine if a sync should happen -for now, alway sync // // First, sync all the authority items // @@ -492,7 +492,18 @@ public abstract class AuthorityDocumentModelHandler return result; // -1 = no sync needed/possible, 0 = sync'd, 1 = created new item - } + } + + private void assertStatusCode(Response res, Specifier specifier, AuthorityClient client) throws Exception { + int statusCode = res.getStatus(); + + if (statusCode != HttpStatus.OK_200) { + String errMsg = String.format("Could not retrieve authority information for '%s' on remote server '%s'. Server returned status code %d", + specifier.getURNValue(), client.getBaseURL(), statusCode); + res.close(); + throw new DocumentException(statusCode, errMsg); + } + } /** * Request an authority item list payload from the SAS server. @@ -504,22 +515,32 @@ public abstract class AuthorityDocumentModelHandler */ private PoxPayloadIn requestPayloadInItemList(ServiceContext ctx, Specifier specifier) throws Exception { PoxPayloadIn result = null; - AuthorityClient client = (AuthorityClient) ctx.getClient(); + // + // First find out how many items exist Response res = client.readItemList(specifier.getURNValue(), null, // partial term string - null // keyword string + null, // keyword string + 0, // page size + 0 // page number ); + assertStatusCode(res, specifier, client); + AbstractCommonList commonList = res.readEntity(AbstractCommonList.class); + res.close(); + long numOfItems = commonList.getTotalItems(); + + // + // Next, request a payload list with all the items + res = client.readItemList(specifier.getURNValue(), + null, // partial term string + null, // keyword string + numOfItems, // page size + 0 // page number + ); + assertStatusCode(res, specifier, client); + try { - int statusCode = res.getStatus(); - - // Check the status code of the response: does it match - // the expected response(s)? - if (logger.isDebugEnabled()) { - logger.debug(client.getClass().getCanonicalName() + ": status = " + statusCode); - } - - result = new PoxPayloadIn((String)res.readEntity(getEntityResponseType())); // Get the entire response! + result = new PoxPayloadIn((String)res.readEntity(getEntityResponseType())); // Get the entire response. } finally { res.close(); } diff --git a/services/client/src/main/java/org/collectionspace/services/client/AbstractServiceClientImpl.java b/services/client/src/main/java/org/collectionspace/services/client/AbstractServiceClientImpl.java index 1b1665b7f..010cf33eb 100644 --- a/services/client/src/main/java/org/collectionspace/services/client/AbstractServiceClientImpl.java +++ b/services/client/src/main/java/org/collectionspace/services/client/AbstractServiceClientImpl.java @@ -47,10 +47,44 @@ import org.jboss.resteasy.plugins.providers.RegisterBuiltin; import org.jboss.resteasy.spi.ResteasyProviderFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; + // FIXME: Deprecated classes that need to be updated import org.jboss.resteasy.client.ProxyFactory; import org.apache.http.impl.client.DefaultHttpClient; +import org.apache.http.conn.ssl.SSLContexts; + +import java.security.SecureRandom; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import javax.net.ssl.SSLContext; +import javax.net.ssl.X509TrustManager; + +/** + * Private class for SSL support + */ +class HttpsTrustManager implements X509TrustManager { + + @Override + public void checkClientTrusted(X509Certificate[] arg0, String arg1) + throws CertificateException { + // TODO Auto-generated method stub + + } + + @Override + public void checkServerTrusted(X509Certificate[] arg0, String arg1) + throws CertificateException { + // TODO Auto-generated method stub + + } + + @Override + public X509Certificate[] getAcceptedIssuers() { + return new X509Certificate[]{}; + } + +} /** * Private class for JAX-RS authentication @@ -498,17 +532,23 @@ public abstract class AbstractServiceClientImpl proxyClass = this.getProxyClass(); + if (useSSL()) { + SSLContext sslcontext = SSLContexts.custom().useSSL().build(); + sslcontext.init(null, new X509TrustManager[]{new HttpsTrustManager()}, new SecureRandom()); + client = (ResteasyClient)ClientBuilder.newBuilder().sslContext(sslcontext).build(); + } else { + client = (ResteasyClient)ClientBuilder.newClient(); + } + if (useAuth()) { String user = properties.getProperty(USER_PROPERTY); String password = properties.getProperty(PASSWORD_PROPERTY); - client = (ResteasyClient)ClientBuilder.newClient().register(new Authenticator(user, password)); - } else { - client = (ResteasyClient)ClientBuilder.newClient(); + client = client.register(new Authenticator(user, password)); } proxy = client.target(urlString).proxy(proxyClass); @@ -532,7 +572,7 @@ public abstract class AbstractServiceClientImpl