org.nimbustools.messaging.gt4_0_elastic.v2008_05_05.security.ServiceSecurityImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.nimbustools.messaging.gt4_0_elastic.v2008_05_05.security.ServiceSecurityImpl.java

Source

/*
 * 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.nimbustools.messaging.gt4_0_elastic.v2008_05_05.security;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.globus.util.Base64;
import org.nimbustools.messaging.gt4_0_elastic.generated.v2010_08_31.CreateKeyPairResponseType;
import org.nimbustools.messaging.gt4_0_elastic.generated.v2010_08_31.CreateKeyPairType;
import org.nimbustools.messaging.gt4_0_elastic.generated.v2010_08_31.DeleteKeyPairResponseType;
import org.nimbustools.messaging.gt4_0_elastic.generated.v2010_08_31.DeleteKeyPairType;
import org.nimbustools.messaging.gt4_0_elastic.generated.v2010_08_31.DescribeKeyPairsInfoType;
import org.nimbustools.messaging.gt4_0_elastic.generated.v2010_08_31.DescribeKeyPairsItemType;
import org.nimbustools.messaging.gt4_0_elastic.generated.v2010_08_31.DescribeKeyPairsResponseInfoType;
import org.nimbustools.messaging.gt4_0_elastic.generated.v2010_08_31.DescribeKeyPairsResponseItemType;
import org.nimbustools.messaging.gt4_0_elastic.generated.v2010_08_31.DescribeKeyPairsResponseType;
import org.nimbustools.messaging.gt4_0_elastic.generated.v2010_08_31.DescribeKeyPairsType;
import org.nimbustools.messaging.gt4_0_elastic.generated.v2010_08_31.ImportKeyPairResponseType;
import org.nimbustools.messaging.gt4_0_elastic.generated.v2010_08_31.ImportKeyPairType;
import org.nimbustools.messaging.gt4_0_elastic.v2008_05_05.ServiceSecurity;
import org.nimbustools.messaging.gt4_0_elastic.v2008_05_05.rm.ContainerInterface;
import org.nimbustools.messaging.gt4_0_elastic.v2008_05_05.service.UnimplementedOperations;
import org.nimbustools.messaging.gt4_0_elastic.DisabledException;
import org.nimbustools.api.repr.Caller;
import org.nimbustools.api.repr.CannotTranslateException;

import java.rmi.RemoteException;
import java.util.List;
import java.util.LinkedList;

/**
 * extends UnimplementedOperations to make sure the unimplemented operations of
 * the ServiceSecurity interface are covered by some implementation.
 */
public class ServiceSecurityImpl extends UnimplementedOperations implements ServiceSecurity {

    // -------------------------------------------------------------------------
    // STATIC VARIABLES
    // -------------------------------------------------------------------------

    private static final Log logger = LogFactory.getLog(ServiceSecurityImpl.class.getName());
    private static final String FAKE_FINGERPRINT = "N0:KE:YF:IN:GE:RP:RI:NT";

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

    protected final SSHKeys sshKeys;
    protected final KeyGen keyGen;
    protected final ContainerInterface container;

    // -------------------------------------------------------------------------
    // CONSTRUCTORS
    // -------------------------------------------------------------------------

    public ServiceSecurityImpl(SSHKeys sshKeysImpl, KeyGen keyGenImpl, ContainerInterface containerImpl) {
        if (sshKeysImpl == null) {
            throw new IllegalArgumentException("sshKeysImpl may not be null");
        }
        this.sshKeys = sshKeysImpl;

        if (keyGenImpl == null) {
            throw new IllegalArgumentException("keyGenImpl may not be null");
        }
        this.keyGen = keyGenImpl;

        if (containerImpl == null) {
            throw new IllegalArgumentException("containerImpl may not be null");
        }
        this.container = containerImpl;
    }

    // -------------------------------------------------------------------------
    // *PARTIALLY* implements ServiceSecurity
    // -------------------------------------------------------------------------

