mirror of
https://github.com/portainer/portainer.git
synced 2025-07-24 15:59:41 +02:00
feat(settings): add a setting to disable privileged mode for non-admins (#1239)
This commit is contained in:
parent
ca9d9b9a77
commit
0bdcff09f8
10 changed files with 79 additions and 33 deletions
16
api/bolt/migrate_dbversion5.go
Normal file
16
api/bolt/migrate_dbversion5.go
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
package bolt
|
||||||
|
|
||||||
|
func (m *Migrator) updateSettingsToVersion6() error {
|
||||||
|
legacySettings, err := m.SettingsService.Settings()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
legacySettings.AllowPrivilegedModeForRegularUsers = true
|
||||||
|
|
||||||
|
err = m.SettingsService.StoreSettings(legacySettings)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -73,6 +73,14 @@ func (m *Migrator) Migrate() error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://github.com/portainer/portainer/issues/1236
|
||||||
|
if m.CurrentDBVersion < 6 {
|
||||||
|
err := m.updateSettingsToVersion6()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
err := m.VersionService.StoreDBVersion(portainer.DBVersion)
|
err := m.VersionService.StoreDBVersion(portainer.DBVersion)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -125,7 +125,8 @@ func initSettings(settingsService portainer.SettingsService, flags *portainer.CL
|
||||||
portainer.LDAPSearchSettings{},
|
portainer.LDAPSearchSettings{},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
AllowBindMountsForRegularUsers: true,
|
AllowBindMountsForRegularUsers: true,
|
||||||
|
AllowPrivilegedModeForRegularUsers: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
if *flags.Templates != "" {
|
if *flags.Templates != "" {
|
||||||
|
|
|
@ -45,20 +45,22 @@ func NewSettingsHandler(bouncer *security.RequestBouncer) *SettingsHandler {
|
||||||
|
|
||||||
type (
|
type (
|
||||||
publicSettingsResponse struct {
|
publicSettingsResponse struct {
|
||||||
LogoURL string `json:"LogoURL"`
|
LogoURL string `json:"LogoURL"`
|
||||||
DisplayExternalContributors bool `json:"DisplayExternalContributors"`
|
DisplayExternalContributors bool `json:"DisplayExternalContributors"`
|
||||||
AuthenticationMethod portainer.AuthenticationMethod `json:"AuthenticationMethod"`
|
AuthenticationMethod portainer.AuthenticationMethod `json:"AuthenticationMethod"`
|
||||||
AllowBindMountsForRegularUsers bool `json:"AllowBindMountsForRegularUsers"`
|
AllowBindMountsForRegularUsers bool `json:"AllowBindMountsForRegularUsers"`
|
||||||
|
AllowPrivilegedModeForRegularUsers bool `json:"AllowPrivilegedModeForRegularUsers"`
|
||||||
}
|
}
|
||||||
|
|
||||||
putSettingsRequest struct {
|
putSettingsRequest struct {
|
||||||
TemplatesURL string `valid:"required"`
|
TemplatesURL string `valid:"required"`
|
||||||
LogoURL string `valid:""`
|
LogoURL string `valid:""`
|
||||||
BlackListedLabels []portainer.Pair `valid:""`
|
BlackListedLabels []portainer.Pair `valid:""`
|
||||||
DisplayExternalContributors bool `valid:""`
|
DisplayExternalContributors bool `valid:""`
|
||||||
AuthenticationMethod int `valid:"required"`
|
AuthenticationMethod int `valid:"required"`
|
||||||
LDAPSettings portainer.LDAPSettings `valid:""`
|
LDAPSettings portainer.LDAPSettings `valid:""`
|
||||||
AllowBindMountsForRegularUsers bool `valid:""`
|
AllowBindMountsForRegularUsers bool `valid:""`
|
||||||
|
AllowPrivilegedModeForRegularUsers bool `valid:""`
|
||||||
}
|
}
|
||||||
|
|
||||||
putSettingsLDAPCheckRequest struct {
|
putSettingsLDAPCheckRequest struct {
|
||||||
|
@ -87,10 +89,11 @@ func (handler *SettingsHandler) handleGetPublicSettings(w http.ResponseWriter, r
|
||||||
}
|
}
|
||||||
|
|
||||||
publicSettings := &publicSettingsResponse{
|
publicSettings := &publicSettingsResponse{
|
||||||
LogoURL: settings.LogoURL,
|
LogoURL: settings.LogoURL,
|
||||||
DisplayExternalContributors: settings.DisplayExternalContributors,
|
DisplayExternalContributors: settings.DisplayExternalContributors,
|
||||||
AuthenticationMethod: settings.AuthenticationMethod,
|
AuthenticationMethod: settings.AuthenticationMethod,
|
||||||
AllowBindMountsForRegularUsers: settings.AllowBindMountsForRegularUsers,
|
AllowBindMountsForRegularUsers: settings.AllowBindMountsForRegularUsers,
|
||||||
|
AllowPrivilegedModeForRegularUsers: settings.AllowPrivilegedModeForRegularUsers,
|
||||||
}
|
}
|
||||||
|
|
||||||
encodeJSON(w, publicSettings, handler.Logger)
|
encodeJSON(w, publicSettings, handler.Logger)
|
||||||
|
@ -112,12 +115,13 @@ func (handler *SettingsHandler) handlePutSettings(w http.ResponseWriter, r *http
|
||||||
}
|
}
|
||||||
|
|
||||||
settings := &portainer.Settings{
|
settings := &portainer.Settings{
|
||||||
TemplatesURL: req.TemplatesURL,
|
TemplatesURL: req.TemplatesURL,
|
||||||
LogoURL: req.LogoURL,
|
LogoURL: req.LogoURL,
|
||||||
BlackListedLabels: req.BlackListedLabels,
|
BlackListedLabels: req.BlackListedLabels,
|
||||||
DisplayExternalContributors: req.DisplayExternalContributors,
|
DisplayExternalContributors: req.DisplayExternalContributors,
|
||||||
LDAPSettings: req.LDAPSettings,
|
LDAPSettings: req.LDAPSettings,
|
||||||
AllowBindMountsForRegularUsers: req.AllowBindMountsForRegularUsers,
|
AllowBindMountsForRegularUsers: req.AllowBindMountsForRegularUsers,
|
||||||
|
AllowPrivilegedModeForRegularUsers: req.AllowPrivilegedModeForRegularUsers,
|
||||||
}
|
}
|
||||||
|
|
||||||
if req.AuthenticationMethod == 1 {
|
if req.AuthenticationMethod == 1 {
|
||||||
|
|
|
@ -70,13 +70,14 @@ type (
|
||||||
|
|
||||||
// Settings represents the application settings.
|
// Settings represents the application settings.
|
||||||
Settings struct {
|
Settings struct {
|
||||||
TemplatesURL string `json:"TemplatesURL"`
|
TemplatesURL string `json:"TemplatesURL"`
|
||||||
LogoURL string `json:"LogoURL"`
|
LogoURL string `json:"LogoURL"`
|
||||||
BlackListedLabels []Pair `json:"BlackListedLabels"`
|
BlackListedLabels []Pair `json:"BlackListedLabels"`
|
||||||
DisplayExternalContributors bool `json:"DisplayExternalContributors"`
|
DisplayExternalContributors bool `json:"DisplayExternalContributors"`
|
||||||
AuthenticationMethod AuthenticationMethod `json:"AuthenticationMethod"`
|
AuthenticationMethod AuthenticationMethod `json:"AuthenticationMethod"`
|
||||||
LDAPSettings LDAPSettings `json:"LDAPSettings"`
|
LDAPSettings LDAPSettings `json:"LDAPSettings"`
|
||||||
AllowBindMountsForRegularUsers bool `json:"AllowBindMountsForRegularUsers"`
|
AllowBindMountsForRegularUsers bool `json:"AllowBindMountsForRegularUsers"`
|
||||||
|
AllowPrivilegedModeForRegularUsers bool `json:"AllowPrivilegedModeForRegularUsers"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// User represents a user account.
|
// User represents a user account.
|
||||||
|
@ -349,7 +350,7 @@ const (
|
||||||
// APIVersion is the version number of the Portainer API.
|
// APIVersion is the version number of the Portainer API.
|
||||||
APIVersion = "1.14.2"
|
APIVersion = "1.14.2"
|
||||||
// DBVersion is the version number of the Portainer database.
|
// DBVersion is the version number of the Portainer database.
|
||||||
DBVersion = 5
|
DBVersion = 6
|
||||||
// DefaultTemplatesURL represents the default URL for the templates definitions.
|
// DefaultTemplatesURL represents the default URL for the templates definitions.
|
||||||
DefaultTemplatesURL = "https://raw.githubusercontent.com/portainer/templates/master/templates.json"
|
DefaultTemplatesURL = "https://raw.githubusercontent.com/portainer/templates/master/templates.json"
|
||||||
)
|
)
|
||||||
|
|
|
@ -485,6 +485,7 @@ function ($q, $scope, $state, $transition$, $filter, Container, ContainerHelper,
|
||||||
SettingsService.publicSettings()
|
SettingsService.publicSettings()
|
||||||
.then(function success(data) {
|
.then(function success(data) {
|
||||||
$scope.allowBindMounts = data.AllowBindMountsForRegularUsers;
|
$scope.allowBindMounts = data.AllowBindMountsForRegularUsers;
|
||||||
|
$scope.allowPrivilegedMode = data.AllowPrivilegedModeForRegularUsers;
|
||||||
})
|
})
|
||||||
.catch(function error(err) {
|
.catch(function error(err) {
|
||||||
Notifications.error('Failure', err, 'Unable to retrieve application settings');
|
Notifications.error('Failure', err, 'Unable to retrieve application settings');
|
||||||
|
|
|
@ -470,13 +470,13 @@
|
||||||
<div class="tab-pane" id="runtime">
|
<div class="tab-pane" id="runtime">
|
||||||
<form class="form-horizontal" style="margin-top: 15px;">
|
<form class="form-horizontal" style="margin-top: 15px;">
|
||||||
<!-- privileged-mode -->
|
<!-- privileged-mode -->
|
||||||
<div class="form-group">
|
<div class="form-group" ng-if="isAdmin || allowPrivilegedMode">
|
||||||
<div class="col-sm-12">
|
<div class="col-sm-12">
|
||||||
<label for="ownership" class="control-label text-left">
|
<label for="privileged_mode" class="control-label text-left">
|
||||||
Privileged mode
|
Privileged mode
|
||||||
</label>
|
</label>
|
||||||
<label class="switch" style="margin-left: 20px;">
|
<label class="switch" style="margin-left: 20px;">
|
||||||
<input type="checkbox" ng-model="config.HostConfig.Privileged"><i></i>
|
<input type="checkbox" name="privileged_mode" ng-model="config.HostConfig.Privileged"><i></i>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -26,6 +26,17 @@
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="col-sm-12">
|
||||||
|
<label for="toggle_allowbindmounts" class="control-label text-left">
|
||||||
|
Disable privileged mode for non-administrators
|
||||||
|
<portainer-tooltip position="bottom" message="When enabled, regular users will not be able to use privileged mode when creating containers."></portainer-tooltip>
|
||||||
|
</label>
|
||||||
|
<label class="switch" style="margin-left: 20px;">
|
||||||
|
<input type="checkbox" name="toggle_allowbindmounts" ng-model="formValues.restrictPrivilegedMode"><i></i>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<!-- security -->
|
<!-- security -->
|
||||||
<!-- logo -->
|
<!-- logo -->
|
||||||
<div class="col-sm-12 form-section-title">
|
<div class="col-sm-12 form-section-title">
|
||||||
|
|
|
@ -7,6 +7,7 @@ function ($scope, $state, Notifications, SettingsService, StateManager, DEFAULT_
|
||||||
customTemplates: false,
|
customTemplates: false,
|
||||||
externalContributions: false,
|
externalContributions: false,
|
||||||
restrictBindMounts: false,
|
restrictBindMounts: false,
|
||||||
|
restrictPrivilegedMode: false,
|
||||||
labelName: '',
|
labelName: '',
|
||||||
labelValue: ''
|
labelValue: ''
|
||||||
};
|
};
|
||||||
|
@ -41,6 +42,7 @@ function ($scope, $state, Notifications, SettingsService, StateManager, DEFAULT_
|
||||||
}
|
}
|
||||||
settings.DisplayExternalContributors = !$scope.formValues.externalContributions;
|
settings.DisplayExternalContributors = !$scope.formValues.externalContributions;
|
||||||
settings.AllowBindMountsForRegularUsers = !$scope.formValues.restrictBindMounts;
|
settings.AllowBindMountsForRegularUsers = !$scope.formValues.restrictBindMounts;
|
||||||
|
settings.AllowPrivilegedModeForRegularUsers = !$scope.formValues.restrictPrivilegedMode;
|
||||||
|
|
||||||
updateSettings(settings, false);
|
updateSettings(settings, false);
|
||||||
};
|
};
|
||||||
|
@ -84,6 +86,7 @@ function ($scope, $state, Notifications, SettingsService, StateManager, DEFAULT_
|
||||||
}
|
}
|
||||||
$scope.formValues.externalContributions = !settings.DisplayExternalContributors;
|
$scope.formValues.externalContributions = !settings.DisplayExternalContributors;
|
||||||
$scope.formValues.restrictBindMounts = !settings.AllowBindMountsForRegularUsers;
|
$scope.formValues.restrictBindMounts = !settings.AllowBindMountsForRegularUsers;
|
||||||
|
$scope.formValues.restrictPrivilegedMode = !settings.AllowPrivilegedModeForRegularUsers;
|
||||||
})
|
})
|
||||||
.catch(function error(err) {
|
.catch(function error(err) {
|
||||||
Notifications.error('Failure', err, 'Unable to retrieve application settings');
|
Notifications.error('Failure', err, 'Unable to retrieve application settings');
|
||||||
|
|
|
@ -6,4 +6,5 @@ function SettingsViewModel(data) {
|
||||||
this.AuthenticationMethod = data.AuthenticationMethod;
|
this.AuthenticationMethod = data.AuthenticationMethod;
|
||||||
this.LDAPSettings = data.LDAPSettings;
|
this.LDAPSettings = data.LDAPSettings;
|
||||||
this.AllowBindMountsForRegularUsers = data.AllowBindMountsForRegularUsers;
|
this.AllowBindMountsForRegularUsers = data.AllowBindMountsForRegularUsers;
|
||||||
|
this.AllowPrivilegedModeForRegularUsers = data.AllowPrivilegedModeForRegularUsers;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue