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

/demo/scalr_newui/app/src/api/2.3.0/class.ScalrAPICore.php

https://github.com/kennethjiang/Wolke
PHP | 362 lines | 323 code | 31 blank | 8 comment | 16 complexity | 45426b8260bd26df7b58e6b3b1931d3c MD5 | raw file
  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 $debug = array();
  21. protected $LastTransactionID;
  22. function __construct($version)
  23. {
  24. $this->DB = Core::GetDBInstance();
  25. $this->Logger = Logger::getLogger(__CLASS__);
  26. $this->Version = $version;
  27. }
  28. protected function insensitiveUksort($a,$b) {
  29. return strtolower($a)>strtolower($b);
  30. }
  31. private function AuthenticateRESTv3($request)
  32. {
  33. if (!$request['Signature'])
  34. throw new Exception("Signature is missing");
  35. if (!$request['KeyID'])
  36. throw new Exception("KeyID is missing");
  37. if (!$request['Timestamp'] && !$request['TimeStamp'])
  38. throw new Exception("Timestamp is missing");
  39. if ($request['Timestamp'])
  40. $request['TimeStamp'] = $request['Timestamp'];
  41. $string_to_sign = "{$request['Action']}:{$request['KeyID']}:{$request['TimeStamp']}";
  42. $this->debug['stringToSign'] = $string_to_sign;
  43. $this->Environment = Scalr_Model::init(Scalr_Model::ENVIRONMENT)->loadByApiKeyId($request['KeyID']);
  44. $auth_key = $this->Environment->getPlatformConfigValue(ENVIRONMENT_SETTINGS::API_ACCESS_KEY, false);
  45. $valid_sign = base64_encode(hash_hmac(self::HASH_ALGO, trim($string_to_sign), $auth_key, 1));
  46. $request['Signature'] = str_replace(" ", "+", $request['Signature']);
  47. $this->debug['reqSignature'] = $request['Signature'];
  48. $this->debug['validSignature'] = $valid_sign;
  49. $this->debug['usedAuthVersion'] = 3;
  50. $this->debug['md5AccessKey'] = md5($auth_key);
  51. if ($valid_sign != $request['Signature'])
  52. throw new Exception("Signature doesn't match");
  53. }
  54. private function AuthenticateRESTv2($request)
  55. {
  56. if (!$request['Signature'])
  57. throw new Exception("Signature is missing");
  58. if (!$request['KeyID'])
  59. throw new Exception("KeyID is missing");
  60. if (!$request['Timestamp'] && !$request['TimeStamp'])
  61. throw new Exception("Timestamp is missing");
  62. foreach ($request as $k=>$v)
  63. {
  64. if (is_array($v))
  65. {
  66. foreach ($v as $kk => $vv)
  67. $request["{$k}[{$kk}]"] = $vv;
  68. unset($request[$k]);
  69. }
  70. }
  71. uksort($request, array($this, 'insensitiveUksort'));
  72. $string_to_sign = "";
  73. foreach ($request as $k=>$v)
  74. {
  75. if (!in_array($k, array("Signature", "SysDebug"))) {
  76. if (is_array($v)) {
  77. foreach ($v as $kk => $vv) {
  78. $string_to_sign.= "{$k}[{$kk}]{$vv}";
  79. }
  80. }
  81. else {
  82. $string_to_sign.= "{$k}{$v}";
  83. }
  84. }
  85. }
  86. $this->debug['stringToSign'] = $string_to_sign;
  87. $this->Environment = Scalr_Model::init(Scalr_Model::ENVIRONMENT)->loadByApiKeyId($request['KeyID']);
  88. $this->Client = Client::Load($this->Environment->clientId);
  89. $auth_key = $this->Environment->getPlatformConfigValue(ENVIRONMENT_SETTINGS::API_ACCESS_KEY, false);
  90. $valid_sign = base64_encode(hash_hmac(self::HASH_ALGO, trim($string_to_sign), $auth_key, 1));
  91. $request['Signature'] = str_replace(" ", "+", $request['Signature']);
  92. $this->debug['reqSignature'] = $request['Signature'];
  93. $this->debug['validSignature'] = $valid_sign;
  94. if ($valid_sign != $request['Signature'])
  95. throw new Exception("Signature doesn't match");
  96. }
  97. private function AuthenticateREST($request)
  98. {
  99. if (!$request['Signature'])
  100. throw new Exception("Signature is missing");
  101. if (!$request['KeyID'])
  102. throw new Exception("KeyID is missing");
  103. if (!$request['Timestamp'] && !$request['TimeStamp'])
  104. throw new Exception("Timestamp is missing");
  105. ksort($request);
  106. $string_to_sign = "";
  107. foreach ($request as $k=>$v) {
  108. if (!in_array($k, array("Signature"))) {
  109. if (is_array($v)) {
  110. foreach ($v as $kk => $vv) {
  111. $string_to_sign.= "{$k}[{$kk}]{$vv}";
  112. }
  113. }
  114. else {
  115. $string_to_sign.= "{$k}{$v}";
  116. }
  117. }
  118. }
  119. $this->debug['stringToSign'] = $string_to_sign;
  120. $this->Environment = Scalr_Model::init(Scalr_Model::ENVIRONMENT)->loadByApiKeyId($request['KeyID']);
  121. $this->Client = Client::Load($this->Environment->clientId);
  122. $auth_key = $this->Environment->getPlatformConfigValue(ENVIRONMENT_SETTINGS::API_ACCESS_KEY, false);
  123. $valid_sign = base64_encode(hash_hmac(self::HASH_ALGO, trim($string_to_sign), $auth_key, 1));
  124. if ($valid_sign != $request['Signature'])
  125. throw new Exception("Signature doesn't match");
  126. }
  127. public function BuildRestServer($request)
  128. {
  129. try
  130. {
  131. $Reflect = new ReflectionObject($this);
  132. if ($Reflect->hasMethod($request['Action']))
  133. {
  134. //Authenticate
  135. if ($request['AuthVersion'] == 2)
  136. $this->AuthenticateRESTv2($request);
  137. elseif ($request['AuthVersion'] == 3)
  138. $this->AuthenticateRESTv3($request);
  139. else
  140. $this->AuthenticateREST($request);
  141. if ($this->Environment->getPlatformConfigValue(ENVIRONMENT_SETTINGS::API_ENABLED) != 1)
  142. throw new Exception(_("API disabled for you. You can enable it at 'Settings -> Environments'"));
  143. //Check IP Addresses
  144. if ($this->Environment->getPlatformConfigValue(ENVIRONMENT_SETTINGS::API_ALLOWED_IPS))
  145. {
  146. $ips = explode(",", $this->Environment->getPlatformConfigValue(ENVIRONMENT_SETTINGS::API_ALLOWED_IPS));
  147. if (!$this->IPAccessCheck($ips) && $_SERVER['REMOTE_ADDR'] != API_SERVER_IP)
  148. throw new Exception(sprintf(_("Access to the API is not allowed from your IP '%s'"), $_SERVER['REMOTE_ADDR']));
  149. }
  150. //Execute API call
  151. $ReflectMethod = $Reflect->getMethod($request['Action']);
  152. $args = array();
  153. foreach ($ReflectMethod->getParameters() as $param)
  154. {
  155. if (!$param->isOptional() && !isset($request[$param->getName()]))
  156. throw new Exception(sprintf("Missing required parameter '%s'", $param->getName()));
  157. else
  158. $args[$param->getName()] = $request[$param->getName()];
  159. }
  160. $result = $ReflectMethod->invokeArgs($this, $args);
  161. $this->LastTransactionID = $result->TransactionID;
  162. // Create response
  163. $DOMDocument = new DOMDocument('1.0', 'UTF-8');
  164. $DOMDocument->loadXML("<{$request['Action']}Response></{$request['Action']}Response>");
  165. $this->ObjectToXML($result, $DOMDocument->documentElement, $DOMDocument);
  166. $retval = $DOMDocument->saveXML();
  167. }
  168. else
  169. throw new Exception(sprintf("Action '%s' is not defined", $request['Action']));
  170. }
  171. catch(Exception $e)
  172. {
  173. if (!$this->LastTransactionID)
  174. $this->LastTransactionID = Scalr::GenerateUID();
  175. if ($request['SysDebug'])
  176. {
  177. $debugInfo = "<StringToSign>{$this->debug['stringToSign']}</StringToSign>";
  178. $debugInfo .= "<reqSignature>{$this->debug['reqSignature']}</reqSignature>";
  179. $debugInfo .= "<validSignature>{$this->debug['validSignature']}</validSignature>";
  180. $debugInfo .= "<md5AccessKey>{$this->debug['md5AccessKey']}</md5AccessKey>";
  181. $debugInfo .= "<usedAuthVersion>{$this->debug['usedAuthVersion']}</usedAuthVersion>";
  182. }
  183. $retval = "<?xml version=\"1.0\"?>\n".
  184. "<Error>\n".
  185. "\t<TransactionID>{$this->LastTransactionID}</TransactionID>\n".
  186. "\t<Message>{$e->getMessage()}</Message>\n".
  187. $debugInfo.
  188. "</Error>\n";
  189. }
  190. $this->LogRequest(
  191. $this->LastTransactionID,
  192. $request['Action'],
  193. (($_SERVER['REMOTE_ADDR'] == API_SERVER_IP) ? 'Mobile app' : $_SERVER['REMOTE_ADDR']),
  194. $request,
  195. $retval
  196. );
  197. header("Content-type: text/xml");
  198. header("Content-length: ".strlen($retval));
  199. print $retval;
  200. }
  201. protected function LogRequest($trans_id, $action, $ipaddr, $request, $response)
  202. {
  203. if ($request['debug'] == 1 || $request['Debug'] == 1 || $request['Action'] == 'DNSZoneRecordAdd')
  204. {
  205. try
  206. {
  207. $this->DB->Execute("INSERT INTO api_log SET
  208. transaction_id = ?,
  209. dtadded = ?,
  210. action = ?,
  211. ipaddress = ?,
  212. request = ?,
  213. response = ?,
  214. clientid = ?,
  215. env_id = ?
  216. ",array(
  217. $trans_id,
  218. time(),
  219. $action,
  220. $ipaddr,
  221. http_build_query($request),
  222. $response,
  223. $this->Client->ID,
  224. $this->Environment->id
  225. ));
  226. }
  227. catch(Exception $e) {}
  228. }
  229. }
  230. protected function IPAccessCheck($allowed_ips)
  231. {
  232. $current_ip = $_SERVER['REMOTE_ADDR'];
  233. $current_ip_parts = explode(".", $current_ip);
  234. foreach ($allowed_ips as $allowed_ip)
  235. {
  236. $allowedhost = trim($allowed_ip);
  237. if ($allowedhost == '')
  238. continue;
  239. if (preg_match("/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/si", $allowedhost))
  240. {
  241. if (ip2long($allowedhost) == ip2long($current_ip))
  242. return true;
  243. }
  244. elseif (stristr($allowedhost, "*"))
  245. {
  246. $ip_parts = explode(".", trim($allowedhost));
  247. if (
  248. ($ip_parts[0] == "*" || $ip_parts[0] == $current_ip_parts[0]) &&
  249. ($ip_parts[1] == "*" || $ip_parts[1] == $current_ip_parts[1]) &&
  250. ($ip_parts[2] == "*" || $ip_parts[2] == $current_ip_parts[2]) &&
  251. ($ip_parts[3] == "*" || $ip_parts[3] == $current_ip_parts[3])
  252. )
  253. return true;
  254. }
  255. else
  256. {
  257. $ip = @gethostbyname($allowedhost);
  258. if ($ip != $allowedhost)
  259. {
  260. if (ip2long($ip) == ip2long($current_ip))
  261. return true;
  262. }
  263. }
  264. }
  265. return false;
  266. }
  267. protected function ObjectToXML($obj, &$DOMElement, &$DOMDocument)
  268. {
  269. if (is_object($obj) || is_array($obj))
  270. {
  271. foreach ($obj as $k=>$v)
  272. {
  273. if (is_object($v))
  274. $this->ObjectToXML($v, $DOMElement->appendChild($DOMDocument->createElement($k)), $DOMDocument);
  275. elseif (is_array($v))
  276. foreach ($v as $vv)
  277. {
  278. $e = &$DOMElement->appendChild($DOMDocument->createElement($k));
  279. $this->ObjectToXML($vv, $e, $DOMDocument);
  280. }
  281. else
  282. $DOMElement->appendChild($DOMDocument->createElement($k, $v));
  283. }
  284. }
  285. else
  286. $DOMElement->appendChild($DOMDocument->createTextNode($obj));
  287. }
  288. protected function CreateInitialResponse()
  289. {
  290. $response = new stdClass();
  291. $response->{"TransactionID"} = Scalr::GenerateUID();
  292. return $response;
  293. }
  294. }
  295. ?>