/** * Performs upgrade literally for the stage ONE. * * Implementation of this method performs update steps needs to be taken * to accomplish upgrade successfully. * * If there are any error during an execution of this scenario it must * throw an exception. * * @param int $stage optional The stage number * @throws \Exception */ protected function run1($stage) { $observers = $this->db->Execute("SELECT * FROM farm_event_observers WHERE event_observer_name = 'MailEventObserver'"); while ($observer = $observers->FetchRow()) { $dbFarm = \DBFarm::LoadByID($observer['farmid']); // Create endpoint $endpointId = $this->db->GetOne("SELECT endpoint_id FROM webhook_endpoints WHERE env_id = ? AND url = ?", array($dbFarm->EnvID, 'SCALR_MAIL_SERVICE')); if ($endpointId) { $endpoint = WebhookEndpoint::findPk(bin2hex($endpointId)); } else { $endpoint = new WebhookEndpoint(); $endpoint->level = WebhookEndpoint::LEVEL_ENVIRONMENT; $endpoint->accountId = $dbFarm->ClientID; $endpoint->envId = $dbFarm->EnvID; $endpoint->securityKey = \Scalr::GenerateRandomKey(64); $endpoint->isValid = true; $endpoint->url = "SCALR_MAIL_SERVICE"; $endpoint->save(); } //Create webhook configuration $webhook = new WebhookConfig(); $webhook->level = WebhookConfig::LEVEL_ENVIRONMENT; $webhook->accountId = $dbFarm->ClientID; $webhook->envId = $dbFarm->EnvID; $webhook->name = "MailEventObserver(FarmID: {$dbFarm->ID})"; $webhook->postData = $this->db->GetOne("SELECT value FROM farm_event_observers_config WHERE `key` = ? AND observerid = ?", array('EventMailTo', $observer['id'])); $webhook->save(); //save endpoints $configEndpoint = new WebhookConfigEndpoint(); $configEndpoint->webhookId = $webhook->webhookId; $configEndpoint->setEndpoint($endpoint); $configEndpoint->save(); //save events $dbEvents = $this->db->Execute("SELECT * FROM farm_event_observers_config WHERE `key` LIKE '%Notify' AND observerid = ?", array($observer['id'])); while ($info = $dbEvents->FetchRow()) { preg_match('/On([A-Za-z0-9]+)Notify/si', $info['key'], $matches); $configEvent = new WebhookConfigEvent(); $configEvent->webhookId = $webhook->webhookId; $configEvent->eventType = $matches[1]; $configEvent->save(); } //save farms $configFarm = new WebhookConfigFarm(); $configFarm->webhookId = $webhook->webhookId; $configFarm->farmId = $dbFarm->ID; $configFarm->save(); } }
public function getWebhooksEndpointsList() { $list = array(); foreach (WebhookEndpoint::findByEnvId($this->getEnvironmentId()) as $entity) { $list[] = array('endpointId' => $entity->endpointId, 'url' => $entity->url, 'isValid' => $entity->isValid, 'validationToken' => $entity->validationToken, 'securityKey' => $entity->securityKey); } return $list; }
public function OnStartForking() { $db = \Scalr::getDb(); // Get pid of running daemon $pid = @file_get_contents(CACHEPATH . "/" . __CLASS__ . ".Daemon.pid"); $this->Logger->info("Current daemon process PID: {$pid}"); // Check is daemon already running or not if ($pid) { $Shell = new Scalr_System_Shell(); // Set terminal width putenv("COLUMNS=400"); // Execute command $ps = $Shell->queryRaw("ps ax -o pid,ppid,command | grep ' 1' | grep {$pid} | grep -v 'ps x' | grep DBQueueEvent"); $this->Logger->info("Shell->queryRaw(): {$ps}"); if ($ps) { // daemon already running $this->Logger->info("Daemon running. All ok!"); return true; } } $rows = $db->Execute("SELECT history_id FROM webhook_history WHERE status='0'"); while ($row = $rows->FetchRow()) { $history = WebhookHistory::findPk(bin2hex($row['history_id'])); if (!$history) { continue; } $endpoint = WebhookEndpoint::findPk($history->endpointId); $request = new HttpRequest(); $request->setMethod(HTTP_METH_POST); if ($endpoint->url == 'SCALR_MAIL_SERVICE') { $request->setUrl('https://my.scalr.com/webhook_mail.php'); } else { $request->setUrl($endpoint->url); } $request->setOptions(array('timeout' => 3, 'connecttimeout' => 3)); $dt = new DateTime('now', new DateTimeZone("UTC")); $timestamp = $dt->format("D, d M Y H:i:s e"); $canonical_string = $history->payload . $timestamp; $signature = hash_hmac('SHA1', $canonical_string, $endpoint->securityKey); $request->addHeaders(array('Date' => $timestamp, 'X-Signature' => $signature, 'X-Scalr-Webhook-Id' => $history->historyId, 'Content-type' => 'application/json')); $request->setBody($history->payload); try { $request->send(); $history->responseCode = $request->getResponseCode(); if ($request->getResponseCode() <= 205) { $history->status = WebhookHistory::STATUS_COMPLETE; } else { $history->status = WebhookHistory::STATUS_FAILED; } } catch (Exception $e) { $history->status = WebhookHistory::STATUS_FAILED; } $history->save(); } }
private function getEndpoints() { $endpoints = array(); $criteria = []; switch ($this->request->getScope()) { case WebhookEndpoint::SCOPE_ENVIRONMENT: $criteria[] = ['$or' => [['$and' => [['accountId' => $this->user->getAccountId()], ['envId' => $this->getEnvironmentId()], ['level' => WebhookEndpoint::LEVEL_ENVIRONMENT]]], ['$and' => [['accountId' => $this->user->getAccountId()], ['envId' => null], ['level' => WebhookEndpoint::LEVEL_ACCOUNT]]], ['$and' => [['accountId' => null], ['envId' => null], ['level' => WebhookEndpoint::LEVEL_SCALR]]]]]; break; case WebhookEndpoint::SCOPE_ACCOUNT: $criteria[] = ['$or' => [['$and' => [['accountId' => $this->user->getAccountId()], ['envId' => null], ['level' => WebhookEndpoint::LEVEL_ACCOUNT]]], ['$and' => [['accountId' => null], ['envId' => null], ['level' => WebhookEndpoint::LEVEL_SCALR]]]]]; break; case WebhookEndpoint::SCOPE_SCALR: $criteria[] = ['level' => WebhookEndpoint::LEVEL_SCALR]; $criteria[] = ['envId' => null]; $criteria[] = ['accountId' => null]; break; } foreach (WebhookEndpoint::find($criteria) as $entity) { $endpoints[] = ['id' => $entity->endpointId, 'url' => $entity->url, 'isValid' => $entity->isValid, 'scope' => $entity->getScope()]; } return $endpoints; }
/** * @param string $scope * @return array * @throws Scalr_Exception_Core */ private function getList($scope = '') { $endpoints = array(); $criteria = []; switch ($this->request->getScope()) { case WebhookEndpoint::SCOPE_ENVIRONMENT: $criteria[] = ['$or' => [['$and' => [['accountId' => $this->user->getAccountId()], ['envId' => $this->getEnvironmentId()], ['level' => WebhookEndpoint::LEVEL_ENVIRONMENT]]], ['$and' => [['accountId' => $this->user->getAccountId()], ['envId' => null], ['level' => WebhookEndpoint::LEVEL_ACCOUNT]]], ['$and' => [['accountId' => null], ['envId' => null], ['level' => WebhookEndpoint::LEVEL_SCALR]]]]]; break; case WebhookEndpoint::SCOPE_ACCOUNT: $criteria[] = ['$or' => [['$and' => [['accountId' => $this->user->getAccountId()], ['envId' => null], ['level' => WebhookEndpoint::LEVEL_ACCOUNT]]], ['$and' => [['accountId' => null], ['envId' => null], ['level' => WebhookEndpoint::LEVEL_SCALR]]]]]; break; case WebhookEndpoint::SCOPE_SCALR: $criteria[] = ['level' => WebhookEndpoint::LEVEL_SCALR]; $criteria[] = ['envId' => null]; $criteria[] = ['accountId' => null]; break; } $scopeLinking = [ScopeInterface::SCOPE_SCALR => WebhookEndpoint::LEVEL_SCALR, ScopeInterface::SCOPE_ACCOUNT => WebhookEndpoint::LEVEL_ACCOUNT, ScopeInterface::SCOPE_ENVIRONMENT => WebhookEndpoint::LEVEL_ENVIRONMENT]; if ($scope && array_key_exists($scope, $scopeLinking)) { $criteria[] = ['level' => $scopeLinking[$scope]]; } foreach (WebhookEndpoint::find($criteria) as $entity) { $webhooks = array(); foreach (WebhookConfigEndpoint::findByEndpointId($entity->endpointId) as $WebhookConfigEndpoint) { $webhooks[$WebhookConfigEndpoint->webhookId] = WebhookConfig::findPk($WebhookConfigEndpoint->webhookId)->name; } $endpoint = array('endpointId' => $entity->endpointId, 'url' => $entity->url, 'scope' => $entity->getScope()); if ($this->request->getScope() == $entity->getScope()) { $endpoint['isValid'] = $entity->isValid; $endpoint['validationToken'] = $entity->validationToken; $endpoint['securityKey'] = $entity->securityKey; $endpoint['webhooks'] = $webhooks; } $endpoints[] = $endpoint; } return $endpoints; }
public function xValidateAction() { $endpoint = WebhookEndpoint::findPk($this->request->getParam('endpointId')); if ($endpoint->envId != $this->getEnvironmentId() || $endpoint->accountId != $this->getEnvironment()->clientId) { throw new Scalr_Exception_Core('Insufficient permissions to edit endpoint'); } if ($endpoint->url != $this->request->getParam('url')) { $endpoint->url = $this->request->getParam('url'); $endpoint->save(); } if ($endpoint->validateUrl()) { $this->response->success(sprintf('Endpoint %s successfully validated', $endpoint->url)); } else { $this->response->failure(sprintf('Unable to validate endpoint %s. Token was not returned.', $endpoint->url)); } $this->response->data(array('endpoint' => array('endpointId' => $endpoint->endpointId, 'url' => $endpoint->url, 'isValid' => $endpoint->isValid, 'validationToken' => $endpoint->validationToken, 'securityKey' => $endpoint->securityKey))); }
<?php require __DIR__ . '/src/prepend.inc.php'; use Scalr\Model\Entity\WebhookHistory; use Scalr\Model\Entity\WebhookEndpoint; use Scalr\Model\Entity\WebhookConfig; try { $webhookId = $_SERVER['HTTP_X_SCALR_WEBHOOK_ID']; $signature = $_SERVER['HTTP_X_SIGNATURE']; $date = $_SERVER['HTTP_DATE']; $history = WebhookHistory::findPk($webhookId); if (!$history) { throw new Exception("Bad request (1)"); } $endpoint = WebhookEndpoint::findPk($history->endpointId); $webhook = WebhookConfig::findPk($history->webhookId); $canonicalString = $history->payload . $date; $validSignature = hash_hmac('SHA1', $canonicalString, $endpoint->securityKey); if ($signature != $validSignature) { throw new Exception("Bad request (2)"); } $payload = json_decode($history->payload); $text = "\n========= Event ========\n\nEVENT_NAME: {$payload->eventName}\nEVENT_ID: {$payload->eventId}\n\n========= Farm ========\n\nFARM_ID: {$payload->data->SCALR_EVENT_FARM_ID}\nFARM_NAME: {$payload->data->SCALR_EVENT_FARM_NAME}\n\n========= Role ========\n\nFARM_ROLE_ID: {$payload->data->SCALR_EVENT_FARM_ROLE_ID}\nROLE_NAME: {$payload->data->SCALR_FARM_ROLE_ALIAS}\n\n========= Server =========\n\nSERVER_ID: {$payload->data->SCALR_EVENT_SERVER_ID}\nCLOUD_SERVER_ID: {$payload->data->SCALR_EVENT_CLOUD_SERVER_ID}\nPUBLIC_IP: {$payload->data->SCALR_EVENT_INTERNAL_IP}\nPRIVATE_IP: {$payload->data->SCALR_EVENT_EXTERNAL_IP}\nCLOUD_LOCATION: {$payload->data->SCALR_EVENT_CLOUD_LOCATION}\nCLOUD_LOCATION_ZONE: {$payload->data->SCALR_EVENT_CLOUD_LOCATION_ZONE}\n"; $subject = "{$payload->data->SCALR_EVENT_FARM_NAME}: {$payload->eventName} on {$payload->data->SCALR_EVENT_SERVER_ID} ({$payload->data->SCALR_EVENT_EXTERNAL_IP})"; $mailer = Scalr::getContainer()->mailer->setFrom('*****@*****.**', 'Scalr')->setMessage($text)->setSubject($subject); $emails = explode(",", $webhook->postData); foreach ($emails as $email) { if ($email) { $mailer->send($email); } }
/** * Fetches endpoint from database * * @return WebhookEndpoint|null Returns endpoint object or null */ public function fetchEndpoint() { $this->_endpoint = WebhookEndpoint::findPk($this->endpointId); return $this->_endpoint; }
public function xSaveAction() { $this->request->defineParams(array('endpoints' => array('type' => 'json'), 'action', 'events' => array('type' => 'json'), 'action', 'farms' => array('type' => 'json'), 'action')); if (!$this->request->getParam('webhookId')) { $webhook = new WebhookConfig(); $webhook->level = WebhookConfig::LEVEL_ENVIRONMENT; $webhook->accountId = $this->getEnvironment()->clientId; $webhook->envId = $this->getEnvironmentId(); } else { $webhook = WebhookConfig::findPk($this->request->getParam('webhookId')); if ($webhook->envId != $this->getEnvironmentId() || $webhook->accountId != $this->getEnvironment()->clientId) { throw new Scalr_Exception_Core('Insufficient permissions to edit webhook'); } } $webhook->name = $this->request->getParam('name'); $webhook->postData = $this->request->getParam('postData'); $webhook->skipPrivateGv = $this->request->getParam('skipPrivateGv') == 'on' ? 1 : 0; $webhook->save(); //save endpoints $endpoints = $this->getParam('endpoints'); foreach (WebhookConfigEndpoint::findByWebhookId($webhook->webhookId) as $endpoint) { $index = array_search($endpoint->endpointId, $endpoints); if ($index === false) { $endpoint->delete(); } else { unset($endpoints[$index]); } } if (!empty($endpoints)) { $endpoints = WebhookEndpoint::find(array(array('accountId' => $this->getEnvironment()->clientId), array('envId' => $this->getEnvironmentId()), array('endpointId' => array('$in' => $endpoints)))); foreach ($endpoints as $endpoint) { $configEndpoint = new WebhookConfigEndpoint(); $configEndpoint->webhookId = $webhook->webhookId; $configEndpoint->setEndpoint($endpoint); $configEndpoint->save(); } } //save events $events = $this->getParam('events'); $allEvents = $this->getEventsList(); foreach (WebhookConfigEvent::findByWebhookId($webhook->webhookId) as $event) { $index = array_search($event->eventType, $events); if ($index === false) { if (isset($allEvents[$event->eventType])) { //20486-rebundlecomplete-emails - we shouldn't remove some events(RebundleComplete...) $event->delete(); } } else { unset($events[$index]); } } foreach ($events as $event) { /*if (!isset(EVENT_TYPE::getScriptingEvents()[$event])) { continue; }*/ $configEvent = new WebhookConfigEvent(); $configEvent->webhookId = $webhook->webhookId; $configEvent->eventType = $event; $configEvent->save(); } //save farms $farms = $this->getParam('farms'); if (empty($farms)) { $farms = array(0); } foreach (WebhookConfigFarm::findByWebhookId($webhook->webhookId) as $farm) { $index = array_search($farm->farmId, $farms); if ($index === false) { $farm->delete(); } else { unset($farms[$index]); } } foreach ($farms as $farmId) { $configFarm = new WebhookConfigFarm(); $configFarm->webhookId = $webhook->webhookId; $configFarm->farmId = $farmId; $configFarm->save(); } $endpoints = array(); foreach ($webhook->getEndpoints() as $endpoint) { $endpoints[] = $endpoint->endpointId; } $events = array(); foreach ($webhook->getEvents() as $event) { $events[] = $event->eventType; } $farms = array(); foreach ($webhook->getFarms() as $farm) { if ($farm->farmId) { $farms[] = $farm->farmId; } } $this->response->data(array('webhook' => array('webhookId' => $webhook->webhookId, 'name' => $webhook->name, 'postData' => $webhook->postData, 'skipPrivateGv' => $webhook->skipPrivateGv, 'endpoints' => $endpoints, 'events' => $events, 'farms' => $farms))); }