diff --git a/cadcTomcat/build.xml b/cadcTomcat/build.xml index a07f5a5de3dcfafdeb18237ed08f98ed24a4d3aa..10ba07f943c3d5a215cfb98b7d402531de1a6399 100644 --- a/cadcTomcat/build.xml +++ b/cadcTomcat/build.xml @@ -136,7 +136,7 @@ </classpath> <test name="ca.nrc.cadc.tomcat.CadcBasicAuthenticatorTest"/> - <test name="ca.nrc.cadc.tomcat.RealmRegistryClientTest"/> + <test name="ca.nrc.cadc.tomcat.AuthenticationLookupTest"/> <formatter type="plain" usefile="false"/> </junit> </target> diff --git a/cadcTomcat/src/ca/nrc/cadc/tomcat/RealmRegistryClient.java b/cadcTomcat/src/ca/nrc/cadc/tomcat/AuthenticationLookup.java similarity index 60% rename from cadcTomcat/src/ca/nrc/cadc/tomcat/RealmRegistryClient.java rename to cadcTomcat/src/ca/nrc/cadc/tomcat/AuthenticationLookup.java index ae3032899be9cbd5ee5a2e27bc99165c10f11660..c8d7a1b109fcb6a5c0cc200229c32aa072cbd088 100644 --- a/cadcTomcat/src/ca/nrc/cadc/tomcat/RealmRegistryClient.java +++ b/cadcTomcat/src/ca/nrc/cadc/tomcat/AuthenticationLookup.java @@ -69,21 +69,13 @@ package ca.nrc.cadc.tomcat; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; import java.net.InetAddress; import java.net.MalformedURLException; -import java.net.URI; import java.net.URL; import java.net.UnknownHostException; -import java.util.List; import org.apache.log4j.Logger; -import java.util.ArrayList; -import java.util.ListIterator; - /** * A very simple caching IVOA Registry client. All the lookups done by this client use a properties @@ -102,52 +94,26 @@ import java.util.ListIterator; * <pre> * ca.nrc.cadc.reg.client.RegistryClient.host=www.example.com * </pre> - * + * <p> * This class is a forked and trimmed version of ca.nrc.cadc.reg.client.RegistryClient. It was forked * to allow the realm implementation to be deployed without library dependencies. * * @author pdowler */ -public class RealmRegistryClient +public class AuthenticationLookup { - private static Logger log = Logger.getLogger(RealmRegistryClient.class); + private static Logger log = Logger.getLogger(AuthenticationLookup.class); - private static final String CACHE_FILENAME = "RegistryClient.properties"; private static final String LOCAL_PROPERTY = "ca.nrc.cadc.reg.client.RegistryClient.local"; private static final String HOST_PROPERTY = "ca.nrc.cadc.reg.client.RegistryClient.host"; private static final String SHORT_HOST_PROPERTY = "ca.nrc.cadc.reg.client.RegistryClient.shortHostname"; - private URL url; - private RealmMultiValuedProperties mvp; - private String hostname; private String shortHostname; - /** - * Constructor. Uses a properties file called RegistryClient.properties found in the classpath. - */ - public RealmRegistryClient() - { - try - { - File conf = new File(System.getProperty("user.home") + "/config", CACHE_FILENAME); - URL furl; - if (conf.exists()) - furl = new URL("file://" + conf.getAbsolutePath()); - else - furl = RealmRegistryClient.class.getResource("/"+CACHE_FILENAME); - - init(furl, false); - } - catch(Exception ex) - { - throw new RuntimeException("failed to find URL to " + CACHE_FILENAME, ex); - } - } - private void init(URL url, boolean unused) + private void init() { - this.url = url; try { String localP = System.getProperty(LOCAL_PROPERTY); @@ -157,10 +123,12 @@ public class RealmRegistryClient log.debug(" local: " + localP); log.debug(" host: " + hostP); log.debug("shortHost: " + shortHostP); - if ( "true".equals(localP) ) + if ("true".equals(localP)) { - log.debug(LOCAL_PROPERTY + " is set, assuming localhost runs the service"); - this.hostname = InetAddress.getLocalHost().getCanonicalHostName(); + log.debug(LOCAL_PROPERTY + + " is set, assuming localhost runs the service"); + this.hostname = InetAddress.getLocalHost() + .getCanonicalHostName(); } if (shortHostP != null) @@ -176,66 +144,36 @@ public class RealmRegistryClient { hostP = hostP.trim(); if (hostP.length() > 0) + { this.hostname = hostP; + } } } - catch(UnknownHostException ex) + catch (UnknownHostException ex) { - log.warn("failed to find localhost name via name resolution (" + ex.toString() + "): using localhost"); + log.warn("failed to find localhost name via name resolution (" + + ex.toString() + "): using localhost"); this.hostname = "localhost"; } } - public URL getServiceURL(URI serviceID, String protocol, String path) - throws MalformedURLException + public URL configureAuthenticationServiceURL(URL serviceURL) + throws MalformedURLException { init(); - log.debug("getServiceURL: " + serviceID + "," + protocol + "," + path); - - //List<URL> urls = lookup.get(serviceID); - List<String> strs = mvp.getProperty(serviceID.toString()); - if (strs == null || strs.isEmpty() ) - { - return null; // no matching serviceURI - } - List<Service> srvs = new ArrayList<Service>(strs.size()); - for (String s : strs) - { - srvs.add(new Service(s)); - } - - String testproto = protocol + "://"; - ListIterator<Service> iter = srvs.listIterator(); - while ( iter.hasNext() ) - { - Service srv = iter.next(); - boolean noMatch = false; - if (protocol != null && !srv.url.startsWith(testproto)) - noMatch = true; // wrong protocol - if (noMatch) - { - iter.remove(); - log.debug("getServiceURL: constraints not matched: " + srv + " vs " + protocol); - } - else - log.debug("getServiceURL: found match: " + srv + " vs " + protocol); - } - if (srvs.isEmpty()) - return null; - - Service srv = srvs.get(0); // first match + log.debug("configureAuthenticationServiceURL: " + serviceURL + "," + + serviceURL.getProtocol() + "," + serviceURL.getPath()); - StringBuilder sb = new StringBuilder(); + final StringBuilder sb = new StringBuilder(); if (hostname != null || shortHostname != null) { - URL ret = new URL(srv.url); - sb.append(ret.getProtocol()); + sb.append(serviceURL.getProtocol()); sb.append("://"); if (shortHostname != null) { String hname = shortHostname; - String fqhn = ret.getHost(); + String fqhn = serviceURL.getHost(); int i = fqhn.indexOf('.'); if (i > 0) { @@ -248,78 +186,19 @@ public class RealmRegistryClient { sb.append(hostname); } - int p = ret.getPort(); - if (p > 0 && p != ret.getDefaultPort()) + int p = serviceURL.getPort(); + if (p > 0 && p != serviceURL.getDefaultPort()) { sb.append(":"); sb.append(p); } - sb.append(ret.getPath()); + sb.append(serviceURL.getPath()); } else - sb.append(srv.url); - - if (path != null) - sb.append(path); - - return new URL(sb.toString()); - } - - private class Service - { - String str; - String url; - - public String toString() { return str; } - Service(String s) { - this.str = s; - String[] parts = s.split(" "); - this.url = parts[0]; + sb.append(serviceURL); } - } - private void init() - { - if (mvp != null) - return; - - InputStream istream = null; - try - { - // find the cache resource from the url - if (url == null) - throw new RuntimeException("failed to find cache resource."); - // read the properties - log.debug("init: reading config from " + url); - istream = url.openStream(); - this.mvp = new RealmMultiValuedProperties(); - mvp.load(istream); - - if (log.isDebugEnabled()) - { - for (String k : mvp.keySet()) - { - List<String> values = mvp.getProperty(k); - for (String v : values) - { - log.debug(k + " = " + v); - } - } - } - } - catch(IOException ex) - { - throw new RuntimeException("failed to load resource: " + CACHE_FILENAME, ex); - } - finally - { - if (istream != null) - try { istream.close(); } - catch(Throwable t) - { - log.warn("failed to close " + url, t); - } - } + return new URL(sb.toString()); } } diff --git a/cadcTomcat/src/ca/nrc/cadc/tomcat/CadcBasicAuthenticator.java b/cadcTomcat/src/ca/nrc/cadc/tomcat/CadcBasicAuthenticator.java index 5aedbbc2dfb1d4a4649b629145a0dac672969877..87e2a8eefaa68f5d354d4b4b503f0de0b46a6e90 100644 --- a/cadcTomcat/src/ca/nrc/cadc/tomcat/CadcBasicAuthenticator.java +++ b/cadcTomcat/src/ca/nrc/cadc/tomcat/CadcBasicAuthenticator.java @@ -71,11 +71,9 @@ package ca.nrc.cadc.tomcat; import java.io.IOException; import java.net.HttpURLConnection; -import java.net.URI; -import java.net.URISyntaxException; import java.net.URL; import java.security.Principal; -import java.util.Arrays; +import java.util.Collections; import java.util.List; import org.apache.catalina.realm.GenericPrincipal; @@ -83,11 +81,12 @@ import org.apache.catalina.realm.RealmBase; import org.apache.log4j.Level; import org.apache.log4j.Logger; + /** * Custom class for Tomcat realm authentication. - * + * <p> * This class was written against the Apache Tomcat 7 (7.0.33.0) API - * + * <p> * Authentication checks are performed as REST calls to servers * implementing the cadcAccessControl-Server code. * @@ -97,7 +96,9 @@ public class CadcBasicAuthenticator extends RealmBase { private static Logger log = Logger.getLogger(CadcBasicAuthenticator.class); - private static final String AC_URI = "ivo://ivoa.net/std/UMS#login-0.1"; + + private String loginURL; + static { @@ -105,6 +106,17 @@ public class CadcBasicAuthenticator extends RealmBase Logger.getLogger("ca.nrc.cadc.tomcat").setLevel(Level.INFO); } + /** + * Set the login URL for the current host. Used by the realm configuration. + * + * @param loginURL The String login URL. + */ + public void setLoginURL(final String loginURL) + { + this.loginURL = loginURL; + } + + @Override protected String getName() { @@ -139,7 +151,7 @@ public class CadcBasicAuthenticator extends RealmBase if (valid) { // authentication ok, add public role - List<String> roles = Arrays.asList("public"); + List<String> roles = Collections.singletonList("public"); // Don't want to return the password here in the principal // in case it makes it into the servlet somehow @@ -151,7 +163,8 @@ public class CadcBasicAuthenticator extends RealmBase catch (Throwable t) { success = false; - String message = "Could not do http basic authentication: " + t.getMessage(); + String message = "Could not do http basic authentication: " + + t.getMessage(); log.error(message, t); throw new IllegalStateException(message, t); } @@ -159,28 +172,30 @@ public class CadcBasicAuthenticator extends RealmBase { long duration = System.currentTimeMillis() - start; - StringBuilder json = new StringBuilder(); - json.append("{"); - json.append("\"method\":\"AUTH\","); - json.append("\"user\":\"" + username + "\","); - json.append("\"success\":" + success + ","); - json.append("\"time\":" + duration); - json.append("}"); + // Converted from StringBuilder as it was unnecessary. + // jenkinsd 2016.08.09 + String json = "{" + + "\"method\":\"AUTH\"," + + "\"user\":\"" + username + "\"," + + "\"success\":" + success + "," + + "\"time\":" + duration + + "}"; - log.info(json.toString()); + log.info(json); } } boolean login(String username, String credentials) - throws URISyntaxException, IOException + throws IOException { - RealmRegistryClient registryClient = new RealmRegistryClient(); - URL loginURL = registryClient.getServiceURL( - new URI(AC_URI + "#login"), "http", ""); - + AuthenticationLookup registryClient = new AuthenticationLookup(); + URL authServiceURL = + registryClient.configureAuthenticationServiceURL( + new URL(loginURL)); String post = "username=" + username + "&password=" + credentials; - HttpURLConnection conn = (HttpURLConnection) loginURL.openConnection(); + HttpURLConnection conn = + (HttpURLConnection) authServiceURL.openConnection(); conn.setRequestMethod("POST"); conn.setDoOutput(true); @@ -190,7 +205,7 @@ public class CadcBasicAuthenticator extends RealmBase int responseCode = conn.getResponseCode(); log.debug("Http POST to /ac/login returned " + - responseCode + " for user " + username); + responseCode + " for user " + username); if (responseCode != 200) { @@ -199,7 +214,8 @@ public class CadcBasicAuthenticator extends RealmBase { // not an unauthorized, so log the // possible server side error - String errorMessage = "Error calling /ac/login, error code: " + responseCode; + String errorMessage = "Error calling /ac/login, error code: " + + responseCode; throw new IllegalStateException(errorMessage); } @@ -211,5 +227,4 @@ public class CadcBasicAuthenticator extends RealmBase } - } diff --git a/cadcTomcat/test/src/ca/nrc/cadc/tomcat/RealmRegistryClientTest.java b/cadcTomcat/test/src/ca/nrc/cadc/tomcat/AuthenticationLookupTest.java similarity index 60% rename from cadcTomcat/test/src/ca/nrc/cadc/tomcat/RealmRegistryClientTest.java rename to cadcTomcat/test/src/ca/nrc/cadc/tomcat/AuthenticationLookupTest.java index e77b56f73df4eae48b36f1436b81120d29855884..6165fc33001c7371e15d019b7cc46050c2c4b4e4 100644 --- a/cadcTomcat/test/src/ca/nrc/cadc/tomcat/RealmRegistryClientTest.java +++ b/cadcTomcat/test/src/ca/nrc/cadc/tomcat/AuthenticationLookupTest.java @@ -70,6 +70,7 @@ package ca.nrc.cadc.tomcat; import java.net.InetAddress; +import java.net.MalformedURLException; import java.net.URI; import java.net.URL; @@ -84,12 +85,12 @@ import org.junit.Test; /** - * * @author pdowler */ -public class RealmRegistryClientTest +public class AuthenticationLookupTest { - private static Logger log = Logger.getLogger(RealmRegistryClientTest.class); + private static Logger log = Logger + .getLogger(AuthenticationLookupTest.class); static { @@ -130,120 +131,58 @@ public class RealmRegistryClientTest { } - static String DUMMY_URI = "ivo://example.com/srv"; - static String DUMMY_URL = "http://www.example.com/current/path/to/my/service"; - static String DUMMY_CERT_URL = "https://www.example.com/current/path/to/my/service"; - static String DUMMY_PASSWORD_URL = "http://www.example.com/current/path/to/my/auth-service"; - static String DUMMY_TOKEN_URL = DUMMY_URL; - static String DUMMY_COOKIE_URL = DUMMY_URL; + static URL DUMMY_URL; - @Test - public void testNotFound() throws Exception + static { try { - RealmRegistryClient rc = new RealmRegistryClient(); - - URL url = rc.getServiceURL(new URI("ivo://foo/bar"), null, null); - Assert.assertNull(url); + DUMMY_URL = new URL( + "http://www.example.com/current/path/to/my/service"); } - catch(Exception unexpected) + catch (MalformedURLException e) { - log.error("unexpected exception", unexpected); - Assert.fail("unexpected exception: " + unexpected); + // Will never happen. } } + @Test public void testFound() throws Exception { - try - { - RealmRegistryClient rc = new RealmRegistryClient(); + AuthenticationLookup authLookup = new AuthenticationLookup(); - URL expected = new URL(DUMMY_URL); - URL url = rc.getServiceURL(new URI(DUMMY_URI), null, null); - Assert.assertEquals(expected, url); - } - catch(Exception unexpected) - { - log.error("unexpected exception", unexpected); - Assert.fail("unexpected exception: " + unexpected); - } + URL url = authLookup.configureAuthenticationServiceURL(DUMMY_URL); + Assert.assertEquals(DUMMY_URL, url); } - @Test - public void testFoundViaConfigFile() throws Exception - { - String home = System.getProperty("user.home"); - try - { - String fakeHome = System.getProperty("user.dir") + "/test"; - log.debug("setting user.home = " + fakeHome); - System.setProperty("user.home", fakeHome); - RealmRegistryClient rc = new RealmRegistryClient(); - - URL expected = new URL("http://alt.example.com/current/path/to/my/service"); - URL url = rc.getServiceURL(new URI("ivo://example.com/srv"), "http", null); - Assert.assertEquals(expected, url); - } - catch(Exception unexpected) - { - log.error("unexpected exception", unexpected); - Assert.fail("unexpected exception: " + unexpected); - } - finally - { - // reset - System.setProperty("user.home", home); - } - } - - - @Test - public void testFoundWithProtocol() throws Exception - { - try - { - RealmRegistryClient rc = new RealmRegistryClient(); - - URL expected = new URL(DUMMY_URL); - URL url = rc.getServiceURL(new URI(DUMMY_URI), "http", null); - Assert.assertEquals(expected, url); - - expected = new URL(DUMMY_CERT_URL); - url = rc.getServiceURL(new URI(DUMMY_URI), "https", null); - Assert.assertEquals(expected, url); - } - catch(Exception unexpected) - { - log.error("unexpected exception", unexpected); - Assert.fail("unexpected exception: " + unexpected); - } - } @Test public void testFoundLocal() throws Exception { try { - System.setProperty("ca.nrc.cadc.reg.client.RegistryClient.local", "true"); - RealmRegistryClient rc = new RealmRegistryClient(); + System.setProperty("ca.nrc.cadc.reg.client.RegistryClient.local", + "true"); + AuthenticationLookup authLookup = new AuthenticationLookup(); - String localhost = InetAddress.getLocalHost().getCanonicalHostName(); - URL expected = new URL("http://" + localhost + "/current/path/to/my/service"); + String localhost = InetAddress.getLocalHost() + .getCanonicalHostName(); + URL expected = new URL("http://" + localhost + + "/current/path/to/my/service"); - URL url = rc.getServiceURL(new URI(DUMMY_URI), null, null); + URL url = authLookup.configureAuthenticationServiceURL(DUMMY_URL); Assert.assertEquals(expected, url); } - catch(Exception unexpected) + catch (Exception unexpected) { log.error("unexpected exception", unexpected); Assert.fail("unexpected exception: " + unexpected); } finally { - System.setProperty("ca.nrc.cadc.reg.client.RegistryClient.local", "false"); + System.setProperty("ca.nrc.cadc.reg.client.RegistryClient.local", + "false"); } } @@ -252,23 +191,27 @@ public class RealmRegistryClientTest { try { - System.setProperty("ca.nrc.cadc.reg.client.RegistryClient.host", "foo.bar.com"); - RealmRegistryClient rc = new RealmRegistryClient(); + System.setProperty("ca.nrc.cadc.reg.client.RegistryClient.host", + "foo.bar.com"); + AuthenticationLookup authLookup = new AuthenticationLookup(); - URL url = rc.getServiceURL(new URI(DUMMY_URI), null, null); - Assert.assertEquals("http://foo.bar.com/current/path/to/my/service", url.toExternalForm()); + URL url = authLookup.configureAuthenticationServiceURL(DUMMY_URL); + Assert.assertEquals("http://foo.bar.com/current/path/to/my/service", + url.toExternalForm()); - url = rc.getServiceURL(new URI(DUMMY_URI), null, null); - Assert.assertEquals("http://foo.bar.com/current/path/to/my/service", url.toExternalForm()); + url = authLookup.configureAuthenticationServiceURL(DUMMY_URL); + Assert.assertEquals("http://foo.bar.com/current/path/to/my/service", + url.toExternalForm()); } - catch(Exception unexpected) + catch (Exception unexpected) { log.error("unexpected exception", unexpected); Assert.fail("unexpected exception: " + unexpected); } finally { - System.setProperty("ca.nrc.cadc.reg.client.RegistryClient.host", ""); + System.setProperty("ca.nrc.cadc.reg.client.RegistryClient.host", + ""); } } @@ -277,21 +220,26 @@ public class RealmRegistryClientTest { try { - System.setProperty("ca.nrc.cadc.reg.client.RegistryClient.shortHostname", "foo"); - RealmRegistryClient rc = new RealmRegistryClient(); + System.setProperty( + "ca.nrc.cadc.reg.client.RegistryClient.shortHostname", + "foo"); + AuthenticationLookup authLookup = new AuthenticationLookup(); - URL url = rc.getServiceURL(new URI(DUMMY_URI), null, null); - Assert.assertEquals("http://foo.example.com/current/path/to/my/service", url.toExternalForm()); + URL url = authLookup.configureAuthenticationServiceURL(DUMMY_URL); + Assert.assertEquals( + "http://foo.example.com/current/path/to/my/service", + url.toExternalForm()); } - catch(Exception unexpected) + catch (Exception unexpected) { log.error("unexpected exception", unexpected); Assert.fail("unexpected exception: " + unexpected); } finally { - System.setProperty("ca.nrc.cadc.reg.client.RegistryClient.shortHostname", ""); + System.setProperty( + "ca.nrc.cadc.reg.client.RegistryClient.shortHostname", ""); } } } diff --git a/cadcTomcat/test/src/ca/nrc/cadc/tomcat/CadcBasicAuthenticatorTest.java b/cadcTomcat/test/src/ca/nrc/cadc/tomcat/CadcBasicAuthenticatorTest.java index 1e713b84654289f9866abf59eab3120fa50feb72..c791fbccb0e50961e33133fae7d1ad260128b371 100644 --- a/cadcTomcat/test/src/ca/nrc/cadc/tomcat/CadcBasicAuthenticatorTest.java +++ b/cadcTomcat/test/src/ca/nrc/cadc/tomcat/CadcBasicAuthenticatorTest.java @@ -71,7 +71,6 @@ package ca.nrc.cadc.tomcat; import java.io.IOException; -import java.net.URISyntaxException; import junit.framework.Assert; @@ -80,10 +79,12 @@ import org.apache.log4j.Level; import org.apache.log4j.Logger; import org.junit.Test; + public class CadcBasicAuthenticatorTest { - private static Logger log = Logger.getLogger(CadcBasicAuthenticatorTest.class); + private static Logger log = + Logger.getLogger(CadcBasicAuthenticatorTest.class); static { @@ -97,7 +98,8 @@ public class CadcBasicAuthenticatorTest try { TestAuthenticator auth = new TestAuthenticator(true); - GenericPrincipal p = (GenericPrincipal) auth.authenticate("user", "pass"); + GenericPrincipal p = (GenericPrincipal) auth.authenticate("user", + "pass"); Assert.assertNotNull(p); Assert.assertEquals("wrong num roles", 1, p.getRoles().length); @@ -117,7 +119,8 @@ public class CadcBasicAuthenticatorTest try { TestAuthenticator auth = new TestAuthenticator(false); - GenericPrincipal p = (GenericPrincipal) auth.authenticate("user", "pass"); + GenericPrincipal p = (GenericPrincipal) auth.authenticate("user", + "pass"); Assert.assertNull(p); } @@ -138,8 +141,7 @@ public class CadcBasicAuthenticatorTest } @Override - boolean login(String username, String credentials) - throws URISyntaxException, IOException + boolean login(String username, String credentials) throws IOException { return authenticate; }