mirror of https://github.com/portainer/portainer
fix(kubernetes): run group permission when endpoint is up [EE-5427] (#10121)
* update group access when env is down * fix testspull/10192/head
parent
d75a8027a5
commit
a02f9f1f07
|
@ -73,6 +73,7 @@
|
||||||
},
|
},
|
||||||
"LastCheckInDate": 0,
|
"LastCheckInDate": 0,
|
||||||
"Name": "local",
|
"Name": "local",
|
||||||
|
"PendingActions": null,
|
||||||
"PostInitMigrations": {
|
"PostInitMigrations": {
|
||||||
"MigrateGPUs": true,
|
"MigrateGPUs": true,
|
||||||
"MigrateIngresses": true
|
"MigrateIngresses": true
|
||||||
|
|
|
@ -7,11 +7,13 @@ import (
|
||||||
|
|
||||||
portainer "github.com/portainer/portainer/api"
|
portainer "github.com/portainer/portainer/api"
|
||||||
"github.com/portainer/portainer/api/dataservices"
|
"github.com/portainer/portainer/api/dataservices"
|
||||||
|
"github.com/portainer/portainer/api/http/utils"
|
||||||
"github.com/portainer/portainer/api/internal/tag"
|
"github.com/portainer/portainer/api/internal/tag"
|
||||||
"github.com/portainer/portainer/pkg/featureflags"
|
"github.com/portainer/portainer/pkg/featureflags"
|
||||||
httperror "github.com/portainer/portainer/pkg/libhttp/error"
|
httperror "github.com/portainer/portainer/pkg/libhttp/error"
|
||||||
"github.com/portainer/portainer/pkg/libhttp/request"
|
"github.com/portainer/portainer/pkg/libhttp/request"
|
||||||
"github.com/portainer/portainer/pkg/libhttp/response"
|
"github.com/portainer/portainer/pkg/libhttp/response"
|
||||||
|
"github.com/rs/zerolog/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
type endpointGroupUpdatePayload struct {
|
type endpointGroupUpdatePayload struct {
|
||||||
|
@ -187,7 +189,10 @@ func (handler *Handler) updateEndpointGroup(tx dataservices.DataStoreTx, endpoin
|
||||||
if endpoint.Type == portainer.KubernetesLocalEnvironment || endpoint.Type == portainer.AgentOnKubernetesEnvironment || endpoint.Type == portainer.EdgeAgentOnKubernetesEnvironment {
|
if endpoint.Type == portainer.KubernetesLocalEnvironment || endpoint.Type == portainer.AgentOnKubernetesEnvironment || endpoint.Type == portainer.EdgeAgentOnKubernetesEnvironment {
|
||||||
err = handler.AuthorizationService.CleanNAPWithOverridePolicies(tx, &endpoint, endpointGroup)
|
err = handler.AuthorizationService.CleanNAPWithOverridePolicies(tx, &endpoint, endpointGroup)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, httperror.InternalServerError("Unable to update user authorizations", err)
|
// Update flag with endpoint and continue
|
||||||
|
endpoint.PendingActions = utils.GetUpdatedEndpointPendingActions(&endpoint, "CleanNAPWithOverridePolicies", endpointGroup.ID)
|
||||||
|
err = tx.Endpoint().UpdateEndpoint(endpoint.ID, &endpoint)
|
||||||
|
log.Warn().Err(err).Msgf("Unable to update user authorizations for endpoint (%d) and endpopint group (%d)", endpoint.ID, endpointGroup.ID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
portainer "github.com/portainer/portainer/api"
|
portainer "github.com/portainer/portainer/api"
|
||||||
|
"github.com/portainer/portainer/api/http/utils"
|
||||||
"github.com/portainer/portainer/api/internal/endpointutils"
|
"github.com/portainer/portainer/api/internal/endpointutils"
|
||||||
httperror "github.com/portainer/portainer/pkg/libhttp/error"
|
httperror "github.com/portainer/portainer/pkg/libhttp/error"
|
||||||
"github.com/portainer/portainer/pkg/libhttp/request"
|
"github.com/portainer/portainer/pkg/libhttp/request"
|
||||||
|
@ -78,6 +79,9 @@ func (handler *Handler) endpointInspect(w http.ResponseWriter, r *http.Request)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Run the pending actions
|
||||||
|
utils.RunPendingActions(endpoint, handler.DataStore, handler.AuthorizationService)
|
||||||
|
|
||||||
return response.JSON(w, endpoint)
|
return response.JSON(w, endpoint)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,61 @@
|
||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
portainer "github.com/portainer/portainer/api"
|
||||||
|
"github.com/portainer/portainer/api/dataservices"
|
||||||
|
"github.com/portainer/portainer/api/internal/authorization"
|
||||||
|
"github.com/rs/zerolog/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
func EndpointPendingActions(endpoint *portainer.Endpoint) *portainer.EndpointPendingActions {
|
||||||
|
return endpoint.PendingActions
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetUpdatedEndpointPendingActions(endpoint *portainer.Endpoint, action string, value interface{}) *portainer.EndpointPendingActions {
|
||||||
|
if endpoint.PendingActions == nil {
|
||||||
|
endpoint.PendingActions = &portainer.EndpointPendingActions{}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch action {
|
||||||
|
case "CleanNAPWithOverridePolicies":
|
||||||
|
endpoint.PendingActions.CleanNAPWithOverridePolicies.EndpointGroups = append(endpoint.PendingActions.CleanNAPWithOverridePolicies.EndpointGroups, value.(portainer.EndpointGroupID))
|
||||||
|
}
|
||||||
|
|
||||||
|
return endpoint.PendingActions
|
||||||
|
}
|
||||||
|
|
||||||
|
func RunPendingActions(endpoint *portainer.Endpoint, dataStore dataservices.DataStoreTx, authorizationService *authorization.Service) error {
|
||||||
|
|
||||||
|
if endpoint.PendingActions == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Info().Msgf("Running pending actions for endpoint %d", endpoint.ID)
|
||||||
|
|
||||||
|
if endpoint.PendingActions.CleanNAPWithOverridePolicies.EndpointGroups != nil {
|
||||||
|
log.Info().Int("endpoint_id", int(endpoint.ID)).Msgf("Cleaning NAP with override policies for endpoint groups %v", endpoint.PendingActions.CleanNAPWithOverridePolicies.EndpointGroups)
|
||||||
|
failedEndpointGroupIDs := make([]portainer.EndpointGroupID, 0)
|
||||||
|
for _, endpointGroupID := range endpoint.PendingActions.CleanNAPWithOverridePolicies.EndpointGroups {
|
||||||
|
endpointGroup, err := dataStore.EndpointGroup().Read(portainer.EndpointGroupID(endpointGroupID))
|
||||||
|
if err != nil {
|
||||||
|
log.Error().Err(err).Msgf("Error reading endpoint group to clean NAP with override policies for endpoint %d and endpoint group %d", endpoint.ID, endpointGroup.ID)
|
||||||
|
failedEndpointGroupIDs = append(failedEndpointGroupIDs, endpointGroupID)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
err = authorizationService.CleanNAPWithOverridePolicies(dataStore, endpoint, endpointGroup)
|
||||||
|
if err != nil {
|
||||||
|
failedEndpointGroupIDs = append(failedEndpointGroupIDs, endpointGroupID)
|
||||||
|
log.Error().Err(err).Msgf("Error cleaning NAP with override policies for endpoint %d and endpoint group %d", endpoint.ID, endpointGroup.ID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
endpoint.PendingActions.CleanNAPWithOverridePolicies.EndpointGroups = failedEndpointGroupIDs
|
||||||
|
err := dataStore.Endpoint().UpdateEndpoint(endpoint.ID, endpoint)
|
||||||
|
if err != nil {
|
||||||
|
log.Error().Err(err).Msgf("While running pending actions, error updating endpoint %d", endpoint.ID)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -9,12 +9,12 @@ import (
|
||||||
// Service represents a service used to
|
// Service represents a service used to
|
||||||
// update authorizations associated to a user or team.
|
// update authorizations associated to a user or team.
|
||||||
type Service struct {
|
type Service struct {
|
||||||
dataStore dataservices.DataStore
|
dataStore dataservices.DataStoreTx
|
||||||
K8sClientFactory *cli.ClientFactory
|
K8sClientFactory *cli.ClientFactory
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewService returns a point to a new Service instance.
|
// NewService returns a point to a new Service instance.
|
||||||
func NewService(dataStore dataservices.DataStore) *Service {
|
func NewService(dataStore dataservices.DataStoreTx) *Service {
|
||||||
return &Service{
|
return &Service{
|
||||||
dataStore: dataStore,
|
dataStore: dataStore,
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,8 @@ import (
|
||||||
"github.com/portainer/portainer/api/agent"
|
"github.com/portainer/portainer/api/agent"
|
||||||
"github.com/portainer/portainer/api/crypto"
|
"github.com/portainer/portainer/api/crypto"
|
||||||
"github.com/portainer/portainer/api/dataservices"
|
"github.com/portainer/portainer/api/dataservices"
|
||||||
|
"github.com/portainer/portainer/api/http/utils"
|
||||||
|
"github.com/portainer/portainer/api/internal/authorization"
|
||||||
"github.com/portainer/portainer/api/internal/endpointutils"
|
"github.com/portainer/portainer/api/internal/endpointutils"
|
||||||
"github.com/portainer/portainer/pkg/featureflags"
|
"github.com/portainer/portainer/pkg/featureflags"
|
||||||
|
|
||||||
|
@ -304,6 +306,11 @@ func updateEndpointStatus(tx dataservices.DataStoreTx, endpoint *portainer.Endpo
|
||||||
Str("URL", endpoint.URL).Err(err).
|
Str("URL", endpoint.URL).Err(err).
|
||||||
Msg("background schedule error (environment snapshot), unable to update environment")
|
Msg("background schedule error (environment snapshot), unable to update environment")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Run the pending actions
|
||||||
|
if latestEndpointReference.Status == portainer.EndpointStatusUp {
|
||||||
|
utils.RunPendingActions(latestEndpointReference, tx, authorization.NewService(tx))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FetchDockerID fetches info.Swarm.Cluster.ID if environment(endpoint) is swarm and info.ID otherwise
|
// FetchDockerID fetches info.Swarm.Cluster.ID if environment(endpoint) is swarm and info.ID otherwise
|
||||||
|
|
|
@ -373,6 +373,12 @@ type (
|
||||||
//EdgeStackStatusType represents an edge stack status type
|
//EdgeStackStatusType represents an edge stack status type
|
||||||
EdgeStackStatusType int
|
EdgeStackStatusType int
|
||||||
|
|
||||||
|
EndpointPendingActions struct {
|
||||||
|
CleanNAPWithOverridePolicies struct {
|
||||||
|
EndpointGroups []EndpointGroupID `json:"EndpointGroups"`
|
||||||
|
} `json:"CleanNAPWithOverridePolicies"`
|
||||||
|
}
|
||||||
|
|
||||||
// Environment(Endpoint) represents a Docker environment(endpoint) with all the info required
|
// Environment(Endpoint) represents a Docker environment(endpoint) with all the info required
|
||||||
// to connect to it
|
// to connect to it
|
||||||
Endpoint struct {
|
Endpoint struct {
|
||||||
|
@ -428,6 +434,9 @@ type (
|
||||||
// Whether we need to run any "post init migrations".
|
// Whether we need to run any "post init migrations".
|
||||||
PostInitMigrations EndpointPostInitMigrations `json:"PostInitMigrations"`
|
PostInitMigrations EndpointPostInitMigrations `json:"PostInitMigrations"`
|
||||||
|
|
||||||
|
// Whether we need to run any action when an endpoint is back online.
|
||||||
|
PendingActions *EndpointPendingActions `json:"PendingActions"`
|
||||||
|
|
||||||
Edge EnvironmentEdgeSettings
|
Edge EnvironmentEdgeSettings
|
||||||
|
|
||||||
Agent struct {
|
Agent struct {
|
||||||
|
|
Loading…
Reference in New Issue