PageRenderTime 34ms CodeModel.GetById 2ms app.highlight 27ms RepoModel.GetById 1ms app.codeStats 1ms

/core-model-test/tests/src/test/java/org/jboss/as/core/model/test/access/RoleMappingTestCase.java

https://github.com/dbuos/wildfly
Java | 546 lines | 374 code | 96 blank | 76 comment | 8 complexity | bd2d3dc4147c50abaaf817c10b34386f MD5 | raw file
  1/*
  2 * JBoss, Home of Professional Open Source.
  3 * Copyright 2013, Red Hat, Inc., and individual contributors
  4 * as indicated by the @author tags. See the copyright.txt file in the
  5 * distribution for a full listing of individual contributors.
  6 *
  7 * This is free software; you can redistribute it and/or modify it
  8 * under the terms of the GNU Lesser General Public License as
  9 * published by the Free Software Foundation; either version 2.1 of
 10 * the License, or (at your option) any later version.
 11 *
 12 * This software is distributed in the hope that it will be useful,
 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 15 * Lesser General Public License for more details.
 16 *
 17 * You should have received a copy of the GNU Lesser General Public
 18 * License along with this software; if not, write to the Free
 19 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 20 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 21 */
 22
 23package org.jboss.as.core.model.test.access;
 24
 25import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ACCESS;
 26import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ADD;
 27import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.AUTHORIZATION;
 28import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.CORE_SERVICE;
 29import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.INCLUDE_ALL;
 30import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.MANAGEMENT;
 31import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.NAME;
 32import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OP;
 33import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OP_ADDR;
 34import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OUTCOME;
 35import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.REALM;
 36import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.REMOVE;
 37import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.RESULT;
 38import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ROLE_MAPPING;
 39import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.SUCCESS;
 40import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.FAILED;
 41import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.TYPE;
 42import static org.jboss.as.domain.management.ModelDescriptionConstants.IS_CALLER_IN_ROLE;
 43import static org.junit.Assert.assertEquals;
 44
 45import java.security.Principal;
 46import java.security.PrivilegedAction;
 47import java.util.Set;
 48
 49import javax.security.auth.Subject;
 50
 51import org.jboss.as.controller.descriptions.ModelDescriptionConstants;
 52import org.jboss.as.core.model.test.AbstractCoreModelTest;
 53import org.jboss.as.core.model.test.KernelServices;
 54import org.jboss.as.core.model.test.TestModelType;
 55import org.jboss.as.core.security.AccountPrincipal;
 56import org.jboss.as.core.security.GroupPrincipal;
 57import org.jboss.as.core.security.RealmPrincipal;
 58import org.jboss.dmr.ModelNode;
 59import org.junit.Before;
 60import org.junit.Test;
 61
 62/**
 63 * Test case to test the role mapping behaviour (model and runtime mapping).
 64 *
 65 * @author <a href="mailto:darran.lofthouse@jboss.com">Darran Lofthouse</a>
 66 */
 67public class RoleMappingTestCase extends AbstractCoreModelTest {
 68
 69    private static final String TEST_REALM = "TestRealm";
 70    private static final String OTHER_REALM = "OtherRealm";
 71    private static final String OTHER_USER = "OtherUser";
 72
 73    private KernelServices kernelServices;
 74    private int uniqueCount = 0;
 75
 76    @Before
 77    public void setUp() throws Exception {
 78        kernelServices = createKernelServicesBuilder(TestModelType.STANDALONE)
 79                .setXmlResource("constraints.xml")
 80                .validateDescription()
 81                .build();
 82    }
 83
 84    /**
 85     * Test that a user is assigned a role based on their username (not realm specific).
 86     *
 87     * Also verify that assignment of a group with the same name does not result in role assignment.
 88     */
 89    @Test
 90    public void testIncludeByUsername() {
 91        final String roleName = "Deployer";
 92        final String userName = "UserOne";
 93        addRole(roleName, false);
 94        addPrincipal(roleName, MappingType.INCLUDE, PrincipalType.USER, userName, null);
 95        assertIsCallerInRole(roleName, null, false);
 96
 97        assertIsCallerInRole(roleName, true, userName, TEST_REALM, null);
 98        assertIsCallerInRole(roleName, false, OTHER_USER, TEST_REALM, null, userName);
 99
100        removeRole(roleName);
101    }
102
103    /**
104     * Same as testIncludeByUsername but now verify that the users realm is taken into account.
105     */
106    @Test
107    public void testIncludeByUsernameAndRealm() {
108        final String roleName = "Deployer";
109        final String userName = "UserTwo";
110        addRole(roleName, false);
111        addPrincipal(roleName, MappingType.INCLUDE, PrincipalType.USER, userName, TEST_REALM);
112        assertIsCallerInRole(roleName, null, false);
113
114        assertIsCallerInRole(roleName, true, userName, TEST_REALM, null);
115        assertIsCallerInRole(roleName, false, userName, OTHER_REALM, null);
116        assertIsCallerInRole(roleName, false, OTHER_USER, TEST_REALM, null, userName);
117
118        removeRole(roleName);
119    }
120
121    /**
122     * Test that a user is assigned a role based on their group membership (not realm specific).
123     *
124     * Also verify that a user account with the same name does not result in role assignment.
125     */
126    @Test
127    public void testIncludeByGroup() {
128        final String roleName = "Deployer";
129        final String userName = "UserThree";
130        final String groupName = "GroupThree";
131        addRole(roleName, false);
132        addPrincipal(roleName, MappingType.INCLUDE, PrincipalType.GROUP, groupName, null);
133        assertIsCallerInRole(roleName, null, false);
134
135        assertIsCallerInRole(roleName, true, userName, TEST_REALM, null, groupName);
136        assertIsCallerInRole(roleName, true, userName, OTHER_REALM, null, groupName);
137        assertIsCallerInRole(roleName, false, groupName, TEST_REALM, null, userName);
138
139        removeRole(roleName);
140    }
141
142    /**
143     * Same as testIncludeByGroup but now include the realm name in the match.
144     */
145    @Test
146    public void testIncludeByGroupAndRealm() {
147        final String roleName = "Deployer";
148        final String userName = "UserFour";
149        final String groupName = "GroupFour";
150        addRole(roleName, false);
151        addPrincipal(roleName, MappingType.INCLUDE, PrincipalType.GROUP, groupName, TEST_REALM);
152        assertIsCallerInRole(roleName, null, false);
153
154        assertIsCallerInRole(roleName, true, userName, TEST_REALM, null, groupName);
155        assertIsCallerInRole(roleName, false, userName, OTHER_REALM, null, groupName);
156        assertIsCallerInRole(roleName, false, groupName, TEST_REALM, null, userName);
157
158        removeRole(roleName);
159    }
160
161    /**
162     * Test that a user matched to a role by group is not assigned the role if their username is in the exclude list.
163     */
164    @Test
165    public void testExcludeByUsername() {
166        final String roleName = "Deployer";
167        final String userName = "UserFive";
168        final String groupName = "GroupFive";
169        addRole(roleName, false);
170        addPrincipal(roleName, MappingType.INCLUDE, PrincipalType.GROUP, groupName, null);
171        addPrincipal(roleName, MappingType.EXCLUDE, PrincipalType.USER, userName, null);
172        assertIsCallerInRole(roleName, null, false);
173
174        assertIsCallerInRole(roleName, true, OTHER_USER, TEST_REALM, null, groupName);
175        assertIsCallerInRole(roleName, false, userName, TEST_REALM, null, groupName);
176
177        removeRole(roleName);
178    }
179
180    /**
181     * Same as testExcludeByUsername except the exclusion is realm specific.
182     */
183    @Test
184    public void testExcludeByUsernameAndRealm() {
185        final String roleName = "Deployer";
186        final String userName = "UserFive";
187        final String groupName = "GroupFive";
188        addRole(roleName, false);
189        addPrincipal(roleName, MappingType.INCLUDE, PrincipalType.GROUP, groupName, null);
190        addPrincipal(roleName, MappingType.EXCLUDE, PrincipalType.USER, userName, TEST_REALM);
191        assertIsCallerInRole(roleName, null, false);
192
193        assertIsCallerInRole(roleName, true, OTHER_USER, TEST_REALM, null, groupName);
194        assertIsCallerInRole(roleName, false, userName, TEST_REALM, null, groupName);
195        assertIsCallerInRole(roleName, true, userName, OTHER_REALM, null, groupName);
196
197        removeRole(roleName);
198    }
199
200    /**
201     * Test that a user assigned a role due to group membership is excluded based on the membership of another group.
202     */
203    @Test
204    public void testExcludeByGroup() {
205        final String roleName = "Deployer";
206        final String userName = "UserSix";
207        final String inGroupName = "GroupSix_In";
208        final String outGroupName = "GroupSix_Out";
209        addRole(roleName, false);
210        addPrincipal(roleName, MappingType.INCLUDE, PrincipalType.GROUP, inGroupName, null);
211        addPrincipal(roleName, MappingType.EXCLUDE, PrincipalType.GROUP, outGroupName, null);
212        assertIsCallerInRole(roleName, null, false);
213
214        assertIsCallerInRole(roleName, true, userName, TEST_REALM, null, inGroupName);
215        assertIsCallerInRole(roleName, false, userName, TEST_REALM, null, inGroupName, outGroupName);
216
217        removeRole(roleName);
218    }
219
220    /**
221     * Same as testExcludeByGroup but the exclusion takes the realm into account.
222     */
223    @Test
224    public void testExcludeByGroupAndRealm() {
225        final String roleName = "Deployer";
226        final String userName = "UserSeven";
227        final String inGroupName = "GroupSeven_In";
228        final String outGroupName = "GroupSeven_Out";
229        addRole(roleName, false);
230        addPrincipal(roleName, MappingType.INCLUDE, PrincipalType.GROUP, inGroupName, null);
231        addPrincipal(roleName, MappingType.EXCLUDE, PrincipalType.GROUP, outGroupName, TEST_REALM);
232        assertIsCallerInRole(roleName, null, false);
233
234        assertIsCallerInRole(roleName, true, userName, TEST_REALM, null, inGroupName);
235        assertIsCallerInRole(roleName, false, userName, TEST_REALM, null, inGroupName, outGroupName);
236        assertIsCallerInRole(roleName, true, userName, OTHER_REALM, null, inGroupName, outGroupName);
237
238        removeRole(roleName);
239    }
240
241    /**
242     * Test that user assigned the SUPERUSER role can actually request a different role.
243     *
244     * On requesting the different role the user should not be assigned the SUPERUSER role anymore.
245     */
246    @Test
247    public void testSuperUserAs() {
248        final String roleName = "SuperUser";
249        final String otherRole = "Deployer";
250        final String userName = "UserThirteen";
251        addRole(roleName, false);
252        ModelNode addedAddress = addPrincipal(roleName, MappingType.INCLUDE, PrincipalType.USER, userName, null);
253
254        assertIsCallerInRole(roleName, true, userName, TEST_REALM, null);
255        assertIsCallerInRole(otherRole, true, userName, TEST_REALM, otherRole);
256        assertIsCallerInRole(roleName, false, userName, TEST_REALM, otherRole);
257
258        removePrincipal(addedAddress);
259        removeRole(roleName);
260    }
261
262    /**
263     * Test that user assigned the Deployer role can NOT request a different role.
264     */
265    @Test
266    public void testDeployerAs() {
267        final String roleName = "Deployer";
268        final String otherRole = "MONITOR";
269        final String userName = "UserFourteen";
270        addRole(roleName, false);
271        ModelNode addedAddress = addPrincipal(roleName, MappingType.INCLUDE, PrincipalType.USER, userName, null);
272
273        assertIsCallerInRole(roleName, true, userName, TEST_REALM, null);
274        assertIsCallerInRole(otherRole, false, userName, TEST_REALM, otherRole);
275        assertIsCallerInRole(roleName, true, userName, TEST_REALM, otherRole);
276
277        removePrincipal(addedAddress);
278        removeRole(roleName);
279    }
280
281    /**
282     * Test that an authenticated user is assigned a role where include-all = true.
283     */
284    @Test
285    public void testIncludeAll() {
286        final String roleName = "Deployer";
287        final String userName = "UserEight";
288        addRole(roleName, true);
289        assertIsCallerInRole(roleName, null, false);
290
291        assertIsCallerInRole(roleName, true, userName, TEST_REALM, null);
292
293        removeRole(roleName);
294    }
295
296    /**
297     * Test that a user matched to a role by include-all is not assigned the role if their username is in the exclude list.
298     */
299    @Test
300    public void testIncludeAll_ExcludeByUsername() {
301        final String roleName = "Deployer";
302        final String userName = "UserNine";
303        final String groupName = "GroupNine";
304        addRole(roleName, true);
305        addPrincipal(roleName, MappingType.EXCLUDE, PrincipalType.USER, userName, null);
306        assertIsCallerInRole(roleName, null, false);
307
308        assertIsCallerInRole(roleName, true, OTHER_USER, TEST_REALM, null, groupName);
309        assertIsCallerInRole(roleName, false, userName, TEST_REALM, null, groupName);
310
311        removeRole(roleName);
312    }
313
314    /**
315     * Test that a user matched to a role by include-all is not assigned the role if their group is in the exclude list.
316     */
317    @Test
318    public void testIncludeAll_ExcludeByGroup() {
319        final String roleName = "Deployer";
320        final String userName = "UserTen";
321        final String groupName = "GroupTen";
322        addRole(roleName, true);
323        addPrincipal(roleName, MappingType.EXCLUDE, PrincipalType.GROUP, groupName, null);
324        assertIsCallerInRole(roleName, null, false);
325
326        assertIsCallerInRole(roleName, true, userName, TEST_REALM, null);
327        assertIsCallerInRole(roleName, false, userName, TEST_REALM, null, groupName);
328
329        removeRole(roleName);
330    }
331
332    /*
333     * Duplicate Handling
334     *
335     * Tests to verify that the add operations successfully detect duplicate include/exclude definitions.
336     */
337
338    @Test
339    public void testDuplicateUserComplete() {
340        final String roleName = "Deployer";
341        final String userName = "UserEleven";
342
343        addRole(roleName, false);
344        addPrincipal(roleName, MappingType.INCLUDE, PrincipalType.USER, userName, TEST_REALM);
345        addPrincipal(roleName, MappingType.INCLUDE, PrincipalType.USER, userName, TEST_REALM, true);
346
347        removeRole(roleName);
348    }
349
350    @Test
351    public void testDuplicateUserRealmLess() {
352        final String roleName = "Deployer";
353        final String userName = "UserTwelve";
354
355        addRole(roleName, false);
356        addPrincipal(roleName, MappingType.INCLUDE, PrincipalType.USER, userName, null);
357        addPrincipal(roleName, MappingType.INCLUDE, PrincipalType.USER, userName, TEST_REALM);
358        addPrincipal(roleName, MappingType.INCLUDE, PrincipalType.USER, userName, null, true);
359
360        addPrincipal(roleName, MappingType.EXCLUDE, PrincipalType.USER, userName, TEST_REALM);
361        addPrincipal(roleName, MappingType.EXCLUDE, PrincipalType.USER, userName, null);
362        addPrincipal(roleName, MappingType.EXCLUDE, PrincipalType.USER, userName, null, true);
363
364        removeRole(roleName);
365    }
366
367    @Test
368    public void testDuplicateGroupComplete() {
369        final String roleName = "Deployer";
370        final String groupName = "UserThirteen";
371
372        addRole(roleName, false);
373        addPrincipal(roleName, MappingType.EXCLUDE, PrincipalType.GROUP, groupName, TEST_REALM);
374        addPrincipal(roleName, MappingType.EXCLUDE, PrincipalType.GROUP, groupName, TEST_REALM, true);
375
376        removeRole(roleName);
377    }
378
379    @Test
380    public void testDuplicateGroupRealmLess() {
381        final String roleName = "Deployer";
382        final String groupName = "UserFourteen";
383
384        addRole(roleName, false);
385        addPrincipal(roleName, MappingType.EXCLUDE, PrincipalType.GROUP, groupName, null);
386        addPrincipal(roleName, MappingType.EXCLUDE, PrincipalType.GROUP, groupName, TEST_REALM);
387        addPrincipal(roleName, MappingType.EXCLUDE, PrincipalType.GROUP, groupName, null, true);
388
389        addPrincipal(roleName, MappingType.INCLUDE, PrincipalType.GROUP, groupName, TEST_REALM);
390        addPrincipal(roleName, MappingType.INCLUDE, PrincipalType.GROUP, groupName, null);
391        addPrincipal(roleName, MappingType.INCLUDE, PrincipalType.GROUP, groupName, null, true);
392
393        removeRole(roleName);
394    }
395
396    private void addRole(final String roleName, boolean includeAll) {
397        ModelNode operation = new ModelNode();
398        operation.get(OP_ADDR).add(CORE_SERVICE, MANAGEMENT).add(ACCESS, AUTHORIZATION).add(ROLE_MAPPING, roleName);
399        operation.get(OP).set(ADD);
400        if (includeAll) {
401            operation.get(INCLUDE_ALL).set(true);
402        }
403
404        ModelNode response = kernelServices.executeOperation(operation);
405        assertEquals(SUCCESS, response.get(OUTCOME).asString());
406    }
407
408    private ModelNode addPrincipal(final String roleName, final MappingType mappingType, final PrincipalType principalType, final String name, final String realm) {
409        return addPrincipal(roleName, mappingType, principalType, name, realm, false);
410    }
411
412    private ModelNode addPrincipal(final String roleName, final MappingType mappingType, final PrincipalType principalType, final String name, final String realm, boolean expectFailure) {
413        ModelNode operation = new ModelNode();
414        operation.get(OP_ADDR).add(CORE_SERVICE, MANAGEMENT).add(ACCESS, AUTHORIZATION).add(ROLE_MAPPING, roleName).add(mappingType.toString(), uniqueCount++);
415        operation.get(OP).set(ADD);
416        operation.get(TYPE).set(principalType.toString());
417        operation.get(NAME).set(name);
418        if (realm != null) {
419            operation.get(REALM).set(realm);
420        }
421
422        ModelNode response = kernelServices.executeOperation(operation);
423        if (expectFailure) {
424            assertEquals(FAILED, response.get(OUTCOME).asString());
425        } else {
426            assertEquals(SUCCESS, response.get(OUTCOME).asString());
427        }
428
429        return operation.get(OP_ADDR);
430    }
431
432    private void removePrincipal(final ModelNode address) {
433        ModelNode operation = new ModelNode();
434        operation.get(OP_ADDR).set(address);
435        operation.get(OP).set(REMOVE);
436
437        ModelNode response = kernelServices.executeOperation(operation);
438        assertEquals(SUCCESS, response.get(OUTCOME).asString());
439    }
440
441    private void removeRole(final String roleName) {
442        ModelNode operation = new ModelNode();
443        operation.get(OP_ADDR).add(CORE_SERVICE, MANAGEMENT).add(ACCESS, AUTHORIZATION).add(ROLE_MAPPING, roleName);
444        operation.get(OP).set(REMOVE);
445
446        ModelNode response = kernelServices.executeOperation(operation);
447        assertEquals(SUCCESS, response.get(OUTCOME).asString());
448    }
449
450    private void assertIsCallerInRole(final String roleName, final String runAsRole, final boolean expectedOutcome) {
451        ModelNode operation = new ModelNode();
452        operation.get(OP_ADDR).add(CORE_SERVICE, MANAGEMENT).add(ACCESS, AUTHORIZATION).add(ROLE_MAPPING, roleName);
453        operation.get(OP).set(IS_CALLER_IN_ROLE);
454        if (runAsRole != null) {
455            ModelNode headers = operation.get(ModelDescriptionConstants.OPERATION_HEADERS);
456            headers.get("roles").set(runAsRole);
457        }
458
459        ModelNode response = kernelServices.executeOperation(operation);
460        assertEquals(SUCCESS, response.get(OUTCOME).asString());
461        assertEquals(expectedOutcome, response.get(RESULT).asBoolean());
462    }
463
464    private void assertIsCallerInRole(final String roleName, final boolean expectedOutcome, final String userName,
465            final String realm, final String runAsRole, final String... groups) {
466        Subject subject = new Subject();
467        Set<Principal> principals = subject.getPrincipals();
468        principals.add(new User(userName, realm));
469        for (String current : groups) {
470            principals.add(new Group(current, realm));
471        }
472
473        Subject.doAs(subject, new PrivilegedAction<Void>() {
474
475            @Override
476            public Void run() {
477                assertIsCallerInRole(roleName, runAsRole, expectedOutcome);
478                return null;
479            }
480        });
481    }
482
483    private enum PrincipalType {
484        GROUP, USER;
485
486        @Override
487        public String toString() {
488            return super.toString().toLowerCase();
489        }
490    }
491
492    private enum MappingType {
493        EXCLUDE, INCLUDE;
494
495        @Override
496        public String toString() {
497            return super.toString().toLowerCase();
498        }
499
500    }
501
502    private static class User implements RealmPrincipal, AccountPrincipal {
503
504        private final String realm;
505        private final String name;
506
507        private User(final String name, final String realm) {
508            this.name = name;
509            this.realm = realm;
510        }
511
512        @Override
513        public String getName() {
514            return name;
515        }
516
517        @Override
518        public String getRealm() {
519            return realm;
520        }
521
522    }
523
524    private static class Group implements RealmPrincipal, GroupPrincipal {
525
526        private final String name;
527        private final String realm;
528
529        private Group(final String name, final String realm) {
530            this.name = name;
531            this.realm = realm;
532        }
533
534        @Override
535        public String getName() {
536            return name;
537        }
538
539        @Override
540        public String getRealm() {
541            return realm;
542        }
543
544    }
545
546}