177 lines
7.1 KiB
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)
|
|
}
|