/
external_service.go
161 lines (138 loc) · 5.11 KB
/
external_service.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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
package oauthserver
import (
"context"
"strconv"
"strings"
"github.com/ory/fosite"
ac "github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/user"
)
type KeyResult struct {
URL string `json:"url,omitempty"`
PrivatePem string `json:"private,omitempty"`
PublicPem string `json:"public,omitempty"`
Generated bool `json:"generated,omitempty"`
}
type ExternalServiceDTO struct {
Name string `json:"name"`
ID string `json:"clientId"`
Secret string `json:"clientSecret"`
RedirectURI string `json:"redirectUri,omitempty"` // Not used yet (code flow)
GrantTypes string `json:"grantTypes"` // CSV value
Audiences string `json:"audiences"` // CSV value
KeyResult *KeyResult `json:"key,omitempty"`
}
type ExternalService struct {
ID int64 `xorm:"id pk autoincr"`
Name string `xorm:"name"`
ClientID string `xorm:"client_id"`
Secret string `xorm:"secret"`
RedirectURI string `xorm:"redirect_uri"` // Not used yet (code flow)
GrantTypes string `xorm:"grant_types"` // CSV value
Audiences string `xorm:"audiences"` // CSV value
PublicPem []byte `xorm:"public_pem"`
ServiceAccountID int64 `xorm:"service_account_id"`
// SelfPermissions are the registered service account permissions (registered and managed permissions)
SelfPermissions []ac.Permission
// ImpersonatePermissions is the restriction set of permissions while impersonating
ImpersonatePermissions []ac.Permission
// SignedInUser refers to the current Service Account identity/user
SignedInUser *user.SignedInUser
Scopes []string
ImpersonateScopes []string
}
func (c *ExternalService) ToDTO() *ExternalServiceDTO {
c2 := ExternalServiceDTO{
Name: c.Name,
ID: c.ClientID,
Secret: c.Secret,
GrantTypes: c.GrantTypes,
Audiences: c.Audiences,
RedirectURI: c.RedirectURI,
}
if len(c.PublicPem) > 0 {
c2.KeyResult = &KeyResult{PublicPem: string(c.PublicPem)}
}
return &c2
}
func (c *ExternalService) LogID() string {
return "{name: " + c.Name + ", clientID: " + c.ClientID + "}"
}
// GetID returns the client ID.
func (c *ExternalService) GetID() string { return c.ClientID }
// GetHashedSecret returns the hashed secret as it is stored in the store.
func (c *ExternalService) GetHashedSecret() []byte {
// Hashed version is stored in the secret field
return []byte(c.Secret)
}
// GetRedirectURIs returns the client's allowed redirect URIs.
func (c *ExternalService) GetRedirectURIs() []string {
return []string{c.RedirectURI}
}
// GetGrantTypes returns the client's allowed grant types.
func (c *ExternalService) GetGrantTypes() fosite.Arguments {
return strings.Split(c.GrantTypes, ",")
}
// GetResponseTypes returns the client's allowed response types.
// All allowed combinations of response types have to be listed, each combination having
// response types of the combination separated by a space.
func (c *ExternalService) GetResponseTypes() fosite.Arguments {
return fosite.Arguments{"code"}
}
// GetScopes returns the scopes this client is allowed to request on its own behalf.
func (c *ExternalService) GetScopes() fosite.Arguments {
if c.Scopes != nil {
return c.Scopes
}
ret := []string{"profile", "email", "groups", "entitlements"}
if c.SignedInUser != nil && c.SignedInUser.Permissions != nil {
perms := c.SignedInUser.Permissions[TmpOrgID]
for action := range perms {
// Add all actions that the plugin is allowed to request
ret = append(ret, action)
}
}
c.Scopes = ret
return ret
}
// GetScopes returns the scopes this client is allowed to request on a specific user.
func (c *ExternalService) GetScopesOnUser(ctx context.Context, accessControl ac.AccessControl, userID int64) []string {
ev := ac.EvalPermission(ac.ActionUsersImpersonate, ac.Scope("users", "id", strconv.FormatInt(userID, 10)))
hasAccess, errAccess := accessControl.Evaluate(ctx, c.SignedInUser, ev)
if errAccess != nil || !hasAccess {
return nil
}
if c.ImpersonateScopes != nil {
return c.ImpersonateScopes
}
ret := []string{}
if c.ImpersonatePermissions != nil {
perms := c.ImpersonatePermissions
for i := range perms {
if perms[i].Action == ac.ActionUsersRead && perms[i].Scope == ScopeGlobalUsersSelf {
ret = append(ret, "profile", "email", ac.ActionUsersRead)
continue
}
if perms[i].Action == ac.ActionUsersPermissionsRead && perms[i].Scope == ScopeUsersSelf {
ret = append(ret, "entitlements", ac.ActionUsersPermissionsRead)
continue
}
if perms[i].Action == ac.ActionTeamsRead && perms[i].Scope == ScopeTeamsSelf {
ret = append(ret, "groups", ac.ActionTeamsRead)
continue
}
// Add all actions that the plugin is allowed to request
ret = append(ret, perms[i].Action)
}
}
c.ImpersonateScopes = ret
return ret
}
// IsPublic returns true, if this client is marked as public.
func (c *ExternalService) IsPublic() bool {
return false
}
// GetAudience returns the allowed audience(s) for this client.
func (c *ExternalService) GetAudience() fosite.Arguments {
return strings.Split(c.Audiences, ",")
}