edu.byu.wso2.apim.extensions.CheckActorPermissions.java Source code

Java tutorial

Introduction

Here is the source code for edu.byu.wso2.apim.extensions.CheckActorPermissions.java

Source

/*
 *    Copyright 2016 Brigham Young University
 *
 *    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 edu.byu.wso2.apim.extensions;

import edu.byu.wso2.apim.extensions.helpers.BYUEntity;
import edu.byu.wso2.apim.extensions.helpers.BYUEntityHelper;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.synapse.ManagedLifecycle;
import org.apache.synapse.MessageContext;
import org.apache.synapse.SynapseLog;
import org.apache.synapse.core.SynapseEnvironment;
import org.apache.synapse.mediators.AbstractMediator;
import org.springframework.util.AntPathMatcher;

import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.servlet.http.HttpServletRequest;
import javax.sql.DataSource;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;

/**
 * Steps to determine if a client can use an actor:
 * 1) get application id from properties - key value 'applicationid'
 * 2) get keytype from properties - key value 'keytype'
 * 3) get usertype from properties - key value 'usertype' - is set to APPLICATION for client credentials grant
 * 4) query client_id from API Manager database - use property WSO2AMDsName to get the datasource name
 * 5) call GRO and IAM with client_id and url of the call - REST_FULL_REQUEST_PATH
 * 6) set ResultPropertyName property with result so sequence can decide what to do.
 *
 */

public class CheckActorPermissions extends AbstractMediator implements ManagedLifecycle {

    private static Log log = LogFactory.getLog(CheckActorPermissions.class);
    private static String APPLICATION_ID_KEY = "applicationid";
    private static String KEYTYPE_KEY = "keytype";
    private static String USERTYPE_KEY = "usertype";
    private static String CLIENT_ID_KEY = "client_id";
    private static String FULL_URL_KEY = "REST_FULL_REQUEST_PATH";
    private static String CONTEXT_URL_KEY = "REST_API_CONTEXT";

    private SynapseLog synLog = null;

    private final AntPathMatcher pathMatcher = new AntPathMatcher();

    private DataSource proDs = null;
    private String PRODsName = null;
    private String resultPropertyName = null;

    public void init(SynapseEnvironment synapseEnvironment) {
        if (log.isInfoEnabled()) {
            log.info("Initializing CheckActorPermissions Mediator");
        }
        if (log.isDebugEnabled())
            log.debug("CheckActorPermissions: looking up Person/GRO datasource" + PRODsName);
        try {
            this.proDs = (DataSource) new InitialContext().lookup(PRODsName);
        } catch (NamingException e) {
            e.printStackTrace();
        }
        if (log.isDebugEnabled())
            log.debug("CheckActorPermissions: acquired datasource");

    }

    public boolean mediate(MessageContext synapseContext) {
        synLog = getLog(synapseContext);

        if (synLog.isTraceOrDebugEnabled()) {
            synLog.traceOrDebug("Start : CheckActorPermissions mediator");
            if (synLog.isTraceTraceEnabled()) {
                synLog.traceTrace("Message : " + synapseContext.getEnvelope());
            }
        }

        String application_id = (String) synapseContext.getProperty(APPLICATION_ID_KEY);
        String keytype = (String) synapseContext.getProperty(KEYTYPE_KEY);
        String target_URL = (String) synapseContext.getProperty(FULL_URL_KEY);
        String client_id = (String) synapseContext.getProperty(CLIENT_ID_KEY);

        if (client_id == null) {
            synLog.error(
                    "Property to use for client_id not set - make sure JWTDecoder class mediator is prior to this one in the sequence and JWT contains BYU custom claims");
            return false;
        }

        if (synLog.isTraceOrDebugEnabled())
            synLog.traceOrDebug("CheckActorPermissions: lookup starting for client_id:" + client_id);

        if (client_id == null) {
            synLog.error("Could not get a client_id for the application_id - stopping sequence");
            return false;
        }

        boolean canUseActor = checkActorPermissionsInGRO(synapseContext, client_id, target_URL);

        /*need to set the return property to the results of the test */
        if (getResultPropertyName() == null) {
            synLog.error("ResultPropertyName not set - stopping sequence");
            return false;
        }
        synapseContext.setProperty(getResultPropertyName(), canUseActor);

        if (log.isDebugEnabled())
            synLog.traceOrDebug("CheckActorPermissions: ending");
        return true;
    }

