PrivilegeEvaluator.java revision fb3b3a01405c222ae1fdbbe6f5c1d4aa696195bb
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster * Copyright (c) 2009 Sun Microsystems Inc. All Rights Reserved
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster * The contents of this file are subject to the terms
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster * of the Common Development and Distribution License
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster * (the License). You may not use this file except in
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster * compliance with the License.
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster * You can obtain a copy of the License at
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster * https://opensso.dev.java.net/public/CDDLv1.0.html or
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster * See the License for the specific language governing
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster * permission and limitations under the License.
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster * When distributing Covered Code, include this CDDL
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster * Header Notice in each file and include the License file
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster * If applicable, add the following below the CDDL Header,
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster * with the fields enclosed by brackets [] replaced by
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster * your own identifying information:
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster * "Portions Copyrighted [year] [name of copyright owner]"
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster * $Id: PrivilegeEvaluator.java,v 1.2 2009/10/07 06:36:40 veiming Exp $
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster * Portions copyright 2010-2014 ForgeRock, Inc.
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Fosterimport com.sun.identity.entitlement.interfaces.IThreadPool;
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Fosterimport java.util.concurrent.locks.ReentrantLock;
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Fosterimport org.forgerock.openam.entitlement.PrivilegeEvaluatorContext;
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Fosterimport org.forgerock.openam.session.util.AppTokenHandler;
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster * This class evaluates entitlements of a subject for a given resource
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster * and a environment parameters.
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster private Map<String, Set<String>> envParameters;
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster private EntitlementCombiner entitlementCombiner;
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster private boolean recursive;
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster private Condition hasResults = lock.newCondition();
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster private final static String PRIVILEGE_EVALUATION_CONTEXT =
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster "org.forgerock.openam.entitlement.context";
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster // Static variables
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster // TODO determine number of tasks per thread
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster private static int evalThreadSize = Evaluator.DEFAULT_POLICY_EVAL_THREAD;
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster private static boolean isMultiThreaded;
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster EntitlementConfiguration ec = EntitlementConfiguration.getInstance(
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster Set<String> setPolicyEvalThread = ec.getConfiguration(
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster EntitlementConfiguration.POLICY_EVAL_THREAD_SIZE);
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster if ((setPolicyEvalThread != null) && !setPolicyEvalThread.isEmpty()) {
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster evalThreadSize = Integer.parseInt(setPolicyEvalThread.
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster "PrivilegeEvaluator.<init>: get evaluation thread pool size",
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster * Initializes the evaluator.
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster * @param adminSubject Administrator subject which is used fo evcaluation.
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster * @param subject Subject to be evaluated.
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster * @param realm Realm Name
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster * @param applicationName Application Name.
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster * @param resourceName Rsource name.
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster * @param actions Action names.
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster * @param envParameters Environment parameters.
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster * @param recursive <code>true</code> for sub tree evaluation
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster * @throws com.sun.identity.entitlement.EntitlementException if
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster * initialization fails.
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster private void init(
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster this.actionNames.addAll(appl.getActions().keySet());
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster entitlementCombiner = appl.getEntitlementCombiner();
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster entitlementCombiner.init(realm, applicationName, resourceName, this.actionNames, recursive);
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster debug.message("[PolicyEval] PrivilegeEvaluator:init()", null);
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster debug.message("[PolicyEval] subject: " + getPrincipalId(subject), null);
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster debug.message("[PolicyEval] realm: " + realm, null);
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster debug.message("[PolicyEval] applicationName: " + applicationName, null);
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster debug.message("[PolicyEval] resourceName: " + resourceName, null);
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster debug.message("[PolicyEval] actions: " + actionNames, null);
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster if ((envParameters != null) && !envParameters.isEmpty()) {
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster private static String getPrincipalId(Subject subject) {
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster Set<Principal> userPrincipals = subject.getPrincipals();
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster return ((userPrincipals != null) && !userPrincipals.isEmpty()) ?
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster userPrincipals.iterator().next().getName() : null;
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster * Returrns <code>true</code> if the subject has privilege to have the
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster * given entitlement.
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster * @param adminSubject Administrator subject which is used for evaluation.
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster * @param subject Subject to be evaluated.
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster * @param applicationName Application Name.
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster * @param entitlement Entitlement to be evaluated.
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster * @param envParameters Environment parameters.
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster * @return <code>true</code> if the subject has privilege to have the
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster * given entitlement.
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster * @throws com.sun.identity.entitlement.EntitlementException if
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster * evaluation fails.
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster public boolean hasEntitlement(
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster init(adminSubject, subject, realm, applicationName,
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster entitlement.getActionValues().keySet(), envParameters, false);
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster entitlement.setApplicationName(applicationName);
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster indexes = entitlement.getResourceSearchIndexes(adminSubject, realm);
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster for (String action : entitlement.getActionValues().keySet()) {
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster // TODO, use policy decision combining algorithm
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster // Default is deny overrides
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster return false;
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster return true;
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster * Returns list of entitlements which is entitled to a subject.
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster * @param adminSubject Administrator subject which is used for evaluation.
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster * @param subject Subject to be evaluated.
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster * @param applicationName Application Name.
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster * @param resourceName Resource name.
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster * @param envParameters Environment parameters.
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster * @param recursive <code>true</code> for sub tree evaluation.
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster * @return <code>true</code> if the subject has privilege to have the
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster * given entitlement.
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster * @throws com.sun.identity.entitlement.EntitlementException if
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster * evaluation fails.
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster init(adminSubject, subject, realm, applicationName,
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster indexes = getApplication().getResourceSearchIndex(resourceName, realm);
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster private List<Entitlement> evaluate(String realm)
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster // Subject index
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster SubjectAttributesManager sam = SubjectAttributesManager.getInstance(
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster // Search for policies
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster PrivilegeIndexStore pis = PrivilegeIndexStore.getInstance(
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster Iterator<IPrivilege> i = pis.search(realm, indexes,
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster sam.getSubjectSearchFilter(subject, applicationName), recursive);
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster // Submit the privileges for evaluation
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster // First collect tasks to be evaluated locally
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster Set<IPrivilege> localPrivileges = new HashSet<IPrivilege>(
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster debug.message("[PolicyEval] PolicyEvaluator.evaluate", null);
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster debug.message("[PolicyEval] search result: privilege=" +
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster // Submit additional privilges to be executed by worker threads
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster boolean tasksSubmitted = false;
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster new PrivilegeEvaluatorContext(realm, resourceName, applicationName);
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster Object appToken = AppTokenHandler.getAndClear();
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster while (true) {
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster privileges = new HashSet<IPrivilege>(2*tasksPerThread);
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster debug.message("[PolicyEval] PolicyEvaluator.evaluate", null);
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster debug.message("[PolicyEval] search result: privilege=" +
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster threadPool.submit(new PrivilegeTask(this, privileges,
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster if ((privileges != null) && !privileges.isEmpty()) {
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster threadPool.submit(new PrivilegeTask(this, privileges,
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster // IPrivilege privileges locally
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster (new PrivilegeTask(this, localPrivileges, tasksSubmitted, appToken, ctx)).run();
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster // Wait for submitted threads to complete evaluation
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster boolean isDone = false;
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster boolean isDone = false;
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster List<Entitlement> ents = entitlementCombiner.getResults();
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster private void receiveEvalResults(int totalCount) {
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster PrivilegeManager.debug.error("PrivilegeEvaluator.evaluate", ex);
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster application = ApplicationManager.getApplicationForEvaluation(
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster // If application is still null, throw an exception
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster private boolean isThreaded;
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster PrivilegeTask(PrivilegeEvaluator parent, Set<IPrivilege> privileges,
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster boolean isThreaded, Object context, PrivilegeEvaluatorContext ctx) {
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster this.privileges = new HashSet<IPrivilege>(privileges.size() *2);
837871e12425577ebe5d6f129d18ea78dd0e640eAllan Foster public void run() {