Skip to content

Commit

Permalink
allow other Access implementations to work with flyio caveats
Browse files Browse the repository at this point in the history
  • Loading branch information
btoews committed Jan 30, 2024
1 parent b10c39a commit c51be8e
Show file tree
Hide file tree
Showing 2 changed files with 142 additions and 34 deletions.
108 changes: 108 additions & 0 deletions flyio/access.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,3 +80,111 @@ func (f *Access) Validate() error {

return nil
}

// OrgIDGetter is an interface allowing other packages to implement Accesses
// that work with Caveats defined in this package.
type OrgIDGetter interface {
resset.Access
GetOrgID() *uint64
}

var _ OrgIDGetter = (*Access)(nil)

// GetOrgID implements OrgIDGetter.
func (a *Access) GetOrgID() *uint64 { return a.OrgID }

// AppIDGetter is an interface allowing other packages to implement Accesses
// that work with Caveats defined in this package.
type AppIDGetter interface {
resset.Access
GetAppID() *uint64
}

var _ AppIDGetter = (*Access)(nil)

// GetAppID implements AppIDGetter.
func (a *Access) GetAppID() *uint64 { return a.AppID }

// FeatureGetter is an interface allowing other packages to implement Accesses
// that work with Caveats defined in this package.
type FeatureGetter interface {
resset.Access
GetFeature() *string
}

var _ FeatureGetter = (*Access)(nil)

// GetFeature implements FeatureGetter.
func (a *Access) GetFeature() *string { return a.Feature }

// VolumeGetter is an interface allowing other packages to implement Accesses
// that work with Caveats defined in this package.
type VolumeGetter interface {
resset.Access
GetVolume() *string
}

var _ VolumeGetter = (*Access)(nil)

// GetVolume implements VolumeGetter.
func (a *Access) GetVolume() *string { return a.Volume }

// MachineGetter is an interface allowing other packages to implement Accesses
// that work with Caveats defined in this package.
type MachineGetter interface {
resset.Access
GetMachine() *string
}

var _ MachineGetter = (*Access)(nil)

// GetMachine implements MachineGetter.
func (a *Access) GetMachine() *string { return a.Machine }

// MachineFeatureGetter is an interface allowing other packages to implement
// Accesses that work with Caveats defined in this package.
type MachineFeatureGetter interface {
resset.Access
GetMachineFeature() *string
}

var _ MachineFeatureGetter = (*Access)(nil)

// GetMachineFeature implements MachineFeatureGetter.
func (a *Access) GetMachineFeature() *string { return a.MachineFeature }

// MutationGetter is an interface allowing other packages to implement Accesses
// that work with Caveats defined in this package.
type MutationGetter interface {
macaroon.Access
GetMutation() *string
}

var _ MutationGetter = (*Access)(nil)

// GetMutation implements MutationGetter.
func (a *Access) GetMutation() *string { return a.Mutation }

// SourceMachineGetter is an interface allowing other packages to implement
// Accesses that work with Caveats defined in this package.
type SourceMachineGetter interface {
macaroon.Access
GetSourceMachine() *string
}

var _ SourceMachineGetter = (*Access)(nil)

// GetSourceMachine implements SourceMachineGetter.
func (a *Access) GetSourceMachine() *string { return a.SourceMachine }

// ClusterGetter is an interface allowing other packages to implement Accesses
// that work with Caveats defined in this package.
type ClusterGetter interface {
resset.Access
GetCluster() *string
}

var _ ClusterGetter = (*Access)(nil)

