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

org.bitbucket.fermenter.stout.authz.StoutAttributeProvider Maven / Gradle / Ivy

Go to download

Provides base functionality and patterns for utilizing Authzforce to provide core authorization needs.

There is a newer version: 2.7.0
Show newest version
package org.bitbucket.fermenter.stout.authz;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.aeonbits.owner.KrauseningConfigFactory;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.bitbucket.fermenter.stout.authz.attribute._2.StoutAttributeExtension;
import org.bitbucket.fermenter.stout.authz.config.AuthorizationConfig;
import org.bitbucket.fermenter.stout.authz.json.StoutAttribute;
import org.ow2.authzforce.core.pdp.api.AttributeFqn;
import org.ow2.authzforce.core.pdp.api.AttributeProvider;
import org.ow2.authzforce.core.pdp.api.BaseNamedAttributeProvider;
import org.ow2.authzforce.core.pdp.api.CloseableNamedAttributeProvider;
import org.ow2.authzforce.core.pdp.api.EnvironmentProperties;
import org.ow2.authzforce.core.pdp.api.EvaluationContext;
import org.ow2.authzforce.core.pdp.api.IndeterminateEvaluationException;
import org.ow2.authzforce.core.pdp.api.value.AttributeBag;
import org.ow2.authzforce.core.pdp.api.value.AttributeValue;
import org.ow2.authzforce.core.pdp.api.value.AttributeValueFactoryRegistry;
import org.ow2.authzforce.core.pdp.api.value.Bags;
import org.ow2.authzforce.core.pdp.api.value.Datatype;
import org.ow2.authzforce.core.pdp.api.value.SimpleValue;
import org.ow2.authzforce.xacml.identifiers.XacmlAttributeId;
import org.ow2.authzforce.xacml.identifiers.XacmlStatusCode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;

import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeDesignatorType;

/**
 * Provides an Authzforce attribute provider that allows relatively easy configuration of various attributes for use in
 * the policy decision point.
 */
public class StoutAttributeProvider extends BaseNamedAttributeProvider {

    private static final String XML_SCHEMA_DATE = "http://www.w3.org/2001/XMLSchema#date";

    private static final String XML_SCHEMA_DOUBLE = "http://www.w3.org/2001/XMLSchema#double";

    private static final String XML_SCHEMA_ANY_URI = "http://www.w3.org/2001/XMLSchema#anyURI";

    private static final String XML_SCHEMA_BOOLEAN = "http://www.w3.org/2001/XMLSchema#boolean";

    private static final String XML_SCHEMA_STRING = "http://www.w3.org/2001/XMLSchema#string";

    private static final String XML_SCHEMA_INTEGER = "http://www.w3.org/2001/XMLSchema#integer";

    private static final TypeReference> attributeListTypeReference = new TypeReference>() {
    };

    private static final Logger logger = LoggerFactory.getLogger(StoutAttributeProvider.class);
    protected AuthorizationConfig config = KrauseningConfigFactory.create(AuthorizationConfig.class);
    protected Map supportedDesignatorTypes = new HashMap<>();
    protected Map, StoutAttributePoint> pointClassToInstanceMap = new HashMap<>();
    protected Map idToAttributePointMap = new HashMap<>();

