feat(settings): add setting to disable device mapping for regular users (#4017)

* feat(settings): introduce device mapping service

* feat(containers): hide devices field when setting is on

* feat(containers): prevent passing of devices when not allowed

* feat(stacks): prevent non admin from device mapping

* feat(stacks): disallow swarm stack creation for user

* refactor(settings): replace disableDeviceMapping with allow

* fix(stacks): remove check for disable device mappings from swarm

* feat(settings): rename field to disable

* feat(settings): supply default value for disableDeviceMapping

* feat(container): check for endpoint admin
This commit is contained in:
Chaim Lev-Ari
2020-07-13 07:32:56 +03:00
committed by GitHub
parent dffcd3fdfd
commit 5ebb03cb4e
16 changed files with 93 additions and 9 deletions

View File

@@ -30,6 +30,7 @@ angular.module('portainer.docker').controller('CreateContainerController', [
'SettingsService',
'PluginService',
'HttpRequestHelper',
'ExtensionService',
function (
$q,
$scope,
@@ -55,7 +56,8 @@ angular.module('portainer.docker').controller('CreateContainerController', [
SystemService,
SettingsService,
PluginService,
HttpRequestHelper
HttpRequestHelper,
ExtensionService
) {
$scope.create = create;
@@ -603,7 +605,7 @@ angular.module('portainer.docker').controller('CreateContainerController', [
});
}
function initView() {
async function initView() {
var nodeName = $transition$.params().nodeName;
$scope.formValues.NodeName = nodeName;
HttpRequestHelper.setPortainerAgentTargetHeader(nodeName);
@@ -682,6 +684,7 @@ angular.module('portainer.docker').controller('CreateContainerController', [
});
$scope.isAdmin = Authentication.isAdmin();
$scope.showDeviceMapping = await shouldShowDevices();
}
function validateForm(accessControlData, isAdmin) {
@@ -894,6 +897,19 @@ angular.module('portainer.docker').controller('CreateContainerController', [
}
}
async function shouldShowDevices() {
const isAdmin = !$scope.applicationState.application.authentication || Authentication.isAdmin();
const { allowDeviceMappingForRegularUsers } = $scope.applicationState.application;
if (isAdmin || allowDeviceMappingForRegularUsers) {
return true;
}
const rbacEnabled = await ExtensionService.extensionEnabled(ExtensionService.EXTENSIONS.RBAC);
if (rbacEnabled) {
return Authentication.hasAuthorizations(['EndpointResourcesAccess']);
}
}
initView();
},
]);

View File

@@ -629,7 +629,7 @@
</form>
<form class="form-horizontal" style="margin-top: 15px;">
<!-- devices -->
<div class="form-group">
<div ng-if="showDeviceMapping" class="form-group">
<div class="col-sm-12" style="margin-top: 5px;">
<label class="control-label text-left">Devices</label>
<span class="label label-default interactive" style="margin-left: 10px;" ng-click="addDevice()">

View File

@@ -15,6 +15,7 @@ export function SettingsViewModel(data) {
this.EnableEdgeComputeFeatures = data.EnableEdgeComputeFeatures;
this.DisableStackManagementForRegularUsers = data.DisableStackManagementForRegularUsers;
this.AllowHostNamespaceForRegularUsers = data.AllowHostNamespaceForRegularUsers;
this.AllowDeviceMappingForRegularUsers = data.AllowDeviceMappingForRegularUsers;
}
export function PublicSettingsViewModel(settings) {
@@ -28,6 +29,7 @@ export function PublicSettingsViewModel(settings) {
this.LogoURL = settings.LogoURL;
this.OAuthLoginURI = settings.OAuthLoginURI;
this.DisableStackManagementForRegularUsers = settings.DisableStackManagementForRegularUsers;
this.AllowDeviceMappingForRegularUsers = settings.AllowDeviceMappingForRegularUsers;
}
export function LDAPSettingsViewModel(data) {

View File

@@ -81,6 +81,11 @@ angular.module('portainer.app').factory('StateManager', [
LocalStorage.storeApplicationState(state.application);
};
manager.updateAllowDeviceMappingForRegularUsers = function updateAllowDeviceMappingForRegularUsers(allowDeviceMappingForRegularUsers) {
state.application.allowDeviceMappingForRegularUsers = allowDeviceMappingForRegularUsers;
LocalStorage.storeApplicationState(state.application);
};
manager.updateAllowHostNamespaceForRegularUsers = function (allowHostNamespaceForRegularUsers) {
state.application.allowHostNamespaceForRegularUsers = allowHostNamespaceForRegularUsers;
LocalStorage.storeApplicationState(state.application);
@@ -98,6 +103,7 @@ angular.module('portainer.app').factory('StateManager', [
state.application.enableVolumeBrowserForNonAdminUsers = settings.AllowVolumeBrowserForRegularUsers;
state.application.enableEdgeComputeFeatures = settings.EnableEdgeComputeFeatures;
state.application.disableStackManagementForRegularUsers = settings.DisableStackManagementForRegularUsers;
state.application.allowDeviceMappingForRegularUsers = settings.AllowDeviceMappingForRegularUsers;
state.application.validity = moment().unix();
}

View File

@@ -141,6 +141,17 @@
</label>
</div>
</div>
<div class="form-group">
<div class="col-sm-12">
<label for="toggle_disableDeviceMappingForRegularUsers" class="control-label text-left">
Disable device mappings for non-administrators
</label>
<label class="switch" style="margin-left: 20px;">
<input type="checkbox" name="toggle_disableDeviceMappingForRegularUsers" ng-model="formValues.disableDeviceMappingForRegularUsers" /><i></i>
</label>
</div>
</div>
<!-- !security -->
<!-- edge -->
<div class="col-sm-12 form-section-title">

View File

@@ -35,6 +35,7 @@ angular.module('portainer.app').controller('SettingsController', [
enableEdgeComputeFeatures: false,
disableStackManagementForRegularUsers: false,
restrictHostNamespaceForRegularUsers: false,
allowDeviceMappingForRegularUsers: false,
};
$scope.removeFilteredContainerLabel = function (index) {
@@ -73,6 +74,7 @@ angular.module('portainer.app').controller('SettingsController', [
settings.EnableEdgeComputeFeatures = $scope.formValues.enableEdgeComputeFeatures;
settings.DisableStackManagementForRegularUsers = $scope.formValues.disableStackManagementForRegularUsers;
settings.AllowHostNamespaceForRegularUsers = !$scope.formValues.restrictHostNamespaceForRegularUsers;
settings.AllowDeviceMappingForRegularUsers = !$scope.formValues.disableDeviceMappingForRegularUsers;
$scope.state.actionInProgress = true;
updateSettings(settings);
@@ -89,6 +91,7 @@ angular.module('portainer.app').controller('SettingsController', [
StateManager.updateEnableEdgeComputeFeatures(settings.EnableEdgeComputeFeatures);
StateManager.updateDisableStackManagementForRegularUsers(settings.DisableStackManagementForRegularUsers);
StateManager.updateAllowHostNamespaceForRegularUsers(settings.AllowHostNamespaceForRegularUsers);
StateManager.updateAllowDeviceMappingForRegularUsers(settings.AllowDeviceMappingForRegularUsers);
$state.reload();
})
.catch(function error(err) {
@@ -117,6 +120,7 @@ angular.module('portainer.app').controller('SettingsController', [
$scope.formValues.enableEdgeComputeFeatures = settings.EnableEdgeComputeFeatures;
$scope.formValues.disableStackManagementForRegularUsers = settings.DisableStackManagementForRegularUsers;
$scope.formValues.restrictHostNamespaceForRegularUsers = !settings.AllowHostNamespaceForRegularUsers;
$scope.formValues.disableDeviceMappingForRegularUsers = !settings.AllowDeviceMappingForRegularUsers;
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to retrieve application settings');