1
0
Fork 0
mirror of https://github.com/portainer/portainer.git synced 2025-07-22 23:09:41 +02:00

feat(containers): Ensure users cannot create privileged containers via the API (#3969) (#4077)

* feat(containers): Ensure users cannot create privileged containers via the API

* feat(containers): add rbac check in stack creation

Co-authored-by: Maxime Bajeux <max.bajeux@gmail.com>
This commit is contained in:
Chaim Lev-Ari 2020-07-22 21:38:45 +03:00 committed by GitHub
parent 4346bf95a7
commit 6f6bc24efd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 135 additions and 18 deletions

View file

@ -1,12 +1,18 @@
package docker
import (
"bytes"
"context"
"encoding/json"
"errors"
"io/ioutil"
"net/http"
"github.com/docker/docker/client"
portainer "github.com/portainer/portainer/api"
bolterrors "github.com/portainer/portainer/api/bolt/errors"
"github.com/portainer/portainer/api/http/proxy/factory/responseutils"
"github.com/portainer/portainer/api/http/security"
"github.com/portainer/portainer/api/internal/authorization"
)
@ -148,3 +154,69 @@ func containerHasBlackListedLabel(containerLabels map[string]interface{}, labelB
return false
}
func (transport *Transport) decorateContainerCreationOperation(request *http.Request, resourceIdentifierAttribute string, resourceType portainer.ResourceControlType) (*http.Response, error) {
type PartialContainer struct {
HostConfig struct {
Privileged bool `json:"Privileged"`
} `json:"HostConfig"`
}
tokenData, err := security.RetrieveTokenData(request)
if err != nil {
return nil, err
}
user, err := transport.dataStore.User().User(tokenData.ID)
if err != nil {
return nil, err
}
rbacExtension, err := transport.dataStore.Extension().Extension(portainer.RBACExtension)
if err != nil && err != bolterrors.ErrObjectNotFound {
return nil, err
}
endpointResourceAccess := false
_, ok := user.EndpointAuthorizations[portainer.EndpointID(transport.endpoint.ID)][portainer.EndpointResourcesAccess]
if ok {
endpointResourceAccess = true
}
if (rbacExtension != nil && !endpointResourceAccess && tokenData.Role != portainer.AdministratorRole) || (rbacExtension == nil && tokenData.Role != portainer.AdministratorRole) {
settings, err := transport.dataStore.Settings().Settings()
if err != nil {
return nil, err
}
if !settings.AllowPrivilegedModeForRegularUsers {
body, err := ioutil.ReadAll(request.Body)
if err != nil {
return nil, err
}
partialContainer := &PartialContainer{}
err = json.Unmarshal(body, partialContainer)
if err != nil {
return nil, err
}
if partialContainer.HostConfig.Privileged {
return nil, errors.New("forbidden to use privileged mode")
}
request.Body = ioutil.NopCloser(bytes.NewBuffer(body))
}
}
response, err := transport.executeDockerRequest(request)
if err != nil {
return response, err
}
if response.StatusCode == http.StatusCreated {
err = transport.decorateGenericResourceCreationResponse(response, resourceIdentifierAttribute, resourceType, tokenData.ID)
}
return response, err
}