/*
* A CCNx library test.
*
* Copyright (C) 2008-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.
*/
package org.ccnx.ccn.test.profiles.security.access.group;
import java.security.Key;
import java.util.ArrayList;
import java.util.Random;
import org.ccnx.ccn.CCNHandle;
import org.ccnx.ccn.KeyManager;
import org.ccnx.ccn.config.SystemConfiguration;
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.ACL;
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.profiles.security.access.group.GroupManager;
import org.ccnx.ccn.protocol.ContentName;
import org.ccnx.ccn.utils.CreateUserData;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
public class GroupTestRepo {
static boolean USE_REPO = true;
static int NUM_USERS = 3;
static char [] USER_PASSWORD = new String("password").toCharArray();
static ContentName testStorePrefix = null;
static ContentName userNamespace = null;
static ContentName groupStore = null;
static ContentName userKeyStorePrefix = null;
static String[] _userList = null;
static CCNHandle _handle = null;
static String myUserName = null;
/**
* Have to make a bunch of users.
* @throws Exception
*/
static CreateUserData users = null;
static GroupAccessControlManager _acm = null;
static GroupManager _gm = null;
static Random _random;
static String _randomGroupName;
@AfterClass
public static void tearDownAfterClass() throws Exception {
users.closeAll();
KeyManager.closeDefaultKeyManager();
}
@BeforeClass
public static void setUpBeforeClass() throws Exception {
try {
myUserName = UserConfiguration.userName();
System.out.println("Username = " + myUserName);
testStorePrefix = UserConfiguration.defaultNamespace();
userNamespace = new ContentName(testStorePrefix, "Users");
userKeyStorePrefix = new ContentName(testStorePrefix, "ccnx_keystore");
groupStore = GroupAccessControlProfile.groupNamespaceName(testStorePrefix);
System.out.println("prefix: " + testStorePrefix);
System.out.println("group store: " + groupStore);
System.out.println("user store: " + userNamespace);
_handle = CCNHandle.getHandle();
users = new CreateUserData(userKeyStorePrefix, NUM_USERS,
USE_REPO,
USER_PASSWORD);
users.publishUserKeysToRepository(userNamespace);
_acm = new GroupAccessControlManager(testStorePrefix, groupStore, userNamespace);
_acm.publishMyIdentity(new ContentName(userNamespace, myUserName),
KeyManager.getDefaultKeyManager().getDefaultPublicKey());
_userList = users.friendlyNames().toArray(new String[0]);
// create the root ACL
// myUserName is a manager
Link lk = new Link(new ContentName(userNamespace, myUserName), ACL.LABEL_MANAGER, null);
ArrayList<Link> rootACLcontents = new ArrayList<Link>();
rootACLcontents.add(lk);
ACL rootACL = new ACL(rootACLcontents);
_acm.initializeNamespace(rootACL);
// Whose access control manager is this supposed to be?
_handle.keyManager().rememberAccessControlManager(_acm);
_gm = _acm.groupManager();
_random = new Random();
_randomGroupName = "testGroup" + _random.nextInt();
} catch (Exception e) {
Log.warning(Log.FAC_TEST, "Exception in setupBeforeClass: " + e);
Log.warningStackTrace(Log.FAC_TEST, e);
throw e;
}
}
@Test
public void testGroup() throws Exception {
Log.info(Log.FAC_TEST, "Starting testGroup");
ArrayList<Link> newMembers = new ArrayList<Link>();
ContentName userID = new ContentName(userNamespace, myUserName);
System.out.println("member to add:" + userID);
newMembers.add(new Link(userID));
for(int i = 0; i <2; i++){
String name = _userList[i];
System.out.println("member to add:" + name);
newMembers.add(new Link(new ContentName(userNamespace, name)));
}
System.out.println("creating a group...");
Group newGroup = _gm.createGroup(_randomGroupName, newMembers, 0);
Assert.assertTrue(_gm.haveKnownGroupMemberships());
Assert.assertTrue(_gm.amCurrentGroupMember(newGroup));
Assert.assertTrue(_gm.amCurrentGroupMember(_randomGroupName));
String name = _userList[2];
System.out.println("adding member to group:"+ name);
ArrayList<Link> addMembers = new ArrayList<Link>();
addMembers.add(new Link(new ContentName(userNamespace, name)));
// add members to the group
newGroup.addMembers(addMembers);
ArrayList<Link> removeMembers = new ArrayList<Link>();
System.out.println("removing user:.................." + newMembers.get(2).targetName());
removeMembers.add(newMembers.get(2));
newGroup.removeMembers(removeMembers);
Assert.assertTrue(_gm.haveKnownGroupMemberships());
Assert.assertTrue(_gm.amCurrentGroupMember(newGroup));
Assert.assertTrue(_gm.amCurrentGroupMember(_randomGroupName));
//isGroup sometimes fails, there's a timing issue.
Assert.assertTrue(_gm.isGroup(_randomGroupName, SystemConfiguration.EXTRA_LONG_TIMEOUT));
ContentName pkName = newGroup.publicKeyName();
System.out.println("new group's pk name is " + pkName);
Assert.assertTrue(_gm.isGroup(pkName));
//test groups of group
String randomParentGroupName = "parentGroup" + _random.nextInt();
newMembers.clear();
ContentName childGroupNamespace = GroupAccessControlProfile.groupName(testStorePrefix, _randomGroupName);
System.out.println("child group namespace = " + childGroupNamespace);
newMembers.add(new Link(childGroupNamespace));
Group newParentGroup = _gm.createGroup(randomParentGroupName, newMembers, 0);
Assert.assertTrue(_gm.amCurrentGroupMember(newParentGroup));
System.out.println("adding users to parent group.........");
Thread.sleep(1000);
newParentGroup.addMembers(addMembers);
Key privKey = _gm.getGroupPrivateKey(randomParentGroupName, null);
System.out.println("retrieved group priv key for parent group:" + privKey.toString());
privKey = _gm.getGroupPrivateKey(_randomGroupName, null);
System.out.println("retrieved group priv key:" + privKey.toString());
Log.info(Log.FAC_TEST, "Completed testGroup");
}
@Test
public void testGroupUpdate() throws Exception {
Log.info(Log.FAC_TEST, "Starting testGroupUpdate");
Group ourExistingGroup = _gm.getGroup(_randomGroupName, SystemConfiguration.EXTRA_LONG_TIMEOUT);
// This should be a cache hit. Test that with a 0 timeout
Group aPointerCopy = _gm.getGroup(_randomGroupName, 0);
Assert.assertNotNull("Unexpected cache miss!", aPointerCopy);
// testing pointer equality -- these should be the same object
Assert.assertTrue(ourExistingGroup == aPointerCopy);
GroupAccessControlManager ourACM = new GroupAccessControlManager(testStorePrefix, groupStore, userNamespace);
ourACM.publishMyIdentity(new ContentName(userNamespace, myUserName), KeyManager.getDefaultKeyManager().getDefaultPublicKey());
GroupManager ourGM = ourACM.groupManager();
Thread.sleep(1000);
Group aSeparateGroupCopy = ourGM.getGroup(_randomGroupName, SystemConfiguration.EXTRA_LONG_TIMEOUT);
Assert.assertEquals(ourExistingGroup.publicKeyName(), aSeparateGroupCopy.publicKeyName());
Log.info("Original key name {0}, copy key name {1}", ourExistingGroup.publicKeyName(), aSeparateGroupCopy.publicKeyName());
System.out.println("Original key version: " + ourExistingGroup.publicKeyVersion());
System.out.println("Copy key version : " + aSeparateGroupCopy.publicKeyVersion());
// Now we update the group public key.
ArrayList<Link> removeMembers = new ArrayList<Link>();
Link memberToRemove = aSeparateGroupCopy.membershipList().contents().getLast();
// Link memberToRemove = ourExistingGroup.membershipList().contents().getLast();
removeMembers.add(memberToRemove);
System.out.println("removing user:.................." + memberToRemove.targetName());
aSeparateGroupCopy.removeMembers(removeMembers);
// ourExistingGroup.removeMembers(removeMembers);
Log.info("Post-write Original key name {0}, copy key name {1}", ourExistingGroup.publicKeyName(), aSeparateGroupCopy.publicKeyName());
System.out.println("Post-write original key version: " + ourExistingGroup.publicKeyVersion());
System.out.println("Post-write copy key version : " + aSeparateGroupCopy.publicKeyVersion());
Thread.sleep(1000);
Log.info("Post-write and sleep Original key name {0}, copy key name {1}", ourExistingGroup.publicKeyName(), aSeparateGroupCopy.publicKeyName());
System.out.println("Post-write and sleep original key version: " + ourExistingGroup.publicKeyVersion());
System.out.println("Post-write and sleep copy key version : " + aSeparateGroupCopy.publicKeyVersion());
Log.info(Log.FAC_TEST, "Completed testGroupUpdate");
}
}