diff --git a/authentication/source/java/ch/systemsx/cisd/authentication/DummyAuthenticationService.java b/authentication/source/java/ch/systemsx/cisd/authentication/DummyAuthenticationService.java index 91cabbd442a740b88f908c9c0698d133c712a7e8..c5e247303cf219b3e0052f24612d79fbf33bef5f 100644 --- a/authentication/source/java/ch/systemsx/cisd/authentication/DummyAuthenticationService.java +++ b/authentication/source/java/ch/systemsx/cisd/authentication/DummyAuthenticationService.java @@ -186,4 +186,10 @@ public final class DummyAuthenticationService implements IAuthenticationService // Always available. } + @Override + public boolean isConfigured() + { + return true; + } + } \ No newline at end of file diff --git a/authentication/source/java/ch/systemsx/cisd/authentication/IAuthenticationService.java b/authentication/source/java/ch/systemsx/cisd/authentication/IAuthenticationService.java index f5d376ab4885338de1fe4e41471a4ae60f76c06d..2c19cf1ca0ea4b6864248049d2fa81022ffd7ea0 100644 --- a/authentication/source/java/ch/systemsx/cisd/authentication/IAuthenticationService.java +++ b/authentication/source/java/ch/systemsx/cisd/authentication/IAuthenticationService.java @@ -27,6 +27,11 @@ import ch.systemsx.cisd.common.utilities.ISelfTestable; */ public interface IAuthenticationService extends ISelfTestable { + /** + * Returns <code>true</code> if this authentication service is configured. + */ + public boolean isConfigured(); + /** * Attempts authentication for the given user credentials. * diff --git a/authentication/source/java/ch/systemsx/cisd/authentication/NullAuthenticationService.java b/authentication/source/java/ch/systemsx/cisd/authentication/NullAuthenticationService.java index 431ad69385889055dfc692146a8c22b88db936e4..8d86a580994472c2ded9fcdfe49270fa739f4308 100644 --- a/authentication/source/java/ch/systemsx/cisd/authentication/NullAuthenticationService.java +++ b/authentication/source/java/ch/systemsx/cisd/authentication/NullAuthenticationService.java @@ -157,4 +157,10 @@ public class NullAuthenticationService implements IAuthenticationService return null; } + @Override + public boolean isConfigured() + { + return false; + } + } diff --git a/authentication/source/java/ch/systemsx/cisd/authentication/crowd/CrowdAuthenticationService.java b/authentication/source/java/ch/systemsx/cisd/authentication/crowd/CrowdAuthenticationService.java index fad6abe05528ddf1ed309fac475d77b38e419a46..e5b364e894ff3fa4efedc85b5b39af7ad59fde07 100644 --- a/authentication/source/java/ch/systemsx/cisd/authentication/crowd/CrowdAuthenticationService.java +++ b/authentication/source/java/ch/systemsx/cisd/authentication/crowd/CrowdAuthenticationService.java @@ -59,7 +59,8 @@ import ch.systemsx.cisd.common.logging.LogFactory; */ public class CrowdAuthenticationService implements IAuthenticationService { - private static final int CONNECTION_TIMEOUT = (int) (5 * DateUtils.MILLIS_PER_MINUTE); + private static final int DEFAULT_CONNECTION_TIMEOUT_MILLIS = + (int) (5 * DateUtils.MILLIS_PER_MINUTE); private static final String DUMMY_TOKEN_STR = "DUMMY-TOKEN"; @@ -133,7 +134,7 @@ public class CrowdAuthenticationService implements IAuthenticationService + " </soap:Body>\n" + "</soap:Envelope>\n"); - private static IRequestExecutor createExecutor() + private static IRequestExecutor createExecutor(final int timeoutMillis) { return new IRequestExecutor() { @@ -149,7 +150,7 @@ public class CrowdAuthenticationService implements IAuthenticationService { final HttpClient client = new HttpClient(); final PostMethod post = new PostMethod(serviceUrl); - post.getParams().setSoTimeout(CONNECTION_TIMEOUT); + post.getParams().setSoTimeout(timeoutMillis); final StringRequestEntity entity = new StringRequestEntity(message, "application/soap+xml", "utf-8"); post.setRequestEntity(entity); @@ -178,15 +179,36 @@ public class CrowdAuthenticationService implements IAuthenticationService private final String applicationPassword; - private final IRequestExecutor requestExecutor; + private final boolean configured; + private final IRequestExecutor requestExecutor; + private final AtomicReference<String> applicationTokenHolder = new AtomicReference<String>(); + public CrowdAuthenticationService(CrowdConfiguration configuration) + { + this.url = configuration.getServerURL(); + this.application = configuration.getApplication(); + this.applicationPassword = configuration.getApplicationPassword(); + this.configured = configuration.isConfigured(); + this.requestExecutor = createExecutor(configuration.getTimeout()); + if (operationLog.isDebugEnabled()) + { + final String msg = + "A new CrowdAuthenticationService instance has been created for [" + "url=" + + url + ", application=" + application + "], timeout: " + + ((configuration.getTimeout() == 0) ? "-." : (configuration.getTimeout() + / 1000 + " s.")); + operationLog.debug(msg); + } + } + + // Keep this constructor for backward compatibility with old Spring application context files. public CrowdAuthenticationService(final String host, final String port, final String application, final String applicationPassword) { this("https://" + host + ":" + checkPort(port) + "/crowd/services/SecurityServer", - application, applicationPassword, createExecutor()); + application, applicationPassword, createExecutor(DEFAULT_CONNECTION_TIMEOUT_MILLIS)); } CrowdAuthenticationService(final String url, final String application, @@ -196,6 +218,7 @@ public class CrowdAuthenticationService implements IAuthenticationService this.application = application; this.applicationPassword = applicationPassword; this.requestExecutor = requestExecutor; + this.configured = true; if (operationLog.isDebugEnabled()) { final String msg = @@ -643,4 +666,10 @@ public class CrowdAuthenticationService implements IAuthenticationService return false; } + @Override + public boolean isConfigured() + { + return configured; + } + } diff --git a/authentication/source/java/ch/systemsx/cisd/authentication/crowd/CrowdConfiguration.java b/authentication/source/java/ch/systemsx/cisd/authentication/crowd/CrowdConfiguration.java new file mode 100644 index 0000000000000000000000000000000000000000..6f0c159ffa70ac8d618978e605cad2fb850669f6 --- /dev/null +++ b/authentication/source/java/ch/systemsx/cisd/authentication/crowd/CrowdConfiguration.java @@ -0,0 +1,208 @@ +/* + * Copyright 2013 ETH Zuerich, CISD + * + * 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 ch.systemsx.cisd.authentication.crowd; + +import org.apache.commons.lang.StringUtils; + +/** + * A configuration object for Crowd. + * + * @author Bernd Rinn + */ +public class CrowdConfiguration +{ + private String host; + + private int port = 443; + + private String application; + + private String applicationPassword; + + private int timeout = 10000; + + /** + * Returns the host of the Crowd service. + */ + public String getHost() + { + return host; + } + + /** + * Sets the host of the Crowd service. + */ + public void setHost(String host) + { + if (isResolved(host)) + { + this.host = host; + } + } + + /** + * Returns the port that the Crowd service is running on. + */ + public int getPort() + { + return port; + } + + /** + * Sets the port that the Crowd service is running on. + */ + public void setPort(int port) + { + if (port > 0) + { + this.port = port; + } + } + + /** + * Returns the port that the Crowd service is running on (as String). + */ + public String getPortStr() + { + return Integer.toString(port); + } + + /** + * Sets the port (as String) that the Crowd service is running on. Only set if a positive integer. + */ + public void setPortStr(String portStr) + { + if (isResolved(portStr)) + { + try + { + setPort(Integer.parseInt(portStr)); + } catch (NumberFormatException ex) + { + // Not set. + } + } + } + + /** + * Returns the server URL of the Crowd service. + */ + public String getServerURL() + { + if (isConfigured()) + { + return "https://" + host + ":" + port + "/crowd/services/SecurityServer"; + } else + { + return null; + } + } + + /** + * Returns the application name that this application sends to the Crowd service. + */ + public String getApplication() + { + return application; + } + + /** + * Sets the application name that this application sends to the Crowd service. + */ + public void setApplication(String application) + { + if (isResolved(application)) + { + this.application = application; + } + } + + /** + * Returns the application password that this application sends to the Crowd service. + */ + public String getApplicationPassword() + { + return applicationPassword; + } + + /** + * Sets the application password that this application sends to the Crowd service. + */ + public void setApplicationPassword(String applicationPassword) + { + if (isResolved(applicationPassword)) + { + this.applicationPassword = applicationPassword; + } + } + + /** + * Returns the timeout, i.e. how long to wait for a result from Crowd (in ms). + */ + public int getTimeout() + { + return timeout; + } + + /** + * Sets the timeout, i.e. how long to wait for a result from Crowd (in ms). + */ + public void setTimeout(int timeoutMillis) + { + this.timeout = (timeoutMillis < 0) ? 0 : timeoutMillis; + } + + /** + * Sets the timeout, i.e. how long to wait for a result from Crowd (as String, in s). + */ + public void setTimeoutStr(String timeoutStr) + { + if (isResolved(timeoutStr)) + { + try + { + setTimeout(Integer.parseInt(timeoutStr) * 1000); + } catch (NumberFormatException ex) + { + // Not set. + } + } + } + + /** + * Returns the timeout, i.e. how long to wait for a result from Crowd (as String, in s). + */ + public String getTimeoutStr() + { + return Integer.toString(getTimeout() / 1000); + } + + /** + * Returns <code>true</code> if the configuration is complete. + */ + public boolean isConfigured() + { + return StringUtils.isNotBlank(host) && StringUtils.isNotBlank(application) + && StringUtils.isNotBlank(applicationPassword); + } + + private static boolean isResolved(String name) + { + return StringUtils.isNotBlank(name) && name.startsWith("${") == false; + } + +} diff --git a/authentication/source/java/ch/systemsx/cisd/authentication/file/CachingAuthenticationService.java b/authentication/source/java/ch/systemsx/cisd/authentication/file/CachingAuthenticationService.java index 1b59ea56adea4db4bea5491ac6f64eb915905164..d9ca05b94a00e7f45ec55049d63e478b7c63c9f2 100644 --- a/authentication/source/java/ch/systemsx/cisd/authentication/file/CachingAuthenticationService.java +++ b/authentication/source/java/ch/systemsx/cisd/authentication/file/CachingAuthenticationService.java @@ -576,4 +576,10 @@ public class CachingAuthenticationService implements IAuthenticationService delegate.check(); } + @Override + public boolean isConfigured() + { + return delegate.isConfigured(); + } + } diff --git a/authentication/source/java/ch/systemsx/cisd/authentication/file/FileAuthenticationService.java b/authentication/source/java/ch/systemsx/cisd/authentication/file/FileAuthenticationService.java index 94dff20a1ceda1566c6efa3e0feaacc73e9a02b9..d8fefeee771b14ff59f6a50ba8bf88b8ff9542e7 100644 --- a/authentication/source/java/ch/systemsx/cisd/authentication/file/FileAuthenticationService.java +++ b/authentication/source/java/ch/systemsx/cisd/authentication/file/FileAuthenticationService.java @@ -57,6 +57,10 @@ public class FileAuthenticationService implements IAuthenticationService private static IUserStore<? extends UserEntry> createUserStore(final String passwordFileName) { + if (passwordFileName == null) + { + return null; + } final ILineStore lineStore = new FileBasedLineStore(new File(passwordFileName), "Password file"); return createUserStore(lineStore); @@ -306,4 +310,10 @@ public class FileAuthenticationService implements IAuthenticationService return (listingServiceOrNull != null) && listingServiceOrNull.isRemote(); } + @Override + public boolean isConfigured() + { + return userStore != null; + } + } diff --git a/authentication/source/java/ch/systemsx/cisd/authentication/ldap/LDAPAuthenticationService.java b/authentication/source/java/ch/systemsx/cisd/authentication/ldap/LDAPAuthenticationService.java index 7c0c63715655b6be0eef63e0626f932a84ecb42d..ea31ac5d5b40c860bf3d3b86e4cdd770638ab8c1 100644 --- a/authentication/source/java/ch/systemsx/cisd/authentication/ldap/LDAPAuthenticationService.java +++ b/authentication/source/java/ch/systemsx/cisd/authentication/ldap/LDAPAuthenticationService.java @@ -40,10 +40,13 @@ public class LDAPAuthenticationService implements IAuthenticationService LogFactory.getLogger(LogCategory.OPERATION, LDAPAuthenticationService.class); private final LDAPPrincipalQuery query; + + private final boolean configured; public LDAPAuthenticationService(LDAPDirectoryConfiguration config) { query = new LDAPPrincipalQuery(config); + this.configured = config.isConfigured(); } @Override @@ -198,4 +201,10 @@ public class LDAPAuthenticationService implements IAuthenticationService return query.isRemote(); } + @Override + public boolean isConfigured() + { + return configured; + } + } diff --git a/authentication/source/java/ch/systemsx/cisd/authentication/ldap/LDAPDirectoryConfiguration.java b/authentication/source/java/ch/systemsx/cisd/authentication/ldap/LDAPDirectoryConfiguration.java index 12170485865a5e822d7ced97cb56a0112e634caa..51bffb5695735cdc243dec4dce94e3757da9c911 100644 --- a/authentication/source/java/ch/systemsx/cisd/authentication/ldap/LDAPDirectoryConfiguration.java +++ b/authentication/source/java/ch/systemsx/cisd/authentication/ldap/LDAPDirectoryConfiguration.java @@ -37,8 +37,9 @@ import org.apache.commons.lang.StringUtils; public final class LDAPDirectoryConfiguration { - static final String DEFAULT_QUERY_TEMPLATE = "(&(objectClass=organizationalPerson)(objectCategory=person)" - + "(objectClass=user)(%s))"; + static final String DEFAULT_QUERY_TEMPLATE = + "(&(objectClass=organizationalPerson)(objectCategory=person)" + + "(objectClass=user)(%s))"; private String userIdAttributeName = "uid"; @@ -47,11 +48,11 @@ public final class LDAPDirectoryConfiguration private String firstNameAttributeName = "givenName"; private String emailAttributeName = "mail"; - + private String emailAliasesAttributeName = "proxyAddresses"; - + private String emailAttributePrefix = "smtp:"; - + private String queryEmailForAliases = "false"; private String securityProtocol = "ssl"; @@ -59,11 +60,11 @@ public final class LDAPDirectoryConfiguration private String securityAuthenticationMethod = "simple"; private String referral = "follow"; - + private long timeout = 10000L; - + private int maxRetries = 1; - + private long timeToWaitAfterFailure = 10000L; private String queryTemplate = @@ -75,6 +76,16 @@ public final class LDAPDirectoryConfiguration private String securityPrincipalPassword; + /** + * Returns <code>true</code> if this configuration is complete. + */ + public boolean isConfigured() + { + return StringUtils.isNotBlank(serverUrl) + && StringUtils.isNotBlank(securityPrincipalDistinguishedName) + && StringUtils.isNotBlank(securityPrincipalPassword); + } + /** * Default value: <code>uid</code> */ @@ -161,8 +172,8 @@ public final class LDAPDirectoryConfiguration } /** - * If the query for emails should use the email aliases instead of the canonical email addresses. - * + * If the query for emails should use the email aliases instead of the canonical email + * addresses. * Default: <code>false</code>. */ public void setQueryEmailForAliases(String queryEmailForAliases) @@ -316,29 +327,27 @@ public final class LDAPDirectoryConfiguration /** * The read timeout (in ms). - * * Default value: <code>-1</code> (which means: wait forever) */ public String getTimeoutStr() { - return Long.toString(timeout); + return Long.toString(timeout / 1000); } /** - * Set the read timeout (in ms). + * Set the read timeout (in s). */ public void setTimeoutStr(String timeoutMillis) { if (isResolved(timeoutMillis)) { - this.timeout = Long.parseLong(timeoutMillis); + this.timeout = Long.parseLong(timeoutMillis) * 1000L; } } /** * The time to wait after failure before retrying (in ms). - * - * Default value: <code>-1</code> (which means: wait forever) + * Default value: <code>10000</code> (10s) */ public long getTimeToWaitAfterFailure() { @@ -346,13 +355,12 @@ public final class LDAPDirectoryConfiguration } /** - * The time to wait after failure before retrying (in ms). - * - * Default value: <code>-1</code> (which means: wait forever) + * The time to wait after failure before retrying (in s). + * Default value: <code>10</code> */ public String getTimeToWaitAfterFailureStr() { - return Long.toString(timeToWaitAfterFailure); + return Long.toString(timeToWaitAfterFailure / 1000); } /** @@ -362,13 +370,12 @@ public final class LDAPDirectoryConfiguration { if (isResolved(timeToWaitOnFailureMillis)) { - this.timeToWaitAfterFailure = Long.parseLong(timeToWaitOnFailureMillis); + this.timeToWaitAfterFailure = Long.parseLong(timeToWaitOnFailureMillis) * 1000L; } } /** * The maximum number of times a failed query is retried. - * * Default value: <code>9</code> */ public int getMaxRetries() @@ -378,7 +385,6 @@ public final class LDAPDirectoryConfiguration /** * The maximum number of times a failed query is retried. - * * Default value: <code>9</code> */ public String getMaxRetriesStr() @@ -416,5 +422,5 @@ public final class LDAPDirectoryConfiguration { return StringUtils.isNotBlank(name) && name.startsWith("${") == false; } - + } diff --git a/authentication/source/java/ch/systemsx/cisd/authentication/stacked/StackedAuthenticationService.java b/authentication/source/java/ch/systemsx/cisd/authentication/stacked/StackedAuthenticationService.java index 4a7ec39f6a6f04b87d67569e4d71fddd42535963..f0453fa60cd413189d60290cb0931bc3de1452a5 100644 --- a/authentication/source/java/ch/systemsx/cisd/authentication/stacked/StackedAuthenticationService.java +++ b/authentication/source/java/ch/systemsx/cisd/authentication/stacked/StackedAuthenticationService.java @@ -41,12 +41,12 @@ public class StackedAuthenticationService implements IAuthenticationService private final boolean supportsListingByEmail; private final boolean supportsListingByLastName; - + private final boolean supportsAuthenticatingByEmail; public StackedAuthenticationService(List<IAuthenticationService> authenticationServices) { - this.delegates = authenticationServices; + this.delegates = filterConfigured(authenticationServices); boolean foundRemote = false; boolean foundSupportsListingByUserId = false; boolean foundSupportsListingByEmail = false; @@ -67,6 +67,21 @@ public class StackedAuthenticationService implements IAuthenticationService this.supportsAuthenticatingByEmail = foundSupportsAuthenticateByEmail; } + private static List<IAuthenticationService> filterConfigured( + List<IAuthenticationService> services) + { + final List<IAuthenticationService> configuredServices = + new ArrayList<IAuthenticationService>(services.size()); + for (IAuthenticationService service : services) + { + if (service.isConfigured()) + { + configuredServices.add(service); + } + } + return configuredServices; + } + @Override public String authenticateApplication() { @@ -260,4 +275,10 @@ public class StackedAuthenticationService implements IAuthenticationService return remote; } + @Override + public boolean isConfigured() + { + return (delegates.isEmpty() == false); + } + } diff --git a/authentication/sourceTest/java/ch/systemsx/cisd/authentication/stacked/StackedAuthenticationServiceTest.java b/authentication/sourceTest/java/ch/systemsx/cisd/authentication/stacked/StackedAuthenticationServiceTest.java index 8b633549fbc0ee31240029de17e3f4b8105bed1e..c5e9c97f8a885a8afd1e06df8bbf453053cd7fcb 100644 --- a/authentication/sourceTest/java/ch/systemsx/cisd/authentication/stacked/StackedAuthenticationServiceTest.java +++ b/authentication/sourceTest/java/ch/systemsx/cisd/authentication/stacked/StackedAuthenticationServiceTest.java @@ -43,6 +43,8 @@ public class StackedAuthenticationServiceTest private IAuthenticationService authService2; + private IAuthenticationService authService3; + private IAuthenticationService stackedAuthService; @BeforeMethod @@ -51,11 +53,29 @@ public class StackedAuthenticationServiceTest context = new Mockery(); authService1 = context.mock(IAuthenticationService.class, "auth service 1"); authService2 = context.mock(IAuthenticationService.class, "auth service 2"); + authService3 = context.mock(IAuthenticationService.class, "auth service 3"); addStandardExpectations(); + addAlways(); stackedAuthService = - new StackedAuthenticationService(Arrays.asList(authService1, authService2)); + new StackedAuthenticationService(Arrays.asList(authService1, authService2, + authService3)); } + private void addAlways() + { + context.checking(new Expectations() + { + { + allowing(authService1).isConfigured(); + will(returnValue(true)); + allowing(authService2).isConfigured(); + will(returnValue(true)); + allowing(authService3).isConfigured(); + will(returnValue(false)); + } + }); + } + private void addStandardExpectations() { context.checking(new Expectations() @@ -66,7 +86,7 @@ public class StackedAuthenticationServiceTest one(authService1).supportsListingByEmail(); one(authService1).supportsListingByLastName(); one(authService1).supportsAuthenticatingByEmail(); - + one(authService2).isRemote(); one(authService2).supportsListingByUserId(); one(authService2).supportsListingByEmail(); @@ -92,6 +112,7 @@ public class StackedAuthenticationServiceTest one(authService2).check(); } }); + assertTrue(stackedAuthService.isConfigured()); stackedAuthService.check(); context.assertIsSatisfied(); } @@ -123,6 +144,7 @@ public class StackedAuthenticationServiceTest context = new Mockery(); authService1 = context.mock(IAuthenticationService.class, "auth service 1"); authService2 = context.mock(IAuthenticationService.class, "auth service 2"); + addAlways(); context.checking(new Expectations() { { @@ -131,7 +153,7 @@ public class StackedAuthenticationServiceTest one(authService1).supportsListingByEmail(); one(authService1).supportsListingByLastName(); one(authService1).supportsAuthenticatingByEmail(); - + one(authService2).isRemote(); one(authService2).supportsListingByUserId(); will(returnValue(true)); @@ -152,6 +174,7 @@ public class StackedAuthenticationServiceTest context = new Mockery(); authService1 = context.mock(IAuthenticationService.class, "auth service 1"); authService2 = context.mock(IAuthenticationService.class, "auth service 2"); + addAlways(); context.checking(new Expectations() { { @@ -161,7 +184,7 @@ public class StackedAuthenticationServiceTest will(returnValue(true)); one(authService1).supportsListingByLastName(); one(authService1).supportsAuthenticatingByEmail(); - + one(authService2).isRemote(); one(authService2).supportsListingByUserId(); one(authService2).supportsListingByEmail(); @@ -181,6 +204,7 @@ public class StackedAuthenticationServiceTest context = new Mockery(); authService1 = context.mock(IAuthenticationService.class, "auth service 1"); authService2 = context.mock(IAuthenticationService.class, "auth service 2"); + addAlways(); context.checking(new Expectations() { { @@ -189,7 +213,7 @@ public class StackedAuthenticationServiceTest one(authService1).supportsListingByEmail(); one(authService1).supportsListingByLastName(); one(authService1).supportsAuthenticatingByEmail(); - + one(authService2).isRemote(); one(authService2).supportsListingByUserId(); one(authService2).supportsListingByEmail(); @@ -217,6 +241,7 @@ public class StackedAuthenticationServiceTest one(authService2).tryGetAndAuthenticateUser(user, password); } }); + addAlways(); assertFalse(stackedAuthService.authenticateUser(user, password)); context.assertIsSatisfied(); } @@ -235,6 +260,7 @@ public class StackedAuthenticationServiceTest will(returnValue(principal)); } }); + addAlways(); assertTrue(stackedAuthService.authenticateUser(user, password)); context.assertIsSatisfied(); } @@ -254,6 +280,7 @@ public class StackedAuthenticationServiceTest will(returnValue(principal)); } }); + addAlways(); assertTrue(stackedAuthService.authenticateUser(user, password)); context.assertIsSatisfied(); } @@ -274,6 +301,7 @@ public class StackedAuthenticationServiceTest will(returnValue(principal)); } }); + addAlways(); assertEquals(principal, stackedAuthService.getPrincipal(user)); context.assertIsSatisfied(); } @@ -295,6 +323,7 @@ public class StackedAuthenticationServiceTest will(returnValue(principal)); } }); + addAlways(); assertEquals(principal, stackedAuthService.getPrincipal(user)); context.assertIsSatisfied(); } @@ -311,6 +340,7 @@ public class StackedAuthenticationServiceTest one(authService2).tryGetAndAuthenticateUser(user, null); } }); + addAlways(); stackedAuthService.getPrincipal(user); } @@ -330,6 +360,8 @@ public class StackedAuthenticationServiceTest { { one(authService1).isRemote(); + one(authService1).isConfigured(); + will(returnValue(true)); one(authService1).supportsListingByUserId(); exactly(2).of(authService1).supportsListingByEmail(); will(returnValue(true)); @@ -337,6 +369,8 @@ public class StackedAuthenticationServiceTest one(authService1).supportsListingByLastName(); one(authService2).isRemote(); + one(authService2).isConfigured(); + will(returnValue(true)); one(authService2).supportsListingByUserId(); exactly(2).of(authService2).supportsListingByEmail(); one(authService2).supportsAuthenticatingByEmail(); @@ -346,6 +380,7 @@ public class StackedAuthenticationServiceTest will(returnValue(Arrays.asList(principal1, principal2))); } }); + addAlways(); stackedAuthService = new StackedAuthenticationService(Arrays.asList(authService1, authService2)); final List<Principal> result = stackedAuthService.listPrincipalsByEmail(emailQuery); @@ -369,12 +404,16 @@ public class StackedAuthenticationServiceTest { { one(authService1).isRemote(); + one(authService1).isConfigured(); + will(returnValue(true)); one(authService1).supportsListingByUserId(); exactly(2).of(authService1).supportsListingByEmail(); one(authService1).supportsAuthenticatingByEmail(); one(authService1).supportsListingByLastName(); - + one(authService2).isRemote(); + one(authService2).isConfigured(); + will(returnValue(true)); one(authService2).supportsListingByUserId(); exactly(2).of(authService2).supportsListingByEmail(); will(returnValue(true)); @@ -385,6 +424,7 @@ public class StackedAuthenticationServiceTest will(returnValue(Arrays.asList(principal))); } }); + addAlways(); stackedAuthService = new StackedAuthenticationService(Arrays.asList(authService1, authService2)); final List<Principal> result = stackedAuthService.listPrincipalsByEmail(emailQuery); @@ -411,13 +451,17 @@ public class StackedAuthenticationServiceTest { { one(authService1).isRemote(); + one(authService1).isConfigured(); + will(returnValue(true)); one(authService1).supportsListingByUserId(); exactly(2).of(authService1).supportsListingByEmail(); will(returnValue(true)); one(authService1).supportsAuthenticatingByEmail(); one(authService1).supportsListingByLastName(); - + one(authService2).isRemote(); + one(authService2).isConfigured(); + will(returnValue(true)); one(authService2).supportsListingByUserId(); exactly(2).of(authService2).supportsListingByEmail(); will(returnValue(true)); @@ -430,6 +474,7 @@ public class StackedAuthenticationServiceTest will(returnValue(Arrays.asList(principal3))); } }); + addAlways(); stackedAuthService = new StackedAuthenticationService(Arrays.asList(authService1, authService2)); final List<Principal> result = stackedAuthService.listPrincipalsByEmail(emailQuery); @@ -461,7 +506,7 @@ public class StackedAuthenticationServiceTest one(authService1).supportsListingByEmail(); one(authService1).supportsListingByLastName(); one(authService1).supportsAuthenticatingByEmail(); - + one(authService2).isRemote(); exactly(2).of(authService2).supportsListingByUserId(); one(authService2).supportsListingByEmail(); @@ -472,6 +517,7 @@ public class StackedAuthenticationServiceTest will(returnValue(Arrays.asList(principal1, principal2))); } }); + addAlways(); stackedAuthService = new StackedAuthenticationService(Arrays.asList(authService1, authService2)); final List<Principal> result = stackedAuthService.listPrincipalsByUserId(userIdQuery); @@ -499,7 +545,7 @@ public class StackedAuthenticationServiceTest one(authService1).supportsListingByEmail(); one(authService1).supportsListingByLastName(); one(authService1).supportsAuthenticatingByEmail(); - + one(authService2).isRemote(); exactly(2).of(authService2).supportsListingByUserId(); will(returnValue(true)); @@ -511,6 +557,7 @@ public class StackedAuthenticationServiceTest will(returnValue(Arrays.asList(principal))); } }); + addAlways(); stackedAuthService = new StackedAuthenticationService(Arrays.asList(authService1, authService2)); final List<Principal> result = stackedAuthService.listPrincipalsByUserId(userIdQuery); @@ -542,7 +589,7 @@ public class StackedAuthenticationServiceTest one(authService1).supportsListingByEmail(); one(authService1).supportsListingByLastName(); one(authService1).supportsAuthenticatingByEmail(); - + one(authService2).isRemote(); exactly(2).of(authService2).supportsListingByUserId(); will(returnValue(true)); @@ -556,6 +603,7 @@ public class StackedAuthenticationServiceTest will(returnValue(Arrays.asList(principal3))); } }); + addAlways(); stackedAuthService = new StackedAuthenticationService(Arrays.asList(authService1, authService2)); final List<Principal> result = stackedAuthService.listPrincipalsByUserId(userIdQuery); @@ -587,7 +635,7 @@ public class StackedAuthenticationServiceTest exactly(2).of(authService1).supportsListingByLastName(); will(returnValue(true)); one(authService1).supportsAuthenticatingByEmail(); - + one(authService2).isRemote(); one(authService2).supportsListingByUserId(); one(authService2).supportsListingByEmail(); @@ -598,6 +646,7 @@ public class StackedAuthenticationServiceTest will(returnValue(Arrays.asList(principal1, principal2))); } }); + addAlways(); stackedAuthService = new StackedAuthenticationService(Arrays.asList(authService1, authService2)); final List<Principal> result = stackedAuthService.listPrincipalsByLastName(lastNameQuery); @@ -625,7 +674,7 @@ public class StackedAuthenticationServiceTest one(authService1).supportsListingByEmail(); exactly(2).of(authService1).supportsListingByLastName(); one(authService1).supportsAuthenticatingByEmail(); - + one(authService2).isRemote(); one(authService2).supportsListingByUserId(); one(authService2).supportsListingByEmail(); @@ -637,6 +686,7 @@ public class StackedAuthenticationServiceTest will(returnValue(Arrays.asList(principal))); } }); + addAlways(); stackedAuthService = new StackedAuthenticationService(Arrays.asList(authService1, authService2)); final List<Principal> result = stackedAuthService.listPrincipalsByLastName(lastNameQuery); @@ -663,13 +713,17 @@ public class StackedAuthenticationServiceTest { { one(authService1).isRemote(); + one(authService1).isConfigured(); + will(returnValue(true)); one(authService1).supportsListingByUserId(); one(authService1).supportsListingByEmail(); one(authService1).supportsAuthenticatingByEmail(); exactly(2).of(authService1).supportsListingByLastName(); will(returnValue(true)); - + one(authService2).isRemote(); + one(authService2).isConfigured(); + will(returnValue(true)); one(authService2).supportsListingByUserId(); one(authService2).supportsListingByEmail(); one(authService2).supportsAuthenticatingByEmail(); @@ -682,6 +736,7 @@ public class StackedAuthenticationServiceTest will(returnValue(Arrays.asList(principal3))); } }); + addAlways(); stackedAuthService = new StackedAuthenticationService(Arrays.asList(authService1, authService2)); final List<Principal> result = stackedAuthService.listPrincipalsByLastName(lastNameQuery); diff --git a/common/source/java/genericCommonContext.xml b/common/source/java/genericCommonContext.xml index 005e6fe21227f8972e4a603370f82c560f8d5253..ac6e0a8a304a3fecdaedf04caa4dbaca2e4f7d20 100644 --- a/common/source/java/genericCommonContext.xml +++ b/common/source/java/genericCommonContext.xml @@ -44,12 +44,18 @@ <bean id="no-authentication-service" class="ch.systemsx.cisd.authentication.NullAuthenticationService" /> + <bean id="crowd-configuration" + class="ch.systemsx.cisd.authentication.crowd.CrowdConfiguration"> + <property name="host" value="${crowd.service.host}" /> + <property name="portStr" value="${crowd.service.port}" /> + <property name="timeoutStr" value="${crowd.service.timeout}" /> + <property name="application" value="${crowd.application.name}" /> + <property name="applicationPassword" value="${crowd.application.password}" /> + </bean> + <bean id="crowd-authentication-service" class="ch.systemsx.cisd.authentication.crowd.CrowdAuthenticationService"> - <constructor-arg value="${crowd.service.host}" /> - <constructor-arg value="${crowd.service.port}" /> - <constructor-arg value="${crowd.application.name}" /> - <constructor-arg value="${crowd.application.password}" /> + <constructor-arg ref="crowd-configuration" /> </bean> <bean id="ldap-directory-configuration" diff --git a/openbis/dist/server/service.properties b/openbis/dist/server/service.properties index 6d897c0e190b7c1bad72047707abc4c3c8d4e49b..b5258b603100cb1679ee46e6927f1d43b1466841 100644 --- a/openbis/dist/server/service.properties +++ b/openbis/dist/server/service.properties @@ -39,21 +39,33 @@ authentication-service = file-authentication-service # --------------------------------------------------------------------------- # Crowd configuration # --------------------------------------------------------------------------- -crowd.service.host = crowd-bsse.ethz.ch -crowd.service.port = 8443 +# +# The Crowd host. +# Mandatory. +crowd.service.host = +# The Crowd service port. Default: 443 +crowd.service.port = +# The timeout (in s) to wait for a Crowd query to return, -1 for "wait indefinitely". Default: 10. +crowd.service.timeout = +# The Crowd application name. +# Mandatory. crowd.application.name = openbis +# The Crowd application password. +# Mandatory. crowd.application.password = # --------------------------------------------------------------------------- # LDAP configuration # --------------------------------------------------------------------------- -# The URL of the LDAP server, e.g. "ldap://d.ethz.ch/DC=d,DC=ethz,DC=ch" -ldap.server.url = <LDAP URL> -# The distinguished name of the security principal, -# e.g. "CN=carl,OU=EthUsers,DC=d,DC=ethz,DC=ch" -ldap.security.principal.distinguished.name = <distinguished name to login to the LDAP server> -# Password of the LDAP user account that will be used to login to the LDAP server to perform the queries -ldap.security.principal.password = <password of the user to connect to the LDAP server> +# The URL of the LDAP server, e.g. "ldap://d.ethz.ch/DC=d,DC=ethz,DC=ch". +# Mandatory. +ldap.server.url = +# The distinguished name of the security principal, e.g. "CN=carl,OU=EthUsers,DC=d,DC=ethz,DC=ch". +# Mandatory. +ldap.security.principal.distinguished.name = +# Password of the LDAP user account that will be used to login to the LDAP server to perform the queries. +# Mandatory. +ldap.security.principal.password = # The security protocol to use, use "ssl" or "none", default is "ssl" ldap.security.protocol = # The authentication method to use: "none" (no authentication), "simple", "strong" (SASL), defaults to "simple" @@ -84,9 +96,9 @@ ldap.queryEmailForAliases = true ldap.queryTemplate = # The number of times a failed LDAP query is retried at the max. Default: 1. ldap.maxRetries = -# The timeout (in ms) to wait for an LDAP query to return, -1 for "wait indefinitely". Default: 10000. +# The timeout (in s) to wait for an LDAP query to return, -1 for "wait indefinitely". Default: 10. ldap.timeout = -# Time time (in ms) to wait after a failure before retrying the query. Default: 10000. +# Time time (in s) to wait after a failure before retrying the query. Default: 10. ldap.timeToWaitAfterFailure= # ---------------------------------------------------------------------------