portainer/api/internal/authorization/endpoint_role_with_override.go

141 lines
3.2 KiB
Go

package authorization
import (
portainer "github.com/portainer/portainer/api"
"github.com/portainer/portainer/api/dataservices"
)
// CleanNAPWithOverridePolicies Clean Namespace Access Policies with override policies
func (service *Service) CleanNAPWithOverridePolicies(
tx dataservices.DataStoreTx,
endpoint *portainer.Endpoint,
endpointGroup *portainer.EndpointGroup,
) error {
kubecli, err := service.K8sClientFactory.GetKubeClient(endpoint)
if err != nil {
return err
}
accessPolicies, err := kubecli.GetNamespaceAccessPolicies()
if err != nil {
return err
}
hasChange := false
for namespace, policy := range accessPolicies {
for teamID := range policy.TeamAccessPolicies {
access, err := service.getTeamEndpointAccessWithPolicies(tx, teamID, endpoint, endpointGroup)
if err != nil {
return err
}
if !access {
delete(accessPolicies[namespace].TeamAccessPolicies, teamID)
hasChange = true
}
}
for userID := range policy.UserAccessPolicies {
access, err := service.getUserEndpointAccessWithPolicies(tx, userID, endpoint, endpointGroup)
if err != nil {
return err
}
if !access {
delete(accessPolicies[namespace].UserAccessPolicies, userID)
hasChange = true
}
}
}
if hasChange {
return kubecli.UpdateNamespaceAccessPolicies(accessPolicies)
}
return nil
}
func (service *Service) getUserEndpointAccessWithPolicies(
tx dataservices.DataStoreTx,
userID portainer.UserID,
endpoint *portainer.Endpoint,
endpointGroup *portainer.EndpointGroup,
) (bool, error) {
memberships, err := tx.TeamMembership().TeamMembershipsByUserID(userID)
if err != nil {
return false, err
}
if endpointGroup == nil {
endpointGroup, err = tx.EndpointGroup().EndpointGroup(endpoint.GroupID)
if err != nil {
return false, err
}
}
if userAccess(tx, userID, endpoint.UserAccessPolicies, endpoint.TeamAccessPolicies, memberships) {
return true, nil
}
if userAccess(tx, userID, endpointGroup.UserAccessPolicies, endpointGroup.TeamAccessPolicies, memberships) {
return true, nil
}
return false, nil
}
func userAccess(
tx dataservices.DataStoreTx,
userID portainer.UserID,
userAccessPolicies portainer.UserAccessPolicies,
teamAccessPolicies portainer.TeamAccessPolicies,
memberships []portainer.TeamMembership,
) bool {
if _, ok := userAccessPolicies[userID]; ok {
return true
}
for _, membership := range memberships {
if _, ok := teamAccessPolicies[membership.TeamID]; ok {
return true
}
}
return false
}
func (service *Service) getTeamEndpointAccessWithPolicies(
tx dataservices.DataStoreTx,
teamID portainer.TeamID,
endpoint *portainer.Endpoint,
endpointGroup *portainer.EndpointGroup,
) (bool, error) {
if endpointGroup == nil {
var err error
endpointGroup, err = tx.EndpointGroup().EndpointGroup(endpoint.GroupID)
if err != nil {
return false, err
}
}
if teamAccess(teamID, endpoint.TeamAccessPolicies) {
return true, nil
}
if teamAccess(teamID, endpointGroup.TeamAccessPolicies) {
return true, nil
}
return false, nil
}
func teamAccess(
teamID portainer.TeamID,
teamAccessPolicies portainer.TeamAccessPolicies,
) bool {
_, ok := teamAccessPolicies[teamID]
return ok
}