Package org.globus.workspace.service.binding.authorization

Source Code of org.globus.workspace.service.binding.authorization.DefaultAuthorize

/*
* Copyright 1999-2008 University of Chicago
*
* 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.globus.workspace.service.binding.authorization;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.globus.workspace.accounting.AccountingReaderAdapter;
import org.globus.workspace.accounting.ElapsedAndReservedMinutes;
import org.globus.workspace.service.binding.GlobalPolicies;
import org.globus.workspace.service.binding.Authorize;
import org.globus.workspace.service.binding.vm.VirtualMachine;
import org.globus.workspace.service.binding.vm.VirtualMachineDeployment;
import org.globus.workspace.service.CurrentVMs;
import org.nimbustools.api.services.rm.AuthorizationException;
import org.nimbustools.api.services.rm.ResourceRequestDeniedException;

import javax.security.auth.Subject;
import java.util.List;
import java.util.Arrays;

public class DefaultAuthorize implements Authorize {

    // -------------------------------------------------------------------------
    // STATIC VARIABLES
    // -------------------------------------------------------------------------
   
    private static final Log logger =
            LogFactory.getLog(DefaultAuthorize.class.getName());


    // -------------------------------------------------------------------------
    // INSTANCE VARIABLES
    // -------------------------------------------------------------------------

    protected final GlobalPolicies globals;
    protected final CurrentVMs currentVMs;
    protected final CreationAuthorizationCallout authzCallout;
    protected AccountingReaderAdapter accountingReader;


    // -------------------------------------------------------------------------
    // CONSTRUCTOR
    // -------------------------------------------------------------------------

    public DefaultAuthorize(CreationAuthorizationCallout calloutImpl,
                            GlobalPolicies globalPolicies,
                            CurrentVMs currentVMs) {
        if (globalPolicies == null) {
            throw new IllegalArgumentException("globalPolicies may not be null");
        }
        this.globals = globalPolicies;
       
        if (currentVMs == null) {
            throw new IllegalArgumentException("currentVMs may not be null");
        }
        this.currentVMs = currentVMs;

        if (calloutImpl == null) {
            throw new IllegalArgumentException("calloutImpl may not be null");
        }
        this.authzCallout = calloutImpl;
    }
   
   
    // -------------------------------------------------------------------------
    // SET
    // -------------------------------------------------------------------------

    public void setAccountingReaderAdapter(AccountingReaderAdapter reader) {
        this.accountingReader = reader;
    }

   
    // -------------------------------------------------------------------------
    // AUTHORIZE
    // -------------------------------------------------------------------------

    // With authz/accounting and scheduling, currently we suffer from a
    // check-then-act problem.  Client could be sending tons of requests
    // to try for a race condition in order to bypass some of the limits.
    // This is ok for now (clients are not anonymous, low priority to
    // defend against this).
    // So future TODO: put a lock around create() on a per-ID basis

    public void authz(VirtualMachine[] bindings,
                      String callerID,
                      Subject peerSubject,
                      double chargeRatio)
            throws ResourceRequestDeniedException,
                   AuthorizationException {

        if (this.authzCallout.isEnabled()) {
            try {

                Long elapsedMins = null;
                Long reservedMins = null;

                if (this.accountingReader != null) {
                    final ElapsedAndReservedMinutes elapRes =
                            this.accountingReader.
                                 totalElapsedAndReservedMinutesTuple(callerID);

                    final long elapsed = elapRes.getElapsed();
                    final long reserved = elapRes.getReserved();

                    if (elapsed < 0 || reserved < 0) {

                        logger.error("Accounting reader returned negative " +
                                     "value? Aborting.");

                        throw new ResourceRequestDeniedException(
                                             "Request denied, internal issue");
                    }

                    elapsedMins = new Long(elapRes.getElapsed());
                    reservedMins = new Long(elapRes.getReserved());
                }

                final int numWorkspaces =
                        this.currentVMs.countIDsByCaller(callerID);

                final boolean permitted =
                        Callout.isPermitted(this.authzCallout,
                                            callerID,
                                            peerSubject,
                                            bindings,
                                            elapsedMins,
                                            reservedMins,
                                            numWorkspaces,
                                            chargeRatio);

                // if a reason to client is desired, throw
                // WorkspaceResourceRequestDeniedException in callout
                if (!permitted) {
                    throw new ResourceRequestDeniedException(
                            "Your request was denied and no reason " +
                                          "was supplied for you to see.");
                }

            } catch (ResourceRequestDeniedException e) {
                throw e;
            } catch (Exception e) {
                logger.error("Problem in authorization callout", e);
                // do not reveal anything specific to the client
                throw new ResourceRequestDeniedException(
                                             "Request denied, internal issue");
            }
        }

        // enforce (global) factory policies
        this.authorize(bindings);
    }
   
    /**
     * Internal authorization and configuration policy enforcement.
     *
     * @param vms mutable, cannot be null
     * @throws AuthorizationException exc
     * @throws ResourceRequestDeniedException exc
     */
    public void authorize(final VirtualMachine[] vms)
            throws AuthorizationException,
                   ResourceRequestDeniedException {

        if (vms == null || vms.length == 0) {
            throw new IllegalArgumentException("no vms");
        }

        final int maxGroupSize = this.globals.getMaximumGroupSize();
        // zero means infinite
        if (maxGroupSize > 0 && vms.length > maxGroupSize) {
            throw new ResourceRequestDeniedException(
                        "request number of VMs (" + vms.length + ")" +
                                " exceeds the maximum permitted (" + maxGroupSize +
                                    " instances per group)");
        }


        final int defaultSecs = this.globals.getDefaultRunningTimeSeconds();
        final int maxSecs = this.globals.getMaximumRunningTimeSeconds();


        // for each because duration could be changed
        for (int i = 0; i < vms.length; i++) {
            authorizeDuration(vms[i], defaultSecs, maxSecs);
        }

        // we know these will all be same across VMs currently
        this.checkArchitecture(vms[0]);
        this.checkVMM(vms[0]);
    }

    protected void checkVMM(VirtualMachine vm)
            throws ResourceRequestDeniedException {

        final String vmm = this.globals.getVmm();
        if (vmm == null) {
            // if policy is null, means 'any'
            return; // *** EARLY RETURN ***
        }

        if (vm.getVmm() != null) {
            if (!vmm.equals(vm.getVmm())) {
                throw new ResourceRequestDeniedException(
                    "incorrect VMM");
            }
        }

        final String[] versions = this.globals.getVmmVersions();
        if (versions != null) {
            final String fromReq = vm.getVmmVersion();
            if (fromReq != null) {
                boolean found = false;
                for (int i = 0; i < versions.length; i++) {
                    if (versions[i].equals(fromReq)) {
                        found = true;
                        break;
                    }
                }
                if (!found) {
                    throw new ResourceRequestDeniedException(
                                                    "unsupported VMM version");
                }
            }
        }

    }

    protected static void authorizeDuration(VirtualMachine vm,
                                            int defaultSecs,
                                            int maxSecs)
                               throws AuthorizationException,
                                      ResourceRequestDeniedException {

        final VirtualMachineDeployment dep = vm.getDeployment();
        if (dep == null) {
            throw new AuthorizationException(
                        "internal error, no deployment, vm #" + vm.getID());
        }

        final int requestedSecs = dep.getMinDuration();
        if (requestedSecs == VirtualMachineDeployment.NOTSET) {
            dep.setMinDuration(defaultSecs);
        } else if (requestedSecs > maxSecs) {
                // client visible message:
                throw new ResourceRequestDeniedException(
                        "request duration (" + requestedSecs + " seconds)" +
                                " exceeds the maximum allowed (" + maxSecs +
                                " seconds)");
        }
    }


    protected void checkArchitecture(VirtualMachine vm)
            throws ResourceRequestDeniedException {

        final String[] allowedCPUArchitectures = this.globals.getCpuArchitectureNames();
        if (allowedCPUArchitectures == null) {
            // if policy is null, means 'any'
            return; // *** EARLY RETURN ***
        }

        final VirtualMachineDeployment dep = vm.getDeployment();
        if (dep == null) {
            throw new ResourceRequestDeniedException(
                            "no CPU architecture description (no dep)");
        }

        final String requestedArch = dep.getCPUArchitecture();
        if (requestedArch == null) {
            throw new ResourceRequestDeniedException(
                            "no CPU architecture description (no dep.arch)");
        }

        List archList = Arrays.asList(allowedCPUArchitectures);

        if (!archList.contains(requestedArch)) {

            StringBuilder sb = new StringBuilder();
            boolean first = true;
            for (int i=0; i < allowedCPUArchitectures.length ; i++) {
                if (first) {
                    first = false;
                }
                else {
                    sb.append(", ");
                }
                sb.append(allowedCPUArchitectures[i]);
            }
            final String allArchitectures = sb.toString();

            throw new ResourceRequestDeniedException(
                    "incorrect CPU architecture, only '" + allArchitectures +
                            "' supported, you requested '" + requestedArch + "'");
        }
    }

}
TOP

Related Classes of org.globus.workspace.service.binding.authorization.DefaultAuthorize

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.