add possibility to enable/disable api access on a per user base

Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
This commit is contained in:
Michael Kaufmann 2019-10-09 11:43:22 +02:00
parent 88d85fc02e
commit 4543c73b4f
No known key found for this signature in database
GPG Key ID: 55284EC83A4823B8
13 changed files with 115 additions and 50 deletions

View File

@ -132,6 +132,7 @@ CREATE TABLE `panel_admins` (
`custom_notes_show` tinyint(1) NOT NULL default '0',
`type_2fa` tinyint(1) NOT NULL default '0',
`data_2fa` varchar(500) NOT NULL default '',
`api_allowed` tinyint(1) NOT NULL default '1',
PRIMARY KEY (`adminid`),
UNIQUE KEY `loginname` (`loginname`)
) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci;
@ -199,6 +200,7 @@ CREATE TABLE `panel_customers` (
`allowed_phpconfigs` varchar(500) NOT NULL default '',
`type_2fa` tinyint(1) NOT NULL default '0',
`data_2fa` varchar(500) NOT NULL default '',
`api_allowed` tinyint(1) NOT NULL default '1',
`logviewenabled` tinyint(1) NOT NULL default '0',
PRIMARY KEY (`customerid`),
UNIQUE KEY `loginname` (`loginname`)
@ -684,7 +686,7 @@ opcache.interned_strings_buffer'),
('panel', 'customer_hide_options', ''),
('panel', 'is_configured', '0'),
('panel', 'version', '0.10.0'),
('panel', 'db_version', '201910030');
('panel', 'db_version', '201910090');
DROP TABLE IF EXISTS `panel_tasks`;

View File

@ -407,6 +407,7 @@ class FroxlorInstall
`name` = 'Froxlor-Administrator',
`email` = :email,
`def_language` = :deflang,
`api_allowed` = 1,
`customers` = -1,
`customers_see_all` = 1,
`caneditphpsettings` = 1,

View File

@ -339,3 +339,13 @@ if (\Froxlor\Froxlor::isDatabaseVersion('201909150')) {
\Froxlor\Froxlor::updateToDbVersion('201910030');
}
if (\Froxlor\Froxlor::isDatabaseVersion('201910030')) {
showUpdateStep("Adding field api_allowed to admins and customers");
Database::query("ALTER TABLE `" . TABLE_PANEL_ADMINS . "` ADD `api_allowed` tinyint(1) NOT NULL default '1';");
Database::query("ALTER TABLE `" . TABLE_PANEL_CUSTOMERS . "` ADD `api_allowed` tinyint(1) NOT NULL default '1';");
lastStepStatus(0);
\Froxlor\Froxlor::updateToDbVersion('201910090');
}

View File

@ -97,6 +97,8 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
* optional, default auto-generated
* @param string $def_language
* optional, default is system-default language
* @param bool $api_allowed
* optional, default is true if system setting api.enabled is true, else false
* @param string $custom_notes
* optional, default empty
* @param bool $custom_notes_show
@ -171,6 +173,7 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
// parameters
$def_language = $this->getParam('def_language', true, Settings::Get('panel.standardlanguage'));
$api_allowed = $this->getBoolParam('api_allowed', true, Settings::Get('api.enabled'));
$custom_notes = $this->getParam('custom_notes', true, '');
$custom_notes_show = $this->getBoolParam('custom_notes_show', true, 0);
$password = $this->getParam('admin_password', true, '');
@ -271,6 +274,7 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
'name' => $name,
'email' => $email,
'lang' => $def_language,
'api_allowed' => $api_allowed,
'change_serversettings' => $change_serversettings,
'customers' => $customers,
'customers_see_all' => $customers_see_all,
@ -299,6 +303,7 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
`name` = :name,
`email` = :email,
`def_language` = :lang,
`api_allowed` = :api_allowed,
`change_serversettings` = :change_serversettings,
`customers` = :customers,
`customers_see_all` = :customers_see_all,
@ -350,6 +355,8 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
* optional, default auto-generated
* @param string $def_language
* optional, default is system-default language
* @param bool $api_allowed
* optional, default is true if system setting api.enabled is true, else false
* @param string $custom_notes
* optional, default empty
* @param string $theme
@ -444,6 +451,7 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
// you cannot edit some of the details of yourself
if ($result['adminid'] == $this->getUserDetail('adminid')) {
$api_allowed = $result['api_allowed'];
$deactivated = $result['deactivated'];
$customers = $result['customers'];
$domains = $result['domains'];
@ -462,6 +470,7 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
$traffic = $result['traffic'];
$ipaddress = ($result['ip'] != - 1 ? json_decode($result['ip'], true) : - 1);
} else {
$api_allowed = $this->getBoolParam('api_allowed', true, $result['api_allowed']);
$deactivated = $this->getBoolParam('deactivated', true, $result['deactivated']);
$dec_places = Settings::Get('panel.decimal_places');
@ -578,6 +587,7 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
'name' => $name,
'email' => $email,
'lang' => $def_language,
'api_allowed' => $api_allowed,
'change_serversettings' => $change_serversettings,
'customers' => $customers,
'customers_see_all' => $customers_see_all,
@ -607,6 +617,7 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
`name` = :name,
`email` = :email,
`def_language` = :lang,
`api_allowed` = :api_allowed,
`change_serversettings` = :change_serversettings,
`customers` = :customers,
`customers_see_all` = :customers_see_all,
@ -793,7 +804,7 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
* @param string $extra
* optional, default empty
* @param int $increase_by
* optional, default 1
* optional, default 1
*/
public static function increaseUsage($adminid = 0, $resource = null, $extra = '', $increase_by = 1)
{
@ -808,7 +819,7 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
* @param string $extra
* optional, default empty
* @param int $decrease_by
* optional, default 1
* optional, default 1
*/
public static function decreaseUsage($adminid = 0, $resource = null, $extra = '', $decrease_by = 1)
{

View File

@ -136,6 +136,8 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
* optional
* @param string $def_language,
* optional, default is system-default language
* @param bool $api_allowed
* optional, default is true if system setting api.enabled is true, else false
* @param int $gender
* optional, 0 = no-gender, 1 = male, 2 = female
* @param string $custom_notes
@ -229,6 +231,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
$fax = $this->getParam('fax', true, '');
$customernumber = $this->getParam('customernumber', true, '');
$def_language = $this->getParam('def_language', true, Settings::Get('panel.standardlanguage'));
$api_allowed = $this->getBoolParam('api_allowed', true, Settings::Get('api.enabled'));
$gender = (int) $this->getParam('gender', true, 0);
$custom_notes = $this->getParam('custom_notes', true, '');
$custom_notes_show = $this->getBoolParam('custom_notes_show', true, 0);
@ -388,26 +391,6 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
\Froxlor\UI\Response::standard_error('documentrootexists', $documentroot, true);
}
if ($createstdsubdomain != '1') {
$createstdsubdomain = '0';
}
if ($phpenabled != '0') {
$phpenabled = '1';
}
if ($perlenabled != '0') {
$perlenabled = '1';
}
if ($dnsenabled != '0') {
$dnsenabled = '1';
}
if ($logviewenabled != '0') {
$logviewenabled = '1';
}
if ($password == '') {
$password = \Froxlor\System\Crypt::generatePassword();
}
@ -430,6 +413,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
'email' => $email,
'customerno' => $customernumber,
'lang' => $def_language,
'api_allowed' => $api_allowed,
'docroot' => $documentroot,
'guid' => $guid,
'diskspace' => $diskspace,
@ -470,6 +454,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
`email` = :email,
`customernumber` = :customerno,
`def_language` = :lang,
`api_allowed` = :api_allowed,
`documentroot` = :docroot,
`guid` = :guid,
`diskspace` = :diskspace,
@ -755,6 +740,8 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
* optional
* @param string $def_language,
* optional, default is system-default language
* @param bool $api_allowed
* optional, default is true if system setting api.enabled is true, else false
* @param int $gender
* optional, 0 = no-gender, 1 = male, 2 = female
* @param string $custom_notes
@ -857,6 +844,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
$fax = $this->getParam('fax', true, $result['fax']);
$customernumber = $this->getParam('customernumber', true, $result['customernumber']);
$def_language = $this->getParam('def_language', true, $result['def_language']);
$api_allowed = $this->getBoolParam('api_allowed', true, $result['api_allowed']);
$gender = (int) $this->getParam('gender', true, $result['gender']);
$custom_notes = $this->getParam('custom_notes', true, $result['custom_notes']);
$custom_notes_show = $this->getBoolParam('custom_notes_show', true, $result['custom_notes_show']);
@ -999,30 +987,10 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
\Froxlor\System\Cronjob::inserttask('1');
}
if ($deactivated != '1') {
$deactivated = '0';
}
if ($phpenabled != '0') {
$phpenabled = '1';
}
if ($perlenabled != '0') {
$perlenabled = '1';
}
if ($dnsenabled != '0') {
$dnsenabled = '1';
}
if ($phpenabled != $result['phpenabled'] || $perlenabled != $result['perlenabled']) {
\Froxlor\System\Cronjob::inserttask('1');
}
if ($logviewenabled != '0') {
$logviewenabled = '1';
}
// activate/deactivate customer services
if ($deactivated != $result['deactivated']) {
@ -1166,7 +1134,8 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
'dnsenabled' => $dnsenabled,
'logviewenabled' => $logviewenabled,
'custom_notes' => $custom_notes,
'custom_notes_show' => $custom_notes_show
'custom_notes_show' => $custom_notes_show,
'api_allowed' => $api_allowed
);
$upd_data = $upd_data + $admin_upd_data;
}
@ -1207,7 +1176,8 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
`dnsenabled` = :dnsenabled,
`logviewenabled` = :logviewenabled,
`custom_notes` = :custom_notes,
`custom_notes_show` = :custom_notes_show";
`custom_notes_show` = :custom_notes_show,
`api_allowed` = :api_allowed";
$upd_query .= $admin_upd_query;
}
$upd_query .= " WHERE `customerid` = :customerid";

