influxdb/authorizer/authorize.go

177 lines
7.1 KiB
Go

package authorizer
import (
"context"
"fmt"
"github.com/influxdata/influxdb/v2"
icontext "github.com/influxdata/influxdb/v2/context"
"github.com/influxdata/influxdb/v2/kit/platform"
"github.com/influxdata/influxdb/v2/kit/platform/errors"
)
func isAllowedAll(a influxdb.Authorizer, permissions []influxdb.Permission) error {
pset, err := a.PermissionSet()
if err != nil {
return err
}
for _, p := range permissions {
if !pset.Allowed(p) {
return &errors.Error{
Code: errors.EUnauthorized,
Msg: fmt.Sprintf("%s is unauthorized", p),
}
}
}
return nil
}
func isAllowed(a influxdb.Authorizer, p influxdb.Permission) error {
return isAllowedAll(a, []influxdb.Permission{p})
}
// IsAllowedAll checks to see if an action is authorized by ALL permissions.
// Also see IsAllowed.
func IsAllowedAll(ctx context.Context, permissions []influxdb.Permission) error {
a, err := icontext.GetAuthorizer(ctx)
if err != nil {
return err
}
return isAllowedAll(a, permissions)
}
// IsAllowed checks to see if an action is authorized by retrieving the authorizer
// off of context and authorizing the action appropriately.
func IsAllowed(ctx context.Context, p influxdb.Permission) error {
return IsAllowedAll(ctx, []influxdb.Permission{p})
}
// IsAllowedAny checks to see if an action is authorized by ANY permissions.
// Also see IsAllowed.
func IsAllowedAny(ctx context.Context, permissions []influxdb.Permission) error {
a, err := icontext.GetAuthorizer(ctx)
if err != nil {
return err
}
pset, err := a.PermissionSet()
if err != nil {
return err
}
for _, p := range permissions {
if pset.Allowed(p) {
return nil
}
}
return &errors.Error{
Code: errors.EUnauthorized,
Msg: fmt.Sprintf("none of %v is authorized", permissions),
}
}
func authorize(ctx context.Context, a influxdb.Action, rt influxdb.ResourceType, rid, oid *platform.ID) (influxdb.Authorizer, influxdb.Permission, error) {
var p *influxdb.Permission
var err error
if rid != nil && oid != nil {
p, err = influxdb.NewPermissionAtID(*rid, a, rt, *oid)
} else if rid != nil {
p, err = influxdb.NewResourcePermission(a, rt, *rid)
} else if oid != nil {
p, err = influxdb.NewPermission(a, rt, *oid)
} else {
p, err = influxdb.NewGlobalPermission(a, rt)
}
if err != nil {
return nil, influxdb.Permission{}, err
}
auth, err := icontext.GetAuthorizer(ctx)
if err != nil {
return nil, influxdb.Permission{}, err
}
return auth, *p, isAllowed(auth, *p)
}
func authorizeReadSystemBucket(ctx context.Context, bid, oid platform.ID) (influxdb.Authorizer, influxdb.Permission, error) {
return AuthorizeReadOrg(ctx, oid)
}
// AuthorizeReadBucket exists because buckets are a special case and should use this method.
// I.e., instead of:
//
// AuthorizeRead(ctx, influxdb.BucketsResourceType, b.ID, b.OrgID)
//
// use:
//
// AuthorizeReadBucket(ctx, b.Type, b.ID, b.OrgID)
func AuthorizeReadBucket(ctx context.Context, bt influxdb.BucketType, bid, oid platform.ID) (influxdb.Authorizer, influxdb.Permission, error) {
switch bt {
case influxdb.BucketTypeSystem:
return authorizeReadSystemBucket(ctx, bid, oid)
default:
return AuthorizeRead(ctx, influxdb.BucketsResourceType, bid, oid)
}
}
// AuthorizeRead authorizes the user in the context to read the specified resource (identified by its type, ID, and orgID).
// NOTE: authorization will pass even if the user only has permissions for the resource type and organization ID only.
func AuthorizeRead(ctx context.Context, rt influxdb.ResourceType, rid, oid platform.ID) (influxdb.Authorizer, influxdb.Permission, error) {
return authorize(ctx, influxdb.ReadAction, rt, &rid, &oid)
}
// AuthorizeWrite authorizes the user in the context to write the specified resource (identified by its type, ID, and orgID).
// NOTE: authorization will pass even if the user only has permissions for the resource type and organization ID only.
func AuthorizeWrite(ctx context.Context, rt influxdb.ResourceType, rid, oid platform.ID) (influxdb.Authorizer, influxdb.Permission, error) {
return authorize(ctx, influxdb.WriteAction, rt, &rid, &oid)
}
// AuthorizeRead authorizes the user in the context to read the specified resource (identified by its type, ID).
// NOTE: authorization will pass only if the user has a specific permission for the given resource.
func AuthorizeReadResource(ctx context.Context, rt influxdb.ResourceType, rid platform.ID) (influxdb.Authorizer, influxdb.Permission, error) {
return authorize(ctx, influxdb.ReadAction, rt, &rid, nil)
}
// AuthorizeWrite authorizes the user in the context to write the specified resource (identified by its type, ID).
// NOTE: authorization will pass only if the user has a specific permission for the given resource.
func AuthorizeWriteResource(ctx context.Context, rt influxdb.ResourceType, rid platform.ID) (influxdb.Authorizer, influxdb.Permission, error) {
return authorize(ctx, influxdb.WriteAction, rt, &rid, nil)
}
// AuthorizeOrgReadResource authorizes the given org to read the resources of the given type.
// NOTE: this is pretty much the same as AuthorizeRead, in the case that the resource ID is ignored.
// Use it in the case that you do not know which resource in particular you want to give access to.
func AuthorizeOrgReadResource(ctx context.Context, rt influxdb.ResourceType, oid platform.ID) (influxdb.Authorizer, influxdb.Permission, error) {
return authorize(ctx, influxdb.ReadAction, rt, nil, &oid)
}
// AuthorizeOrgWriteResource authorizes the given org to write the resources of the given type.
// NOTE: this is pretty much the same as AuthorizeWrite, in the case that the resource ID is ignored.
// Use it in the case that you do not know which resource in particular you want to give access to.
func AuthorizeOrgWriteResource(ctx context.Context, rt influxdb.ResourceType, oid platform.ID) (influxdb.Authorizer, influxdb.Permission, error) {
return authorize(ctx, influxdb.WriteAction, rt, nil, &oid)
}
// AuthorizeCreate authorizes a user to create a resource of the given type for the given org.
func AuthorizeCreate(ctx context.Context, rt influxdb.ResourceType, oid platform.ID) (influxdb.Authorizer, influxdb.Permission, error) {
return AuthorizeOrgWriteResource(ctx, rt, oid)
}
// AuthorizeReadOrg authorizes the user to read the given org.
func AuthorizeReadOrg(ctx context.Context, oid platform.ID) (influxdb.Authorizer, influxdb.Permission, error) {
return authorize(ctx, influxdb.ReadAction, influxdb.OrgsResourceType, &oid, nil)
}
// AuthorizeWriteOrg authorizes the user to write the given org.
func AuthorizeWriteOrg(ctx context.Context, oid platform.ID) (influxdb.Authorizer, influxdb.Permission, error) {
return authorize(ctx, influxdb.WriteAction, influxdb.OrgsResourceType, &oid, nil)
}
// AuthorizeReadGlobal authorizes to read resources of the given type.
func AuthorizeReadGlobal(ctx context.Context, rt influxdb.ResourceType) (influxdb.Authorizer, influxdb.Permission, error) {
return authorize(ctx, influxdb.ReadAction, rt, nil, nil)
}
// AuthorizeWriteGlobal authorizes to write resources of the given type.
func AuthorizeWriteGlobal(ctx context.Context, rt influxdb.ResourceType) (influxdb.Authorizer, influxdb.Permission, error) {
return authorize(ctx, influxdb.WriteAction, rt, nil, nil)
}