/
authorization.go
85 lines (67 loc) · 2.43 KB
/
authorization.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
package auth
import (
"context"
"fmt"
"net/http"
"github.com/openfga/openfga/pkg/storage"
"github.com/canonical/lxd/lxd/identity"
"github.com/canonical/lxd/shared/api"
"github.com/canonical/lxd/shared/entity"
"github.com/canonical/lxd/shared/logger"
)
var authorizers = map[string]func() authorizer{}
// ErrUnknownDriver is the "Unknown driver" error.
var ErrUnknownDriver = fmt.Errorf("Unknown driver")
type authorizer interface {
Authorizer
init(driverName string, logger logger.Logger) error
load(ctx context.Context, certificateCache *identity.Cache, opts Opts) error
}
// PermissionChecker is a type alias for a function that returns whether a user has required permissions on an object.
// It is returned by Authorizer.GetPermissionChecker.
type PermissionChecker func(entityURL *api.URL) bool
// Authorizer is the primary external API for this package.
type Authorizer interface {
Driver() string
CheckPermission(ctx context.Context, r *http.Request, entityURL *api.URL, entitlement Entitlement) error
GetPermissionChecker(ctx context.Context, r *http.Request, entitlement Entitlement, entityType entity.Type) (PermissionChecker, error)
}
// Opts is used as part of the LoadAuthorizer function so that only the relevant configuration fields are passed into a
// particular driver.
type Opts struct {
config map[string]any
openfgaDatastore storage.OpenFGADatastore
}
// WithConfig can be passed into LoadAuthorizer to pass in driver specific configuration.
func WithConfig(c map[string]any) func(*Opts) {
return func(o *Opts) {
o.config = c
}
}
// WithOpenFGADatastore should be passed into LoadAuthorizer when using the embedded openfga driver.
func WithOpenFGADatastore(store storage.OpenFGADatastore) func(*Opts) {
return func(o *Opts) {
o.openfgaDatastore = store
}
}
// LoadAuthorizer instantiates, configures, and initialises an Authorizer.
func LoadAuthorizer(ctx context.Context, driver string, logger logger.Logger, certificateCache *identity.Cache, options ...func(opts *Opts)) (Authorizer, error) {
opts := &Opts{}
for _, o := range options {
o(opts)
}
driverFunc, ok := authorizers[driver]
if !ok {
return nil, ErrUnknownDriver
}
d := driverFunc()
err := d.init(driver, logger)
if err != nil {
return nil, fmt.Errorf("Failed to initialize authorizer: %w", err)
}
err = d.load(ctx, certificateCache, *opts)
if err != nil {
return nil, fmt.Errorf("Failed to load authorizer: %w", err)
}
return d, nil
}