1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package client
16
17 import (
18 "bytes"
19 "context"
20 "encoding/json"
21 "net/http"
22 "net/url"
23 )
24
25 type Role struct {
26 Role string `json:"role"`
27 Permissions Permissions `json:"permissions"`
28 Grant *Permissions `json:"grant,omitempty"`
29 Revoke *Permissions `json:"revoke,omitempty"`
30 }
31
32 type Permissions struct {
33 KV rwPermission `json:"kv"`
34 }
35
36 type rwPermission struct {
37 Read []string `json:"read"`
38 Write []string `json:"write"`
39 }
40
41 type PermissionType int
42
43 const (
44 ReadPermission PermissionType = iota
45 WritePermission
46 ReadWritePermission
47 )
48
49
50
51 func NewAuthRoleAPI(c Client) AuthRoleAPI {
52 return &httpAuthRoleAPI{
53 client: c,
54 }
55 }
56
57 type AuthRoleAPI interface {
58
59 AddRole(ctx context.Context, role string) error
60
61
62 RemoveRole(ctx context.Context, role string) error
63
64
65 GetRole(ctx context.Context, role string) (*Role, error)
66
67
68 GrantRoleKV(ctx context.Context, role string, prefixes []string, permType PermissionType) (*Role, error)
69
70
71 RevokeRoleKV(ctx context.Context, role string, prefixes []string, permType PermissionType) (*Role, error)
72
73
74 ListRoles(ctx context.Context) ([]string, error)
75 }
76
77 type httpAuthRoleAPI struct {
78 client httpClient
79 }
80
81 type authRoleAPIAction struct {
82 verb string
83 name string
84 role *Role
85 }
86
87 type authRoleAPIList struct{}
88
89 func (list *authRoleAPIList) HTTPRequest(ep url.URL) *http.Request {
90 u := v2AuthURL(ep, "roles", "")
91 req, _ := http.NewRequest("GET", u.String(), nil)
92 req.Header.Set("Content-Type", "application/json")
93 return req
94 }
95
96 func (l *authRoleAPIAction) HTTPRequest(ep url.URL) *http.Request {
97 u := v2AuthURL(ep, "roles", l.name)
98 if l.role == nil {
99 req, _ := http.NewRequest(l.verb, u.String(), nil)
100 return req
101 }
102 b, err := json.Marshal(l.role)
103 if err != nil {
104 panic(err)
105 }
106 body := bytes.NewReader(b)
107 req, _ := http.NewRequest(l.verb, u.String(), body)
108 req.Header.Set("Content-Type", "application/json")
109 return req
110 }
111
112 func (r *httpAuthRoleAPI) ListRoles(ctx context.Context) ([]string, error) {
113 resp, body, err := r.client.Do(ctx, &authRoleAPIList{})
114 if err != nil {
115 return nil, err
116 }
117 if err = assertStatusCode(resp.StatusCode, http.StatusOK); err != nil {
118 return nil, err
119 }
120 var roleList struct {
121 Roles []Role `json:"roles"`
122 }
123 if err = json.Unmarshal(body, &roleList); err != nil {
124 return nil, err
125 }
126 ret := make([]string, 0, len(roleList.Roles))
127 for _, r := range roleList.Roles {
128 ret = append(ret, r.Role)
129 }
130 return ret, nil
131 }
132
133 func (r *httpAuthRoleAPI) AddRole(ctx context.Context, rolename string) error {
134 role := &Role{
135 Role: rolename,
136 }
137 return r.addRemoveRole(ctx, &authRoleAPIAction{
138 verb: "PUT",
139 name: rolename,
140 role: role,
141 })
142 }
143
144 func (r *httpAuthRoleAPI) RemoveRole(ctx context.Context, rolename string) error {
145 return r.addRemoveRole(ctx, &authRoleAPIAction{
146 verb: "DELETE",
147 name: rolename,
148 })
149 }
150
151 func (r *httpAuthRoleAPI) addRemoveRole(ctx context.Context, req *authRoleAPIAction) error {
152 resp, body, err := r.client.Do(ctx, req)
153 if err != nil {
154 return err
155 }
156 if err := assertStatusCode(resp.StatusCode, http.StatusOK, http.StatusCreated); err != nil {
157 var sec authError
158 err := json.Unmarshal(body, &sec)
159 if err != nil {
160 return err
161 }
162 return sec
163 }
164 return nil
165 }
166
167 func (r *httpAuthRoleAPI) GetRole(ctx context.Context, rolename string) (*Role, error) {
168 return r.modRole(ctx, &authRoleAPIAction{
169 verb: "GET",
170 name: rolename,
171 })
172 }
173
174 func buildRWPermission(prefixes []string, permType PermissionType) rwPermission {
175 var out rwPermission
176 switch permType {
177 case ReadPermission:
178 out.Read = prefixes
179 case WritePermission:
180 out.Write = prefixes
181 case ReadWritePermission:
182 out.Read = prefixes
183 out.Write = prefixes
184 }
185 return out
186 }
187
188 func (r *httpAuthRoleAPI) GrantRoleKV(ctx context.Context, rolename string, prefixes []string, permType PermissionType) (*Role, error) {
189 rwp := buildRWPermission(prefixes, permType)
190 role := &Role{
191 Role: rolename,
192 Grant: &Permissions{
193 KV: rwp,
194 },
195 }
196 return r.modRole(ctx, &authRoleAPIAction{
197 verb: "PUT",
198 name: rolename,
199 role: role,
200 })
201 }
202
203 func (r *httpAuthRoleAPI) RevokeRoleKV(ctx context.Context, rolename string, prefixes []string, permType PermissionType) (*Role, error) {
204 rwp := buildRWPermission(prefixes, permType)
205 role := &Role{
206 Role: rolename,
207 Revoke: &Permissions{
208 KV: rwp,
209 },
210 }
211 return r.modRole(ctx, &authRoleAPIAction{
212 verb: "PUT",
213 name: rolename,
214 role: role,
215 })
216 }
217
218 func (r *httpAuthRoleAPI) modRole(ctx context.Context, req *authRoleAPIAction) (*Role, error) {
219 resp, body, err := r.client.Do(ctx, req)
220 if err != nil {
221 return nil, err
222 }
223 if err = assertStatusCode(resp.StatusCode, http.StatusOK); err != nil {
224 var sec authError
225 err = json.Unmarshal(body, &sec)
226 if err != nil {
227 return nil, err
228 }
229 return nil, sec
230 }
231 var role Role
232 if err = json.Unmarshal(body, &role); err != nil {
233 return nil, err
234 }
235 return &role, nil
236 }
237
View as plain text