All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.fcrepo.server.security.xacml.util.ContextUtil Maven / Gradle / Ivy

There is a newer version: 3.8.1
Show newest version
/*
 * File: ContextUtil.java
 *
 * Copyright 2007 Macquarie E-Learning Centre Of Excellence
 *
 * Licensed 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
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * 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.fcrepo.server.security.xacml.util;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import org.fcrepo.common.Constants;
import org.fcrepo.server.security.xacml.MelcoeXacmlException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.sun.xacml.Indenter;
import com.sun.xacml.ParsingException;
import com.sun.xacml.attr.AnyURIAttribute;
import com.sun.xacml.attr.AttributeValue;
import com.sun.xacml.attr.StringAttribute;
import com.sun.xacml.ctx.Attribute;
import com.sun.xacml.ctx.RequestCtx;
import com.sun.xacml.ctx.ResponseCtx;
import com.sun.xacml.ctx.Result;
import com.sun.xacml.ctx.Subject;


/**
 * Utility class that provides various methods for creating/converting contexts.
 * This class can convert requests and responses from their string
 * representations to their object representations and vice versa as well as a
 * few utility methods for getting information from the contexts. It also
 * contains methods for constructing requests.
 *
 * @author [email protected]
 */

public class ContextUtil {

    private static final Logger logger =
            LoggerFactory.getLogger(ContextUtil.class);

    private static final URI XACML_RESOURCE_ID =
            Constants.XACML1_RESOURCE.ID.getURI();

    private final Map actionMap =
            new ConcurrentHashMap();

    private final Map actionValueMap =
            new ConcurrentHashMap();

    public ContextUtil() {
        logger.info("created");
    }

    public void setActionMap(Map actions) {
        for (String from: actions.keySet()){
            URI key;
            String to = actions.get(from);
            try {
                key = new URI(from);
                URI value = new URI(actions.get(from));
                actionMap.put(key, value);
            } catch (URISyntaxException e) {
                logger.warn("Mapping contained invalid URI: ["
                        + from + "] / [" + to + "]");
            }
        }
    }

    public void setActionValueMap(Map values) {
        actionValueMap.putAll(values);
    }

    /**
     * Sets up the Subject section of the request. Takes a list of Maps of
     * URI/AttributeValue pairs. Each list element represents one subject which
     * contains a map of URI/AttributeValues.
     *
     * @return a Set of Subject instances for inclusion in a Request
     */
    public Set setupSubjects(List>> subjs) {
        Set subjects = new HashSet();

        if (subjs == null || subjs.size() == 0) {
            subjects.add(new Subject(new HashSet()));
            return subjects;
        }

        // Go through each of the subjects
        for (Map> s : subjs) {
            Set attributes = new HashSet();

            // Extract and create the attributes for this subject and add them
            // to the set
            for (URI uri : s.keySet()) {
                List attributeValues = s.get(uri);
                for (AttributeValue attributeValue : attributeValues) {
                    attributes.add(new Attribute(uri,
                                                 null,
                                                 null,
                                                 attributeValue));
                }
            }

            // Create a new subject and add the attributes for this subject
            subjects.add(new Subject(attributes));
        }

        return subjects;
    }

    /**
     * Creates a Resource specifying the resource-id, a required attribute.
     *
     * @return a Set of Attributes for inclusion in a Request
     */
    public Set setupResources(Map res, RelationshipResolver relationshipResolver)
            throws MelcoeXacmlException {
        Set attributes = new HashSet();

        if (res == null || res.size() == 0) {
            return attributes;
        }

        try {
            String pid = null;
            AttributeValue pidAttr = res.get(XACML_RESOURCE_ID);
            if (pidAttr != null) {
                pid = pidAttr.encode();
                pid = relationshipResolver.buildRESTParentHierarchy(pid);

                String dsid = null;
                AttributeValue dsidAttr =
                        res.get(Constants.DATASTREAM.ID.getURI());
                if (dsidAttr != null) {
                    dsid = dsidAttr.encode();
                    if (!dsid.equals("")) {
                        pid += "/" + dsid;
                    }
                }

                res.put(XACML_RESOURCE_ID, new AnyURIAttribute(new URI(pid)));
            }
        } catch (Exception e) {
            logger.error("Error finding parents.", e);
            throw new MelcoeXacmlException("Error finding parents.", e);
        }

        for (URI uri : res.keySet()) {
            attributes.add(new Attribute(uri, null, null, res.get(uri)));
        }

        return attributes;
    }

