From f8bd075ce44fe7e577e4e2839b1c10a1c2f5c7ed Mon Sep 17 00:00:00 2001 From: Chaim Lev-Ari Date: Mon, 13 Jul 2020 13:26:23 +0300 Subject: [PATCH] feat(containers): disable edit container on security setting restricting regular users (#4033) * feat(settings): add info about container edit disable * feat(settings): set security settings * feat(containers): hide recreate button when setting is enabled * feat(settings): rephrase security notice * fix(settings): save allowHostNamespaceForRegularUsers to state --- .../views/containers/edit/containerController.js | 10 ++++++++-- app/portainer/models/settings.js | 1 + app/portainer/services/stateManager.js | 13 +++++++++++++ app/portainer/views/settings/settings.html | 6 ++++++ app/portainer/views/settings/settingsController.js | 7 +++++++ 5 files changed, 35 insertions(+), 2 deletions(-) diff --git a/app/docker/views/containers/edit/containerController.js b/app/docker/views/containers/edit/containerController.js index 6528669f1..4a60af2c5 100644 --- a/app/docker/views/containers/edit/containerController.js +++ b/app/docker/views/containers/edit/containerController.js @@ -21,6 +21,7 @@ angular.module('portainer.docker').controller('ContainerController', [ 'ImageService', 'HttpRequestHelper', 'Authentication', + 'StateManager', function ( $q, $scope, @@ -40,7 +41,8 @@ angular.module('portainer.docker').controller('ContainerController', [ RegistryService, ImageService, HttpRequestHelper, - Authentication + Authentication, + StateManager ) { $scope.activityTime = 0; $scope.portBindings = []; @@ -94,9 +96,13 @@ angular.module('portainer.docker').controller('ContainerController', [ const inSwarm = $scope.container.Config.Labels['com.docker.swarm.service.id']; const autoRemove = $scope.container.HostConfig.AutoRemove; const admin = Authentication.isAdmin(); + const appState = StateManager.getState(); + const { allowHostNamespaceForRegularUsers, allowDeviceMappingForRegularUsers, allowBindMountsForRegularUsers, allowPrivilegedModeForRegularUsers } = appState.application; + const settingRestrictsRegularUsers = + !allowBindMountsForRegularUsers || !allowDeviceMappingForRegularUsers || !allowHostNamespaceForRegularUsers || !allowPrivilegedModeForRegularUsers; ExtensionService.extensionEnabled(ExtensionService.EXTENSIONS.RBAC).then((rbacEnabled) => { - $scope.displayRecreateButton = !inSwarm && !autoRemove && (rbacEnabled ? admin : true); + $scope.displayRecreateButton = !inSwarm && !autoRemove && (settingRestrictsRegularUsers || rbacEnabled ? admin : true); }); }) .catch(function error(err) { diff --git a/app/portainer/models/settings.js b/app/portainer/models/settings.js index 840244e5e..1b1e38672 100644 --- a/app/portainer/models/settings.js +++ b/app/portainer/models/settings.js @@ -30,6 +30,7 @@ export function PublicSettingsViewModel(settings) { this.OAuthLoginURI = settings.OAuthLoginURI; this.AllowStackManagementForRegularUsers = settings.AllowStackManagementForRegularUsers; this.AllowDeviceMappingForRegularUsers = settings.AllowDeviceMappingForRegularUsers; + this.AllowHostNamespaceForRegularUsers = settings.AllowHostNamespaceForRegularUsers; } export function LDAPSettingsViewModel(data) { diff --git a/app/portainer/services/stateManager.js b/app/portainer/services/stateManager.js index 1c8792807..66fc15cf7 100644 --- a/app/portainer/services/stateManager.js +++ b/app/portainer/services/stateManager.js @@ -91,6 +91,16 @@ angular.module('portainer.app').factory('StateManager', [ LocalStorage.storeApplicationState(state.application); }; + manager.updateAllowBindMountsForRegularUsers = function updateAllowBindMountsForRegularUsers(allowBindMountsForRegularUsers) { + state.application.allowBindMountsForRegularUsers = allowBindMountsForRegularUsers; + LocalStorage.storeApplicationState(state.application); + }; + + manager.updateAllowPrivilegedModeForRegularUsers = function (AllowPrivilegedModeForRegularUsers) { + state.application.allowPrivilegedModeForRegularUsers = AllowPrivilegedModeForRegularUsers; + LocalStorage.storeApplicationState(state.application); + }; + function assignStateFromStatusAndSettings(status, settings) { state.application.authentication = status.Authentication; state.application.analytics = status.Analytics; @@ -103,7 +113,10 @@ angular.module('portainer.app').factory('StateManager', [ state.application.enableVolumeBrowserForNonAdminUsers = settings.AllowVolumeBrowserForRegularUsers; state.application.enableEdgeComputeFeatures = settings.EnableEdgeComputeFeatures; state.application.allowStackManagementForRegularUsers = settings.AllowStackManagementForRegularUsers; + state.application.allowBindMountsForRegularUsers = settings.AllowBindMountsForRegularUsers; + state.application.allowPrivilegedModeForRegularUsers = settings.AllowPrivilegedModeForRegularUsers; state.application.allowDeviceMappingForRegularUsers = settings.AllowDeviceMappingForRegularUsers; + state.application.allowHostNamespaceForRegularUsers = settings.AllowHostNamespaceForRegularUsers; state.application.validity = moment().unix(); } diff --git a/app/portainer/views/settings/settings.html b/app/portainer/views/settings/settings.html index a45d1e316..1c43a7bb0 100644 --- a/app/portainer/views/settings/settings.html +++ b/app/portainer/views/settings/settings.html @@ -152,6 +152,12 @@ + +
+ + Note: The recreate/duplicate/edit feature is currently disabled (for non-admin users) by one or more security settings. + +
diff --git a/app/portainer/views/settings/settingsController.js b/app/portainer/views/settings/settingsController.js index 7285051e3..8e85e4938 100644 --- a/app/portainer/views/settings/settingsController.js +++ b/app/portainer/views/settings/settingsController.js @@ -38,6 +38,11 @@ angular.module('portainer.app').controller('SettingsController', [ allowDeviceMappingForRegularUsers: false, }; + $scope.isContainerEditDisabled = function isContainerEditDisabled() { + const { restrictBindMounts, restrictHostNamespaceForRegularUsers, restrictPrivilegedMode, disableDeviceMappingForRegularUsers } = this.formValues; + return restrictBindMounts || restrictHostNamespaceForRegularUsers || restrictPrivilegedMode || disableDeviceMappingForRegularUsers; + }; + $scope.removeFilteredContainerLabel = function (index) { var settings = $scope.settings; settings.BlackListedLabels.splice(index, 1); @@ -92,6 +97,8 @@ angular.module('portainer.app').controller('SettingsController', [ StateManager.updateAllowStackManagementForRegularUsers(settings.AllowStackManagementForRegularUsers); StateManager.updateAllowHostNamespaceForRegularUsers(settings.AllowHostNamespaceForRegularUsers); StateManager.updateAllowDeviceMappingForRegularUsers(settings.AllowDeviceMappingForRegularUsers); + StateManager.updateAllowPrivilegedModeForRegularUsers(settings.AllowPrivilegedModeForRegularUsers); + StateManager.updateAllowBindMountsForRegularUsers(settings.AllowBindMountsForRegularUsers); $state.reload(); }) .catch(function error(err) {