Skip to content

Commit

Permalink
Allow organization BE ref validation to be skipped. (#201)
Browse files Browse the repository at this point in the history
Required for migration when we switch off the BE part of the API-Server.
  • Loading branch information
bastjan authored Feb 5, 2024
1 parent 0810551 commit 2778cd7
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 27 deletions.
5 changes: 3 additions & 2 deletions api.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,10 @@ import (
func APICommand() *cobra.Command {
roles := []string{}
usernamePrefix := ""
var allowEmptyBillingEntity bool
var allowEmptyBillingEntity, skipBillingEntityValidation bool

ob := &odooStorageBuilder{}
ost := orgStore.New(&roles, &usernamePrefix, &allowEmptyBillingEntity)
ost := orgStore.New(&roles, &usernamePrefix, &allowEmptyBillingEntity, &skipBillingEntityValidation)
ib := &invitationStorageBuilder{usernamePrefix: &usernamePrefix}

cmd, err := builder.APIServer.
Expand All @@ -55,6 +55,7 @@ func APICommand() *cobra.Command {
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")
cmd.Flags().BoolVar(&allowEmptyBillingEntity, "allow-empty-billing-entity", true, "Allow empty billing entity references")
cmd.Flags().BoolVar(&skipBillingEntityValidation, "organization-skip-billing-entity-validation", false, "Skip validation of billing entity references")

cmd.Flags().StringVar(&ob.billingEntityStorage, "billing-entity-storage", "fake", "Storage backend for billing entities. Supported values: fake, odoo8, odoo16")

Expand Down
50 changes: 30 additions & 20 deletions apiserver/organization/billingentity_validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package organization
import (
"context"
"fmt"
"os"

"k8s.io/apiserver/pkg/authentication/user"
"k8s.io/apiserver/pkg/endpoints/request"
Expand Down Expand Up @@ -45,29 +46,38 @@ func (c impersonatorFromRestconf) Impersonate(u user.Info) (client.Client, error
// billingEntityValidator validates that the billing entity exists and the requesting user has access to it.
// it does so by impersonating the user and trying to get the billing entity.
func (s *organizationStorage) billingEntityValidator(ctx context.Context, org, oldOrg *orgv1.Organization) error {
// check if changed
if oldOrg != nil && oldOrg.Spec.BillingEntityRef == org.Spec.BillingEntityRef {
return nil
}
// check if we allow empty billing entities
if org.Spec.BillingEntityRef == "" && s.allowEmptyBillingEntity {
return nil
}
validate := func() error {
// check if changed
if oldOrg != nil && oldOrg.Spec.BillingEntityRef == org.Spec.BillingEntityRef {
return nil
}
// check if we allow empty billing entities
if org.Spec.BillingEntityRef == "" && s.allowEmptyBillingEntity {
return nil
}

user, ok := request.UserFrom(ctx)
if !ok {
return fmt.Errorf("no user in context")
}
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)
}
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: org.Spec.BillingEntityRef}, &be); err != nil {
return err
}

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

return nil
err := validate()
if err != nil && s.skipBillingEntityValidation {
fmt.Fprintf(os.Stderr, "Warning: billing entity validation for %q (ref: %q) would have failed: %v\n", org.Name, org.Spec.BillingEntityRef, err)
return nil
}
return err
}
12 changes: 7 additions & 5 deletions apiserver/organization/organization.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,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, usernamePrefix *string, allowEmptyBillingEntity *bool) restbuilder.ResourceHandlerProvider {
func New(clusterRoles *[]string, usernamePrefix *string, allowEmptyBillingEntity, skipBillingEntityValidation *bool) restbuilder.ResourceHandlerProvider {
return func(s *runtime.Scheme, g genericregistry.RESTOptionsGetter) (rest.Storage, error) {
masterConfig := loopback.GetLoopbackMasterClientConfig()

Expand All @@ -54,9 +54,10 @@ func New(clusterRoles *[]string, usernamePrefix *string, allowEmptyBillingEntity
members: kubeMemberProvider{
Client: c,
},
usernamePrefix: *usernamePrefix,
impersonator: impersonatorFromRestconf{masterConfig, client.Options{Scheme: c.Scheme()}},
allowEmptyBillingEntity: *allowEmptyBillingEntity,
usernamePrefix: *usernamePrefix,
impersonator: impersonatorFromRestconf{masterConfig, client.Options{Scheme: c.Scheme()}},
allowEmptyBillingEntity: *allowEmptyBillingEntity,
skipBillingEntityValidation: *skipBillingEntityValidation,
}

return authwrapper.NewAuthorizedStorage(stor, metav1.GroupVersionResource{
Expand All @@ -78,7 +79,8 @@ type organizationStorage struct {

impersonator impersonator

allowEmptyBillingEntity bool
skipBillingEntityValidation bool
allowEmptyBillingEntity bool
}

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

0 comments on commit 2778cd7

Please sign in to comment.