Skip to content

Commit

Permalink
Merge pull request #28 from superfly/storage-object-caveat
Browse files Browse the repository at this point in the history
`StorageObjects` caveat
  • Loading branch information
btoews authored Jul 17, 2024
2 parents 87d5324 + dfd7d69 commit fecb31e
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 15 deletions.
1 change: 1 addition & 0 deletions caveat.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ const (
CavAction
CavFlyioCommands
CavFlyioAppFeatureSet
CavFlyioStorageObjects

// allocate internal blocks of size 255 here
block255Min CaveatType = 1 << 16
Expand Down
53 changes: 38 additions & 15 deletions flyio/access.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,19 @@ import (
)

type Access struct {
Action resset.Action `json:"action,omitempty"`
OrgID *uint64 `json:"orgid,omitempty"`
AppID *uint64 `json:"appid,omitempty"`
AppFeature *string `json:"app_feature,omitempty"`
Feature *string `json:"feature,omitempty"`
Volume *string `json:"volume,omitempty"`
Machine *string `json:"machine,omitempty"`
MachineFeature *string `json:"machine_feature,omitempty"`
Mutation *string `json:"mutation,omitempty"`
SourceMachine *string `json:"sourceMachine,omitempty"`
Cluster *string `json:"cluster,omitempty"`
Command []string `json:"command,omitempty"`
Action resset.Action `json:"action,omitempty"`
OrgID *uint64 `json:"orgid,omitempty"`
AppID *uint64 `json:"appid,omitempty"`
AppFeature *string `json:"app_feature,omitempty"`
Feature *string `json:"feature,omitempty"`
Volume *string `json:"volume,omitempty"`
Machine *string `json:"machine,omitempty"`
MachineFeature *string `json:"machine_feature,omitempty"`
Mutation *string `json:"mutation,omitempty"`
SourceMachine *string `json:"sourceMachine,omitempty"`
Cluster *string `json:"cluster,omitempty"`
Command []string `json:"command,omitempty"`
StorageObject *resset.Prefix `json:"storage_object,omitempty"`
}

var (
Expand Down Expand Up @@ -49,9 +50,19 @@ func (f *Access) Validate() error {
return fmt.Errorf("%w org", resset.ErrResourceUnspecified)
}

// org-level resources = apps, features
if f.AppID != nil && f.Feature != nil {
return fmt.Errorf("%w: app, org-feature", resset.ErrResourcesMutuallyExclusive)
// org-level resources = apps, features, storage objects
var orgResources []string
if f.AppID != nil {
orgResources = append(orgResources, "app")
}
if f.Feature != nil {
orgResources = append(orgResources, *f.Feature)
}
if f.StorageObject != nil {
orgResources = append(orgResources, "storage-object")
}
if len(orgResources) > 1 {
return fmt.Errorf("%w: %s", resset.ErrResourcesMutuallyExclusive, strings.Join(orgResources, ", "))
}

// app-level resources = machines, volumes, app-features
Expand Down Expand Up @@ -232,3 +243,15 @@ var _ CommandGetter = (*Access)(nil)

// GetCommand implements CommandGetter.
func (a *Access) GetCommand() []string { return a.Command }

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

var _ StorageObjectGetter = (*Access)(nil)

// GetStorageObject implements StorageObjectGetter.
func (a *Access) GetStorageObject() *resset.Prefix { return a.StorageObject }
25 changes: 25 additions & 0 deletions flyio/caveats.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ const (
CavNoAdminFeatures = macaroon.CavNoAdminFeatures
CavCommands = macaroon.CavFlyioCommands
CavAppFeatureSet = macaroon.CavFlyioAppFeatureSet
CavStorageObjects = macaroon.CavFlyioStorageObjects
)

type FromMachine struct {
Expand Down Expand Up @@ -383,3 +384,27 @@ func (c *AppFeatureSet) Prohibits(a macaroon.Access) error {
}
return c.Features.Prohibits(f.GetAppFeature(), f.GetAction())
}

// StorageObjects limits what storage objects can be accessed. Objects are
// identified by a URL prefix string, so you can specify just the storage
// provider (e.g. `https://storage.fly/`), a specific bucket within a storage
// provider (e.g. `https://storage.fly/my_bucket`), or a object within a bucket
// (e.g. `https://storage.fly/my_bucket/my_file`).
type StorageObjects struct {
Prefixes resset.ResourceSet[resset.Prefix] `json:"storage_objects"`
}

func init() {
macaroon.RegisterCaveatType(&StorageObjects{})
}

func (c *StorageObjects) CaveatType() macaroon.CaveatType { return CavStorageObjects }
func (c *StorageObjects) Name() string { return "StorageObjects" }

func (c *StorageObjects) Prohibits(a macaroon.Access) error {
f, isFlyioAccess := a.(StorageObjectGetter)
if !isFlyioAccess {
return fmt.Errorf("%w: access isnt StorageObjectGetter", macaroon.ErrInvalidAccess)
}
return c.Prefixes.Prohibits(f.GetStorageObject(), f.GetAction())
}

0 comments on commit fecb31e

Please sign in to comment.