diff --git a/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/Api/SettingsController.php b/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/Api/SettingsController.php index e8fb42d1b..f93f514e9 100644 --- a/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/Api/SettingsController.php +++ b/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/Api/SettingsController.php @@ -1103,4 +1103,265 @@ class SettingsController extends ApiControllerBase "name" ); } + + /** + * retrieve group settings or return defaults + * @param $uuid item unique id + * @return array + */ + public function getGroupAction($uuid = null) + { + $mdlCP = new HAProxy(); + if ($uuid != null) { + $node = $mdlCP->getNodeByReference('groups.group.'.$uuid); + if ($node != null) { + // return node + return array("group" => $node->getNodes()); + } + } else { + // generate new node, but don't save to disc + $node = $mdlCP->groups->group->add(); + return array("group" => $node->getNodes()); + } + return array(); + } + + /** + * update group with given properties + * @param $uuid item unique id + * @return array + */ + public function setGroupAction($uuid) + { + if ($this->request->isPost() && $this->request->hasPost("group")) { + $mdlCP = new HAProxy(); + if ($uuid != null) { + $node = $mdlCP->getNodeByReference('groups.group.'.$uuid); + if ($node != null) { + $node->setNodes($this->request->getPost("group")); + return $this->save($mdlCP, $node, "group"); + } + } + } + return array("result"=>"failed"); + } + + /** + * add new group and set with attributes from post + * @return array + */ + public function addGroupAction() + { + $result = array("result"=>"failed"); + if ($this->request->isPost() && $this->request->hasPost("group")) { + $mdlCP = new HAProxy(); + $node = $mdlCP->groups->group->Add(); + $node->setNodes($this->request->getPost("group")); + return $this->save($mdlCP, $node, "group"); + } + return $result; + } + + /** + * delete group by uuid + * @param $uuid item unique id + * @return array status + */ + public function delGroupAction($uuid) + { + $result = array("result"=>"failed"); + if ($this->request->isPost()) { + $mdlCP = new HAProxy(); + if ($uuid != null) { + if ($mdlCP->groups->group->del($uuid)) { + // if item is removed, serialize to config and save + $mdlCP->serializeToConfig(); + Config::getInstance()->save(); + $result['result'] = 'deleted'; + } else { + $result['result'] = 'not found'; + } + } + } + return $result; + } + + /** + * toggle group by uuid (enable/disable) + * @param $uuid item unique id + * @param $enabled desired state enabled(1)/disabled(0), leave empty for toggle + * @return array status + */ + public function toggleGroupAction($uuid, $enabled = null) + { + + $result = array("result" => "failed"); + if ($this->request->isPost()) { + $mdlCP = new HAProxy(); + if ($uuid != null) { + $node = $mdlCP->getNodeByReference('groups.group.' . $uuid); + if ($node != null) { + if ($enabled == "0" || $enabled == "1") { + $node->enabled = (string)$enabled; + } elseif ((string)$node->enabled == "1") { + $node->enabled = "0"; + } else { + $node->enabled = "1"; + } + $result['result'] = $node->enabled; + // if item has toggled, serialize to config and save + $mdlCP->serializeToConfig(); + Config::getInstance()->save(); + } + } + } + return $result; + } + + /** + * search groups + * @return array + */ + public function searchGroupsAction() + { + $this->sessionClose(); + $mdlCP = new HAProxy(); + $grid = new UIModelGrid($mdlCP->groups->group); + return $grid->fetchBindRequest( + $this->request, + array("enabled", "name", "description"), + "name" + ); + } + + /** + * retrieve user settings or return defaults + * @param $uuid item unique id + * @return array + */ + public function getUserAction($uuid = null) + { + $mdlCP = new HAProxy(); + if ($uuid != null) { + $node = $mdlCP->getNodeByReference('users.user.'.$uuid); + if ($node != null) { + // return node + return array("user" => $node->getNodes()); + } + } else { + // generate new node, but don't save to disc + $node = $mdlCP->users->user->add(); + return array("user" => $node->getNodes()); + } + return array(); + } + + /** + * update user with given properties + * @param $uuid item unique id + * @return array + */ + public function setUserAction($uuid) + { + if ($this->request->isPost() && $this->request->hasPost("user")) { + $mdlCP = new HAProxy(); + if ($uuid != null) { + $node = $mdlCP->getNodeByReference('users.user.'.$uuid); + if ($node != null) { + $node->setNodes($this->request->getPost("user")); + return $this->save($mdlCP, $node, "user"); + } + } + } + return array("result"=>"failed"); + } + + /** + * add new user and set with attributes from post + * @return array + */ + public function addUserAction() + { + $result = array("result"=>"failed"); + if ($this->request->isPost() && $this->request->hasPost("user")) { + $mdlCP = new HAProxy(); + $node = $mdlCP->users->user->Add(); + $node->setNodes($this->request->getPost("user")); + return $this->save($mdlCP, $node, "user"); + } + return $result; + } + + /** + * delete user by uuid + * @param $uuid item unique id + * @return array status + */ + public function delUserAction($uuid) + { + $result = array("result"=>"failed"); + if ($this->request->isPost()) { + $mdlCP = new HAProxy(); + if ($uuid != null) { + if ($mdlCP->users->user->del($uuid)) { + // if item is removed, serialize to config and save + $mdlCP->serializeToConfig(); + Config::getInstance()->save(); + $result['result'] = 'deleted'; + } else { + $result['result'] = 'not found'; + } + } + } + return $result; + } + + /** + * toggle user by uuid (enable/disable) + * @param $uuid item unique id + * @param $enabled desired state enabled(1)/disabled(0), leave empty for toggle + * @return array status + */ + public function toggleUserAction($uuid, $enabled = null) + { + + $result = array("result" => "failed"); + if ($this->request->isPost()) { + $mdlCP = new HAProxy(); + if ($uuid != null) { + $node = $mdlCP->getNodeByReference('users.user.' . $uuid); + if ($node != null) { + if ($enabled == "0" || $enabled == "1") { + $node->enabled = (string)$enabled; + } elseif ((string)$node->enabled == "1") { + $node->enabled = "0"; + } else { + $node->enabled = "1"; + } + $result['result'] = $node->enabled; + // if item has toggled, serialize to config and save + $mdlCP->serializeToConfig(); + Config::getInstance()->save(); + } + } + } + return $result; + } + + /** + * search users + * @return array + */ + public function searchUsersAction() + { + $this->sessionClose(); + $mdlCP = new HAProxy(); + $grid = new UIModelGrid($mdlCP->users->user); + return $grid->fetchBindRequest( + $this->request, + array("enabled", "name", "description"), + "name" + ); + } + } diff --git a/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/IndexController.php b/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/IndexController.php index 265d1734d..604f1d4c7 100644 --- a/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/IndexController.php +++ b/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/IndexController.php @@ -51,6 +51,8 @@ class IndexController extends \OPNsense\Base\IndexController $this->view->formDialogHealthcheck = $this->getForm("dialogHealthcheck"); $this->view->formDialogAction = $this->getForm("dialogAction"); $this->view->formDialogAcl = $this->getForm("dialogAcl"); + $this->view->formDialogUser = $this->getForm("dialogUser"); + $this->view->formDialogGroup = $this->getForm("dialogGroup"); $this->view->formDialogLua = $this->getForm("dialogLua"); $this->view->formDialogErrorfile = $this->getForm("dialogErrorfile"); $this->view->formDialogMapfile = $this->getForm("dialogMapfile"); diff --git a/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/forms/dialogGroup.xml b/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/forms/dialogGroup.xml new file mode 100644 index 000000000..d868a472d --- /dev/null +++ b/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/forms/dialogGroup.xml @@ -0,0 +1,27 @@ +
+ + group.enabled + + checkbox + Enable this group. + + + group.name + + text + Name to identify this group. + + + group.description + + text + Description for this group. + + + group.members + + select_multiple + true + Type username or choose from list. + +
diff --git a/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/forms/dialogUser.xml b/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/forms/dialogUser.xml new file mode 100644 index 000000000..000bd9a65 --- /dev/null +++ b/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/forms/dialogUser.xml @@ -0,0 +1,26 @@ +
+ + user.enabled + + checkbox + Enable this user. + + + user.name + + text + Name to identify this user. + + + user.description + + text + Description for this user. + + + user.password + + password +
NOTE: Avoid using unencrypted passwords that start with a $-sign, because this indicates an encrypted password and will make it impossible to authenticate.
]]>
+
+
diff --git a/net/haproxy/src/opnsense/mvc/app/models/OPNsense/HAProxy/HAProxy.xml b/net/haproxy/src/opnsense/mvc/app/models/OPNsense/HAProxy/HAProxy.xml index 3ada067d2..16d993616 100644 --- a/net/haproxy/src/opnsense/mvc/app/models/OPNsense/HAProxy/HAProxy.xml +++ b/net/haproxy/src/opnsense/mvc/app/models/OPNsense/HAProxy/HAProxy.xml @@ -1,6 +1,6 @@ //OPNsense/HAProxy - 2.5.0 + 2.6.0 the HAProxy load balancer @@ -1921,5 +1921,64 @@ + + + + Y + + + 1 + Y + + + /^[^\t^,^;^\.^\[^\]^\{^\}]{1,255}$/u + Should be a string between 1 and 255 characters. + Y + + + /^.{1,255}$/u + Should be a string between 1 and 255 characters. + N + + + + + + Related user not found + Y + N + + + + + + + Y + + + 1 + Y + + + /^[^\t^,^;^\.^\[^\]^\{^\}]{1,255}$/u + Should be a string between 1 and 255 characters. + Y + + + /^.{1,255}$/u + Should be a string between 1 and 255 characters. + N + + + /^.{1,512}$/u + Should be a string between 1 and 512 characters. + Y + + + diff --git a/net/haproxy/src/opnsense/mvc/app/models/OPNsense/HAProxy/Menu/Menu.xml b/net/haproxy/src/opnsense/mvc/app/models/OPNsense/HAProxy/Menu/Menu.xml index 3747da2ca..8e11c33d5 100644 --- a/net/haproxy/src/opnsense/mvc/app/models/OPNsense/HAProxy/Menu/Menu.xml +++ b/net/haproxy/src/opnsense/mvc/app/models/OPNsense/HAProxy/Menu/Menu.xml @@ -14,6 +14,8 @@ + + diff --git a/net/haproxy/src/opnsense/mvc/app/views/OPNsense/HAProxy/index.volt b/net/haproxy/src/opnsense/mvc/app/views/OPNsense/HAProxy/index.volt index 6148888a7..b6c9479b1 100644 --- a/net/haproxy/src/opnsense/mvc/app/views/OPNsense/HAProxy/index.volt +++ b/net/haproxy/src/opnsense/mvc/app/views/OPNsense/HAProxy/index.volt @@ -121,6 +121,32 @@ POSSIBILITY OF SUCH DAMAGE. } ); + $("#grid-users").UIBootgrid( + { search:'/api/haproxy/settings/searchUsers', + get:'/api/haproxy/settings/getUser/', + set:'/api/haproxy/settings/setUser/', + add:'/api/haproxy/settings/addUser/', + del:'/api/haproxy/settings/delUser/', + toggle:'/api/haproxy/settings/toggleUser/', + options: { + rowCount:[10,25,50,100,500,1000] + } + } + ); + + $("#grid-groups").UIBootgrid( + { search:'/api/haproxy/settings/searchGroups', + get:'/api/haproxy/settings/getGroup/', + set:'/api/haproxy/settings/setGroup/', + add:'/api/haproxy/settings/addGroup/', + del:'/api/haproxy/settings/delGroup/', + toggle:'/api/haproxy/settings/toggleGroup/', + options: { + rowCount:[10,25,50,100,500,1000] + } + } + ); + $("#grid-luas").UIBootgrid( { search:'/api/haproxy/settings/searchLuas', get:'/api/haproxy/settings/getLua/', @@ -439,6 +465,20 @@ POSSIBILITY OF SUCH DAMAGE. + + {# add automatically generated tabs #} {% for tab in mainForm['tabs']|default([]) %} {% if tab['subtabs']|default(false) %} @@ -541,6 +581,20 @@ POSSIBILITY OF SUCH DAMAGE. +
+
+

{{ lang._('User Management') }}

+

{{ lang._("Optionally HAProxy manages an internal list of users and groups, which can be used for HTTP Basic Authentication as well as access to HAProxy's internal statistic pages.") }}

+
    +
  • {{ lang._('%sUser:%s A username/password combination. Both secure (encrypted) and insecure (unencrypted) passwords can be used.') | format('', '') }}
  • +
  • {{ lang._('%sGroup:%s A optional list containing one or more users. Groups usually make it easier to manage permissions for a large number of users') | format('', '') }}
  • +
+

{{ lang._('Note that users and groups must be selected from the Backend Pool or Public Service configuration in order to be used for authentication.') }}

+

{{ lang._("For more information on HAProxy's %suser/group management%s see the %sofficial documentation%s.") | format('', '', '', '') }}

+
+
+
+

{{ lang._('Advanced Features') }}

@@ -780,6 +834,76 @@ POSSIBILITY OF SUCH DAMAGE.
+
+ + + + + + + + + + + + + + + + + + + + +
{{ lang._('Enabled') }}{{ lang._('User ID') }}{{ lang._('Username') }}{{ lang._('Description') }}{{ lang._('Commands') }}{{ lang._('ID') }}
+ + +
+ +
+
+ + +
+
+
+
+ +
+ + + + + + + + + + + + + + + + + + + + +
{{ lang._('Enabled') }}{{ lang._('Group ID') }}{{ lang._('Group') }}{{ lang._('Description') }}{{ lang._('Commands') }}{{ lang._('ID') }}
+ + +
+ +
+
+ + +
+
+
+
+
@@ -891,6 +1015,8 @@ POSSIBILITY OF SUCH DAMAGE. {{ partial("layout_partials/base_dialog",['fields':formDialogHealthcheck,'id':'DialogHealthcheck','label':lang._('Edit Health Monitor')])}} {{ partial("layout_partials/base_dialog",['fields':formDialogAction,'id':'DialogAction','label':lang._('Edit Rule')])}} {{ partial("layout_partials/base_dialog",['fields':formDialogAcl,'id':'DialogAcl','label':lang._('Edit Condition')])}} +{{ partial("layout_partials/base_dialog",['fields':formDialogUser,'id':'DialogUser','label':lang._('Edit User')])}} +{{ partial("layout_partials/base_dialog",['fields':formDialogGroup,'id':'DialogGroup','label':lang._('Edit Group')])}} {{ partial("layout_partials/base_dialog",['fields':formDialogLua,'id':'DialogLua','label':lang._('Edit Lua Script')])}} {{ partial("layout_partials/base_dialog",['fields':formDialogErrorfile,'id':'DialogErrorfile','label':lang._('Edit Error Message')])}} {{ partial("layout_partials/base_dialog",['fields':formDialogMapfile,'id':'DialogMapfile','label':lang._('Edit Map File')])}}