/core-model-test/tests/src/test/java/org/jboss/as/core/model/test/access/RoleMappingTestCase.java
Java | 599 lines | 414 code | 101 blank | 84 comment | 7 complexity | 02888e777ce1f3775fadf63f5163857a MD5 | raw file
- /*
- * 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.core.model.test.access;
- 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.AUTHORIZATION;
- 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.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.OP;
- import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OP_ADDR;
- import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OUTCOME;
- import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.REALM;
- 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.ROLE_MAPPING;
- import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.SUCCESS;
- import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.TYPE;
- import static org.jboss.as.domain.management.ModelDescriptionConstants.IS_CALLER_IN_ROLE;
- import static org.junit.Assert.assertEquals;
- import static org.junit.Assert.assertTrue;
- import java.security.Principal;
- import java.security.PrivilegedAction;
- import java.util.Arrays;
- import java.util.Collections;
- import java.util.HashMap;
- import java.util.Map;
- import java.util.function.Function;
- import org.jboss.as.controller.AccessAuditContext;
- import org.jboss.as.controller.access.rbac.StandardRole;
- import org.jboss.as.controller.descriptions.ModelDescriptionConstants;
- import org.jboss.as.core.model.test.AbstractCoreModelTest;
- import org.jboss.as.core.model.test.KernelServices;
- import org.jboss.as.core.model.test.TestModelType;
- import org.jboss.as.core.security.AccountPrincipal;
- import org.jboss.as.core.security.GroupPrincipal;
- import org.jboss.as.core.security.RealmPrincipal;
- import org.jboss.as.core.security.RealmUser;
- import org.jboss.dmr.ModelNode;
- import org.junit.Before;
- import org.junit.Test;
- import org.wildfly.security.auth.permission.LoginPermission;
- import org.wildfly.security.auth.principal.NamePrincipal;
- import org.wildfly.security.auth.realm.SimpleMapBackedSecurityRealm;
- import org.wildfly.security.auth.realm.SimpleRealmEntry;
- import org.wildfly.security.auth.server.RealmIdentity;
- import org.wildfly.security.auth.server.RealmUnavailableException;
- import org.wildfly.security.auth.server.SecurityDomain;
- import org.wildfly.security.auth.server.SecurityIdentity;
- import org.wildfly.security.auth.server.ServerAuthenticationContext;
- import org.wildfly.security.authz.MapAttributes;
- import org.wildfly.security.authz.RoleDecoder;
- /**
- * Test case to test the role mapping behaviour (model and runtime mapping).
- *
- * @author <a href="mailto:darran.lofthouse@jboss.com">Darran Lofthouse</a>
- */
- public class RoleMappingTestCase extends AbstractCoreModelTest {
- private static final String TEST_REALM = "TestRealm";
- private static final String OTHER_REALM = "OtherRealm";
- private static final String OTHER_USER = "OtherUser";
- private KernelServices kernelServices;
- private int uniqueCount = 0;
- @Before
- public void setUp() throws Exception {
- kernelServices = createKernelServicesBuilder(TestModelType.STANDALONE)
- .setXmlResource("constraints.xml")
- .validateDescription()
- .build();
- }
- /**
- * Test that a user is assigned a role based on their username (not realm specific).
- *
- * Also verify that assignment of a group with the same name does not result in role assignment.
- */
- @Test
- public void testIncludeByUsername() {
- final String roleName = "Deployer";
- final String userName = "UserOne";
- addRole(roleName, false);
- addPrincipal(roleName, MappingType.INCLUDE, PrincipalType.USER, userName, null);
- assertIsCallerInRole(roleName, null, false);
- assertIsCallerInRole(roleName, true, userName, TEST_REALM, null);
- assertIsCallerInRole(roleName, false, OTHER_USER, TEST_REALM, null, userName);
- removeRole(roleName);
- }
- /**
- * Same as testIncludeByUsername but now verify that the users realm is taken into account.
- */
- @Test
- public void testIncludeByUsernameAndRealm() {
- final String roleName = "Deployer";
- final String userName = "UserTwo";
- addRole(roleName, false);
- addPrincipal(roleName, MappingType.INCLUDE, PrincipalType.USER, userName, TEST_REALM);
- assertIsCallerInRole(roleName, null, false);
- assertIsCallerInRole(roleName, true, userName, TEST_REALM, null);
- assertIsCallerInRole(roleName, false, userName, OTHER_REALM, null);
- assertIsCallerInRole(roleName, false, OTHER_USER, TEST_REALM, null, userName);
- removeRole(roleName);
- }
- /**
- * Test that a user is assigned a role based on their group membership (not realm specific).
- *
- * Also verify that a user account with the same name does not result in role assignment.
- */
- @Test
- public void testIncludeByGroup() {
- final String roleName = "Deployer";
- final String userName = "UserThree";
- final String groupName = "GroupThree";
- addRole(roleName, false);
- addPrincipal(roleName, MappingType.INCLUDE, PrincipalType.GROUP, groupName, null);
- assertIsCallerInRole(roleName, null, false);
- assertIsCallerInRole(roleName, true, userName, TEST_REALM, null, groupName);
- assertIsCallerInRole(roleName, true, userName, OTHER_REALM, null, groupName);
- assertIsCallerInRole(roleName, false, groupName, TEST_REALM, null, userName);
- removeRole(roleName);
- }
- /**
- * Same as testIncludeByGroup but now include the realm name in the match.
- */
- @Test
- public void testIncludeByGroupAndRealm() {
- final String roleName = "Deployer";
- final String userName = "UserFour";
- final String groupName = "GroupFour";
- addRole(roleName, false);
- addPrincipal(roleName, MappingType.INCLUDE, PrincipalType.GROUP, groupName, TEST_REALM);
- assertIsCallerInRole(roleName, null, false);
- assertIsCallerInRole(roleName, true, userName, TEST_REALM, null, groupName);
- assertIsCallerInRole(roleName, false, userName, OTHER_REALM, null, groupName);
- assertIsCallerInRole(roleName, false, groupName, TEST_REALM, null, userName);
- removeRole(roleName);
- }
- /**
- * Test that a user matched to a role by group is not assigned the role if their username is in the exclude list.
- */
- @Test
- public void testExcludeByUsername() {
- final String roleName = "Deployer";
- final String userName = "UserFive";
- final String groupName = "GroupFive";
- addRole(roleName, false);
- addPrincipal(roleName, MappingType.INCLUDE, PrincipalType.GROUP, groupName, null);
- addPrincipal(roleName, MappingType.EXCLUDE, PrincipalType.USER, userName, null);
- assertIsCallerInRole(roleName, null, false);
- assertIsCallerInRole(roleName, true, OTHER_USER, TEST_REALM, null, groupName);
- assertIsCallerInRole(roleName, false, userName, TEST_REALM, null, groupName);
- removeRole(roleName);
- }
- /**
- * Same as testExcludeByUsername except the exclusion is realm specific.
- */
- @Test
- public void testExcludeByUsernameAndRealm() {
- final String roleName = "Deployer";
- final String userName = "UserFive";
- final String groupName = "GroupFive";
- addRole(roleName, false);
- addPrincipal(roleName, MappingType.INCLUDE, PrincipalType.GROUP, groupName, null);
- addPrincipal(roleName, MappingType.EXCLUDE, PrincipalType.USER, userName, TEST_REALM);
- assertIsCallerInRole(roleName, null, false);
- assertIsCallerInRole(roleName, true, OTHER_USER, TEST_REALM, null, groupName);
- assertIsCallerInRole(roleName, false, userName, TEST_REALM, null, groupName);
- assertIsCallerInRole(roleName, true, userName, OTHER_REALM, null, groupName);
- removeRole(roleName);
- }
- /**
- * Test that a user assigned a role due to group membership is excluded based on the membership of another group.
- */
- @Test
- public void testExcludeByGroup() {
- final String roleName = "Deployer";
- final String userName = "UserSix";
- final String inGroupName = "GroupSix_In";
- final String outGroupName = "GroupSix_Out";
- addRole(roleName, false);
- addPrincipal(roleName, MappingType.INCLUDE, PrincipalType.GROUP, inGroupName, null);
- addPrincipal(roleName, MappingType.EXCLUDE, PrincipalType.GROUP, outGroupName, null);
- assertIsCallerInRole(roleName, null, false);
- assertIsCallerInRole(roleName, true, userName, TEST_REALM, null, inGroupName);
- assertIsCallerInRole(roleName, false, userName, TEST_REALM, null, inGroupName, outGroupName);
- removeRole(roleName);
- }
- /**
- * Same as testExcludeByGroup but the exclusion takes the realm into account.
- */
- @Test
- public void testExcludeByGroupAndRealm() {
- final String roleName = "Deployer";
- final String userName = "UserSeven";
- final String inGroupName = "GroupSeven_In";
- final String outGroupName = "GroupSeven_Out";
- addRole(roleName, false);
- addPrincipal(roleName, MappingType.INCLUDE, PrincipalType.GROUP, inGroupName, null);
- addPrincipal(roleName, MappingType.EXCLUDE, PrincipalType.GROUP, outGroupName, TEST_REALM);
- assertIsCallerInRole(roleName, null, false);
- assertIsCallerInRole(roleName, true, userName, TEST_REALM, null, inGroupName);
- assertIsCallerInRole(roleName, false, userName, TEST_REALM, null, inGroupName, outGroupName);
- assertIsCallerInRole(roleName, true, userName, OTHER_REALM, null, inGroupName, outGroupName);
- removeRole(roleName);
- }
- /**
- * Test that user assigned the SUPERUSER role can actually request a different role.
- *
- * On requesting the different role the user should not be assigned the SUPERUSER role anymore.
- */
- @Test
- public void testSuperUserAs() {
- final String roleName = "SuperUser";
- final String otherRole = "Deployer";
- final String userName = "UserThirteen";
- // TODO Elytron The SuperUser mapping was added to constraints.xml to allow the remainder of the tests to run.
- //addRole(roleName, false);
- ModelNode addedAddress = addPrincipal(roleName, MappingType.INCLUDE, PrincipalType.USER, userName, null);
- assertIsCallerInRole(roleName, true, userName, TEST_REALM, null);
- assertIsCallerInRole(otherRole, true, userName, TEST_REALM, otherRole);
- assertIsCallerInRole(roleName, false, userName, TEST_REALM, otherRole);
- removePrincipal(addedAddress);
- // TODO Elytron The SuperUser mapping was added to constraints.xml to allow the remainder of the tests to run.
- //removeRole(roleName);
- }
- /**
- * Test that user assigned the Deployer role can NOT request a different role.
- */
- @Test
- public void testDeployerAs() {
- final String roleName = "Deployer";
- final String otherRole = "MONITOR";
- final String userName = "UserFourteen";
- addRole(roleName, false);
- ModelNode addedAddress = addPrincipal(roleName, MappingType.INCLUDE, PrincipalType.USER, userName, null);
- assertIsCallerInRole(roleName, true, userName, TEST_REALM, null);
- assertIsCallerInRole(otherRole, false, userName, TEST_REALM, otherRole);
- assertIsCallerInRole(roleName, true, userName, TEST_REALM, otherRole);
- removePrincipal(addedAddress);
- removeRole(roleName);
- }
- /**
- * Test that an authenticated user is assigned a role where include-all = true.
- */
- @Test
- public void testIncludeAll() {
- final String roleName = "Deployer";
- final String userName = "UserEight";
- addRole(roleName, true);
- // TODO Elytron Hack - Default user 'anonymous' is picked up as being in the role.
- assertIsCallerInRole(roleName, null, true);
- assertIsCallerInRole(roleName, true, userName, TEST_REALM, null);
- removeRole(roleName);
- }
- /**
- * Test that a user matched to a role by include-all is not assigned the role if their username is in the exclude list.
- */
- @Test
- public void testIncludeAll_ExcludeByUsername() {
- final String roleName = "Deployer";
- final String userName = "UserNine";
- final String groupName = "GroupNine";
- addRole(roleName, true);
- addPrincipal(roleName, MappingType.EXCLUDE, PrincipalType.USER, userName, null);
- // TODO Elytron Hack to also exclude the default user 'anonymous'.
- addPrincipal(roleName, MappingType.EXCLUDE, PrincipalType.USER, "anonymous", null);
- assertIsCallerInRole(roleName, null, false);
- assertIsCallerInRole(roleName, true, OTHER_USER, TEST_REALM, null, groupName);
- assertIsCallerInRole(roleName, false, userName, TEST_REALM, null, groupName);
- removeRole(roleName);
- }
- /**
- * Test that a user matched to a role by include-all is not assigned the role if their group is in the exclude list.
- */
- @Test
- public void testIncludeAll_ExcludeByGroup() {
- final String roleName = "Deployer";
- final String userName = "UserTen";
- final String groupName = "GroupTen";
- addRole(roleName, true);
- addPrincipal(roleName, MappingType.EXCLUDE, PrincipalType.GROUP, groupName, null);
- // TODO Elytron Hack to also exclude the default user 'anonymous'.
- addPrincipal(roleName, MappingType.EXCLUDE, PrincipalType.USER, "anonymous", null);
- assertIsCallerInRole(roleName, null, false);
- assertIsCallerInRole(roleName, true, userName, TEST_REALM, null);
- assertIsCallerInRole(roleName, false, userName, TEST_REALM, null, groupName);
- removeRole(roleName);
- }
- /*
- * Duplicate Handling
- *
- * Tests to verify that the add operations successfully detect duplicate include/exclude definitions.
- */
- @Test
- public void testDuplicateUserComplete() {
- final String roleName = "Deployer";
- final String userName = "UserEleven";
- addRole(roleName, false);
- addPrincipal(roleName, MappingType.INCLUDE, PrincipalType.USER, userName, TEST_REALM);
- addPrincipal(roleName, MappingType.INCLUDE, PrincipalType.USER, userName, TEST_REALM, true);
- removeRole(roleName);
- }
- @Test
- public void testDuplicateUserRealmLess() {
- final String roleName = "Deployer";
- final String userName = "UserTwelve";
- addRole(roleName, false);
- addPrincipal(roleName, MappingType.INCLUDE, PrincipalType.USER, userName, null);
- addPrincipal(roleName, MappingType.INCLUDE, PrincipalType.USER, userName, TEST_REALM);
- addPrincipal(roleName, MappingType.INCLUDE, PrincipalType.USER, userName, null, true);
- addPrincipal(roleName, MappingType.EXCLUDE, PrincipalType.USER, userName, TEST_REALM);
- addPrincipal(roleName, MappingType.EXCLUDE, PrincipalType.USER, userName, null);
- addPrincipal(roleName, MappingType.EXCLUDE, PrincipalType.USER, userName, null, true);
- removeRole(roleName);
- }
- @Test
- public void testDuplicateGroupComplete() {
- final String roleName = "Deployer";
- final String groupName = "UserThirteen";
- addRole(roleName, false);
- addPrincipal(roleName, MappingType.EXCLUDE, PrincipalType.GROUP, groupName, TEST_REALM);
- addPrincipal(roleName, MappingType.EXCLUDE, PrincipalType.GROUP, groupName, TEST_REALM, true);
- removeRole(roleName);
- }
- @Test
- public void testDuplicateGroupRealmLess() {
- final String roleName = "Deployer";
- final String groupName = "UserFourteen";
- addRole(roleName, false);
- addPrincipal(roleName, MappingType.EXCLUDE, PrincipalType.GROUP, groupName, null);
- addPrincipal(roleName, MappingType.EXCLUDE, PrincipalType.GROUP, groupName, TEST_REALM);
- addPrincipal(roleName, MappingType.EXCLUDE, PrincipalType.GROUP, groupName, null, true);
- addPrincipal(roleName, MappingType.INCLUDE, PrincipalType.GROUP, groupName, TEST_REALM);
- addPrincipal(roleName, MappingType.INCLUDE, PrincipalType.GROUP, groupName, null);
- addPrincipal(roleName, MappingType.INCLUDE, PrincipalType.GROUP, groupName, null, true);
- removeRole(roleName);
- }
- private void addRole(final String roleName, boolean includeAll) {
- ModelNode operation = new ModelNode();
- operation.get(OP_ADDR).add(CORE_SERVICE, MANAGEMENT).add(ACCESS, AUTHORIZATION).add(ROLE_MAPPING, roleName);
- operation.get(OP).set(ADD);
- if (includeAll) {
- operation.get(INCLUDE_ALL).set(true);
- }
- ModelNode response = kernelServices.executeOperation(operation);
- assertEquals(SUCCESS, response.get(OUTCOME).asString());
- }
- private ModelNode addPrincipal(final String roleName, final MappingType mappingType, final PrincipalType principalType, final String name, final String realm) {
- return addPrincipal(roleName, mappingType, principalType, name, realm, false);
- }
- private ModelNode addPrincipal(final String roleName, final MappingType mappingType, final PrincipalType principalType, final String name, final String realm, boolean expectFailure) {
- ModelNode operation = new ModelNode();
- operation.get(OP_ADDR).add(CORE_SERVICE, MANAGEMENT).add(ACCESS, AUTHORIZATION).add(ROLE_MAPPING, roleName).add(mappingType.toString(), uniqueCount++);
- operation.get(OP).set(ADD);
- operation.get(TYPE).set(principalType.toString());
- operation.get(NAME).set(name);
- if (realm != null) {
- operation.get(REALM).set(realm);
- }
- ModelNode response = kernelServices.executeOperation(operation);
- if (expectFailure) {
- assertEquals(FAILED, response.get(OUTCOME).asString());
- } else {
- assertEquals(SUCCESS, response.get(OUTCOME).asString());
- }
- return operation.get(OP_ADDR);
- }
- private void removePrincipal(final ModelNode address) {
- ModelNode operation = new ModelNode();
- operation.get(OP_ADDR).set(address);
- operation.get(OP).set(REMOVE);
- ModelNode response = kernelServices.executeOperation(operation);
- assertEquals(SUCCESS, response.get(OUTCOME).asString());
- }
- private void removeRole(final String roleName) {
- ModelNode operation = new ModelNode();
- operation.get(OP_ADDR).add(CORE_SERVICE, MANAGEMENT).add(ACCESS, AUTHORIZATION).add(ROLE_MAPPING, roleName);
- operation.get(OP).set(REMOVE);
- ModelNode response = kernelServices.executeOperation(operation);
- assertEquals(SUCCESS, response.get(OUTCOME).asString());
- }
- private void assertIsCallerInRole(final String roleName, final String runAsRole, final boolean expectedOutcome) {
- ModelNode operation = new ModelNode();
- operation.get(OP_ADDR).add(CORE_SERVICE, MANAGEMENT).add(ACCESS, AUTHORIZATION).add(ROLE_MAPPING, roleName);
- operation.get(OP).set(IS_CALLER_IN_ROLE);
- if (runAsRole != null) {
- ModelNode headers = operation.get(ModelDescriptionConstants.OPERATION_HEADERS);
- headers.get("roles").set(runAsRole);
- }
- ModelNode response = kernelServices.executeOperation(operation);
- assertEquals(SUCCESS, response.get(OUTCOME).asString());
- assertEquals(expectedOutcome, response.get(RESULT).asBoolean());
- }
- private void assertIsCallerInRole(final String roleName, final boolean expectedOutcome, final String userName,
- final String realm, final String runAsRole, final String... groups) {
- MapAttributes testAttributes = new MapAttributes();
- testAttributes.addAll("groups", Arrays.asList(groups));
- Map<String, SimpleRealmEntry> entries = new HashMap<>(StandardRole.values().length);
- entries.put(userName, new SimpleRealmEntry(Collections.emptyList(), testAttributes));
- SimpleMapBackedSecurityRealm securityRealm = new SimpleMapBackedSecurityRealm() {
- @Override
- public RealmIdentity getRealmIdentity(Principal principal) {
- return super.getRealmIdentity(new NamePrincipal(principal.getName()));
- }
- };
- securityRealm.setPasswordMap(entries);
- SecurityDomain testDomain = SecurityDomain.builder()
- .setDefaultRealmName("Default")
- .setPreRealmRewriter((Function<Principal, Principal>) p -> new RealmUser(realm, p.getName()))
- .addRealm("Default", securityRealm)
- .setRoleDecoder(RoleDecoder.simple("groups"))
- .build()
- .setPermissionMapper((p,r) -> new LoginPermission())
- .build();
- SecurityIdentity securityIdentity;
- try {
- ServerAuthenticationContext authenticationContext = testDomain.createNewAuthenticationContext();
- authenticationContext.setAuthenticationName(userName);
- assertTrue("Authorized", authenticationContext.authorize());
- securityIdentity = authenticationContext.getAuthorizedIdentity();
- } catch (RealmUnavailableException e) {
- // Should not be possible
- throw new IllegalStateException(e);
- }
- AccessAuditContext.doAs(securityIdentity, null, new PrivilegedAction<Void>() {
- @Override
- public Void run() {
- assertIsCallerInRole(roleName, runAsRole, expectedOutcome);
- return null;
- }
- });
- }
- private enum PrincipalType {
- GROUP, USER;
- @Override
- public String toString() {
- return super.toString().toLowerCase();
- }
- }
- private enum MappingType {
- EXCLUDE, INCLUDE;
- @Override
- public String toString() {
- return super.toString().toLowerCase();
- }
- }
- private static class User implements RealmPrincipal, AccountPrincipal {
- private final String realm;
- private final String name;
- private User(final String name, final String realm) {
- this.name = name;
- this.realm = realm;
- }
- @Override
- public String getName() {
- return name;
- }
- @Override
- public String getRealm() {
- return realm;
- }
- }
- private static class Group implements RealmPrincipal, GroupPrincipal {
- private final String name;
- private final String realm;
- private Group(final String name, final String realm) {
- this.name = name;
- this.realm = realm;
- }
- @Override
- public String getName() {
- return name;
- }
- @Override
- public String getRealm() {
- return realm;
- }
- }
- }