diff --git a/pkg/application/service/services.go b/pkg/application/service/services.go index 2602dccc..b5799121 100644 --- a/pkg/application/service/services.go +++ b/pkg/application/service/services.go @@ -16,6 +16,7 @@ type InformerService interface { ListSpaceBindings(reqs ...labels.Requirement) ([]toolchainv1alpha1.SpaceBinding, error) GetProxyPluginConfig(name string) (*toolchainv1alpha1.ProxyPlugin, error) GetNSTemplateTier(name string) (*toolchainv1alpha1.NSTemplateTier, error) + ListBannedUsersByEmail(email string) ([]toolchainv1alpha1.BannedUser, error) } type SignupService interface { diff --git a/pkg/informers/informers.go b/pkg/informers/informers.go index 6435788d..887f18d8 100644 --- a/pkg/informers/informers.go +++ b/pkg/informers/informers.go @@ -3,6 +3,7 @@ package informers import ( "fmt" + toolchainv1alpha1 "github.com/codeready-toolchain/api/api/v1alpha1" "github.com/codeready-toolchain/registration-service/pkg/configuration" "github.com/codeready-toolchain/registration-service/pkg/kubeclient/resources" "github.com/codeready-toolchain/registration-service/pkg/log" @@ -23,9 +24,12 @@ type Informer struct { UserSignup cache.GenericLister ProxyPluginConfig cache.GenericLister NSTemplateTier cache.GenericLister + BannedUsers cache.GenericLister } func StartInformer(cfg *rest.Config) (*Informer, chan struct{}, error) { + group := toolchainv1alpha1.GroupVersion.Group + version := toolchainv1alpha1.GroupVersion.Version informer := &Informer{} dynamicClient, err := dynamic.NewForConfig(cfg) @@ -36,40 +40,45 @@ func StartInformer(cfg *rest.Config) (*Informer, chan struct{}, error) { factory := dynamicinformer.NewFilteredDynamicSharedInformerFactory(dynamicClient, 0, configuration.Namespace(), nil) // MasterUserRecords - genericMasterUserRecordInformer := factory.ForResource(schema.GroupVersionResource{Group: "toolchain.dev.openshift.com", Version: "v1alpha1", Resource: resources.MurResourcePlural}) + genericMasterUserRecordInformer := factory.ForResource(schema.GroupVersionResource{Group: group, Version: version, Resource: resources.MurResourcePlural}) informer.Masteruserrecord = genericMasterUserRecordInformer.Lister() masterUserRecordInformer := genericMasterUserRecordInformer.Informer() // Space - genericSpaceInformer := factory.ForResource(schema.GroupVersionResource{Group: "toolchain.dev.openshift.com", Version: "v1alpha1", Resource: resources.SpaceResourcePlural}) + genericSpaceInformer := factory.ForResource(schema.GroupVersionResource{Group: group, Version: version, Resource: resources.SpaceResourcePlural}) informer.Space = genericSpaceInformer.Lister() spaceInformer := genericSpaceInformer.Informer() // SpaceBinding - genericSpaceBindingInformer := factory.ForResource(schema.GroupVersionResource{Group: "toolchain.dev.openshift.com", Version: "v1alpha1", Resource: resources.SpaceBindingResourcePlural}) + genericSpaceBindingInformer := factory.ForResource(schema.GroupVersionResource{Group: group, Version: version, Resource: resources.SpaceBindingResourcePlural}) informer.SpaceBinding = genericSpaceBindingInformer.Lister() spaceBindingInformer := genericSpaceBindingInformer.Informer() // ToolchainStatus - genericToolchainStatusInformer := factory.ForResource(schema.GroupVersionResource{Group: "toolchain.dev.openshift.com", Version: "v1alpha1", Resource: resources.ToolchainStatusPlural}) + genericToolchainStatusInformer := factory.ForResource(schema.GroupVersionResource{Group: group, Version: version, Resource: resources.ToolchainStatusPlural}) informer.ToolchainStatus = genericToolchainStatusInformer.Lister() toolchainstatusInformer := genericToolchainStatusInformer.Informer() // UserSignups - genericUserSignupInformer := factory.ForResource(schema.GroupVersionResource{Group: "toolchain.dev.openshift.com", Version: "v1alpha1", Resource: resources.UserSignupResourcePlural}) + genericUserSignupInformer := factory.ForResource(schema.GroupVersionResource{Group: group, Version: version, Resource: resources.UserSignupResourcePlural}) informer.UserSignup = genericUserSignupInformer.Lister() userSignupInformer := genericUserSignupInformer.Informer() // Proxy plugins - proxyPluginInformer := factory.ForResource(schema.GroupVersionResource{Group: "toolchain.dev.openshift.com", Version: "v1alpha1", Resource: resources.ProxyPluginsPlural}) + proxyPluginInformer := factory.ForResource(schema.GroupVersionResource{Group: group, Version: version, Resource: resources.ProxyPluginsPlural}) informer.ProxyPluginConfig = proxyPluginInformer.Lister() proxyPluginConfigInformer := proxyPluginInformer.Informer() // NSTemplateTier plugins - genericNSTemplateTierInformer := factory.ForResource(schema.GroupVersionResource{Group: "toolchain.dev.openshift.com", Version: "v1alpha1", Resource: resources.NSTemplateTierPlural}) + genericNSTemplateTierInformer := factory.ForResource(schema.GroupVersionResource{Group: group, Version: version, Resource: resources.NSTemplateTierPlural}) informer.NSTemplateTier = genericNSTemplateTierInformer.Lister() nsTemplateTierInformer := genericNSTemplateTierInformer.Informer() + // BannedUsers + genericBannedUsersInformer := factory.ForResource(schema.GroupVersionResource{Group: group, Version: version, Resource: resources.BannedUserResourcePlural}) + informer.BannedUsers = genericBannedUsersInformer.Lister() + bannedUsersInformer := genericBannedUsersInformer.Informer() + stopper := make(chan struct{}) log.Info(nil, "Starting proxy cache informers") @@ -83,6 +92,7 @@ func StartInformer(cfg *rest.Config) (*Informer, chan struct{}, error) { userSignupInformer.HasSynced, proxyPluginConfigInformer.HasSynced, nsTemplateTierInformer.HasSynced, + bannedUsersInformer.HasSynced, ) { err := fmt.Errorf("timed out waiting for caches to sync") log.Error(nil, err, "Failed to create informers") diff --git a/pkg/informers/service/informer_service.go b/pkg/informers/service/informer_service.go index ab1ce673..d0d5e8ae 100644 --- a/pkg/informers/service/informer_service.go +++ b/pkg/informers/service/informer_service.go @@ -9,10 +9,12 @@ import ( "github.com/codeready-toolchain/registration-service/pkg/informers" "github.com/codeready-toolchain/registration-service/pkg/kubeclient/resources" "github.com/codeready-toolchain/registration-service/pkg/log" + "github.com/codeready-toolchain/toolchain-common/pkg/hash" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/selection" ) type Option func(f *ServiceImpl) @@ -145,3 +147,33 @@ func (s *ServiceImpl) GetNSTemplateTier(name string) (*toolchainv1alpha1.NSTempl } return tier, err } + +func (s *ServiceImpl) ListBannedUsersByEmail(email string) ([]toolchainv1alpha1.BannedUser, error) { + hashedEmail := hash.EncodeString(email) + r, err := labels.NewRequirement(toolchainv1alpha1.BannedUserEmailHashLabelKey, selection.Equals, []string{hashedEmail}) + if err != nil { + return nil, err + } + + ls := labels.NewSelector().Add(*r) + objs, err := s.informer.BannedUsers.ByNamespace(configuration.Namespace()).List(ls) + if err != nil { + return nil, err + } + + bb := []toolchainv1alpha1.BannedUser{} + for _, obj := range objs { + unobj := obj.(*unstructured.Unstructured) + bu := &toolchainv1alpha1.BannedUser{} + if err := runtime.DefaultUnstructuredConverter.FromUnstructured(unobj.UnstructuredContent(), bu); err != nil { + log.Errorf(nil, err, "failed to list BannedUsers") + return nil, err + } + + // check in case of hash collision + if bu.Spec.Email == email { + bb = append(bb, *bu) + } + } + return bb, nil +} diff --git a/pkg/informers/service/informer_service_test.go b/pkg/informers/service/informer_service_test.go index 5ab7682e..bbb15b5c 100644 --- a/pkg/informers/service/informer_service_test.go +++ b/pkg/informers/service/informer_service_test.go @@ -6,15 +6,18 @@ import ( toolchainv1alpha1 "github.com/codeready-toolchain/api/api/v1alpha1" appservice "github.com/codeready-toolchain/registration-service/pkg/application/service" + "github.com/codeready-toolchain/registration-service/pkg/configuration" "github.com/codeready-toolchain/registration-service/pkg/informers" "github.com/codeready-toolchain/registration-service/pkg/informers/service" "github.com/codeready-toolchain/registration-service/pkg/kubeclient" "github.com/codeready-toolchain/registration-service/test" + "github.com/codeready-toolchain/toolchain-common/pkg/hash" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/stretchr/testify/suite" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime" @@ -386,6 +389,108 @@ func (s *TestInformerServiceSuite) TestInformerService() { }) }) + s.Run("bannedusers", func() { + // given + bb := map[string]toolchainv1alpha1.BannedUser{ + "alice": { + ObjectMeta: metav1.ObjectMeta{ + Name: "alice", + Namespace: configuration.Namespace(), + Labels: map[string]string{ + toolchainv1alpha1.BannedUserEmailHashLabelKey: hash.EncodeString("alice@redhat.com"), + }, + }, + Spec: toolchainv1alpha1.BannedUserSpec{ + Email: "alice@redhat.com", + }, + }, + "bob": { + ObjectMeta: metav1.ObjectMeta{ + Name: "bob", + Namespace: configuration.Namespace(), + Labels: map[string]string{ + toolchainv1alpha1.BannedUserEmailHashLabelKey: hash.EncodeString("bob@redhat.com"), + }, + }, + Spec: toolchainv1alpha1.BannedUserSpec{ + Email: "bob@redhat.com", + }, + }, + "bob-dup": { + ObjectMeta: metav1.ObjectMeta{ + Name: "bob-dup", + Namespace: configuration.Namespace(), + Labels: map[string]string{ + toolchainv1alpha1.BannedUserEmailHashLabelKey: hash.EncodeString("bob@redhat.com"), + }, + }, + Spec: toolchainv1alpha1.BannedUserSpec{ + Email: "bob@redhat.com", + }, + }, + } + + // convert to unstructured.Unstructured for fakeLister + bbu := make(map[string]*unstructured.Unstructured, len(bb)) + for k, b := range bb { + bu, err := runtime.DefaultUnstructuredConverter.ToUnstructured(b.DeepCopy()) + require.NoError(s.T(), err) + bbu[k] = &unstructured.Unstructured{Object: bu} + } + + // setup InformerService with fakeLister + inf := informers.Informer{BannedUsers: fakeLister{objs: bbu}} + svc := service.NewInformerService(fakeInformerServiceContext{ + Svcs: s.Application, + informer: inf, + }) + + s.Run("not found", func() { + // when + rbb, err := svc.ListBannedUsersByEmail("unknown@unknown.com") + + // then + require.NoError(s.T(), err) + require.Empty(s.T(), rbb) + }) + + s.Run("invalid email", func() { + // when + rbb, err := svc.ListBannedUsersByEmail("not-an-email") + + // then + require.NoError(s.T(), err) + require.Empty(s.T(), rbb) + }) + + s.Run("found one", func() { + // given + expected := bb["alice"] + + // when + rbb, err := svc.ListBannedUsersByEmail(expected.Spec.Email) + + // then + require.NotNil(s.T(), rbb) + require.NoError(s.T(), err) + require.Len(s.T(), rbb, 1, "expected 1 result for email %s", expected.Spec.Email) + require.Equal(s.T(), expected, rbb[0]) + }) + + s.Run("found multiple", func() { + // given + expected := []toolchainv1alpha1.BannedUser{bb["bob"], bb["bob-dup"]} + + // when + rbb, err := svc.ListBannedUsersByEmail(expected[0].Spec.Email) + + // then + require.NotNil(s.T(), rbb) + require.NoError(s.T(), err) + require.Len(s.T(), rbb, 2, "expected 2 results for email %s", expected[0].Spec.Email) + require.Equal(s.T(), expected, rbb) + }) + }) } type fakeInformerServiceContext struct { @@ -410,8 +515,15 @@ type fakeLister struct { } // List will return all objects across namespaces -func (l fakeLister) List(_ labels.Selector) (ret []runtime.Object, err error) { - return nil, nil +func (l fakeLister) List(ls labels.Selector) (ret []runtime.Object, err error) { + objs := []runtime.Object{} + for _, o := range l.objs { + ll := labels.Set(o.GetLabels()) + if ls.Matches(ll) { + objs = append(objs, o) + } + } + return objs, nil } // Get will attempt to retrieve assuming that name==key diff --git a/pkg/kubeclient/resources/names.go b/pkg/kubeclient/resources/names.go index 1995fd56..7f0f3119 100644 --- a/pkg/kubeclient/resources/names.go +++ b/pkg/kubeclient/resources/names.go @@ -9,4 +9,5 @@ const ( ToolchainStatusName = "toolchain-status" ProxyPluginsPlural = "proxyplugins" NSTemplateTierPlural = "nstemplatetiers" + BannedUserResourcePlural = "bannedusers" ) diff --git a/pkg/proxy/proxy.go b/pkg/proxy/proxy.go index 106813a3..2b7e469b 100644 --- a/pkg/proxy/proxy.go +++ b/pkg/proxy/proxy.go @@ -118,6 +118,7 @@ func (p *Proxy) StartProxy(port string) *http.Server { return next(ctx) } }, + p.ensureUserIsNotBanned(), ) // middleware after routing @@ -395,18 +396,52 @@ func (p *Proxy) addUserContext() echo.MiddlewareFunc { return next(ctx) } - userID, username, err := p.extractUserID(ctx.Request()) + token, err := p.extractUserToken(ctx.Request()) if err != nil { return crterrors.NewUnauthorizedError("invalid bearer token", err.Error()) } - ctx.Set(context.SubKey, userID) - ctx.Set(context.UsernameKey, username) + ctx.Set(context.SubKey, token.Subject) + ctx.Set(context.UsernameKey, token.PreferredUsername) + ctx.Set(context.EmailKey, token.Email) return next(ctx) } } } +// ensureUserIsNotBanned rejects the request if the user is banned. +// This Middleware requires the context to contain the email of the user, +// so it needs to be executed after the `addUserContext` Middleware. +func (p *Proxy) ensureUserIsNotBanned() echo.MiddlewareFunc { + return func(next echo.HandlerFunc) echo.HandlerFunc { + return func(ctx echo.Context) error { + if unsecured(ctx) { // skip only for unsecured endpoints + return next(ctx) + } + + email := ctx.Get(context.EmailKey).(string) + if email == "" { + return crterrors.NewUnauthorizedError("unauthenticated request", "invalid email in token") + } + + // retrieve banned users + uu, err := p.app.InformerService().ListBannedUsersByEmail(email) + if err != nil { + ctx.Logger().Errorf("error retrieving the list of banned users with email address %s: %v", email, err) + return crterrors.NewInternalError(errs.New("user access could not be verified"), "could not define user access") + } + + // if a matching Banned user is found, then user is banned + if len(uu) > 0 { + return crterrors.NewForbiddenError("user access is forbidden", "user access is forbidden") + } + + // user is not banned + return next(ctx) + } + } +} + func (p *Proxy) stripInvalidHeaders() echo.MiddlewareFunc { return func(next echo.HandlerFunc) echo.HandlerFunc { return func(ctx echo.Context) error { @@ -434,26 +469,26 @@ func (p *Proxy) addStartTime() echo.MiddlewareFunc { } } -func (p *Proxy) extractUserID(req *http.Request) (string, string, error) { +func (p *Proxy) extractUserToken(req *http.Request) (*auth.TokenClaims, error) { userToken := "" var err error if wsstream.IsWebSocketRequest(req) { userToken, err = extractTokenFromWebsocketRequest(req) if err != nil { - return "", "", err + return nil, err } } else { userToken, err = extractUserToken(req) if err != nil { - return "", "", err + return nil, err } } token, err := p.tokenParser.FromString(userToken) if err != nil { - return "", "", crterrors.NewUnauthorizedError("unable to extract userID from token", err.Error()) + return nil, crterrors.NewUnauthorizedError("unable to extract userID from token", err.Error()) } - return token.Subject, token.PreferredUsername, nil + return token, nil } func extractUserToken(req *http.Request) (string, error) { diff --git a/pkg/proxy/proxy_test.go b/pkg/proxy/proxy_test.go index d465cfda..50f05db4 100644 --- a/pkg/proxy/proxy_test.go +++ b/pkg/proxy/proxy_test.go @@ -19,6 +19,7 @@ import ( appservice "github.com/codeready-toolchain/registration-service/pkg/application/service" "github.com/codeready-toolchain/registration-service/pkg/auth" + "github.com/codeready-toolchain/registration-service/pkg/configuration" "github.com/codeready-toolchain/registration-service/pkg/proxy/access" "github.com/codeready-toolchain/registration-service/pkg/proxy/handlers" "github.com/codeready-toolchain/registration-service/pkg/proxy/metrics" @@ -31,6 +32,7 @@ import ( toolchainv1alpha1 "github.com/codeready-toolchain/api/api/v1alpha1" commoncluster "github.com/codeready-toolchain/toolchain-common/pkg/cluster" + "github.com/codeready-toolchain/toolchain-common/pkg/hash" commontest "github.com/codeready-toolchain/toolchain-common/pkg/test" authsupport "github.com/codeready-toolchain/toolchain-common/pkg/test/auth" testconfig "github.com/codeready-toolchain/toolchain-common/pkg/test/config" @@ -55,6 +57,23 @@ func TestRunProxySuite(t *testing.T) { suite.Run(t, &TestProxySuite{test.UnitTestSuite{}}) } +var ( + bannedUser = toolchainv1alpha1.BannedUser{ + ObjectMeta: metav1.ObjectMeta{ + Name: "alice", + Namespace: configuration.Namespace(), + Labels: map[string]string{ + toolchainv1alpha1.BannedUserEmailHashLabelKey: hash.EncodeString("alice@redhat.com"), + }, + }, + Spec: toolchainv1alpha1.BannedUserSpec{ + Email: "alice@redhat.com", + }, + } + + bannedUserListErrorEmailValue = "banneduser-list-error" +) + func (s *TestProxySuite) TestProxy() { // given @@ -71,7 +90,23 @@ func (s *TestProxySuite) TestProxy() { s.SetConfig(testconfig.RegistrationService(). Environment(string(environment))) - fakeApp := &fake.ProxyFakeApp{} + + inf := fake.GetInformerService( + fake.InitClient(s.T()), + fake.WithGetBannedUsersByEmailFunc(func(email string) ([]toolchainv1alpha1.BannedUser, error) { + switch email { + case bannedUser.Spec.Email: + return []toolchainv1alpha1.BannedUser{bannedUser}, nil + case bannedUserListErrorEmailValue: + return nil, fmt.Errorf("list banned user error") + default: + return nil, nil + } + }))() + + fakeApp := &fake.ProxyFakeApp{ + InformerServiceMock: inf, + } proxyMetrics := metrics.NewProxyMetrics(prometheus.NewRegistry()) p, err := newProxyWithClusterClient(fakeApp, nil, proxyMetrics, proxytest.NewGetMembersFunc(fake.InitClient(s.T()))) require.NoError(s.T(), err) @@ -202,9 +237,10 @@ func (s *TestProxySuite) checkPlainHTTPErrors(fakeApp *fake.ProxyFakeApp) { s.Run("internal error if get accesses returns an error", func() { // given + fakeApp.Err = errors.New("some-error") + defer func() { fakeApp.Err = nil }() req := s.request() fakeApp.Accesses = map[string]*access.ClusterAccess{} - fakeApp.Err = errors.New("some-error") // when resp, err := http.DefaultClient.Do(req) @@ -219,6 +255,8 @@ func (s *TestProxySuite) checkPlainHTTPErrors(fakeApp *fake.ProxyFakeApp) { s.Run("internal error if accessing incorrect url", func() { // given + fakeApp.Err = errors.New("some-error") + defer func() { fakeApp.Err = nil }() req := s.request() req.URL.Path = "http://localhost:8081/metrics" require.NotNil(s.T(), req) @@ -232,6 +270,42 @@ func (s *TestProxySuite) checkPlainHTTPErrors(fakeApp *fake.ProxyFakeApp) { defer resp.Body.Close() assert.Equal(s.T(), http.StatusInternalServerError, resp.StatusCode) }) + + s.Run("forbidden error if user is banned", func() { + // given + req, err := http.NewRequest("GET", "http://localhost:8081/api/mycoolworkspace/pods", nil) + require.NoError(s.T(), err) + require.NotNil(s.T(), req) + userID := uuid.New() + token := s.token(userID, authsupport.WithSubClaim("alice"), authsupport.WithEmailClaim(bannedUser.Spec.Email)) + req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", token)) + resp, err := http.DefaultClient.Do(req) + + // then + require.NoError(s.T(), err) + require.NotNil(s.T(), resp) + defer resp.Body.Close() + assert.Equal(s.T(), http.StatusForbidden, resp.StatusCode) + s.assertResponseBody(resp, "user access is forbidden: user access is forbidden") + }) + + s.Run("internal error if error occurred while defining if the user is banned", func() { + // given + req, err := http.NewRequest("GET", "http://localhost:8081/api/mycoolworkspace/pods", nil) + require.NoError(s.T(), err) + require.NotNil(s.T(), req) + userID := uuid.New() + token := s.token(userID, authsupport.WithSubClaim("alice"), authsupport.WithEmailClaim(bannedUserListErrorEmailValue)) + req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", token)) + resp, err := http.DefaultClient.Do(req) + + // then + require.NoError(s.T(), err) + require.NotNil(s.T(), resp) + defer resp.Body.Close() + assert.Equal(s.T(), http.StatusInternalServerError, resp.StatusCode) + s.assertResponseBody(resp, "user access could not be verified: could not define user access") + }) }) } @@ -690,6 +764,9 @@ func (s *TestProxySuite) checkProxyOK(fakeApp *fake.ProxyFakeApp, p *Proxy) { inf.GetNSTemplateTierFunc = func(_ string) (*toolchainv1alpha1.NSTemplateTier, error) { return fake.NewBase1NSTemplateTier(), nil } + inf.ListBannedUsersByEmailFunc = func(_ string) ([]toolchainv1alpha1.BannedUser, error) { + return nil, nil + } s.Application.MockInformerService(inf) fakeApp.MemberClusterServiceMock = s.newMemberClusterServiceWithMembers(testServer.URL) @@ -1168,7 +1245,8 @@ func (s *TestProxySuite) token(userID uuid.UUID, extraClaims ...authsupport.Extr Username: "username-" + userID.String(), } - extra := append(extraClaims, authsupport.WithEmailClaim("someemail@comp.com")) + // if an email address is not explicitly set, someemail@comp.com is used + extra := append([]authsupport.ExtraClaim{authsupport.WithEmailClaim("someemail@comp.com")}, extraClaims...) token, err := authsupport.GenerateSignedE2ETestToken(*userIdentity, extra...) require.NoError(s.T(), err) diff --git a/test/fake/informer.go b/test/fake/informer.go index 2af4bc7a..c51e297c 100644 --- a/test/fake/informer.go +++ b/test/fake/informer.go @@ -23,13 +23,14 @@ func NewFakeInformer() Informer { } type Informer struct { - GetMurFunc func(name string) (*toolchainv1alpha1.MasterUserRecord, error) - GetSpaceFunc func(name string) (*toolchainv1alpha1.Space, error) - GetToolchainStatusFunc func() (*toolchainv1alpha1.ToolchainStatus, error) - GetUserSignupFunc func(name string) (*toolchainv1alpha1.UserSignup, error) - ListSpaceBindingFunc func(reqs ...labels.Requirement) ([]toolchainv1alpha1.SpaceBinding, error) - GetProxyPluginConfigFunc func(name string) (*toolchainv1alpha1.ProxyPlugin, error) - GetNSTemplateTierFunc func(name string) (*toolchainv1alpha1.NSTemplateTier, error) + GetMurFunc func(name string) (*toolchainv1alpha1.MasterUserRecord, error) + GetSpaceFunc func(name string) (*toolchainv1alpha1.Space, error) + GetToolchainStatusFunc func() (*toolchainv1alpha1.ToolchainStatus, error) + GetUserSignupFunc func(name string) (*toolchainv1alpha1.UserSignup, error) + ListSpaceBindingFunc func(reqs ...labels.Requirement) ([]toolchainv1alpha1.SpaceBinding, error) + GetProxyPluginConfigFunc func(name string) (*toolchainv1alpha1.ProxyPlugin, error) + GetNSTemplateTierFunc func(name string) (*toolchainv1alpha1.NSTemplateTier, error) + ListBannedUsersByEmailFunc func(email string) ([]toolchainv1alpha1.BannedUser, error) } func (f Informer) GetProxyPluginConfig(name string) (*toolchainv1alpha1.ProxyPlugin, error) { @@ -81,6 +82,13 @@ func (f Informer) GetNSTemplateTier(tier string) (*toolchainv1alpha1.NSTemplateT panic("not supposed to call GetNSTemplateTierFunc") } +func (f Informer) ListBannedUsersByEmail(email string) ([]toolchainv1alpha1.BannedUser, error) { + if f.ListBannedUsersByEmailFunc != nil { + return f.ListBannedUsersByEmailFunc(email) + } + panic("not supposed to call BannedUsersByEmail") +} + func NewSpace(name, targetCluster, compliantUserName string, spaceTestOptions ...spacetest.Option) *toolchainv1alpha1.Space { spaceTestOptions = append(spaceTestOptions, @@ -199,6 +207,12 @@ func WithGetMurFunc(getMurFunc func(name string) (*toolchainv1alpha1.MasterUserR } } +func WithGetBannedUsersByEmailFunc(bannedUsersByEmail func(ermail string) ([]toolchainv1alpha1.BannedUser, error)) InformerServiceOptions { + return func(informer *Informer) { + informer.ListBannedUsersByEmailFunc = bannedUsersByEmail + } +} + func GetInformerService(fakeClient client.Client, options ...InformerServiceOptions) func() service.InformerService { return func() service.InformerService { diff --git a/test/fake/proxy.go b/test/fake/proxy.go index 3b539a66..5dc68736 100644 --- a/test/fake/proxy.go +++ b/test/fake/proxy.go @@ -17,9 +17,13 @@ type ProxyFakeApp struct { Err error SignupServiceMock service.SignupService MemberClusterServiceMock service.MemberClusterService + InformerServiceMock service.InformerService } func (a *ProxyFakeApp) InformerService() service.InformerService { + if a.InformerServiceMock != nil { + return a.InformerServiceMock + } panic("InformerService shouldn't be called") }