/**
* Licensed to Apereo under one or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information regarding copyright ownership. Apereo
* licenses this file to you 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 the
* following location:
*
* <p>http://www.apache.org/licenses/LICENSE-2.0
*
* <p>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.apereo.portal.security.provider;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.Random;
import junit.framework.TestCase;
import junit.textui.TestRunner;
import org.apereo.portal.AuthorizationException;
import org.apereo.portal.groups.GroupServiceConfiguration;
import org.apereo.portal.groups.IGroupMember;
import org.apereo.portal.permission.IPermissionActivity;
import org.apereo.portal.permission.IPermissionOwner;
import org.apereo.portal.permission.target.IPermissionTarget;
import org.apereo.portal.properties.PropertiesManager;
import org.apereo.portal.security.IAuthorizationPrincipal;
import org.apereo.portal.security.IAuthorizationService;
import org.apereo.portal.security.IAuthorizationServiceFactory;
import org.apereo.portal.security.IPermission;
import org.apereo.portal.security.IPermissionPolicy;
import org.apereo.portal.security.IPermissionStore;
import org.apereo.portal.security.PortalSecurityException;
import org.apereo.portal.services.AuthorizationService;
import org.apereo.portal.services.GroupService;
/**
* Tests the authorization framework.
*/
public class AuthorizationTester extends TestCase {
private String OWNER = "UP_FRAMEWORK";
private String TEST_TARGET = "Test_Target.";
private String TEST_ACTIVITY = "Test_Activity";
private String EVERYONE_GROUP_KEY;
private String EVERYONE_GROUP_PRINCIPAL_KEY;
private String NOONE_GROUP_PRINCIPAL_KEY;
private String STUDENT_GROUP_PRINCIPAL_KEY;
private String STUDENT_PRINCIPAL_KEY = "2.student";
private String GROUP_SEPARATOR;
private int NUMBER_TEST_PERMISSIONS = 10;
private IAuthorizationService authorizationService;
private IPermissionStore permissionStore;
private IPermissionPolicy defaultPermissionPolicy;
private IPermissionPolicy negativePermissionPolicy;
private IPermissionPolicy positivePermissionPolicy;
private List testPermissions = new ArrayList();
private static Class GROUP_CLASS;
private static Class IPERSON_CLASS;
private static String CR = "\n";
private Random random = new Random();
private class NegativePermissionPolicy implements IPermissionPolicy {
private NegativePermissionPolicy() {
super();
}
public boolean doesPrincipalHavePermission(
IAuthorizationService service,
IAuthorizationPrincipal principal,
IPermissionOwner owner,
IPermissionActivity activity,
IPermissionTarget target)
throws AuthorizationException {
// Seems the only value this method provides is NPE detection
return !(service.equals(service))
&& (principal.equals(principal))
&& (owner.equals(owner))
&& (activity.equals(activity));
}
public String toString() {
return this.getClass().getName();
}
}
private class PositivePermissionPolicy implements IPermissionPolicy {
private PositivePermissionPolicy() {
super();
}
public boolean doesPrincipalHavePermission(
IAuthorizationService service,
IAuthorizationPrincipal principal,
IPermissionOwner owner,
IPermissionActivity activity,
IPermissionTarget target)
throws AuthorizationException {
// Seems the only value this method provides is NPE detection
return (service.equals(service))
&& (principal.equals(principal))
&& (owner.equals(owner))
&& (activity.equals(activity));
}
public String toString() {
return this.getClass().getName();
}
}
private class PrincipalTester implements Runnable {
protected Class type;
protected String key;
int numTests = 0;
protected String testerID = null;
protected String printID = null;
protected IPermission testPermission;
protected PrincipalTester(
String pKey, Class pType, int tests, String id, IPermission permission) {
super();
key = pKey;
type = pType;
numTests = tests;
testerID = id;
testPermission = permission;
}
public void run() {
printID = "Tester " + testerID;
print(printID + " starting.");
runAndSleep(numTests, true);
print(
printID
+ " finished first part of tests. Will now sleep for 5000 ms to let main thread catch up.");
try {
Thread.sleep(5000);
} catch (Exception ex) {
}
print(printID + " starting second part of tests.");
runAndSleep(numTests, false);
print(printID + " is done.");
}
private void runAndSleep(int cycles, boolean expectedResult) {
for (int i = 0; i < cycles; i++) {
//print(printID + " running test # " + (i+1));
try {
String msg =
"Testing for "
+ testPermission
+ " (should be "
+ expectedResult
+ ")";
boolean testResult = (runTest() == expectedResult);
assertTrue(msg, testResult);
} catch (Exception ex) {
}
int sleepMillis = random.nextInt(10);
//print(printID + " will now sleep for " + sleepMillis + " ms.");
try {
Thread.sleep(sleepMillis);
} catch (Exception ex) {
}
}
}
private boolean runTest() throws AuthorizationException {
IAuthorizationPrincipal principal = getService().newPrincipal(key, type);
//print("Testing principal for " + testPermission);
return principal.hasPermission(OWNER, TEST_ACTIVITY, testPermission.getTarget());
}
}
/** AuthorizationTester constructor comment. */
public AuthorizationTester(String name) {
super(name);
}
/** @return org.apereo.portal.security.IPermissionPolicy */
private IPermissionPolicy getNegativePermissionPolicy() throws AuthorizationException {
if (negativePermissionPolicy == null) {
negativePermissionPolicy = new AuthorizationTester.NegativePermissionPolicy();
}
return negativePermissionPolicy;
}
/** @return org.apereo.portal.security.IPermissionStore */
private IPermissionStore getPermissionStore() throws AuthorizationException {
if (permissionStore == null) {
initializePermissionStore();
}
return permissionStore;
}
/** @return org.apereo.portal.security.IPermissionPolicy */
private IPermissionPolicy getPositivePermissionPolicy() throws AuthorizationException {
if (positivePermissionPolicy == null) {
positivePermissionPolicy = new AuthorizationTester.PositivePermissionPolicy();
}
return positivePermissionPolicy;
}
/** @return org.apereo.portal.security.AuthorizationService */
private IAuthorizationService getService() throws AuthorizationException {
if (authorizationService == null) {
initializeAuthorizationService();
}
return authorizationService;
}
/** Create an implementation of IAuthorizationService. */
private void initializeAuthorizationService() throws AuthorizationException {
// Get the security properties file
java.io.InputStream secprops =
AuthorizationService.class.getResourceAsStream("/properties/security.properties");
// Get the properties from the security properties file
Properties pr = new Properties();
String s_factoryName = null;
try {
pr.load(secprops);
// Look for our authorization factory and instantiate an instance of it or die trying.
if ((s_factoryName = pr.getProperty("authorizationProvider")) == null) {
print(
"ERROR: AuthorizationProvider not specified or incorrect in security.properties");
} else {
try {
IAuthorizationServiceFactory factory =
(IAuthorizationServiceFactory)
Class.forName(s_factoryName).newInstance();
authorizationService = factory.getAuthorization();
} catch (Exception e) {
print("ERROR: Failed to instantiate " + s_factoryName);
}
}
} catch (IOException e) {
print("ERROR: " + e.getMessage());
} finally {
try {
if (secprops != null) secprops.close();
} catch (IOException ioe) {
print(new PortalSecurityException(ioe.getMessage()).toString());
}
}
}
/** Create an implementation of IPermissionStore. */
private void initializePermissionStore() throws AuthorizationException {
String eMsg = null;
String factoryName =
PropertiesManager.getProperty(
"org.apereo.portal.security.IPermissionStore.implementation");
if (factoryName == null) {
eMsg =
"AuthorizationTester.initializePermissionStore(): No entry for org.apereo.portal.security.IPermissionStore.implementation portal.properties.";
print(eMsg);
throw new AuthorizationException(eMsg);
}
try {
permissionStore = (IPermissionStore) Class.forName(factoryName).newInstance();
} catch (Exception e) {
eMsg =
"AuthorizationTester.initializePermissionStore(): Problem creating permission store... "
+ e.getMessage();
print(eMsg);
throw new AuthorizationException(eMsg);
}
}
/**
* Starts the application.
*
* @param args an array of command-line arguments
*/
public static void main(java.lang.String[] args) throws Exception {
String[] mainArgs = {"org.apereo.portal.security.provider.AuthorizationTester"};
print("START TESTING AUTHORIZATION SERVICE");
printBlankLine();
TestRunner.main(mainArgs);
printBlankLine();
print("END TESTING AUTHORIZATION SERVICE");
}
/** @param msg java.lang.String */
private static void print(String msg) {
java.sql.Timestamp ts = new java.sql.Timestamp(System.currentTimeMillis());
System.out.println(ts + " : " + msg);
}
private static void printBlankLine() {
System.out.println("");
}
protected void setUp() {
String msg = null;
IPermission[] retrievedPermissions = null;
IPermission newPermission, retrievedPermission = null;
java.util.Date effectiveDate = new java.util.Date();
java.util.Date expirationDate =
new java.util.Date(System.currentTimeMillis() + (60 * 60 * 24 * 1000));
int idx = 0;
try {
if (GROUP_CLASS == null) {
GROUP_CLASS = Class.forName("org.apereo.portal.groups.IEntityGroup");
}
if (IPERSON_CLASS == null) {
IPERSON_CLASS = Class.forName("org.apereo.portal.security.IPerson");
}
GROUP_SEPARATOR = GroupServiceConfiguration.getConfiguration().getNodeSeparator();
EVERYONE_GROUP_KEY = "local" + GROUP_SEPARATOR + "0";
EVERYONE_GROUP_PRINCIPAL_KEY = "3." + EVERYONE_GROUP_KEY;
NOONE_GROUP_PRINCIPAL_KEY = "3.local" + GROUP_SEPARATOR + "999";
STUDENT_GROUP_PRINCIPAL_KEY = "3.local" + GROUP_SEPARATOR + "1";
msg = "Creating test permissions.";
print(msg);
retrievedPermissions =
getPermissionStore()
.select(
OWNER,
EVERYONE_GROUP_PRINCIPAL_KEY,
TEST_ACTIVITY,
null,
IPermission.PERMISSION_TYPE_GRANT);
assertEquals(msg, 0, retrievedPermissions.length);
for (idx = 0; idx < NUMBER_TEST_PERMISSIONS; idx++) {
newPermission = getPermissionStore().newInstance(OWNER);
newPermission.setPrincipal(EVERYONE_GROUP_PRINCIPAL_KEY);
newPermission.setActivity(TEST_ACTIVITY);
newPermission.setTarget(TEST_TARGET + idx);
newPermission.setType(IPermission.PERMISSION_TYPE_GRANT);
newPermission.setEffective(effectiveDate);
newPermission.setExpires(expirationDate);
getPermissionStore().add(newPermission);
testPermissions.add(newPermission);
}
retrievedPermissions =
getPermissionStore()
.select(
OWNER,
EVERYONE_GROUP_PRINCIPAL_KEY,
TEST_ACTIVITY,
null,
IPermission.PERMISSION_TYPE_GRANT);
assertEquals(msg, NUMBER_TEST_PERMISSIONS, retrievedPermissions.length);
msg = "Creating test DENY permission for student group.";
print(msg);
retrievedPermission = (IPermission) testPermissions.get(0);
newPermission = getPermissionStore().newInstance(OWNER);
newPermission.setActivity(TEST_ACTIVITY);
newPermission.setPrincipal(STUDENT_GROUP_PRINCIPAL_KEY);
newPermission.setTarget(retrievedPermission.getTarget());
newPermission.setType(IPermission.PERMISSION_TYPE_DENY);
retrievedPermissions =
getPermissionStore()
.select(
OWNER,
STUDENT_GROUP_PRINCIPAL_KEY,
TEST_ACTIVITY,
retrievedPermission.getTarget(),
IPermission.PERMISSION_TYPE_DENY);
assertEquals(msg, 0, retrievedPermissions.length);
getPermissionStore().add(newPermission);
retrievedPermissions =
getPermissionStore()
.select(
OWNER,
STUDENT_GROUP_PRINCIPAL_KEY,
TEST_ACTIVITY,
retrievedPermission.getTarget(),
IPermission.PERMISSION_TYPE_DENY);
assertEquals(msg, 1, retrievedPermissions.length);
testPermissions.add(newPermission);
msg = "Creating test DENY permission for student entity.";
print(msg);
newPermission = getPermissionStore().newInstance(OWNER);
retrievedPermission = (IPermission) testPermissions.get(1);
newPermission.setPrincipal(STUDENT_PRINCIPAL_KEY);
newPermission.setActivity(TEST_ACTIVITY);
newPermission.setTarget(retrievedPermission.getTarget());
newPermission.setType(IPermission.PERMISSION_TYPE_DENY);
retrievedPermissions =
getPermissionStore()
.select(
OWNER,
STUDENT_PRINCIPAL_KEY,
TEST_ACTIVITY,
retrievedPermission.getTarget(),
IPermission.PERMISSION_TYPE_DENY);
assertEquals(msg, 0, retrievedPermissions.length);
getPermissionStore().add(newPermission);
retrievedPermissions =
getPermissionStore()
.select(
OWNER,
STUDENT_PRINCIPAL_KEY,
TEST_ACTIVITY,
retrievedPermission.getTarget(),
IPermission.PERMISSION_TYPE_DENY);
assertEquals(msg, 1, retrievedPermissions.length);
testPermissions.add(newPermission);
} catch (Exception ex) {
print("AuthorizationTester.setUp(): " + ex.getMessage());
}
}
protected void tearDown() {
try {
IPermission[] permissions =
(IPermission[])
testPermissions.toArray(new IPermission[testPermissions.size()]);
getPermissionStore().delete(permissions);
testPermissions.clear();
} catch (Exception ex) {
print("AuthorizationTester.tearDown(): " + ex.getMessage());
}
}
public void testAlternativePermissionPolicies() throws Exception {
print("***** ENTERING AuthorizationTester.testAlternativePermissionPolicies() *****");
String msg = null;
boolean testResult = false;
String activity = IPermission.PORTLET_SUBSCRIBER_ACTIVITY;
String existingTarget = "CHAN_ID.1";
String nonExistingTarget = "CHAN_ID.9999";
msg = "Creating a group member for everyone (" + EVERYONE_GROUP_PRINCIPAL_KEY + ").";
print(msg);
IGroupMember everyone = GroupService.getGroupMember(EVERYONE_GROUP_KEY, GROUP_CLASS);
assertNotNull(msg, everyone);
msg = "Getting principal for " + everyone;
print(msg);
IAuthorizationPrincipal prin = getService().newPrincipal(everyone);
assertNotNull(msg, prin);
msg = "Testing DEFAULT permission policy for an existing channel";
print(msg);
testResult = prin.hasPermission(OWNER, activity, existingTarget);
assertTrue(msg, testResult);
msg = "Testing POSITIVE permission policy for an existing channel";
print(msg);
testResult =
prin.hasPermission(OWNER, activity, existingTarget, getPositivePermissionPolicy());
assertTrue(msg, testResult);
msg = "Testing NEGATIVE permission policy for an existing channel";
print(msg);
testResult =
prin.hasPermission(OWNER, activity, existingTarget, getNegativePermissionPolicy());
assertTrue(msg, !testResult);
msg = "Testing DEFAULT permission policy for a nonexistent channel";
print(msg);
testResult = prin.hasPermission(OWNER, activity, nonExistingTarget);
assertTrue(msg, !testResult);
msg = "Testing POSITIVE permission policy for nonexistent channel";
print(msg);
testResult =
prin.hasPermission(
OWNER, activity, nonExistingTarget, getPositivePermissionPolicy());
assertTrue(msg, testResult);
msg = "Testing NEGATIVE permission policy for a nonexistent channel";
print(msg);
testResult =
prin.hasPermission(
OWNER, activity, nonExistingTarget, getNegativePermissionPolicy());
assertTrue(msg, !testResult);
print("***** LEAVING AuthorizationTester.testAlternativePermissionPolicies() *****" + CR);
}
public void testDoesPrincipalHavePermission() throws Exception {
print("***** ENTERING AuthorizationTester.testDoesPrincipalHavePermission() *****");
String msg = null;
IPermission testPermission = null;
boolean testResult = false;
int idx = 0;
msg = "Creating authorizationPrincipal for student.";
print(msg);
IAuthorizationPrincipal prin = getService().newPrincipal("student", IPERSON_CLASS);
assertNotNull(msg, prin);
testPermission = (IPermission) testPermissions.get(0);
msg = "Testing " + testPermission + " (should be TRUE -- inherited from Everyone)";
print(msg);
testResult = prin.hasPermission(OWNER, TEST_ACTIVITY, testPermission.getTarget());
assertTrue(msg, testResult);
testPermission = (IPermission) testPermissions.get(1);
msg = "Testing " + testPermission + " (should be FALSE -- directly denied)";
print(msg);
testResult = prin.hasPermission(OWNER, TEST_ACTIVITY, testPermission.getTarget());
assertTrue(msg, !testResult);
msg = "Testing the rest of the test permissions (should be TRUE).";
print(msg);
for (idx = 2; idx < NUMBER_TEST_PERMISSIONS; idx++) {
testPermission = (IPermission) testPermissions.get(idx);
testResult = prin.hasPermission(OWNER, TEST_ACTIVITY, testPermission.getTarget());
assertTrue(msg, testResult);
}
print("***** LEAVING AuthorizationTester.testDoesPrincipalHavePermission() *****" + CR);
}
public void testPermissionStore() throws Exception {
print("***** ENTERING AuthorizationTester.testPermissionStore() *****");
String msg = null;
String activity = IPermission.PORTLET_SUBSCRIBER_ACTIVITY;
String existingTarget = "CHAN_ID.1";
String nonExistingTarget = "CHAN_ID.000";
// String noonePrincipal = "3.local.999";
IPermission[] permissions, addedPermissions = null;
IPermission newPermission, retrievedPermission = null;
java.util.Date effectiveDate = new java.util.Date();
java.util.Date expirationDate =
new java.util.Date(System.currentTimeMillis() + (60 * 60 * 24 * 1000));
int numAddedPermissions = 10;
int idx = 0;
// Add a new permission.
msg = "Creating a new permission for everyone (" + EVERYONE_GROUP_PRINCIPAL_KEY + ").";
print(msg);
newPermission = getPermissionStore().newInstance(OWNER);
assertNotNull(msg, newPermission);
newPermission.setPrincipal(EVERYONE_GROUP_PRINCIPAL_KEY);
newPermission.setActivity(activity);
newPermission.setTarget(nonExistingTarget);
newPermission.setType(IPermission.PERMISSION_TYPE_GRANT);
msg = "Testing if new permission exists in store.";
print(msg);
permissions =
getPermissionStore()
.select(
OWNER,
EVERYONE_GROUP_PRINCIPAL_KEY,
activity,
nonExistingTarget,
IPermission.PERMISSION_TYPE_GRANT);
assertEquals(msg, 0, permissions.length);
msg = "Adding permission to store.";
print(msg);
getPermissionStore().add(newPermission);
permissions =
getPermissionStore()
.select(
OWNER,
EVERYONE_GROUP_PRINCIPAL_KEY,
activity,
nonExistingTarget,
IPermission.PERMISSION_TYPE_GRANT);
assertEquals(msg, 1, permissions.length);
// Update the new permission we have just added.
msg = "Updating permission.";
print(msg);
retrievedPermission = permissions[0];
retrievedPermission.setType(IPermission.PERMISSION_TYPE_DENY);
retrievedPermission.setEffective(effectiveDate);
retrievedPermission.setExpires(expirationDate);
getPermissionStore().update(retrievedPermission);
permissions =
getPermissionStore()
.select(
OWNER,
EVERYONE_GROUP_PRINCIPAL_KEY,
activity,
nonExistingTarget,
IPermission.PERMISSION_TYPE_DENY);
assertEquals(msg, 1, permissions.length);
assertEquals(msg, IPermission.PERMISSION_TYPE_DENY, permissions[0].getType());
assertEquals(msg, effectiveDate, permissions[0].getEffective());
assertEquals(msg, expirationDate, permissions[0].getExpires());
// Delete the retrieved permission.
msg = "Deleting the updated permission.";
print(msg);
getPermissionStore().delete(retrievedPermission);
permissions =
getPermissionStore()
.select(
OWNER,
EVERYONE_GROUP_PRINCIPAL_KEY,
activity,
nonExistingTarget,
IPermission.PERMISSION_TYPE_DENY);
assertEquals(msg, 0, permissions.length);
// Add and delete an array of permissions.
msg = "Creating and adding an Array of " + numAddedPermissions + " Permissions.";
print(msg);
addedPermissions = new IPermission[numAddedPermissions];
for (idx = 0; idx < numAddedPermissions; idx++) {
addedPermissions[idx] = getPermissionStore().newInstance(OWNER);
addedPermissions[idx].setActivity(activity);
addedPermissions[idx].setPrincipal(NOONE_GROUP_PRINCIPAL_KEY);
addedPermissions[idx].setTarget(existingTarget + "_" + idx);
addedPermissions[idx].setType(IPermission.PERMISSION_TYPE_GRANT);
addedPermissions[idx].setEffective(effectiveDate);
addedPermissions[idx].setExpires(expirationDate);
}
getPermissionStore().add(addedPermissions);
permissions =
getPermissionStore().select(OWNER, NOONE_GROUP_PRINCIPAL_KEY, activity, null, null);
assertEquals(msg, numAddedPermissions, permissions.length);
msg = "Deleting the Array of " + numAddedPermissions + " Permissions.";
print(msg);
getPermissionStore().delete(permissions);
permissions =
getPermissionStore().select(OWNER, NOONE_GROUP_PRINCIPAL_KEY, activity, null, null);
assertEquals(msg, 0, permissions.length);
print("***** LEAVING AuthorizationTester.testPermissionStore() *****" + CR);
}
/**
* Tests concurrent access to permissions via "singleton" principal objects. Only run this test
* when the property org.apereo.portal.security.IAuthorizationService.cachePermissions=true,
* since performance of the db calls will distort the time needed to complete the various parts
* of the test.
*/
public void testPermissionPrincipal() throws Exception {
print("***** ENTERING AuthorizationTester.testPermissionPrincipal() *****");
Class type = IPERSON_CLASS;
String key = "student";
int numPrincipals = 10;
int numTestingThreads = 10;
int idx = 0;
long pauseBeforeUpdateMillis = 3000;
long pauseAfterUpdateMillis = 10000;
IAuthorizationPrincipal[] principals = new IAuthorizationPrincipal[numPrincipals];
for (idx = 0; idx < numPrincipals; idx++) {
principals[idx] = getService().newPrincipal(key, type);
}
String msg = "Test that principal " + principals[0] + " is being cached.";
print(msg);
for (idx = 1; idx < numPrincipals; idx++) {
assertTrue(msg, principals[idx] == principals[0]);
}
IAuthorizationPrincipal p1 = principals[0];
IPermission testPermission = (IPermission) testPermissions.get(0);
msg =
"Testing first principal for "
+ testPermission
+ " (should be TRUE -- inherited from Everyone)";
print(msg);
boolean testResult = p1.hasPermission(OWNER, TEST_ACTIVITY, testPermission.getTarget());
assertTrue(msg, testResult);
print("Starting testing Threads.");
Thread[] testers = new Thread[numTestingThreads];
for (idx = 0; idx < numTestingThreads; idx++) {
String id = "" + idx;
PrincipalTester pt = new PrincipalTester(key, type, 10, id, testPermission);
testers[idx] = new Thread(pt);
testers[idx].start();
}
print("Will now sleep for " + pauseBeforeUpdateMillis + " ms to let testing threads run.");
try {
Thread.sleep(pauseBeforeUpdateMillis);
} catch (Exception ex) {
}
/*
* Remove a permission and test a principal. After a pause, the testing threads
* will wake up and perform the 2nd part of their tests to confirm this update.
*/
msg = "Deleting " + testPermission;
print(msg);
IPermission[] perms = new IPermission[1];
perms[0] = testPermission;
getService().removePermissions(perms);
msg =
"Testing first principal for "
+ testPermission
+ " (should be FALSE -- has been removed.)";
print(msg);
testResult = p1.hasPermission(OWNER, TEST_ACTIVITY, testPermission.getTarget());
assertTrue(msg, !testResult);
print(
"Will now sleep for "
+ pauseAfterUpdateMillis
+ " ms to let testing threads complete.");
try {
Thread.sleep(pauseAfterUpdateMillis);
} catch (Exception ex) {
}
print("***** LEAVING AuthorizationTester.testPermissionPrincipal() *****" + CR);
}
}