-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathauthz.go
112 lines (92 loc) · 2.48 KB
/
authz.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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"regexp"
"github.com/pkg/errors"
)
type authzUser struct {
UserID string `json:"user_id"`
Role string `json:"role"`
rolePtr *authzRole
}
func (x *authzUser) permitted() []string {
return x.rolePtr.PermittedTags
}
type authzRole struct {
Name string `json:"name"`
PermittedTags []string `json:"permitted_tags"`
}
type authzRule struct {
UserRegex string `json:"user_regex"`
Role string `json:"role"`
regex *regexp.Regexp
rolePtr *authzRole
}
type authzService struct {
Users []*authzUser `json:"users"`
Roles []*authzRole `json:"roles"`
Rules []*authzRule `json:"rules"`
UserMap map[string]*authzUser
RoleMap map[string]*authzRole
}
func newAuthzServiceFromFile(filePath string) (*authzService, error) {
raw, err := ioutil.ReadFile(filePath)
if err != nil {
return nil, errors.Wrapf(err, "Fail to load authz file: %s", filePath)
}
return newAuthzService(raw)
}
func newAuthzService(raw []byte) (*authzService, error) {
var srv authzService
if err := json.Unmarshal(raw, &srv); err != nil {
return nil, errors.Wrapf(err, "Fail to parse authz data json: %s", string(raw))
}
srv.UserMap = map[string]*authzUser{}
srv.RoleMap = map[string]*authzRole{}
for _, r := range srv.Roles {
if _, ok := srv.RoleMap[r.Name]; ok {
return nil, fmt.Errorf("Role '%s' is duplicated", r.Name)
}
srv.RoleMap[r.Name] = r
}
for _, u := range srv.Users {
if _, ok := srv.UserMap[u.UserID]; ok {
return nil, fmt.Errorf("User '%s' is duplicated", u.UserID)
}
role, ok := srv.RoleMap[u.Role]
if !ok {
return nil, fmt.Errorf("Role '%s' of User '%s' is not found", u.Role, u.UserID)
}
u.rolePtr = role
srv.UserMap[u.UserID] = u
}
for _, rule := range srv.Rules {
role, ok := srv.RoleMap[rule.Role]
if !ok {
return nil, fmt.Errorf("Role '%s' of Rule '%s' is not found", rule.Role, rule.UserRegex)
}
rule.rolePtr = role
ptn, err := regexp.Compile(rule.UserRegex)
if err != nil {
return nil, fmt.Errorf("Fail to compile regex of a rule: %s", rule.UserRegex)
}
rule.regex = ptn
}
logger.WithField("authz", srv).Info("Read authorization table")
return &srv, nil
}
func (x *authzService) lookup(userID string) *authzUser {
user, ok := x.UserMap[userID]
if !ok {
for _, rule := range x.Rules {
if rule.regex.MatchString(userID) {
newUser := &authzUser{UserID: userID, rolePtr: rule.rolePtr}
x.UserMap[userID] = newUser
return newUser
}
}
}
return user
}