From 7c0a25be7f7f26c6d16324ea4d5d26f15846ee6b Mon Sep 17 00:00:00 2001 From: drigato Date: Mon, 1 Dec 2014 21:05:46 -0500 Subject: [PATCH] SAAS-505: Extract Amazon_S3 class and have it inherit from a general 'cloud backend' class --- airtime_mvc/application/amazon/Amazon_S3.php | 72 ----------------- .../application/cloud_storage/Amazon_S3.php | 74 ++++++++++++++++++ .../cloud_storage/ProxyStorageBackend.php | 44 +++++++++++ .../cloud_storage/StorageBackend.php | 55 +++++++++++++ airtime_mvc/application/configs/conf.php | 1 + .../application/models/airtime/CloudFile.php | 77 +++++-------------- airtime_mvc/public/index.php | 4 +- 7 files changed, 194 insertions(+), 133 deletions(-) delete mode 100644 airtime_mvc/application/amazon/Amazon_S3.php create mode 100644 airtime_mvc/application/cloud_storage/Amazon_S3.php create mode 100644 airtime_mvc/application/cloud_storage/ProxyStorageBackend.php create mode 100644 airtime_mvc/application/cloud_storage/StorageBackend.php diff --git a/airtime_mvc/application/amazon/Amazon_S3.php b/airtime_mvc/application/amazon/Amazon_S3.php deleted file mode 100644 index ce1615b1e..000000000 --- a/airtime_mvc/application/amazon/Amazon_S3.php +++ /dev/null @@ -1,72 +0,0 @@ -initZendServiceAmazonS3(); - } - - private function initZendServiceAmazonS3() - { - $CC_CONFIG = Config::getConfig(); - - $this->setBucket($CC_CONFIG['storage_backend']['bucket']); - $this->setAccessKey($CC_CONFIG['storage_backend']['api_key']); - $this->setSecretKey($CC_CONFIG['storage_backend']['api_key_secret']); - - $this->zendServiceAmazonS3 = new Zend_Service_Amazon_S3( - $this->getAccessKey(), - $this->getSecretKey()); - } - - public function getZendServiceAmazonS3() - { - return $this->zendServiceAmazonS3; - } - - public function getBucket() - { - return $this->bucket; - } - - private function setBucket($bucket) - { - $this->bucket = $bucket; - } - - public function getAccessKey() - { - return $this->accessKey; - } - - private function setAccessKey($accessKey) - { - $this->accessKey = $accessKey; - } - - public function getSecretKey() - { - return $this->secretKey; - } - - private function setSecretKey($secretKey) - { - $this->secretKey = $secretKey; - } -} \ No newline at end of file diff --git a/airtime_mvc/application/cloud_storage/Amazon_S3.php b/airtime_mvc/application/cloud_storage/Amazon_S3.php new file mode 100644 index 000000000..b9e405032 --- /dev/null +++ b/airtime_mvc/application/cloud_storage/Amazon_S3.php @@ -0,0 +1,74 @@ +setBucket($CC_CONFIG['storage_backend']['bucket']); + $this->setAccessKey($CC_CONFIG['storage_backend']['api_key']); + $this->setSecretKey($CC_CONFIG['storage_backend']['api_key_secret']); + + $this->zendServiceAmazonS3 = new Zend_Service_Amazon_S3( + $this->getAccessKey(), + $this->getSecretKey()); + } + + public function getAbsoluteFilePath($resourceId) + { + $endpoint = $this->zendServiceAmazonS3->getEndpoint(); + $scheme = $endpoint->getScheme(); + $host = $endpoint->getHost(); + $bucket = $this->getBucket(); + return "$scheme://$bucket.$host/".utf8_encode($resourceId); + } + + public function getSignedURL($resourceId) + { + //URL will be active for 30 minutes + $expires = time()+1800; + + $bucket = $this->getBucket(); + $secretKey = $this->getSecretKey(); + $accessKey = $this->getAccessKey(); + + $string_to_sign = utf8_encode("GET\n\n\n$expires\n/$bucket/$resourceId"); + // We need to urlencode the entire signature in case the hashed signature + // has spaces. (NOTE: utf8_encode() does not work here because it turns + // spaces into non-breaking spaces) + $signature = urlencode(base64_encode((hash_hmac("sha1", $string_to_sign, $secretKey, true)))); + + $resourceURL = $this->getAbsoluteFilePath($resourceId); + return $resourceURL."?AWSAccessKeyId=$accessKey&Expires=$expires&Signature=$signature"; + } + + public function getFileSize($resourceId) + { + $bucket = $this->getBucket(); + + $amz_resource = utf8_encode("$bucket/$resourceId"); + $amz_resource_info = $this->zendServiceAmazonS3->getInfo($amz_resource); + return $amz_resource_info["size"]; + } + + public function deletePhysicalFile($resourceId) + { + $bucket = $this->getBucket(); + $amz_resource = utf8_encode("$bucket/$resourceId"); + + if ($this->zendServiceAmazonS3->isObjectAvailable($amz_resource)) { + // removeObject() returns true even if the object was not deleted (bug?) + // so that is not a good way to do error handling. isObjectAvailable() + // does however return the correct value; We have to assume that if the + // object is available the removeObject() function will work. + $this->zendServiceAmazonS3->removeObject($amz_resource); + } else { + throw new Exception("ERROR: Could not locate object on Amazon S3"); + } + } +} diff --git a/airtime_mvc/application/cloud_storage/ProxyStorageBackend.php b/airtime_mvc/application/cloud_storage/ProxyStorageBackend.php new file mode 100644 index 000000000..db475c04a --- /dev/null +++ b/airtime_mvc/application/cloud_storage/ProxyStorageBackend.php @@ -0,0 +1,44 @@ +storageBackend = new $storageBackend(); + } + + public function getAbsoluteFilePath($resourceId) + { + return $this->storageBackend->getAbsoluteFilePath($resourceId); + } + + public function getSignedURL($resourceId) + { + return $this->storageBackend->getSignedURL($resourceId); + } + + public function getFileSize($resourceId) + { + return $this->storageBackend->getFileSize($resourceId); + } + + public function deletePhysicalFile($resourceId) + { + $this->storageBackend->deletePhysicalFile($resourceId); + } + +} diff --git a/airtime_mvc/application/cloud_storage/StorageBackend.php b/airtime_mvc/application/cloud_storage/StorageBackend.php new file mode 100644 index 000000000..84a9a8d72 --- /dev/null +++ b/airtime_mvc/application/cloud_storage/StorageBackend.php @@ -0,0 +1,55 @@ +bucket; + } + + protected function setBucket($bucket) + { + $this->bucket = $bucket; + } + + protected function getAccessKey() + { + return $this->accessKey; + } + + protected function setAccessKey($accessKey) + { + $this->accessKey = $accessKey; + } + + protected function getSecretKey() + { + return $this->secretKey; + } + + protected function setSecretKey($secretKey) + { + $this->secretKey = $secretKey; + } +} diff --git a/airtime_mvc/application/configs/conf.php b/airtime_mvc/application/configs/conf.php index 00eaecdbe..fda19171a 100644 --- a/airtime_mvc/application/configs/conf.php +++ b/airtime_mvc/application/configs/conf.php @@ -29,6 +29,7 @@ class Config { $cloudStorageConfig = isset($_SERVER['CLOUD_STORAGE_CONF']) ? $_SERVER['CLOUD_STORAGE_CONF'] : "/etc/airtime-saas/cloud_storage.conf"; $cloudStorageValues = parse_ini_file($cloudStorageConfig, true); $currentStorageBackend = $cloudStorageValues['current_backend']['storage_backend']; + $CC_CONFIG['current_backend'] = $cloudStorageValues['current_backend']['storage_backend']; $CC_CONFIG['storage_backend'] = $cloudStorageValues[$currentStorageBackend]; $values = parse_ini_file($filename, true); diff --git a/airtime_mvc/application/models/airtime/CloudFile.php b/airtime_mvc/application/models/airtime/CloudFile.php index c1d5b3b7a..099f7c4fa 100644 --- a/airtime_mvc/application/models/airtime/CloudFile.php +++ b/airtime_mvc/application/models/airtime/CloudFile.php @@ -1,13 +1,13 @@ getAbsoluteFilePath()."?".$this->getAuthenticationParams(); + if ($this->proxyStorageBackend == null) { + $this->proxyStorageBackend = new ProxyStorageBackend($this->getStorageBackend()); + } + return $this->proxyStorageBackend->getSignedURL($this->getResourceId()); } /** @@ -34,39 +38,10 @@ class CloudFile extends BaseCloudFile */ public function getAbsoluteFilePath() { - $amazon_s3 = new Amazon_S3(); - $zend_s3 = $amazon_s3->getZendServiceAmazonS3(); - $resource_id = $this->getResourceId(); - $endpoint = $zend_s3->getEndpoint(); - $scheme = $endpoint->getScheme(); - $host = $endpoint->getHost(); - $s3_bucket = $amazon_s3->getBucket(); - return "$scheme://$s3_bucket.$host/".utf8_encode($resource_id); - } - - /** - * - * Returns a string of authentication paramaters to append to the cloud - * object's URL. We need this for track preview and download because the - * objects are privately stored on Amazon S3. - */ - public function getAuthenticationParams() - { - $expires = time()+120; - $resource_id = $this->getResourceId(); - - $amazon_s3 = new Amazon_S3(); - $s3_bucket = $amazon_s3->getBucket(); - $s3_secret_key = $amazon_s3->getSecretKey(); - $s3_access_key = $amazon_s3->getAccessKey(); - - $string_to_sign = utf8_encode("GET\n\n\n$expires\n/$s3_bucket/$resource_id"); - // We need to urlencode the entire signature in case the hashed signature - // has spaces. (NOTE: utf8_encode() does not work here because it turns - // spaces into non-breaking spaces) - $signature = urlencode(base64_encode((hash_hmac("sha1", $string_to_sign, $s3_secret_key, true)))); - - return "AWSAccessKeyId=$s3_access_key&Expires=$expires&Signature=$signature"; + if ($this->proxyStorageBackend == null) { + $this->proxyStorageBackend = new ProxyStorageBackend($this->getStorageBackend()); + } + return $this->proxyStorageBackend->getAbsoluteFilePath($this->getResourceId()); } /** @@ -74,15 +49,10 @@ class CloudFile extends BaseCloudFile */ public function getFileSize() { - $amazon_s3 = new Amazon_S3(); - - $zend_s3 = $amazon_s3->getZendServiceAmazonS3(); - $bucket = $amazon_s3->getBucket(); - $resource_id = $this->getResourceId(); - - $amz_resource = utf8_encode("$bucket/$resource_id"); - $amz_resource_info = $zend_s3->getInfo($amz_resource); - return $amz_resource_info["size"]; + if ($this->proxyStorageBackend == null) { + $this->proxyStorageBackend = new ProxyStorageBackend($this->getStorageBackend()); + } + return $this->proxyStorageBackend->getFileSize($this->getResourceId()); } public function getFilename() @@ -119,21 +89,10 @@ class CloudFile extends BaseCloudFile */ public function deletePhysicalFile() { - $amazon_s3 = new Amazon_S3(); - $zend_s3 = $amazon_s3->getZendServiceAmazonS3(); - $bucket = $amazon_s3->getBucket(); - $resource_id = $this->getResourceId(); - $amz_resource = utf8_encode("$bucket/$resource_id"); - - if ($zend_s3->isObjectAvailable($amz_resource)) { - // removeObject() returns true even if the object was not deleted (bug?) - // so that is not a good way to do error handling. isObjectAvailable() - // does however return the correct value; We have to assume that if the - // object is available the removeObject() function will work. - $zend_s3->removeObject($amz_resource); - } else { - throw new Exception("ERROR: Could not locate object on Amazon S3"); + if ($this->proxyStorageBackend == null) { + $this->proxyStorageBackend = new ProxyStorageBackend($this->getStorageBackend()); } + $this->proxyStorageBackend->deletePhysicalFile($this->getResourceId()); } /** diff --git a/airtime_mvc/public/index.php b/airtime_mvc/public/index.php index a20586e82..fd1335ee3 100644 --- a/airtime_mvc/public/index.php +++ b/airtime_mvc/public/index.php @@ -57,8 +57,8 @@ if (file_exists('/usr/share/php/libzend-framework-php')) { set_include_path('/usr/share/php/libzend-framework-php' . PATH_SEPARATOR . get_include_path()); } -//amazon directory -set_include_path(APPLICATION_PATH . '/amazon' . PATH_SEPARATOR . get_include_path()); +//cloud storage directory +set_include_path(APPLICATION_PATH . '/cloud_storage' . PATH_SEPARATOR . get_include_path()); /** Zend_Application */ require_once 'Zend/Application.php';