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-2016 ForgeRock AS.
028 */
029package com.sun.identity.entitlement;
030
031import static org.forgerock.openam.entitlement.PolicyConstants.SUPER_ADMIN_SUBJECT;
032import static org.forgerock.openam.entitlement.utils.EntitlementUtils.getApplicationService;
033import static org.forgerock.openam.utils.Time.*;
034
035import com.sun.identity.shared.Constants;
036import com.sun.identity.shared.configuration.SystemPropertiesManager;
037import java.util.ArrayList;
038import java.util.List;
039import java.util.Map;
040import java.util.Set;
041import javax.security.auth.Subject;
042import org.forgerock.guice.core.InjectorHolder;
043import org.forgerock.openam.entitlement.monitoring.EntitlementConfigurationWrapper;
044import org.forgerock.openam.entitlement.monitoring.PolicyMonitor;
045import org.forgerock.openam.entitlement.monitoring.PolicyMonitoringType;
046
047/**
048 * The class evaluates entitlement request and provides decisions.
049 * @supported.api
050 */
051public class Evaluator {
052
053    private Subject adminSubject;
054    private String applicationName =
055        ApplicationTypeManager.URL_APPLICATION_TYPE_NAME;
056
057    public static final int DEFAULT_POLICY_EVAL_THREAD = 10;
058
059    private final PolicyMonitor policyMonitor;
060    private final EntitlementConfigurationWrapper configWrapper;
061
062    /**
063     * Constructor to create an evaluator of default service type.
064     *
065     * @throws EntitlementException if any other abnormal condition occ.
066     */
067    private Evaluator()
068        throws EntitlementException {
069        policyMonitor = getPolicyMonitor();
070        configWrapper = new EntitlementConfigurationWrapper();
071
072    }
073
074    private PolicyMonitor getPolicyMonitor() {
075        //used as no direct access to SystemProperties
076        boolean serverMode = Boolean.parseBoolean(SystemPropertiesManager.get(Constants.SERVER_MODE));
077
078        if (serverMode) {
079            return InjectorHolder.getInstance(PolicyMonitor.class);
080        } else {
081            return null;
082        }
083    }
084
085    /**
086     * Constructor to create an evaluator given the service type.
087     *
088     * @param subject Subject who credential is used for performing the 
089     *        evaluation.
090     * @param applicationName the name of the aplication for
091     *        which this evaluator can be used.
092     * @throws EntitlementException if any other abnormal condition occured.
093     */
094    public Evaluator(Subject subject, String applicationName)
095        throws EntitlementException {
096        adminSubject = subject;
097        this.applicationName = applicationName;
098        policyMonitor = getPolicyMonitor();
099        configWrapper = new EntitlementConfigurationWrapper();
100    }
101
102    /**
103     * Constructor to create an evaluator the default service type.
104     *
105     * @param subject Subject who credential is used for performing the 
106     *        evaluation.
107     * @throws EntitlementException if any other abnormal condition occured.
108     */
109    public Evaluator(Subject subject)
110        throws EntitlementException {
111        adminSubject = subject;
112        policyMonitor = getPolicyMonitor();
113        configWrapper = new EntitlementConfigurationWrapper();
114    }
115    
116    /**
117     * Returns <code>true</code> if the subject is granted to an
118     * entitlement.
119     *
120     * @param realm Realm name.
121     * @param subject Subject who is under evaluation.
122     * @param e Entitlement object which describes the resource name and 
123     *          actions.
124     * @param envParameters Map of environment parameters.
125     * @return <code>true</code> if the subject is granted to an
126     *         entitlement.
127     * @throws EntitlementException if the result cannot be determined.
128     */
129    public boolean hasEntitlement(
130        String realm,
131        Subject subject, 
132        Entitlement e,
133        Map<String, Set<String>> envParameters
134    ) throws EntitlementException {
135
136        PrivilegeEvaluator evaluator = new PrivilegeEvaluator();
137        boolean result = evaluator.hasEntitlement(realm,
138            adminSubject, subject, applicationName, e, envParameters);
139
140        return result;
141    }
142
143    /**
144     * Returns a list of entitlements for a given subject, resource names
145     * and environment.
146     *
147     * @param realm Realm Name.
148     * @param subject Subject who is under evaluation.
149     * @param resourceNames Resource names.
150     * @param environment Environment parameters.
151     * @return a list of entitlements for a given subject, resource name
152     *         and environment.
153     * @throws EntitlementException if the result cannot be determined.
154     */
155    public List<Entitlement> evaluate(
156        String realm,
157        Subject subject,
158        Set<String> resourceNames,
159        Map<String, Set<String>> environment
160    ) throws EntitlementException {
161        if ((resourceNames == null) || resourceNames.isEmpty()) {
162            throw new EntitlementException(424);
163        }
164
165        List<Entitlement> results = new ArrayList<Entitlement>();
166
167        for (String res : resourceNames) {
168            List<Entitlement> r = evaluate(realm, subject, res, environment,
169                false);
170            if ((r != null) && !r.isEmpty()) {
171                results.addAll(r);
172            }
173        }
174        return results;
175    }
176
177    /**
178     * Returns a list of entitlements for a given subject, resource name
179     * and environment.
180     *
181     * @param realm
182     *         Realm Name.
183     * @param subject
184     *         Subject who is under evaluation.
185     * @param resourceName
186     *         Resource name.
187     * @param environment
188     *         Environment parameters.
189     * @param recursive
190     *         <code>true</code> to perform evaluation on sub resources
191     *         from the given resource name.
192     * @return a list of entitlements for a given subject, resource name
193     *         and environment.
194     * @throws EntitlementException
195     *         if the result cannot be determined.
196     */
197    public List<Entitlement> evaluate(
198            String realm,
199            Subject subject,
200            String resourceName,
201            Map<String, Set<String>> environment,
202            boolean recursive
203    ) throws EntitlementException {
204
205        long startTime = currentTimeMillis();
206
207        // Delegation to applications is currently not configurable, passing super admin (see AME-4959)
208        Application application = getApplicationService(SUPER_ADMIN_SUBJECT, realm).getApplication(applicationName);
209
210        if (application == null) {
211            // App retrieval error.
212            throw new EntitlementException(EntitlementException.APP_RETRIEVAL_ERROR, new String[] {realm});
213        }
214
215        // Normalise the incoming resource URL.
216        String normalisedResourceName = application.getResourceComparator().canonicalize(resourceName);
217
218        PrivilegeEvaluator evaluator = new PrivilegeEvaluator();
219        List<Entitlement> results = evaluator.evaluate(realm, adminSubject, subject,
220                applicationName, normalisedResourceName, resourceName, environment, recursive);
221
222        if (configWrapper.isMonitoringRunning()) {
223            policyMonitor.addEvaluation(currentTimeMillis() - startTime, realm, applicationName, resourceName,
224                    subject, recursive ? PolicyMonitoringType.SUBTREE : PolicyMonitoringType.SELF);
225        }
226
227        return results;
228    }
229
230    /**
231     * Returns application name.
232     * 
233     * @return application name.
234     */
235    public String getApplicationName() {
236        return applicationName;
237    }
238}
239