Skip to content

Commit

Permalink
BE validation draft with impersonation
Browse files Browse the repository at this point in the history
  • Loading branch information
bastjan committed Jan 9, 2023
1 parent fa0bfa8 commit e0d8f73
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 3 deletions.
26 changes: 26 additions & 0 deletions apiserver/organization/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,14 @@ import (
"fmt"
"strings"

billingv1 "github.com/appuio/control-api/apis/billing/v1"
orgv1 "github.com/appuio/control-api/apis/organization/v1"
controlv1 "github.com/appuio/control-api/apis/v1"
"sigs.k8s.io/controller-runtime/pkg/client"

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apiserver/pkg/endpoints/request"
"k8s.io/apiserver/pkg/registry/rest"
)

Expand Down Expand Up @@ -90,3 +93,26 @@ func newOrganizationMembers(ctx context.Context, organization *orgv1.Organizatio
},
}
}

func (s *organizationStorage) billingEntityValidator(ctx context.Context, organization *orgv1.Organization) error {
if organization.Spec.BillingEntityRef == "" && s.allowEmptyBillingEntity {
return nil
}

user, ok := request.UserFrom(ctx)
if !ok {
return fmt.Errorf("no user in context")
}

var be billingv1.BillingEntity
c, err := s.impersonator.Impersonate(user)
if err != nil {
return fmt.Errorf("failed to impersonate user: %w", err)
}

if err := c.Get(ctx, client.ObjectKey{Name: organization.Name}, &be); err != nil {
return err
}

return nil
}
37 changes: 34 additions & 3 deletions apiserver/organization/organization.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"errors"
"strings"

billingv1 "github.com/appuio/control-api/apis/billing/v1"
orgv1 "github.com/appuio/control-api/apis/organization/v1"
controlv1 "github.com/appuio/control-api/apis/v1"
"github.com/appuio/control-api/apiserver/authwrapper"
Expand All @@ -17,6 +18,7 @@ import (
"k8s.io/apiserver/pkg/endpoints/request"
genericregistry "k8s.io/apiserver/pkg/registry/generic"
"k8s.io/apiserver/pkg/registry/rest"
restclient "k8s.io/client-go/rest"
restbuilder "sigs.k8s.io/apiserver-runtime/pkg/builder/rest"
"sigs.k8s.io/apiserver-runtime/pkg/util/loopback"
"sigs.k8s.io/controller-runtime/pkg/client"
Expand All @@ -29,11 +31,19 @@ import (
// New returns a new storage provider for Organizations
func New(clusterRoles *[]string, usernamePrefix *string) restbuilder.ResourceHandlerProvider {
return func(s *runtime.Scheme, g genericregistry.RESTOptionsGetter) (rest.Storage, error) {
c, err := client.NewWithWatch(loopback.GetLoopbackMasterClientConfig(), client.Options{})
if err != nil {
masterConfig := loopback.GetLoopbackMasterClientConfig()

scheme := runtime.NewScheme()
if err := controlv1.AddToScheme(scheme); err != nil {
return nil, err
}
if err := billingv1.AddToScheme(scheme); err != nil {
return nil, err
}
err = controlv1.AddToScheme(c.Scheme())

c, err := client.NewWithWatch(loopback.GetLoopbackMasterClientConfig(), client.Options{
Scheme: scheme,
})
if err != nil {
return nil, err
}
Expand All @@ -50,6 +60,7 @@ func New(clusterRoles *[]string, usernamePrefix *string) restbuilder.ResourceHan
Client: c,
},
usernamePrefix: *usernamePrefix,
impersonator: impersonator{masterConfig, client.Options{Scheme: scheme}},
}

return authwrapper.NewAuthorizedStorage(stor, metav1.GroupVersionResource{
Expand All @@ -68,6 +79,26 @@ type organizationStorage struct {

rbac roleBindingCreator
clusterRoles []string

impersonator impersonator
}

type impersonator struct {
config *restclient.Config
opts client.Options
}

func (c impersonator) Impersonate(u user.Info) (client.Client, error) {
var conf *restclient.Config
*conf = *c.config

conf.Impersonate = restclient.ImpersonationConfig{
UserName: u.GetName(),
UID: u.GetUID(),
Groups: u.GetGroups(),
Extra: u.GetExtra(),
}
return client.New(conf, c.opts)
}

func (s organizationStorage) New() runtime.Object {
Expand Down

0 comments on commit e0d8f73

Please sign in to comment.