/* * 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.util.ArrayList; import java.util.Random; import junit.framework.Assert; import org.ccnx.ccn.CCNHandle; import org.ccnx.ccn.config.SystemConfiguration; import org.ccnx.ccn.config.UserConfiguration; import org.ccnx.ccn.impl.CCNFlowControl.SaveType; import org.ccnx.ccn.impl.support.Log; import org.ccnx.ccn.io.CCNFileInputStream; import org.ccnx.ccn.io.CCNInputStream; import org.ccnx.ccn.io.CCNOutputStream; import org.ccnx.ccn.io.RepositoryFileOutputStream; import org.ccnx.ccn.io.content.Link; import org.ccnx.ccn.profiles.namespace.NamespaceManager; import org.ccnx.ccn.profiles.namespace.ParameterizedName; import org.ccnx.ccn.profiles.security.access.AccessControlManager; import org.ccnx.ccn.profiles.security.access.AccessDeniedException; import org.ccnx.ccn.profiles.security.access.group.ACL; 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.ACL.ACLOperation; 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 ACPerformanceTestRepo { static ContentName domainPrefix, userKeystore, userNamespace, groupNamespace; static String[] userNames = {"Alice", "Bob", "Carol"}; static ContentName baseDirectory, nodeName; static CreateUserData cua; static final int blockSize = 8096; static final int contentSizeInBlocks = 100; static Random rnd; static CCNHandle _AliceHandle; static GroupAccessControlManager _AliceACM; int readsize = 1024; byte [] buffer = new byte[readsize]; @BeforeClass public static void setUpBeforeClass() throws Exception { rnd = new Random(); CCNTestHelper testHelper = new CCNTestHelper(ACPerformanceTestRepo.class); domainPrefix = testHelper.getTestNamespace("testInOrder"); userNamespace = GroupAccessControlProfile.userNamespaceName(UserConfiguration.defaultNamespace()); groupNamespace = GroupAccessControlProfile.groupNamespaceName(UserConfiguration.defaultNamespace()); userKeystore = new ContentName(UserConfiguration.defaultNamespace(), "_keystore_"); cua = new CreateUserData(userKeystore, userNames, userNames.length, true, "password".toCharArray()); cua.publishUserKeysToRepositorySetLocators(userNamespace); // The root ACL at domainPrefix has Alice as a manager ArrayList<Link> ACLcontents = new ArrayList<Link>(); Link lk = new Link(new ContentName(userNamespace, userNames[0]), ACL.LABEL_MANAGER, null); ACLcontents.add(lk); ACL rootACL = new ACL(ACLcontents); // Set user and group storage locations as parameterized names ArrayList<ParameterizedName> parameterizedNames = new ArrayList<ParameterizedName>(); ParameterizedName uName = new ParameterizedName("User", userNamespace, null); parameterizedNames.add(uName); ParameterizedName gName = new ParameterizedName("Group", groupNamespace, null); parameterizedNames.add(gName); // Set access control policy marker, written as default user. ContentName profileName = ContentName.fromNative(GroupAccessControlManager.PROFILE_NAME_STRING); GroupAccessControlManager.create(domainPrefix, profileName, rootACL, parameterizedNames, null, SaveType.REPOSITORY, CCNHandle.getHandle()); // get handle and ACM for Alice _AliceHandle = cua.getHandleForUser(userNames[0]); Assert.assertNotNull(_AliceHandle); NamespaceManager.clearSearchedPathCache(); AccessControlManager.loadAccessControlManagerForNamespace(domainPrefix, _AliceHandle); _AliceACM = (GroupAccessControlManager) AccessControlManager.findACM(domainPrefix, _AliceHandle); Assert.assertNotNull(_AliceACM); // load an ACM for the other users. CCNHandle userHandle = null; for (int i=1; i < userNames.length; ++i) { userHandle = cua.getHandleForUser(userNames[i]); AccessControlManager.loadAccessControlManagerForNamespace(domainPrefix, userHandle); } } @AfterClass public static void tearDownAfterClass() throws Exception { cua.closeAll(); } @Test public void performanceTest() throws Exception { Log.info(Log.FAC_TEST, "Starting performanceTest"); createBaseDirectoryACL(); writeContentInDirectory(); // Alice and Bob have permission to read the file readFileAs(userNames[0]); readFileAs(userNames[1]); // Carol does not have permission to read the file try { readFileAs(userNames[2]); Assert.fail(); } catch (AccessDeniedException ade) {} updateACL(); // Carol now has permission to read the file readFileAs(userNames[2]); Log.info(Log.FAC_TEST, "Completed performanceTest"); } /** * Create a new ACL at baseDirectory with Alice as a manager and Bob as a reader */ public void createBaseDirectoryACL() throws Exception { long startTime = System.currentTimeMillis(); baseDirectory = domainPrefix.append(ContentName.fromNative("/Alice/documents/images/")); ArrayList<Link> ACLcontents = new ArrayList<Link>(); ACLcontents.add(new Link(new ContentName(userNamespace, userNames[0]), ACL.LABEL_MANAGER, null)); ACLcontents.add(new Link(new ContentName(userNamespace, userNames[1]), ACL.LABEL_READER, null)); ACL baseDirACL = new ACL(ACLcontents); _AliceACM.setACL(baseDirectory, baseDirACL); System.out.println("createACL: " + (System.currentTimeMillis() - startTime)); } /** * write a file in the baseDirectory */ public void writeContentInDirectory() { long startTime = System.currentTimeMillis(); try { nodeName = new ContentName(baseDirectory, "randomContent"); CCNOutputStream ostream = new RepositoryFileOutputStream(nodeName, _AliceHandle); ostream.setTimeout(SystemConfiguration.MAX_TIMEOUT); byte [] buffer = new byte[blockSize]; for (int i=0; i<contentSizeInBlocks; i++) { rnd.nextBytes(buffer); ostream.write(buffer, 0, blockSize); } ostream.close(); } catch (Exception e) { Log.warningStackTrace(Log.FAC_TEST, e); Assert.fail(); } System.out.println("writeContent: " + (System.currentTimeMillis() - startTime)); } /** * Read the file as the specified user * @param userName the name of the user * @throws AccessDeniedException */ public void readFileAs(String userName) throws Exception { long startTime = System.currentTimeMillis(); try { CCNHandle handle = cua.getHandleForUser(userName); CCNInputStream input = new CCNFileInputStream(nodeName, handle); input.setTimeout(SystemConfiguration.MAX_TIMEOUT); int readcount = 0; int readtotal = 0; while ((readcount = input.read(buffer)) != -1){ readtotal += readcount; } Assert.assertEquals(blockSize * contentSizeInBlocks, readtotal); } // we want to propagate AccessDeniedException, but not IOException. // Since AccessDeniedException is a subclass of IOException, we catch and re-throw it. catch (AccessDeniedException ade) { System.out.println("Failed to read file as " + userName + ": " + (System.currentTimeMillis() - startTime)); throw ade; } catch (Exception e) { throw e; } System.out.println("read file as " + userName + ": " + (System.currentTimeMillis() - startTime)); } /** * Add Carol as a reader to the ACL on baseDirectory */ public void updateACL() throws Exception { long startTime = System.currentTimeMillis(); ArrayList<ACLOperation> ACLUpdates = new ArrayList<ACLOperation>(); Link lk = new Link(new ContentName(userNamespace, userNames[2])); ACLUpdates.add(ACLOperation.addReaderOperation(lk)); _AliceACM.updateACL(baseDirectory, ACLUpdates); System.out.println("updateACL: " + (System.currentTimeMillis() - startTime)); } }