    private StoutAttributeProvider(StoutAttributeExtension conf) {
        super(conf.getId());

        loadAttributeConfiguration();

    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void close() throws IOException {
        // nothing to close
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Set getProvidedAttributes() {
        return Collections.unmodifiableSet(new HashSet<>(supportedDesignatorTypes.values()));
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public  AttributeBag get(final AttributeFqn attributeGUID,
            final Datatype attributeDatatype, final EvaluationContext context)
            throws IndeterminateEvaluationException {
        String id = attributeGUID.getId();
        String subject = findSubjectInEnvironmentContext(context);

        // lookup the correct attribute point to use:
        AttributeBag attrVals = null;
        Collection attributeCollection = new ArrayList<>();
        StoutAttributePoint attributePoint = idToAttributePointMap.get(id);
        Collection> retrievedValues = attributePoint
                .getValueForAttribute(id, subject);
        if (retrievedValues != null) {
            for (org.bitbucket.fermenter.stout.authz.AttributeValue retrievedValue : retrievedValues) {
                SimpleValue simpleValue = convertRetrievedValueToXacmlFormat(attributeDatatype, id, subject,
                        retrievedValue);

                if (simpleValue != null) {
                    attributeCollection.add((AV) simpleValue);
                }
            }
        }

        if (attrVals == null) {
            attrVals = Bags.newAttributeBag(attributeDatatype, attributeCollection);
            if (logger.isDebugEnabled()) {
                logger.debug("Retrieved attribute '{}' for subject '{}' with the values '{}'", id, subject,
                        attributeCollection.toString());

            }
        }

        if (attrVals == null || attrVals.getElementDatatype().equals(attributeDatatype)) {
            return (AttributeBag) attrVals;
        }

        throw new IndeterminateEvaluationException("Requested datatype (" + attributeDatatype + ") != provided by "
                + this + " (" + attrVals.getElementDatatype() + ")", XacmlStatusCode.MISSING_ATTRIBUTE.value());

    }

    protected  SimpleValue convertRetrievedValueToXacmlFormat(
            Datatype attributeDatatype, String id, String subject,
            org.bitbucket.fermenter.stout.authz.AttributeValue retrievedValue) {
        SimpleValue simpleValue = null;
        if (retrievedValue != null) {
            switch (attributeDatatype.toString()) {
            case XML_SCHEMA_INTEGER:
                simpleValue = retrievedValue.getAsIntegerValue();
                break;
            case XML_SCHEMA_STRING:
                simpleValue = retrievedValue.getAsStringValue();
                break;
            case XML_SCHEMA_BOOLEAN:
                simpleValue = retrievedValue.getAsBooleanValue();
                break;
            case XML_SCHEMA_ANY_URI:
                simpleValue = retrievedValue.getAsAnyUriValue();
                break;
            case XML_SCHEMA_DOUBLE:
                simpleValue = retrievedValue.getAsDoubleValue();
                break;
            case XML_SCHEMA_DATE:
                simpleValue = retrievedValue.getAsDateValue();
                break;
            default:
                simpleValue = retrievedValue.getAsStringValue();
                logger.warn("No type of '{}' was found for attribute '{}', converting to string!", attributeDatatype,
                        id);
            }
        }

        return simpleValue;
    }

    protected String findSubjectInEnvironmentContext(final EvaluationContext context) {
        String subject = null;
        Iterator>> contextAttributeIterator = context.getNamedAttributes();
        while (contextAttributeIterator.hasNext()) {
            Entry> contextAttribute = contextAttributeIterator.next();
            AttributeFqn attributeFullyQualifiedName = contextAttribute.getKey();
            if (XacmlAttributeId.XACML_1_0_SUBJECT_ID.value().equals(attributeFullyQualifiedName.getId())) {
                subject = contextAttribute.getValue().getSingleElement().toString();
                break;
            }

        }
        return subject;
    }

    /**
     * {@link StoutAttributeExtension} factory
     * 
     */
    public static class Factory extends CloseableNamedAttributeProvider.FactoryBuilder {

        @Override
        public Class getJaxbClass() {
            return StoutAttributeExtension.class;
        }

        @Override
        public DependencyAwareFactory getInstance(StoutAttributeExtension conf, EnvironmentProperties envProperties) {
            return new DependencyAwareFactory() {

                @Override
                public Set getDependencies() {
                    // no dependency
                    return null;
                }

                @Override
                public CloseableNamedAttributeProvider getInstance(AttributeValueFactoryRegistry attrDatatypeFactory,
                        AttributeProvider depAttrProvider) {
                    return new StoutAttributeProvider(conf);
                }
            };
        }

    }

    protected void loadAttributeConfiguration() {
        String attributeLocation = config.getAttributeDefinitionLocation();
        ObjectMapper mapper = new ObjectMapper();
        File root = new File(attributeLocation);
        if (root.exists()) {
            String[] extensions = { "json" };
            Collection files = FileUtils.listFiles(root, extensions, true);
            if (files.isEmpty()) {

                logger.warn(
                        "Your PDP is configured to use custom attributes, but the location that defines "
                                + "these attributes does not contain any attribute definitions! - {}",
                        root.getAbsolutePath());

            }

            for (File attributeDefintionFile : files) {
                List attributes = null;
                try {
                    attributes = mapper.readValue(attributeDefintionFile, attributeListTypeReference);
                    for (StoutAttribute attribute : attributes) {
                        addAttributeDefinition(attribute);

                    }

                } catch (IOException e) {
                    logger.error("Problem loading attributes in file {}!", attributeDefintionFile.getAbsolutePath(), e);
                    attributes = Collections.emptyList();
                }
                logger.info("Found {} attribute definitions in file {}", attributes.size(),
                        attributeDefintionFile.getAbsolutePath());
            }

        } else {
            logger.warn("\n");
            logger.warn("*********************************************************************************");
            logger.warn("Your PDP is configured to use custom attributes, but the location that defines these "
                    + "attributes does not exist! - {}", root.getAbsolutePath());
            logger.warn("Update the your authorization.properties via Krausening to point to a valid location "
                    + "for attribute json files!");
            logger.warn("*********************************************************************************");
            logger.warn("\n");

        }
    }

    protected void addAttributeDefinition(StoutAttribute attribute) {
        String id = attribute.getId();

        AttributeDesignatorType designatorType = StoutAttributeUtils.translateAttributeToXacmlFormat(attribute);
        AttributeDesignatorType existingDesignatorType = supportedDesignatorTypes.put(id, designatorType);

        StoutAttributePoint attributePoint = findAttributePointImplementation(attribute);
        idToAttributePointMap.put(id, attributePoint);

        logger.info("Translated Stout attribute definition '{}' into the fully qualified \n\t{}", id, designatorType);

        if (existingDesignatorType != null) {
            logger.warn("Multiple attributes named '{}' exist!  The last one in read will be used {}", id,
                    designatorType);
        }
    }

    protected StoutAttributePoint findAttributePointImplementation(StoutAttribute attribute) {
        StoutAttributePoint attributePoint = null;

        String attributePointClassName = null;
        try {
            attributePointClassName = attribute.getAttributePointClass();
            if (StringUtils.isBlank(attributePointClassName)) {
                logger.error("No attribute point specified for attribute '{}'!", attribute.getId());

            } else {
                Class attributePointClass = (Class) Class
                        .forName(attributePointClassName);

                // reuse an existing instance if we have already encountered this class:
                attributePoint = pointClassToInstanceMap.get(attributePointClass);

                if (attributePoint == null) {
                    // add a new reusable instance if we have not already encountered this class:
                    attributePoint = attributePointClass.newInstance();
                    pointClassToInstanceMap.put(attributePointClass, attributePoint);
                    logger.debug("Instantiated AttributePoint '{}'", attributePointClass.getName());
                }

            }

        } catch (ClassNotFoundException e) {
            logger.error("Could not find attribute point '{}' in classpath!", attributePointClassName);

        } catch (InstantiationException | IllegalAccessException e) {
            logger.error("Could not instantiate attribute point '" + attributePointClassName + "'!", e);

        }

        return attributePoint;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy