Skip to content
Permalink
Browse files
This closes #138
  • Loading branch information
ahgittin committed Jan 16, 2019
2 parents 46d1dd1 + 288b87d commit 2e87c83f52173736ecdcf7b9d1449602cfcf273b
Show file tree
Hide file tree
Showing 8 changed files with 72 additions and 194 deletions.
@@ -131,3 +131,6 @@ karaf.secured.services = (&(osgi.command.scope=*)(osgi.command.function=*))
# You can specify the location of the lock file using the
# karaf.lock.dir=/path/to/the/directory/containing/the/lock
#

# Needed to get CXF to run as the Jersey provider
javax.ws.rs.ext.RuntimeDelegate = org.apache.cxf.jaxrs.impl.RuntimeDelegateImpl
@@ -19,8 +19,14 @@
package org.apache.brooklyn.core.catalog.internal;


import org.apache.brooklyn.api.catalog.CatalogItem;
import static org.apache.brooklyn.KarafTestUtils.defaultOptionsWith;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;

import javax.inject.Inject;

import org.apache.brooklyn.api.mgmt.ManagementContext;
import org.apache.brooklyn.api.typereg.RegisteredType;
import org.apache.brooklyn.core.BrooklynVersion;
import org.apache.brooklyn.test.IntegrationTest;
import org.apache.karaf.features.BootFinished;
@@ -34,12 +40,6 @@
import org.ops4j.pax.exam.spi.reactors.PerMethod;
import org.ops4j.pax.exam.util.Filter;

import javax.inject.Inject;

import static org.apache.brooklyn.KarafTestUtils.defaultOptionsWith;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;

@RunWith(PaxExam.class)
@ExamReactorStrategy(PerMethod.class)
@Category(IntegrationTest.class)
@@ -69,9 +69,8 @@ public static Option[] configuration() throws Exception {
@Test
@Category(IntegrationTest.class)
public void shouldHaveLoadedDefaultCatalogBom() throws Exception {
final CatalogItem<?, ?> catalogItem = managementContext.getCatalog()
.getCatalogItem("server-template", BrooklynVersion.get()); // from brooklyn-software-base catalog.bom
assertNotNull(catalogItem);
assertEquals("Template: Server", catalogItem.getDisplayName());
RegisteredType item = managementContext.getTypeRegistry().get("server-template", BrooklynVersion.get());
assertNotNull(item);
assertEquals("Template: Server", item.getDisplayName());
}
}
@@ -20,7 +20,7 @@

import static org.apache.brooklyn.KarafTestUtils.defaultOptionsWith;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.editConfigurationFilePut;
import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.features;

