PageRenderTime 26ms CodeModel.GetById 9ms RepoModel.GetById 0ms app.codeStats 0ms

/scalr-2/tags/scalr-2.1.0/app/src/api/class.ScalrAPICore.php

http://scalr.googlecode.com/
PHP | 248 lines | 223 code | 16 blank | 9 comment | 8 complexity | 8a2becd194ef5cf32332c74ad2f59772 MD5 | raw file
Possible License(s): LGPL-2.1, Apache-2.0, GPL-3.0
  1. <?php
  2. define("API_SERVER_IP", "174.132.108.66");
  3. abstract class ScalrAPICore
  4. {
  5. const HASH_ALGO = 'SHA256';
  6. protected $Request;
  7. /**
  8. *
  9. * @var Client
  10. */
  11. protected $Client;
  12. /**
  13. *
  14. * @var Scalr_Environment
  15. */
  16. protected $Environment;
  17. protected $DB;
  18. protected $Logger;
  19. public $Version;
  20. protected $LastTransactionID;
  21. function __construct($version)
  22. {
  23. $this->DB = Core::GetDBInstance();
  24. $this->Logger = Logger::getLogger(__CLASS__);
  25. $this->Version = $version;
  26. }
  27. private function AuthenticateREST($request)
  28. {
  29. if (!$request['Signature'])
  30. throw new Exception("Signature is missing");
  31. if (!$request['KeyID'])
  32. throw new Exception("KeyID is missing");
  33. if (!$request['Timestamp'] && !$request['TimeStamp'])
  34. throw new Exception("Timestamp is missing");
  35. //TODO: Validate TimeStamp
  36. ksort($request);
  37. $string_to_sign = "";
  38. foreach ($request as $k=>$v)
  39. {
  40. if (!in_array($k, array("Signature")))
  41. {
  42. if (is_array($v))
  43. {
  44. foreach ($v as $kk => $vv)
  45. $string_to_sign.= "{$k}[{$kk}]{$vv}";
  46. }
  47. else
  48. $string_to_sign.= "{$k}{$v}";
  49. }
  50. }
  51. $this->Environment = Scalr_Model::init(Scalr_Model::ENVIRONMENT)->loadByApiKeyId($request['KeyID']);
  52. $this->Client = Client::Load($this->Environment->clientId);
  53. $auth_key = $this->Environment->getPlatformConfigValue(ENVIRONMENT_SETTINGS::API_ACCESS_KEY, false);
  54. $valid_sign = base64_encode(hash_hmac(self::HASH_ALGO, $string_to_sign, $auth_key, 1));
  55. if ($valid_sign != $request['Signature'])
  56. throw new Exception("Signature doesn't match");
  57. }
  58. public function BuildRestServer($request)
  59. {
  60. try
  61. {
  62. $Reflect = new ReflectionObject($this);
  63. if ($Reflect->hasMethod($request['Action']))
  64. {
  65. //Authenticate
  66. $this->AuthenticateREST($request);
  67. if ($this->Environment->getPlatformConfigValue(ENVIRONMENT_SETTINGS::API_ENABLED) != 1)
  68. throw new Exception(_("API disabled for you. You can enable it at 'Settings -> Environments'"));
  69. //Check IP Addresses
  70. if ($this->Environment->getPlatformConfigValue(ENVIRONMENT_SETTINGS::API_ALLOWED_IPS))
  71. {
  72. $ips = explode(",", $this->Environment->getPlatformConfigValue(ENVIRONMENT_SETTINGS::API_ALLOWED_IPS));
  73. if (!$this->IPAccessCheck($ips) && $_SERVER['REMOTE_ADDR'] != API_SERVER_IP)
  74. throw new Exception(sprintf(_("Access to the API is not allowed from your IP '%s'"), $_SERVER['REMOTE_ADDR']));
  75. }
  76. //Execute API call
  77. $ReflectMethod = $Reflect->getMethod($request['Action']);
  78. $args = array();
  79. foreach ($ReflectMethod->getParameters() as $param)
  80. {
  81. if (!$param->isOptional() && !isset($request[$param->getName()]))
  82. throw new Exception(sprintf("Missing required parameter '%s'", $param->getName()));
  83. else
  84. $args[$param->getName()] = $request[$param->getName()];
  85. }
  86. $result = $ReflectMethod->invokeArgs($this, $args);
  87. $this->LastTransactionID = $result->TransactionID;
  88. // Create response
  89. $DOMDocument = new DOMDocument('1.0', 'UTF-8');
  90. $DOMDocument->loadXML("<{$request['Action']}Response></{$request['Action']}Response>");
  91. $this->ObjectToXML($result, $DOMDocument->documentElement, $DOMDocument);
  92. $retval = $DOMDocument->saveXML();
  93. }
  94. else
  95. throw new Exception(sprintf("Action '%s' is not defined", $request['Action']));
  96. }
  97. catch(Exception $e)
  98. {
  99. if (!$this->LastTransactionID)
  100. $this->LastTransactionID = Scalr::GenerateUID();
  101. $retval = "<?xml version=\"1.0\"?>\n".
  102. "<Error>\n".
  103. "\t<TransactionID>{$this->LastTransactionID}</TransactionID>\n".
  104. "\t<Message>{$e->getMessage()}</Message>\n".
  105. "</Error>\n";
  106. }
  107. $this->LogRequest(
  108. $this->LastTransactionID,
  109. $request['Action'],
  110. (($_SERVER['REMOTE_ADDR'] == API_SERVER_IP) ? 'Mobile app' : $_SERVER['REMOTE_ADDR']),
  111. $request,
  112. $retval
  113. );
  114. header("Content-type: text/xml");
  115. header("Content-length: ".strlen($retval));
  116. print $retval;
  117. }
  118. protected function LogRequest($trans_id, $action, $ipaddr, $request, $response)
  119. {
  120. if ($request['debug'] == 1)
  121. {
  122. try
  123. {
  124. $this->DB->Execute("INSERT INTO api_log SET
  125. transaction_id = ?,
  126. dtadded = ?,
  127. action = ?,
  128. ipaddress = ?,
  129. request = ?,
  130. response = ?,
  131. clientid = ?,
  132. env_id = ?
  133. ",array(
  134. $trans_id,
  135. time(),
  136. $action,
  137. $ipaddr,
  138. http_build_query($request),
  139. $response,
  140. $this->Client->ID,
  141. $this->Environment->id
  142. ));
  143. }
  144. catch(Exception $e) {}
  145. }
  146. }
  147. protected function IPAccessCheck($allowed_ips)
  148. {
  149. $current_ip = $_SERVER['REMOTE_ADDR'];
  150. $current_ip_parts = explode(".", $current_ip);
  151. foreach ($allowed_ips as $allowed_ip)
  152. {
  153. $allowedhost = trim($allowed_ip);
  154. if ($allowedhost == '')
  155. continue;
  156. if (preg_match("/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/si", $allowedhost))
  157. {
  158. if (ip2long($allowedhost) == ip2long($current_ip))
  159. return true;
  160. }
  161. elseif (stristr($allowedhost, "*"))
  162. {
  163. $ip_parts = explode(".", trim($allowedhost));
  164. if (
  165. ($ip_parts[0] == "*" || $ip_parts[0] == $current_ip_parts[0]) &&
  166. ($ip_parts[1] == "*" || $ip_parts[1] == $current_ip_parts[1]) &&
  167. ($ip_parts[2] == "*" || $ip_parts[2] == $current_ip_parts[2]) &&
  168. ($ip_parts[3] == "*" || $ip_parts[3] == $current_ip_parts[3])
  169. )
  170. return true;
  171. }
  172. else
  173. {
  174. $ip = @gethostbyname($allowedhost);
  175. if ($ip != $allowedhost)
  176. {
  177. if (ip2long($ip) == ip2long($current_ip))
  178. return true;
  179. }
  180. }
  181. }
  182. return false;
  183. }
  184. protected function ObjectToXML($obj, &$DOMElement, &$DOMDocument)
  185. {
  186. if (is_object($obj) || is_array($obj))
  187. {
  188. foreach ($obj as $k=>$v)
  189. {
  190. if (is_object($v))
  191. $this->ObjectToXML($v, $DOMElement->appendChild($DOMDocument->createElement($k)), $DOMDocument);
  192. elseif (is_array($v))
  193. foreach ($v as $vv)
  194. {
  195. $e = &$DOMElement->appendChild($DOMDocument->createElement($k));
  196. $this->ObjectToXML($vv, $e, $DOMDocument);
  197. }
  198. else
  199. $DOMElement->appendChild($DOMDocument->createElement($k, $v));
  200. }
  201. }
  202. else
  203. $DOMElement->appendChild($DOMDocument->createTextNode($obj));
  204. }
  205. protected function CreateInitialResponse()
  206. {
  207. $response = new stdClass();
  208. $response->{"TransactionID"} = Scalr::GenerateUID();
  209. return $response;
  210. }
  211. }
  212. ?>