    /**
     * Creates an Action specifying the action-id, an optional attribute.
     *
     * @return a Set of Attributes for inclusion in a Request
     */
    public Set setupAction(Map a) {
        Set actions = new HashSet();

        if (a == null || a.size() == 0) {
            return actions;
        }

        Map newActions =
                new HashMap();
        for (URI uri : a.keySet()) {
            URI newUri = null;
            AttributeValue newValue = null;

            if (actionMap != null && actionMap.size() > 0) {
                newUri = actionMap.get(uri);
            }

            if (actionValueMap != null && actionValueMap.size() > 0) {
                String tmpValue = actionValueMap.get(a.get(uri).encode());
                if (tmpValue != null) {
                    newValue = new StringAttribute(tmpValue);
                }
            }

            newUri = newUri == null ? uri : newUri;
            newValue = newValue == null ? a.get(uri) : newValue;
            newActions.put(newUri, newValue);
        }

        for (URI uri : newActions.keySet()) {
            actions.add(new Attribute(uri, null, null, newActions.get(uri)));
        }

        return actions;
    }

    /**
     * Creates the Environment attributes.
     *
     * @return a Set of Attributes for inclusion in a Request
     */
    public Set setupEnvironment(Map e) {
        Set environment = new HashSet();

        if (e == null || e.size() == 0) {
            return environment;
        }

        for (URI uri : e.keySet()) {
            environment.add(new Attribute(uri, null, null, e.get(uri)));
        }

        return environment;
    }

    /**
     * Constructs a RequestCtx object.
     *
     * @param subjects
     *        list of Subjects
     * @param actions
     *        list of Action attributes
     * @param resources
     *        list of resource Attributes
     * @param environment
     *        list of environment Attributes
     * @return the RequestCtx object
     * @throws MelcoeXacmlException
     */
    public RequestCtx buildRequest(List>> subjects,
                                   Map actions,
                                   Map resources,
                                   Map environment,
                                   RelationshipResolver relationshipResolver)
            throws MelcoeXacmlException {
        if (logger.isDebugEnabled()) {
            logger.debug("Building request!");
        }

        RequestCtx request = null;

        // Create the new Request.
        // Note that the Environment must be specified using a valid Set, even
        // if that Set is empty
        try {
            request =
                    new RequestCtx(setupSubjects(subjects),
                                   setupResources(resources, relationshipResolver),
                                   setupAction(actions),
                                   setupEnvironment(environment));
        } catch (Exception e) {
            logger.error("Error creating request.", e);
            throw new MelcoeXacmlException("Error creating request", e);
        }

        return request;
    }

    /**
     * Converts a string based response to a ResponseCtx obejct.
     *
     * @param response
     *        the string response
     * @return the ResponseCtx object
     * @throws MelcoeXacmlException
     */
    public ResponseCtx makeResponseCtx(String response)
            throws MelcoeXacmlException {
        ResponseCtx resCtx = null;
        try {
            // sunxacml 1.2 bug. ResponseCtx.getInstance looks for
            // ResourceId and creates ResourceID
            String newResponse =
                    response.replaceAll("ResourceID", "ResourceId");
            ByteArrayInputStream is =
                    new ByteArrayInputStream(newResponse.getBytes());
            resCtx = ResponseCtx.getInstance(is);
        } catch (ParsingException pe) {
            throw new MelcoeXacmlException("Error parsing response.", pe);
        }
        return resCtx;
    }

    /**
     * Converts a string based request to a RequestCtx obejct.
     *
     * @param request
     *        the string request
     * @return the RequestCtx object
     * @throws MelcoeXacmlException
     */
    public RequestCtx makeRequestCtx(String request)
            throws MelcoeXacmlException {
        RequestCtx reqCtx = null;
        try {
            ByteArrayInputStream is =
                    new ByteArrayInputStream(request.getBytes());
            reqCtx = RequestCtx.getInstance(is);
        } catch (ParsingException pe) {
            throw new MelcoeXacmlException("Error parsing response.", pe);
        }
        return reqCtx;
    }

    /**
     * Converts a RequestCtx object to its string representation.
     *
     * @param reqCtx
     *        the RequestCtx object
     * @return the String representation of the RequestCtx object
     */
    public String makeRequestCtx(RequestCtx reqCtx) {
        ByteArrayOutputStream request = new ByteArrayOutputStream();
        reqCtx.encode(request, new Indenter());
        return new String(request.toByteArray());
    }

    /**
     * Converst a ResponseCtx object to its string representation.
     *
     * @param resCtx
     *        the ResponseCtx object
     * @return the String representation of the ResponseCtx object
     */
    public String makeResponseCtx(ResponseCtx resCtx) {
        ByteArrayOutputStream response = new ByteArrayOutputStream();
        resCtx.encode(response, new Indenter());
        return new String(response.toByteArray());
    }

    /**
     * Returns a map of resource-id, result based on an XACML response.
     *
     * @param resCtx
     *        the XACML response
     * @return the Map of resource-id and result
     */
    public Map makeResultMap(ResponseCtx resCtx) {
        @SuppressWarnings("unchecked")
        Iterator i = resCtx.getResults().iterator();

        Map resultMap = new HashMap();

        while (i.hasNext()) {
            Result r = i.next();
            resultMap.put(r.getResource(), r);
        }

        return resultMap;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy