Skip to content

Commit 5c7804e

Browse files
oliverbaehlerprometherion
authored andcommitted
fix: add rolebinding validation against rfc-1123 dns for sa subjects
Signed-off-by: Oliver Bähler <[email protected]>
1 parent c4481f2 commit 5c7804e

File tree

3 files changed

+70
-1
lines changed

3 files changed

+70
-1
lines changed

controllers/tenant/rolebindings.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,9 @@ func (r *Manager) syncAdditionalRoleBinding(tenant *capsulev1beta1.Tenant, ns st
9797
r.Log.Error(err, "Cannot sync Additional RoleBinding")
9898
}
9999
r.Log.Info(fmt.Sprintf("Additional RoleBindings sync result: %s", string(res)), "name", target.Name, "namespace", target.Namespace)
100+
if err != nil {
101+
return
102+
}
100103
}
101104

102105
return nil

main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ func main() {
167167
route.PVC(pvc.Handler()),
168168
route.Service(service.Handler()),
169169
route.NetworkPolicy(utils.InCapsuleGroups(cfg, networkpolicy.Handler())),
170-
route.Tenant(tenant.NameHandler(), tenant.IngressClassRegexHandler(), tenant.StorageClassRegexHandler(), tenant.ContainerRegistryRegexHandler(), tenant.HostnameRegexHandler(), tenant.FreezedEmitter(), tenant.ServiceAccountNameHandler()),
170+
route.Tenant(tenant.NameHandler(), tenant.RoleBindingRegexHandler(), tenant.IngressClassRegexHandler(), tenant.StorageClassRegexHandler(), tenant.ContainerRegistryRegexHandler(), tenant.HostnameRegexHandler(), tenant.FreezedEmitter(), tenant.ServiceAccountNameHandler()),
171171
route.OwnerReference(utils.InCapsuleGroups(cfg, ownerreference.Handler(cfg))),
172172
route.Cordoning(tenant.CordoningHandler(cfg)),
173173
route.Node(utils.InCapsuleGroups(cfg, node.UserMetadataHandler(cfg, kubeVersion))),
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
// Copyright 2020-2021 Clastix Labs
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package tenant
5+
6+
import (
7+
"context"
8+
"fmt"
9+
"strings"
10+
11+
rbacv1 "k8s.io/api/rbac/v1"
12+
"k8s.io/apimachinery/pkg/util/validation"
13+
"k8s.io/client-go/tools/record"
14+
"sigs.k8s.io/controller-runtime/pkg/client"
15+
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
16+
17+
capsulev1beta1 "github.com/clastix/capsule/api/v1beta1"
18+
capsulewebhook "github.com/clastix/capsule/pkg/webhook"
19+
"github.com/clastix/capsule/pkg/webhook/utils"
20+
)
21+
22+
type rbRegexHandler struct {
23+
}
24+
25+
func RoleBindingRegexHandler() capsulewebhook.Handler {
26+
return &rbRegexHandler{}
27+
}
28+
29+
func (h *rbRegexHandler) validate(req admission.Request, decoder *admission.Decoder) *admission.Response {
30+
tenant := &capsulev1beta1.Tenant{}
31+
if err := decoder.Decode(req, tenant); err != nil {
32+
return utils.ErroredResponse(err)
33+
}
34+
35+
if len(tenant.Spec.AdditionalRoleBindings) > 0 {
36+
for _, binding := range tenant.Spec.AdditionalRoleBindings {
37+
for _, subject := range binding.Subjects {
38+
if subject.Kind == rbacv1.ServiceAccountKind {
39+
err := validation.IsDNS1123Subdomain(subject.Name)
40+
if len(err) > 0 {
41+
response := admission.Denied(fmt.Sprintf("Subject Name '%v' for binding '%v' is invalid. %v", subject.Name, binding.ClusterRoleName, strings.Join(err, ", ")))
42+
return &response
43+
}
44+
}
45+
}
46+
}
47+
}
48+
return nil
49+
}
50+
func (h *rbRegexHandler) OnCreate(_ client.Client, decoder *admission.Decoder, _ record.EventRecorder) capsulewebhook.Func {
51+
return func(_ context.Context, req admission.Request) *admission.Response {
52+
return h.validate(req, decoder)
53+
}
54+
}
55+
56+
func (h *rbRegexHandler) OnDelete(client.Client, *admission.Decoder, record.EventRecorder) capsulewebhook.Func {
57+
return func(context.Context, admission.Request) *admission.Response {
58+
return nil
59+
}
60+
}
61+
62+
func (h *rbRegexHandler) OnUpdate(_ client.Client, decoder *admission.Decoder, _ record.EventRecorder) capsulewebhook.Func {
63+
return func(_ context.Context, req admission.Request) *admission.Response {
64+
return h.validate(req, decoder)
65+
}
66+
}

0 commit comments

Comments
 (0)