// GetCluster implements ClusterGetter.
func (a *Access) GetCluster() *string { return a.Cluster }
68 changes: 34 additions & 34 deletions flyio/caveats.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,15 @@ func (c *FromMachine) CaveatType() macaroon.CaveatType { return CavFromMachineSo
func (c *FromMachine) Name() string { return "FromMachineSource" }

func (c *FromMachine) Prohibits(a macaroon.Access) error {
f, isFlyioAccess := a.(*Access)
f, isFlyioAccess := a.(SourceMachineGetter)

switch {
case !isFlyioAccess:
return macaroon.ErrInvalidAccess
case f.SourceMachine == nil:
case f.GetSourceMachine() == nil:
return fmt.Errorf("%w missing SourceMachine", macaroon.ErrInvalidAccess)
case c.ID != *f.SourceMachine:
return fmt.Errorf("%w: unauthorized source, expected from machine %s, but got %s", macaroon.ErrUnauthorized, c.ID, *f.SourceMachine)
case c.ID != *f.GetSourceMachine():
return fmt.Errorf("%w: unauthorized source, expected from machine %s, but got %s", macaroon.ErrUnauthorized, c.ID, *f.GetSourceMachine())
default:
return nil
}
Expand All @@ -59,17 +59,17 @@ func (c *Organization) CaveatType() macaroon.CaveatType { return CavOrganization
func (c *Organization) Name() string { return "Organization" }

func (c *Organization) Prohibits(a macaroon.Access) error {
f, isFlyioAccess := a.(*Access)
f, isFlyioAccess := a.(OrgIDGetter)

switch {
case !isFlyioAccess:
return macaroon.ErrInvalidAccess
case f.OrgID == nil:
case f.GetOrgID() == nil:
return fmt.Errorf("%w org", resset.ErrResourceUnspecified)
case c.ID != *f.OrgID:
return fmt.Errorf("%w org %d, only %d", resset.ErrUnauthorizedForResource, f.OrgID, c.ID)
case !f.Action.IsSubsetOf(c.Mask):
return fmt.Errorf("%w access %s (%s not allowed)", resset.ErrUnauthorizedForAction, f.Action, f.Action.Remove(c.Mask))
case c.ID != *f.GetOrgID():
return fmt.Errorf("%w org %d, only %d", resset.ErrUnauthorizedForResource, *f.GetOrgID(), c.ID)
case !f.GetAction().IsSubsetOf(c.Mask):
return fmt.Errorf("%w access %s (%s not allowed)", resset.ErrUnauthorizedForAction, f.GetAction(), f.GetAction().Remove(c.Mask))
default:
return nil
}
Expand All @@ -91,11 +91,11 @@ func (c *Apps) CaveatType() macaroon.CaveatType { return CavApps }
func (c *Apps) Name() string { return "Apps" }

func (c *Apps) Prohibits(a macaroon.Access) error {
f, isFlyioAccess := a.(*Access)
f, isFlyioAccess := a.(AppIDGetter)
if !isFlyioAccess {
return macaroon.ErrInvalidAccess
}
return c.Apps.Prohibits(f.AppID, f.Action)
return c.Apps.Prohibits(f.GetAppID(), f.GetAction())
}

type Volumes struct {
Expand All @@ -107,11 +107,11 @@ func (c *Volumes) CaveatType() macaroon.CaveatType { return CavVolumes }
func (c *Volumes) Name() string { return "Volumes" }

func (c *Volumes) Prohibits(a macaroon.Access) error {
f, isFlyioAccess := a.(*Access)
f, isFlyioAccess := a.(VolumeGetter)
if !isFlyioAccess {
return macaroon.ErrInvalidAccess
}
return c.Volumes.Prohibits(f.Volume, f.Action)
return c.Volumes.Prohibits(f.GetVolume(), f.GetAction())
}

type Machines struct {
Expand All @@ -123,11 +123,11 @@ func (c *Machines) CaveatType() macaroon.CaveatType { return CavMachines }
func (c *Machines) Name() string { return "Machines" }

func (c *Machines) Prohibits(a macaroon.Access) error {
f, isFlyioAccess := a.(*Access)
f, isFlyioAccess := a.(MachineGetter)
if !isFlyioAccess {
return macaroon.ErrInvalidAccess
}
return c.Machines.Prohibits(f.Machine, f.Action)
return c.Machines.Prohibits(f.GetMachine(), f.GetAction())
}

type MachineFeatureSet struct {
Expand All @@ -139,11 +139,11 @@ func (c *MachineFeatureSet) CaveatType() macaroon.CaveatType { return CavMachine
func (c *MachineFeatureSet) Name() string { return "MachineFeatureSet" }

func (c *MachineFeatureSet) Prohibits(a macaroon.Access) error {
f, isFlyioAccess := a.(*Access)
f, isFlyioAccess := a.(MachineFeatureGetter)
if !isFlyioAccess {
return macaroon.ErrInvalidAccess
}
return c.Features.Prohibits(f.MachineFeature, f.Action)
return c.Features.Prohibits(f.GetMachineFeature(), f.GetAction())
}

// FeatureSet is a collection of organization-level "features" that are managed
Expand All @@ -160,11 +160,11 @@ func (c *FeatureSet) CaveatType() macaroon.CaveatType { return CavFeatureSet }
func (c *FeatureSet) Name() string { return "FeatureSet" }

func (c *FeatureSet) Prohibits(a macaroon.Access) error {
f, isFlyioAccess := a.(*Access)
f, isFlyioAccess := a.(FeatureGetter)
if !isFlyioAccess {
return macaroon.ErrInvalidAccess
}
return c.Features.Prohibits(f.Feature, f.Action)
return c.Features.Prohibits(f.GetFeature(), f.GetAction())
}

// Mutations is a set of GraphQL mutations allowed by this token.
Expand All @@ -177,27 +177,27 @@ func (c *Mutations) CaveatType() macaroon.CaveatType { return CavMutations }
func (c *Mutations) Name() string { return "Mutations" }

func (c *Mutations) Prohibits(a macaroon.Access) error {
f, isFlyioAccess := a.(*Access)
f, isFlyioAccess := a.(MutationGetter)
if !isFlyioAccess {
return macaroon.ErrInvalidAccess
}

if f.Mutation == nil {
if f.GetMutation() == nil {
// explicitly don't return resset.ErrResourceUnspecified. A mutation isn't a
// resource and can't be used with IfPresent caveats.
return fmt.Errorf("%w: only authorized for graphql mutations", macaroon.ErrUnauthorized)
}

var found bool
for _, mutation := range c.Mutations {
if mutation != *f.Mutation {
if mutation != *f.GetMutation() {
continue
}
found = true
}

if !found {
return fmt.Errorf("%w mutation %s", resset.ErrUnauthorizedForResource, *f.Mutation)
return fmt.Errorf("%w mutation %s", resset.ErrUnauthorizedForResource, *f.GetMutation())
}

return nil
Expand Down Expand Up @@ -228,12 +228,12 @@ func (c *Clusters) CaveatType() macaroon.CaveatType { return CavClusters }
func (c *Clusters) Name() string { return "Clusters" }

func (c *Clusters) Prohibits(a macaroon.Access) error {
f, isFlyioAccess := a.(*Access)
f, isFlyioAccess := a.(ClusterGetter)
if !isFlyioAccess {
return macaroon.ErrInvalidAccess
}

return c.Clusters.Prohibits(f.Cluster, f.Action)
return c.Clusters.Prohibits(f.GetCluster(), f.GetAction())
}

const (
Expand Down Expand Up @@ -288,27 +288,27 @@ func (c *NoAdminFeatures) CaveatType() macaroon.CaveatType { return CavNoAdminFe
func (c *NoAdminFeatures) Name() string { return "NoAdminFeatures" }

func (c *NoAdminFeatures) Prohibits(a macaroon.Access) error {
f, isFlyioAccess := a.(*Access)
f, isFlyioAccess := a.(FeatureGetter)
if !isFlyioAccess {
return macaroon.ErrInvalidAccess
}
if f.Feature == nil {
if f.GetFeature() == nil {
return nil
}
if *f.Feature == "" {
if *f.GetFeature() == "" {
return fmt.Errorf("%w admin org features", resset.ErrUnauthorizedForResource)
}

memberPermission, ok := MemberFeatures[*f.Feature]
memberPermission, ok := MemberFeatures[*f.GetFeature()]
if !ok {
return fmt.Errorf("%w %s", resset.ErrUnauthorizedForResource, *f.Feature)
return fmt.Errorf("%w %s", resset.ErrUnauthorizedForResource, *f.GetFeature())
}
if !f.Action.IsSubsetOf(memberPermission) {
if !f.GetAction().IsSubsetOf(memberPermission) {
return fmt.Errorf(
"%w %s access to %s",
resset.ErrUnauthorizedForAction,
f.Action.Remove(memberPermission),
*f.Feature,
f.GetAction().Remove(memberPermission),
*f.GetFeature(),
)
}

Expand Down

0 comments on commit c51be8e

Please sign in to comment.