From a732dfaf857e9a4e1172d084bf499dc2fe2207fc Mon Sep 17 00:00:00 2001 From: fabiankramm Date: Thu, 10 Sep 2020 11:38:51 +0200 Subject: [PATCH] improvement: wait after space creation for user access --- pkg/apiserver/registry/space/rest.go | 53 +++++++++++++++++++++------- 1 file changed, 40 insertions(+), 13 deletions(-) diff --git a/pkg/apiserver/registry/space/rest.go b/pkg/apiserver/registry/space/rest.go index aae9bb2b..9cf68f6b 100644 --- a/pkg/apiserver/registry/space/rest.go +++ b/pkg/apiserver/registry/space/rest.go @@ -35,11 +35,13 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/wait" + "k8s.io/apiserver/pkg/authentication/user" authorizer "k8s.io/apiserver/pkg/authorization/authorizer" "k8s.io/apiserver/pkg/endpoints/filters" "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/rest" "k8s.io/client-go/util/retry" + "k8s.io/klog" "sigs.k8s.io/controller-runtime/pkg/client" "time" ) @@ -197,15 +199,15 @@ func (r *spaceStorage) Create(ctx context.Context, obj runtime.Object, createVal return nil, err } + // check if user can create namespaces + a, err := filters.GetAuthorizerAttributes(ctx) + if err != nil { + return nil, err + } + // Check if user can access account and create space var account *configv1alpha1.Account if space.Spec.Account == "" { - // check if user can create namespaces - a, err := filters.GetAuthorizerAttributes(ctx) - if err != nil { - return nil, err - } - decision, _, err := r.authorizer.Authorize(ctx, util.ChangeAttributesResource(a, corev1.SchemeGroupVersion.WithResource("namespaces"), space.Name)) if err != nil { return nil, err @@ -221,12 +223,6 @@ func (r *spaceStorage) Create(ctx context.Context, obj runtime.Object, createVal // check if user is part of account if util.IsUserPartOfAccount(userInfo, account) == false { - // check if user can create namespaces - a, err := filters.GetAuthorizerAttributes(ctx) - if err != nil { - return nil, err - } - decision, _, err := r.authorizer.Authorize(ctx, util.ChangeAttributesResource(a, corev1.SchemeGroupVersion.WithResource("namespaces"), space.Name)) if err != nil { return nil, err @@ -283,7 +279,7 @@ func (r *spaceStorage) Create(ctx context.Context, obj runtime.Object, createVal // Create the default space templates and role binding err = r.initializeSpace(ctx, namespace, account) if err != nil { - r.client.Delete(ctx, namespace) + _ = r.client.Delete(ctx, namespace) return nil, err } } else { @@ -295,9 +291,40 @@ func (r *spaceStorage) Create(ctx context.Context, obj runtime.Object, createVal } } + err = r.waitForAccess(ctx, a.GetUser(), namespace) + if err != nil { + // if this happens it is kind of weird, but its not a reason to return an error and abort the request + klog.Infof("error waiting for access to namespace %s for user %s: %v", namespace.Name, a.GetUser().GetName(), err) + } + return ConvertNamespace(namespace), nil } +func (r *spaceStorage) waitForAccess(ctx context.Context, user user.Info, namespace *corev1.Namespace) error { + a := &authorizer.AttributesRecord{ + User: user, + Verb: "get", + Namespace: namespace.Name, + APIGroup: corev1.SchemeGroupVersion.Group, + APIVersion: corev1.SchemeGroupVersion.Version, + Resource: "namespaces", + Name: namespace.Name, + ResourceRequest: true, + } + + // here we wait until the authorizer tells us that the account can get the space + backoff := retry.DefaultBackoff + backoff.Steps = 8 + return wait.ExponentialBackoff(backoff, func() (bool, error) { + decision, _, err := r.authorizer.Authorize(ctx, a) + if err != nil { + return false, err + } + + return decision == authorizer.DecisionAllow, nil + }) +} + func (r *spaceStorage) initializeSpace(ctx context.Context, namespace *corev1.Namespace, account *configv1alpha1.Account) error { // Create template instances templateInstances := []*configv1alpha1.TemplateInstance{}