/* * JBoss, Home of Professional Open Source * * Copyright 2015 Red Hat, Inc. and/or its affiliates. * * 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. */ package org.wildfly.security.authz.jacc; import org.hamcrest.core.IsInstanceOf; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Ignore; import org.junit.Test; import org.wildfly.security.WildFlyElytronProvider; import org.wildfly.security.auth.principal.NamePrincipal; import org.wildfly.security.auth.realm.SimpleMapBackedSecurityRealm; 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; import org.wildfly.security.authz.RoleMapper; import org.wildfly.security.password.PasswordFactory; import org.wildfly.security.password.interfaces.ClearPassword; import org.wildfly.security.password.spec.ClearPasswordSpec; import javax.security.jacc.PolicyConfiguration; import javax.security.jacc.PolicyConfigurationFactory; import javax.security.jacc.PolicyContext; import javax.security.jacc.WebResourcePermission; import java.security.Policy; import java.security.Principal; import java.security.ProtectionDomain; import java.security.Provider; import java.security.Security; import java.util.Arrays; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; /** * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a> */ @Ignore public class LinkPolicyConfigurationTest { private static final Provider provider = new WildFlyElytronProvider(); @BeforeClass public static void onBeforeClass() { System.setProperty("javax.security.jacc.PolicyConfigurationFactory.provider", ElytronPolicyConfigurationFactory.class.getName()); Policy.setPolicy(new JaccDelegatingPolicy()); Security.addProvider(provider); } @AfterClass public static void onAfter() throws Exception { Security.removeProvider(provider.getName()); } @Test public void testLinkPolicyConfigurationSharingRoleMapping() throws Exception { ElytronPolicyConfigurationFactory policyConfigurationFactory = (ElytronPolicyConfigurationFactory) PolicyConfigurationFactory.getPolicyConfigurationFactory(); // let's create the parent module policy final WebResourcePermission parentPermission = new WebResourcePermission("/webResource", "PUT"); String parentContextID = "parent-module"; SecurityDomain parentSecurityDomain = createSecurityDomain("mary", "Administrator"); PolicyConfiguration parentPolicyConfiguration = policyConfigurationFactory.getPolicyConfiguration(parentContextID, false); parentPolicyConfiguration.addToRole("Administrator", parentPermission); parentPolicyConfiguration.addToRole("User", parentPermission); // let's create the first child module final WebResourcePermission child1Permission = new WebResourcePermission("/webResource", "POST"); String child1ContextID = "child-module-1"; SecurityDomain child1SecurityDomain = createSecurityDomain("john", "User"); PolicyConfiguration child1PolicyConfiguration = policyConfigurationFactory.getPolicyConfiguration(child1ContextID, false); child1PolicyConfiguration.addToRole("Administrator", child1Permission); child1PolicyConfiguration.addToRole("User", child1Permission); child1PolicyConfiguration.addToRole("Manager", child1Permission); // let's create the second child module final WebResourcePermission child2Permission = new WebResourcePermission("/webResource", "GET"); String child2ContextID = "child-module-2"; SecurityDomain child2SecurityDomain = createSecurityDomain("smith", "Manager"); PolicyConfiguration child2PolicyConfiguration = policyConfigurationFactory.getPolicyConfiguration(child2ContextID, false); child2PolicyConfiguration.addToRole("User", child2Permission); child2PolicyConfiguration.addToRole("Manager", child2Permission); // link first child module with parent parentPolicyConfiguration.linkConfiguration(child1PolicyConfiguration); // link second child module with parent parentPolicyConfiguration.linkConfiguration(child2PolicyConfiguration); parentPolicyConfiguration.commit(); child1PolicyConfiguration.commit(); child2PolicyConfiguration.commit(); // let's check now permissions for first child module PolicyContext.setContextID(child1ContextID); Policy policy = Policy.getPolicy(); ServerAuthenticationContext authenticationContext = child1SecurityDomain.createNewAuthenticationContext(); authenticationContext.setAuthenticationName("john"); authenticationContext.succeed(); SecurityIdentity johnIdentity = authenticationContext.getAuthorizedIdentity(); // john is known by first child module, it should pass johnIdentity.runAs(() -> { assertTrue(policy.implies(createProtectionDomain(), child1Permission)); }); authenticationContext = child2SecurityDomain.createNewAuthenticationContext(); authenticationContext.setAuthenticationName("smith"); authenticationContext.succeed(); SecurityIdentity smithIdentity = authenticationContext.getAuthorizedIdentity(); PolicyContext.setContextID(child2ContextID); // smith is not know by first module, but by second module. As they share the same role mapping, smith should be known by first module as well smithIdentity.runAs(() -> { assertTrue(policy.implies(createProtectionDomain(), child1Permission)); }); // same thing above, but using mary which is known only by parent module assertTrue(policy.implies(createProtectionDomain(), child1Permission)); PolicyContext.setContextID(child2ContextID); // smith is known by first child module, it should pass assertTrue(policy.implies(createProtectionDomain(), child2Permission)); // john is not know by first module, but by first module. As they share the same role mapping, john should be known by second module as well assertTrue(policy.implies(createProtectionDomain(), child2Permission)); // same thing above, but using mary which is known only by parent module. However, in this case we don't have a permission for mary/Administrator in the second module assertFalse(policy.implies(createProtectionDomain(), child2Permission)); PolicyContext.setContextID(parentContextID); assertTrue(policy.implies(createProtectionDomain(), parentPermission)); assertFalse(policy.implies(createProtectionDomain(), parentPermission)); parentPolicyConfiguration.delete(); PolicyContext.setContextID(child1ContextID); // parent module was deleted, mary is longer resolvable assertFalse(policy.implies(createProtectionDomain(), child1Permission)); } private SecurityDomain createSecurityDomain(String userName, String... roles) throws Exception { SecurityDomain.Builder builder = SecurityDomain.builder(); SimpleMapBackedSecurityRealm realm = new SimpleMapBackedSecurityRealm(); MapAttributes attributes = new MapAttributes(); attributes.addAll(RoleDecoder.KEY_ROLES, Arrays.asList(roles)); realm.setPasswordMap(userName, PasswordFactory.getInstance(ClearPassword.ALGORITHM_CLEAR).generatePassword(new ClearPasswordSpec(userName.toCharArray())), attributes); builder.setDefaultRealmName("default"); builder.addRealm("default",realm).setRoleMapper(RoleMapper.IDENTITY_ROLE_MAPPER).build(); return builder.build(); } @Test public void testFailLinkSamePolicyConfiguration() throws Exception { ElytronPolicyConfigurationFactory policyConfigurationFactory = (ElytronPolicyConfigurationFactory) PolicyConfigurationFactory.getPolicyConfigurationFactory(); String parentContextID = "parent-module"; PolicyConfiguration parentPolicyConfiguration = policyConfigurationFactory.getPolicyConfiguration(parentContextID, false); try { parentPolicyConfiguration.linkConfiguration(parentPolicyConfiguration); fail("Should not be possible to link the same policy with itself"); } catch (Exception e) { assertThat(e, new IsInstanceOf(IllegalArgumentException.class)); } parentPolicyConfiguration.commit(); } private Principal createPrincipal(final String name) { return new NamePrincipal(name); } private ProtectionDomain createProtectionDomain(Principal... principals) { return new ProtectionDomain(null, getClass().getProtectionDomain().getPermissions(), null, principals); } }