Skip to content

Commit

Permalink
Test and correctly integrate username prefix
Browse files Browse the repository at this point in the history
  • Loading branch information
glrf committed Jan 19, 2022
1 parent 2b7e3ed commit 1c0b8ea
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 9 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ clean: ## Cleans up the generated resources
.PHONY: run
KUBECONFIG ?= ~/.kube/config
run: build ## Starts control api against the configured kuberentes cluster
$(BIN_FILENAME) --secure-port 9443 --kubeconfig $(KUBECONFIG) --authentication-kubeconfig $(KUBECONFIG) --authorization-kubeconfig $(KUBECONFIG) --cluster-roles appuio-organization-viewer,appuio-organization-admin
$(BIN_FILENAME) --secure-port 9443 --kubeconfig $(KUBECONFIG) --authentication-kubeconfig $(KUBECONFIG) --authorization-kubeconfig $(KUBECONFIG) --cluster-roles appuio-organization-viewer,appuio-organization-admin --username-prefix "appuio#"

.PHONY: local-env
local-env-setup: ## Setup local kind-based dev environment
Expand Down
2 changes: 1 addition & 1 deletion apiserver/organization/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ func (s *organizationStorage) create(ctx context.Context, org *orgv1.Organizatio
return nil, fmt.Errorf("failed to create organization: %w", err)
}

orgMembers := newOrganizationMembers(ctx, org.Name, "")
orgMembers := newOrganizationMembers(ctx, org.Name, s.usernamePrefix)

if err := s.members.CreateMembers(ctx, orgMembers); err != nil {
// rollback
Expand Down
37 changes: 34 additions & 3 deletions apiserver/organization/create_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,38 +3,46 @@ package organization
import (
"context"
"errors"
"fmt"
"testing"

"github.com/golang/mock/gomock"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

orgv1 "github.com/appuio/control-api/apis/organization/v1"
controlv1 "github.com/appuio/control-api/apis/v1"
mock "github.com/appuio/control-api/apiserver/organization/mock"

apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apiserver/pkg/authentication/user"
"k8s.io/apiserver/pkg/authorization/authorizer"
"k8s.io/apiserver/pkg/endpoints/request"
)

func TestOrganizationStorage_Create(t *testing.T) {
tests := map[string]struct {
userID string
organizationIn *orgv1.Organization

namespaceErr error

authDecision authResponse

memberName string

organizationOut *orgv1.Organization
err error
}{
"GivenCreateOrg_ThenSuccess": {
userID: "appuio#smith",
organizationIn: fooOrg,
authDecision: authResponse{
decision: authorizer.DecisionAllow,
},
memberName: "smith",
organizationOut: fooOrg,
},
"GivenNsExists_ThenFail": {
Expand Down Expand Up @@ -79,6 +87,7 @@ func TestOrganizationStorage_Create(t *testing.T) {
os.rbac = mrb
mmemb := mock.NewMockmemberProvider(ctrl)
os.members = mmemb
os.usernamePrefix = "appuio#"
mauth.EXPECT().
Authorize(gomock.Any(), isAuthRequest("create")).
Return(tc.authDecision.decision, tc.authDecision.reason, tc.authDecision.err).
Expand All @@ -92,20 +101,22 @@ func TestOrganizationStorage_Create(t *testing.T) {
Return(nil).
AnyTimes()
mmemb.EXPECT().
CreateMembers(gomock.Any(), gomock.Any()).
CreateMembers(gomock.Any(), containsMember(tc.memberName)).
Return(nil).
AnyTimes()

nopValidate := func(ctx context.Context, obj runtime.Object) error {
return nil
}
org, err := os.Create(request.WithRequestInfo(request.NewContext(),
org, err := os.Create(request.WithUser(request.WithRequestInfo(request.NewContext(),
&request.RequestInfo{
Verb: "create",
APIGroup: orgv1.GroupVersion.Group,
Resource: "organizations",
Name: tc.organizationIn.Name,
}),
}), &user.DefaultInfo{
Name: tc.userID,
}),
tc.organizationIn, nopValidate, nil)

if tc.err != nil {
Expand Down Expand Up @@ -189,3 +200,23 @@ func TestOrganizationStorage_Create_Abort(t *testing.T) {
})
}
}

type memberMatcher struct {
user string
}

func (m memberMatcher) Matches(x interface{}) bool {
mem, ok := x.(*controlv1.OrganizationMembers)
if !ok {
return ok
}
return len(mem.Spec.UserRefs) > 0 && mem.Spec.UserRefs[0].ID == m.user
}

func (m memberMatcher) String() string {
return fmt.Sprintf("contains %s", m.user)
}

func containsMember(user string) memberMatcher {
return memberMatcher{user: user}
}
10 changes: 7 additions & 3 deletions apiserver/organization/organization.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import (
// +kubebuilder:rbac:groups="flowcontrol.apiserver.k8s.io",resources=prioritylevelconfigurations;flowschemas,verbs=get;list;watch

// New returns a new storage provider for Organizations
func New(clusterRoles *[]string) restbuilder.ResourceHandlerProvider {
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 {
Expand All @@ -45,13 +45,17 @@ func New(clusterRoles *[]string) restbuilder.ResourceHandlerProvider {
members: kubeMemberProvider{
Client: c,
},
usernamePrefix: *usernamePrefix,
}, nil
}
}

type organizationStorage struct {
namepaces namespaceProvider
members memberProvider
namepaces namespaceProvider

members memberProvider
usernamePrefix string

authorizer rbacAuthorizer

rbac roleBindingCreator
Expand Down
4 changes: 3 additions & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,9 @@ func main() {
).Info("Starting control-api…")

roles := []string{}
usernamePrefix := ""
cmd, err := builder.APIServer.
WithResourceAndHandler(&orgv1.Organization{}, orgStore.New(&roles)).
WithResourceAndHandler(&orgv1.Organization{}, orgStore.New(&roles, &usernamePrefix)).
WithoutEtcd().
ExposeLoopbackAuthorizer().
ExposeLoopbackMasterClientConfig().
Expand All @@ -46,6 +47,7 @@ func main() {
}

cmd.Flags().StringSliceVar(&roles, "cluster-roles", []string{}, "Cluster Roles to bind when creating an organization")
cmd.Flags().StringVar(&usernamePrefix, "username-prefix", "", "Prefix prepended to username claims. Usually the same as \"--oidc-username-prefix\" of the Kubernetes API server")
err = cmd.Execute()
if err != nil {
logger.Error(err, "API server stopped unexpectedly")
Expand Down

0 comments on commit 1c0b8ea

Please sign in to comment.