@@ -46,12 +46,16 @@
import org.ops4j.pax.exam.spi.reactors.PerClass;
import org.ops4j.pax.exam.util.Filter;
import org.osgi.service.cm.ConfigurationAdmin;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@RunWith(PaxExam.class)
@ExamReactorStrategy(PerClass.class)
@Category(IntegrationTest.class)
public class OsgiLauncherTest {

private static final Logger log = LoggerFactory.getLogger(OsgiLauncherTest.class);

private static final String TEST_VALUE_RUNTIME = "test.value";
private static final String TEST_KEY_RUNTIME = "test.key";
private static final String TEST_VALUE_IN_CFG = "test.cfg";
@@ -94,11 +98,12 @@ public static Option[] configuration() throws Exception {

@Test
public void testConfig() throws IOException {
assertFalse(mgmt.getConfig().getAllConfig().containsKey(TEST_KEY_RUNTIME));
assertNull(mgmt.getConfig().getFirst(TEST_KEY_RUNTIME));
org.osgi.service.cm.Configuration config = configAdmin.getConfiguration("brooklyn", null);
assertEquals(config.getProperties().get(TEST_KEY_IN_CFG), TEST_VALUE_IN_CFG);
config.getProperties().put(TEST_KEY_RUNTIME, TEST_VALUE_RUNTIME);
config.update();
log.info("Waiting for Brooklyn mgmt "+mgmt+" to see updated value...");
Asserts.succeedsEventually(new Runnable() {
@Override
public void run() {
@@ -24,10 +24,17 @@
import org.apache.brooklyn.rest.security.provider.SecurityProvider;

public class CustomSecurityProvider extends AbstractSecurityProvider implements SecurityProvider {

static final String USER = "custom";

@Override
public boolean authenticate(HttpSession session, String user, String password) {
return "custom".equals(user);
return USER.equals(user);
}

@Override
public boolean requiresUserPass() {
return true;
}

}
@@ -19,32 +19,19 @@
package org.apache.brooklyn.security;

import static org.apache.brooklyn.KarafTestUtils.defaultOptionsWith;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertEquals;
import static org.ops4j.pax.exam.CoreOptions.streamBundle;
import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.editConfigurationFilePut;

import java.io.IOException;

import javax.inject.Inject;
import javax.security.auth.Subject;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.callback.UnsupportedCallbackException;
import javax.security.auth.login.AppConfigurationEntry;
import javax.security.auth.login.FailedLoginException;
import javax.security.auth.login.LoginContext;
import javax.security.auth.login.LoginException;

import org.apache.brooklyn.api.mgmt.ManagementContext;
import org.apache.brooklyn.core.internal.BrooklynProperties;
import org.apache.brooklyn.rest.BrooklynWebConfig;
import org.apache.brooklyn.rest.security.jaas.BrooklynLoginModule;
import org.apache.brooklyn.test.Asserts;
import org.apache.brooklyn.test.IntegrationTest;
import org.apache.brooklyn.util.text.Identifiers;
import org.apache.http.HttpStatus;
import org.apache.karaf.features.BootFinished;
import org.junit.Before;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.junit.runner.RunWith;
@@ -57,13 +44,13 @@
import org.ops4j.pax.tinybundles.core.TinyBundles;
import org.osgi.framework.Constants;

import com.google.common.collect.ImmutableSet;

@RunWith(PaxExam.class)
@ExamReactorStrategy(PerClass.class)
@Category(IntegrationTest.class)
public class CustomSecurityProviderTest {
private static final String WEBCONSOLE_REALM = "webconsole";

private static final String NEW_SECURITY_TEST_BUNDLE = "org.apache.brooklyn.test.security";
private static final String NEW_SECURITY_TEST_BUNDLE_VERSION = "1.0.0";

/**
* To make sure the tests run only when the boot features are fully
@@ -82,76 +69,36 @@ public static Option[] configuration() throws Exception {
return defaultOptionsWith(
streamBundle(TinyBundles.bundle()
.add(CustomSecurityProvider.class)
.add("OSGI-INF/blueprint/security.xml", CustomSecurityProviderTest.class.getResource("/custom-security-bp.xml"))
.set(Constants.BUNDLE_MANIFESTVERSION, "2") // defaults to 1 which doesn't work
.set(Constants.BUNDLE_SYMBOLICNAME, "org.apache.brooklyn.test.security")
.set(Constants.BUNDLE_VERSION, "1.0.0")
.set(Constants.BUNDLE_SYMBOLICNAME, NEW_SECURITY_TEST_BUNDLE)
.set(Constants.BUNDLE_VERSION, NEW_SECURITY_TEST_BUNDLE_VERSION)
.set(Constants.DYNAMICIMPORT_PACKAGE, "*")
.set(Constants.EXPORT_PACKAGE, CustomSecurityProvider.class.getPackage().getName())
.build())
.build()),
editConfigurationFilePut("etc/brooklyn.cfg",
BrooklynWebConfig.SECURITY_PROVIDER_CLASSNAME.getName(), CustomSecurityProvider.class.getCanonicalName()),
editConfigurationFilePut("etc/brooklyn.cfg",
BrooklynWebConfig.SECURITY_PROVIDER_BUNDLE.getName(), NEW_SECURITY_TEST_BUNDLE),
editConfigurationFilePut("etc/brooklyn.cfg",
BrooklynWebConfig.SECURITY_PROVIDER_BUNDLE_VERSION.getName(), NEW_SECURITY_TEST_BUNDLE_VERSION)
// Uncomment this for remote debugging the tests on port 5005
// ,KarafDistributionOption.debugConfiguration()
);
}

@Before
public void setUp() {
// Works only before initializing the security provider (i.e. before first use)
// TODO Dirty hack to inject the needed properties. Improve once managementContext is configurable.
// Alternatively re-register a test managementContext service (how?)
BrooklynProperties brooklynProperties = (BrooklynProperties)managementContext.getConfig();
brooklynProperties.put(BrooklynWebConfig.SECURITY_PROVIDER_CLASSNAME.getName(), CustomSecurityProvider.class.getCanonicalName());
}

@Test(expected = FailedLoginException.class)
public void checkLoginFails() throws LoginException {
assertRealmRegisteredEventually(WEBCONSOLE_REALM);
doLogin("invalid", "auth");
}

@Test
public void checkLoginSucceeds() throws LoginException {
assertRealmRegisteredEventually(WEBCONSOLE_REALM);
String user = "custom";
LoginContext lc = doLogin(user, "password");
Subject subject = lc.getSubject();
assertNotNull(subject);
assertEquals(subject.getPrincipals(), ImmutableSet.of(
new BrooklynLoginModule.UserPrincipal(user),
new BrooklynLoginModule.RolePrincipal("users")));
public void checkRestSecurityNoUserFails() throws IOException {
StockSecurityProviderTest.checkSecurity(null, null, HttpStatus.SC_UNAUTHORIZED);
}

private LoginContext doLogin(final String username, final String password) throws LoginException {
assertRealmRegisteredEventually(WEBCONSOLE_REALM);
LoginContext lc = new LoginContext(WEBCONSOLE_REALM, new CallbackHandler() {
@Override
public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
for (int i = 0; i < callbacks.length; i++) {
Callback callback = callbacks[i];
if (callback instanceof PasswordCallback) {
PasswordCallback passwordCallback = (PasswordCallback)callback;
passwordCallback.setPassword(password.toCharArray());
} else if (callback instanceof NameCallback) {
NameCallback nameCallback = (NameCallback)callback;
nameCallback.setName(username);
}
}
}
});
lc.login();
return lc;
@Test
public void checkRestSecurityWrongUserFails() throws IOException {
StockSecurityProviderTest.checkSecurity("admin", "password", HttpStatus.SC_UNAUTHORIZED);
}

private void assertRealmRegisteredEventually(final String userPassRealm) {
// Need to wait a bit for the realm to get registered, any OSGi way to do this?
Asserts.succeedsEventually(new Runnable() {
@Override
public void run() {
javax.security.auth.login.Configuration initialConfig = javax.security.auth.login.Configuration.getConfiguration();
AppConfigurationEntry[] realm = initialConfig.getAppConfigurationEntry(userPassRealm);
assertNotNull(realm);
}
});
@Test
public void checkRestSecuritySucceeds() throws IOException {
StockSecurityProviderTest.checkSecurity(CustomSecurityProvider.USER, "any-password-"+Identifiers.makeRandomId(2), HttpStatus.SC_OK);
}

}
@@ -20,21 +20,12 @@

import static org.apache.brooklyn.KarafTestUtils.defaultOptionsWith;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.editConfigurationFilePut;

import java.io.IOException;
import java.util.concurrent.Callable;

import javax.inject.Inject;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.callback.UnsupportedCallbackException;
import javax.security.auth.login.AppConfigurationEntry;
import javax.security.auth.login.FailedLoginException;
import javax.security.auth.login.LoginContext;
import javax.security.auth.login.LoginException;

import org.apache.brooklyn.api.mgmt.ManagementContext;
import org.apache.brooklyn.core.internal.BrooklynProperties;
@@ -69,7 +60,6 @@
@Category(IntegrationTest.class)
public class StockSecurityProviderTest {

private static final String WEBCONSOLE_REALM = "webconsole";
private static final String USER = "admin";
private static final String PASSWORD = "password";

@@ -88,6 +78,13 @@ public class StockSecurityProviderTest {
@Configuration
public static Option[] configuration() throws Exception {
return defaultOptionsWith(
editConfigurationFilePut("etc/brooklyn.cfg",
BrooklynWebConfig.SECURITY_PROVIDER_CLASSNAME.getName(), ExplicitUsersSecurityProvider.class.getCanonicalName()),
editConfigurationFilePut("etc/brooklyn.cfg",
BrooklynWebConfig.SECURITY_PROVIDER_CLASSNAME.getName()+".users", USER),
editConfigurationFilePut("etc/brooklyn.cfg",
BrooklynWebConfig.SECURITY_PROVIDER_CLASSNAME.getName()+".user."+USER, PASSWORD)

// Uncomment this for remote debugging the tests on port 5005
// KarafDistributionOption.debugConfiguration()
);
@@ -99,28 +96,17 @@ public void setUp() {
addUser(USER, PASSWORD);
}

@Test(expected = FailedLoginException.class)
public void checkLoginFails() throws LoginException {
doLogin("invalid", "auth");
}

@Test
public void checkLoginSucceeds() throws LoginException {
LoginContext lc = doLogin(USER, PASSWORD);
assertNotNull(lc.getSubject());
}

@Test
public void checkRestSecurityFails() throws IOException {
checkRestSecurity(null, null, HttpStatus.SC_UNAUTHORIZED);
checkSecurity(null, null, HttpStatus.SC_UNAUTHORIZED);
}

@Test
public void checkRestSecuritySucceeds() throws IOException {
checkRestSecurity(USER, PASSWORD, HttpStatus.SC_OK);
checkSecurity(USER, PASSWORD, HttpStatus.SC_OK);
}

private void checkRestSecurity(String username, String password, final int code) throws IOException {
static void checkSecurity(String username, String password, final int code) throws IOException {
CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
if (username != null && password != null) {
credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(username, password));
@@ -130,17 +116,21 @@ private void checkRestSecurity(String username, String password, final int code)
Asserts.succeedsEventually(new Callable<Void>() {
@Override
public Void call() throws Exception {
assertResponseEquals(client, code);
assertResponseEquals(urlBase()+"/v1/server/ha/state", client, code);
assertResponseEquals(urlBase()+"/", client, code);
assertResponseEquals(urlBase()+"/brooklyn-ui-catalog", client, code);
return null;
}
});
}
}

private void assertResponseEquals(CloseableHttpClient httpclient, int code) throws IOException, ClientProtocolException {
// TODO get this dynamically (from CXF service?)
// TODO port is static, should make it dynamic
HttpGet httpGet = new HttpGet("http://localhost:8081/v1/server/ha/state");
// TODO get this dynamically (from CXF service?)
// TODO port is static, should make it dynamic
private static String urlBase() { return "http://localhost:8081"; }

private static void assertResponseEquals(String url, CloseableHttpClient httpclient, int code) throws IOException, ClientProtocolException {
HttpGet httpGet = new HttpGet(url);
try (CloseableHttpResponse response = httpclient.execute(httpGet)) {
assertEquals(code, response.getStatusLine().getStatusCode());
}
@@ -156,37 +146,4 @@ private void addUser(String username, String password) {
brooklynProperties.put(BrooklynWebConfig.PASSWORD_FOR_USER(username), password);
}

private LoginContext doLogin(final String username, final String password) throws LoginException {
assertRealmRegisteredEventually(WEBCONSOLE_REALM);
LoginContext lc = new LoginContext(WEBCONSOLE_REALM, new CallbackHandler() {
@Override
public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
for (int i = 0; i < callbacks.length; i++) {
Callback callback = callbacks[i];
if (callback instanceof PasswordCallback) {
PasswordCallback passwordCallback = (PasswordCallback)callback;
passwordCallback.setPassword(password.toCharArray());
} else if (callback instanceof NameCallback) {
NameCallback nameCallback = (NameCallback)callback;
nameCallback.setName(username);
}
}
}
});
lc.login();
return lc;
}

private void assertRealmRegisteredEventually(final String userPassRealm) {
// Need to wait a bit for the realm to get registered, any OSGi way to do this?
Asserts.succeedsEventually(new Runnable() {
@Override
public void run() {
javax.security.auth.login.Configuration initialConfig = javax.security.auth.login.Configuration.getConfiguration();
AppConfigurationEntry[] realm = initialConfig.getAppConfigurationEntry(userPassRealm);
assertNotNull(realm);
}
});
}

}

0 comments on commit 2e87c83

Please sign in to comment.