/** * @param string $historyId * @throws Exception */ public function xGetInfoAction($historyId) { $history = WebhookHistory::findPk($historyId); $webhook = WebhookConfig::findPk($history->webhookId); if (!$this->canViewPayload($webhook)) { throw new Scalr_Exception_InsufficientPermissions(); } $this->response->data(array('info' => array('historyId' => $history->historyId, 'payload' => $history->payload))); }
/** * 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 getWebhooksConfigsList() { $list = array(); foreach (WebhookConfig::findByEnvId($this->getEnvironmentId()) as $entity) { $endpoints = array(); foreach ($entity->getEndpoints() as $endpoint) { $endpoints[] = $endpoint->endpointId; } $events = array(); foreach ($entity->getEvents() as $event) { $events[] = $event->eventType; } $farms = array(); foreach ($entity->getFarms() as $farm) { if ($farm->farmId) { $farms[] = $farm->farmId; } } $list[] = array('webhookId' => $entity->webhookId, 'name' => $entity->name, 'postData' => $entity->postData, 'skipPrivateGv' => $entity->skipPrivateGv, 'endpoints' => $endpoints, 'events' => $events, 'farms' => $farms); } return $list; }
/** * @param string $scope * @return array * @throws Scalr_Exception_Core */ private function getList($scope = '') { $criteria = []; switch ($this->request->getScope()) { case WebhookConfig::SCOPE_ENVIRONMENT: $criteria[] = ['$or' => [['$and' => [['accountId' => $this->user->getAccountId()], ['envId' => $this->getEnvironmentId()], ['level' => WebhookConfig::LEVEL_ENVIRONMENT]]], ['$and' => [['accountId' => $this->user->getAccountId()], ['envId' => null], ['level' => WebhookConfig::LEVEL_ACCOUNT]]], ['$and' => [['accountId' => null], ['envId' => null], ['level' => WebhookConfig::LEVEL_SCALR]]]]]; break; case WebhookConfig::SCOPE_ACCOUNT: $criteria[] = ['$or' => [['$and' => [['accountId' => $this->user->getAccountId()], ['envId' => null], ['level' => WebhookConfig::LEVEL_ACCOUNT]]], ['$and' => [['accountId' => null], ['envId' => null], ['level' => WebhookConfig::LEVEL_SCALR]]]]]; break; case WebhookConfig::SCOPE_SCALR: $criteria[] = ['level' => WebhookConfig::LEVEL_SCALR]; $criteria[] = ['envId' => null]; $criteria[] = ['accountId' => null]; break; } $scopeLinking = [ScopeInterface::SCOPE_SCALR => WebhookConfig::LEVEL_SCALR, ScopeInterface::SCOPE_ACCOUNT => WebhookConfig::LEVEL_ACCOUNT, ScopeInterface::SCOPE_ENVIRONMENT => WebhookConfig::LEVEL_ENVIRONMENT]; if ($scope && array_key_exists($scope, $scopeLinking)) { $criteria[] = ['level' => $scopeLinking[$scope]]; } foreach (WebhookConfig::find($criteria) as $entity) { $webhook = ['webhookId' => $entity->webhookId, 'name' => $entity->name, 'scope' => $entity->getScope()]; $endpoints = []; foreach ($entity->getEndpoints() as $endpoint) { $endpoints[] = $endpoint->endpointId; } $events = []; foreach ($entity->getEvents() as $event) { $events[] = $event->eventType; } $farms = array(); foreach ($entity->getFarms() as $farm) { if ($farm->farmId) { $farms[] = $farm->farmId; } } $webhook['postData'] = $this->request->getScope() == $entity->getScope() ? $entity->postData : ''; $webhook['timeout'] = $entity->timeout; $webhook['attempts'] = $entity->attempts; $webhook['skipPrivateGv'] = $entity->skipPrivateGv; $webhook['endpoints'] = $endpoints; $webhook['events'] = $events; $webhook['farms'] = $farms; $list[] = $webhook; } return $list; }
/** * @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; }
/** * Store event in database * * @param integer $farmid * @param string $event_name */ public static function StoreEvent($farmid, Event $event, $eventTime = null) { if ($event->DBServer) { $eventServerId = $event->DBServer->serverId; } try { $DB = self::getDb(); // Generate event message $message = $event->getTextDetails(); //short_message temporary used for time tracking // Store event in database $DB->Execute("INSERT INTO events SET\n farmid\t= ?,\n type\t= ?,\n dtadded\t= NOW(),\n message\t= ?,\n event_object = '',\n event_id\t = ?,\n event_server_id = ?,\n short_message = ?,\n msg_expected = ?,\n msg_created = ?,\n scripts_total = ?,\n is_suspend = ?", array($farmid, $event->GetName(), $message, $event->GetEventID(), $eventServerId, $eventTime, $event->msgExpected, $event->msgCreated, $event->scriptsCount, $event->isSuspended ? 1 : 0)); } catch (Exception $e) { Logger::getLogger(__CLASS__)->fatal(sprintf(_("Cannot store event in database: %s"), $e->getMessage())); } try { if ($eventServerId) { $dbServer = DBServer::LoadByID($eventServerId); if (!$dbServer->farmRoleId) { return true; } $dt = new DateTime('now', new DateTimeZone("UTC")); $timestamp = $dt->format("D d M Y H:i:s e"); $payload = new stdClass(); $payload->eventName = $event->GetName(); $payload->eventId = $event->GetEventID(); $payload->timestamp = $timestamp; $globalVars = Scalr_Scripting_GlobalVariables::listServerGlobalVariables($dbServer, true, $event); $webhooks = WebhookConfig::findByEvent($event->GetName(), $farmid, $dbServer->clientId, $dbServer->envId); $count = 0; foreach ($webhooks as $webhook) { /* @var $webhook \Scalr\Model\Entity\WebhookConfig */ $payload->configurationId = $webhook->webhookId; $payload->data = array(); $variables = []; foreach ($globalVars as $gv) { $variables[$gv->name] = $gv->value; if ($gv->private && $webhook->skipPrivateGv == 1 && !$gv->system) { continue; } $payload->data[$gv->name] = $gv->value; } if ($webhook->postData) { //Parse variable $keys = array_keys($variables); $f = create_function('$item', 'return "{".$item."}";'); $keys = array_map($f, $keys); $values = array_values($variables); // Strip undefined variables & return value $payload->userData = preg_replace("/{[A-Za-z0-9_-]+}/", "", str_replace($keys, $values, $webhook->postData)); } else { $payload->userData = ''; } foreach ($webhook->getEndpoints() as $ce) { /* @var $ce \Scalr\Model\Entity\WebhookConfigEndpoint */ $endpoint = $ce->getEndpoint(); if (!$endpoint->isValid) { continue; } $payload->endpointId = $endpoint->endpointId; $encPayload = json_encode($payload); $history = new WebhookHistory(); $history->eventId = $event->GetEventID(); $history->eventType = $event->GetName(); $history->payload = $encPayload; $history->serverId = $event->DBServer ? $event->DBServer->serverId : null; $history->endpointId = $endpoint->endpointId; $history->webhookId = $webhook->webhookId; $history->farmId = $farmid; $history->save(); $count++; } } if ($count != 0) { $DB->Execute("UPDATE events SET wh_total = ? WHERE event_id = ?", array($count, $event->GetEventID())); } } } catch (Exception $e) { Logger::getLogger(__CLASS__)->fatal(sprintf(_("WebHooks: %s"), $e->getMessage())); } }
<?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); } }
public function xGroupActionHandlerAction() { $this->request->defineParams(array('webhookIds' => array('type' => 'json'), 'action')); $processed = array(); $errors = array(); $webhooks = WebhookConfig::find(array(array('accountId' => $this->getEnvironment()->clientId), array('envId' => $this->getEnvironmentId()), array('webhookId' => array('$in' => $this->getParam('webhookIds'))))); foreach ($webhooks as $webhook) { $processed[] = $webhook->webhookId; $webhook->delete(); } $num = count($this->getParam('webhookIds')); if (count($processed) == $num) { $this->response->success('Webhooks successfully processed'); } else { array_walk($errors, function (&$item) { $item = '- ' . $item; }); $this->response->warning(sprintf("Successfully processed only %d from %d webhooks. \nFollowing errors occurred:\n%s", count($processed), $num, join($errors, ''))); } $this->response->data(array('processed' => $processed)); }
/** * Store event in database * * @param integer $farmid * @param string $event_name */ public static function StoreEvent($farmid, Event $event, $eventTime = null) { if ($event->DBServer) { $eventServerId = $event->DBServer->serverId; } try { $DB = self::getDb(); // Generate event message $message = $event->getTextDetails(); $eventStr = null; try { $eventStr = serialize($event); } catch (Exception $e) { } //short_message temporary used for time tracking // Store event in database $DB->Execute("INSERT INTO events SET\n farmid\t= ?,\n type\t= ?,\n dtadded\t= NOW(),\n message\t= ?,\n event_object = ?,\n event_id\t = ?,\n event_server_id = ?,\n short_message = ?,\n msg_expected = ?,\n msg_created = ?\n ", array($farmid, $event->GetName(), $message, $eventStr, $event->GetEventID(), $eventServerId, $eventTime, $event->msgExpected, $event->msgCreated)); } catch (Exception $e) { Logger::getLogger(__CLASS__)->fatal(sprintf(_("Cannot store event in database: %s"), $e->getMessage())); } try { if ($eventServerId) { $dbServer = DBServer::LoadByID($eventServerId); $dt = new DateTime('now', new DateTimeZone("UTC")); $timestamp = $dt->format("D d M Y H:i:s e"); $payload = new stdClass(); $payload->eventName = $event->GetName(); $payload->eventId = $event->GetEventID(); $payload->timestamp = $timestamp; $globalVars = Scalr_Scripting_GlobalVariables::listServerGlobalVariables($dbServer, true, $event); $webhooks = WebhookConfig::findByEvent($event->GetName(), $farmid, $dbServer->clientId, $dbServer->envId); foreach ($webhooks as $webhook) { /* @var $webhook \Scalr\Model\Entity\WebhookConfig */ $payload->data = array(); foreach ($globalVars as $gv) { if ($gv->private && $webhook->skipPrivateGv == 1 && !$gv->system) { continue; } $payload->data[$gv->name] = $gv->value; } if ($webhook->postData) { $payload->userData = $dbServer->applyGlobalVarsToValue($webhook->postData); } else { $payload->userData = ''; } $encPayload = json_encode($payload); foreach ($webhook->getEndpoints() as $ce) { /* @var $ce \Scalr\Model\Entity\WebhookConfigEndpoint */ $endpoint = $ce->getEndpoint(); if (!$endpoint->isValid) { continue; } $history = new WebhookHistory(); $history->eventId = $event->GetEventID(); $history->eventType = $event->GetName(); $history->payload = $encPayload; $history->endpointId = $endpoint->endpointId; $history->webhookId = $webhook->webhookId; $history->farmId = $farmid; $history->save(); } } } } catch (Exception $e) { Logger::getLogger(__CLASS__)->fatal(sprintf(_("WebHooks: %s"), $e->getMessage())); } }