Skip to content

Commit

Permalink
Add option to exclude groups from capsule (#26)
Browse files Browse the repository at this point in the history
  • Loading branch information
unai-ttxu committed Nov 22, 2024
1 parent d616812 commit 511d1c5
Show file tree
Hide file tree
Showing 13 changed files with 35 additions and 13 deletions.
2 changes: 2 additions & 0 deletions api/v1beta2/capsuleconfiguration_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ type CapsuleConfigurationSpec struct {
// Names of the groups for Capsule users.
// +kubebuilder:default={capsule.clastix.io}
UserGroups []string `json:"userGroups,omitempty"`
// Names of the groups for Capsule users.
ExcludeUserGroups []string `json:"excludeUserGroups,omitempty"`
// Enforces the Tenant owner, during Namespace creation, to name it using the selected Tenant name as prefix,
// separated by a dash. This is useful to avoid Namespace name collision in a public CaaS environment.
// +kubebuilder:default=false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,11 @@ spec:
items:
type: string
type: array
excludeUserGroups:
description: Names of the groups for Capsule users to exclude.
items:
type: string
type: array
required:
- enableTLSReconciler
type: object
Expand Down
4 changes: 4 additions & 0 deletions charts/capsule/templates/configuration-default.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ spec:
userGroups:
{{- range .Values.manager.options.capsuleUserGroups }}
- {{ . }}
{{- end}}
excludeUserGroups:
{{- range .Values.manager.options.capsuleExcludeUserGroups }}
- {{ . }}
{{- end}}
protectedNamespaceRegex: {{ .Values.manager.options.protectedNamespaceRegex | quote }}
{{- with .Values.manager.options.nodeMetadata }}
Expand Down
2 changes: 2 additions & 0 deletions charts/capsule/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ manager:
forceTenantPrefix: false
# -- Override the Capsule user groups
capsuleUserGroups: ["projectcapsule.dev"]
# -- Override the Capsule exclude user groups
capsuleExcludeUserGroups: []
# -- If specified, disallows creation of namespaces matching the passed regexp
protectedNamespaceRegex: ""
# -- Specifies whether capsule webhooks certificates should be generated by capsule operator
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,11 @@ spec:
items:
type: string
type: array
excludeUserGroups:
description: Names of the groups for Capsule users to exclude.
items:
type: string
type: array
required:
- enableTLSReconciler
type: object
Expand Down
4 changes: 4 additions & 0 deletions pkg/configuration/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,10 @@ func (c *capsuleConfiguration) UserGroups() []string {
return c.retrievalFn().Spec.UserGroups
}

func (c *capsuleConfiguration) ExcludeUserGroups() []string {
return c.retrievalFn().Spec.ExcludeUserGroups
}

func (c *capsuleConfiguration) ForbiddenUserNodeLabels() *capsuleapi.ForbiddenListSpec {
if c.retrievalFn().Spec.NodeMetadata == nil {
return nil
Expand Down
1 change: 1 addition & 0 deletions pkg/configuration/configuration.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ type Configuration interface {
ValidatingWebhookConfigurationName() string
TenantCRDName() string
UserGroups() []string
ExcludeUserGroups() []string
ForbiddenUserNodeLabels() *capsuleapi.ForbiddenListSpec
ForbiddenUserNodeAnnotations() *capsuleapi.ForbiddenListSpec
}
4 changes: 2 additions & 2 deletions pkg/webhook/namespace/freezed.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ func (r *freezedHandler) OnDelete(c client.Client, _ admission.Decoder, recorder

tnt := tntList.Items[0]

if tnt.Spec.Cordoned && utils.IsCapsuleUser(ctx, req, c, r.configuration.UserGroups()) {
if tnt.Spec.Cordoned && utils.IsCapsuleUser(ctx, req, c, r.configuration.UserGroups(), r.configuration.ExcludeUserGroups()) {
recorder.Eventf(&tnt, corev1.EventTypeWarning, "TenantFreezed", "Namespace %s cannot be deleted, the current Tenant is freezed", req.Name)

response := admission.Denied("the selected Tenant is freezed")
Expand Down Expand Up @@ -106,7 +106,7 @@ func (r *freezedHandler) OnUpdate(c client.Client, decoder admission.Decoder, re

tnt := tntList.Items[0]

if tnt.Spec.Cordoned && utils.IsCapsuleUser(ctx, req, c, r.configuration.UserGroups()) {
if tnt.Spec.Cordoned && utils.IsCapsuleUser(ctx, req, c, r.configuration.UserGroups(), r.configuration.ExcludeUserGroups()) {
recorder.Eventf(&tnt, corev1.EventTypeWarning, "TenantFreezed", "Namespace %s cannot be updated, the current Tenant is freezed", ns.GetName())

response := admission.Denied("the selected Tenant is freezed")
Expand Down
1 change: 0 additions & 1 deletion pkg/webhook/ownerreference/patching.go
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,6 @@ func (h *handler) setOwnerRef(ctx context.Context, req admission.Request, client
return &response
}


if h.cfg.ForceTenantPrefix() {
for _, tnt := range tenants {
if strings.HasPrefix(ns.GetName(), fmt.Sprintf("%s-", tnt.GetName())) {
Expand Down
2 changes: 1 addition & 1 deletion pkg/webhook/tenant/cordoning.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ func (h *cordoningHandler) cordonHandler(ctx context.Context, clt client.Client,
}

tnt := tntList.Items[0]
if tnt.Spec.Cordoned && utils.IsCapsuleUser(ctx, req, clt, h.configuration.UserGroups()) {
if tnt.Spec.Cordoned && utils.IsCapsuleUser(ctx, req, clt, h.configuration.UserGroups(), h.configuration.ExcludeUserGroups()) {
recorder.Eventf(&tnt, corev1.EventTypeWarning, "TenantFreezed", "%s %s/%s cannot be %sd, current Tenant is freezed", req.Kind.String(), req.Namespace, req.Name, strings.ToLower(string(req.Operation)))

response := admission.Denied(fmt.Sprintf("tenant %s is freezed: please, reach out to the system administrator", tnt.GetName()))
Expand Down
6 changes: 3 additions & 3 deletions pkg/webhook/utils/in_capsule_groups.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ type handler struct {

func (h *handler) OnCreate(client client.Client, decoder admission.Decoder, recorder record.EventRecorder) webhook.Func {
return func(ctx context.Context, req admission.Request) *admission.Response {
if !IsCapsuleUser(ctx, req, client, h.configuration.UserGroups()) {
if !IsCapsuleUser(ctx, req, client, h.configuration.UserGroups(), h.configuration.ExcludeUserGroups()) {
return nil
}

Expand All @@ -44,7 +44,7 @@ func (h *handler) OnCreate(client client.Client, decoder admission.Decoder, reco

func (h *handler) OnDelete(client client.Client, decoder admission.Decoder, recorder record.EventRecorder) webhook.Func {
return func(ctx context.Context, req admission.Request) *admission.Response {
if !IsCapsuleUser(ctx, req, client, h.configuration.UserGroups()) {
if !IsCapsuleUser(ctx, req, client, h.configuration.UserGroups(), h.configuration.ExcludeUserGroups()) {
return nil
}

Expand All @@ -60,7 +60,7 @@ func (h *handler) OnDelete(client client.Client, decoder admission.Decoder, reco

func (h *handler) OnUpdate(client client.Client, decoder admission.Decoder, recorder record.EventRecorder) webhook.Func {
return func(ctx context.Context, req admission.Request) *admission.Response {
if !IsCapsuleUser(ctx, req, client, h.configuration.UserGroups()) {
if !IsCapsuleUser(ctx, req, client, h.configuration.UserGroups(), h.configuration.ExcludeUserGroups()) {
return nil
}

Expand Down
10 changes: 5 additions & 5 deletions pkg/webhook/utils/is_capsule_user.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ import (

func IsCapsuleUser(ctx context.Context, req admission.Request, clt client.Client, userGroups []string) bool {
groupList := utils.NewUserGroupList(req.UserInfo.Groups)
// if the user is a ServiceAccount belonging to the kube-system namespace, definitely, it's not a Capsule user
// and we can skip the check in case of Capsule user group assigned to system:authenticated
// (ref: https://github.com/projectcapsule/capsule/issues/234)
if groupList.Find("system:serviceaccounts:kube-system") {
return false

for _, group := range excludeUserGroups {
if groupList.Find(group) {
return false
}
}
//nolint:nestif
if sets.NewString(req.UserInfo.Groups...).Has("system:serviceaccounts") {
Expand Down
2 changes: 1 addition & 1 deletion pkg/webhook/utils/is_tenant_owner.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
capsulev1beta2 "github.com/projectcapsule/capsule/api/v1beta2"
)

func IsTenantOwner(owners capsulev1beta1.OwnerListSpec, userInfo authenticationv1.UserInfo, capsuleUserName string) bool {
func IsTenantOwner(owners capsulev1beta2.OwnerListSpec, userInfo authenticationv1.UserInfo, capsuleUserName string) bool {
if userInfo.Username == capsuleUserName {
return true
}
Expand Down

0 comments on commit 511d1c5

Please sign in to comment.