diff --git a/awsapi/src/com/cloud/bridge/model/CloudStackUserVO.java b/awsapi/src/com/cloud/bridge/model/CloudStackUserVO.java new file mode 100644 index 00000000000..fe1ec946941 --- /dev/null +++ b/awsapi/src/com/cloud/bridge/model/CloudStackUserVO.java @@ -0,0 +1,49 @@ +// 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.model; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Table; + +@Entity +@Table(name="user") +public class CloudStackUserVO { + + @Column(name="api_key") + private String apiKey; + + @Column(name="secret_key") + private String secretKey; + + public String getApiKey() { + return apiKey; + } + + public String getSecretKey() { + return secretKey; + } + + public void setApiKey(String apiKey) { + this.apiKey = apiKey; + } + + public void setSecretKey(String secretKey) { + this.secretKey = secretKey; + } + +} diff --git a/awsapi/src/com/cloud/bridge/persist/dao/CloudStackUserDao.java b/awsapi/src/com/cloud/bridge/persist/dao/CloudStackUserDao.java new file mode 100644 index 00000000000..f5d4aa14f57 --- /dev/null +++ b/awsapi/src/com/cloud/bridge/persist/dao/CloudStackUserDao.java @@ -0,0 +1,26 @@ +// 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.persist.dao; + +import com.cloud.bridge.model.CloudStackUserVO; +import com.cloud.utils.db.GenericDao; + +public interface CloudStackUserDao extends GenericDao { + + public String getSecretKeyByAccessKey(String acessKey); + +} diff --git a/awsapi/src/com/cloud/bridge/persist/dao/CloudStackUserDaoImpl.java b/awsapi/src/com/cloud/bridge/persist/dao/CloudStackUserDaoImpl.java new file mode 100644 index 00000000000..061351930da --- /dev/null +++ b/awsapi/src/com/cloud/bridge/persist/dao/CloudStackUserDaoImpl.java @@ -0,0 +1,66 @@ +// 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.persist.dao; + +import javax.ejb.Local; + +import org.apache.log4j.Logger; +import org.jasypt.encryption.pbe.StandardPBEStringEncryptor; + +import com.cloud.bridge.model.CloudStackUserVO; +import com.cloud.bridge.util.EncryptionSecretKeyCheckerUtil; +import com.cloud.utils.db.GenericDaoBase; +import com.cloud.utils.db.SearchBuilder; +import com.cloud.utils.db.SearchCriteria; +import com.cloud.utils.db.Transaction; + +@Local(value={CloudStackUserDao.class}) +public class CloudStackUserDaoImpl extends GenericDaoBase implements CloudStackUserDao { + public static final Logger logger = Logger.getLogger(CloudStackUserDaoImpl.class); + + public CloudStackUserDaoImpl() {} + + @Override + public String getSecretKeyByAccessKey( String accessKey ) { + CloudStackUserVO user = null; + String cloudSecretKey = null; + + SearchBuilder searchByAccessKey = createSearchBuilder(); + searchByAccessKey.and("apiKey", searchByAccessKey.entity().getApiKey(), SearchCriteria.Op.EQ); + searchByAccessKey.done(); + Transaction txn = Transaction.open(Transaction.CLOUD_DB); + try { + txn.start(); + SearchCriteria sc = searchByAccessKey.create(); + sc.setParameters("apiKey", accessKey); + user = findOneBy(sc); + if ( user != null && user.getSecretKey() != null) { + // if the cloud db is encrypted, decrypt the secret_key returned by cloud db before signature generation + if( EncryptionSecretKeyCheckerUtil.useEncryption() ) { + StandardPBEStringEncryptor encryptor = EncryptionSecretKeyCheckerUtil.getEncryptor(); + cloudSecretKey = encryptor.decrypt( user.getSecretKey() ); + } else { + cloudSecretKey = user.getSecretKey(); + } + } + return cloudSecretKey; + } finally { + txn.close(); + } + } + +} diff --git a/awsapi/src/com/cloud/bridge/service/EC2RestServlet.java b/awsapi/src/com/cloud/bridge/service/EC2RestServlet.java index 78e736f4ec9..4260e9fedac 100644 --- a/awsapi/src/com/cloud/bridge/service/EC2RestServlet.java +++ b/awsapi/src/com/cloud/bridge/service/EC2RestServlet.java @@ -56,6 +56,7 @@ import org.apache.axis2.databinding.ADBException; import org.apache.axis2.databinding.utils.writer.MTOMAwareXMLSerializer; import org.apache.commons.codec.binary.Base64; import org.apache.log4j.Logger; +import org.jasypt.encryption.pbe.StandardPBEStringEncryptor; import com.amazon.ec2.AllocateAddressResponse; import com.amazon.ec2.AssociateAddressResponse; @@ -94,7 +95,9 @@ 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.CloudStackUserVO; 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; @@ -138,6 +141,7 @@ import com.cloud.bridge.service.exception.EC2ServiceException.ClientError; import com.cloud.bridge.util.AuthenticationUtils; import com.cloud.bridge.util.ConfigurationHelper; import com.cloud.bridge.util.EC2RestAuth; +import com.cloud.bridge.util.EncryptionSecretKeyCheckerUtil; import com.cloud.stack.models.CloudStackAccount; import com.cloud.utils.component.ComponentLocator; import com.cloud.utils.db.Transaction; @@ -147,6 +151,7 @@ public class EC2RestServlet extends HttpServlet { private static final long serialVersionUID = -6168996266762804888L; protected final UserCredentialsDaoImpl ucDao = ComponentLocator.inject(UserCredentialsDaoImpl.class); + protected final CloudStackUserDaoImpl userDao = ComponentLocator.inject(CloudStackUserDaoImpl.class); protected final OfferingDaoImpl ofDao = ComponentLocator.inject(OfferingDaoImpl.class); public static final Logger logger = Logger.getLogger(EC2RestServlet.class); @@ -1734,18 +1739,14 @@ public class EC2RestServlet extends HttpServlet { } } - // [B] Use the cloudAccessKey to get the users secret key in the db - UserCredentialsVO cloudKeys = ucDao.getByAccessKey( cloudAccessKey ); + // [B] Use the access key to get the users secret key from the cloud DB + cloudSecretKey = userDao.getSecretKeyByAccessKey( cloudAccessKey ); + if ( cloudSecretKey == null ) { + logger.debug("No Secret key found for Access key '" + cloudAccessKey + "' in the the EC2 service"); + throw new EC2ServiceException( ClientError.AuthFailure, "No Secret key found for Access key '" + cloudAccessKey + + "' in the the EC2 service" ); + } - if ( null == cloudKeys ) - { - logger.debug( cloudAccessKey + " is not defined in the EC2 service - call SetUserKeys" ); - response.sendError(404, cloudAccessKey + " is not defined in the EC2 service - call SetUserKeys" ); - return false; - } - else cloudSecretKey = cloudKeys.getSecretKey(); - - // [C] Verify the signature // -> getting the query-string in this way maintains its URL encoding EC2RestAuth restAuth = new EC2RestAuth();