fix(api): review security policies when creating/updating a resource control (#1964)
parent
e3d564325b
commit
1e12057cdd
|
@ -43,6 +43,15 @@ func (handler *Handler) resourceControlUpdate(w http.ResponseWriter, r *http.Req
|
|||
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to find a resource control with with the specified identifier inside the database", err}
|
||||
}
|
||||
|
||||
securityContext, err := security.RetrieveRestrictedRequestContext(r)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to retrieve info from request context", err}
|
||||
}
|
||||
|
||||
if !security.AuthorizedResourceControlAccess(resourceControl, securityContext) {
|
||||
return &httperror.HandlerError{http.StatusForbidden, "Permission denied to update the resource control", portainer.ErrResourceAccessDenied}
|
||||
}
|
||||
|
||||
resourceControl.AdministratorsOnly = payload.AdministratorsOnly
|
||||
|
||||
var userAccesses = make([]portainer.UserResourceAccess, 0)
|
||||
|
@ -65,11 +74,6 @@ func (handler *Handler) resourceControlUpdate(w http.ResponseWriter, r *http.Req
|
|||
}
|
||||
resourceControl.TeamAccesses = teamAccesses
|
||||
|
||||
securityContext, err := security.RetrieveRestrictedRequestContext(r)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to retrieve info from request context", err}
|
||||
}
|
||||
|
||||
if !security.AuthorizedResourceControlUpdate(resourceControl, securityContext) {
|
||||
return &httperror.HandlerError{http.StatusForbidden, "Permission denied to update the resource control", portainer.ErrResourceAccessDenied}
|
||||
}
|
||||
|
|
|
@ -40,6 +40,43 @@ func AuthorizedResourceControlDeletion(resourceControl *portainer.ResourceContro
|
|||
return false
|
||||
}
|
||||
|
||||
// AuthorizedResourceControlAccess checks whether the user can alter an existing resource control.
|
||||
func AuthorizedResourceControlAccess(resourceControl *portainer.ResourceControl, context *RestrictedRequestContext) bool {
|
||||
if context.IsAdmin {
|
||||
return true
|
||||
}
|
||||
|
||||
if resourceControl.AdministratorsOnly {
|
||||
return false
|
||||
}
|
||||
|
||||
authorizedTeamAccess := false
|
||||
for _, access := range resourceControl.TeamAccesses {
|
||||
for _, membership := range context.UserMemberships {
|
||||
if membership.TeamID == access.TeamID {
|
||||
authorizedTeamAccess = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if !authorizedTeamAccess {
|
||||
return false
|
||||
}
|
||||
|
||||
authorizedUserAccess := false
|
||||
for _, access := range resourceControl.UserAccesses {
|
||||
if context.UserID == access.UserID {
|
||||
authorizedUserAccess = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !authorizedUserAccess {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// AuthorizedResourceControlUpdate ensure that the user can update a resource control object.
|
||||
// It reuses the creation restrictions and adds extra checks.
|
||||
// A non-administrator user cannot update a resource control where:
|
||||
|
@ -56,7 +93,9 @@ func AuthorizedResourceControlUpdate(resourceControl *portainer.ResourceControl,
|
|||
// AuthorizedResourceControlCreation ensure that the user can create a resource control object.
|
||||
// A non-administrator user cannot create a resource control where:
|
||||
// * the AdministratorsOnly flag is set
|
||||
// * he wants to create a resource control without any user/team accesses
|
||||
// * he wants to add more than one user in the user accesses
|
||||
// * he wants tp add a user in the user accesses that is not corresponding to its id
|
||||
// * he wants to add a team he is not a member of
|
||||
func AuthorizedResourceControlCreation(resourceControl *portainer.ResourceControl, context *RestrictedRequestContext) bool {
|
||||
if context.IsAdmin {
|
||||
|
@ -69,6 +108,11 @@ func AuthorizedResourceControlCreation(resourceControl *portainer.ResourceContro
|
|||
|
||||
userAccessesCount := len(resourceControl.UserAccesses)
|
||||
teamAccessesCount := len(resourceControl.TeamAccesses)
|
||||
|
||||
if userAccessesCount == 0 && teamAccessesCount == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
if userAccessesCount > 1 || (userAccessesCount == 1 && teamAccessesCount == 1) {
|
||||
return false
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue