680 lines
18 KiB
PHP
680 lines
18 KiB
PHP
<?php
|
|
/**
|
|
* Cloud wizard manager.
|
|
*
|
|
* @category Wizard
|
|
* @package Pandora FMS
|
|
* @subpackage Cloud
|
|
* @version 1.0.0
|
|
* @license See below
|
|
*
|
|
* ______ ___ _______ _______ ________
|
|
* | __ \.-----.--.--.--| |.-----.----.-----. | ___| | | __|
|
|
* | __/| _ | | _ || _ | _| _ | | ___| |__ |
|
|
* |___| |___._|__|__|_____||_____|__| |___._| |___| |__|_|__|_______|
|
|
*
|
|
* ============================================================================
|
|
* Copyright (c) 2007-2021 Artica Soluciones Tecnologicas, http://www.artica.es
|
|
* This code is NOT free software. This code is NOT licenced under GPL2 licence
|
|
* You cannnot redistribute it without written permission of copyright holder.
|
|
* ============================================================================
|
|
*/
|
|
|
|
global $config;
|
|
|
|
require_once $config['homedir'].'/godmode/wizards/Wizard.main.php';
|
|
require_once $config['homedir'].'/include/functions_users.php';
|
|
require_once $config['homedir'].'/include/class/CredentialStore.class.php';
|
|
|
|
/**
|
|
* Implements Wizard to provide generic Cloud wizard.
|
|
*/
|
|
class Cloud extends Wizard
|
|
{
|
|
|
|
/**
|
|
* Sub-wizard to be launch (vmware,oracle...).
|
|
*
|
|
* @var string
|
|
*/
|
|
public $mode;
|
|
|
|
/**
|
|
* Discovery task data.
|
|
*
|
|
* @var array.
|
|
*/
|
|
public $task;
|
|
|
|
/**
|
|
* General maxPages.
|
|
*
|
|
* @var integer
|
|
*/
|
|
public $maxPages;
|
|
|
|
/**
|
|
* Product string.
|
|
*
|
|
* @var string
|
|
*/
|
|
protected $product = '';
|
|
|
|
/**
|
|
* Credentials store identifier.
|
|
*
|
|
* @var string
|
|
*/
|
|
protected $keyIdentifier = null;
|
|
|
|
/**
|
|
* Credentials store product identifier.
|
|
*
|
|
* @var string
|
|
*/
|
|
protected $keyStoreType = null;
|
|
|
|
|
|
/**
|
|
* Constructor.
|
|
*
|
|
* @param integer $page Start page, by default 0.
|
|
* @param string $msg Default message to show to users.
|
|
* @param string $icon Target icon to be used.
|
|
* @param string $label Target label to be displayed.
|
|
*
|
|
* @return mixed
|
|
*/
|
|
public function __construct(
|
|
int $page=0,
|
|
string $msg='Default message. Not set.',
|
|
string $icon='images/wizard/cloud.png',
|
|
string $label='Cloud'
|
|
) {
|
|
$this->setBreadcrum([]);
|
|
|
|
$this->access = 'AW';
|
|
$this->task = [];
|
|
$this->msg = $msg;
|
|
$this->icon = $icon;
|
|
$this->label = $label;
|
|
$this->page = $page;
|
|
$this->url = ui_get_full_url(
|
|
'index.php?sec=gservers&sec2=godmode/servers/discovery&wiz=cloud'
|
|
);
|
|
|
|
return $this;
|
|
}
|
|
|
|
|
|
/**
|
|
* Run wizard manager.
|
|
*
|
|
* @return mixed Returns null if wizard is ongoing. Result if done.
|
|
*/
|
|
public function run()
|
|
{
|
|
global $config;
|
|
|
|
// Load styles.
|
|
parent::run();
|
|
|
|
// Load current wiz. sub-styles.
|
|
ui_require_css_file(
|
|
'cloud',
|
|
ENTERPRISE_DIR.'/include/styles/wizards/'
|
|
);
|
|
|
|
$mode = get_parameter('mode', null);
|
|
|
|
// Load cloud wizards.
|
|
$enterprise_classes = glob(
|
|
$config['homedir'].'/'.ENTERPRISE_DIR.'/include/class/*.cloud.php'
|
|
);
|
|
$extensions = new ExtensionsDiscovery('cloud', $mode);
|
|
|
|
foreach ($enterprise_classes as $classpath) {
|
|
enterprise_include_once(
|
|
'include/class/'.basename($classpath)
|
|
);
|
|
}
|
|
|
|
switch ($mode) {
|
|
case 'amazonws':
|
|
$classname_selected = 'Aws';
|
|
break;
|
|
|
|
case 'azure':
|
|
$classname_selected = 'Azure';
|
|
break;
|
|
|
|
case 'gcp':
|
|
$classname_selected = 'Google';
|
|
break;
|
|
|
|
default:
|
|
$classname_selected = null;
|
|
break;
|
|
}
|
|
|
|
// Else: class not found pseudo exception.
|
|
if ($classname_selected !== null) {
|
|
$wiz = new $classname_selected($this->page);
|
|
// Check if app has been migrated.
|
|
if (method_exists($wiz, 'isMigrated') === true) {
|
|
if ($wiz->isMigrated() === true) {
|
|
ui_print_info_message(__('This legacy app has been migrated to new discovery 2.0 system'));
|
|
return false;
|
|
}
|
|
}
|
|
|
|
$result = $wiz->run();
|
|
if (is_array($result) === true) {
|
|
return $result;
|
|
}
|
|
}
|
|
|
|
if ($classname_selected === null) {
|
|
if ($mode !== null) {
|
|
// Load extension if exist.
|
|
$extensions->run();
|
|
return;
|
|
}
|
|
|
|
// Load classes and print selector.
|
|
$wiz_data = [];
|
|
foreach ($enterprise_classes as $classpath) {
|
|
$classname = basename($classpath, '.cloud.php');
|
|
$obj = new $classname();
|
|
// Check if legacy has been migrated.
|
|
if (method_exists($obj, 'isMigrated') === true) {
|
|
if ($obj->isMigrated() === true) {
|
|
continue;
|
|
}
|
|
}
|
|
|
|
$wiz_data[] = $obj->load();
|
|
}
|
|
|
|
$wiz_data = array_merge($wiz_data, $extensions->loadExtensions());
|
|
|
|
$this->prepareBreadcrum(
|
|
[
|
|
[
|
|
'link' => ui_get_full_url(
|
|
'index.php?sec=gservers&sec2=godmode/servers/discovery'
|
|
),
|
|
'label' => __('Discovery'),
|
|
],
|
|
[
|
|
'link' => $this->url,
|
|
'label' => __('Cloud'),
|
|
'selected' => true,
|
|
],
|
|
],
|
|
true
|
|
);
|
|
|
|
// Header.
|
|
ui_print_page_header(
|
|
__('Cloud'),
|
|
'',
|
|
false,
|
|
'',
|
|
true,
|
|
'',
|
|
false,
|
|
'',
|
|
GENERIC_SIZE_TEXT,
|
|
'',
|
|
$this->printHeader(true)
|
|
);
|
|
|
|
Wizard::printBigButtonsList($wiz_data);
|
|
|
|
echo '<div class="app_mssg"><i>*'.__('All company names used here are for identification purposes only. Use of these names, logos, and brands does not imply endorsement.').'</i></div>';
|
|
}
|
|
|
|
// Print Warning Message.
|
|
$this->printWarningMessage();
|
|
|
|
return $result;
|
|
}
|
|
|
|
|
|
/**
|
|
* Run credentials wizard.
|
|
*
|
|
* @return boolean True if credentials wizard is displayed and false if not.
|
|
*/
|
|
public function runCredentials()
|
|
{
|
|
global $config;
|
|
|
|
if ($this->status === false) {
|
|
$empty_account = true;
|
|
}
|
|
|
|
// Checks credentials. If check not passed. Show the form to fill it.
|
|
if ($this->checkCredentials()) {
|
|
return true;
|
|
}
|
|
|
|
// Add breadcrum and print header.
|
|
$this->prepareBreadcrum(
|
|
[
|
|
[
|
|
'link' => $this->url.'&credentials=1',
|
|
'label' => __('%s credentials', $this->product),
|
|
'selected' => true,
|
|
],
|
|
],
|
|
true
|
|
);
|
|
// Header.
|
|
ui_print_page_header(
|
|
__('%s credentials', $this->product),
|
|
'',
|
|
false,
|
|
$this->product.'_credentials_tab',
|
|
true,
|
|
'',
|
|
false,
|
|
'',
|
|
GENERIC_SIZE_TEXT,
|
|
'',
|
|
$this->printHeader(true)
|
|
);
|
|
|
|
if ($this->product === 'Aws') {
|
|
ui_print_warning_message(
|
|
__(
|
|
'If a task with the selected credentials is already running, it will be edited. To create a new one, another account from the credential store must be selected.'
|
|
)
|
|
);
|
|
}
|
|
|
|
if ($this->status === true) {
|
|
ui_print_success_message($this->msg);
|
|
} else if ($this->status === false) {
|
|
ui_print_error_message($this->msg);
|
|
}
|
|
|
|
if ($empty_account === true) {
|
|
ui_print_error_message($this->msg);
|
|
}
|
|
|
|
$link_to_cs = '';
|
|
if (check_acl($config['id_user'], 0, 'UM')) {
|
|
$link_to_cs = '<a class="ext_link" href="'.ui_get_full_url(
|
|
'index.php?sec=gmodules&sec2=godmode/groups/group_list&tab=credbox'
|
|
).'" >';
|
|
$link_to_cs .= __('Manage accounts').'</a>';
|
|
}
|
|
|
|
$this->getCredentials();
|
|
$this->printFormAsList(
|
|
[
|
|
'form' => [
|
|
'action' => $this->url,
|
|
'method' => 'POST',
|
|
'id' => 'form-credentials',
|
|
],
|
|
'inputs' => [
|
|
[
|
|
'label' => __('Cloud tool full path'),
|
|
'arguments' => [
|
|
'name' => 'cloud_util_path',
|
|
'value' => isset($config['cloud_util_path']) ? io_safe_output($config['cloud_util_path']) : '/usr/bin/pandora-cm-api',
|
|
'type' => 'text',
|
|
],
|
|
],
|
|
[
|
|
'label' => __('Account'),
|
|
'extra' => $link_to_cs,
|
|
'arguments' => [
|
|
'name' => 'account_identifier',
|
|
'type' => 'select',
|
|
'fields' => CredentialStore::getKeys($this->keyStoreType),
|
|
'selected' => $this->keyIdentifier,
|
|
'return' => true,
|
|
],
|
|
],
|
|
[
|
|
'arguments' => [
|
|
'name' => 'parse_credentials',
|
|
'value' => 1,
|
|
'type' => 'hidden',
|
|
'return' => true,
|
|
],
|
|
],
|
|
],
|
|
]
|
|
);
|
|
|
|
$buttons_form = $this->printInput(
|
|
[
|
|
'name' => 'submit',
|
|
'label' => __('Validate'),
|
|
'type' => 'submit',
|
|
'attributes' => [
|
|
'icon' => 'wand',
|
|
'form' => 'form-credentials',
|
|
],
|
|
'return' => true,
|
|
'width' => 'initial',
|
|
]
|
|
);
|
|
|
|
$buttons_form .= $this->printGoBackButton(
|
|
ui_get_full_url(
|
|
'index.php?sec=gservers&sec2=godmode/servers/discovery&wiz=cloud'
|
|
),
|
|
true
|
|
);
|
|
|
|
html_print_action_buttons($buttons_form);
|
|
return false;
|
|
}
|
|
|
|
|
|
/**
|
|
* Check credentials.
|
|
*
|
|
* @return boolean True if credentials are OK.
|
|
*/
|
|
public function checkCredentials()
|
|
{
|
|
global $config;
|
|
|
|
$pandora = io_safe_output($config['cloud_util_path']);
|
|
|
|
if (isset($pandora) === false) {
|
|
config_update_value('cloud_util_path', '/usr/bin/pandora-cm-api');
|
|
}
|
|
|
|
if ((bool) get_parameter('disconnect_account', false) === true) {
|
|
$this->status = null;
|
|
return false;
|
|
}
|
|
|
|
if ($this->keyIdentifier === null) {
|
|
// Ask user for available credentials.
|
|
$this->msg = __('Select a set of credentials from the list');
|
|
$this->status = null;
|
|
return false;
|
|
}
|
|
|
|
$credentials = $this->getCredentials($this->keyIdentifier);
|
|
|
|
if (empty($credentials['username']) === true
|
|
|| empty($credentials['password']) === true
|
|
|| isset($pandora) === false
|
|
|| is_executable($pandora) === false
|
|
) {
|
|
if (is_executable($pandora) === false) {
|
|
$this->msg = (__('Path %s is not executable.', $pandora));
|
|
$this->status = false;
|
|
} else {
|
|
$this->msg = __('Invalid username or password');
|
|
$this->status = false;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
try {
|
|
$value = $this->executeCMCommand('--get availability');
|
|
} catch (Exception $e) {
|
|
$this->msg = $e->getMessage();
|
|
$this->status = false;
|
|
return false;
|
|
}
|
|
|
|
if ($value == '1') {
|
|
return true;
|
|
}
|
|
|
|
$this->status = false;
|
|
|
|
// Error message directly from pandora-cm-api.
|
|
$this->msg = str_replace('"', '', $value);
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
/**
|
|
* Handle the click on disconnect account link.
|
|
*
|
|
* @return void But it prints some info to user.
|
|
*/
|
|
protected function parseDisconnectAccount()
|
|
{
|
|
// Check if disconection account link is pressed.
|
|
if ((bool) get_parameter('disconnect_account') === false) {
|
|
return;
|
|
}
|
|
|
|
$ret = $this->setCredentials(null);
|
|
if ($ret) {
|
|
$this->msg = __('Account disconnected');
|
|
} else {
|
|
$this->msg = __('Failed disconnecting account');
|
|
}
|
|
|
|
$this->status = $ret;
|
|
$this->page = 0;
|
|
}
|
|
|
|
|
|
/**
|
|
* Build an array with Product credentials.
|
|
*
|
|
* @return array with credentials (pass and id).
|
|
*/
|
|
public function getCredentials()
|
|
{
|
|
return CredentialStore::getKey($this->keyIdentifier);
|
|
}
|
|
|
|
|
|
/**
|
|
* Set Product credentials.
|
|
*
|
|
* @param string|null $identifier Credential store identifier.
|
|
*
|
|
* @return boolean True if success.
|
|
*/
|
|
public function setCredentials($identifier)
|
|
{
|
|
if ($identifier === null) {
|
|
unset($this->keyIdentifier);
|
|
return true;
|
|
}
|
|
|
|
if (isset($identifier) === false) {
|
|
return false;
|
|
}
|
|
|
|
$all = CredentialStore::getKeys($this->type);
|
|
|
|
if (in_array($identifier, $all) === true) {
|
|
$this->keyIdentifier = $identifier;
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
/**
|
|
* Parse credentials form.
|
|
*
|
|
* @return void But it prints a message.
|
|
*/
|
|
protected function parseCredentials()
|
|
{
|
|
global $config;
|
|
|
|
if (!$this->keyIdentifier) {
|
|
$this->setCredentials(get_parameter('ki', null));
|
|
}
|
|
|
|
// Check if credentials form is submitted.
|
|
if ((bool) get_parameter('parse_credentials') === false) {
|
|
return;
|
|
}
|
|
|
|
$this->page = 0;
|
|
$ret = $this->setCredentials(
|
|
get_parameter('account_identifier')
|
|
);
|
|
|
|
$path = get_parameter('cloud_util_path');
|
|
$ret_path = config_update_value('cloud_util_path', $path);
|
|
if ($ret_path) {
|
|
$config['cloud_util_path'] = $path;
|
|
}
|
|
|
|
if ($ret && $ret_path) {
|
|
$this->msg = __('Credentials successfully updated');
|
|
} else {
|
|
$this->msg = __('Failed updating credentials process');
|
|
}
|
|
|
|
$this->status = ($ret && $ret_path);
|
|
}
|
|
|
|
|
|
/**
|
|
* This method must be implemented.
|
|
*
|
|
* Execute a pandora-cm-api request.
|
|
*
|
|
* @param string $command Command to execute.
|
|
*
|
|
* @return void But must return string STDOUT of executed command.
|
|
* @throws Exception If not implemented.
|
|
*/
|
|
protected function executeCMCommand($command)
|
|
{
|
|
throw new Exception('executeCMCommand must be implemented.');
|
|
}
|
|
|
|
|
|
/**
|
|
* Get a recon token value
|
|
*
|
|
* @param string $token The recon key to retrieve.
|
|
*
|
|
* @return string String with the value.
|
|
*/
|
|
protected function getConfigReconElement($token)
|
|
{
|
|
if ($this->reconConfig === false
|
|
|| isset($this->reconConfig[0][$token]) === false
|
|
) {
|
|
if (is_array($this->task) === true
|
|
&& isset($this->task[$token]) === true
|
|
) {
|
|
return $this->task[$token];
|
|
} else {
|
|
return '';
|
|
}
|
|
} else {
|
|
return $this->reconConfig[0][$token];
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Print global inputs
|
|
*
|
|
* @param boolean $last True if is last element.
|
|
*
|
|
* @return array Array with all global inputs.
|
|
*/
|
|
protected function getGlobalInputs(bool $last=false)
|
|
{
|
|
$task_id = $this->task['id_rt'];
|
|
if (!$task_id) {
|
|
$task_id = $this->getConfigReconElement('id_rt');
|
|
}
|
|
|
|
return [
|
|
[
|
|
'arguments' => [
|
|
'name' => 'page',
|
|
'value' => ($this->page + 1),
|
|
'type' => 'hidden',
|
|
'return' => true,
|
|
],
|
|
],
|
|
[
|
|
'arguments' => [
|
|
'name' => 'submit',
|
|
'label' => ($last) ? __('Finish') : __('Next'),
|
|
'type' => 'submit',
|
|
'attributes' => 'class="sub '.(($last) ? 'wand' : 'next').'"',
|
|
'return' => true,
|
|
],
|
|
],
|
|
[
|
|
'arguments' => [
|
|
'name' => 'task',
|
|
'value' => $task_id,
|
|
'type' => 'hidden',
|
|
'return' => true,
|
|
],
|
|
],
|
|
[
|
|
'arguments' => [
|
|
'name' => 'parse_form',
|
|
'value' => 1,
|
|
'type' => 'hidden',
|
|
'return' => true,
|
|
],
|
|
],
|
|
];
|
|
}
|
|
|
|
|
|
/**
|
|
* Print required css in some points.
|
|
*
|
|
* @return string With js code.
|
|
*/
|
|
protected function cloudJS()
|
|
{
|
|
return '
|
|
function toggleCloudSubmenu(curr_elem, id_csm){
|
|
if (document.getElementsByName(curr_elem)[0].checked){
|
|
$("#li-"+id_csm).show();
|
|
} else {
|
|
$("#li-"+id_csm).hide();
|
|
}
|
|
};
|
|
';
|
|
}
|
|
|
|
|
|
/**
|
|
* Check if section have extensions.
|
|
*
|
|
* @return boolean Return true if section is empty.
|
|
*/
|
|
public function isEmpty()
|
|
{
|
|
$extensions = new ExtensionsDiscovery('cloud');
|
|
$listExtensions = $extensions->getExtensionsApps();
|
|
if ($listExtensions > 0 || enterprise_installed() === true) {
|
|
return false;
|
|
} else {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
|
|
}
|