/*
* JBoss, Home of Professional Open Source.
* Copyright 2013, Red Hat, Inc., and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.as.test.integration.management.rbac;
import static org.jboss.as.controller.PathAddress.pathAddress;
import static org.jboss.as.controller.PathElement.pathElement;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ACCESS;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ADD;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.BASE_ROLE;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.CORE_SERVICE;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.FAILED;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.FAILURE_DESCRIPTION;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.GROUP;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.HOSTS;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.HOST_SCOPED_ROLE;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.INCLUDE_ALL;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.MANAGEMENT;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.NAME;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OPERATION_HEADERS;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OUTCOME;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.READ_RESOURCE_OPERATION;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.REMOVE;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.RESULT;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ROLES;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.SERVER_GROUPS;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.SERVER_GROUP_SCOPED_ROLE;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.SUCCESS;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.TYPE;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.USER;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.VALUE;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.WRITE_ATTRIBUTE_OPERATION;
import static org.jboss.as.domain.management.ModelDescriptionConstants.IS_CALLER_IN_ROLE;
import static org.jboss.as.test.integration.management.util.ModelUtil.createOpNode;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import java.io.IOException;
import org.jboss.as.controller.client.ModelControllerClient;
import org.jboss.as.controller.descriptions.ModelDescriptionConstants;
import org.jboss.as.controller.operations.common.Util;
import org.jboss.as.test.integration.management.interfaces.ManagementInterface;
import org.jboss.dmr.ModelNode;
/**
* Utilities related to RBAC testing.
*
* @author Brian Stansberry (c) 2013 Red Hat Inc.
*/
public class RbacUtil {
public static final String MONITOR_USER = "Monitor";
public static final String OPERATOR_USER = "Operator";
public static final String MAINTAINER_USER = "Maintainer";
public static final String DEPLOYER_USER = "Deployer";
public static final String ADMINISTRATOR_USER = "Administrator";
public static final String AUDITOR_USER = "Auditor";
public static final String SUPERUSER_USER = "SuperUser";
public static final String MONITOR_ROLE = "Monitor";
public static final String OPERATOR_ROLE = "Operator";
public static final String MAINTAINER_ROLE = "Maintainer";
public static final String DEPLOYER_ROLE = "Deployer";
public static final String ADMINISTRATOR_ROLE = "Administrator";
public static final String AUDITOR_ROLE = "Auditor";
public static final String SUPERUSER_ROLE = "SuperUser";
public static final String ROLE_MAPPING_ADDRESS_BASE = "core-service=management/access=authorization/role-mapping=";
private static final String ROLE_MAPPING_USER_INCLUDE_ADDRESS_BASE = "/include=user-";
private static final String ROLE_MAPPING_GROUP_INCLUDE_ADDRESS_BASE = "/include=group-";
private RbacUtil() {
// prevent instantiation
}
public static ModelNode executeOperation(ModelControllerClient client, ModelNode operation, Outcome expectedOutcome)
throws IOException {
ModelNode result = client.execute(operation);
return checkOperationResult(operation, result, expectedOutcome);
}
public static ModelNode executeOperation(ManagementInterface client, ModelNode operation, Outcome expectedOutcome) throws IOException {
ModelNode result = client.execute(operation);
return checkOperationResult(operation, result, expectedOutcome);
}
public static ModelNode checkOperationResult(ModelNode operation, ModelNode result, Outcome expectedOutcome) {
String outcome = result.get(OUTCOME).asString();
switch (expectedOutcome) {
case SUCCESS:
if (!SUCCESS.equals(outcome)) {
System.out.println("Failed: " + operation);
System.out.print("Result: " + result);
fail(result.asString());
}
break;
case UNAUTHORIZED: {
if (!FAILED.equals(outcome)) {
fail("Didn't fail: " + result.asString());
}
if (!result.get(FAILURE_DESCRIPTION).asString().contains("WFLYCTL0313") && !result.asString().contains("WFLYJMX0037")
&& !result.asString().contains("WFLYJMX0038") && !result.asString().contains("WFLYJMX0039") && !result.asString().contains("WFLYJMX0040")) {
fail("Incorrect failure type: " + result.asString());
}
break;
}
case HIDDEN: {
if (!FAILED.equals(outcome)) {
fail("Didn't fail: " + result.asString());
}
String failureDesc = result.get(FAILURE_DESCRIPTION).asString();
if (!failureDesc.contains("WFLYCTL0216") && !failureDesc.contains("WFLYCTL0030") && !failureDesc.contains("WFLYJMX0017")) {
fail("Incorrect failure type: " + result.asString());
}
break;
}
case FAILED: {
if (!FAILED.equals(outcome)) {
fail("Didn't fail: " + result.asString());
}
String failureDesc = result.get(FAILURE_DESCRIPTION).asString();
if (failureDesc.contains("WFLYCTL0216") || failureDesc.contains("WFLYCTL0030")
|| failureDesc.contains("WFLYCTL0313") || failureDesc.contains("WFLYJMX0017")) {
fail("Incorrect failure type: " + result.asString());
}
break;
}
default:
throw new IllegalStateException();
}
return result;
}
public static void addRoleMapping(String role, ModelControllerClient client) throws IOException {
String address = ROLE_MAPPING_ADDRESS_BASE + role;
ModelNode readOp = createOpNode(address, READ_RESOURCE_OPERATION);
if (FAILED.equals(client.execute(readOp).get(OUTCOME).asString())) {
ModelNode addOp = createOpNode(address, ADD);
executeOperation(client, addOp, Outcome.SUCCESS);
}
}
public static void addRoleUser(String role, String user, ModelControllerClient client) throws IOException {
ModelNode op = createOpNode(ROLE_MAPPING_ADDRESS_BASE + role + ROLE_MAPPING_USER_INCLUDE_ADDRESS_BASE + user, ADD);
op.get(TYPE).set(USER);
op.get(NAME).set(user);
executeOperation(client, op, Outcome.SUCCESS);
}
public static void removeRoleUser(String role, String user, ModelControllerClient client) throws IOException {
ModelNode op = createOpNode(ROLE_MAPPING_ADDRESS_BASE + role + ROLE_MAPPING_USER_INCLUDE_ADDRESS_BASE + user, REMOVE);
executeOperation(client, op, Outcome.SUCCESS);
}
public static void addRoleGroup(String role, String group, ModelControllerClient client) throws IOException {
ModelNode op = createOpNode(ROLE_MAPPING_ADDRESS_BASE + role + ROLE_MAPPING_GROUP_INCLUDE_ADDRESS_BASE + group, ADD);
op.get(TYPE).set(GROUP);
op.get(NAME).set(group);
executeOperation(client, op, Outcome.SUCCESS);
}
public static void removeRoleGroup(String role, String group, ModelControllerClient client) throws IOException {
ModelNode op = createOpNode(ROLE_MAPPING_ADDRESS_BASE + role + ROLE_MAPPING_GROUP_INCLUDE_ADDRESS_BASE + group, REMOVE);
executeOperation(client, op, Outcome.SUCCESS);
}
public static void removeRoleMapping(String role, ModelControllerClient client) throws IOException {
ModelNode op = createOpNode(ROLE_MAPPING_ADDRESS_BASE + role, REMOVE);
executeOperation(client, op, Outcome.SUCCESS);
}
public static void addRoleHeader(ModelNode operation, String... roles) {
ModelNode header = operation.get(OPERATION_HEADERS, ROLES);
for (String role : roles) {
header.add(role);
}
}
public static String[] allStandardRoles() {
return new String[] {MONITOR_ROLE, OPERATOR_ROLE, MAINTAINER_ROLE, DEPLOYER_ROLE, ADMINISTRATOR_ROLE, AUDITOR_ROLE, SUPERUSER_ROLE};
}
public static void assertIsCallerInRole(ModelControllerClient client, String role, boolean expectedOutcome) throws IOException {
ModelNode operation = createOpNode(ROLE_MAPPING_ADDRESS_BASE + role, IS_CALLER_IN_ROLE);
ModelNode result = executeOperation(client, operation, Outcome.SUCCESS);
assertEquals("expected caller to be in role " + role, expectedOutcome, result.get(RESULT).asBoolean());
}
public static void setRoleMappingIncludeAll(ModelControllerClient client, String role, boolean includeAll) throws IOException {
ModelNode operation = createOpNode(ROLE_MAPPING_ADDRESS_BASE + role, WRITE_ATTRIBUTE_OPERATION);
operation.get(NAME).set(INCLUDE_ALL);
operation.get(VALUE).set(includeAll);
executeOperation(client, operation, Outcome.SUCCESS);
}
public static void addServerGroupScopedRole(ModelControllerClient client, String roleName, String baseRole,
String... serverGroups) throws IOException {
ModelNode operation = Util.createOperation(ADD, pathAddress(
pathElement(CORE_SERVICE, MANAGEMENT),
pathElement(ACCESS, ModelDescriptionConstants.AUTHORIZATION),
pathElement(SERVER_GROUP_SCOPED_ROLE, roleName)
));
operation.get(BASE_ROLE).set(baseRole);
ModelNode serverGroupsModelNode = operation.get(SERVER_GROUPS);
for (String serverGroup : serverGroups) {
serverGroupsModelNode.add(serverGroup);
}
executeOperation(client, operation, Outcome.SUCCESS);
}
public static void removeServerGroupScopedRole(ModelControllerClient client, String roleName) throws IOException {
ModelNode operation = Util.createOperation(REMOVE, pathAddress(
pathElement(CORE_SERVICE, MANAGEMENT),
pathElement(ACCESS, ModelDescriptionConstants.AUTHORIZATION),
pathElement(SERVER_GROUP_SCOPED_ROLE, roleName)
));
executeOperation(client, operation, Outcome.SUCCESS);
}
public static void addHostScopedRole(ModelControllerClient client, String roleName, String baseRole,
String... hosts) throws IOException {
ModelNode operation = Util.createOperation(ADD, pathAddress(
pathElement(CORE_SERVICE, MANAGEMENT),
pathElement(ACCESS, ModelDescriptionConstants.AUTHORIZATION),
pathElement(HOST_SCOPED_ROLE, roleName)
));
operation.get(BASE_ROLE).set(baseRole);
ModelNode hostsModelNode = operation.get(HOSTS);
for (String host : hosts) {
hostsModelNode.add(host);
}
executeOperation(client, operation, Outcome.SUCCESS);
}
public static void removeHostScopedRole(ModelControllerClient client, String roleName) throws IOException {
ModelNode operation = Util.createOperation(REMOVE, pathAddress(
pathElement(CORE_SERVICE, MANAGEMENT),
pathElement(ACCESS, ModelDescriptionConstants.AUTHORIZATION),
pathElement(HOST_SCOPED_ROLE, roleName)
));
executeOperation(client, operation, Outcome.SUCCESS);
}
}