/* * A CCNx library test. * * Copyright (C) 2009-2012 Palo Alto Research Center, Inc. * * This work is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License version 2 as published by the * Free Software Foundation. * This work 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 General Public License * for more details. You should have received a copy of the GNU General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ /** * PD org.ccnx.ccn.test.profiles.security.access.group */ package org.ccnx.ccn.test.profiles.security.access.group; import java.util.ArrayList; import java.util.Random; import junit.framework.Assert; import org.ccnx.ccn.CCNHandle; import org.ccnx.ccn.config.UserConfiguration; import org.ccnx.ccn.impl.support.Log; import org.ccnx.ccn.io.content.Link; import org.ccnx.ccn.profiles.security.access.group.Group; import org.ccnx.ccn.profiles.security.access.group.GroupAccessControlManager; import org.ccnx.ccn.profiles.security.access.group.GroupAccessControlProfile; import org.ccnx.ccn.protocol.CCNTime; import org.ccnx.ccn.protocol.ContentName; import org.ccnx.ccn.test.CCNTestHelper; import org.ccnx.ccn.utils.CreateUserData; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; public class GroupRecursiveKeyUpdateTestRepo { static GroupAccessControlManager acm; static ContentName directoryBase, userKeyStorePrefix, userNamespace, groupNamespace; static final int numberOfusers = 2; static CreateUserData td; static String[] friendlyNames; static final int numberOfGroups = 5; static String[] groupName = new String[numberOfGroups]; static Group[] group = new Group[numberOfGroups]; static CCNTime[] groupKeyCreationTime = new CCNTime[numberOfGroups]; static CCNHandle handle; @BeforeClass public static void setUpBeforeClass() throws Exception { CCNTestHelper testHelper = new CCNTestHelper(GroupRecursiveKeyUpdateTestRepo.class); directoryBase = testHelper.getTestNamespace("testInOrder"); userNamespace = GroupAccessControlProfile.userNamespaceName(UserConfiguration.defaultNamespace()); groupNamespace = GroupAccessControlProfile.groupNamespaceName(UserConfiguration.defaultNamespace()); userKeyStorePrefix = new ContentName(UserConfiguration.defaultNamespace(), "_keystore_"); // create user identities with TestUserData td = new CreateUserData(userKeyStorePrefix, numberOfusers, true, "password".toCharArray()); td.publishUserKeysToRepository(userNamespace); friendlyNames = td.friendlyNames().toArray(new String[0]); // create ACM handle = td.getHandleForUser(friendlyNames[1]); acm = new GroupAccessControlManager(directoryBase, groupNamespace, userNamespace, handle); acm.publishMyIdentity(new ContentName(userNamespace, friendlyNames[1]), handle.keyManager().getDefaultPublicKey()); } @AfterClass public static void tearDownAfterClass() throws Exception { td.closeAll(); handle.close(); } /** * Ensures that the tests run in the correct order. * @throws Exception */ @Test public void testInOrder() throws Exception { Log.info(Log.FAC_TEST, "Starting testInOrder"); createGroups(); testRecursiveGroupAncestors(); removeMemberFromGroup0(); Log.info(Log.FAC_TEST, "Completed testInOrder"); } /** * We create the following group structure: * * Group3 * / \ * Group1 Group2 * \ / \ * Group0 Group4 * / \ / * User0 User1 * * @throws Exception */ public void createGroups() throws Exception { Random rand = new Random(); // create group0 containing user0 and user1 ArrayList<Link> G0Members = new ArrayList<Link>(); G0Members.add(new Link(new ContentName(userNamespace, friendlyNames[0]))); G0Members.add(new Link(new ContentName(userNamespace, friendlyNames[1]))); groupName[0] = "group0-" + rand.nextInt(10000); group[0] = acm.groupManager().createGroup(groupName[0], G0Members, 0); // create group4 containing user1 ArrayList<Link> G4Members = new ArrayList<Link>(); G4Members.add(new Link(new ContentName(userNamespace, friendlyNames[1]))); groupName[4] = "group4-" + rand.nextInt(10000); group[4] = acm.groupManager().createGroup(groupName[4], G4Members, 0); // create group1 and group2 containing group0 ArrayList<Link> G1G2Members = new ArrayList<Link>(); G1G2Members.add(new Link(new ContentName(groupNamespace, groupName[0]))); groupName[1] = "group1-" + rand.nextInt(10000); group[1] = acm.groupManager().createGroup(groupName[1], G1G2Members, 0); groupName[2] = "group2-" + rand.nextInt(10000); group[2] = acm.groupManager().createGroup(groupName[2], G1G2Members, 0); // create group3 containing group1 and group2 ArrayList<Link> G3Members = new ArrayList<Link>(); G3Members.add(new Link(new ContentName(groupNamespace, groupName[1]))); G3Members.add(new Link(new ContentName(groupNamespace, groupName[2]))); groupName[3] = "group3-" + rand.nextInt(10000); group[3] = acm.groupManager().createGroup(groupName[3], G3Members, 0); // record the creation time of the original group keys for (int i=0; i<numberOfGroups; i++) groupKeyCreationTime[i] = group[i].publicKeyVersion(); // check the size of the groups Assert.assertEquals(2, group[0].membershipList().membershipList().size()); Assert.assertEquals(1, group[1].membershipList().membershipList().size()); Assert.assertEquals(1, group[2].membershipList().membershipList().size()); Assert.assertEquals(2, group[3].membershipList().membershipList().size()); Assert.assertEquals(1, group[4].membershipList().membershipList().size()); } public void testRecursiveGroupAncestors() throws Exception { ArrayList<Link> ancestors = group[0].recursiveAncestorList(null); // Group0 should have 3 ancestors, not 4 (check that Group3 is not double-counted) Assert.assertEquals(3, ancestors.size()); } /** * We delete User0 from Group0 to cause a recursive key update for groups 0, 1, 2 and 3 (but not Group4). * * Group3 * / \ * Group1 Group2 * \ / \ * Group0 Group4 * / \ / * --- User1 * * @throws Exception */ public void removeMemberFromGroup0() throws Exception { // delete user0 from group0 ArrayList<Link> membersToRemove = new ArrayList<Link>(); membersToRemove.add(new Link(new ContentName(userNamespace, friendlyNames[0]))); group[0].removeMembers(membersToRemove); Thread.sleep(1000); // check group0 is of size 1 Assert.assertEquals(1, group[0].membershipList().membershipList().size()); // check keys of group0, group1, group2 and group3 were updated Assert.assertTrue(group[0].publicKeyVersion().after(groupKeyCreationTime[0])); Assert.assertTrue(group[1].publicKeyVersion().after(groupKeyCreationTime[1])); Assert.assertTrue(group[2].publicKeyVersion().after(groupKeyCreationTime[2])); Assert.assertTrue(group[3].publicKeyVersion().after(groupKeyCreationTime[3])); // check key of group4 was not updated Assert.assertTrue(group[4].publicKeyVersion().equals(groupKeyCreationTime[4])); } }