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
majimenez-stratio authored Jun 14, 2023
1 parent af018cf commit 700f75c
Show file tree
Hide file tree
Showing 17 changed files with 41 additions and 15 deletions.
2 changes: 2 additions & 0 deletions api/v1alpha1/capsuleconfiguration_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,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
5 changes: 5 additions & 0 deletions api/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Binary file added bin/controller-gen
Binary file not shown.
Binary file added bin/manager
Binary file not shown.
5 changes: 5 additions & 0 deletions charts/capsule/crds/capsuleconfiguration-crd.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ spec:
spec:
description: CapsuleConfigurationSpec defines the Capsule configuration.
properties:
excludeUserGroups:
description: Names of the groups for Capsule users.
items:
type: string
type: array
forceTenantPrefix:
default: false
description: 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.
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 @@ -17,5 +17,9 @@ spec:
userGroups:
{{- range .Values.manager.options.capsuleUserGroups }}
- {{ . }}
{{- end}}
excludeUserGroups:
{{- range .Values.manager.options.capsuleExcludeUserGroups }}
- {{ . }}
{{- end}}
protectedNamespaceRegex: {{ .Values.manager.options.protectedNamespaceRegex | quote }}
2 changes: 2 additions & 0 deletions charts/capsule/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ manager:
forceTenantPrefix: false
# -- Override the Capsule user groups
capsuleUserGroups: ["capsule.clastix.io"]
# -- 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 @@ -32,6 +32,11 @@ spec:
spec:
description: CapsuleConfigurationSpec defines the Capsule configuration.
properties:
excludeUserGroups:
description: Names of the groups for Capsule users.
items:
type: string
type: array
forceTenantPrefix:
default: false
description: 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.
Expand Down
1 change: 0 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ require (
github.com/modern-go/reflect2 v1.0.1 // indirect
github.com/nxadm/tail v1.4.8 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_golang v1.11.0 // indirect
github.com/prometheus/client_model v0.2.0 // indirect
github.com/prometheus/common v0.26.0 // indirect
github.com/prometheus/procfs v0.6.0 // indirect
Expand Down
1 change: 0 additions & 1 deletion go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -695,7 +695,6 @@ golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
Expand Down
4 changes: 4 additions & 0 deletions pkg/configuration/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,10 @@ func (c capsuleConfiguration) UserGroups() []string {
return c.retrievalFn().Spec.UserGroups
}

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

func (c capsuleConfiguration) hasForbiddenNodeLabelsAnnotations() bool {
if _, ok := c.retrievalFn().Annotations[capsulev1alpha1.ForbiddenNodeLabelsAnnotation]; ok {
return true
Expand Down
1 change: 1 addition & 0 deletions pkg/configuration/configuration.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ type Configuration interface {
ValidatingWebhookConfigurationName() string
TenantCRDName() string
UserGroups() []string
ExcludeUserGroups() []string
ForbiddenUserNodeLabels() *capsulev1beta1.ForbiddenListSpec
ForbiddenUserNodeAnnotations() *capsulev1beta1.ForbiddenListSpec
}
4 changes: 2 additions & 2 deletions pkg/webhook/namespace/freezed.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ func (r *freezedHandler) OnDelete(c client.Client, _ *admission.Decoder, recorde

tnt := tntList.Items[0]

if tnt.IsCordoned() && utils.IsCapsuleUser(ctx, req, c, r.configuration.UserGroups()) {
if tnt.IsCordoned() && 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 @@ -101,7 +101,7 @@ func (r *freezedHandler) OnUpdate(c client.Client, decoder *admission.Decoder, r

tnt := tntList.Items[0]

if tnt.IsCordoned() && utils.IsCapsuleUser(ctx, req, c, r.configuration.UserGroups()) {
if tnt.IsCordoned() && 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 @@ -146,7 +146,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.IsCordoned() && utils.IsCapsuleUser(ctx, req, clt, h.configuration.UserGroups()) {
if tnt.IsCordoned() && 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, rec

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, rec

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
13 changes: 7 additions & 6 deletions pkg/webhook/utils/is_capsule_user.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,15 @@ import (
"github.com/clastix/capsule/pkg/utils"
)

func IsCapsuleUser(ctx context.Context, req admission.Request, clt client.Client, userGroups []string) bool {
func IsCapsuleUser(ctx context.Context, req admission.Request, clt client.Client, userGroups []string, excludeUserGroups []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/clastix/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") {
parts := strings.Split(req.UserInfo.Username, ":")
Expand Down

0 comments on commit 700f75c

Please sign in to comment.