    public CreateKeyPairResponseType createKeyPair(CreateKeyPairType req) throws RemoteException {

        // no use proceeding if these calls fail:
        final Caller caller = this.container.getCaller();
        final String ownerID;
        try {
            ownerID = this.container.getOwnerID(caller);
        } catch (CannotTranslateException e) {
            throw new RemoteException(e.getMessage(), e);
        }

        if (req == null) {
            throw new RemoteException("createKeyPair request is missing");
        }

        final String input = req.getKeyName();
        if (input == null) {
            throw new RemoteException("createKeyPair request does not contain key name");
        }

        final String splitToken;
        try {

            splitToken = this.sshKeys.getSplitToken();

        } catch (DisabledException e) {

            /* If split token method is disabled that means the standard
               "create keypair serverside" method is enabled.  Input field
               is the requested key name. */
            try {
                // *** EARLY RETURN ***
                return this.keyGen.createNewKeyPair(caller, input.trim());
            } catch (DisabledException e1) {
                throw new RuntimeException("Both SSH key implementations are disabled?");
            } catch (KeyGenException e1) {
                throw new RemoteException(e1.getMessage(), e1);
            }
        }

        // this is like an 'else' clause, see createNewKeyPair() call
        return this.splitMethod(splitToken, input, ownerID);
    }

    public ImportKeyPairResponseType importKeyPair(ImportKeyPairType req) throws RemoteException {

        // no use proceeding if these calls fail:
        final Caller caller = this.container.getCaller();
        final String ownerID;
        try {
            ownerID = this.container.getOwnerID(caller);
        } catch (CannotTranslateException e) {
            throw new RemoteException(e.getMessage(), e);
        }

        if (req == null) {
            throw new RemoteException("key name is missing");
        }

        final String keyName = req.getKeyName();
        if (keyName == null) {
            throw new RemoteException("createKeyPair request does not contain key name");
        }

        final String publicKeyMaterial = req.getPublicKeyMaterial();
        if (publicKeyMaterial == null) {
            throw new RemoteException("key material is missing");
        }
        if (!Base64.isBase64(publicKeyMaterial)) {
            throw new RemoteException("key material does not appear to " + "be base64 encoded?");
        }
        final byte[] bytes = Base64.decode(publicKeyMaterial.getBytes());
        final String keyMaterial = new String(bytes);

        this.sshKeys.newKey(ownerID, keyName, keyMaterial, FAKE_FINGERPRINT);

        final ImportKeyPairResponseType resp = new ImportKeyPairResponseType(FAKE_FINGERPRINT, keyName, null);

        logger.info("SSH key registered, name='" + keyName + "', owner ID='" + ownerID + "'");

        return resp;
    }

    public DescribeKeyPairsResponseType describeKeyPairs(DescribeKeyPairsType req) throws RemoteException {

        // no use proceeding if these calls fail:
        final Caller caller = this.container.getCaller();
        final String ownerID;
        try {
            ownerID = this.container.getOwnerID(caller);
        } catch (CannotTranslateException e) {
            throw new RemoteException(e.getMessage(), e);
        }

        if (req == null) {
            throw new RemoteException("describeKeyPairs request is missing");
        }

        final DescribeKeyPairsInfoType pairsInfoType = req.getKeySet();
        final DescribeKeyPairsItemType[] keyPairsItemTypes = pairsInfoType.getItem();

        final String[] filterQuery;
        if (keyPairsItemTypes == null || keyPairsItemTypes.length == 0) {
            filterQuery = null;
        } else {
            filterQuery = new String[keyPairsItemTypes.length];
            for (int i = 0; i < keyPairsItemTypes.length; i++) {
                if (keyPairsItemTypes[i] == null) {
                    throw new RemoteException("describeKeyPairs request is invalid, contains empty element?");
                }
                filterQuery[i] = keyPairsItemTypes[i].getKeyName();
                if (filterQuery[i] == null || filterQuery[i].trim().length() == 0) {
                    throw new RemoteException("describeKeyPairs request is invalid, contains empty element?");
                }
            }
        }

        if (filterQuery == null) {
            return this.describeAllPairs(ownerID);
        } else {
            return this.describeSomePairs(ownerID, filterQuery);
        }
    }

    public DeleteKeyPairResponseType deleteKeyPair(DeleteKeyPairType req) throws RemoteException {

        // no use proceeding if these calls fail:
        final Caller caller = this.container.getCaller();
        final String ownerID;
        try {
            ownerID = this.container.getOwnerID(caller);
        } catch (CannotTranslateException e) {
            throw new RemoteException(e.getMessage(), e);
        }

        if (req == null) {
            throw new RemoteException("deleteKeyPair request is missing");
        }

        final String keyToDelete = req.getKeyName();

        final boolean aKeyWasDeleted = this.sshKeys.removeKey(ownerID, keyToDelete);

        final DeleteKeyPairResponseType dkprt = new DeleteKeyPairResponseType();
        dkprt.set_return(aKeyWasDeleted);
        return dkprt;
    }

