Skip to content

Commit

Permalink
Capsule user should be treated as a tenant owner (#19)
Browse files Browse the repository at this point in the history
  • Loading branch information
unai-ttxu committed Nov 22, 2024
1 parent ae0f38c commit 0046dc6
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 13 deletions.
4 changes: 4 additions & 0 deletions charts/capsule/templates/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,10 @@ spec:
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: SERVICE_ACCOUNT_NAME
valueFrom:
fieldRef:
fieldPath: spec.serviceAccountName
ports:
- name: webhook-server
containerPort: {{ .Values.manager.webhookPort }}
Expand Down
14 changes: 11 additions & 3 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"fmt"
"os"
goRuntime "runtime"
"strings"

flag "github.com/spf13/pflag"
_ "go.uber.org/automaxprocs"
Expand Down Expand Up @@ -81,7 +82,7 @@ func printVersion() {
func main() {
var enableLeaderElection, version bool

var metricsAddr, namespace, configurationName string
var metricsAddr, namespace, serviceAccountName, capsuleUserName, configurationName string

var webhookPort int

Expand Down Expand Up @@ -118,6 +119,13 @@ func main() {
os.Exit(1)
}

if serviceAccountName = os.Getenv("SERVICE_ACCOUNT_NAME"); len(serviceAccountName) == 0 {
setupLog.Error(fmt.Errorf("unable to determinate the Namespace Capsule is running on"), "unable to start manager")
os.Exit(1)
}

capsuleUserName = strings.Join([]string{"system:serviceaccount", namespace, serviceAccountName}, ":")

if len(configurationName) == 0 {
setupLog.Error(fmt.Errorf("missing CapsuleConfiguration resource name"), "unable to start manager")
os.Exit(1)
Expand Down Expand Up @@ -220,14 +228,14 @@ func main() {
webhooksList := append(
make([]webhook.Webhook, 0),
route.Pod(pod.ImagePullPolicy(), pod.ContainerRegistry(), pod.PriorityClass(), pod.RuntimeClass()),
route.Namespace(utils.InCapsuleGroups(cfg, namespacewebhook.PatchHandler(), namespacewebhook.QuotaHandler(), namespacewebhook.FreezeHandler(cfg), namespacewebhook.PrefixHandler(cfg), namespacewebhook.UserMetadataHandler())),
route.Namespace(utils.InCapsuleGroups(cfg, namespacewebhook.PatchHandler(capsuleUserName), namespacewebhook.QuotaHandler(), namespacewebhook.FreezeHandler(cfg), namespacewebhook.PrefixHandler(cfg), namespacewebhook.UserMetadataHandler())),
route.Ingress(ingress.Class(cfg, kubeVersion), ingress.Hostnames(cfg), ingress.Collision(cfg), ingress.Wildcard()),
route.PVC(pvc.Validating(), pvc.PersistentVolumeReuse()),
route.Service(service.Handler()),
route.TenantResourceObjects(utils.InCapsuleGroups(cfg, tntresource.WriteOpsHandler())),
route.NetworkPolicy(utils.InCapsuleGroups(cfg, networkpolicy.Handler())),
route.Tenant(tenant.NameHandler(), tenant.RoleBindingRegexHandler(), tenant.IngressClassRegexHandler(), tenant.StorageClassRegexHandler(), tenant.ContainerRegistryRegexHandler(), tenant.HostnameRegexHandler(), tenant.FreezedEmitter(), tenant.ServiceAccountNameHandler(), tenant.ForbiddenAnnotationsRegexHandler(), tenant.ProtectedHandler(), tenant.MetaHandler()),
route.OwnerReference(utils.InCapsuleGroups(cfg, ownerreference.Handler(cfg))),
route.OwnerReference(utils.InCapsuleGroups(cfg, ownerreference.Handler(cfg,capsuleUserName))),
route.Cordoning(tenant.CordoningHandler(cfg), tenant.ResourceCounterHandler(manager.GetClient())),
route.Node(utils.InCapsuleGroups(cfg, node.UserMetadataHandler(cfg, kubeVersion))),
route.Defaults(defaults.Handler(cfg, kubeVersion)),
Expand Down
12 changes: 8 additions & 4 deletions pkg/webhook/namespace/patch.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,14 @@ import (
"github.com/projectcapsule/capsule/pkg/webhook/utils"
)

type patchHandler struct{}
type patchHandler struct{
capsuleUserName string
}

func PatchHandler() capsulewebhook.Handler {
return &patchHandler{}
func PatchHandler(capsuleUserName string) capsulewebhook.Handler {
return &patchHandler{
capsuleUserName: capsuleUserName,
}
}

func (r *patchHandler) OnCreate(client.Client, admission.Decoder, record.EventRecorder) capsulewebhook.Func {
Expand Down Expand Up @@ -66,7 +70,7 @@ func (r *patchHandler) OnUpdate(c client.Client, decoder admission.Decoder, reco
return &response
}

if !utils.IsTenantOwner(tnt.Spec.Owners, req.UserInfo) {
if !utils.IsTenantOwner(tnt.Spec.Owners, req.UserInfo, r.capsuleUserName) {
recorder.Eventf(tnt, corev1.EventTypeWarning, "NamespacePatch", e)
response := admission.Denied(e)

Expand Down
12 changes: 7 additions & 5 deletions pkg/webhook/ownerreference/patching.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,14 @@ import (
)

type handler struct {
cfg configuration.Configuration
cfg configuration.Configuration
capsuleUserName string
}

func Handler(cfg configuration.Configuration) capsulewebhook.Handler {
func Handler(cfg configuration.Configuration, capsuleUserName string) capsulewebhook.Handler {
return &handler{
cfg: cfg,
cfg: cfg,
capsuleUserName: capsuleUserName,
}
}

Expand Down Expand Up @@ -120,7 +122,7 @@ func (h *handler) namespaceIsOwned(ns *corev1.Namespace, tenantList *capsulev1be
continue
}

if ownerRef.UID == tenant.UID && utils.IsTenantOwner(tenant.Spec.Owners, req.UserInfo) {
if ownerRef.UID == tenant.UID && utils.IsTenantOwner(tenant.Spec.Owners, req.UserInfo, h.capsuleUserName) {
return true
}
}
Expand Down Expand Up @@ -153,7 +155,7 @@ func (h *handler) setOwnerRef(ctx context.Context, req admission.Request, client
return &response
}
// Tenant owner must adhere to user that asked for NS creation
if !utils.IsTenantOwner(tnt.Spec.Owners, req.UserInfo) {
if !utils.IsTenantOwner(tnt.Spec.Owners, req.UserInfo, h.capsuleUserName) {
recorder.Eventf(tnt, corev1.EventTypeWarning, "NonOwnedTenant", "Namespace %s cannot be assigned to the current Tenant", ns.GetName())

response := admission.Denied("Cannot assign the desired namespace to a non-owned Tenant")
Expand Down
5 changes: 4 additions & 1 deletion pkg/webhook/utils/is_tenant_owner.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ import (
capsulev1beta2 "github.com/projectcapsule/capsule/api/v1beta2"
)

func IsTenantOwner(owners capsulev1beta2.OwnerListSpec, userInfo authenticationv1.UserInfo) bool {
func IsTenantOwner(owners capsulev1beta2.OwnerListSpec, userInfo authenticationv1.UserInfo, capsuleUserName string) bool {
if userInfo.Username == capsuleUserName {
return true
}
for _, owner := range owners {
switch owner.Kind {
case capsulev1beta2.UserOwner, capsulev1beta2.ServiceAccountOwner:
Expand Down

0 comments on commit 0046dc6

Please sign in to comment.