001package com.identityworksllc.iiq.common;
002
003import com.identityworksllc.iiq.common.access.AccessCheck;
004import com.identityworksllc.iiq.common.access.AccessCheckInput;
005import com.identityworksllc.iiq.common.auth.DummyPluginResource;
006import org.apache.commons.logging.Log;
007import org.apache.commons.logging.LogFactory;
008import sailpoint.api.SailPointContext;
009import sailpoint.object.*;
010import sailpoint.rest.plugin.BasePluginResource;
011import sailpoint.tools.GeneralException;
012import sailpoint.web.UserContext;
013
014import java.util.Map;
015
016/**
017 * Implements the "Common Security" protocol that was originally part of the
018 * UPE plugin. This allows more detailed authorization to check access to
019 * various objects within IIQ.
020 *
021 * There are two users involved in thing access: an subject Identity and a target
022 * Identity. The subject is the one doing the thing while the target is the one
023 * the thing is being done to. Some actions may be 'self' actions, where both the
024 * subject and the target are the same. Other actions don't have a 'target' concept
025 * and are treated as 'self' actions.
026 *
027 * @see AccessCheck
028 */
029@SuppressWarnings("unused")
030public final class ThingAccessUtils {
031
032    /**
033     * The logger
034     */
035    private static final Log log = LogFactory.getLog(ThingAccessUtils.class);
036
037    /**
038     * Returns true if the logged in user can access the item based on the Common Security configuration parameters.
039     *
040     * @param pluginContext The plugin context, which provides user details
041     * @param configuration The configuration for the field or button or other object
042     * @return True if the user has access to the thing based on the configuration
043     * @throws GeneralException if any check failures occur (this should be interpreted as "no access")
044     */
045    public static boolean checkThingAccess(UserContext pluginContext, Map<String, Object> configuration) throws GeneralException {
046        return checkThingAccess(pluginContext, null, AccessCheck.ANONYMOUS_THING, configuration);
047    }
048
049    /**
050     * Returns true if the logged in user can access the item based on the Common Security configuration parameters.
051     *
052     * @param pluginContext The plugin context, which provides user details
053     * @param configuration The configuration for the field or button or other object
054     * @return True if the user has access to the thing based on the configuration
055     * @throws GeneralException if any check failures occur (this should be interpreted as "no access")
056     */
057    public static boolean checkThingAccess(BasePluginResource pluginContext, Map<String, Object> configuration) throws GeneralException {
058        return checkThingAccess(pluginContext, null, AccessCheck.ANONYMOUS_THING, configuration);
059    }
060
061    /**
062     * Returns true if the logged in user can access the item based on the CommonSecurityConfig object
063     *
064     * @param pluginContext The plugin context, which provides user details
065     * @param config the CommonSecurityConfig object
066     * @return True if the user has access to the thing based on the configuration
067     * @throws GeneralException if any check failures occur (this should be interpreted as "no access")
068     */
069    public static boolean checkThingAccess(UserContext pluginContext, CommonSecurityConfig config) throws GeneralException {
070        return checkThingAccess(pluginContext, null, AccessCheck.ANONYMOUS_THING, config);
071    }
072
073    /**
074     * Returns true if the logged in user can access the item based on the CommonSecurityConfig object
075     *
076     * @param pluginContext The plugin context, which provides user details
077     * @param config the CommonSecurityConfig object
078     * @return True if the user has access to the thing based on the configuration
079     * @throws GeneralException if any check failures occur (this should be interpreted as "no access")
080     */
081    public static boolean checkThingAccess(BasePluginResource pluginContext, CommonSecurityConfig config) throws GeneralException {
082        return checkThingAccess(pluginContext, null, AccessCheck.ANONYMOUS_THING, config);
083    }
084
085    /**
086     * Returns true if the logged in user can access the item based on the common configuration parameters.
087     *
088     * @param pluginContext The login context, which provides user details
089     * @param targetIdentity The target identity for the action (as opposed to the actor)
090     * @param configuration The configuration for the field or button or other object
091     * @return True if the user has access to the thing based on the configuration
092     * @throws GeneralException if any check failures occur (this should be interpreted as "no access")
093     */
094    public static boolean checkThingAccess(UserContext pluginContext, Identity targetIdentity, Map<String, Object> configuration) throws GeneralException {
095        return checkThingAccess(pluginContext, targetIdentity, AccessCheck.ANONYMOUS_THING, configuration);
096    }
097
098    /**
099     * Returns true if the logged in user can access the item based on the common configuration parameters.
100     *
101     * @param pluginContext The plugin context, which provides user details
102     * @param targetIdentity The target identity for the action (as opposed to the actor)
103     * @param configuration The configuration for the field or button or other object
104     * @return True if the user has access to the thing based on the configuration
105     * @throws GeneralException if any check failures occur (this should be interpreted as "no access")
106     */
107    public static boolean checkThingAccess(BasePluginResource pluginContext, Identity targetIdentity, Map<String, Object> configuration) throws GeneralException {
108        return checkThingAccess(pluginContext, targetIdentity, AccessCheck.ANONYMOUS_THING, configuration);
109    }
110
111    /**
112     * Returns true if the logged in user can access the item based on the common configuration parameters.
113     *
114     * @param pluginContext The plugin context, which provides user details
115     * @param targetIdentity The target identity for the action (as opposed to the actor)
116     * @param configuration The configuration for the field or button or other object
117     * @return True if the user has access to the thing based on the configuration
118     * @throws GeneralException if any check failures occur (this should be interpreted as "no access")
119     */
120    public static boolean checkThingAccess(BasePluginResource pluginContext, Identity targetIdentity, String thingName, Map<String, Object> configuration) throws GeneralException {
121        return checkThingAccess((UserContext) pluginContext, targetIdentity, AccessCheck.ANONYMOUS_THING, configuration);
122    }
123
124    /**
125     * Returns true if the logged in user can access the item based on the common configuration parameters.
126     *
127     * @param pluginContext A plugin REST API resource (or fake equivalent) used to get some details and settings. This must not be null.
128     * @param targetIdentity The target identity
129     * @param thingName The thing being checked
130     * @param configuration The configuration for the field or button or other object
131     * @return True if the user has access to the thing based on the configuration
132     * @throws GeneralException if any check failures occur (this should be interpreted as "no access")
133     */
134    public static boolean checkThingAccess(UserContext pluginContext, Identity targetIdentity, String thingName, Map<String, Object> configuration) throws GeneralException {
135        Identity currentUser = pluginContext.getLoggedInUser();
136        Identity target = targetIdentity;
137        if (target == null) {
138            target = currentUser;
139        }
140        if (configuration == null || configuration.isEmpty()) {
141            Configuration systemConfig = Configuration.getSystemConfig();
142            boolean defaultDeny = systemConfig.getBoolean("IIQCommon.ThingAccessUtils.denyOnEmpty", false);
143            if (defaultDeny) {
144                log.debug("Configuration for " + thingName + " is empty; assuming that access is NOT allowed");
145                return false;
146            } else {
147                log.debug("Configuration for " + thingName + " is empty; assuming that access is allowed");
148                return true;
149            }
150        }
151        CommonSecurityConfig config = CommonSecurityConfig.decode(configuration);
152        return checkThingAccess(pluginContext, target, thingName, config);
153    }
154
155    /**
156     * Returns true if the logged in user can access the item based on the common configuration parameters.
157     *
158     * Results for the same CommonSecurityConfig, source, and target user will be cached for up to one minute
159     * unless the CommonSecurityConfig object has noCache set to true.
160     *
161     * @param pluginContext A plugin REST API resource (or fake equivalent) used to get some details and settings. This must not be null.
162     * @param target The target identity
163     * @param thingName The thing being checked, entirely for logging purposes
164     * @param config The configuration specifying security rights
165     * @return True if the user has access to the thing based on the configuration
166     * @throws GeneralException if any check failures occur (this should be interpreted as "no access")
167     */
168    public static boolean checkThingAccess(UserContext pluginContext, Identity target, String thingName, CommonSecurityConfig config) throws GeneralException {
169        AccessCheckInput input = new AccessCheckInput(pluginContext, target, thingName, config);
170
171        return AccessCheck.accessCheck(input).isAllowed();
172    }
173
174    /**
175     * An optional clear-cache method that can be used by plugin code
176     */
177    public static void clearCachedResults() {
178        AccessCheck.clearCachedResults();
179    }
180
181    /**
182     * Creates a fake plugin context for use with {@link ThingAccessUtils#checkThingAccess(UserContext, Identity, String, Map)} outside of a plugin. This constructs a new instance of a dummy BasePluginResource web service endpoint class.
183     * @param context The SailPointContext to return from {@link BasePluginResource#getContext()}
184     * @param loggedInUser The Identity to return from various getLoggedIn... methods
185     * @param pluginName The name of the plugin to include in the fake plugin context
186     * @return The fake plugin resource
187     */
188    public static BasePluginResource createFakePluginContext(final SailPointContext context, final Identity loggedInUser, String pluginName) {
189        return new DummyPluginResource(context, loggedInUser, pluginName);
190    }
191
192}