| // Licensed to the Apache Software Foundation (ASF) under one | |
| // or more contributor license agreements. See the NOTICE file | |
| // distributed with this work for additional information | |
| // regarding copyright ownership. The ASF licenses this file | |
| // to you 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 com.cloud.bridge.service; | |
| import java.io.ByteArrayInputStream; | |
| import java.io.File; | |
| import java.io.FileInputStream; | |
| import java.io.FileNotFoundException; | |
| import java.io.FileOutputStream; | |
| import java.io.IOException; | |
| import java.io.OutputStream; | |
| import java.io.OutputStreamWriter; | |
| import java.net.URLEncoder; | |
| import java.security.KeyStore; | |
| import java.security.SignatureException; | |
| import java.security.cert.Certificate; | |
| import java.security.cert.CertificateFactory; | |
| import java.sql.SQLException; | |
| import java.text.ParseException; | |
| import java.util.ArrayList; | |
| import java.util.Calendar; | |
| import java.util.Date; | |
| import java.util.Enumeration; | |
| import java.util.HashMap; | |
| import java.util.List; | |
| import java.util.Map; | |
| import java.util.Properties; | |
| import java.util.UUID; | |
| import javax.inject.Inject; | |
| import javax.servlet.ServletConfig; | |
| import javax.servlet.ServletException; | |
| import javax.servlet.http.HttpServlet; | |
| import javax.servlet.http.HttpServletRequest; | |
| import javax.servlet.http.HttpServletResponse; | |
| import javax.xml.stream.XMLOutputFactory; | |
| import javax.xml.stream.XMLStreamException; | |
| import javax.xml.stream.XMLStreamWriter; | |
| import org.apache.axiom.om.OMAbstractFactory; | |
| import org.apache.axiom.om.OMFactory; | |
| import org.apache.axis2.AxisFault; | |
| import org.apache.axis2.databinding.ADBBean; | |
| import org.apache.axis2.databinding.ADBException; | |
| import org.apache.axis2.databinding.utils.writer.MTOMAwareXMLSerializer; | |
| import org.apache.commons.codec.binary.Base64; | |
| import org.apache.commons.io.IOUtils; | |
| import org.apache.log4j.Logger; | |
| import org.springframework.stereotype.Component; | |
| import org.springframework.web.context.support.SpringBeanAutowiringSupport; | |
| import com.amazon.ec2.AllocateAddressResponse; | |
| import com.amazon.ec2.AssociateAddressResponse; | |
| import com.amazon.ec2.AttachVolumeResponse; | |
| import com.amazon.ec2.AuthorizeSecurityGroupIngressResponse; | |
| import com.amazon.ec2.CreateImageResponse; | |
| import com.amazon.ec2.CreateKeyPairResponse; | |
| import com.amazon.ec2.CreateSecurityGroupResponse; | |
| import com.amazon.ec2.CreateSnapshotResponse; | |
| import com.amazon.ec2.CreateTagsResponse; | |
| import com.amazon.ec2.CreateVolumeResponse; | |
| import com.amazon.ec2.DeleteKeyPairResponse; | |
| import com.amazon.ec2.DeleteSecurityGroupResponse; | |
| import com.amazon.ec2.DeleteSnapshotResponse; | |
| import com.amazon.ec2.DeleteTagsResponse; | |
| import com.amazon.ec2.DeleteVolumeResponse; | |
| import com.amazon.ec2.DeregisterImageResponse; | |
| import com.amazon.ec2.DescribeAvailabilityZonesResponse; | |
| import com.amazon.ec2.DescribeImageAttributeResponse; | |
| import com.amazon.ec2.DescribeImagesResponse; | |
| import com.amazon.ec2.DescribeInstanceAttributeResponse; | |
| import com.amazon.ec2.DescribeInstancesResponse; | |
| import com.amazon.ec2.DescribeKeyPairsResponse; | |
| import com.amazon.ec2.DescribeSecurityGroupsResponse; | |
| import com.amazon.ec2.DescribeSnapshotsResponse; | |
| import com.amazon.ec2.DescribeTagsResponse; | |
| import com.amazon.ec2.DescribeVolumesResponse; | |
| import com.amazon.ec2.DetachVolumeResponse; | |
| import com.amazon.ec2.DisassociateAddressResponse; | |
| import com.amazon.ec2.GetPasswordDataResponse; | |
| import com.amazon.ec2.ImportKeyPairResponse; | |
| import com.amazon.ec2.ModifyImageAttributeResponse; | |
| import com.amazon.ec2.ModifyInstanceAttributeResponse; | |
| import com.amazon.ec2.RebootInstancesResponse; | |
| import com.amazon.ec2.RegisterImageResponse; | |
| import com.amazon.ec2.ReleaseAddressResponse; | |
| import com.amazon.ec2.ResetImageAttributeResponse; | |
| import com.amazon.ec2.RevokeSecurityGroupIngressResponse; | |
| import com.amazon.ec2.RunInstancesResponse; | |
| import com.amazon.ec2.StartInstancesResponse; | |
| import com.amazon.ec2.StopInstancesResponse; | |
| import com.amazon.ec2.TerminateInstancesResponse; | |
| import com.cloud.bridge.model.UserCredentialsVO; | |
| import com.cloud.bridge.persist.dao.CloudStackUserDaoImpl; | |
| import com.cloud.bridge.persist.dao.OfferingDaoImpl; | |
| import com.cloud.bridge.persist.dao.UserCredentialsDaoImpl; | |
| import com.cloud.bridge.service.controller.s3.ServiceProvider; | |
| import com.cloud.bridge.service.core.ec2.EC2AddressFilterSet; | |
| import com.cloud.bridge.service.core.ec2.EC2AssociateAddress; | |
| import com.cloud.bridge.service.core.ec2.EC2AuthorizeRevokeSecurityGroup; | |
| import com.cloud.bridge.service.core.ec2.EC2AvailabilityZonesFilterSet; | |
| import com.cloud.bridge.service.core.ec2.EC2CreateImage; | |
| import com.cloud.bridge.service.core.ec2.EC2CreateKeyPair; | |
| import com.cloud.bridge.service.core.ec2.EC2CreateVolume; | |
| import com.cloud.bridge.service.core.ec2.EC2DeleteKeyPair; | |
| import com.cloud.bridge.service.core.ec2.EC2DescribeAddresses; | |
| import com.cloud.bridge.service.core.ec2.EC2DescribeAvailabilityZones; | |
| import com.cloud.bridge.service.core.ec2.EC2DescribeImageAttribute; | |
| import com.cloud.bridge.service.core.ec2.EC2DescribeImages; | |
| import com.cloud.bridge.service.core.ec2.EC2DescribeInstances; | |
| import com.cloud.bridge.service.core.ec2.EC2DescribeKeyPairs; | |
| import com.cloud.bridge.service.core.ec2.EC2DescribeSecurityGroups; | |
| import com.cloud.bridge.service.core.ec2.EC2DescribeSnapshots; | |
| import com.cloud.bridge.service.core.ec2.EC2DescribeTags; | |
| import com.cloud.bridge.service.core.ec2.EC2DescribeVolumes; | |
| import com.cloud.bridge.service.core.ec2.EC2DisassociateAddress; | |
| import com.cloud.bridge.service.core.ec2.EC2Engine; | |
| import com.cloud.bridge.service.core.ec2.EC2Filter; | |
| import com.cloud.bridge.service.core.ec2.EC2GroupFilterSet; | |
| import com.cloud.bridge.service.core.ec2.EC2Image; | |
| import com.cloud.bridge.service.core.ec2.EC2ImageAttributes.ImageAttribute; | |
| import com.cloud.bridge.service.core.ec2.EC2ImageFilterSet; | |
| import com.cloud.bridge.service.core.ec2.EC2ImageLaunchPermission; | |
| import com.cloud.bridge.service.core.ec2.EC2ImportKeyPair; | |
| import com.cloud.bridge.service.core.ec2.EC2InstanceFilterSet; | |
| import com.cloud.bridge.service.core.ec2.EC2IpPermission; | |
| import com.cloud.bridge.service.core.ec2.EC2KeyPairFilterSet; | |
| import com.cloud.bridge.service.core.ec2.EC2ModifyImageAttribute; | |
| import com.cloud.bridge.service.core.ec2.EC2ModifyInstanceAttribute; | |
| import com.cloud.bridge.service.core.ec2.EC2RebootInstances; | |
| import com.cloud.bridge.service.core.ec2.EC2RegisterImage; | |
| import com.cloud.bridge.service.core.ec2.EC2ReleaseAddress; | |
| import com.cloud.bridge.service.core.ec2.EC2RunInstances; | |
| import com.cloud.bridge.service.core.ec2.EC2SecurityGroup; | |
| import com.cloud.bridge.service.core.ec2.EC2SnapshotFilterSet; | |
| import com.cloud.bridge.service.core.ec2.EC2StartInstances; | |
| import com.cloud.bridge.service.core.ec2.EC2StopInstances; | |
| import com.cloud.bridge.service.core.ec2.EC2Tags; | |
| import com.cloud.bridge.service.core.ec2.EC2TagsFilterSet; | |
| import com.cloud.bridge.service.core.ec2.EC2Volume; | |
| import com.cloud.bridge.service.core.ec2.EC2VolumeFilterSet; | |
| import com.cloud.bridge.service.exception.EC2ServiceException; | |
| import com.cloud.bridge.service.exception.EC2ServiceException.ClientError; | |
| import com.cloud.bridge.service.exception.NoSuchObjectException; | |
| import com.cloud.bridge.service.exception.PermissionDeniedException; | |
| import com.cloud.bridge.util.AuthenticationUtils; | |
| import com.cloud.bridge.util.ConfigurationHelper; | |
| import com.cloud.bridge.util.EC2RestAuth; | |
| import com.cloud.stack.models.CloudStackAccount; | |
| import com.cloud.utils.db.TransactionLegacy; | |
| @Component("EC2RestServlet") | |
| public class EC2RestServlet extends HttpServlet { | |
| private static final long serialVersionUID = -6168996266762804888L; | |
| @Inject | |
| UserCredentialsDaoImpl ucDao; | |
| @Inject | |
| OfferingDaoImpl ofDao; | |
| @Inject | |
| CloudStackUserDaoImpl userDao; | |
| public static final Logger logger = Logger.getLogger(EC2RestServlet.class); | |
| private final OMFactory factory = OMAbstractFactory.getOMFactory(); | |
| private final XMLOutputFactory xmlOutFactory = XMLOutputFactory.newInstance(); | |
| private String pathToKeystore = null; | |
| private String keystorePassword = null; | |
| private String wsdlVersion = null; | |
| private String version = null; | |
| boolean debug = true; | |
| public EC2RestServlet() { | |
| } | |
| /** | |
| * We build the path to where the keystore holding the WS-Security X509 certificates | |
| * are stored. | |
| */ | |
| @Override | |
| public void init(ServletConfig config) throws ServletException { | |
| SpringBeanAutowiringSupport.processInjectionBasedOnServletContext(this, config.getServletContext()); | |
| File propertiesFile = ConfigurationHelper.findConfigurationFile("ec2-service.properties"); | |
| Properties EC2Prop = null; | |
| if (null != propertiesFile) { | |
| logger.info("Use EC2 properties file: " + propertiesFile.getAbsolutePath()); | |
| EC2Prop = new Properties(); | |
| FileInputStream ec2PropFile = null; | |
| try { | |
| ec2PropFile = new FileInputStream(propertiesFile); | |
| EC2Prop.load(ec2PropFile); | |
| } catch (FileNotFoundException e) { | |
| logger.warn("Unable to open properties file: " + propertiesFile.getAbsolutePath(), e); | |
| } catch (IOException e) { | |
| logger.warn("Unable to read properties file: " + propertiesFile.getAbsolutePath(), e); | |
| } finally { | |
| IOUtils.closeQuietly(ec2PropFile); | |
| } | |
| String keystore = EC2Prop.getProperty("keystore"); | |
| keystorePassword = EC2Prop.getProperty("keystorePass"); | |
| wsdlVersion = EC2Prop.getProperty("WSDLVersion", "2012-08-15"); | |
| version = EC2Prop.getProperty("cloudbridgeVersion", "UNKNOWN VERSION"); | |
| String installedPath = System.getenv("CATALINA_HOME"); | |
| if (installedPath == null) | |
| installedPath = System.getenv("CATALINA_BASE"); | |
| if (installedPath == null) | |
| installedPath = System.getProperty("catalina.home"); | |
| String webappPath = config.getServletContext().getRealPath("/"); | |
| //pathToKeystore = new String( installedPath + File.separator + "webapps" + File.separator + webappName + File.separator + "WEB-INF" + File.separator + "classes" + File.separator + keystore ); | |
| pathToKeystore = new String(webappPath + File.separator + "WEB-INF" + File.separator + "classes" + File.separator + keystore); | |
| } | |
| } | |
| @Override | |
| protected void doGet(HttpServletRequest req, HttpServletResponse resp) { | |
| doGetOrPost(req, resp); | |
| } | |
| @Override | |
| protected void doPost(HttpServletRequest req, HttpServletResponse resp) { | |
| doGetOrPost(req, resp); | |
| } | |
| protected void doGetOrPost(HttpServletRequest request, HttpServletResponse response) { | |
| if (debug) { | |
| System.out.println("EC2RestServlet.doGetOrPost: javax.servlet.forward.request_uri: " + request.getAttribute("javax.servlet.forward.request_uri")); | |
| System.out.println("EC2RestServlet.doGetOrPost: javax.servlet.forward.context_path: " + request.getAttribute("javax.servlet.forward.context_path")); | |
| System.out.println("EC2RestServlet.doGetOrPost: javax.servlet.forward.servlet_path: " + request.getAttribute("javax.servlet.forward.servlet_path")); | |
| System.out.println("EC2RestServlet.doGetOrPost: javax.servlet.forward.path_info: " + request.getAttribute("javax.servlet.forward.path_info")); | |
| System.out.println("EC2RestServlet.doGetOrPost: javax.servlet.forward.query_string: " + request.getAttribute("javax.servlet.forward.query_string")); | |
| } | |
| String action = request.getParameter("Action"); | |
| logRequest(request); | |
| // -> unauthenticated calls, should still be done over HTTPS | |
| if (action.equalsIgnoreCase("SetUserKeys")) { | |
| setUserKeys(request, response); | |
| return; | |
| } | |
| if (action.equalsIgnoreCase("CloudEC2Version")) { | |
| cloudEC2Version(request, response); | |
| return; | |
| } | |
| // -> authenticated calls | |
| try { | |
| if (!authenticateRequest(request, response)) | |
| return; | |
| if (action.equalsIgnoreCase("AllocateAddress")) | |
| allocateAddress(request, response); | |
| else if (action.equalsIgnoreCase("AssociateAddress")) | |
| associateAddress(request, response); | |
| else if (action.equalsIgnoreCase("AttachVolume")) | |
| attachVolume(request, response); | |
| else if (action.equalsIgnoreCase("AuthorizeSecurityGroupIngress")) | |
| authorizeSecurityGroupIngress(request, response); | |
| else if (action.equalsIgnoreCase("CreateImage")) | |
| createImage(request, response); | |
| else if (action.equalsIgnoreCase("CreateSecurityGroup")) | |
| createSecurityGroup(request, response); | |
| else if (action.equalsIgnoreCase("CreateSnapshot")) | |
| createSnapshot(request, response); | |
| else if (action.equalsIgnoreCase("CreateVolume")) | |
| createVolume(request, response); | |
| else if (action.equalsIgnoreCase("DeleteSecurityGroup")) | |
| deleteSecurityGroup(request, response); | |
| else if (action.equalsIgnoreCase("DeleteSnapshot")) | |
| deleteSnapshot(request, response); | |
| else if (action.equalsIgnoreCase("DeleteVolume")) | |
| deleteVolume(request, response); | |
| else if (action.equalsIgnoreCase("DeregisterImage")) | |
| deregisterImage(request, response); | |
| else if (action.equalsIgnoreCase("DescribeAddresses")) | |
| describeAddresses(request, response); | |
| else if (action.equalsIgnoreCase("DescribeAvailabilityZones")) | |
| describeAvailabilityZones(request, response); | |
| else if (action.equalsIgnoreCase("DescribeImageAttribute")) | |
| describeImageAttribute(request, response); | |
| else if (action.equalsIgnoreCase("DescribeImages")) | |
| describeImages(request, response); | |
| else if (action.equalsIgnoreCase("DescribeInstanceAttribute")) | |
| describeInstanceAttribute(request, response); | |
| else if (action.equalsIgnoreCase("DescribeInstances")) | |
| describeInstances(request, response); | |
| else if (action.equalsIgnoreCase("DescribeSecurityGroups")) | |
| describeSecurityGroups(request, response); | |
| else if (action.equalsIgnoreCase("DescribeSnapshots")) | |
| describeSnapshots(request, response); | |
| else if (action.equalsIgnoreCase("DescribeVolumes")) | |
| describeVolumes(request, response); | |
| else if (action.equalsIgnoreCase("DetachVolume")) | |
| detachVolume(request, response); | |
| else if (action.equalsIgnoreCase("DisassociateAddress")) | |
| disassociateAddress(request, response); | |
| else if (action.equalsIgnoreCase("ModifyImageAttribute")) | |
| modifyImageAttribute(request, response); | |
| else if (action.equalsIgnoreCase("ModifyInstanceAttribute")) | |
| modifyInstanceAttribute(request, response); | |
| else if (action.equalsIgnoreCase("RebootInstances")) | |
| rebootInstances(request, response); | |
| else if (action.equalsIgnoreCase("RegisterImage")) | |
| registerImage(request, response); | |
| else if (action.equalsIgnoreCase("ReleaseAddress")) | |
| releaseAddress(request, response); | |
| else if (action.equalsIgnoreCase("ResetImageAttribute")) | |
| resetImageAttribute(request, response); | |
| else if (action.equalsIgnoreCase("RevokeSecurityGroupIngress")) | |
| revokeSecurityGroupIngress(request, response); | |
| else if (action.equalsIgnoreCase("RunInstances")) | |
| runInstances(request, response); | |
| else if (action.equalsIgnoreCase("StartInstances")) | |
| startInstances(request, response); | |
| else if (action.equalsIgnoreCase("StopInstances")) | |
| stopInstances(request, response); | |
| else if (action.equalsIgnoreCase("TerminateInstances")) | |
| terminateInstances(request, response); | |
| else if (action.equalsIgnoreCase("SetCertificate")) | |
| setCertificate(request, response); | |
| else if (action.equalsIgnoreCase("DeleteCertificate")) | |
| deleteCertificate(request, response); | |
| else if (action.equalsIgnoreCase("SetOfferMapping")) | |
| setOfferMapping(request, response); | |
| else if (action.equalsIgnoreCase("DeleteOfferMapping")) | |
| deleteOfferMapping(request, response); | |
| else if (action.equalsIgnoreCase("CreateKeyPair")) | |
| createKeyPair(request, response); | |
| else if (action.equalsIgnoreCase("ImportKeyPair")) | |
| importKeyPair(request, response); | |
| else if (action.equalsIgnoreCase("DeleteKeyPair")) | |
| deleteKeyPair(request, response); | |
| else if (action.equalsIgnoreCase("DescribeKeyPairs")) | |
| describeKeyPairs(request, response); | |
| else if (action.equalsIgnoreCase("CreateTags")) | |
| createTags(request, response); | |
| else if (action.equalsIgnoreCase("DeleteTags")) | |
| deleteTags(request, response); | |
| else if (action.equalsIgnoreCase("DescribeTags")) | |
| describeTags(request, response); | |
| else if (action.equalsIgnoreCase("GetPasswordData")) | |
| getPasswordData(request, response); | |
| else { | |
| logger.error("Unsupported action " + action); | |
| throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available"); | |
| } | |
| } catch (EC2ServiceException e) { | |
| response.setStatus(e.getErrorCode()); | |
| if (e.getCause() != null && e.getCause() instanceof AxisFault) { | |
| String errorCode = ((AxisFault)e.getCause()).getFaultCode().getLocalPart(); | |
| if (errorCode.startsWith("Client.")) // only in a SOAP API client error code is prefixed with Client. | |
| errorCode = errorCode.split("Client.")[1]; | |
| else if (errorCode.startsWith("Server.")) // only in a SOAP API server error code is prefixed with Server. | |
| errorCode = errorCode.split("Server.")[1]; | |
| faultResponse(response, errorCode, e.getMessage()); | |
| } else { | |
| logger.error("EC2ServiceException: " + e.getMessage(), e); | |
| endResponse(response, e.toString()); | |
| } | |
| } catch (PermissionDeniedException e) { | |
| logger.error("Unexpected exception: " + e.getMessage(), e); | |
| response.setStatus(403); | |
| endResponse(response, "Access denied"); | |
| } catch (Exception e) { | |
| logger.error("Unexpected exception: " + e.getMessage(), e); | |
| response.setStatus(500); | |
| endResponse(response, e.toString()); | |
| } finally { | |
| try { | |
| response.flushBuffer(); | |
| } catch (IOException e) { | |
| logger.error("Unexpected exception " + e.getMessage(), e); | |
| } | |
| } | |
| } | |
| /** | |
| * Provide an easy way to determine the version of the implementation running. | |
| * | |
| * This is an unauthenticated REST call. | |
| */ | |
| private void cloudEC2Version(HttpServletRequest request, HttpServletResponse response) { | |
| String version_response = new String("<?xml version=\"1.0\" encoding=\"utf-8\"?><CloudEC2Version>" + version + "</CloudEC2Version>"); | |
| response.setStatus(200); | |
| endResponse(response, version_response); | |
| } | |
| /** | |
| * This request registers the Cloud.com account holder to the EC2 service. The Cloud.com | |
| * account holder saves his API access and secret keys with the EC2 service so that | |
| * the EC2 service can make Cloud.com API calls on his behalf. The given API access | |
| * and secret key are saved into the "usercredentials" database table. | |
| * | |
| * This is an unauthenticated REST call. The only required parameters are 'accesskey' and | |
| * 'secretkey'. | |
| * | |
| * To verify that the given keys represent an existing account they are used to execute the | |
| * Cloud.com's listAccounts API function. If the keys do not represent a valid account the | |
| * listAccounts function will fail. | |
| * | |
| * A user can call this REST function any number of times, on each call the Cloud.com secret | |
| * key is simply over writes any previously stored value. | |
| * | |
| * As with all REST calls HTTPS should be used to ensure their security. | |
| */ | |
| private void setUserKeys(HttpServletRequest request, HttpServletResponse response) { | |
| String[] accessKey = null; | |
| String[] secretKey = null; | |
| TransactionLegacy txn = null; | |
| try { | |
| // -> all these parameters are required | |
| accessKey = request.getParameterValues("accesskey"); | |
| if (null == accessKey || 0 == accessKey.length) { | |
| response.sendError(530, "Missing accesskey parameter"); | |
| return; | |
| } | |
| secretKey = request.getParameterValues("secretkey"); | |
| if (null == secretKey || 0 == secretKey.length) { | |
| response.sendError(530, "Missing secretkey parameter"); | |
| return; | |
| } | |
| } catch (Exception e) { | |
| logger.error("SetUserKeys exception " + e.getMessage(), e); | |
| response.setStatus(500); | |
| endResponse(response, "SetUserKeys exception " + e.getMessage()); | |
| return; | |
| } | |
| try { | |
| txn = TransactionLegacy.open(TransactionLegacy.AWSAPI_DB); | |
| txn.start(); | |
| // -> use the keys to see if the account actually exists | |
| ServiceProvider.getInstance().getEC2Engine().validateAccount(accessKey[0], secretKey[0]); | |
| UserCredentialsVO user = new UserCredentialsVO(accessKey[0], secretKey[0]); | |
| ucDao.persist(user); | |
| txn.commit(); | |
| } catch (Exception e) { | |
| logger.error("SetUserKeys " + e.getMessage(), e); | |
| response.setStatus(401); | |
| endResponse(response, e.toString()); | |
| txn.close(); | |
| return; | |
| } | |
| response.setStatus(200); | |
| endResponse(response, "User keys set successfully"); | |
| } | |
| /** | |
| * The SOAP API for EC2 uses WS-Security to sign all client requests. This requires that | |
| * the client have a public/private key pair and the public key defined by a X509 certificate. | |
| * Thus in order for a Cloud.com account holder to use the EC2's SOAP API he must register | |
| * his X509 certificate with the EC2 service. This function allows the Cloud.com account | |
| * holder to "load" his X509 certificate into the service. Note, that the SetUserKeys REST | |
| * function must be called before this call. | |
| * | |
| * This is an authenticated REST call and as such must contain all the required REST parameters | |
| * including: Signature, Timestamp, Expires, etc. The signature is calculated using the | |
| * Cloud.com account holder's API access and secret keys and the Amazon defined EC2 signature | |
| * algorithm. | |
| * | |
| * A user can call this REST function any number of times, on each call the X509 certificate | |
| * simply over writes any previously stored value. | |
| */ | |
| private void setCertificate(HttpServletRequest request, HttpServletResponse response) throws Exception { | |
| TransactionLegacy txn = null; | |
| try { | |
| // [A] Pull the cert and cloud AccessKey from the request | |
| String[] certificate = request.getParameterValues("cert"); | |
| if (null == certificate || 0 == certificate.length) { | |
| response.sendError(530, "Missing cert parameter"); | |
| return; | |
| } | |
| // logger.debug( "SetCertificate cert: [" + certificate[0] + "]" ); | |
| String[] accessKey = request.getParameterValues("AWSAccessKeyId"); | |
| if (null == accessKey || 0 == accessKey.length) { | |
| response.sendError(530, "Missing AWSAccessKeyId parameter"); | |
| return; | |
| } | |
| // [B] Open our keystore | |
| FileInputStream fsIn = new FileInputStream(pathToKeystore); | |
| KeyStore certStore = KeyStore.getInstance("JKS"); | |
| certStore.load(fsIn, keystorePassword.toCharArray()); | |
| // -> use the Cloud API key to save the cert in the keystore | |
| // -> write the cert into the keystore on disk | |
| Certificate userCert = null; | |
| CertificateFactory cf = CertificateFactory.getInstance("X.509"); | |
| ByteArrayInputStream bs = new ByteArrayInputStream(certificate[0].getBytes()); | |
| while (bs.available() > 0) | |
| userCert = cf.generateCertificate(bs); | |
| certStore.setCertificateEntry(accessKey[0], userCert); | |
| FileOutputStream fsOut = new FileOutputStream(pathToKeystore); | |
| certStore.store(fsOut, keystorePassword.toCharArray()); | |
| // [C] Associate the cert's uniqueId with the Cloud API keys | |
| String uniqueId = AuthenticationUtils.X509CertUniqueId(userCert); | |
| logger.debug("SetCertificate, uniqueId: " + uniqueId); | |
| txn = TransactionLegacy.open(TransactionLegacy.AWSAPI_DB); | |
| txn.start(); | |
| UserCredentialsVO user = ucDao.getByAccessKey(accessKey[0]); | |
| user.setCertUniqueId(uniqueId); | |
| ucDao.update(user.getId(), user); | |
| response.setStatus(200); | |
| endResponse(response, "User certificate set successfully"); | |
| txn.commit(); | |
| } catch (NoSuchObjectException e) { | |
| logger.error("SetCertificate exception " + e.getMessage(), e); | |
| response.sendError(404, "SetCertificate exception " + e.getMessage()); | |
| } catch (Exception e) { | |
| logger.error("SetCertificate exception " + e.getMessage(), e); | |
| response.sendError(500, "SetCertificate exception " + e.getMessage()); | |
| } finally { | |
| txn.close(); | |
| } | |
| } | |
| /** | |
| * The SOAP API for EC2 uses WS-Security to sign all client requests. This requires that | |
| * the client have a public/private key pair and the public key defined by a X509 certificate. | |
| * This REST call allows a Cloud.com account holder to remove a previouly "loaded" X509 | |
| * certificate out of the EC2 service. | |
| * | |
| * This is an unauthenticated REST call and as such must contain all the required REST parameters | |
| * including: Signature, Timestamp, Expires, etc. The signature is calculated using the | |
| * Cloud.com account holder's API access and secret keys and the Amazon defined EC2 signature | |
| * algorithm. | |
| */ | |
| private void deleteCertificate(HttpServletRequest request, HttpServletResponse response) throws Exception { | |
| TransactionLegacy txn = null; | |
| try { | |
| String[] accessKey = request.getParameterValues("AWSAccessKeyId"); | |
| if (null == accessKey || 0 == accessKey.length) { | |
| response.sendError(530, "Missing AWSAccessKeyId parameter"); | |
| return; | |
| } | |
| // -> delete the specified entry and save back to disk | |
| FileInputStream fsIn = new FileInputStream(pathToKeystore); | |
| KeyStore certStore = KeyStore.getInstance("JKS"); | |
| certStore.load(fsIn, keystorePassword.toCharArray()); | |
| if (certStore.containsAlias(accessKey[0])) { | |
| certStore.deleteEntry(accessKey[0]); | |
| FileOutputStream fsOut = new FileOutputStream(pathToKeystore); | |
| certStore.store(fsOut, keystorePassword.toCharArray()); | |
| // -> dis-associate the cert's uniqueId with the Cloud API keys | |
| /* UserCredentialsDao credentialDao = new UserCredentialsDao(); | |
| credentialDao.setCertificateId( accessKey[0], null ); | |
| */txn = TransactionLegacy.open(TransactionLegacy.AWSAPI_DB); | |
| UserCredentialsVO user = ucDao.getByAccessKey(accessKey[0]); | |
| user.setCertUniqueId(null); | |
| ucDao.update(user.getId(), user); | |
| response.setStatus(200); | |
| endResponse(response, "User certificate deleted successfully"); | |
| txn.commit(); | |
| } else | |
| response.setStatus(404); | |
| } catch (NoSuchObjectException e) { | |
| logger.error("SetCertificate exception " + e.getMessage(), e); | |
| response.sendError(404, "SetCertificate exception " + e.getMessage()); | |
| } catch (Exception e) { | |
| logger.error("DeleteCertificate exception " + e.getMessage(), e); | |
| response.sendError(500, "DeleteCertificate exception " + e.getMessage()); | |
| } finally { | |
| txn.close(); | |
| } | |
| } | |
| /** | |
| * Allow the caller to define the mapping between the Amazon instance type strings | |
| * (e.g., m1.small, cc1.4xlarge) and the cloudstack service offering ids. Setting | |
| * an existing mapping just over writes the prevous values. | |
| */ | |
| private void setOfferMapping(HttpServletRequest request, HttpServletResponse response) { | |
| String amazonOffer = null; | |
| String cloudOffer = null; | |
| try { | |
| // -> all these parameters are required | |
| amazonOffer = request.getParameter("amazonoffer"); | |
| if (null == amazonOffer) { | |
| response.sendError(530, "Missing amazonoffer parameter"); | |
| return; | |
| } | |
| cloudOffer = request.getParameter("cloudoffer"); | |
| if (null == cloudOffer) { | |
| response.sendError(530, "Missing cloudoffer parameter"); | |
| return; | |
| } | |
| } catch (Exception e) { | |
| logger.error("SetOfferMapping exception " + e.getMessage(), e); | |
| response.setStatus(500); | |
| endResponse(response, "SetOfferMapping exception " + e.getMessage()); | |
| return; | |
| } | |
| // validate account is admin level | |
| try { | |
| CloudStackAccount currentAccount = ServiceProvider.getInstance().getEC2Engine().getCurrentAccount(); | |
| if (currentAccount.getAccountType() != 1) { | |
| logger.debug("SetOfferMapping called by non-admin user!"); | |
| response.setStatus(500); | |
| endResponse(response, "Permission denied for non-admin user to setOfferMapping!"); | |
| return; | |
| } | |
| } catch (Exception e) { | |
| logger.error("SetOfferMapping " + e.getMessage(), e); | |
| response.setStatus(401); | |
| endResponse(response, e.toString()); | |
| return; | |
| } | |
| try { | |
| ofDao.setOfferMapping(amazonOffer, cloudOffer); | |
| } catch (Exception e) { | |
| logger.error("SetOfferMapping " + e.getMessage(), e); | |
| response.setStatus(401); | |
| endResponse(response, e.toString()); | |
| return; | |
| } | |
| response.setStatus(200); | |
| endResponse(response, "offering mapping set successfully"); | |
| } | |
| private void deleteOfferMapping(HttpServletRequest request, HttpServletResponse response) { | |
| String amazonOffer = null; | |
| try { | |
| // -> all these parameters are required | |
| amazonOffer = request.getParameter("amazonoffer"); | |
| if (null == amazonOffer) { | |
| response.sendError(530, "Missing amazonoffer parameter"); | |
| return; | |
| } | |
| } catch (Exception e) { | |
| logger.error("DeleteOfferMapping exception " + e.getMessage(), e); | |
| response.setStatus(500); | |
| endResponse(response, "DeleteOfferMapping exception " + e.getMessage()); | |
| return; | |
| } | |
| // validate account is admin level | |
| try { | |
| CloudStackAccount currentAccount = ServiceProvider.getInstance().getEC2Engine().getCurrentAccount(); | |
| if (currentAccount.getAccountType() != 1) { | |
| logger.debug("deleteOfferMapping called by non-admin user!"); | |
| response.setStatus(500); | |
| endResponse(response, "Permission denied for non-admin user to deleteOfferMapping!"); | |
| return; | |
| } | |
| } catch (Exception e) { | |
| logger.error("deleteOfferMapping " + e.getMessage(), e); | |
| response.setStatus(401); | |
| endResponse(response, e.toString()); | |
| return; | |
| } | |
| try { | |
| ofDao.deleteOfferMapping(amazonOffer); | |
| } catch (Exception e) { | |
| logger.error("DeleteOfferMapping " + e.getMessage(), e); | |
| response.setStatus(401); | |
| endResponse(response, e.toString()); | |
| return; | |
| } | |
| response.setStatus(200); | |
| endResponse(response, "offering mapping deleted successfully"); | |
| } | |
| /** | |
| * The approach taken here is to map these REST calls into the same objects used | |
| * to implement the matching SOAP requests (e.g., AttachVolume). This is done by parsing | |
| * out the URL parameters and loading them into the relevant EC2XXX object(s). Once | |
| * the parameters are loaded the appropriate EC2Engine function is called to perform | |
| * the requested action. The result of the EC2Engine function is a standard | |
| * Amazon WSDL defined object (e.g., AttachVolumeResponse Java object). Finally the | |
| * serialize method is called on the returned response object to obtain the extected | |
| * response XML. | |
| */ | |
| private void attachVolume(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException { | |
| EC2Volume EC2request = new EC2Volume(); | |
| // -> all these parameters are required | |
| String[] volumeId = request.getParameterValues("VolumeId"); | |
| if (null != volumeId && 0 < volumeId.length) | |
| EC2request.setId(volumeId[0]); | |
| else { | |
| throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - VolumeId"); | |
| } | |
| String[] instanceId = request.getParameterValues("InstanceId"); | |
| if (null != instanceId && 0 < instanceId.length) | |
| EC2request.setInstanceId(instanceId[0]); | |
| else { | |
| throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - InstanceId"); | |
| } | |
| String[] device = request.getParameterValues("Device"); | |
| if (null != device && 0 < device.length) | |
| EC2request.setDevice(device[0]); | |
| else { | |
| throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - Device"); | |
| } | |
| // -> execute the request | |
| AttachVolumeResponse EC2response = EC2SoapServiceImpl.toAttachVolumeResponse(ServiceProvider.getInstance().getEC2Engine().attachVolume(EC2request)); | |
| serializeResponse(response, EC2response); | |
| } | |
| /** | |
| * The SOAP equivalent of this function appears to allow multiple permissions per request, yet | |
| * in the REST API documentation only one permission is allowed. | |
| */ | |
| private void revokeSecurityGroupIngress(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException { | |
| EC2AuthorizeRevokeSecurityGroup EC2request = new EC2AuthorizeRevokeSecurityGroup(); | |
| String[] groupName = request.getParameterValues("GroupName"); | |
| if (null != groupName && 0 < groupName.length) | |
| EC2request.setName(groupName[0]); | |
| else { | |
| throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - GroupName"); | |
| } | |
| // -> not clear how many parameters there are until we fail to get IpPermissions.n.IpProtocol | |
| int nCount = 1, mCount; | |
| do { | |
| EC2IpPermission perm = new EC2IpPermission(); | |
| String[] protocol = request.getParameterValues("IpPermissions." + nCount + ".IpProtocol"); | |
| if (null != protocol && 0 < protocol.length) | |
| perm.setProtocol(protocol[0]); | |
| else | |
| break; | |
| String[] fromPort = request.getParameterValues("IpPermissions." + nCount + ".FromPort"); | |
| if (null != fromPort && 0 < fromPort.length) { | |
| if (protocol[0].equalsIgnoreCase("icmp")) | |
| perm.setIcmpType(fromPort[0]); | |
| else | |
| perm.setFromPort(Integer.parseInt(fromPort[0])); | |
| } | |
| String[] toPort = request.getParameterValues("IpPermissions." + nCount + ".ToPort"); | |
| if (null != toPort && 0 < toPort.length) { | |
| if (protocol[0].equalsIgnoreCase("icmp")) | |
| perm.setIcmpCode(toPort[0]); | |
| else | |
| perm.setToPort(Integer.parseInt(toPort[0])); | |
| } | |
| // -> list: IpPermissions.n.IpRanges.m.CidrIp | |
| mCount = 1; | |
| do { | |
| String[] ranges = request.getParameterValues("IpPermissions." + nCount + ".IpRanges." + mCount + ".CidrIp"); | |
| if (null != ranges && 0 < ranges.length) | |
| perm.addIpRange(ranges[0]); | |
| else | |
| break; | |
| mCount++; | |
| } while (true); | |
| // -> list: IpPermissions.n.Groups.m.UserId and IpPermissions.n.Groups.m.GroupName | |
| mCount = 1; | |
| do { | |
| EC2SecurityGroup group = new EC2SecurityGroup(); | |
| String[] user = request.getParameterValues("IpPermissions." + nCount + ".Groups." + mCount + ".UserId"); | |
| if (null != user && 0 < user.length) | |
| group.setAccount(user[0]); | |
| else | |
| break; | |
| String[] name = request.getParameterValues("IpPermissions." + nCount + ".Groups." + mCount + ".GroupName"); | |
| if (null != name && 0 < name.length) | |
| group.setName(name[0]); | |
| else | |
| break; | |
| perm.addUser(group); | |
| mCount++; | |
| } while (true); | |
| // -> multiple IP permissions can be specified per group name | |
| EC2request.addIpPermission(perm); | |
| nCount++; | |
| } while (true); | |
| if (1 == nCount) { | |
| throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - IpPermissions"); | |
| } | |
| // -> execute the request | |
| RevokeSecurityGroupIngressResponse EC2response = | |
| EC2SoapServiceImpl.toRevokeSecurityGroupIngressResponse(ServiceProvider.getInstance().getEC2Engine().revokeSecurityGroup(EC2request)); | |
| serializeResponse(response, EC2response); | |
| } | |
| private void authorizeSecurityGroupIngress(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException { | |
| // -> parse the complicated paramters into our standard object | |
| EC2AuthorizeRevokeSecurityGroup EC2request = new EC2AuthorizeRevokeSecurityGroup(); | |
| String[] groupName = request.getParameterValues("GroupName"); | |
| if (null != groupName && 0 < groupName.length) | |
| EC2request.setName(groupName[0]); | |
| else { | |
| throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter 'Groupname'"); | |
| } | |
| // -> not clear how many parameters there are until we fail to get IpPermissions.n.IpProtocol | |
| int nCount = 1; | |
| do { | |
| EC2IpPermission perm = new EC2IpPermission(); | |
| String[] protocol = request.getParameterValues("IpPermissions." + nCount + ".IpProtocol"); | |
| if (null != protocol && 0 < protocol.length) | |
| perm.setProtocol(protocol[0]); | |
| else | |
| break; | |
| String[] fromPort = request.getParameterValues("IpPermissions." + nCount + ".FromPort"); | |
| if (null != fromPort && 0 < fromPort.length) { | |
| if (protocol[0].equalsIgnoreCase("icmp")) | |
| perm.setIcmpType(fromPort[0]); | |
| else | |
| perm.setFromPort(Integer.parseInt(fromPort[0])); | |
| } | |
| String[] toPort = request.getParameterValues("IpPermissions." + nCount + ".ToPort"); | |
| if (null != toPort && 0 < toPort.length) { | |
| if (protocol[0].equalsIgnoreCase("icmp")) | |
| perm.setIcmpCode(toPort[0]); | |
| else | |
| perm.setToPort(Integer.parseInt(toPort[0])); | |
| } | |
| // -> list: IpPermissions.n.IpRanges.m.CidrIp | |
| int mCount = 1; | |
| do { | |
| String[] ranges = request.getParameterValues("IpPermissions." + nCount + ".IpRanges." + mCount + ".CidrIp"); | |
| if (null != ranges && 0 < ranges.length) | |
| perm.addIpRange(ranges[0]); | |
| else | |
| break; | |
| mCount++; | |
| } while (true); | |
| // -> list: IpPermissions.n.Groups.m.UserId and IpPermissions.n.Groups.m.GroupName | |
| mCount = 1; | |
| do { | |
| String[] user = request.getParameterValues("IpPermissions." + nCount + ".Groups." + mCount + ".UserId"); | |
| if (null == user || 0 == user.length) | |
| break; | |
| String[] name = request.getParameterValues("IpPermissions." + nCount + ".Groups." + mCount + ".GroupName"); | |
| if (null == name || 0 == name.length) | |
| break; | |
| EC2SecurityGroup group = new EC2SecurityGroup(); | |
| group.setAccount(user[0]); | |
| group.setName(name[0]); | |
| perm.addUser(group); | |
| mCount++; | |
| } while (true); | |
| // -> multiple IP permissions can be specified per group name | |
| EC2request.addIpPermission(perm); | |
| nCount++; | |
| } while (true); | |
| if (1 == nCount) { | |
| throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - IpPermissions"); | |
| } | |
| // -> execute the request | |
| AuthorizeSecurityGroupIngressResponse EC2response = | |
| EC2SoapServiceImpl.toAuthorizeSecurityGroupIngressResponse(ServiceProvider.getInstance().getEC2Engine().authorizeSecurityGroup(EC2request)); | |
| serializeResponse(response, EC2response); | |
| } | |
| private void detachVolume(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException { | |
| EC2Volume EC2request = new EC2Volume(); | |
| String[] volumeId = request.getParameterValues("VolumeId"); | |
| if (null != volumeId && 0 < volumeId.length) | |
| EC2request.setId(volumeId[0]); | |
| else { | |
| throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter 'VolumeId'"); | |
| } | |
| String[] instanceId = request.getParameterValues("InstanceId"); | |
| if (null != instanceId && 0 < instanceId.length) | |
| EC2request.setInstanceId(instanceId[0]); | |
| String[] device = request.getParameterValues("Device"); | |
| if (null != device && 0 < device.length) | |
| EC2request.setDevice(device[0]); | |
| // -> execute the request | |
| DetachVolumeResponse EC2response = EC2SoapServiceImpl.toDetachVolumeResponse(ServiceProvider.getInstance().getEC2Engine().detachVolume(EC2request)); | |
| serializeResponse(response, EC2response); | |
| } | |
| private void deleteVolume(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException { | |
| EC2Volume EC2request = new EC2Volume(); | |
| String[] volumeId = request.getParameterValues("VolumeId"); | |
| if (null != volumeId && 0 < volumeId.length) | |
| EC2request.setId(volumeId[0]); | |
| else { | |
| throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - VolumeId"); | |
| } | |
| // -> execute the request | |
| DeleteVolumeResponse EC2response = EC2SoapServiceImpl.toDeleteVolumeResponse(ServiceProvider.getInstance().getEC2Engine().deleteVolume(EC2request)); | |
| serializeResponse(response, EC2response); | |
| } | |
| private void createVolume(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException { | |
| EC2CreateVolume EC2request = new EC2CreateVolume(); | |
| String[] zoneName = request.getParameterValues("AvailabilityZone"); | |
| if (null != zoneName && 0 < zoneName.length) | |
| EC2request.setZoneName(zoneName[0]); | |
| else { | |
| throw new EC2ServiceException(ClientError.MissingParamter, "Missing parameter - AvailabilityZone"); | |
| } | |
| String[] size = request.getParameterValues("Size"); | |
| String[] snapshotId = request.getParameterValues("SnapshotId"); | |
| boolean useSnapshot = false; | |
| boolean useSize = false; | |
| if (null != size && 0 < size.length) | |
| useSize = true; | |
| if (snapshotId != null && snapshotId.length != 0) | |
| useSnapshot = true; | |
| if (useSize && !useSnapshot) { | |
| EC2request.setSize(size[0]); | |
| } else if (useSnapshot && !useSize) { | |
| EC2request.setSnapshotId(snapshotId[0]); | |
| } else if (useSize && useSnapshot) { | |
| throw new EC2ServiceException(ClientError.InvalidParameterCombination, "Parameters 'Size' and 'SnapshotId' are mutually exclusive"); | |
| } else { | |
| throw new EC2ServiceException(ClientError.MissingParamter, "Parameter 'Size' or 'SnapshotId' has to be specified"); | |
| } | |
| // -> execute the request | |
| CreateVolumeResponse EC2response = EC2SoapServiceImpl.toCreateVolumeResponse(ServiceProvider.getInstance().getEC2Engine().createVolume(EC2request)); | |
| serializeResponse(response, EC2response); | |
| } | |
| private void createSecurityGroup(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException { | |
| String groupName, groupDescription = null; | |
| String[] name = request.getParameterValues("GroupName"); | |
| if (null != name && 0 < name.length) | |
| groupName = name[0]; | |
| else { | |
| throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - GroupName"); | |
| } | |
| String[] desc = request.getParameterValues("GroupDescription"); | |
| if (null != desc && 0 < desc.length) | |
| groupDescription = desc[0]; | |
| else { | |
| throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - GroupDescription"); | |
| } | |
| // -> execute the request | |
| CreateSecurityGroupResponse EC2response = | |
| EC2SoapServiceImpl.toCreateSecurityGroupResponse(ServiceProvider.getInstance().getEC2Engine().createSecurityGroup(groupName, groupDescription)); | |
| serializeResponse(response, EC2response); | |
| } | |
| private void deleteSecurityGroup(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException { | |
| String groupName = null; | |
| String[] name = request.getParameterValues("GroupName"); | |
| if (null != name && 0 < name.length) | |
| groupName = name[0]; | |
| else { | |
| throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - GroupName"); | |
| } | |
| // -> execute the request | |
| DeleteSecurityGroupResponse EC2response = | |
| EC2SoapServiceImpl.toDeleteSecurityGroupResponse(ServiceProvider.getInstance().getEC2Engine().deleteSecurityGroup(groupName)); | |
| serializeResponse(response, EC2response); | |
| } | |
| private void deleteSnapshot(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException { | |
| String snapshotId = null; | |
| String[] snapSet = request.getParameterValues("SnapshotId"); | |
| if (null != snapSet && 0 < snapSet.length) | |
| snapshotId = snapSet[0]; | |
| else { | |
| throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - SnapshotId"); | |
| } | |
| // -> execute the request | |
| DeleteSnapshotResponse EC2response = EC2SoapServiceImpl.toDeleteSnapshotResponse(ServiceProvider.getInstance().getEC2Engine().deleteSnapshot(snapshotId)); | |
| serializeResponse(response, EC2response); | |
| } | |
| private void createSnapshot(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException { | |
| String volumeId = null; | |
| String[] volSet = request.getParameterValues("VolumeId"); | |
| if (null != volSet && 0 < volSet.length) | |
| volumeId = volSet[0]; | |
| else { | |
| throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - VolumeId"); | |
| } | |
| // -> execute the request | |
| EC2Engine engine = ServiceProvider.getInstance().getEC2Engine(); | |
| CreateSnapshotResponse EC2response = EC2SoapServiceImpl.toCreateSnapshotResponse(engine.createSnapshot(volumeId), engine); | |
| serializeResponse(response, EC2response); | |
| } | |
| private void deregisterImage(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException { | |
| EC2Image image = new EC2Image(); | |
| String[] imageId = request.getParameterValues("ImageId"); | |
| if (null != imageId && 0 < imageId.length) | |
| image.setId(imageId[0]); | |
| else { | |
| throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - ImageId"); | |
| } | |
| // -> execute the request | |
| DeregisterImageResponse EC2response = EC2SoapServiceImpl.toDeregisterImageResponse(ServiceProvider.getInstance().getEC2Engine().deregisterImage(image)); | |
| serializeResponse(response, EC2response); | |
| } | |
| private void createImage(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException { | |
| EC2CreateImage EC2request = new EC2CreateImage(); | |
| String[] instanceId = request.getParameterValues("InstanceId"); | |
| if (null != instanceId && 0 < instanceId.length) | |
| EC2request.setInstanceId(instanceId[0]); | |
| else { | |
| throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - InstanceId"); | |
| } | |
| String[] name = request.getParameterValues("Name"); | |
| if (null != name && 0 < name.length) | |
| EC2request.setName(name[0]); | |
| else { | |
| throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - Name"); | |
| } | |
| String[] description = request.getParameterValues("Description"); | |
| if (null != description && 0 < description.length) { | |
| if (description[0].length() > 255) | |
| throw new EC2ServiceException(ClientError.InvalidParameterValue, "Length of the value of parameter Description should be less than 255"); | |
| EC2request.setDescription(description[0]); | |
| } | |
| // -> execute the request | |
| CreateImageResponse EC2response = EC2SoapServiceImpl.toCreateImageResponse(ServiceProvider.getInstance().getEC2Engine().createImage(EC2request)); | |
| serializeResponse(response, EC2response); | |
| } | |
| private void registerImage(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException { | |
| EC2RegisterImage EC2request = new EC2RegisterImage(); | |
| String[] location = request.getParameterValues("ImageLocation"); | |
| if (null != location && 0 < location.length) | |
| EC2request.setLocation(location[0]); | |
| else { | |
| throw new EC2ServiceException(ClientError.MissingParamter, "Missing parameter - ImageLocation"); | |
| } | |
| String[] cloudRedfined = request.getParameterValues("Architecture"); | |
| if (null != cloudRedfined && 0 < cloudRedfined.length) | |
| EC2request.setArchitecture(cloudRedfined[0]); | |
| else { | |
| throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - Architecture"); | |
| } | |
| String[] name = request.getParameterValues("Name"); | |
| if (null != name && 0 < name.length) | |
| EC2request.setName(name[0]); | |
| else { | |
| throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - Name"); | |
| } | |
| String[] description = request.getParameterValues("Description"); | |
| if (null != description && 0 < description.length) | |
| EC2request.setDescription(description[0]); | |
| // -> execute the request | |
| RegisterImageResponse EC2response = EC2SoapServiceImpl.toRegisterImageResponse(ServiceProvider.getInstance().getEC2Engine().registerImage(EC2request)); | |
| serializeResponse(response, EC2response); | |
| } | |
| private void modifyImageAttribute(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException { | |
| EC2ModifyImageAttribute ec2request = new EC2ModifyImageAttribute(); | |
| String[] imageId = request.getParameterValues("ImageId"); | |
| if (imageId != null && imageId.length > 0) | |
| ec2request.setImageId(imageId[0]); | |
| else { | |
| throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - ImageId"); | |
| } | |
| String[] description = request.getParameterValues("Description.Value"); | |
| if (description != null && description.length > 0) { | |
| ec2request.setAttribute(ImageAttribute.description); | |
| ec2request.setDescription(description[0]); | |
| } else { | |
| //add all launch permissions to ec2request | |
| ec2request = addLaunchPermImageAttribute(request, ec2request); | |
| if (ec2request.getLaunchPermissionSet().length > 0) | |
| ec2request.setAttribute(ImageAttribute.launchPermission); | |
| else { | |
| throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - Description/LaunchPermission should be provided"); | |
| } | |
| } | |
| // -> execute the request | |
| ModifyImageAttributeResponse EC2response = | |
| EC2SoapServiceImpl.toModifyImageAttributeResponse(ServiceProvider.getInstance().getEC2Engine().modifyImageAttribute(ec2request)); | |
| serializeResponse(response, EC2response); | |
| } | |
| private EC2ModifyImageAttribute addLaunchPermImageAttribute(HttpServletRequest request, EC2ModifyImageAttribute ec2request) { | |
| String[] users = {".UserId", ".Group"}; | |
| String[] operations = {"LaunchPermission.Add.", "LaunchPermission.Remove."}; | |
| int nCount = 1; | |
| for (int i = 0; i < 2; i++) { | |
| for (int j = 0; j < 2; j++) { | |
| List<String> launchPermissionList = new ArrayList<String>(); | |
| do { | |
| String[] launchPermissionAddGroup = request.getParameterValues(operations[j] + nCount + users[i]); | |
| if (launchPermissionAddGroup != null && launchPermissionAddGroup.length > 0) | |
| launchPermissionList.add(launchPermissionAddGroup[0]); | |
| else | |
| break; | |
| nCount++; | |
| } while (true); | |
| if (nCount != 1) { | |
| EC2ImageLaunchPermission ec2LaunchPermission = new EC2ImageLaunchPermission(); | |
| if (operations[j].contains("Add")) | |
| ec2LaunchPermission.setLaunchPermOp(EC2ImageLaunchPermission.Operation.add); | |
| else | |
| ec2LaunchPermission.setLaunchPermOp(EC2ImageLaunchPermission.Operation.remove); | |
| for (String launchPerm : launchPermissionList) { | |
| ec2LaunchPermission.addLaunchPermission(launchPerm); | |
| } | |
| ec2request.addLaunchPermission(ec2LaunchPermission); | |
| nCount = 1; | |
| } | |
| } | |
| } | |
| return ec2request; | |
| } | |
| private void resetImageAttribute(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException { | |
| EC2ModifyImageAttribute ec2request = new EC2ModifyImageAttribute(); | |
| String[] imageId = request.getParameterValues("ImageId"); | |
| if (imageId != null && imageId.length > 0) | |
| ec2request.setImageId(imageId[0]); | |
| else { | |
| throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - ImageId"); | |
| } | |
| String[] attribute = request.getParameterValues("Attribute"); | |
| if (attribute != null && attribute.length > 0) { | |
| if (attribute[0].equalsIgnoreCase("launchPermission")) | |
| ec2request.setAttribute(ImageAttribute.launchPermission); | |
| else { | |
| throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - Description/LaunchPermission should be provided"); | |
| } | |
| } else { | |
| throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - Attribute"); | |
| } | |
| EC2ImageLaunchPermission launchPermission = new EC2ImageLaunchPermission(); | |
| launchPermission.setLaunchPermOp(EC2ImageLaunchPermission.Operation.reset); | |
| ec2request.addLaunchPermission(launchPermission); | |
| // -> execute the request | |
| ResetImageAttributeResponse EC2response = | |
| EC2SoapServiceImpl.toResetImageAttributeResponse(ServiceProvider.getInstance().getEC2Engine().modifyImageAttribute(ec2request)); | |
| serializeResponse(response, EC2response); | |
| } | |
| private void runInstances(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException { | |
| EC2RunInstances EC2request = new EC2RunInstances(); | |
| // -> so in the Amazon docs for this REST call there is no userData even though there is in the SOAP docs | |
| String[] imageId = request.getParameterValues("ImageId"); | |
| if (null != imageId && 0 < imageId.length) | |
| EC2request.setTemplateId(imageId[0]); | |
| else { | |
| throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - ImageId"); | |
| } | |
| String[] minCount = request.getParameterValues("MinCount"); | |
| if (minCount == null || minCount.length < 1) { | |
| throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - MinCount"); | |
| } else if (Integer.parseInt(minCount[0]) < 1) { | |
| throw new EC2ServiceException(ClientError.InvalidParameterValue, "Value of parameter MinCount should be greater than 0"); | |
| } else { | |
| EC2request.setMinCount(Integer.parseInt(minCount[0])); | |
| } | |
| String[] maxCount = request.getParameterValues("MaxCount"); | |
| if (maxCount == null || maxCount.length < 1) { | |
| throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - MaxCount"); | |
| } else if (Integer.parseInt(maxCount[0]) < 1) { | |
| throw new EC2ServiceException(ClientError.InvalidParameterValue, "Value of parameter MaxCount should be greater than 0"); | |
| } else { | |
| EC2request.setMaxCount(Integer.parseInt(maxCount[0])); | |
| } | |
| String[] instanceType = request.getParameterValues("InstanceType"); | |
| if (null != instanceType && 0 < instanceType.length) | |
| EC2request.setInstanceType(instanceType[0]); | |
| String[] zoneName = request.getParameterValues("Placement.AvailabilityZone"); | |
| if (null != zoneName && 0 < zoneName.length) | |
| EC2request.setZoneName(zoneName[0]); | |
| String[] size = request.getParameterValues("size"); | |
| if (size != null) { | |
| EC2request.setSize(Integer.valueOf(size[0])); | |
| } | |
| String[] keyName = request.getParameterValues("KeyName"); | |
| if (keyName != null) { | |
| EC2request.setKeyName(keyName[0]); | |
| } | |
| String[] userData = request.getParameterValues("UserData"); | |
| if (userData != null) { | |
| EC2request.setUserData(userData[0]); | |
| } | |
| Enumeration<?> names = request.getParameterNames(); | |
| while (names.hasMoreElements()) { | |
| String key = (String)names.nextElement(); | |
| if (key.startsWith("SecurityGroup")) { | |
| String[] value = request.getParameterValues(key); | |
| if (null != value && 0 < value.length) { | |
| if (key.startsWith("SecurityGroupId")) | |
| EC2request.addSecuritGroupId(value[0]); | |
| else | |
| EC2request.addSecuritGroupName(value[0]); | |
| } | |
| } | |
| } | |
| // -> execute the request | |
| EC2Engine engine = ServiceProvider.getInstance().getEC2Engine(); | |
| RunInstancesResponse EC2response = EC2SoapServiceImpl.toRunInstancesResponse(engine.runInstances(EC2request), engine); | |
| serializeResponse(response, EC2response); | |
| } | |
| private void rebootInstances(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException { | |
| EC2RebootInstances EC2request = new EC2RebootInstances(); | |
| int count = 0; | |
| // -> load in all the "InstanceId.n" parameters if any | |
| Enumeration<?> names = request.getParameterNames(); | |
| while (names.hasMoreElements()) { | |
| String key = (String)names.nextElement(); | |
| if (key.startsWith("InstanceId")) { | |
| String[] value = request.getParameterValues(key); | |
| if (null != value && 0 < value.length) { | |
| EC2request.addInstanceId(value[0]); | |
| count++; | |
| } | |
| } | |
| } | |
| if (0 == count) { | |
| throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - InstanceId"); | |
| } | |
| // -> execute the request | |
| RebootInstancesResponse EC2response = EC2SoapServiceImpl.toRebootInstancesResponse(ServiceProvider.getInstance().getEC2Engine().rebootInstances(EC2request)); | |
| serializeResponse(response, EC2response); | |
| } | |
| private void startInstances(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException { | |
| EC2StartInstances EC2request = new EC2StartInstances(); | |
| int count = 0; | |
| // -> load in all the "InstanceId.n" parameters if any | |
| Enumeration<?> names = request.getParameterNames(); | |
| while (names.hasMoreElements()) { | |
| String key = (String)names.nextElement(); | |
| if (key.startsWith("InstanceId")) { | |
| String[] value = request.getParameterValues(key); | |
| if (null != value && 0 < value.length) { | |
| EC2request.addInstanceId(value[0]); | |
| count++; | |
| } | |
| } | |
| } | |
| if (0 == count) { | |
| throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - InstanceId"); | |
| } | |
| // -> execute the request | |
| StartInstancesResponse EC2response = EC2SoapServiceImpl.toStartInstancesResponse(ServiceProvider.getInstance().getEC2Engine().startInstances(EC2request)); | |
| serializeResponse(response, EC2response); | |
| } | |
| private void stopInstances(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException { | |
| EC2StopInstances EC2request = new EC2StopInstances(); | |
| int count = 0; | |
| // -> load in all the "InstanceId.n" parameters if any | |
| Enumeration<?> names = request.getParameterNames(); | |
| while (names.hasMoreElements()) { | |
| String key = (String)names.nextElement(); | |
| if (key.startsWith("InstanceId")) { | |
| String[] value = request.getParameterValues(key); | |
| if (null != value && 0 < value.length) { | |
| EC2request.addInstanceId(value[0]); | |
| count++; | |
| } | |
| } | |
| } | |
| if (0 == count) { | |
| throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - InstanceId"); | |
| } | |
| String[] force = request.getParameterValues("Force"); | |
| if (force != null) { | |
| EC2request.setForce(Boolean.parseBoolean(force[0])); | |
| } | |
| // -> execute the request | |
| StopInstancesResponse EC2response = EC2SoapServiceImpl.toStopInstancesResponse(ServiceProvider.getInstance().getEC2Engine().stopInstances(EC2request)); | |
| serializeResponse(response, EC2response); | |
| } | |
| private void terminateInstances(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException { | |
| EC2StopInstances EC2request = new EC2StopInstances(); | |
| int count = 0; | |
| // -> load in all the "InstanceId.n" parameters if any | |
| Enumeration<?> names = request.getParameterNames(); | |
| while (names.hasMoreElements()) { | |
| String key = (String)names.nextElement(); | |
| if (key.startsWith("InstanceId")) { | |
| String[] value = request.getParameterValues(key); | |
| if (null != value && 0 < value.length) { | |
| EC2request.addInstanceId(value[0]); | |
| count++; | |
| } | |
| } | |
| } | |
| if (0 == count) { | |
| throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - InstanceId"); | |
| } | |
| // -> execute the request | |
| EC2request.setDestroyInstances(true); | |
| TerminateInstancesResponse EC2response = EC2SoapServiceImpl.toTermInstancesResponse(ServiceProvider.getInstance().getEC2Engine().stopInstances(EC2request)); | |
| serializeResponse(response, EC2response); | |
| } | |
| /** | |
| * We are reusing the SOAP code to process this request. We then use Axiom to serialize the | |
| * resulting EC2 Amazon object into XML to return to the client. | |
| */ | |
| private void describeAvailabilityZones(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException { | |
| EC2DescribeAvailabilityZones EC2request = new EC2DescribeAvailabilityZones(); | |
| // -> load in all the "ZoneName.n" parameters if any | |
| Enumeration<?> names = request.getParameterNames(); | |
| while (names.hasMoreElements()) { | |
| String key = (String)names.nextElement(); | |
| if (key.startsWith("ZoneName")) { | |
| String[] value = request.getParameterValues(key); | |
| if (null != value && 0 < value.length) | |
| EC2request.addZone(value[0]); | |
| } | |
| } | |
| // add filters | |
| EC2Filter[] filterSet = extractFilters(request); | |
| if (filterSet != null) { | |
| EC2AvailabilityZonesFilterSet afs = new EC2AvailabilityZonesFilterSet(); | |
| for (int i = 0; i < filterSet.length; i++) { | |
| afs.addFilter(filterSet[i]); | |
| } | |
| EC2request.setFilterSet(afs); | |
| } | |
| // -> execute the request | |
| DescribeAvailabilityZonesResponse EC2response = | |
| EC2SoapServiceImpl.toDescribeAvailabilityZonesResponse(ServiceProvider.getInstance().getEC2Engine().describeAvailabilityZones(EC2request)); | |
| serializeResponse(response, EC2response); | |
| } | |
| private void describeImages(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException { | |
| EC2DescribeImages EC2request = new EC2DescribeImages(); | |
| // -> load in all the "ImageId.n" parameters if any, and ignore all other parameters | |
| Enumeration<?> names = request.getParameterNames(); | |
| while (names.hasMoreElements()) { | |
| String key = (String)names.nextElement(); | |
| if (key.startsWith("ImageId")) { | |
| String[] value = request.getParameterValues(key); | |
| if (null != value && 0 < value.length) | |
| EC2request.addImageSet(value[0]); | |
| } | |
| } | |
| // add filters | |
| EC2Filter[] filterSet = extractFilters(request); | |
| if (filterSet != null) { | |
| EC2ImageFilterSet ifs = new EC2ImageFilterSet(); | |
| for (int i = 0; i < filterSet.length; i++) { | |
| ifs.addFilter(filterSet[i]); | |
| } | |
| EC2request.setFilterSet(ifs); | |
| } | |
| // -> execute the request | |
| EC2Engine engine = ServiceProvider.getInstance().getEC2Engine(); | |
| DescribeImagesResponse EC2response = EC2SoapServiceImpl.toDescribeImagesResponse(engine.describeImages(EC2request)); | |
| serializeResponse(response, EC2response); | |
| } | |
| private void describeImageAttribute(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException { | |
| EC2DescribeImageAttribute ec2request = new EC2DescribeImageAttribute(); | |
| String[] imageId = request.getParameterValues("ImageId"); | |
| if (imageId != null && imageId.length > 0) | |
| ec2request.setImageId(imageId[0]); | |
| else { | |
| throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - ImageId"); | |
| } | |
| String[] attribute = request.getParameterValues("Attribute"); | |
| if (attribute != null && attribute.length > 0) { | |
| if (attribute[0].equalsIgnoreCase("description")) | |
| ec2request.setAttribute(ImageAttribute.description); | |
| else if (attribute[0].equalsIgnoreCase("launchPermission")) | |
| ec2request.setAttribute(ImageAttribute.launchPermission); | |
| else { | |
| throw new EC2ServiceException(ClientError.InvalidParameterValue, "Only values supported for paramter Attribute are - Description/LaunchPermission"); | |
| } | |
| } else { | |
| throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - Attribute"); | |
| } | |
| DescribeImageAttributeResponse EC2response = | |
| EC2SoapServiceImpl.toDescribeImageAttributeResponse(ServiceProvider.getInstance().getEC2Engine().describeImageAttribute(ec2request)); | |
| serializeResponse(response, EC2response); | |
| } | |
| private void describeInstances(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException { | |
| EC2DescribeInstances EC2request = new EC2DescribeInstances(); | |
| // -> load in all the "InstanceId.n" parameters if any | |
| Enumeration<?> names = request.getParameterNames(); | |
| while (names.hasMoreElements()) { | |
| String key = (String)names.nextElement(); | |
| if (key.startsWith("InstanceId")) { | |
| String[] value = request.getParameterValues(key); | |
| if (null != value && 0 < value.length) | |
| EC2request.addInstanceId(value[0]); | |
| } | |
| } | |
| // -> are there any filters with this request? | |
| EC2Filter[] filterSet = extractFilters(request); | |
| if (null != filterSet) { | |
| EC2InstanceFilterSet ifs = new EC2InstanceFilterSet(); | |
| for (int i = 0; i < filterSet.length; i++) | |
| ifs.addFilter(filterSet[i]); | |
| EC2request.setFilterSet(ifs); | |
| } | |
| // -> execute the request | |
| EC2Engine engine = ServiceProvider.getInstance().getEC2Engine(); | |
| DescribeInstancesResponse EC2response = EC2SoapServiceImpl.toDescribeInstancesResponse(engine.describeInstances(EC2request), engine); | |
| serializeResponse(response, EC2response); | |
| } | |
| private void describeAddresses(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException { | |
| EC2DescribeAddresses ec2Request = new EC2DescribeAddresses(); | |
| // -> load in all the "PublicIp.n" parameters if any | |
| Enumeration<?> names = request.getParameterNames(); | |
| while (names.hasMoreElements()) { | |
| String key = (String)names.nextElement(); | |
| if (key.startsWith("PublicIp")) { | |
| String[] value = request.getParameterValues(key); | |
| if (null != value && 0 < value.length) | |
| ec2Request.addPublicIp(value[0]); | |
| } | |
| } | |
| // add filters | |
| EC2Filter[] filterSet = extractFilters(request); | |
| if (filterSet != null) { | |
| EC2AddressFilterSet afs = new EC2AddressFilterSet(); | |
| for (int i = 0; i < filterSet.length; i++) | |
| afs.addFilter(filterSet[i]); | |
| ec2Request.setFilterSet(afs); | |
| } | |
| // -> execute the request | |
| EC2Engine engine = ServiceProvider.getInstance().getEC2Engine(); | |
| serializeResponse(response, EC2SoapServiceImpl.toDescribeAddressesResponse(engine.describeAddresses(ec2Request))); | |
| } | |
| private void allocateAddress(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException { | |
| EC2Engine engine = ServiceProvider.getInstance().getEC2Engine(); | |
| AllocateAddressResponse ec2Response = EC2SoapServiceImpl.toAllocateAddressResponse(engine.allocateAddress()); | |
| serializeResponse(response, ec2Response); | |
| } | |
| private void releaseAddress(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException { | |
| EC2Engine engine = ServiceProvider.getInstance().getEC2Engine(); | |
| String publicIp = request.getParameter("PublicIp"); | |
| if (publicIp == null) { | |
| throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - PublicIp"); | |
| } | |
| EC2ReleaseAddress ec2Request = new EC2ReleaseAddress(); | |
| if (ec2Request != null) { | |
| ec2Request.setPublicIp(publicIp); | |
| } | |
| ReleaseAddressResponse EC2Response = EC2SoapServiceImpl.toReleaseAddressResponse(engine.releaseAddress(ec2Request)); | |
| serializeResponse(response, EC2Response); | |
| } | |
| private void associateAddress(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException { | |
| EC2Engine engine = ServiceProvider.getInstance().getEC2Engine(); | |
| String publicIp = request.getParameter("PublicIp"); | |
| if (null == publicIp) { | |
| throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - PublicIp"); | |
| } | |
| String instanceId = request.getParameter("InstanceId"); | |
| if (null == instanceId) { | |
| throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - InstanceId"); | |
| } | |
| EC2AssociateAddress ec2Request = new EC2AssociateAddress(); | |
| if (ec2Request != null) { | |
| ec2Request.setInstanceId(instanceId); | |
| ec2Request.setPublicIp(publicIp); | |
| } | |
| AssociateAddressResponse ec2Response = EC2SoapServiceImpl.toAssociateAddressResponse(engine.associateAddress(ec2Request)); | |
| serializeResponse(response, ec2Response); | |
| } | |
| private void disassociateAddress(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException { | |
| EC2Engine engine = ServiceProvider.getInstance().getEC2Engine(); | |
| String publicIp = request.getParameter("PublicIp"); | |
| if (null == publicIp) { | |
| throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - PublicIp"); | |
| } | |
| EC2DisassociateAddress ec2Request = new EC2DisassociateAddress(); | |
| if (ec2Request != null) { | |
| ec2Request.setPublicIp(publicIp); | |
| } | |
| DisassociateAddressResponse ec2Response = EC2SoapServiceImpl.toDisassociateAddressResponse(engine.disassociateAddress(ec2Request)); | |
| serializeResponse(response, ec2Response); | |
| } | |
| private void describeSecurityGroups(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException { | |
| EC2DescribeSecurityGroups EC2request = new EC2DescribeSecurityGroups(); | |
| // -> load in all the "GroupName.n" parameters if any | |
| Enumeration<?> names = request.getParameterNames(); | |
| while (names.hasMoreElements()) { | |
| String key = (String)names.nextElement(); | |
| if (key.startsWith("GroupName")) { | |
| String[] value = request.getParameterValues(key); | |
| if (null != value && 0 < value.length) | |
| EC2request.addGroupName(value[0]); | |
| } | |
| } | |
| // -> are there any filters with this request? | |
| EC2Filter[] filterSet = extractFilters(request); | |
| if (null != filterSet) { | |
| EC2GroupFilterSet gfs = new EC2GroupFilterSet(); | |
| for (EC2Filter filter : filterSet) | |
| gfs.addFilter(filter); | |
| EC2request.setFilterSet(gfs); | |
| } | |
| // -> execute the request | |
| EC2Engine engine = ServiceProvider.getInstance().getEC2Engine(); | |
| DescribeSecurityGroupsResponse EC2response = EC2SoapServiceImpl.toDescribeSecurityGroupsResponse(engine.describeSecurityGroups(EC2request)); | |
| serializeResponse(response, EC2response); | |
| } | |
| private void describeInstanceAttribute(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException { | |
| EC2DescribeInstances EC2request = new EC2DescribeInstances(); | |
| String[] instanceId = request.getParameterValues("InstanceId"); | |
| if (instanceId != null && instanceId.length > 0) | |
| EC2request.addInstanceId(instanceId[0]); | |
| else | |
| throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - InstanceId"); | |
| String[] attribute = request.getParameterValues("Attribute"); | |
| if (attribute != null && attribute.length > 0) { | |
| if (!attribute[0].equalsIgnoreCase("instanceType")) { | |
| throw new EC2ServiceException(ClientError.InvalidParameterValue, "Only value supported for paramter Attribute is 'instanceType'"); | |
| } | |
| } else { | |
| throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - Attribute"); | |
| } | |
| // -> execute the request | |
| DescribeInstanceAttributeResponse EC2response = | |
| EC2SoapServiceImpl.toDescribeInstanceAttributeResponse(ServiceProvider.getInstance().getEC2Engine().describeInstances(EC2request)); | |
| serializeResponse(response, EC2response); | |
| } | |
| private void modifyInstanceAttribute(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException { | |
| EC2ModifyInstanceAttribute ec2Request = new EC2ModifyInstanceAttribute(); | |
| String[] instanceId = request.getParameterValues("InstanceId"); | |
| if (instanceId != null && instanceId.length > 0) | |
| ec2Request.setInstanceId(instanceId[0]); | |
| else { | |
| throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - InstanceId"); | |
| } | |
| String[] instanceType = request.getParameterValues("InstanceType.Value"); | |
| String[] userData = request.getParameterValues("UserData.Value"); | |
| if (instanceType != null && userData != null) { | |
| throw new EC2ServiceException(ClientError.InvalidParameterCombination, "Only one attribute can be" + " specified at a time"); | |
| } | |
| if (instanceType != null && instanceType.length > 0) { | |
| ec2Request.setInstanceType(instanceType[0]); | |
| } else if (userData != null && userData.length > 0) { | |
| ec2Request.setUserData(userData[0]); | |
| } else { | |
| throw new EC2ServiceException(ClientError.MissingParamter, "Missing parameter - InstanceType/UserData should be provided"); | |
| } | |
| // -> execute the request | |
| ModifyInstanceAttributeResponse EC2response = | |
| EC2SoapServiceImpl.toModifyInstanceAttributeResponse(ServiceProvider.getInstance().getEC2Engine().modifyInstanceAttribute(ec2Request)); | |
| serializeResponse(response, EC2response); | |
| } | |
| private void describeSnapshots(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException { | |
| EC2DescribeSnapshots EC2request = new EC2DescribeSnapshots(); | |
| // -> load in all the "SnapshotId.n" parameters if any, and ignore any other parameters | |
| Enumeration<?> names = request.getParameterNames(); | |
| while (names.hasMoreElements()) { | |
| String key = (String)names.nextElement(); | |
| if (key.startsWith("SnapshotId")) { | |
| String[] value = request.getParameterValues(key); | |
| if (null != value && 0 < value.length) | |
| EC2request.addSnapshotId(value[0]); | |
| } | |
| } | |
| // -> are there any filters with this request? | |
| EC2Filter[] filterSet = extractFilters(request); | |
| if (null != filterSet) { | |
| EC2SnapshotFilterSet sfs = new EC2SnapshotFilterSet(); | |
| for (int i = 0; i < filterSet.length; i++) | |
| sfs.addFilter(filterSet[i]); | |
| EC2request.setFilterSet(sfs); | |
| } | |
| // -> execute the request | |
| EC2Engine engine = ServiceProvider.getInstance().getEC2Engine(); | |
| DescribeSnapshotsResponse EC2response = EC2SoapServiceImpl.toDescribeSnapshotsResponse(engine.describeSnapshots(EC2request)); | |
| serializeResponse(response, EC2response); | |
| } | |
| private void describeVolumes(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException { | |
| EC2DescribeVolumes EC2request = new EC2DescribeVolumes(); | |
| // -> load in all the "VolumeId.n" parameters if any | |
| Enumeration<?> names = request.getParameterNames(); | |
| while (names.hasMoreElements()) { | |
| String key = (String)names.nextElement(); | |
| if (key.startsWith("VolumeId")) { | |
| String[] value = request.getParameterValues(key); | |
| if (null != value && 0 < value.length) | |
| EC2request.addVolumeId(value[0]); | |
| } | |
| } | |
| // -> are there any filters with this request? | |
| EC2Filter[] filterSet = extractFilters(request); | |
| if (null != filterSet) { | |
| EC2VolumeFilterSet vfs = new EC2VolumeFilterSet(); | |
| for (int i = 0; i < filterSet.length; i++) | |
| vfs.addFilter(filterSet[i]); | |
| EC2request.setFilterSet(vfs); | |
| } | |
| // -> execute the request | |
| EC2Engine engine = ServiceProvider.getInstance().getEC2Engine(); | |
| DescribeVolumesResponse EC2response = | |
| EC2SoapServiceImpl.toDescribeVolumesResponse(ServiceProvider.getInstance().getEC2Engine().describeVolumes(EC2request), engine); | |
| serializeResponse(response, EC2response); | |
| } | |
| /** | |
| * Example of how the filters are defined in a REST request: | |
| * https://<server>/?Action=DescribeVolumes | |
| * &Filter.1.Name=attachment.instance-id | |
| * &Filter.1.Value.1=i-1a2b3c4d | |
| * &Filter.2.Name=attachment.delete-on-termination | |
| * &Filter.2.Value.1=true | |
| * | |
| * @param request | |
| * @return List<EC2Filter> | |
| */ | |
| private EC2Filter[] extractFilters(HttpServletRequest request) { | |
| String filterName = null; | |
| String value = null; | |
| EC2Filter nextFilter = null; | |
| boolean timeFilter = false; | |
| int filterCount = 1; | |
| int valueCount = 1; | |
| List<EC2Filter> filterSet = new ArrayList<EC2Filter>(); | |
| do { | |
| filterName = request.getParameter("Filter." + filterCount + ".Name"); | |
| if (null != filterName) { | |
| nextFilter = new EC2Filter(); | |
| nextFilter.setName(filterName); | |
| timeFilter = (filterName.equalsIgnoreCase("attachment.attach-time") || filterName.equalsIgnoreCase("create-time")); | |
| valueCount = 1; | |
| do { | |
| value = request.getParameter("Filter." + filterCount + ".Value." + valueCount); | |
| if (null != value) { | |
| // -> time values are not encoded as regexes | |
| if (timeFilter) | |
| nextFilter.addValue(value); | |
| else | |
| nextFilter.addValueEncoded(value); | |
| valueCount++; | |
| } | |
| } while (null != value); | |
| filterSet.add(nextFilter); | |
| filterCount++; | |
| } | |
| } while (null != filterName); | |
| if (1 == filterCount) | |
| return null; | |
| else | |
| return filterSet.toArray(new EC2Filter[0]); | |
| } | |
| private void describeKeyPairs(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException { | |
| EC2DescribeKeyPairs ec2Request = new EC2DescribeKeyPairs(); | |
| Enumeration<?> names = request.getParameterNames(); | |
| while (names.hasMoreElements()) { | |
| String key = (String)names.nextElement(); | |
| if (key.startsWith("KeyName")) { | |
| String[] value = request.getParameterValues(key); | |
| if (null != value && 0 < value.length) | |
| ec2Request.addKeyName(value[0]); | |
| } | |
| } | |
| EC2Filter[] filterSet = extractFilters(request); | |
| if (null != filterSet) { | |
| EC2KeyPairFilterSet vfs = new EC2KeyPairFilterSet(); | |
| for (EC2Filter filter : filterSet) { | |
| vfs.addFilter(filter); | |
| } | |
| ec2Request.setKeyFilterSet(vfs); | |
| } | |
| DescribeKeyPairsResponse EC2Response = EC2SoapServiceImpl.toDescribeKeyPairs(ServiceProvider.getInstance().getEC2Engine().describeKeyPairs(ec2Request)); | |
| serializeResponse(response, EC2Response); | |
| } | |
| private void importKeyPair(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException { | |
| String keyName = request.getParameter("KeyName"); | |
| if (keyName == null) { | |
| throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - KeyName"); | |
| } | |
| String publicKeyMaterial = request.getParameter("PublicKeyMaterial"); | |
| if (publicKeyMaterial == null) { | |
| throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - PublicKeyMaterial"); | |
| } | |
| if (!publicKeyMaterial.contains(" ")) | |
| publicKeyMaterial = new String(Base64.decodeBase64(publicKeyMaterial.getBytes())); | |
| EC2ImportKeyPair ec2Request = new EC2ImportKeyPair(); | |
| if (ec2Request != null) { | |
| ec2Request.setKeyName(request.getParameter("KeyName")); | |
| ec2Request.setPublicKeyMaterial(request.getParameter("PublicKeyMaterial")); | |
| } | |
| ImportKeyPairResponse EC2Response = EC2SoapServiceImpl.toImportKeyPair(ServiceProvider.getInstance().getEC2Engine().importKeyPair(ec2Request)); | |
| serializeResponse(response, EC2Response); | |
| } | |
| private void createKeyPair(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException { | |
| String keyName = request.getParameter("KeyName"); | |
| if (keyName == null) { | |
| throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - KeyName"); | |
| } | |
| EC2CreateKeyPair ec2Request = new EC2CreateKeyPair(); | |
| if (ec2Request != null) { | |
| ec2Request.setKeyName(keyName); | |
| } | |
| CreateKeyPairResponse EC2Response = EC2SoapServiceImpl.toCreateKeyPair(ServiceProvider.getInstance().getEC2Engine().createKeyPair(ec2Request)); | |
| serializeResponse(response, EC2Response); | |
| } | |
| private void deleteKeyPair(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException { | |
| String keyName = request.getParameter("KeyName"); | |
| if (keyName == null) { | |
| throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - KeyName"); | |
| } | |
| EC2DeleteKeyPair ec2Request = new EC2DeleteKeyPair(); | |
| ec2Request.setKeyName(keyName); | |
| DeleteKeyPairResponse EC2Response = EC2SoapServiceImpl.toDeleteKeyPair(ServiceProvider.getInstance().getEC2Engine().deleteKeyPair(ec2Request)); | |
| serializeResponse(response, EC2Response); | |
| } | |
| private void getPasswordData(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException { | |
| String instanceId = request.getParameter("InstanceId"); | |
| if (instanceId == null) { | |
| throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - InstanceId"); | |
| } | |
| GetPasswordDataResponse EC2Response = EC2SoapServiceImpl.toGetPasswordData(ServiceProvider.getInstance().getEC2Engine().getPasswordData(instanceId)); | |
| serializeResponse(response, EC2Response); | |
| } | |
| private void createTags(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException { | |
| EC2Tags ec2Request = createTagsRequest(request, response); | |
| if (ec2Request == null) | |
| return; | |
| CreateTagsResponse EC2Response = EC2SoapServiceImpl.toCreateTagsResponse(ServiceProvider.getInstance().getEC2Engine().modifyTags(ec2Request, "create")); | |
| serializeResponse(response, EC2Response); | |
| } | |
| private void deleteTags(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException { | |
| EC2Tags ec2Request = createTagsRequest(request, response); | |
| if (ec2Request == null) | |
| return; | |
| DeleteTagsResponse EC2Response = EC2SoapServiceImpl.toDeleteTagsResponse(ServiceProvider.getInstance().getEC2Engine().modifyTags(ec2Request, "delete")); | |
| serializeResponse(response, EC2Response); | |
| } | |
| private EC2Tags createTagsRequest(HttpServletRequest request, HttpServletResponse response) throws IOException { | |
| EC2Tags ec2Request = new EC2Tags(); | |
| ArrayList<String> resourceIdList = new ArrayList<String>(); | |
| Map<String, String> resourceTagList = new HashMap<String, String>(); | |
| int nCount = 1; | |
| do { | |
| String[] resourceIds = request.getParameterValues("ResourceId." + nCount); | |
| if (resourceIds != null && resourceIds.length > 0) | |
| resourceIdList.add(resourceIds[0]); | |
| else | |
| break; | |
| nCount++; | |
| } while (true); | |
| if (resourceIdList.isEmpty()) { | |
| throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - ResourceId"); | |
| } | |
| ec2Request = EC2SoapServiceImpl.toResourceTypeAndIds(ec2Request, resourceIdList); | |
| nCount = 1; | |
| do { | |
| String[] tagKey = request.getParameterValues("Tag." + nCount + ".Key"); | |
| if (tagKey != null && tagKey.length > 0) { | |
| String[] tagValue = request.getParameterValues("Tag." + nCount + ".Value"); | |
| if (tagValue != null && tagValue.length > 0) { | |
| resourceTagList.put(tagKey[0], tagValue[0]); | |
| } else | |
| resourceTagList.put(tagKey[0], null); | |
| } else | |
| break; | |
| nCount++; | |
| } while (true); | |
| if (resourceTagList.isEmpty()) { | |
| throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - ResourceTag"); | |
| } | |
| ec2Request = EC2SoapServiceImpl.toResourceTag(ec2Request, resourceTagList); | |
| return ec2Request; | |
| } | |
| private void describeTags(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException { | |
| EC2DescribeTags ec2Request = new EC2DescribeTags(); | |
| EC2Filter[] filterSet = extractFilters(request); | |
| if (null != filterSet) { | |
| EC2TagsFilterSet tfs = new EC2TagsFilterSet(); | |
| for (int i = 0; i < filterSet.length; i++) | |
| tfs.addFilter(filterSet[i]); | |
| ec2Request.setFilterSet(tfs); | |
| } | |
| DescribeTagsResponse EC2Response = EC2SoapServiceImpl.toDescribeTagsResponse(ServiceProvider.getInstance().getEC2Engine().describeTags(ec2Request)); | |
| serializeResponse(response, EC2Response); | |
| } | |
| /** | |
| * This function implements the EC2 REST authentication algorithm. It uses the given | |
| * "AWSAccessKeyId" parameter to look up the Cloud.com account holder's secret key which is | |
| * used as input to the signature calculation. In addition, it tests the given "Expires" | |
| * parameter to see if the signature has expired and if so the request fails. | |
| */ | |
| private boolean authenticateRequest(HttpServletRequest request, HttpServletResponse response) throws SignatureException, IOException, InstantiationException, | |
| IllegalAccessException, ClassNotFoundException, SQLException, ParseException { | |
| String cloudSecretKey = null; | |
| String cloudAccessKey = null; | |
| String signature = null; | |
| String sigMethod = null; | |
| // [A] Basic parameters required for an authenticated rest request | |
| // -> note that the Servlet engine will un-URL encode all parameters we extract via "getParameterValues()" calls | |
| String[] awsAccess = request.getParameterValues("AWSAccessKeyId"); | |
| if (null != awsAccess && 0 < awsAccess.length) | |
| cloudAccessKey = awsAccess[0]; | |
| else { | |
| throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - AWSAccessKeyId"); | |
| } | |
| String[] clientSig = request.getParameterValues("Signature"); | |
| if (null != clientSig && 0 < clientSig.length) | |
| signature = clientSig[0]; | |
| else { | |
| throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - Signature"); | |
| } | |
| String[] method = request.getParameterValues("SignatureMethod"); | |
| if (null != method && 0 < method.length) { | |
| sigMethod = method[0]; | |
| if (!sigMethod.equals("HmacSHA256") && !sigMethod.equals("HmacSHA1")) { | |
| throw new EC2ServiceException(ClientError.InvalidParameterValue, "Unsupported SignatureMethod value: " + sigMethod + " expecting: HmacSHA256 or HmacSHA1"); | |
| } | |
| } else { | |
| throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - SignatureMethod"); | |
| } | |
| String[] version = request.getParameterValues("Version"); | |
| if (null != version && 0 < version.length) { | |
| if (!version[0].equals(wsdlVersion)) { | |
| throw new EC2ServiceException(ClientError.InvalidParameterValue, "Unsupported Version value: " + version[0] + " expecting: " + wsdlVersion); | |
| } | |
| } else { | |
| throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - Version"); | |
| } | |
| String[] sigVersion = request.getParameterValues("SignatureVersion"); | |
| if (null != sigVersion && 0 < sigVersion.length) { | |
| if (!sigVersion[0].equals("2")) { | |
| throw new EC2ServiceException(ClientError.InvalidParameterValue, "Unsupported SignatureVersion value: " + sigVersion[0] + " expecting: 2"); | |
| } | |
| } else { | |
| throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - SignatureVersion"); | |
| } | |
| // -> can have only one but not both { Expires | Timestamp } headers | |
| String[] expires = request.getParameterValues("Expires"); | |
| if (null != expires && 0 < expires.length) { | |
| // -> contains the date and time at which the signature included in the request EXPIRES | |
| if (hasSignatureExpired(expires[0])) { //InvalidSecurity.RequestHasExpired | |
| throw new EC2ServiceException(ClientError.InvalidSecurity_RequestHasExpired, "Expires parameter indicates signature has expired: " + expires[0]); | |
| } | |
| } else { // -> contains the date and time at which the request is SIGNED | |
| String[] time = request.getParameterValues("Timestamp"); | |
| if (null == time || 0 == time.length) { | |
| throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter -" + " Timestamp/Expires"); | |
| } | |
| } | |
| // [B] Use the access key to get the users secret key from the cloud DB | |
| cloudSecretKey = userDao.getSecretKeyByAccessKey(cloudAccessKey); | |
| if (cloudSecretKey == null) { | |
| logger.debug("Access key '" + cloudAccessKey + "' not found in the the EC2 service "); | |
| throw new EC2ServiceException(ClientError.AuthFailure, "Access key '" + cloudAccessKey + "' not found in the the EC2 service "); | |
| } | |
| // [C] Verify the signature | |
| // -> getting the query-string in this way maintains its URL encoding | |
| EC2RestAuth restAuth = new EC2RestAuth(); | |
| restAuth.setHostHeader(request.getHeader("Host")); | |
| String requestUri = request.getRequestURI(); | |
| // If forwarded from another basepath: | |
| String forwardedPath = (String)request.getAttribute("javax.servlet.forward.request_uri"); | |
| if (forwardedPath != null) { | |
| requestUri = forwardedPath; | |
| } | |
| restAuth.setHTTPRequestURI(requestUri); | |
| String queryString = request.getQueryString(); | |
| // getQueryString returns null (does it ever NOT return null for these), | |
| // we need to construct queryString to avoid changing the auth code... | |
| if (queryString == null) { | |
| // construct our idea of a queryString with parameters! | |
| Enumeration<?> params = request.getParameterNames(); | |
| if (params != null) { | |
| while (params.hasMoreElements()) { | |
| String paramName = (String)params.nextElement(); | |
| // exclude the signature string obviously. ;) | |
| if (paramName.equalsIgnoreCase("Signature")) | |
| continue; | |
| // URLEncoder performs application/x-www-form-urlencoded-type encoding and not Percent encoding | |
| // according to RFC 3986 as required by Amazon, we need to Percent-encode (URL Encode) | |
| String encodedValue = URLEncoder.encode(request.getParameter(paramName), "UTF-8").replace("+", "%20").replace("*", "%2A"); | |
| if (queryString == null) | |
| queryString = paramName + "=" + encodedValue; | |
| else | |
| queryString = queryString + "&" + paramName + "=" + encodedValue; | |
| } | |
| } | |
| } | |
| restAuth.setQueryString(queryString); | |
| if (restAuth.verifySignature(request.getMethod(), cloudSecretKey, signature, sigMethod)) { | |
| UserContext.current().initContext(cloudAccessKey, cloudSecretKey, cloudAccessKey, "REST request", null); | |
| return true; | |
| } else | |
| throw new EC2ServiceException(ClientError.SignatureDoesNotMatch, "The request signature calculated does not match the signature provided by the user."); | |
| } | |
| /** | |
| * We check this to reduce replay attacks. | |
| * | |
| * @param timeStamp | |
| * @return true - if the request is not longer valid, false otherwise | |
| * @throws ParseException | |
| */ | |
| private boolean hasSignatureExpired(String timeStamp) { | |
| Calendar cal = EC2RestAuth.parseDateString(timeStamp); | |
| if (null == cal) | |
| return false; | |
| Date expiredTime = cal.getTime(); | |
| Date today = new Date(); // -> gets set to time of creation | |
| if (0 >= expiredTime.compareTo(today)) { | |
| logger.debug("timestamp given: [" + timeStamp + "], now: [" + today.toString() + "]"); | |
| return true; | |
| } else | |
| return false; | |
| } | |
| private static void endResponse(HttpServletResponse response, String content) { | |
| try { | |
| byte[] data = content.getBytes(); | |
| response.setContentLength(data.length); | |
| OutputStream os = response.getOutputStream(); | |
| os.write(data); | |
| os.close(); | |
| } catch (Throwable e) { | |
| logger.error("Unexpected exception " + e.getMessage(), e); | |
| } | |
| } | |
| private void logRequest(HttpServletRequest request) { | |
| if (logger.isInfoEnabled()) { | |
| logger.info("EC2 Request method: " + request.getMethod()); | |
| logger.info("Request contextPath: " + request.getContextPath()); | |
| logger.info("Request pathInfo: " + request.getPathInfo()); | |
| logger.info("Request pathTranslated: " + request.getPathTranslated()); | |
| logger.info("Request queryString: " + request.getQueryString()); | |
| logger.info("Request requestURI: " + request.getRequestURI()); | |
| logger.info("Request requestURL: " + request.getRequestURL()); | |
| logger.info("Request servletPath: " + request.getServletPath()); | |
| Enumeration<?> headers = request.getHeaderNames(); | |
| if (headers != null) { | |
| while (headers.hasMoreElements()) { | |
| Object headerName = headers.nextElement(); | |
| logger.info("Request header " + headerName + ":" + request.getHeader((String)headerName)); | |
| } | |
| } | |
| Enumeration<?> params = request.getParameterNames(); | |
| if (params != null) { | |
| while (params.hasMoreElements()) { | |
| Object paramName = params.nextElement(); | |
| logger.info("Request parameter " + paramName + ":" + request.getParameter((String)paramName)); | |
| } | |
| } | |
| } | |
| } | |
| /** | |
| * Send out an error response according to Amazon convention. | |
| */ | |
| private void faultResponse(HttpServletResponse response, String errorCode, String errorMessage) { | |
| try { | |
| OutputStreamWriter out = new OutputStreamWriter(response.getOutputStream()); | |
| response.setContentType("text/xml; charset=UTF-8"); | |
| out.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"); | |
| out.write("<Response><Errors><Error><Code>"); | |
| out.write(errorCode); | |
| out.write("</Code><Message>"); | |
| out.write(errorMessage); | |
| out.write("</Message></Error></Errors><RequestID>"); | |
| out.write(UUID.randomUUID().toString()); | |
| out.write("</RequestID></Response>"); | |
| out.flush(); | |
| out.close(); | |
| } catch (IOException e) { | |
| logger.error("Unexpected exception " + e.getMessage(), e); | |
| } | |
| } | |
| /** | |
| * Serialize Axis beans to XML output. | |
| */ | |
| private void serializeResponse(HttpServletResponse response, ADBBean EC2Response) throws ADBException, XMLStreamException, IOException { | |
| OutputStream os = response.getOutputStream(); | |
| response.setStatus(200); | |
| response.setContentType("text/xml"); | |
| XMLStreamWriter xmlWriter = xmlOutFactory.createXMLStreamWriter(os); | |
| xmlWriter.writeStartDocument("UTF-8", "1.0"); | |
| MTOMAwareXMLSerializer MTOMWriter = new MTOMAwareXMLSerializer(xmlWriter); | |
| MTOMWriter.setDefaultNamespace("http://ec2.amazonaws.com/doc/" + wsdlVersion + "/"); | |
| EC2Response.serialize(null, factory, MTOMWriter); | |
| xmlWriter.flush(); | |
| xmlWriter.close(); | |
| os.close(); | |
| } | |
| } |