Skip to content

Commit

Permalink
[resolves #2676] Add test coverage for securing camel-servlet endpoin…
Browse files Browse the repository at this point in the history
…ts with Elytron
  • Loading branch information
jamesnetherton committed Oct 11, 2018
1 parent 29f2b82 commit 574b046
Show file tree
Hide file tree
Showing 6 changed files with 298 additions and 72 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -47,51 +47,6 @@ public final class UserManager implements Closeable {
private static final String MANAGEMENT_REALM = "ManagementRealm";
private static final char[] HEX_CHARS = "0123456789abcdef".toCharArray();

public static String encryptPassword(String userName, String password, String realm) {
try {
String stringToEncrypt = String.format("%s:%s:%s", userName, realm, password);

MessageDigest md = MessageDigest.getInstance("MD5");
byte[] hashedPassword = md.digest(stringToEncrypt.getBytes(StandardCharsets.UTF_8));

char[] converted = new char[hashedPassword.length * 2];
for (int i = 0; i < hashedPassword.length; i++) {
byte b = hashedPassword[i];
converted[i * 2] = HEX_CHARS[b >> 4 & 0x0F];
converted[i * 2 + 1] = HEX_CHARS[b & 0x0F];
}
return String.valueOf(converted);
} catch (NoSuchAlgorithmException e) {
throw new IllegalStateException(e);
}
}

/**
* @return a new {@link UserManager} that will operate on
* {@code $jbossHome/standalone/configuration/application-users.properties} and
* {@code $jbossHome/standalone/configuration/application-roles.properties}
* @throws IOException
*/
public static UserManager forStandaloneApplicationRealm() throws IOException {
final Path jbossHome = EnvironmentUtils.getWildFlyHome();
final Path userPropertiesPath = jbossHome.resolve("standalone/configuration/application-users.properties");
final Path rolePropertiesPath = jbossHome.resolve("standalone/configuration/application-roles.properties");
return new UserManager(userPropertiesPath, rolePropertiesPath, APPLICATION_REALM);
}

/**
* @return a new {@link UserManager} that will operate on
* {@code $jbossHome/standalone/configuration/mgmt-users.properties} and
* {@code $jbossHome/standalone/configuration/mgmt-roles.properties}
* @throws IOException
*/
public static UserManager forStandaloneManagementRealm() throws IOException {
final Path jbossHome = EnvironmentUtils.getWildFlyHome();
final Path userPropertiesPath = jbossHome.resolve("standalone/configuration/mgmt-users.properties");
final Path rolePropertiesPath = jbossHome.resolve("standalone/configuration/mgmt-roles.properties");
return new UserManager(userPropertiesPath, rolePropertiesPath, MANAGEMENT_REALM);
}

private final String realm;
private Properties roleProperties;
private final Path rolePropertiesPath;
Expand Down Expand Up @@ -125,6 +80,39 @@ public UserManager(Path userPropertiesPath, Path rolePropertiesPath, String real
}
}

/**
* @return a new {@link UserManager} that will operate on
* {@code $jbossHome/standalone/configuration/application-users.properties} and
* {@code $jbossHome/standalone/configuration/application-roles.properties}
* @throws IOException
*/
public static UserManager forStandaloneApplicationRealm() throws IOException {
final Path jbossHome = EnvironmentUtils.getWildFlyHome();
final Path userPropertiesPath = jbossHome.resolve("standalone/configuration/application-users.properties");
final Path rolePropertiesPath = jbossHome.resolve("standalone/configuration/application-roles.properties");
return new UserManager(userPropertiesPath, rolePropertiesPath, APPLICATION_REALM);
}

/**
* @return a new {@link UserManager} that will operate on
* {@code $jbossHome/standalone/configuration/mgmt-users.properties} and
* {@code $jbossHome/standalone/configuration/mgmt-roles.properties}
* @throws IOException
*/
public static UserManager forStandaloneManagementRealm() throws IOException {
final Path jbossHome = EnvironmentUtils.getWildFlyHome();
final Path userPropertiesPath = jbossHome.resolve("standalone/configuration/mgmt-users.properties");
final Path rolePropertiesPath = jbossHome.resolve("standalone/configuration/mgmt-roles.properties");
return new UserManager(userPropertiesPath, rolePropertiesPath, MANAGEMENT_REALM);
}

public static UserManager forStandaloneCustomRealm(String userPropertiesFileName, String rolesPropertiesFileName, String realmName) throws IOException {
final Path jbossHome = EnvironmentUtils.getWildFlyHome();
final Path userPropertiesPath = jbossHome.resolve("standalone/configuration/" + userPropertiesFileName);
final Path rolePropertiesPath = jbossHome.resolve("standalone/configuration/" + rolesPropertiesFileName);
return new UserManager(userPropertiesPath, rolePropertiesPath, realmName);
}

public UserManager addRole(String userName, String role) {
final List<String> roles = Optional.ofNullable(roleProperties.getProperty(userName))
.map(list -> new ArrayList<>(Arrays.asList(list.split(","))))
Expand Down Expand Up @@ -171,4 +159,22 @@ public UserManager removeUser(String userName) {
return this;
}

private static String encryptPassword(String userName, String password, String realm) {
try {
String stringToEncrypt = String.format("%s:%s:%s", userName, realm, password);

MessageDigest md = MessageDigest.getInstance("MD5");
byte[] hashedPassword = md.digest(stringToEncrypt.getBytes(StandardCharsets.UTF_8));

char[] converted = new char[hashedPassword.length * 2];
for (int i = 0; i < hashedPassword.length; i++) {
byte b = hashedPassword[i];
converted[i * 2] = HEX_CHARS[b >> 4 & 0x0F];
converted[i * 2 + 1] = HEX_CHARS[b & 0x0F];
}
return String.valueOf(converted);
} catch (NoSuchAlgorithmException e) {
throw new IllegalStateException(e);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
package org.wildfly.camel.test.common.security;

import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;

import org.jboss.as.arquillian.api.ServerSetupTask;
import org.jboss.as.arquillian.container.ManagementClient;
import org.jboss.as.controller.PathAddress;
Expand All @@ -12,7 +8,6 @@
import org.jboss.dmr.ModelNode;
import org.wildfly.camel.test.common.http.HttpRequest;
import org.wildfly.camel.test.common.utils.DMRUtils;
import org.wildfly.camel.test.common.utils.EnvironmentUtils;
import org.wildfly.camel.test.common.utils.UserManager;

/**
Expand Down Expand Up @@ -63,7 +58,7 @@ public void setup(ManagementClient managementClient, String containerId) throws
HttpRequest.post(HTTPS_HOST).getResponse();
final ModelControllerClient client = managementClient.getControllerClient();

try (UserManager um = newUserManager()) {
try (UserManager um = UserManager.forStandaloneCustomRealm(USERS_PROPS, ROLES_PROPS, SECURITY_REALM)) {
um
.addUser(APPLICATION_USER, APPLICATION_PASSWORD)
.addRole(APPLICATION_USER, APPLICATION_ROLE)
Expand Down Expand Up @@ -110,16 +105,9 @@ public void setup(ManagementClient managementClient, String containerId) throws
.assertSuccess();
}

private static UserManager newUserManager() throws IOException {
final Path jbossHome = EnvironmentUtils.getWildFlyHome();
final Path userPropertiesPath = jbossHome.resolve("standalone/configuration/" + USERS_PROPS);
final Path rolePropertiesPath = jbossHome.resolve("standalone/configuration/" + ROLES_PROPS);
return new UserManager(userPropertiesPath, rolePropertiesPath, SECURITY_REALM);
}

@Override
public void tearDown(ManagementClient managementClient, String containerId) throws Exception {
try (UserManager um = newUserManager()) {
try (UserManager um = UserManager.forStandaloneCustomRealm(USERS_PROPS, ROLES_PROPS, SECURITY_REALM)) {
um
.removeUser(APPLICATION_USER)
.removeRole(APPLICATION_USER, APPLICATION_ROLE)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
package org.wildfly.camel.test.common.security;

import java.io.IOException;
import java.nio.file.Path;

import org.jboss.as.arquillian.api.ServerSetupTask;
import org.jboss.as.arquillian.container.ManagementClient;
import org.jboss.as.controller.PathAddress;
Expand All @@ -11,7 +8,6 @@
import org.jboss.dmr.ModelNode;
import org.wildfly.camel.test.common.http.HttpRequest;
import org.wildfly.camel.test.common.utils.DMRUtils;
import org.wildfly.camel.test.common.utils.EnvironmentUtils;
import org.wildfly.camel.test.common.utils.UserManager;

/**
Expand Down Expand Up @@ -59,7 +55,7 @@ public void setup(ManagementClient managementClient, String containerId) throws
HttpRequest.post(HTTPS_HOST).getResponse();
final ModelControllerClient client = managementClient.getControllerClient();

try (UserManager um = newUserManager()) {
try (UserManager um = UserManager.forStandaloneCustomRealm(USERS_PROPS, ROLES_PROPS, SECURITY_REALM)) {
um
.addUser(APPLICATION_USER, APPLICATION_PASSWORD)
.addRole(APPLICATION_USER, APPLICATION_ROLE)
Expand Down Expand Up @@ -104,16 +100,9 @@ public void setup(ManagementClient managementClient, String containerId) throws
.assertSuccess();
}

private static UserManager newUserManager() throws IOException {
final Path jbossHome = EnvironmentUtils.getWildFlyHome();
final Path userPropertiesPath = jbossHome.resolve("standalone/configuration/"+ USERS_PROPS);
final Path rolePropertiesPath = jbossHome.resolve("standalone/configuration/"+ ROLES_PROPS);
return new UserManager(userPropertiesPath, rolePropertiesPath, SECURITY_REALM);
}

@Override
public void tearDown(ManagementClient managementClient, String containerId) throws Exception {
try (UserManager um = newUserManager()) {
try (UserManager um = UserManager.forStandaloneCustomRealm(USERS_PROPS, ROLES_PROPS, SECURITY_REALM)) {
um
.removeUser(APPLICATION_USER)
.removeRole(APPLICATION_USER, APPLICATION_ROLE)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
/*
* #%L
* Wildfly Camel :: Testsuite
* %%
* Copyright (C) 2013 - 2014 RedHat
* %%
* 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.
* #L%
*/

package org.wildfly.camel.test.servlet;

import java.nio.charset.StandardCharsets;

import static javax.xml.bind.DatatypeConverter.printBase64Binary;
import static org.wildfly.camel.test.common.http.HttpRequest.HttpResponse;
import static org.wildfly.camel.test.servlet.subA.SecurityDomainSetupTask.SECURITY_DOMAIN;

import org.apache.camel.CamelContext;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.impl.DefaultCamelContext;
import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.junit.Arquillian;
import org.jboss.as.arquillian.api.ServerSetup;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.asset.StringAsset;
import org.jboss.shrinkwrap.api.spec.WebArchive;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.wildfly.camel.test.common.http.HttpRequest;
import org.wildfly.camel.test.servlet.subA.SecurityDomainSetupTask;
import org.wildfly.extension.camel.CamelAware;

/**
* Tests basic authentication with Elytron securing a camel-servlet REST DSL endpoint path
*/
@CamelAware
@RunWith(Arquillian.class)
@ServerSetup({SecurityDomainSetupTask.class})
public class SecureServletIntegrationTest {

private static final String JBOSS_WEB = "<jboss-web><security-domain>" + SECURITY_DOMAIN + "</security-domain></jboss-web>";

@Deployment
public static WebArchive createDeployment() {
return ShrinkWrap.create(WebArchive.class, "camel-secure-servlet.war")
.addAsWebInfResource("servlet/secure-web.xml", "web.xml")
.addAsWebInfResource(new StringAsset(JBOSS_WEB), "jboss-web.xml")
.addClasses(HttpRequest.class, SecurityDomainSetupTask.class);
}

@Test
public void testSecureServletRoute() throws Exception {
CamelContext camelctx = new DefaultCamelContext();
camelctx.addRoutes(new RouteBuilder() {
@Override
public void configure() throws Exception {
restConfiguration()
.component("servlet");

rest()
.get("/insecure")
.route()
.setBody(constant("GET: /insecure"))
.endRest()
.get("/secure")
.route()
.setBody(constant("GET: /secure"))
.endRest();
}
});

camelctx.start();
try {
// Insecure should work without authentication
HttpResponse response = HttpRequest.get("http://localhost:8080/camel-secure-servlet/services/insecure")
.throwExceptionOnFailure(false)
.getResponse();
Assert.assertEquals(200, response.getStatusCode());
Assert.assertEquals("GET: /insecure", response.getBody());

// No credentials provided so expect HTTP 401
int statusCode = HttpRequest.get("http://localhost:8080/camel-secure-servlet/services/secure")
.throwExceptionOnFailure(false)
.getResponse()
.getStatusCode();
Assert.assertEquals(401, statusCode);

// Invalid credentials provided so expect HTTP 401
statusCode = HttpRequest.get("http://localhost:8080/camel-secure-servlet/services/secure")
.throwExceptionOnFailure(false)
.header("Authorization", "Basic " + printBase64Binary("bad-user:bad-password".getBytes(StandardCharsets.UTF_8)))
.getResponse()
.getStatusCode();
Assert.assertEquals(401, statusCode);

// Pass valid credentials and expect HTTP 200
response = HttpRequest.get("http://localhost:8080/camel-secure-servlet/services/secure")
.throwExceptionOnFailure(false)
.header("Authorization", "Basic " + printBase64Binary("camel-servlet-user:camel-servlet-password".getBytes(StandardCharsets.UTF_8)))
.getResponse();
Assert.assertEquals(200, response.getStatusCode());
Assert.assertEquals("GET: /secure", response.getBody());
} finally {
camelctx.stop();
}
}
}
Loading

0 comments on commit 574b046

Please sign in to comment.