From 00439f575f7dad4d425a30ef559b66e27df9c5d8 Mon Sep 17 00:00:00 2001 From: Frank Bergkemper Date: Mon, 10 Oct 2016 15:51:33 +0100 Subject: [PATCH] Required Command ACL validation This adds a new controller plugin to validate in each controller action if all required commands to run the module properly are given in the used Console/Profile Command ACL. Additionally a new view helper is introduced to centralize the ACL alert message which is displayed when the given Command ACL does not fit the requirements. This commit changes the views and controllers of the following modules: - Dashboard - Jobs - Restore - Clients - Schedules - Storages - Pools - Media/Volumes - Director Furthermore this commit removes some whitespace from the Director Model. --- module/Application/config/module.config.php | 1 + .../Controller/Plugin/CommandACLPlugin.php | 24 +++++++ .../src/Application/View/Helper/ACLAlert.php | 63 +++++++++++++++++++ .../src/Auth/Controller/AuthController.php | 27 +++++++- module/Auth/view/auth/auth/login.phtml | 21 +++++++ .../Client/Controller/ClientController.php | 39 ++++++++++++ module/Client/view/client/client/index.phtml | 4 ++ .../Controller/DashboardController.php | 16 +++++ .../view/dashboard/dashboard/index.phtml | 4 ++ .../Controller/DirectorController.php | 38 +++++++++++ .../src/Director/Model/DirectorModel.php | 13 ++++ .../view/director/director/console.phtml | 4 ++ .../view/director/director/index.phtml | 4 ++ .../view/director/director/messages.phtml | 4 ++ .../Job/src/Job/Controller/JobController.php | 42 +++++++++++++ module/Job/view/job/job/actions.phtml | 4 ++ module/Job/view/job/job/details.phtml | 4 ++ module/Job/view/job/job/index.phtml | 4 ++ .../src/Media/Controller/MediaController.php | 26 ++++++++ module/Media/view/media/media/details.phtml | 4 ++ module/Media/view/media/media/index.phtml | 4 ++ .../src/Pool/Controller/PoolController.php | 26 ++++++++ module/Pool/view/pool/pool/details.phtml | 4 ++ module/Pool/view/pool/pool/index.phtml | 4 ++ module/Restore/config/module.config.php | 1 + .../Restore/Controller/RestoreController.php | 24 +++++++ .../Restore/view/restore/restore/index.phtml | 5 +- .../Controller/ScheduleController.php | 49 +++++++++++++++ .../view/schedule/schedule/details.phtml | 4 ++ .../view/schedule/schedule/index.phtml | 4 ++ .../view/schedule/schedule/overview.phtml | 6 +- .../view/schedule/schedule/status.phtml | 4 ++ .../Storage/Controller/StorageController.php | 43 +++++++++++++ .../view/storage/storage/details.phtml | 4 ++ .../Storage/view/storage/storage/index.phtml | 4 ++ .../Storage/view/storage/storage/status.phtml | 4 ++ 36 files changed, 533 insertions(+), 3 deletions(-) create mode 100644 module/Application/src/Application/Controller/Plugin/CommandACLPlugin.php create mode 100644 module/Application/src/Application/View/Helper/ACLAlert.php diff --git a/module/Application/config/module.config.php b/module/Application/config/module.config.php index 4304b9f0..a0568020 100644 --- a/module/Application/config/module.config.php +++ b/module/Application/config/module.config.php @@ -90,6 +90,7 @@ 'invokables' => array ( //'printExample' => 'Application\View\Helper\Example', // Example ViewHelper 'UpdateAlert' => 'Application\View\Helper\UpdateAlert', + 'ACLAlert' => 'Application\View\Helper\ACLAlert', ), ), 'view_manager' => array( diff --git a/module/Application/src/Application/Controller/Plugin/CommandACLPlugin.php b/module/Application/src/Application/Controller/Plugin/CommandACLPlugin.php new file mode 100644 index 00000000..a5b10bcb --- /dev/null +++ b/module/Application/src/Application/Controller/Plugin/CommandACLPlugin.php @@ -0,0 +1,24 @@ +commands = $commands; + $this->required = $required; + + foreach($this->required as $cmd) { + if($this->commands[$cmd]['permission'] == 0) { + return false; + } + } + return true; + } +} diff --git a/module/Application/src/Application/View/Helper/ACLAlert.php b/module/Application/src/Application/View/Helper/ACLAlert.php new file mode 100644 index 00000000..4a3363e3 --- /dev/null +++ b/module/Application/src/Application/View/Helper/ACLAlert.php @@ -0,0 +1,63 @@ +. + * + */ +namespace Application\View\Helper; + +use Zend\View\Helper\AbstractHelper; + +class ACLAlert extends AbstractHelper +{ + private $required_commands = null; + private $alert = null; + + public function __invoke($required_commands) + { + $msg_part_a = _('Sorry, it seems you are not authorized to run this module. If you think this is an error, please contact your local administrator.'); + $msg_part_b = _('Please read the Bareos documentation for any additional information on how to configure the Command ACL directive of your Console/Profile resources. Following is a list of required commands which need to be in your Command ACL to run this module properly:'); + + $this->required_commands = $required_commands; + + $this->alert = '
'; + $this->alert .= '
'; + $this->alert .= '
'; + $this->alert .= '
'.$msg_part_a.'
'; + $this->alert .= $msg_part_b; + + $this->alert .= '

'; + $this->alert .= '
    '; + + foreach($this->required_commands as $cmd) { + $this->alert .= '
  • '.$cmd.'
  • '; + } + + $this->alert .= '
'; + $this->alert .= '
'; + $this->alert .= '
'; + $this->alert .= '
'; + $this->alert .= '
'; + + return $this->alert; + } +} diff --git a/module/Auth/src/Auth/Controller/AuthController.php b/module/Auth/src/Auth/Controller/AuthController.php index 1a1f1e6d..ccd91ba7 100644 --- a/module/Auth/src/Auth/Controller/AuthController.php +++ b/module/Auth/src/Auth/Controller/AuthController.php @@ -92,7 +92,6 @@ public function loginAction() try { $dird_version = $this->getDirectorModel()->getDirectorVersion($this->bsock); - $this->bsock->disconnect(); } catch(Exception $e) { echo $e->getMessage(); @@ -132,6 +131,30 @@ public function loginAction() $_SESSION['bareos']['product-updates-status'] = false; } + // Get available commands + try { + $commands = $this->getDirectorModel()->getAvailableCommands($this->bsock); + } + catch(Exception $e) { + echo $e->getMessage(); + } + + // Push available commands into SESSION context. + $_SESSION['bareos']['commands'] = $commands; + + // Check if Command ACL has the minimal requirements + if($_SESSION['bareos']['commands']['.help']['permission'] == 0) { + $this->bsock->disconnect(); + session_destroy(); + $err_msg = 'Sorry, your Command ACL does not fit the minimal requirements. For further information, please read the Bareos documentation.'; + return new ViewModel( + array( + 'form' => $form, + 'err_msg' => $err_msg, + ) + ); + } + // Get the config. $configuration = $this->getServiceLocator()->get('configuration'); @@ -151,6 +174,8 @@ public function loginAction() else { return $this->redirect()->toRoute('dashboard', array('action' => 'index')); } + + $this->bsock->disconnect(); } else { $this->bsock->disconnect(); session_destroy(); diff --git a/module/Auth/view/auth/auth/login.phtml b/module/Auth/view/auth/auth/login.phtml index ac46d307..efe5f126 100644 --- a/module/Auth/view/auth/auth/login.phtml +++ b/module/Auth/view/auth/auth/login.phtml @@ -161,6 +161,27 @@ $this->headTitle($title); +
+ + +
+
+ + + err_msg)) { + echo ''; + } + ?> + + +
+
+ +
+ + + diff --git a/module/Dashboard/src/Dashboard/Controller/DashboardController.php b/module/Dashboard/src/Dashboard/Controller/DashboardController.php index 14fa23d7..c490bb8e 100644 --- a/module/Dashboard/src/Dashboard/Controller/DashboardController.php +++ b/module/Dashboard/src/Dashboard/Controller/DashboardController.php @@ -35,6 +35,12 @@ class DashboardController extends AbstractActionController protected $jobModel = null; protected $dashboardModel = null; protected $bsock = null; + protected $acl_alert = false; + + private $required_commands = array( + "list", + "llist" + ); public function indexAction() { @@ -44,6 +50,16 @@ public function indexAction() return $this->redirect()->toRoute('auth', array('action' => 'login'), array('query' => array('req' => $this->RequestURIPlugin()->getRequestURI(), 'dird' => $_SESSION['bareos']['director']))); } + if(!$this->CommandACLPlugin()->validate($_SESSION['bareos']['commands'], $this->required_commands)) { + $this->acl_alert = true; + return new ViewModel( + array( + 'acl_alert' => $this->acl_alert, + 'required_commands' => $this->required_commands, + ) + ); + } + try { $this->bsock = $this->getServiceLocator()->get('director'); $running = $this->getJobs("running", 1, null); diff --git a/module/Dashboard/view/dashboard/dashboard/index.phtml b/module/Dashboard/view/dashboard/dashboard/index.phtml index 7a0c422b..42c06de7 100644 --- a/module/Dashboard/view/dashboard/dashboard/index.phtml +++ b/module/Dashboard/view/dashboard/dashboard/index.phtml @@ -29,6 +29,8 @@ $this->headTitle($title); ?> +acl_alert) : echo $this->ACLAlert($this->required_commands); elseif(!$this->acl_alert) : ?> +
@@ -189,3 +191,5 @@ $this->headTitle($title); ); + + diff --git a/module/Director/src/Director/Controller/DirectorController.php b/module/Director/src/Director/Controller/DirectorController.php index 709f1a48..fb511b26 100644 --- a/module/Director/src/Director/Controller/DirectorController.php +++ b/module/Director/src/Director/Controller/DirectorController.php @@ -33,6 +33,14 @@ class DirectorController extends AbstractActionController { protected $directorModel = null; protected $bsock = null; + protected $acl_alert = false; + + private $required_commands = array( + "list", + "llist", + "status", + "help" + ); public function indexAction() { @@ -42,6 +50,16 @@ public function indexAction() return $this->redirect()->toRoute('auth', array('action' => 'login'), array('query' => array('req' => $this->RequestURIPlugin()->getRequestURI(), 'dird' => $_SESSION['bareos']['director']))); } + if(!$this->CommandACLPlugin()->validate($_SESSION['bareos']['commands'], $this->required_commands)) { + $this->acl_alert = true; + return new ViewModel( + array( + 'acl_alert' => $this->acl_alert, + 'required_commands' => $this->required_commands, + ) + ); + } + try { $this->bsock = $this->getServiceLocator()->get('director'); $result = $this->getDirectorModel()->getDirectorStatus($this->bsock); @@ -64,6 +82,16 @@ public function messagesAction() return $this->redirect()->toRoute('auth', array('action' => 'login'), array('query' => array('req' => $this->RequestURIPlugin()->getRequestURI(), 'dird' => $_SESSION['bareos']['director']))); } + if(!$this->CommandACLPlugin()->validate($_SESSION['bareos']['commands'], $this->required_commands)) { + $this->acl_alert = true; + return new ViewModel( + array( + 'acl_alert' => $this->acl_alert, + 'required_commands' => $this->required_commands, + ) + ); + } + return new ViewModel(); } @@ -75,6 +103,16 @@ public function consoleAction() return $this->redirect()->toRoute('auth', array('action' => 'login'), array('query' => array('req' => $this->RequestURIPlugin()->getRequestURI(), 'dird' => $_SESSION['bareos']['director']))); } + if(!$this->CommandACLPlugin()->validate($_SESSION['bareos']['commands'], $this->required_commands)) { + $this->acl_alert = true; + return new ViewModel( + array( + 'acl_alert' => $this->acl_alert, + 'required_commands' => $this->required_commands, + ) + ); + } + return new ViewModel(); } diff --git a/module/Director/src/Director/Model/DirectorModel.php b/module/Director/src/Director/Model/DirectorModel.php index e156a351..953e1dd8 100644 --- a/module/Director/src/Director/Model/DirectorModel.php +++ b/module/Director/src/Director/Model/DirectorModel.php @@ -27,6 +27,19 @@ class DirectorModel { + public function getAvailableCommands(&$bsock=null) + { + if(isset($bsock)) { + $cmd = '.help'; + $result = $bsock->send_command($cmd, 2, null); + $messages = \Zend\Json\Json::decode($result, \Zend\Json\Json::TYPE_ARRAY); + return $messages['result']; + } + else { + throw new \Exception('Missing argument.'); + } + } + public function getDirectorVersion(&$bsock=null) { if(isset($bsock)) { diff --git a/module/Director/view/director/director/console.phtml b/module/Director/view/director/director/console.phtml index 1eeed5e3..805af287 100644 --- a/module/Director/view/director/director/console.phtml +++ b/module/Director/view/director/director/console.phtml @@ -36,6 +36,8 @@ $this->headTitle($title);
+acl_alert) : echo $this->ACLAlert($this->required_commands); elseif(!$this->acl_alert) : ?> +
    

translate("bconsole (batch-mode), please handle with care."); ?>
translate("All commands have to be a one liner, dialogs are not working."); ?>
translate("Type help for a list of commands."); ?>

@@ -111,3 +113,5 @@ $(document).ready(function() { }); + + diff --git a/module/Director/view/director/director/index.phtml b/module/Director/view/director/director/index.phtml index 70114190..be2fc85c 100644 --- a/module/Director/view/director/director/index.phtml +++ b/module/Director/view/director/director/index.phtml @@ -37,6 +37,8 @@ $this->headTitle($title);
+acl_alert) : echo $this->ACLAlert($this->required_commands); elseif(!$this->acl_alert) : ?> +
@@ -56,3 +58,5 @@ $this->headTitle($title);
+ + diff --git a/module/Director/view/director/director/messages.phtml b/module/Director/view/director/director/messages.phtml index 9cf96a1a..84b4174a 100644 --- a/module/Director/view/director/director/messages.phtml +++ b/module/Director/view/director/director/messages.phtml @@ -36,6 +36,8 @@ $this->headTitle($title);
+acl_alert) : echo $this->ACLAlert($this->required_commands); elseif(!$this->acl_alert) : ?> +
@@ -84,3 +86,5 @@ $(document).ready(function() { }); + + diff --git a/module/Job/src/Job/Controller/JobController.php b/module/Job/src/Job/Controller/JobController.php index 091da45e..96256a77 100644 --- a/module/Job/src/Job/Controller/JobController.php +++ b/module/Job/src/Job/Controller/JobController.php @@ -35,6 +35,18 @@ class JobController extends AbstractActionController protected $jobModel = null; protected $bsock = null; + protected $acl_alert = false; + + private $required_commands = array( + "list", + "llist", + "rerun", + "cancel", + "run", + "enable", + "disable", + ".jobs" + ); public function indexAction() { @@ -44,6 +56,16 @@ public function indexAction() return $this->redirect()->toRoute('auth', array('action' => 'login'), array('query' => array('req' => $this->RequestURIPlugin()->getRequestURI(), 'dird' => $_SESSION['bareos']['director']))); } + if(!$this->CommandACLPlugin()->validate($_SESSION['bareos']['commands'], $this->required_commands)) { + $this->acl_alert = true; + return new ViewModel( + array( + 'acl_alert' => $this->acl_alert, + 'required_commands' => $this->required_commands, + ) + ); + } + $period = $this->params()->fromQuery('period') ? $this->params()->fromQuery('period') : '7'; $status = $this->params()->fromQuery('status') ? $this->params()->fromQUery('status') : 'all'; @@ -105,6 +127,16 @@ public function detailsAction() return $this->redirect()->toRoute('auth', array('action' => 'login'), array('query' => array('req' => $this->RequestURIPlugin()->getRequestURI(), 'dird' => $_SESSION['bareos']['director']))); } + if(!$this->CommandACLPlugin()->validate($_SESSION['bareos']['commands'], $this->required_commands)) { + $this->acl_alert = true; + return new ViewModel( + array( + 'acl_alert' => $this->acl_alert, + 'required_commands' => $this->required_commands, + ) + ); + } + $jobid = (int) $this->params()->fromRoute('id', 0); try { @@ -160,6 +192,16 @@ public function actionsAction() return $this->redirect()->toRoute('auth', array('action' => 'login'), array('query' => array('req' => $this->RequestURIPlugin()->getRequestURI(), 'dird' => $_SESSION['bareos']['director']))); } + if(!$this->CommandACLPlugin()->validate($_SESSION['bareos']['commands'], $this->required_commands)) { + $this->acl_alert = true; + return new ViewModel( + array( + 'acl_alert' => $this->acl_alert, + 'required_commands' => $this->required_commands, + ) + ); + } + $result = null; $action = $this->params()->fromQuery('action'); diff --git a/module/Job/view/job/job/actions.phtml b/module/Job/view/job/job/actions.phtml index 7374d08b..87fb1a4c 100644 --- a/module/Job/view/job/job/actions.phtml +++ b/module/Job/view/job/job/actions.phtml @@ -36,6 +36,8 @@ $this->headTitle($title);
+acl_alert) : echo $this->ACLAlert($this->required_commands); elseif(!$this->acl_alert) : ?> +