View File

@ -55,13 +55,20 @@ class FroxlorRPC
*/
private static function validateAuth($key, $secret)
{
$sel_stmt = \Froxlor\Database\Database::prepare("SELECT * FROM `api_keys` WHERE `apikey` = :ak AND `secret` = :as");
$sel_stmt = \Froxlor\Database\Database::prepare("
SELECT ak.*, a.api_allowed as admin_api_allowed, c.api_allowed as cust_api_allowed
FROM `api_keys` ak
LEFT JOIN `panel_admins` a ON a.adminid = ak.adminid
LEFT JOIN `panel_customers` c ON c.customerid = ak.customerid
WHERE `apikey` = :ak AND `secret` = :as
");
$result = \Froxlor\Database\Database::pexecute_first($sel_stmt, array(
'ak' => $key,
'as' => $secret
), true, true);
if ($result) {
if ($result['apikey'] == $key && $result['secret'] == $secret && ($result['valid_until'] == - 1 || $result['valid_until'] >= time())) {
if ($result['apikey'] == $key && $result['secret'] == $secret && ($result['valid_until'] == - 1 || $result['valid_until'] >= time()) && (($result['customerid'] == 0 && $result['admin_api_allowed'] == 1) || ($result['customerid'] > 0 && $result['cust_api_allowed'] == 1))) {
// get user to check whether api call is allowed
if (! empty($result['allowed_from'])) {
// @todo allow specification and validating of whole subnets later
$ip_list = explode(",", $result['allowed_from']);

View File

@ -10,7 +10,7 @@ final class Froxlor
const VERSION = '0.10.0';
// Database version (YYYYMMDDC where C is a daily counter)
const DBVERSION = '201910030';
const DBVERSION = '201910090';
// Distribution branding-tag (used for Debian etc.)
const BRANDING = '';

View File

@ -44,6 +44,21 @@ return array(
'label' => $lng['login']['language'],
'type' => 'select',
'select_var' => $language_options
),
'api_allowed' => array(
'label' => $lng['usersettings']['api_allowed']['title'],
'desc' => $lng['usersettings']['api_allowed']['description'],
'type' => 'checkbox',
'values' => array(
array(
'label' => $lng['panel']['yes'],
'value' => '1'
)
),
'value' => array(
'1'
),
'visible' => (\Froxlor\Settings::Get('api.enabled') == '1' ? true : false)
)
)
),

View File

@ -59,6 +59,21 @@ return array(
'type' => 'select',
'select_var' => $language_options,
'visible' => ($result['adminid'] == $userinfo['userid'] ? false : true)
),
'api_allowed' => array(
'label' => $lng['usersettings']['api_allowed']['title'],
'desc' => $lng['usersettings']['api_allowed']['description'],
'type' => 'checkbox',
'values' => array(
array(
'label' => $lng['panel']['yes'],
'value' => '1'
)
),
'value' => array(
$result['api_allowed']
),
'visible' => (\Froxlor\Settings::Get('api.enabled') == '1' ? true : false)
)
)
),

View File

@ -81,6 +81,21 @@ return array(
'label' => $lng['login']['language'],
'type' => 'select',
'select_var' => $language_options
),
'api_allowed' => array(
'label' => $lng['usersettings']['api_allowed']['title'],
'desc' => $lng['usersettings']['api_allowed']['description'],
'type' => 'checkbox',
'values' => array(
array(
'label' => $lng['panel']['yes'],
'value' => '1'
)
),
'value' => array(
'1'
),
'visible' => (\Froxlor\Settings::Get('api.enabled') == '1' ? true : false)
)
)
),
@ -294,9 +309,9 @@ return array(
'values' => $phpconfigs,
'value' => ((int) \Froxlor\Settings::Get('system.mod_fcgid') == 1 ? array(
\Froxlor\Settings::Get('system.mod_fcgid_defaultini')
) : (int) \Froxlor\Settings::Get('phpfpm.enabled') == 1 ? array(
) : ((int) \Froxlor\Settings::Get('phpfpm.enabled') == 1 ? array(
\Froxlor\Settings::Get('phpfpm.defaultini')
) : array()),
) : array())),
'is_array' => 1
),
'perlenabled' => array(

View File

@ -74,6 +74,21 @@ return array(
'label' => $lng['login']['language'],
'type' => 'select',
'select_var' => $language_options
),
'api_allowed' => array(
'label' => $lng['usersettings']['api_allowed']['title'],
'desc' => $lng['usersettings']['api_allowed']['description'],
'type' => 'checkbox',
'values' => array(
array(
'label' => $lng['panel']['yes'],
'value' => '1'
)
),
'value' => array(
$result['api_allowed']
),
'visible' => (\Froxlor\Settings::Get('api.enabled') == '1' ? true : false)
)
)
),

