File indexing completed on 2025-03-02 05:29:48
0001 <?php 0002 /** 0003 * Zend Framework 0004 * 0005 * LICENSE 0006 * 0007 * This source file is subject to the new BSD license that is bundled 0008 * with this package in the file LICENSE.txt. 0009 * It is also available through the world-wide-web at this URL: 0010 * http://framework.zend.com/license/new-bsd 0011 * If you did not receive a copy of the license and are unable to 0012 * obtain it through the world-wide-web, please send an email 0013 * to license@zend.com so we can send you a copy immediately. 0014 * 0015 * @category Zend 0016 * @package Zend_Service_WindowsAzure 0017 * @subpackage Management 0018 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 0019 * @license http://framework.zend.com/license/new-bsd New BSD License 0020 * @version $Id$ 0021 */ 0022 0023 /** 0024 * @see Zend_Http_Client 0025 */ 0026 // require_once 'Zend/Http/Client.php'; 0027 0028 /** 0029 * @see Zend_Service_WindowsAzure_RetryPolicy_RetryPolicyAbstract 0030 */ 0031 // require_once 'Zend/Service/WindowsAzure/RetryPolicy/RetryPolicyAbstract.php'; 0032 0033 /** 0034 * @see Zend_Service_SqlAzure_Management_ServerInstance 0035 */ 0036 // require_once 'Zend/Service/SqlAzure/Management/ServerInstance.php'; 0037 0038 /** 0039 * @see Zend_Service_SqlAzure_Management_FirewallRuleInstance 0040 */ 0041 // require_once 'Zend/Service/SqlAzure/Management/FirewallRuleInstance.php'; 0042 0043 /** @see Zend_Xml_Security */ 0044 // require_once 'Zend/Xml/Security.php'; 0045 0046 /** 0047 * @category Zend 0048 * @package Zend_Service_SqlAzure 0049 * @subpackage Management 0050 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 0051 * @license http://framework.zend.com/license/new-bsd New BSD License 0052 */ 0053 class Zend_Service_SqlAzure_Management_Client 0054 { 0055 /** 0056 * Management service URL 0057 */ 0058 const URL_MANAGEMENT = "https://management.database.windows.net:8443"; 0059 0060 /** 0061 * Operations 0062 */ 0063 const OP_OPERATIONS = "operations"; 0064 const OP_SERVERS = "servers"; 0065 const OP_FIREWALLRULES = "firewallrules"; 0066 0067 /** 0068 * Current API version 0069 * 0070 * @var string 0071 */ 0072 protected $_apiVersion = '1.0'; 0073 0074 /** 0075 * Subscription ID 0076 * 0077 * @var string 0078 */ 0079 protected $_subscriptionId = ''; 0080 0081 /** 0082 * Management certificate path (.PEM) 0083 * 0084 * @var string 0085 */ 0086 protected $_certificatePath = ''; 0087 0088 /** 0089 * Management certificate passphrase 0090 * 0091 * @var string 0092 */ 0093 protected $_certificatePassphrase = ''; 0094 0095 /** 0096 * Zend_Http_Client channel used for communication with REST services 0097 * 0098 * @var Zend_Http_Client 0099 */ 0100 protected $_httpClientChannel = null; 0101 0102 /** 0103 * Zend_Service_WindowsAzure_RetryPolicy_RetryPolicyAbstract instance 0104 * 0105 * @var Zend_Service_WindowsAzure_RetryPolicy_RetryPolicyAbstract 0106 */ 0107 protected $_retryPolicy = null; 0108 0109 /** 0110 * Returns the last request ID 0111 * 0112 * @var string 0113 */ 0114 protected $_lastRequestId = null; 0115 0116 /** 0117 * Creates a new Zend_Service_SqlAzure_Management instance 0118 * 0119 * @param string $subscriptionId Subscription ID 0120 * @param string $certificatePath Management certificate path (.PEM) 0121 * @param string $certificatePassphrase Management certificate passphrase 0122 * @param Zend_Service_WindowsAzure_RetryPolicy_RetryPolicyAbstract $retryPolicy Retry policy to use when making requests 0123 */ 0124 public function __construct( 0125 $subscriptionId, 0126 $certificatePath, 0127 $certificatePassphrase, 0128 Zend_Service_WindowsAzure_RetryPolicy_RetryPolicyAbstract $retryPolicy = null 0129 ) { 0130 $this->_subscriptionId = $subscriptionId; 0131 $this->_certificatePath = $certificatePath; 0132 $this->_certificatePassphrase = $certificatePassphrase; 0133 0134 $this->_retryPolicy = $retryPolicy; 0135 if (is_null($this->_retryPolicy)) { 0136 $this->_retryPolicy = Zend_Service_WindowsAzure_RetryPolicy_RetryPolicyAbstract::noRetry(); 0137 } 0138 0139 // Setup default Zend_Http_Client channel 0140 $options = array( 0141 'adapter' => 'Zend_Http_Client_Adapter_Socket', 0142 'ssltransport' => 'ssl', 0143 'sslcert' => $this->_certificatePath, 0144 'sslpassphrase' => $this->_certificatePassphrase, 0145 'sslusecontext' => true, 0146 ); 0147 if (function_exists('curl_init')) { 0148 // Set cURL options if cURL is used afterwards 0149 $options['curloptions'] = array( 0150 CURLOPT_FOLLOWLOCATION => true, 0151 CURLOPT_TIMEOUT => 120, 0152 ); 0153 } 0154 $this->_httpClientChannel = new Zend_Http_Client(null, $options); 0155 } 0156 0157 /** 0158 * Set the HTTP client channel to use 0159 * 0160 * @param Zend_Http_Client_Adapter_Interface|string $adapterInstance Adapter instance or adapter class name. 0161 */ 0162 public function setHttpClientChannel($adapterInstance = 'Zend_Http_Client_Adapter_Socket') 0163 { 0164 $this->_httpClientChannel->setAdapter($adapterInstance); 0165 } 0166 0167 /** 0168 * Retrieve HTTP client channel 0169 * 0170 * @return Zend_Http_Client_Adapter_Interface 0171 */ 0172 public function getHttpClientChannel() 0173 { 0174 return $this->_httpClientChannel; 0175 } 0176 0177 /** 0178 * Returns the Windows Azure subscription ID 0179 * 0180 * @return string 0181 */ 0182 public function getSubscriptionId() 0183 { 0184 return $this->_subscriptionId; 0185 } 0186 0187 /** 0188 * Returns the last request ID. 0189 * 0190 * @return string 0191 */ 0192 public function getLastRequestId() 0193 { 0194 return $this->_lastRequestId; 0195 } 0196 0197 /** 0198 * Get base URL for creating requests 0199 * 0200 * @return string 0201 */ 0202 public function getBaseUrl() 0203 { 0204 return self::URL_MANAGEMENT . '/' . $this->_subscriptionId; 0205 } 0206 0207 /** 0208 * Perform request using Zend_Http_Client channel 0209 * 0210 * @param string $path Path 0211 * @param string $queryString Query string 0212 * @param string $httpVerb HTTP verb the request will use 0213 * @param array $headers x-ms headers to add 0214 * @param mixed $rawData Optional RAW HTTP data to be sent over the wire 0215 * @return Zend_Http_Response 0216 */ 0217 protected function _performRequest( 0218 $path = '/', 0219 $queryString = '', 0220 $httpVerb = Zend_Http_Client::GET, 0221 $headers = array(), 0222 $rawData = null 0223 ) { 0224 // Clean path 0225 if (strpos($path, '/') !== 0) { 0226 $path = '/' . $path; 0227 } 0228 0229 // Clean headers 0230 if (is_null($headers)) { 0231 $headers = array(); 0232 } 0233 0234 // Ensure cUrl will also work correctly: 0235 // - disable Content-Type if required 0236 // - disable Expect: 100 Continue 0237 if (!isset($headers["Content-Type"])) { 0238 $headers["Content-Type"] = ''; 0239 } 0240 //$headers["Expect"] = ''; 0241 0242 // Add version header 0243 $headers['x-ms-version'] = $this->_apiVersion; 0244 0245 // URL encoding 0246 $path = self::urlencode($path); 0247 $queryString = self::urlencode($queryString); 0248 0249 // Generate URL and sign request 0250 $requestUrl = $this->getBaseUrl() . $path . $queryString; 0251 $requestHeaders = $headers; 0252 0253 // Prepare request 0254 $this->_httpClientChannel->resetParameters(true); 0255 $this->_httpClientChannel->setUri($requestUrl); 0256 $this->_httpClientChannel->setHeaders($requestHeaders); 0257 $this->_httpClientChannel->setRawData($rawData); 0258 0259 // Execute request 0260 $response = $this->_retryPolicy->execute( 0261 array($this->_httpClientChannel, 'request'), 0262 array($httpVerb) 0263 ); 0264 0265 // Store request id 0266 $this->_lastRequestId = $response->getHeader('x-ms-request-id'); 0267 0268 return $response; 0269 } 0270 0271 /** 0272 * Parse result from Zend_Http_Response 0273 * 0274 * @param Zend_Http_Response $response Response from HTTP call 0275 * @return object 0276 * @throws Zend_Service_WindowsAzure_Exception 0277 */ 0278 protected function _parseResponse(Zend_Http_Response $response = null) 0279 { 0280 if (is_null($response)) { 0281 // require_once 'Zend/Service/SqlAzure/Exception.php'; 0282 throw new Zend_Service_SqlAzure_Exception('Response should not be null.'); 0283 } 0284 0285 $xml = @Zend_Xml_Security::scan($response->getBody()); 0286 0287 if ($xml !== false) { 0288 // Fetch all namespaces 0289 $namespaces = array_merge($xml->getNamespaces(true), $xml->getDocNamespaces(true)); 0290 0291 // Register all namespace prefixes 0292 foreach ($namespaces as $prefix => $ns) { 0293 if ($prefix != '') { 0294 $xml->registerXPathNamespace($prefix, $ns); 0295 } 0296 } 0297 } 0298 0299 return $xml; 0300 } 0301 0302 /** 0303 * URL encode function 0304 * 0305 * @param string $value Value to encode 0306 * @return string Encoded value 0307 */ 0308 public static function urlencode($value) 0309 { 0310 return str_replace(' ', '%20', $value); 0311 } 0312 0313 /** 0314 * Builds a query string from an array of elements 0315 * 0316 * @param array Array of elements 0317 * @return string Assembled query string 0318 */ 0319 public static function createQueryStringFromArray($queryString) 0320 { 0321 return count($queryString) > 0 ? '?' . implode('&', $queryString) : ''; 0322 } 0323 0324 /** 0325 * Get error message from Zend_Http_Response 0326 * 0327 * @param Zend_Http_Response $response Repsonse 0328 * @param string $alternativeError Alternative error message 0329 * @return string 0330 */ 0331 protected function _getErrorMessage(Zend_Http_Response $response, $alternativeError = 'Unknown error.') 0332 { 0333 $response = $this->_parseResponse($response); 0334 if ($response && $response->Message) { 0335 return (string)$response->Message; 0336 } else { 0337 return $alternativeError; 0338 } 0339 } 0340 0341 /** 0342 * The Create Server operation adds a new SQL Azure server to a subscription. 0343 * 0344 * @param string $administratorLogin Administrator login. 0345 * @param string $administratorPassword Administrator password. 0346 * @param string $location Location of the server. 0347 * @return Zend_Service_SqlAzure_Management_ServerInstance Server information. 0348 * @throws Zend_Service_SqlAzure_Management_Exception 0349 */ 0350 public function createServer($administratorLogin, $administratorPassword, $location) 0351 { 0352 if ($administratorLogin == '' || is_null($administratorLogin)) { 0353 // require_once 'Zend/Service/SqlAzure/Management/Exception.php'; 0354 throw new Zend_Service_SqlAzure_Management_Exception('Administrator login should be specified.'); 0355 } 0356 if ($administratorPassword == '' || is_null($administratorPassword)) { 0357 // require_once 'Zend/Service/SqlAzure/Management/Exception.php'; 0358 throw new Zend_Service_SqlAzure_Management_Exception('Administrator password should be specified.'); 0359 } 0360 if (is_null($location) && is_null($affinityGroup)) { 0361 // require_once 'Zend/Service/SqlAzure/Management/Exception.php'; 0362 throw new Zend_Service_SqlAzure_Management_Exception('Please specify a location for the server.'); 0363 } 0364 0365 $response = $this->_performRequest(self::OP_SERVERS, '', 0366 Zend_Http_Client::POST, 0367 array('Content-Type' => 'application/xml; charset=utf-8'), 0368 '<Server xmlns="http://schemas.microsoft.com/sqlazure/2010/12/"><AdministratorLogin>' . $administratorLogin . '</AdministratorLogin><AdministratorLoginPassword>' . $administratorPassword . '</AdministratorLoginPassword><Location>' . $location . '</Location></Server>'); 0369 0370 if ($response->isSuccessful()) { 0371 $xml = $this->_parseResponse($response); 0372 0373 return new Zend_Service_SqlAzure_Management_ServerInstance( 0374 (string)$xml, 0375 $administratorLogin, 0376 $location 0377 ); 0378 } else { 0379 // require_once 'Zend/Service/SqlAzure/Management/Exception.php'; 0380 throw new Zend_Service_SqlAzure_Management_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.')); 0381 } 0382 } 0383 0384 /** 0385 * The Get Servers operation enumerates SQL Azure servers that are provisioned for a subscription. 0386 * 0387 * @return array An array of Zend_Service_SqlAzure_Management_ServerInstance. 0388 * @throws Zend_Service_SqlAzure_Management_Exception 0389 */ 0390 public function listServers() 0391 { 0392 $response = $this->_performRequest(self::OP_SERVERS); 0393 0394 if ($response->isSuccessful()) { 0395 $xml = $this->_parseResponse($response); 0396 $xmlServices = null; 0397 0398 if (!$xml->Server) { 0399 return array(); 0400 } 0401 if (count($xml->Server) > 1) { 0402 $xmlServices = $xml->Server; 0403 } else { 0404 $xmlServices = array($xml->Server); 0405 } 0406 0407 $services = array(); 0408 if (!is_null($xmlServices)) { 0409 0410 for ($i = 0; $i < count($xmlServices); $i++) { 0411 $services[] = new Zend_Service_SqlAzure_Management_ServerInstance( 0412 (string)$xmlServices[$i]->Name, 0413 (string)$xmlServices[$i]->AdministratorLogin, 0414 (string)$xmlServices[$i]->Location 0415 ); 0416 } 0417 } 0418 return $services; 0419 } else { 0420 // require_once 'Zend/Service/SqlAzure/Management/Exception.php'; 0421 throw new Zend_Service_SqlAzure_Management_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.')); 0422 } 0423 } 0424 0425 /** 0426 * The Drop Server operation drops a SQL Azure server from a subscription. 0427 * 0428 * @param string $serverName Server to drop. 0429 * @throws Zend_Service_SqlAzure_Management_Exception 0430 */ 0431 public function dropServer($serverName) 0432 { 0433 if ($serverName == '' || is_null($serverName)) { 0434 // require_once 'Zend/Service/SqlAzure/Management/Exception.php'; 0435 throw new Zend_Service_SqlAzure_Management_Exception('Server name should be specified.'); 0436 } 0437 0438 $response = $this->_performRequest(self::OP_SERVERS . '/' . $serverName, '', Zend_Http_Client::DELETE); 0439 0440 if (!$response->isSuccessful()) { 0441 // require_once 'Zend/Service/SqlAzure/Management/Exception.php'; 0442 throw new Zend_Service_SqlAzure_Management_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.')); 0443 } 0444 } 0445 0446 /** 0447 * The Set Server Administrator Password operation sets the administrative password of a SQL Azure server for a subscription. 0448 * 0449 * @param string $serverName Server to set password for. 0450 * @param string $administratorPassword Administrator password. 0451 * @throws Zend_Service_SqlAzure_Management_Exception 0452 */ 0453 public function setAdministratorPassword($serverName, $administratorPassword) 0454 { 0455 if ($serverName == '' || is_null($serverName)) { 0456 // require_once 'Zend/Service/SqlAzure/Management/Exception.php'; 0457 throw new Zend_Service_SqlAzure_Management_Exception('Server name should be specified.'); 0458 } 0459 if ($administratorPassword == '' || is_null($administratorPassword)) { 0460 // require_once 'Zend/Service/SqlAzure/Management/Exception.php'; 0461 throw new Zend_Service_SqlAzure_Management_Exception('Administrator password should be specified.'); 0462 } 0463 0464 $response = $this->_performRequest(self::OP_SERVERS . '/' . $serverName, '?op=ResetPassword', 0465 Zend_Http_Client::POST, 0466 array('Content-Type' => 'application/xml; charset=utf-8'), 0467 '<AdministratorLoginPassword xmlns="http://schemas.microsoft.com/sqlazure/2010/12/">' . $administratorPassword . '</AdministratorLoginPassword>'); 0468 0469 if (!$response->isSuccessful()) { 0470 // require_once 'Zend/Service/SqlAzure/Management/Exception.php'; 0471 throw new Zend_Service_SqlAzure_Management_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.')); 0472 } 0473 } 0474 0475 /** 0476 * The Set Server Firewall Rule operation updates an existing firewall rule or adds a new firewall rule for a SQL Azure server that belongs to a subscription. 0477 * 0478 * @param string $serverName Server name. 0479 * @param string $ruleName Firewall rule name. 0480 * @param string $startIpAddress Start IP address. 0481 * @param string $endIpAddress End IP address. 0482 * @return Zend_Service_SqlAzure_Management_FirewallRuleInstance 0483 * @throws Zend_Service_SqlAzure_Management_Exception 0484 */ 0485 public function createFirewallRule($serverName, $ruleName, $startIpAddress, $endIpAddress) 0486 { 0487 if ($serverName == '' || is_null($serverName)) { 0488 // require_once 'Zend/Service/SqlAzure/Management/Exception.php'; 0489 throw new Zend_Service_SqlAzure_Management_Exception('Server name should be specified.'); 0490 } 0491 if ($ruleName == '' || is_null($ruleName)) { 0492 // require_once 'Zend/Service/SqlAzure/Management/Exception.php'; 0493 throw new Zend_Service_SqlAzure_Management_Exception('Rule name should be specified.'); 0494 } 0495 if ($startIpAddress == '' || is_null($startIpAddress) || !filter_var($startIpAddress, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) { 0496 // require_once 'Zend/Service/SqlAzure/Management/Exception.php'; 0497 throw new Zend_Service_SqlAzure_Management_Exception('Start IP address should be specified.'); 0498 } 0499 if ($endIpAddress == '' || is_null($endIpAddress) || !filter_var($endIpAddress, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) { 0500 // require_once 'Zend/Service/SqlAzure/Management/Exception.php'; 0501 throw new Zend_Service_SqlAzure_Management_Exception('End IP address should be specified.'); 0502 } 0503 0504 $response = $this->_performRequest(self::OP_SERVERS . '/' . $serverName . '/' . self::OP_FIREWALLRULES . '/' . $ruleName, '', 0505 Zend_Http_Client::PUT, 0506 array('Content-Type' => 'application/xml; charset=utf-8'), 0507 '<FirewallRule xmlns="http://schemas.microsoft.com/sqlazure/2010/12/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://schemas.microsoft.com/sqlazure/2010/12/ FirewallRule.xsd"><StartIpAddress>' . $startIpAddress . '</StartIpAddress><EndIpAddress>' . $endIpAddress . '</EndIpAddress></FirewallRule>'); 0508 0509 if ($response->isSuccessful()) { 0510 0511 return new Zend_Service_SqlAzure_Management_FirewallRuleInstance( 0512 $ruleName, 0513 $startIpAddress, 0514 $endIpAddress 0515 ); 0516 } else { 0517 // require_once 'Zend/Service/SqlAzure/Management/Exception.php'; 0518 throw new Zend_Service_SqlAzure_Management_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.')); 0519 } 0520 } 0521 0522 /** 0523 * The Get Server Firewall Rules operation retrieves a list of all the firewall rules for a SQL Azure server that belongs to a subscription. 0524 * 0525 * @param string $serverName Server name. 0526 * @return Array of Zend_Service_SqlAzure_Management_FirewallRuleInstance. 0527 * @throws Zend_Service_SqlAzure_Management_Exception 0528 */ 0529 public function listFirewallRules($serverName) 0530 { 0531 if ($serverName == '' || is_null($serverName)) { 0532 // require_once 'Zend/Service/SqlAzure/Management/Exception.php'; 0533 throw new Zend_Service_SqlAzure_Management_Exception('Server name should be specified.'); 0534 } 0535 0536 $response = $this->_performRequest(self::OP_SERVERS . '/' . $serverName . '/' . self::OP_FIREWALLRULES); 0537 0538 if ($response->isSuccessful()) { 0539 $xml = $this->_parseResponse($response); 0540 $xmlServices = null; 0541 0542 if (!$xml->FirewallRule) { 0543 return array(); 0544 } 0545 if (count($xml->FirewallRule) > 1) { 0546 $xmlServices = $xml->FirewallRule; 0547 } else { 0548 $xmlServices = array($xml->FirewallRule); 0549 } 0550 0551 $services = array(); 0552 if (!is_null($xmlServices)) { 0553 0554 for ($i = 0; $i < count($xmlServices); $i++) { 0555 $services[] = new Zend_Service_SqlAzure_Management_FirewallRuleInstance( 0556 (string)$xmlServices[$i]->Name, 0557 (string)$xmlServices[$i]->StartIpAddress, 0558 (string)$xmlServices[$i]->EndIpAddress 0559 ); 0560 } 0561 } 0562 return $services; 0563 } else { 0564 // require_once 'Zend/Service/SqlAzure/Management/Exception.php'; 0565 throw new Zend_Service_SqlAzure_Management_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.')); 0566 } 0567 } 0568 0569 /** 0570 * The Delete Server Firewall Rule operation deletes a firewall rule from a SQL Azure server that belongs to a subscription. 0571 * 0572 * @param string $serverName Server name. 0573 * @param string $ruleName Rule name. 0574 * @throws Zend_Service_SqlAzure_Management_Exception 0575 */ 0576 public function deleteFirewallRule($serverName, $ruleName) 0577 { 0578 if ($serverName == '' || is_null($serverName)) { 0579 // require_once 'Zend/Service/SqlAzure/Management/Exception.php'; 0580 throw new Zend_Service_SqlAzure_Management_Exception('Server name should be specified.'); 0581 } 0582 if ($ruleName == '' || is_null($ruleName)) { 0583 // require_once 'Zend/Service/SqlAzure/Management/Exception.php'; 0584 throw new Zend_Service_SqlAzure_Management_Exception('Rule name should be specified.'); 0585 } 0586 0587 $response = $this->_performRequest(self::OP_SERVERS . '/' . $serverName . '/' . self::OP_FIREWALLRULES . '/' . $ruleName, '', 0588 Zend_Http_Client::DELETE); 0589 0590 if (!$response->isSuccessful()) { 0591 // require_once 'Zend/Service/SqlAzure/Management/Exception.php'; 0592 throw new Zend_Service_SqlAzure_Management_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.')); 0593 } 0594 } 0595 0596 /** 0597 * Creates a firewall rule for Microsoft Services. This is required if access to SQL Azure is required from other services like Windows Azure. 0598 * 0599 * @param string $serverName Server name. 0600 * @param boolean $allowAccess Allow access from other Microsoft Services? 0601 * @throws Zend_Service_SqlAzure_Management_Exception 0602 */ 0603 public function createFirewallRuleForMicrosoftServices($serverName, $allowAccess) 0604 { 0605 if ($allowAccess) { 0606 $this->createFirewallRule($serverName, 'MicrosoftServices', '0.0.0.0', '0.0.0.0'); 0607 } else { 0608 $this->deleteFirewallRule($serverName, 'MicrosoftServices'); 0609 } 0610 } 0611 0612 }