    // -------------------------------------------------------------------------
    // SPLITTING IMPL (PUBKEY ONLY METHOD)
    // -------------------------------------------------------------------------

    protected CreateKeyPairResponseType splitMethod(String splitToken, String input, String ownerID)
            throws RemoteException {

        final String err = "Cannot register keypair.  Semantics "
                + "for keypair creation are different than normal, see " + "documentation.  "
                + "(Expecting <keyname>" + splitToken + "<keyvalue>)";

        final int idx = input.indexOf(splitToken);
        if (idx < 1) {
            // (can't be idx 0 either, there would be no keyname then)
            throw new RemoteException(err + " (no token '" + splitToken + "')");
        }

        if (input.length() < splitToken.length() + 2) {
            throw new RemoteException(err + " (token present but " + "name or value is missing)");
        }

        final String givenKeyName = input.substring(0, idx);
        final int validx = idx + splitToken.length();
        final String givenKeyValue = input.substring(validx);

        final String keyName = givenKeyName.trim();
        final String keyValue = givenKeyValue.trim();

        if (keyName.length() == 0 || keyValue.length() == 0) {
            throw new RemoteException(err + " (token present but " + "name or value is missing)");
        }

        final String fingerprint = FAKE_FINGERPRINT;
        this.sshKeys.newKey(ownerID, keyName, keyValue, fingerprint);

        final CreateKeyPairResponseType ckprt = new CreateKeyPairResponseType();
        ckprt.setKeyFingerprint(fingerprint);
        ckprt.setKeyName(keyName);
        ckprt.setKeyMaterial(keyValue);

        logger.info("SSH key registered, name='" + keyName + "', owner ID='" + ownerID + "'");

        return ckprt;
    }

    // -------------------------------------------------------------------------
    // DESCRIBE IMPL
    // -------------------------------------------------------------------------

    protected DescribeKeyPairsResponseType describeAllPairs(String ownerID) {

        if (ownerID == null) {
            throw new IllegalArgumentException("ownerID may not be null");
        }

        final SSHKey[] allKeys = this.sshKeys.getOwnerKeys(ownerID);
        final List retList = new LinkedList();
        for (int i = 0; i < allKeys.length; i++) {
            final SSHKey key = allKeys[i];
            if (key == null) {
                logger.error("null in allKeys[]");
                continue; // *** SKIP ***
            }
            final DescribeKeyPairsResponseItemType one = this.getAPair(key);
            if (one == null) {
                continue; // *** SKIP ***
            }
            retList.add(one);
        }

        return convertDKPRTList(retList);
    }

    protected DescribeKeyPairsResponseType describeSomePairs(String ownerID, String[] filter) {

        if (filter == null || filter.length == 0) {
            throw new IllegalArgumentException("filters may not be null/empty");
        }

        final List retList = new LinkedList();
        for (int i = 0; i < filter.length; i++) {
            if (filter[i] == null || filter[i].trim().length() == 0) {
                throw new IllegalArgumentException("filters may not have null/empty elements");
            }
            final String keyname = filter[i].trim();
            final SSHKey key = this.sshKeys.findKey(ownerID, keyname);
            if (key == null) {
                continue; // *** SKIP ***
            }
            final DescribeKeyPairsResponseItemType one = this.getAPair(key);
            if (one == null) {
                continue; // *** SKIP ***
            }
            retList.add(one);
        }

        return convertDKPRTList(retList);
    }

    protected DescribeKeyPairsResponseItemType getAPair(SSHKey key) {
        if (key == null) {
            throw new IllegalArgumentException("key may not be null");
        }
        final DescribeKeyPairsResponseItemType dkprit = new DescribeKeyPairsResponseItemType();
        dkprit.setKeyName(key.getKeyName());
        dkprit.setKeyFingerprint(key.getFingerprint());
        return dkprit;
    }

    private static DescribeKeyPairsResponseType convertDKPRTList(List retList) {
        final DescribeKeyPairsResponseItemType[] rets = (DescribeKeyPairsResponseItemType[]) retList
                .toArray(new DescribeKeyPairsResponseItemType[retList.size()]);

        final DescribeKeyPairsResponseInfoType dkprt = new DescribeKeyPairsResponseInfoType();
        dkprt.setItem(rets);

        final DescribeKeyPairsResponseType response = new DescribeKeyPairsResponseType();
        response.setKeySet(dkprt);

        return response;
    }
}