View File

@ -2069,3 +2069,5 @@ $lng['serversettings']['froxloraliases']['description'] = "Comma separated list
$lng['serversettings']['ssl']['tlsv13_cipher_list']['title'] = 'Configure explicit TLSv1.3 ciphers if used';
$lng['serversettings']['ssl']['tlsv13_cipher_list']['description'] = 'This is a list of ciphers that you want (or don\'t want) to use when talking TLSv1.3. For a list of ciphers and how to include/exclude them, see <a href="https://wiki.openssl.org/index.php/TLS1.3">the docs for TLSv1.3</a>.<br /><br /><b>Default value is empty</b>';
$lng['usersettings']['api_allowed']['title'] = 'Allow API access';
$lng['usersettings']['api_allowed']['description'] = 'When enabled in the settings, this user can create API keys and access the froxlor API';

View File

@ -1716,3 +1716,5 @@ $lng['serversettings']['froxloraliases']['description'] = "Komma getrennte Liste
$lng['serversettings']['ssl']['tlsv13_cipher_list']['title'] = 'Explizite TLSv1.3 Ciphers, wenn genutzt';
$lng['serversettings']['ssl']['tlsv13_cipher_list']['description'] = 'Dies ist eine Liste von Ciphers, die genutzt werden sollen (oder auch nicht genutzt werden sollen), wenn eine TLSv1.3 Verbindung hergestellt werden soll. Eine Liste aller Ciphers und wie diese hinzugefügt/ausgeschlossen werden ist <a href="https://wiki.openssl.org/index.php/TLS1.3">der Dokumentation für TLSv1.3</a> zu entnehmen.<br /><br /><b>Standard-Wert ist leer</b>';
$lng['usersettings']['api_allowed']['title'] = 'Erlaube API Zugriff';
$lng['usersettings']['api_allowed']['description'] = 'Wenn in den Einstellungen aktiviert, kann der Benutzer API Schlüssel erstellen und auf die froxlor API Zugreifen';