roles and role bindings delete and isSystem

pull/12297/head
testA113 2024-10-05 15:17:09 +13:00
parent 9ddebf91f2
commit 61bea1b06d
13 changed files with 268 additions and 17 deletions

View File

@ -18,7 +18,7 @@ import (
// @security ApiKeyAuth || jwt // @security ApiKeyAuth || jwt
// @produce json // @produce json
// @param id path int true "Environment identifier" // @param id path int true "Environment identifier"
// @success 200 {array} models.K8sClusterRoleBinding "Success" // @success 200 {array} kubernetes.K8sClusterRoleBinding "Success"
// @failure 400 "Invalid request payload, such as missing required fields or fields not meeting validation criteria." // @failure 400 "Invalid request payload, such as missing required fields or fields not meeting validation criteria."
// @failure 401 "Unauthorized access - the user is not authenticated or does not have the necessary permissions. Ensure that you have provided a valid API key or JWT token, and that you have the required permissions." // @failure 401 "Unauthorized access - the user is not authenticated or does not have the necessary permissions. Ensure that you have provided a valid API key or JWT token, and that you have the required permissions."
// @failure 403 "Permission denied - the user is authenticated but does not have the necessary permissions to access the requested resource or perform the specified operation. Check your user roles and permissions." // @failure 403 "Permission denied - the user is authenticated but does not have the necessary permissions to access the requested resource or perform the specified operation. Check your user roles and permissions."
@ -55,7 +55,7 @@ func (handler *Handler) getAllKubernetesClusterRoleBindings(w http.ResponseWrite
// @security jwt // @security jwt
// @produce text/plain // @produce text/plain
// @param id path int true "Environment(Endpoint) identifier" // @param id path int true "Environment(Endpoint) identifier"
// @param payload body models.K8sClusterRoleBindingDeleteRequests true "Cluster role bindings to delete" // @param payload body kubernetes.K8sClusterRoleBindingDeleteRequests true "Cluster role bindings to delete"
// @success 200 "Success" // @success 200 "Success"
// @failure 500 "Server error" // @failure 500 "Server error"
// @router /kubernetes/{id}/cluster_role_bindings/delete [POST] // @router /kubernetes/{id}/cluster_role_bindings/delete [POST]

View File

@ -55,7 +55,7 @@ func (handler *Handler) getAllKubernetesClusterRoles(w http.ResponseWriter, r *h
// @security jwt // @security jwt
// @produce text/plain // @produce text/plain
// @param id path int true "Environment(Endpoint) identifier" // @param id path int true "Environment(Endpoint) identifier"
// @param payload body models.K8sClusterRoleDeleteRequests true "Cluster roles to delete" // @param payload body kubernetes.K8sClusterRoleDeleteRequests true "Cluster roles to delete"
// @success 200 "Success" // @success 200 "Success"
// @failure 500 "Server error" // @failure 500 "Server error"
// @router /kubernetes/{id}/cluster_roles/delete [POST] // @router /kubernetes/{id}/cluster_roles/delete [POST]

View File

@ -74,16 +74,12 @@ func NewHandler(bouncer security.BouncerService, authorizationService *authoriza
endpointRouter.Handle("/ingresses/delete", httperror.LoggerHandler(h.deleteKubernetesIngresses)).Methods(http.MethodPost) endpointRouter.Handle("/ingresses/delete", httperror.LoggerHandler(h.deleteKubernetesIngresses)).Methods(http.MethodPost)
endpointRouter.Handle("/ingresses", httperror.LoggerHandler(h.GetAllKubernetesClusterIngresses)).Methods(http.MethodGet) endpointRouter.Handle("/ingresses", httperror.LoggerHandler(h.GetAllKubernetesClusterIngresses)).Methods(http.MethodGet)
endpointRouter.Handle("/ingresses/count", httperror.LoggerHandler(h.getAllKubernetesClusterIngressesCount)).Methods(http.MethodGet) endpointRouter.Handle("/ingresses/count", httperror.LoggerHandler(h.getAllKubernetesClusterIngressesCount)).Methods(http.MethodGet)
endpointRouter.Handle("/service_accounts", httperror.LoggerHandler(h.getAllKubernetesServiceAccounts)).Methods(http.MethodGet)
endpointRouter.Handle("/services", httperror.LoggerHandler(h.GetAllKubernetesServices)).Methods(http.MethodGet) endpointRouter.Handle("/services", httperror.LoggerHandler(h.GetAllKubernetesServices)).Methods(http.MethodGet)
endpointRouter.Handle("/services/count", httperror.LoggerHandler(h.getAllKubernetesServicesCount)).Methods(http.MethodGet) endpointRouter.Handle("/services/count", httperror.LoggerHandler(h.getAllKubernetesServicesCount)).Methods(http.MethodGet)
endpointRouter.Handle("/secrets", httperror.LoggerHandler(h.GetAllKubernetesSecrets)).Methods(http.MethodGet) endpointRouter.Handle("/secrets", httperror.LoggerHandler(h.GetAllKubernetesSecrets)).Methods(http.MethodGet)
endpointRouter.Handle("/secrets/count", httperror.LoggerHandler(h.getAllKubernetesSecretsCount)).Methods(http.MethodGet) endpointRouter.Handle("/secrets/count", httperror.LoggerHandler(h.getAllKubernetesSecretsCount)).Methods(http.MethodGet)
endpointRouter.Handle("/services/delete", httperror.LoggerHandler(h.deleteKubernetesServices)).Methods(http.MethodPost) endpointRouter.Handle("/services/delete", httperror.LoggerHandler(h.deleteKubernetesServices)).Methods(http.MethodPost)
endpointRouter.Handle("/service_accounts/delete", httperror.LoggerHandler(h.deleteKubernetesServiceAccounts)).Methods(http.MethodPost)
endpointRouter.Handle("/rbac_enabled", httperror.LoggerHandler(h.getKubernetesRBACStatus)).Methods(http.MethodGet) endpointRouter.Handle("/rbac_enabled", httperror.LoggerHandler(h.getKubernetesRBACStatus)).Methods(http.MethodGet)
endpointRouter.Handle("/roles", httperror.LoggerHandler(h.getAllKubernetesRoles)).Methods(http.MethodGet)
endpointRouter.Handle("/role_bindings", httperror.LoggerHandler(h.getAllKubernetesRoleBindings)).Methods(http.MethodGet)
endpointRouter.Handle("/namespaces", httperror.LoggerHandler(h.createKubernetesNamespace)).Methods(http.MethodPost) endpointRouter.Handle("/namespaces", httperror.LoggerHandler(h.createKubernetesNamespace)).Methods(http.MethodPost)
endpointRouter.Handle("/namespaces", httperror.LoggerHandler(h.updateKubernetesNamespace)).Methods(http.MethodPut) endpointRouter.Handle("/namespaces", httperror.LoggerHandler(h.updateKubernetesNamespace)).Methods(http.MethodPut)
endpointRouter.Handle("/namespaces", httperror.LoggerHandler(h.deleteKubernetesNamespace)).Methods(http.MethodDelete) endpointRouter.Handle("/namespaces", httperror.LoggerHandler(h.deleteKubernetesNamespace)).Methods(http.MethodDelete)
@ -92,6 +88,16 @@ func NewHandler(bouncer security.BouncerService, authorizationService *authoriza
endpointRouter.Handle("/namespaces/{namespace}", httperror.LoggerHandler(h.getKubernetesNamespace)).Methods(http.MethodGet) endpointRouter.Handle("/namespaces/{namespace}", httperror.LoggerHandler(h.getKubernetesNamespace)).Methods(http.MethodGet)
endpointRouter.Handle("/volumes", httperror.LoggerHandler(h.GetAllKubernetesVolumes)).Methods(http.MethodGet) endpointRouter.Handle("/volumes", httperror.LoggerHandler(h.GetAllKubernetesVolumes)).Methods(http.MethodGet)
endpointRouter.Handle("/volumes/count", httperror.LoggerHandler(h.getAllKubernetesVolumesCount)).Methods(http.MethodGet) endpointRouter.Handle("/volumes/count", httperror.LoggerHandler(h.getAllKubernetesVolumesCount)).Methods(http.MethodGet)
endpointRouter.Handle("/service_accounts", httperror.LoggerHandler(h.getAllKubernetesServiceAccounts)).Methods(http.MethodGet)
endpointRouter.Handle("/service_accounts/delete", httperror.LoggerHandler(h.deleteKubernetesServiceAccounts)).Methods(http.MethodPost)
endpointRouter.Handle("/roles", httperror.LoggerHandler(h.getAllKubernetesRoles)).Methods(http.MethodGet)
endpointRouter.Handle("/roles/delete", httperror.LoggerHandler(h.deleteRoles)).Methods(http.MethodPost)
endpointRouter.Handle("/role_bindings", httperror.LoggerHandler(h.getAllKubernetesRoleBindings)).Methods(http.MethodGet)
endpointRouter.Handle("/role_bindings/delete", httperror.LoggerHandler(h.deleteRoleBindings)).Methods(http.MethodPost)
endpointRouter.Handle("/cluster_roles", httperror.LoggerHandler(h.getAllKubernetesClusterRoles)).Methods(http.MethodGet)
endpointRouter.Handle("/cluster_roles/delete", httperror.LoggerHandler(h.deleteClusterRoles)).Methods(http.MethodPost)
endpointRouter.Handle("/cluster_role_bindings", httperror.LoggerHandler(h.getAllKubernetesClusterRoleBindings)).Methods(http.MethodGet)
endpointRouter.Handle("/cluster_role_bindings/delete", httperror.LoggerHandler(h.deleteClusterRoleBindings)).Methods(http.MethodPost)
// namespaces // namespaces
// in the future this piece of code might be in another package (or a few different packages - namespaces/namespace?) // in the future this piece of code might be in another package (or a few different packages - namespaces/namespace?)

View File

@ -3,7 +3,9 @@ package kubernetes
import ( import (
"net/http" "net/http"
models "github.com/portainer/portainer/api/http/models/kubernetes"
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/response" "github.com/portainer/portainer/pkg/libhttp/response"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
) )
@ -38,3 +40,35 @@ func (handler *Handler) getAllKubernetesRoleBindings(w http.ResponseWriter, r *h
return response.JSON(w, rolebindings) return response.JSON(w, rolebindings)
} }
// @id DeleteRoleBindings
// @summary Delete the provided role bindings
// @description Delete the provided role bindings for the given Kubernetes environment
// @description **Access policy**: administrator
// @tags rbac_enabled
// @security ApiKeyAuth
// @security jwt
// @produce text/plain
// @param id path int true "Environment(Endpoint) identifier"
// @param payload body models.K8sRoleDeleteRequests true "Role bindings to delete"
// @success 200 "Success"
// @failure 500 "Server error"
// @router /kubernetes/{id}/role_bindings/delete [POST]
func (h *Handler) deleteRoleBindings(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
var payload models.K8sRoleBindingDeleteRequests
if err := request.DecodeAndValidateJSONPayload(r, &payload); err != nil {
return httperror.BadRequest("Invalid request payload", err)
}
cli, handlerErr := h.getProxyKubeClient(r)
if handlerErr != nil {
return handlerErr
}
if err := cli.DeleteRoleBindings(payload); err != nil {
return httperror.InternalServerError("Failed to delete role bindings", err)
}
return nil
}

View File

@ -3,7 +3,9 @@ package kubernetes
import ( import (
"net/http" "net/http"
models "github.com/portainer/portainer/api/http/models/kubernetes"
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/response" "github.com/portainer/portainer/pkg/libhttp/response"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
) )
@ -38,3 +40,36 @@ func (handler *Handler) getAllKubernetesRoles(w http.ResponseWriter, r *http.Req
return response.JSON(w, roles) return response.JSON(w, roles)
} }
// @id DeleteRoles
// @summary Delete the provided roles
// @description Delete the provided roles for the given Kubernetes environment
// @description **Access policy**: administrator
// @tags rbac_enabled
// @security ApiKeyAuth
// @security jwt
// @produce text/plain
// @param id path int true "Environment(Endpoint) identifier"
// @param payload body kubernetes.K8sRoleDeleteRequests true "Roles to delete "
// @success 200 "Success"
// @failure 500 "Server error"
// @router /kubernetes/{id}/roles/delete [POST]
func (h *Handler) deleteRoles(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
var payload models.K8sRoleDeleteRequests
err := request.DecodeAndValidateJSONPayload(r, &payload)
if err != nil {
return httperror.BadRequest("Invalid request payload", err)
}
cli, handlerErr := h.getProxyKubeClient(r)
if handlerErr != nil {
return handlerErr
}
err = cli.DeleteRoles(payload)
if err != nil {
return httperror.InternalServerError("Failed to delete roles", err)
}
return nil
}

View File

@ -50,7 +50,7 @@ func (handler *Handler) getAllKubernetesServiceAccounts(w http.ResponseWriter, r
// @security jwt // @security jwt
// @produce text/plain // @produce text/plain
// @param id path int true "Environment(Endpoint) identifier" // @param id path int true "Environment(Endpoint) identifier"
// @param payload body models.K8sServiceAccountDeleteRequests true "Service accounts to delete " // @param payload body kubernetes.K8sServiceAccountDeleteRequests true "Service accounts to delete "
// @success 200 "Success" // @success 200 "Success"
// @failure 500 "Server error" // @failure 500 "Server error"
// @router /kubernetes/{id}/service_accounts/delete [POST] // @router /kubernetes/{id}/service_accounts/delete [POST]

View File

@ -13,6 +13,7 @@ type (
K8sClusterRoleBinding struct { K8sClusterRoleBinding struct {
Name string `json:"name"` Name string `json:"name"`
UID types.UID `json:"uid"` UID types.UID `json:"uid"`
Namespace string `json:"namespace"`
RoleRef rbacv1.RoleRef `json:"roleRef"` RoleRef rbacv1.RoleRef `json:"roleRef"`
Subjects []rbacv1.Subject `json:"subjects"` Subjects []rbacv1.Subject `json:"subjects"`
CreationDate time.Time `json:"creationDate"` CreationDate time.Time `json:"creationDate"`

View File

@ -1,17 +1,38 @@
package kubernetes package kubernetes
import ( import (
"errors"
"net/http"
"time" "time"
rbacv1 "k8s.io/api/rbac/v1" rbacv1 "k8s.io/api/rbac/v1"
"k8s.io/apimachinery/pkg/types"
) )
type ( type (
K8sRoleBinding struct { K8sRoleBinding struct {
Name string `json:"name"` Name string `json:"name"`
UID types.UID `json:"uid"`
Namespace string `json:"namespace"` Namespace string `json:"namespace"`
RoleRef rbacv1.RoleRef `json:"roleRef"` RoleRef rbacv1.RoleRef `json:"roleRef"`
Subjects []rbacv1.Subject `json:"subjects"` Subjects []rbacv1.Subject `json:"subjects"`
CreationDate time.Time `json:"creationDate"` CreationDate time.Time `json:"creationDate"`
IsSystem bool `json:"isSystem"`
} }
// K8sRoleBindingDeleteRequests is a mapping of namespace names to a slice of role bindings.
K8sRoleBindingDeleteRequests map[string][]string
) )
func (r K8sRoleBindingDeleteRequests) Validate(request *http.Request) error {
if len(r) == 0 {
return errors.New("missing deletion request list in payload")
}
for ns := range r {
if len(ns) == 0 {
return errors.New("deletion given with empty namespace")
}
}
return nil
}

View File

@ -1,9 +1,36 @@
package kubernetes package kubernetes
import "time" import (
"errors"
"net/http"
"time"
type K8sRole struct { "k8s.io/apimachinery/pkg/types"
Name string `json:"name"` )
Namespace string `json:"namespace"`
CreationDate time.Time `json:"creationDate"` type (
K8sRole struct {
Name string `json:"name"`
UID types.UID `json:"uid"`
Namespace string `json:"namespace"`
CreationDate time.Time `json:"creationDate"`
// isSystem is true if prefixed with "system:" or exists in the kube-system namespace
// or is one of the portainer roles
IsSystem bool `json:"isSystem"`
}
// K8sRoleDeleteRequests is a mapping of namespace names to a slice of roles.
K8sRoleDeleteRequests map[string][]string
)
func (r K8sRoleDeleteRequests) Validate(request *http.Request) error {
if len(r) == 0 {
return errors.New("missing deletion request list in payload")
}
for ns := range r {
if len(ns) == 0 {
return errors.New("deletion given with empty namespace")
}
}
return nil
} }

View File

@ -43,6 +43,7 @@ func parseClusterRoleBinding(clusterRoleBinding rbacv1.ClusterRoleBinding) model
return models.K8sClusterRoleBinding{ return models.K8sClusterRoleBinding{
Name: clusterRoleBinding.Name, Name: clusterRoleBinding.Name,
UID: clusterRoleBinding.UID, UID: clusterRoleBinding.UID,
Namespace: clusterRoleBinding.Namespace,
RoleRef: clusterRoleBinding.RoleRef, RoleRef: clusterRoleBinding.RoleRef,
Subjects: clusterRoleBinding.Subjects, Subjects: clusterRoleBinding.Subjects,
CreationDate: clusterRoleBinding.CreationTimestamp.Time, CreationDate: clusterRoleBinding.CreationTimestamp.Time,

View File

@ -2,11 +2,15 @@ package cli
import ( import (
"context" "context"
"strings"
models "github.com/portainer/portainer/api/http/models/kubernetes" models "github.com/portainer/portainer/api/http/models/kubernetes"
"github.com/portainer/portainer/api/internal/errorlist"
"github.com/rs/zerolog/log"
rbacv1 "k8s.io/api/rbac/v1" rbacv1 "k8s.io/api/rbac/v1"
k8serrors "k8s.io/apimachinery/pkg/api/errors" k8serrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
) )
// GetRoles gets all the roles for either at the cluster level or a given namespace in a k8s endpoint. // GetRoles gets all the roles for either at the cluster level or a given namespace in a k8s endpoint.
@ -48,18 +52,20 @@ func (kcl *KubeClient) fetchRoles(namespace string) ([]models.K8sRole, error) {
results := make([]models.K8sRole, 0) results := make([]models.K8sRole, 0)
for _, role := range roles.Items { for _, role := range roles.Items {
results = append(results, parseRole(role)) results = append(results, kcl.parseRole(role))
} }
return results, nil return results, nil
} }
// parseRole converts a rbacv1.Role object to a models.K8sRole object. // parseRole converts a rbacv1.Role object to a models.K8sRole object.
func parseRole(role rbacv1.Role) models.K8sRole { func (kcl *KubeClient) parseRole(role rbacv1.Role) models.K8sRole {
return models.K8sRole{ return models.K8sRole{
Name: role.Name, Name: role.Name,
UID: role.UID,
Namespace: role.Namespace, Namespace: role.Namespace,
CreationDate: role.CreationTimestamp.Time, CreationDate: role.CreationTimestamp.Time,
IsSystem: kcl.isSystemRole(&role),
} }
} }
@ -114,3 +120,42 @@ func getPortainerDefaultK8sRoleNames() []string {
string(portainerUserCRName), string(portainerUserCRName),
} }
} }
func (kcl *KubeClient) isSystemRole(role *rbacv1.Role) bool {
if strings.HasPrefix(role.Name, "system:") {
return true
}
return kcl.isSystemNamespace(role.Namespace)
}
// DeleteRoles processes a K8sServiceDeleteRequest by deleting each role
// in its given namespace.
func (kcl *KubeClient) DeleteRoles(reqs models.K8sRoleDeleteRequests) error {
var errors []error
for namespace := range reqs {
for _, name := range reqs[namespace] {
client := kcl.cli.RbacV1().Roles(namespace)
role, err := client.Get(context.Background(), name, v1.GetOptions{})
if err != nil {
if k8serrors.IsNotFound(err) {
continue
}
// This is a more serious error to do with the client so we return right away
return err
}
if kcl.isSystemRole(role) {
log.Error().Str("role_name", name).Msg("ignoring delete of 'system' role, not allowed")
}
if err := client.Delete(context.TODO(), name, metav1.DeleteOptions{}); err != nil {
errors = append(errors, err)
}
}
}
return errorlist.Combine(errors)
}

View File

@ -2,10 +2,16 @@ package cli
import ( import (
"context" "context"
"strings"
models "github.com/portainer/portainer/api/http/models/kubernetes" models "github.com/portainer/portainer/api/http/models/kubernetes"
"github.com/portainer/portainer/api/internal/errorlist"
"github.com/rs/zerolog/log"
corev1 "k8s.io/api/rbac/v1"
rbacv1 "k8s.io/api/rbac/v1" rbacv1 "k8s.io/api/rbac/v1"
k8serrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
) )
// GetRoleBindings gets all the roleBindings for either at the cluster level or a given namespace in a k8s endpoint. // GetRoleBindings gets all the roleBindings for either at the cluster level or a given namespace in a k8s endpoint.
@ -47,19 +53,82 @@ func (kcl *KubeClient) fetchRoleBindings(namespace string) ([]models.K8sRoleBind
results := make([]models.K8sRoleBinding, 0) results := make([]models.K8sRoleBinding, 0)
for _, roleBinding := range roleBindings.Items { for _, roleBinding := range roleBindings.Items {
results = append(results, parseRoleBinding(roleBinding)) results = append(results, kcl.parseRoleBinding(roleBinding))
} }
return results, nil return results, nil
} }
// parseRoleBinding converts a rbacv1.RoleBinding object to a models.K8sRoleBinding object. // parseRoleBinding converts a rbacv1.RoleBinding object to a models.K8sRoleBinding object.
func parseRoleBinding(roleBinding rbacv1.RoleBinding) models.K8sRoleBinding { func (kcl *KubeClient) parseRoleBinding(roleBinding rbacv1.RoleBinding) models.K8sRoleBinding {
return models.K8sRoleBinding{ return models.K8sRoleBinding{
Name: roleBinding.Name, Name: roleBinding.Name,
UID: roleBinding.UID,
Namespace: roleBinding.Namespace, Namespace: roleBinding.Namespace,
RoleRef: roleBinding.RoleRef, RoleRef: roleBinding.RoleRef,
Subjects: roleBinding.Subjects, Subjects: roleBinding.Subjects,
CreationDate: roleBinding.CreationTimestamp.Time, CreationDate: roleBinding.CreationTimestamp.Time,
IsSystem: kcl.isSystemRoleBinding(&roleBinding),
} }
} }
func (kcl *KubeClient) isSystemRoleBinding(rb *rbacv1.RoleBinding) bool {
if strings.HasPrefix(rb.Name, "system:") {
return true
}
if rb.Labels != nil {
if rb.Labels["kubernetes.io/bootstrapping"] == "rbac-defaults" {
return true
}
}
if rb.RoleRef.Name != "" {
role, err := kcl.getRole(rb.Namespace, rb.RoleRef.Name)
if err != nil {
return false
}
// Linked to a role that is marked a system role
if kcl.isSystemRole(role) {
return true
}
}
return false
}
func (kcl *KubeClient) getRole(namespace, name string) (*corev1.Role, error) {
client := kcl.cli.RbacV1().Roles(namespace)
return client.Get(context.Background(), name, metav1.GetOptions{})
}
// DeleteRoleBindings processes a K8sServiceDeleteRequest by deleting each service
// in its given namespace.
func (kcl *KubeClient) DeleteRoleBindings(reqs models.K8sRoleBindingDeleteRequests) error {
var errors []error
for namespace := range reqs {
for _, name := range reqs[namespace] {
client := kcl.cli.RbacV1().RoleBindings(namespace)
roleBinding, err := client.Get(context.Background(), name, v1.GetOptions{})
if err != nil {
if k8serrors.IsNotFound(err) {
continue
}
// This is a more serious error to do with the client so we return right away
return err
}
if kcl.isSystemRoleBinding(roleBinding) {
log.Error().Str("role_name", name).Msg("ignoring delete of 'system' role binding, not allowed")
}
if err := client.Delete(context.Background(), name, v1.DeleteOptions{}); err != nil {
errors = append(errors, err)
}
}
}
return errorlist.Combine(errors)
}

View File

@ -1498,6 +1498,8 @@ type (
SetupUserServiceAccount(userID int, teamIDs []int, restrictDefaultNamespace bool) error SetupUserServiceAccount(userID int, teamIDs []int, restrictDefaultNamespace bool) error
IsRBACEnabled() (bool, error) IsRBACEnabled() (bool, error)
GetPortainerUserServiceAccount(tokendata *TokenData) (*corev1.ServiceAccount, error) GetPortainerUserServiceAccount(tokendata *TokenData) (*corev1.ServiceAccount, error)
GetServiceAccounts(namespace string) ([]models.K8sServiceAccount, error)
DeleteServiceAccounts(reqs models.K8sServiceAccountDeleteRequests) error
GetServiceAccountBearerToken(userID int) (string, error) GetServiceAccountBearerToken(userID int) (string, error)
CreateUserShellPod(ctx context.Context, serviceAccountName, shellPodImage string) (*KubernetesShellPod, error) CreateUserShellPod(ctx context.Context, serviceAccountName, shellPodImage string) (*KubernetesShellPod, error)
StartExecProcess(token string, useAdminToken bool, namespace, podName, containerName string, command []string, stdin io.Reader, stdout io.Writer, errChan chan error) StartExecProcess(token string, useAdminToken bool, namespace, podName, containerName string, command []string, stdin io.Reader, stdout io.Writer, errChan chan error)
@ -1531,6 +1533,16 @@ type (
CreateRegistrySecret(registry *Registry, namespace string) error CreateRegistrySecret(registry *Registry, namespace string) error
IsRegistrySecret(namespace, secretName string) (bool, error) IsRegistrySecret(namespace, secretName string) (bool, error)
ToggleSystemState(namespace string, isSystem bool) error ToggleSystemState(namespace string, isSystem bool) error
GetClusterRoles() ([]models.K8sClusterRole, error)
DeleteClusterRoles(models.K8sClusterRoleDeleteRequests) error
GetClusterRoleBindings() ([]models.K8sClusterRoleBinding, error)
DeleteClusterRoleBindings(models.K8sClusterRoleBindingDeleteRequests) error
GetRoles(namespace string) ([]models.K8sRole, error)
DeleteRoles(models.K8sRoleDeleteRequests) error
GetRoleBindings(namespace string) ([]models.K8sRoleBinding, error)
DeleteRoleBindings(models.K8sRoleBindingDeleteRequests) error
} }
// KubernetesDeployer represents a service to deploy a manifest inside a Kubernetes environment(endpoint) // KubernetesDeployer represents a service to deploy a manifest inside a Kubernetes environment(endpoint)