001/**
002 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003 *
004 * Copyright (c) 2008 Sun Microsystems Inc. All Rights Reserved
005 *
006 * The contents of this file are subject to the terms
007 * of the Common Development and Distribution License
008 * (the License). You may not use this file except in
009 * compliance with the License.
010 *
011 * You can obtain a copy of the License at
012 * https://opensso.dev.java.net/public/CDDLv1.0.html or
013 * opensso/legal/CDDLv1.0.txt
014 * See the License for the specific language governing
015 * permission and limitations under the License.
016 *
017 * When distributing Covered Code, include this CDDL
018 * Header Notice in each file and include the License file
019 * at opensso/legal/CDDLv1.0.txt.
020 * If applicable, add the following below the CDDL Header,
021 * with the fields enclosed by brackets [] replaced by
022 * your own identifying information:
023 * "Portions Copyrighted [year] [name of copyright owner]"
024 *
025 * $Id: Evaluator.java,v 1.2 2009/09/10 16:35:38 veiming Exp $
026 *
027 * Portions copyright 2013-2015 ForgeRock AS.
028 */
029package com.sun.identity.entitlement;
030
031import com.sun.identity.shared.Constants;
032import com.sun.identity.shared.configuration.SystemPropertiesManager;
033import java.util.ArrayList;
034import java.util.List;
035import java.util.Map;
036import java.util.Set;
037import javax.security.auth.Subject;
038import org.forgerock.guice.core.InjectorHolder;
039import org.forgerock.openam.entitlement.PolicyConstants;
040import org.forgerock.openam.entitlement.monitoring.EntitlementConfigurationWrapper;
041import org.forgerock.openam.entitlement.monitoring.PolicyMonitor;
042import org.forgerock.openam.entitlement.monitoring.PolicyMonitoringType;
043
044/**
045 * The class evaluates entitlement request and provides decisions.
046 * @supported.api
047 */
048public class Evaluator {
049
050    private Subject adminSubject;
051    private String applicationName =
052        ApplicationTypeManager.URL_APPLICATION_TYPE_NAME;
053
054    public static final int DEFAULT_POLICY_EVAL_THREAD = 10;
055
056    private final PolicyMonitor policyMonitor;
057    private final EntitlementConfigurationWrapper configWrapper;
058
059    /**
060     * Constructor to create an evaluator of default service type.
061     *
062     * @throws EntitlementException if any other abnormal condition occ.
063     */
064    private Evaluator()
065        throws EntitlementException {
066        policyMonitor = getPolicyMonitor();
067        configWrapper = new EntitlementConfigurationWrapper();
068
069    }
070
071    private PolicyMonitor getPolicyMonitor() {
072        //used as no direct access to SystemProperties
073        boolean serverMode = Boolean.parseBoolean(SystemPropertiesManager.get(Constants.SERVER_MODE));
074
075        if (serverMode) {
076            return InjectorHolder.getInstance(PolicyMonitor.class);
077        } else {
078            return null;
079        }
080    }
081
082    /**
083     * Constructor to create an evaluator given the service type.
084     *
085     * @param subject Subject who credential is used for performing the 
086     *        evaluation.
087     * @param applicationName the name of the aplication for
088     *        which this evaluator can be used.
089     * @throws EntitlementException if any other abnormal condition occured.
090     */
091    public Evaluator(Subject subject, String applicationName)
092        throws EntitlementException {
093        adminSubject = subject;
094        this.applicationName = applicationName;
095        policyMonitor = getPolicyMonitor();
096        configWrapper = new EntitlementConfigurationWrapper();
097    }
098
099    /**
100     * Constructor to create an evaluator the default service type.
101     *
102     * @param subject Subject who credential is used for performing the 
103     *        evaluation.
104     * @throws EntitlementException if any other abnormal condition occured.
105     */
106    public Evaluator(Subject subject)
107        throws EntitlementException {
108        adminSubject = subject;
109        policyMonitor = getPolicyMonitor();
110        configWrapper = new EntitlementConfigurationWrapper();
111    }
112    
113    /**
114     * Returns <code>true</code> if the subject is granted to an
115     * entitlement.
116     *
117     * @param realm Realm name.
118     * @param subject Subject who is under evaluation.
119     * @param e Entitlement object which describes the resource name and 
120     *          actions.
121     * @param envParameters Map of environment parameters.
122     * @return <code>true</code> if the subject is granted to an
123     *         entitlement.
124     * @throws EntitlementException if the result cannot be determined.
125     */
126    public boolean hasEntitlement(
127        String realm,
128        Subject subject, 
129        Entitlement e,
130        Map<String, Set<String>> envParameters
131    ) throws EntitlementException {
132
133        PrivilegeEvaluator evaluator = new PrivilegeEvaluator();
134        boolean result = evaluator.hasEntitlement(realm,
135            adminSubject, subject, applicationName, e, envParameters);
136
137        return result;
138    }
139
140    /**
141     * Returns a list of entitlements for a given subject, resource names
142     * and environment.
143     *
144     * @param realm Realm Name.
145     * @param subject Subject who is under evaluation.
146     * @param resourceNames Resource names.
147     * @param environment Environment parameters.
148     * @return a list of entitlements for a given subject, resource name
149     *         and environment.
150     * @throws EntitlementException if the result cannot be determined.
151     */
152    public List<Entitlement> evaluate(
153        String realm,
154        Subject subject,
155        Set<String> resourceNames,
156        Map<String, Set<String>> environment
157    ) throws EntitlementException {
158        if ((resourceNames == null) || resourceNames.isEmpty()) {
159            throw new EntitlementException(424);
160        }
161
162        List<Entitlement> results = new ArrayList<Entitlement>();
163
164        for (String res : resourceNames) {
165            List<Entitlement> r = evaluate(realm, subject, res, environment,
166                false);
167            if ((r != null) && !r.isEmpty()) {
168                results.addAll(r);
169            }
170        }
171        return results;
172    }
173
174    /**
175     * Returns a list of entitlements for a given subject, resource name
176     * and environment.
177     *
178     * @param realm
179     *         Realm Name.
180     * @param subject
181     *         Subject who is under evaluation.
182     * @param resourceName
183     *         Resource name.
184     * @param environment
185     *         Environment parameters.
186     * @param recursive
187     *         <code>true</code> to perform evaluation on sub resources
188     *         from the given resource name.
189     * @return a list of entitlements for a given subject, resource name
190     *         and environment.
191     * @throws EntitlementException
192     *         if the result cannot be determined.
193     */
194    public List<Entitlement> evaluate(
195            String realm,
196            Subject subject,
197            String resourceName,
198            Map<String, Set<String>> environment,
199            boolean recursive
200    ) throws EntitlementException {
201
202        long startTime = System.currentTimeMillis();
203
204        // Delegation to applications is currently not configurable, passing super admin (see AME-4959)
205        Application application = ApplicationManager
206                .getApplication(PolicyConstants.SUPER_ADMIN_SUBJECT, realm, applicationName);
207
208        if (application == null) {
209            // App retrieval error.
210            throw new EntitlementException(EntitlementException.APP_RETRIEVAL_ERROR, new String[] {realm});
211        }
212
213        // Normalise the incoming resource URL.
214        String normalisedResourceName = application.getResourceComparator().canonicalize(resourceName);
215
216        PrivilegeEvaluator evaluator = new PrivilegeEvaluator();
217        List<Entitlement> results = evaluator.evaluate(realm, adminSubject, subject,
218                applicationName, normalisedResourceName, resourceName, environment, recursive);
219
220        if (configWrapper.isMonitoringRunning()) {
221            policyMonitor.addEvaluation(System.currentTimeMillis() - startTime, realm, applicationName, resourceName,
222                    subject, recursive ? PolicyMonitoringType.SUBTREE : PolicyMonitoringType.SELF);
223        }
224
225        return results;
226    }
227
228    /**
229     * Returns application name.
230     * 
231     * @return application name.
232     */
233    public String getApplicationName() {
234        return applicationName;
235    }
236}
237