    public boolean checkActorPermissionsInGRO(MessageContext synapseContext, String client_id, String target_URL) {
        boolean canUseActor = false;

        if (synLog.isTraceOrDebugEnabled()) {
            synLog.traceOrDebug("Start : CheckActorPermissionsInGRO");
        }

        /* step 1 - check for a service with a matching pattern. This must be done in code - can't match patterns in the db
           if service doesn't resolve - can't use actors.
         */

        Service service = resolve(target_URL);
        if (service == null) {
            if (synLog.isTraceOrDebugEnabled()) {
                synLog.traceOrDebug("no service mapping found - can't use actors");
            }
            return false;
        }

        /* step 2 - get person_id associated with the client_id. If there isn't one - can't use actors.
         */
        BYUEntity byuEntity = new BYUEntityHelper(getPRODsName()).getBYUEntityFromConsumerKey(client_id);

        if (byuEntity == null) {
            if (synLog.isTraceOrDebugEnabled()) {
                synLog.traceOrDebug("no person_id associated with client_id " + client_id + " - can't use actors");
            }
            return false;
        }

        /* step 3 - check to see if the person_id is allowed to access this web service with an actor
        if count comes back as 0 - can't use actors
         */

        Connection con = null;
        PreparedStatement statement = null;
        ResultSet resultSet = null;
        String query = "select count(*) from gro.person_group g, gro.group_definition d, gro.access_policy p \n"
                + "where g.group_id = d.group_api \n" + "and d.group_definition_id = p.group_definition_id \n"
                + "and p.WEB_SERVICE_ID = ? \n" + "and p.policy_type = 'Provider' \n" + "and g.person_id = ?";

        if (synLog.isTraceOrDebugEnabled())
            synLog.traceOrDebug("CheckActorPermissionsInGRO: lookup starting for person_id "
                    + byuEntity.getPersonId() + " and web service " + service.toString());

        try {
            con = proDs.getConnection();
            if (synLog.isTraceOrDebugEnabled())
                synLog.traceOrDebug("connection acquired. creating statement and executing query");
            statement = con.prepareStatement(query);
            statement.setLong(1, service.getWebServiceId());
            statement.setString(2, byuEntity.getPersonId());
            resultSet = statement.executeQuery();
            if (resultSet.next()) {
                if (resultSet.getInt(1) > 0)
                    if (synLog.isTraceOrDebugEnabled())
                        synLog.traceOrDebug("client_id authorization succeeded");
                canUseActor = true;
            } else {
                if (synLog.isTraceOrDebugEnabled())
                    synLog.traceOrDebug("client_id authorization failed");
                canUseActor = false;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            if (resultSet != null) {
                try {
                    resultSet.close();
                } catch (SQLException e) {
                    /* ignored */ }
            }
            if (statement != null) {
                try {
                    statement.close();
                } catch (SQLException e) {
                    /* ignored */ }
            }
            if (con != null) {
                try {
                    con.close();
                } catch (SQLException e) {
                    /* ignored */ }
            }
        }
        if (synLog.isTraceOrDebugEnabled())
            synLog.traceOrDebug("CheckActorPermissionsInGRO: ending with value - " + String.valueOf(canUseActor));
        return canUseActor;
    }

    public Service resolve(String requestUrl) {
        final List<Service> services = getServices();
        for (Service serviceDefinition : services) {
            if (pathMatcher.match(serviceDefinition.getUrlPattern(), requestUrl)) {
                return serviceDefinition;
            }
        }
        return null;
    }

    private List<Service> getServices() {
        if (synLog.isTraceOrDebugEnabled()) {
            synLog.traceOrDebug("Start : getServices");
        }
        List<Service> serviceList = new ArrayList<Service>();
        Connection con = null;
        PreparedStatement statement = null;
        ResultSet resultSet = null;
        String query = "select web_service_id, url_pattern from common.web_service order by url_pattern";

        if (synLog.isTraceOrDebugEnabled())
            synLog.traceOrDebug("getServices: retrieving web services with url patterns from common.web_service");

        try {
            con = proDs.getConnection();
            if (synLog.isTraceOrDebugEnabled())
                synLog.traceOrDebug("connection acquired. creating statement and executing query");
            statement = con.prepareStatement(query);
            resultSet = statement.executeQuery();
            while (resultSet.next()) {
                serviceList
                        .add(new Service(resultSet.getLong("web_service_id"), resultSet.getString("url_pattern")));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            if (resultSet != null) {
                try {
                    resultSet.close();
                } catch (SQLException e) {
                    /* ignored */ }
            }
            if (statement != null) {
                try {
                    statement.close();
                } catch (SQLException e) {
                    /* ignored */ }
            }
            if (con != null) {
                try {
                    con.close();
                } catch (SQLException e) {
                    /* ignored */ }
            }
        }

        if (synLog.isTraceOrDebugEnabled()) {
            synLog.traceOrDebug("getService: ending");
        }
        return serviceList;
    }

    public void destroy() {
        if (log.isInfoEnabled()) {
            log.info("Destroying CheckActorPermissions Mediator");
        }
    }

    /* DataSource name to use for lookup */
    public String getPRODsName() {
        return PRODsName;
    }

    public void setPRODsName(String PRODsName) {
        this.PRODsName = PRODsName;
    }

    public String getResultPropertyName() {
        return resultPropertyName;
    }

    public void setResultPropertyName(String resultPropertyName) {
        this.resultPropertyName = resultPropertyName;
    }
}