Skip to content

Commit

Permalink
add public-viewer support to SpaceLister's Get
Browse files Browse the repository at this point in the history
this commit is part of the effort of splitting PR #443

Signed-off-by: Francesco Ilario <filario@redhat.com>
  • Loading branch information
filariow committed Jul 25, 2024
1 parent 06efa59 commit 99e41e8
Show file tree
Hide file tree
Showing 4 changed files with 344 additions and 17 deletions.
84 changes: 74 additions & 10 deletions pkg/proxy/handlers/spacelister_get.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import (
"time"

toolchainv1alpha1 "github.com/codeready-toolchain/api/api/v1alpha1"
"github.com/codeready-toolchain/registration-service/pkg/configuration"
"github.com/codeready-toolchain/registration-service/pkg/context"
regsercontext "github.com/codeready-toolchain/registration-service/pkg/context"
"github.com/codeready-toolchain/registration-service/pkg/proxy/metrics"
"github.com/codeready-toolchain/registration-service/pkg/signup"
Expand All @@ -26,6 +28,8 @@ func HandleSpaceGetRequest(spaceLister *SpaceLister, GetMembersFunc cluster.GetM
// get specific workspace
return func(ctx echo.Context) error {
requestReceivedTime := ctx.Get(regsercontext.RequestReceivedTime).(time.Time)
publicViewerEnabled := configuration.GetRegistrationServiceConfig().PublicViewerEnabled()
ctx.Set(context.PublicViewerEnabled, publicViewerEnabled)
workspace, err := GetUserWorkspaceWithBindings(ctx, spaceLister, ctx.Param("workspace"), GetMembersFunc)
if err != nil {
spaceLister.ProxyMetrics.RegServWorkspaceHistogramVec.WithLabelValues(fmt.Sprintf("%d", http.StatusInternalServerError), metrics.MetricsLabelVerbGet).Observe(time.Since(requestReceivedTime).Seconds()) // using list as the default value for verb to minimize label combinations for prometheus to process
Expand All @@ -42,7 +46,7 @@ func HandleSpaceGetRequest(spaceLister *SpaceLister, GetMembersFunc cluster.GetM
}
}

// GetUserWorkspace returns a workspace object with the required fields used by the proxy
// GetUserWorkspace returns a workspace object with the required fields used by the proxy.
func GetUserWorkspace(ctx echo.Context, spaceLister *SpaceLister, workspaceName string) (*toolchainv1alpha1.Workspace, error) {
userSignup, space, err := getUserSignupAndSpace(ctx, spaceLister, workspaceName)
if err != nil {
Expand All @@ -53,10 +57,58 @@ func GetUserWorkspace(ctx echo.Context, spaceLister *SpaceLister, workspaceName
return nil, nil
}

// retrieve user space binding
userSpaceBinding, err := getUserOrPublicViewerSpaceBinding(ctx, spaceLister, space, userSignup, workspaceName)
if err != nil {
return nil, err
}
// consider this as not found
if userSpaceBinding == nil {
return nil, nil
}

// create and return the result workspace object
return createWorkspaceObject(userSignup.Name, space, userSpaceBinding), nil
}

// getUserOrPublicViewerSpaceBinding retrieves the user space binding for an user and a space.
// If the SpaceBinding is not found and the PublicViewer feature is enabled, it will retry
// with the PublicViewer credentials.
func getUserOrPublicViewerSpaceBinding(ctx echo.Context, spaceLister *SpaceLister, space *toolchainv1alpha1.Space, userSignup *signup.Signup, workspaceName string) (*toolchainv1alpha1.SpaceBinding, error) {
userSpaceBinding, err := getUserSpaceBinding(ctx, spaceLister, space, userSignup.CompliantUsername)
if err != nil {
return nil, err
}

// if user space binding is not found and PublicViewer is enabled,
// retry with PublicViewer's signup
if userSpaceBinding == nil {
if context.IsPublicViewerEnabled(ctx) {
pvSb, err := getUserSpaceBinding(ctx, spaceLister, space, toolchainv1alpha1.KubesawAuthenticatedUsername)
if err != nil {
ctx.Logger().Error(fmt.Sprintf("error checking if SpaceBinding is present for user %s and the workspace %s", toolchainv1alpha1.KubesawAuthenticatedUsername, workspaceName))
return nil, err

Check warning on line 90 in pkg/proxy/handlers/spacelister_get.go

View check run for this annotation

Codecov / codecov/patch

pkg/proxy/handlers/spacelister_get.go#L89-L90

Added lines #L89 - L90 were not covered by tests
}
if pvSb == nil {
ctx.Logger().Error(fmt.Sprintf("unauthorized access - there is no SpaceBinding present for the user %s and the workspace %s", toolchainv1alpha1.KubesawAuthenticatedUsername, workspaceName))
return nil, nil
}
return pvSb, nil
}
ctx.Logger().Error(fmt.Sprintf("unauthorized access - there is no SpaceBinding present for the user %s and the workspace %s", userSignup.CompliantUsername, workspaceName))
}

return userSpaceBinding, nil
}

// getUserSpaceBinding retrieves the user space binding for an user and a space.
// If no space binding found for this user and space then returns nil, nil
// If multiple found then returns the first one.
func getUserSpaceBinding(ctx echo.Context, spaceLister *SpaceLister, space *toolchainv1alpha1.Space, compliantUsername string) (*toolchainv1alpha1.SpaceBinding, error) {
// recursively get all the spacebindings for the current workspace
listSpaceBindingsFunc := func(spaceName string) ([]toolchainv1alpha1.SpaceBinding, error) {
spaceSelector, _ := labels.SelectorFromSet(labels.Set{toolchainv1alpha1.SpaceBindingSpaceLabelKey: spaceName}).Requirements()
murSelector, _ := labels.SelectorFromSet(labels.Set{toolchainv1alpha1.SpaceBindingMasterUserRecordLabelKey: userSignup.CompliantUsername}).Requirements()
murSelector, _ := labels.SelectorFromSet(labels.Set{toolchainv1alpha1.SpaceBindingMasterUserRecordLabelKey: compliantUsername}).Requirements()
return spaceLister.GetInformerServiceFunc().ListSpaceBindings(spaceSelector[0], murSelector[0])
}
spaceBindingLister := spacebinding.NewLister(listSpaceBindingsFunc, spaceLister.GetInformerServiceFunc().GetSpace)
Expand All @@ -66,21 +118,20 @@ func GetUserWorkspace(ctx echo.Context, spaceLister *SpaceLister, workspaceName
return nil, err
}
if len(userSpaceBindings) == 0 {
// let's only log the issue and consider this as not found
ctx.Logger().Error(fmt.Sprintf("unauthorized access - there is no SpaceBinding present for the user %s and the workspace %s", userSignup.CompliantUsername, workspaceName))
// consider this as not found
return nil, nil
}

if len(userSpaceBindings) > 1 {
userBindingsErr := fmt.Errorf("invalid number of SpaceBindings found for MUR:%s and Space:%s. Expected 1 got %d", userSignup.CompliantUsername, space.Name, len(userSpaceBindings))
userBindingsErr := fmt.Errorf("invalid number of SpaceBindings found for MUR:%s and Space:%s. Expected 1 got %d", compliantUsername, space.Name, len(userSpaceBindings))
ctx.Logger().Error(userBindingsErr)
return nil, userBindingsErr
}

return createWorkspaceObject(userSignup.Name, space, &userSpaceBindings[0]), nil
return &userSpaceBindings[0], nil
}

// GetUserWorkspaceWithBindings returns a workspace object with the required fields+bindings (the list with all the users access details)
// GetUserWorkspaceWithBindings returns a workspace object with the required fields+bindings (the list with all the users access details).
func GetUserWorkspaceWithBindings(ctx echo.Context, spaceLister *SpaceLister, workspaceName string, GetMembersFunc cluster.GetMemberClustersFunc) (*toolchainv1alpha1.Workspace, error) {
userSignup, space, err := getUserSignupAndSpace(ctx, spaceLister, workspaceName)
if err != nil {
Expand All @@ -106,9 +157,16 @@ func GetUserWorkspaceWithBindings(ctx echo.Context, spaceLister *SpaceLister, wo
// check if user has access to this workspace
userBinding := filterUserSpaceBinding(userSignup.CompliantUsername, allSpaceBindings)
if userBinding == nil {
// let's only log the issue and consider this as not found
ctx.Logger().Error(fmt.Sprintf("unauthorized access - there is no SpaceBinding present for the user %s and the workspace %s", userSignup.CompliantUsername, workspaceName))
return nil, nil
// if PublicViewer is enabled, check if the Space is visibile to PublicViewer
if context.IsPublicViewerEnabled(ctx) && userSignup.CompliantUsername != toolchainv1alpha1.KubesawAuthenticatedUsername {
userBinding = filterUserSpaceBinding(toolchainv1alpha1.KubesawAuthenticatedUsername, allSpaceBindings)
}

if userBinding == nil {
// let's only log the issue and consider this as not found
ctx.Logger().Error(fmt.Sprintf("unauthorized access - there is no SpaceBinding present for the user %s and the workspace %s", userSignup.CompliantUsername, workspaceName))
return nil, nil
}
}

// list all SpaceBindingRequests , just in case there might be some failing to create a SpaceBinding resource.
Expand Down Expand Up @@ -145,6 +203,12 @@ func getUserSignupAndSpace(ctx echo.Context, spaceLister *SpaceLister, workspace
if err != nil {
return nil, nil, err
}
if userSignup == nil && context.IsPublicViewerEnabled(ctx) {
userSignup = &signup.Signup{
CompliantUsername: toolchainv1alpha1.KubesawAuthenticatedUsername,
Name: toolchainv1alpha1.KubesawAuthenticatedUsername,
}
}

space, err := spaceLister.GetInformerServiceFunc().GetSpace(workspaceName)
if err != nil {
Expand Down
Loading

0 comments on commit 99e41e8

Please sign in to comment.