forked from juju/juju
/
fakeauthorizer.go
137 lines (121 loc) · 3.86 KB
/
fakeauthorizer.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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
// Copyright 2013 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.
package testing
import (
"strings"
"gopkg.in/juju/names.v2"
"github.com/juju/juju/permission"
)
// FakeAuthorizer implements the facade.Authorizer interface.
type FakeAuthorizer struct {
Tag names.Tag
Controller bool
ModelUUID string
AdminTag names.UserTag
HasWriteTag names.UserTag
}
func (fa FakeAuthorizer) AuthOwner(tag names.Tag) bool {
return fa.Tag == tag
}
func (fa FakeAuthorizer) AuthController() bool {
return fa.Controller
}
// AuthMachineAgent returns whether the current client is a machine agent.
func (fa FakeAuthorizer) AuthMachineAgent() bool {
_, isMachine := fa.GetAuthTag().(names.MachineTag)
return isMachine
}
// AuthUnitAgent returns whether the current client is a unit agent.
func (fa FakeAuthorizer) AuthUnitAgent() bool {
_, isUnit := fa.GetAuthTag().(names.UnitTag)
return isUnit
}
// AuthClient returns whether the authenticated entity is a client
// user.
func (fa FakeAuthorizer) AuthClient() bool {
_, isUser := fa.GetAuthTag().(names.UserTag)
return isUser
}
func (fa FakeAuthorizer) GetAuthTag() names.Tag {
return fa.Tag
}
// HasPermission returns true if the logged in user is admin or has a name equal to
// the pre-set admin tag.
func (fa FakeAuthorizer) HasPermission(operation permission.Access, target names.Tag) (bool, error) {
if fa.Tag.Kind() == names.UserTagKind {
ut := fa.Tag.(names.UserTag)
emptyTag := names.UserTag{}
if fa.AdminTag != emptyTag && ut == fa.AdminTag {
return true, nil
}
if operation == permission.WriteAccess && ut == fa.HasWriteTag {
return true, nil
}
uTag := fa.Tag.(names.UserTag)
return nameBasedHasPermission(uTag.Name(), operation, target), nil
}
return false, nil
}
// nameBasedHasPermission provides a way for tests to fake the expected outcomes of the
// authentication.
// setting permissionname as the name that user will always have the given permission.
// setting permissionnamemodeltagstring as the name will make that user have the given
// permission only in that model.
func nameBasedHasPermission(name string, operation permission.Access, target names.Tag) bool {
var perm permission.Access
switch {
case strings.HasPrefix(name, string(permission.SuperuserAccess)):
return operation == permission.SuperuserAccess
case strings.HasPrefix(name, string(permission.AddModelAccess)):
return operation == permission.AddModelAccess
case strings.HasPrefix(name, string(permission.LoginAccess)):
return operation == permission.LoginAccess
case strings.HasPrefix(name, string(permission.AdminAccess)):
perm = permission.AdminAccess
case strings.HasPrefix(name, string(permission.WriteAccess)):
perm = permission.WriteAccess
case strings.HasPrefix(name, string(permission.ReadAccess)):
perm = permission.ReadAccess
default:
return false
}
name = name[len(perm):]
if len(name) == 0 && perm == permission.AdminAccess {
return true
}
if len(name) == 0 {
return operation == perm
}
if target.Kind() != names.ModelTagKind {
return false
}
if names.IsValidModel(name) {
newTarget, err := names.ParseModelTag(name)
if err != nil {
return false
}
return operation == perm && newTarget == target.(names.ModelTag)
}
return false
}
// ConnectedModel returns the UUID of the model the current client is
// connected to.
func (fa FakeAuthorizer) ConnectedModel() string {
return fa.ModelUUID
}
// UserHasPermission returns true if the passed user is admin or has a name equal to
// the pre-set admin tag.
func (fa FakeAuthorizer) UserHasPermission(user names.UserTag, operation permission.Access, target names.Tag) (bool, error) {
if user.Name() == "admin" {
return true, nil
}
emptyTag := names.UserTag{}
if fa.AdminTag != emptyTag && user == fa.AdminTag {
return true, nil
}
ut := fa.Tag.(names.UserTag)
if ut == user {
return true, nil
}
return false, nil
}