blob: 124409ff2b74f776c27d5a2cc9e2e5d314a701de [file] [log] [blame]
William Kurkianea869482019-04-09 15:16:11 -04001package api
2
3import (
4 "fmt"
5 "io"
6 "io/ioutil"
Abhilash S.L3b494632019-07-16 15:51:09 +05307 "net/url"
William Kurkianea869482019-04-09 15:16:11 -04008 "time"
Abhilash S.L3b494632019-07-16 15:51:09 +05309
10 "github.com/mitchellh/mapstructure"
William Kurkianea869482019-04-09 15:16:11 -040011)
12
13const (
14 // ACLClientType is the client type token
15 ACLClientType = "client"
16
17 // ACLManagementType is the management type token
18 ACLManagementType = "management"
19)
20
21type ACLTokenPolicyLink struct {
22 ID string
23 Name string
24}
Abhilash S.L3b494632019-07-16 15:51:09 +053025type ACLTokenRoleLink struct {
26 ID string
27 Name string
28}
William Kurkianea869482019-04-09 15:16:11 -040029
30// ACLToken represents an ACL Token
31type ACLToken struct {
Abhilash S.L3b494632019-07-16 15:51:09 +053032 CreateIndex uint64
33 ModifyIndex uint64
34 AccessorID string
35 SecretID string
36 Description string
37 Policies []*ACLTokenPolicyLink `json:",omitempty"`
38 Roles []*ACLTokenRoleLink `json:",omitempty"`
39 ServiceIdentities []*ACLServiceIdentity `json:",omitempty"`
40 Local bool
41 ExpirationTTL time.Duration `json:",omitempty"`
42 ExpirationTime *time.Time `json:",omitempty"`
43 CreateTime time.Time `json:",omitempty"`
44 Hash []byte `json:",omitempty"`
William Kurkianea869482019-04-09 15:16:11 -040045
46 // DEPRECATED (ACL-Legacy-Compat)
47 // Rules will only be present for legacy tokens returned via the new APIs
48 Rules string `json:",omitempty"`
49}
50
51type ACLTokenListEntry struct {
Abhilash S.L3b494632019-07-16 15:51:09 +053052 CreateIndex uint64
53 ModifyIndex uint64
54 AccessorID string
55 Description string
56 Policies []*ACLTokenPolicyLink `json:",omitempty"`
57 Roles []*ACLTokenRoleLink `json:",omitempty"`
58 ServiceIdentities []*ACLServiceIdentity `json:",omitempty"`
59 Local bool
60 ExpirationTime *time.Time `json:",omitempty"`
61 CreateTime time.Time
62 Hash []byte
63 Legacy bool
William Kurkianea869482019-04-09 15:16:11 -040064}
65
66// ACLEntry is used to represent a legacy ACL token
67// The legacy tokens are deprecated.
68type ACLEntry struct {
69 CreateIndex uint64
70 ModifyIndex uint64
71 ID string
72 Name string
73 Type string
74 Rules string
75}
76
77// ACLReplicationStatus is used to represent the status of ACL replication.
78type ACLReplicationStatus struct {
79 Enabled bool
80 Running bool
81 SourceDatacenter string
82 ReplicationType string
83 ReplicatedIndex uint64
Abhilash S.L3b494632019-07-16 15:51:09 +053084 ReplicatedRoleIndex uint64
William Kurkianea869482019-04-09 15:16:11 -040085 ReplicatedTokenIndex uint64
86 LastSuccess time.Time
87 LastError time.Time
88}
89
Abhilash S.L3b494632019-07-16 15:51:09 +053090// ACLServiceIdentity represents a high-level grant of all necessary privileges
91// to assume the identity of the named Service in the Catalog and within
92// Connect.
93type ACLServiceIdentity struct {
94 ServiceName string
95 Datacenters []string `json:",omitempty"`
96}
97
William Kurkianea869482019-04-09 15:16:11 -040098// ACLPolicy represents an ACL Policy.
99type ACLPolicy struct {
100 ID string
101 Name string
102 Description string
103 Rules string
104 Datacenters []string
105 Hash []byte
106 CreateIndex uint64
107 ModifyIndex uint64
108}
109
110type ACLPolicyListEntry struct {
111 ID string
112 Name string
113 Description string
114 Datacenters []string
115 Hash []byte
116 CreateIndex uint64
117 ModifyIndex uint64
118}
119
Abhilash S.L3b494632019-07-16 15:51:09 +0530120type ACLRolePolicyLink struct {
121 ID string
122 Name string
123}
124
125// ACLRole represents an ACL Role.
126type ACLRole struct {
127 ID string
128 Name string
129 Description string
130 Policies []*ACLRolePolicyLink `json:",omitempty"`
131 ServiceIdentities []*ACLServiceIdentity `json:",omitempty"`
132 Hash []byte
133 CreateIndex uint64
134 ModifyIndex uint64
135}
136
137// BindingRuleBindType is the type of binding rule mechanism used.
138type BindingRuleBindType string
139
140const (
141 // BindingRuleBindTypeService binds to a service identity with the given name.
142 BindingRuleBindTypeService BindingRuleBindType = "service"
143
144 // BindingRuleBindTypeRole binds to pre-existing roles with the given name.
145 BindingRuleBindTypeRole BindingRuleBindType = "role"
146)
147
148type ACLBindingRule struct {
149 ID string
150 Description string
151 AuthMethod string
152 Selector string
153 BindType BindingRuleBindType
154 BindName string
155
156 CreateIndex uint64
157 ModifyIndex uint64
158}
159
160type ACLAuthMethod struct {
161 Name string
162 Type string
163 Description string
164
165 // Configuration is arbitrary configuration for the auth method. This
166 // should only contain primitive values and containers (such as lists and
167 // maps).
168 Config map[string]interface{}
169
170 CreateIndex uint64
171 ModifyIndex uint64
172}
173
174type ACLAuthMethodListEntry struct {
175 Name string
176 Type string
177 Description string
178 CreateIndex uint64
179 ModifyIndex uint64
180}
181
182// ParseKubernetesAuthMethodConfig takes a raw config map and returns a parsed
183// KubernetesAuthMethodConfig.
184func ParseKubernetesAuthMethodConfig(raw map[string]interface{}) (*KubernetesAuthMethodConfig, error) {
185 var config KubernetesAuthMethodConfig
186 decodeConf := &mapstructure.DecoderConfig{
187 Result: &config,
188 WeaklyTypedInput: true,
189 }
190
191 decoder, err := mapstructure.NewDecoder(decodeConf)
192 if err != nil {
193 return nil, err
194 }
195
196 if err := decoder.Decode(raw); err != nil {
197 return nil, fmt.Errorf("error decoding config: %s", err)
198 }
199
200 return &config, nil
201}
202
203// KubernetesAuthMethodConfig is the config for the built-in Consul auth method
204// for Kubernetes.
205type KubernetesAuthMethodConfig struct {
206 Host string `json:",omitempty"`
207 CACert string `json:",omitempty"`
208 ServiceAccountJWT string `json:",omitempty"`
209}
210
211// RenderToConfig converts this into a map[string]interface{} suitable for use
212// in the ACLAuthMethod.Config field.
213func (c *KubernetesAuthMethodConfig) RenderToConfig() map[string]interface{} {
214 return map[string]interface{}{
215 "Host": c.Host,
216 "CACert": c.CACert,
217 "ServiceAccountJWT": c.ServiceAccountJWT,
218 }
219}
220
221type ACLLoginParams struct {
222 AuthMethod string
223 BearerToken string
224 Meta map[string]string `json:",omitempty"`
225}
226
William Kurkianea869482019-04-09 15:16:11 -0400227// ACL can be used to query the ACL endpoints
228type ACL struct {
229 c *Client
230}
231
232// ACL returns a handle to the ACL endpoints
233func (c *Client) ACL() *ACL {
234 return &ACL{c}
235}
236
237// Bootstrap is used to perform a one-time ACL bootstrap operation on a cluster
238// to get the first management token.
239func (a *ACL) Bootstrap() (*ACLToken, *WriteMeta, error) {
240 r := a.c.newRequest("PUT", "/v1/acl/bootstrap")
241 rtt, resp, err := requireOK(a.c.doRequest(r))
242 if err != nil {
243 return nil, nil, err
244 }
245 defer resp.Body.Close()
246
247 wm := &WriteMeta{RequestTime: rtt}
248 var out ACLToken
249 if err := decodeBody(resp, &out); err != nil {
250 return nil, nil, err
251 }
252 return &out, wm, nil
253}
254
255// Create is used to generate a new token with the given parameters
256//
257// Deprecated: Use TokenCreate instead.
258func (a *ACL) Create(acl *ACLEntry, q *WriteOptions) (string, *WriteMeta, error) {
259 r := a.c.newRequest("PUT", "/v1/acl/create")
260 r.setWriteOptions(q)
261 r.obj = acl
262 rtt, resp, err := requireOK(a.c.doRequest(r))
263 if err != nil {
264 return "", nil, err
265 }
266 defer resp.Body.Close()
267
268 wm := &WriteMeta{RequestTime: rtt}
269 var out struct{ ID string }
270 if err := decodeBody(resp, &out); err != nil {
271 return "", nil, err
272 }
273 return out.ID, wm, nil
274}
275
276// Update is used to update the rules of an existing token
277//
278// Deprecated: Use TokenUpdate instead.
279func (a *ACL) Update(acl *ACLEntry, q *WriteOptions) (*WriteMeta, error) {
280 r := a.c.newRequest("PUT", "/v1/acl/update")
281 r.setWriteOptions(q)
282 r.obj = acl
283 rtt, resp, err := requireOK(a.c.doRequest(r))
284 if err != nil {
285 return nil, err
286 }
287 defer resp.Body.Close()
288
289 wm := &WriteMeta{RequestTime: rtt}
290 return wm, nil
291}
292
293// Destroy is used to destroy a given ACL token ID
294//
295// Deprecated: Use TokenDelete instead.
296func (a *ACL) Destroy(id string, q *WriteOptions) (*WriteMeta, error) {
297 r := a.c.newRequest("PUT", "/v1/acl/destroy/"+id)
298 r.setWriteOptions(q)
299 rtt, resp, err := requireOK(a.c.doRequest(r))
300 if err != nil {
301 return nil, err
302 }
303 resp.Body.Close()
304
305 wm := &WriteMeta{RequestTime: rtt}
306 return wm, nil
307}
308
309// Clone is used to return a new token cloned from an existing one
310//
311// Deprecated: Use TokenClone instead.
312func (a *ACL) Clone(id string, q *WriteOptions) (string, *WriteMeta, error) {
313 r := a.c.newRequest("PUT", "/v1/acl/clone/"+id)
314 r.setWriteOptions(q)
315 rtt, resp, err := requireOK(a.c.doRequest(r))
316 if err != nil {
317 return "", nil, err
318 }
319 defer resp.Body.Close()
320
321 wm := &WriteMeta{RequestTime: rtt}
322 var out struct{ ID string }
323 if err := decodeBody(resp, &out); err != nil {
324 return "", nil, err
325 }
326 return out.ID, wm, nil
327}
328
329// Info is used to query for information about an ACL token
330//
331// Deprecated: Use TokenRead instead.
332func (a *ACL) Info(id string, q *QueryOptions) (*ACLEntry, *QueryMeta, error) {
333 r := a.c.newRequest("GET", "/v1/acl/info/"+id)
334 r.setQueryOptions(q)
335 rtt, resp, err := requireOK(a.c.doRequest(r))
336 if err != nil {
337 return nil, nil, err
338 }
339 defer resp.Body.Close()
340
341 qm := &QueryMeta{}
342 parseQueryMeta(resp, qm)
343 qm.RequestTime = rtt
344
345 var entries []*ACLEntry
346 if err := decodeBody(resp, &entries); err != nil {
347 return nil, nil, err
348 }
349 if len(entries) > 0 {
350 return entries[0], qm, nil
351 }
352 return nil, qm, nil
353}
354
355// List is used to get all the ACL tokens
356//
357// Deprecated: Use TokenList instead.
358func (a *ACL) List(q *QueryOptions) ([]*ACLEntry, *QueryMeta, error) {
359 r := a.c.newRequest("GET", "/v1/acl/list")
360 r.setQueryOptions(q)
361 rtt, resp, err := requireOK(a.c.doRequest(r))
362 if err != nil {
363 return nil, nil, err
364 }
365 defer resp.Body.Close()
366
367 qm := &QueryMeta{}
368 parseQueryMeta(resp, qm)
369 qm.RequestTime = rtt
370
371 var entries []*ACLEntry
372 if err := decodeBody(resp, &entries); err != nil {
373 return nil, nil, err
374 }
375 return entries, qm, nil
376}
377
378// Replication returns the status of the ACL replication process in the datacenter
379func (a *ACL) Replication(q *QueryOptions) (*ACLReplicationStatus, *QueryMeta, error) {
380 r := a.c.newRequest("GET", "/v1/acl/replication")
381 r.setQueryOptions(q)
382 rtt, resp, err := requireOK(a.c.doRequest(r))
383 if err != nil {
384 return nil, nil, err
385 }
386 defer resp.Body.Close()
387
388 qm := &QueryMeta{}
389 parseQueryMeta(resp, qm)
390 qm.RequestTime = rtt
391
392 var entries *ACLReplicationStatus
393 if err := decodeBody(resp, &entries); err != nil {
394 return nil, nil, err
395 }
396 return entries, qm, nil
397}
398
Abhilash S.L3b494632019-07-16 15:51:09 +0530399// TokenCreate creates a new ACL token. If either the AccessorID or SecretID fields
400// of the ACLToken structure are empty they will be filled in by Consul.
William Kurkianea869482019-04-09 15:16:11 -0400401func (a *ACL) TokenCreate(token *ACLToken, q *WriteOptions) (*ACLToken, *WriteMeta, error) {
William Kurkianea869482019-04-09 15:16:11 -0400402 r := a.c.newRequest("PUT", "/v1/acl/token")
403 r.setWriteOptions(q)
404 r.obj = token
405 rtt, resp, err := requireOK(a.c.doRequest(r))
406 if err != nil {
407 return nil, nil, err
408 }
409 defer resp.Body.Close()
410
411 wm := &WriteMeta{RequestTime: rtt}
412 var out ACLToken
413 if err := decodeBody(resp, &out); err != nil {
414 return nil, nil, err
415 }
416
417 return &out, wm, nil
418}
419
420// TokenUpdate updates a token in place without modifying its AccessorID or SecretID. A valid
421// AccessorID must be set in the ACLToken structure passed to this function but the SecretID may
422// be omitted and will be filled in by Consul with its existing value.
423func (a *ACL) TokenUpdate(token *ACLToken, q *WriteOptions) (*ACLToken, *WriteMeta, error) {
424 if token.AccessorID == "" {
425 return nil, nil, fmt.Errorf("Must specify an AccessorID for Token Updating")
426 }
427 r := a.c.newRequest("PUT", "/v1/acl/token/"+token.AccessorID)
428 r.setWriteOptions(q)
429 r.obj = token
430 rtt, resp, err := requireOK(a.c.doRequest(r))
431 if err != nil {
432 return nil, nil, err
433 }
434 defer resp.Body.Close()
435
436 wm := &WriteMeta{RequestTime: rtt}
437 var out ACLToken
438 if err := decodeBody(resp, &out); err != nil {
439 return nil, nil, err
440 }
441
442 return &out, wm, nil
443}
444
445// TokenClone will create a new token with the same policies and locality as the original
446// token but will have its own auto-generated AccessorID and SecretID as well having the
447// description passed to this function. The tokenID parameter must be a valid Accessor ID
448// of an existing token.
449func (a *ACL) TokenClone(tokenID string, description string, q *WriteOptions) (*ACLToken, *WriteMeta, error) {
450 if tokenID == "" {
451 return nil, nil, fmt.Errorf("Must specify a tokenID for Token Cloning")
452 }
453
454 r := a.c.newRequest("PUT", "/v1/acl/token/"+tokenID+"/clone")
455 r.setWriteOptions(q)
456 r.obj = struct{ Description string }{description}
457 rtt, resp, err := requireOK(a.c.doRequest(r))
458 if err != nil {
459 return nil, nil, err
460 }
461 defer resp.Body.Close()
462
463 wm := &WriteMeta{RequestTime: rtt}
464 var out ACLToken
465 if err := decodeBody(resp, &out); err != nil {
466 return nil, nil, err
467 }
468
469 return &out, wm, nil
470}
471
472// TokenDelete removes a single ACL token. The tokenID parameter must be a valid
473// Accessor ID of an existing token.
474func (a *ACL) TokenDelete(tokenID string, q *WriteOptions) (*WriteMeta, error) {
475 r := a.c.newRequest("DELETE", "/v1/acl/token/"+tokenID)
476 r.setWriteOptions(q)
477 rtt, resp, err := requireOK(a.c.doRequest(r))
478 if err != nil {
479 return nil, err
480 }
481 resp.Body.Close()
482
483 wm := &WriteMeta{RequestTime: rtt}
484 return wm, nil
485}
486
487// TokenRead retrieves the full token details. The tokenID parameter must be a valid
488// Accessor ID of an existing token.
489func (a *ACL) TokenRead(tokenID string, q *QueryOptions) (*ACLToken, *QueryMeta, error) {
490 r := a.c.newRequest("GET", "/v1/acl/token/"+tokenID)
491 r.setQueryOptions(q)
492 rtt, resp, err := requireOK(a.c.doRequest(r))
493 if err != nil {
494 return nil, nil, err
495 }
496 defer resp.Body.Close()
497
498 qm := &QueryMeta{}
499 parseQueryMeta(resp, qm)
500 qm.RequestTime = rtt
501
502 var out ACLToken
503 if err := decodeBody(resp, &out); err != nil {
504 return nil, nil, err
505 }
506
507 return &out, qm, nil
508}
509
510// TokenReadSelf retrieves the full token details of the token currently
511// assigned to the API Client. In this manner its possible to read a token
512// by its Secret ID.
513func (a *ACL) TokenReadSelf(q *QueryOptions) (*ACLToken, *QueryMeta, error) {
514 r := a.c.newRequest("GET", "/v1/acl/token/self")
515 r.setQueryOptions(q)
516 rtt, resp, err := requireOK(a.c.doRequest(r))
517 if err != nil {
518 return nil, nil, err
519 }
520 defer resp.Body.Close()
521
522 qm := &QueryMeta{}
523 parseQueryMeta(resp, qm)
524 qm.RequestTime = rtt
525
526 var out ACLToken
527 if err := decodeBody(resp, &out); err != nil {
528 return nil, nil, err
529 }
530
531 return &out, qm, nil
532}
533
534// TokenList lists all tokens. The listing does not contain any SecretIDs as those
535// may only be retrieved by a call to TokenRead.
536func (a *ACL) TokenList(q *QueryOptions) ([]*ACLTokenListEntry, *QueryMeta, error) {
537 r := a.c.newRequest("GET", "/v1/acl/tokens")
538 r.setQueryOptions(q)
539 rtt, resp, err := requireOK(a.c.doRequest(r))
540 if err != nil {
541 return nil, nil, err
542 }
543 defer resp.Body.Close()
544
545 qm := &QueryMeta{}
546 parseQueryMeta(resp, qm)
547 qm.RequestTime = rtt
548
549 var entries []*ACLTokenListEntry
550 if err := decodeBody(resp, &entries); err != nil {
551 return nil, nil, err
552 }
553 return entries, qm, nil
554}
555
556// PolicyCreate will create a new policy. It is not allowed for the policy parameters
557// ID field to be set as this will be generated by Consul while processing the request.
558func (a *ACL) PolicyCreate(policy *ACLPolicy, q *WriteOptions) (*ACLPolicy, *WriteMeta, error) {
559 if policy.ID != "" {
560 return nil, nil, fmt.Errorf("Cannot specify an ID in Policy Creation")
561 }
William Kurkianea869482019-04-09 15:16:11 -0400562 r := a.c.newRequest("PUT", "/v1/acl/policy")
563 r.setWriteOptions(q)
564 r.obj = policy
565 rtt, resp, err := requireOK(a.c.doRequest(r))
566 if err != nil {
567 return nil, nil, err
568 }
569 defer resp.Body.Close()
570
571 wm := &WriteMeta{RequestTime: rtt}
572 var out ACLPolicy
573 if err := decodeBody(resp, &out); err != nil {
574 return nil, nil, err
575 }
576
577 return &out, wm, nil
578}
579
580// PolicyUpdate updates a policy. The ID field of the policy parameter must be set to an
581// existing policy ID
582func (a *ACL) PolicyUpdate(policy *ACLPolicy, q *WriteOptions) (*ACLPolicy, *WriteMeta, error) {
583 if policy.ID == "" {
Abhilash S.L3b494632019-07-16 15:51:09 +0530584 return nil, nil, fmt.Errorf("Must specify an ID in Policy Update")
William Kurkianea869482019-04-09 15:16:11 -0400585 }
586
587 r := a.c.newRequest("PUT", "/v1/acl/policy/"+policy.ID)
588 r.setWriteOptions(q)
589 r.obj = policy
590 rtt, resp, err := requireOK(a.c.doRequest(r))
591 if err != nil {
592 return nil, nil, err
593 }
594 defer resp.Body.Close()
595
596 wm := &WriteMeta{RequestTime: rtt}
597 var out ACLPolicy
598 if err := decodeBody(resp, &out); err != nil {
599 return nil, nil, err
600 }
601
602 return &out, wm, nil
603}
604
605// PolicyDelete deletes a policy given its ID.
606func (a *ACL) PolicyDelete(policyID string, q *WriteOptions) (*WriteMeta, error) {
607 r := a.c.newRequest("DELETE", "/v1/acl/policy/"+policyID)
608 r.setWriteOptions(q)
609 rtt, resp, err := requireOK(a.c.doRequest(r))
610 if err != nil {
611 return nil, err
612 }
613 resp.Body.Close()
614
615 wm := &WriteMeta{RequestTime: rtt}
616 return wm, nil
617}
618
619// PolicyRead retrieves the policy details including the rule set.
620func (a *ACL) PolicyRead(policyID string, q *QueryOptions) (*ACLPolicy, *QueryMeta, error) {
621 r := a.c.newRequest("GET", "/v1/acl/policy/"+policyID)
622 r.setQueryOptions(q)
623 rtt, resp, err := requireOK(a.c.doRequest(r))
624 if err != nil {
625 return nil, nil, err
626 }
627 defer resp.Body.Close()
628
629 qm := &QueryMeta{}
630 parseQueryMeta(resp, qm)
631 qm.RequestTime = rtt
632
633 var out ACLPolicy
634 if err := decodeBody(resp, &out); err != nil {
635 return nil, nil, err
636 }
637
638 return &out, qm, nil
639}
640
641// PolicyList retrieves a listing of all policies. The listing does not include the
642// rules for any policy as those should be retrieved by subsequent calls to PolicyRead.
643func (a *ACL) PolicyList(q *QueryOptions) ([]*ACLPolicyListEntry, *QueryMeta, error) {
644 r := a.c.newRequest("GET", "/v1/acl/policies")
645 r.setQueryOptions(q)
646 rtt, resp, err := requireOK(a.c.doRequest(r))
647 if err != nil {
648 return nil, nil, err
649 }
650 defer resp.Body.Close()
651
652 qm := &QueryMeta{}
653 parseQueryMeta(resp, qm)
654 qm.RequestTime = rtt
655
656 var entries []*ACLPolicyListEntry
657 if err := decodeBody(resp, &entries); err != nil {
658 return nil, nil, err
659 }
660 return entries, qm, nil
661}
662
663// RulesTranslate translates the legacy rule syntax into the current syntax.
664//
665// Deprecated: Support for the legacy syntax translation will be removed
666// when legacy ACL support is removed.
667func (a *ACL) RulesTranslate(rules io.Reader) (string, error) {
668 r := a.c.newRequest("POST", "/v1/acl/rules/translate")
669 r.body = rules
670 rtt, resp, err := requireOK(a.c.doRequest(r))
671 if err != nil {
672 return "", err
673 }
674 defer resp.Body.Close()
675 qm := &QueryMeta{}
676 parseQueryMeta(resp, qm)
677 qm.RequestTime = rtt
678
679 ruleBytes, err := ioutil.ReadAll(resp.Body)
680 if err != nil {
681 return "", fmt.Errorf("Failed to read translated rule body: %v", err)
682 }
683
684 return string(ruleBytes), nil
685}
686
687// RulesTranslateToken translates the rules associated with the legacy syntax
688// into the current syntax and returns the results.
689//
690// Deprecated: Support for the legacy syntax translation will be removed
691// when legacy ACL support is removed.
692func (a *ACL) RulesTranslateToken(tokenID string) (string, error) {
693 r := a.c.newRequest("GET", "/v1/acl/rules/translate/"+tokenID)
694 rtt, resp, err := requireOK(a.c.doRequest(r))
695 if err != nil {
696 return "", err
697 }
698 defer resp.Body.Close()
699 qm := &QueryMeta{}
700 parseQueryMeta(resp, qm)
701 qm.RequestTime = rtt
702
703 ruleBytes, err := ioutil.ReadAll(resp.Body)
704 if err != nil {
705 return "", fmt.Errorf("Failed to read translated rule body: %v", err)
706 }
707
708 return string(ruleBytes), nil
709}
Abhilash S.L3b494632019-07-16 15:51:09 +0530710
711// RoleCreate will create a new role. It is not allowed for the role parameters
712// ID field to be set as this will be generated by Consul while processing the request.
713func (a *ACL) RoleCreate(role *ACLRole, q *WriteOptions) (*ACLRole, *WriteMeta, error) {
714 if role.ID != "" {
715 return nil, nil, fmt.Errorf("Cannot specify an ID in Role Creation")
716 }
717
718 r := a.c.newRequest("PUT", "/v1/acl/role")
719 r.setWriteOptions(q)
720 r.obj = role
721 rtt, resp, err := requireOK(a.c.doRequest(r))
722 if err != nil {
723 return nil, nil, err
724 }
725 defer resp.Body.Close()
726
727 wm := &WriteMeta{RequestTime: rtt}
728 var out ACLRole
729 if err := decodeBody(resp, &out); err != nil {
730 return nil, nil, err
731 }
732
733 return &out, wm, nil
734}
735
736// RoleUpdate updates a role. The ID field of the role parameter must be set to an
737// existing role ID
738func (a *ACL) RoleUpdate(role *ACLRole, q *WriteOptions) (*ACLRole, *WriteMeta, error) {
739 if role.ID == "" {
740 return nil, nil, fmt.Errorf("Must specify an ID in Role Update")
741 }
742
743 r := a.c.newRequest("PUT", "/v1/acl/role/"+role.ID)
744 r.setWriteOptions(q)
745 r.obj = role
746 rtt, resp, err := requireOK(a.c.doRequest(r))
747 if err != nil {
748 return nil, nil, err
749 }
750 defer resp.Body.Close()
751
752 wm := &WriteMeta{RequestTime: rtt}
753 var out ACLRole
754 if err := decodeBody(resp, &out); err != nil {
755 return nil, nil, err
756 }
757
758 return &out, wm, nil
759}
760
761// RoleDelete deletes a role given its ID.
762func (a *ACL) RoleDelete(roleID string, q *WriteOptions) (*WriteMeta, error) {
763 r := a.c.newRequest("DELETE", "/v1/acl/role/"+roleID)
764 r.setWriteOptions(q)
765 rtt, resp, err := requireOK(a.c.doRequest(r))
766 if err != nil {
767 return nil, err
768 }
769 resp.Body.Close()
770
771 wm := &WriteMeta{RequestTime: rtt}
772 return wm, nil
773}
774
775// RoleRead retrieves the role details (by ID). Returns nil if not found.
776func (a *ACL) RoleRead(roleID string, q *QueryOptions) (*ACLRole, *QueryMeta, error) {
777 r := a.c.newRequest("GET", "/v1/acl/role/"+roleID)
778 r.setQueryOptions(q)
779 found, rtt, resp, err := requireNotFoundOrOK(a.c.doRequest(r))
780 if err != nil {
781 return nil, nil, err
782 }
783 defer resp.Body.Close()
784
785 qm := &QueryMeta{}
786 parseQueryMeta(resp, qm)
787 qm.RequestTime = rtt
788
789 if !found {
790 return nil, qm, nil
791 }
792
793 var out ACLRole
794 if err := decodeBody(resp, &out); err != nil {
795 return nil, nil, err
796 }
797
798 return &out, qm, nil
799}
800
801// RoleReadByName retrieves the role details (by name). Returns nil if not found.
802func (a *ACL) RoleReadByName(roleName string, q *QueryOptions) (*ACLRole, *QueryMeta, error) {
803 r := a.c.newRequest("GET", "/v1/acl/role/name/"+url.QueryEscape(roleName))
804 r.setQueryOptions(q)
805 found, rtt, resp, err := requireNotFoundOrOK(a.c.doRequest(r))
806 if err != nil {
807 return nil, nil, err
808 }
809 defer resp.Body.Close()
810
811 qm := &QueryMeta{}
812 parseQueryMeta(resp, qm)
813 qm.RequestTime = rtt
814
815 if !found {
816 return nil, qm, nil
817 }
818
819 var out ACLRole
820 if err := decodeBody(resp, &out); err != nil {
821 return nil, nil, err
822 }
823
824 return &out, qm, nil
825}
826
827// RoleList retrieves a listing of all roles. The listing does not include some
828// metadata for the role as those should be retrieved by subsequent calls to
829// RoleRead.
830func (a *ACL) RoleList(q *QueryOptions) ([]*ACLRole, *QueryMeta, error) {
831 r := a.c.newRequest("GET", "/v1/acl/roles")
832 r.setQueryOptions(q)
833 rtt, resp, err := requireOK(a.c.doRequest(r))
834 if err != nil {
835 return nil, nil, err
836 }
837 defer resp.Body.Close()
838
839 qm := &QueryMeta{}
840 parseQueryMeta(resp, qm)
841 qm.RequestTime = rtt
842
843 var entries []*ACLRole
844 if err := decodeBody(resp, &entries); err != nil {
845 return nil, nil, err
846 }
847 return entries, qm, nil
848}
849
850// AuthMethodCreate will create a new auth method.
851func (a *ACL) AuthMethodCreate(method *ACLAuthMethod, q *WriteOptions) (*ACLAuthMethod, *WriteMeta, error) {
852 if method.Name == "" {
853 return nil, nil, fmt.Errorf("Must specify a Name in Auth Method Creation")
854 }
855
856 r := a.c.newRequest("PUT", "/v1/acl/auth-method")
857 r.setWriteOptions(q)
858 r.obj = method
859 rtt, resp, err := requireOK(a.c.doRequest(r))
860 if err != nil {
861 return nil, nil, err
862 }
863 defer resp.Body.Close()
864
865 wm := &WriteMeta{RequestTime: rtt}
866 var out ACLAuthMethod
867 if err := decodeBody(resp, &out); err != nil {
868 return nil, nil, err
869 }
870
871 return &out, wm, nil
872}
873
874// AuthMethodUpdate updates an auth method.
875func (a *ACL) AuthMethodUpdate(method *ACLAuthMethod, q *WriteOptions) (*ACLAuthMethod, *WriteMeta, error) {
876 if method.Name == "" {
877 return nil, nil, fmt.Errorf("Must specify a Name in Auth Method Update")
878 }
879
880 r := a.c.newRequest("PUT", "/v1/acl/auth-method/"+url.QueryEscape(method.Name))
881 r.setWriteOptions(q)
882 r.obj = method
883 rtt, resp, err := requireOK(a.c.doRequest(r))
884 if err != nil {
885 return nil, nil, err
886 }
887 defer resp.Body.Close()
888
889 wm := &WriteMeta{RequestTime: rtt}
890 var out ACLAuthMethod
891 if err := decodeBody(resp, &out); err != nil {
892 return nil, nil, err
893 }
894
895 return &out, wm, nil
896}
897
898// AuthMethodDelete deletes an auth method given its Name.
899func (a *ACL) AuthMethodDelete(methodName string, q *WriteOptions) (*WriteMeta, error) {
900 if methodName == "" {
901 return nil, fmt.Errorf("Must specify a Name in Auth Method Delete")
902 }
903
904 r := a.c.newRequest("DELETE", "/v1/acl/auth-method/"+url.QueryEscape(methodName))
905 r.setWriteOptions(q)
906 rtt, resp, err := requireOK(a.c.doRequest(r))
907 if err != nil {
908 return nil, err
909 }
910 resp.Body.Close()
911
912 wm := &WriteMeta{RequestTime: rtt}
913 return wm, nil
914}
915
916// AuthMethodRead retrieves the auth method. Returns nil if not found.
917func (a *ACL) AuthMethodRead(methodName string, q *QueryOptions) (*ACLAuthMethod, *QueryMeta, error) {
918 if methodName == "" {
919 return nil, nil, fmt.Errorf("Must specify a Name in Auth Method Read")
920 }
921
922 r := a.c.newRequest("GET", "/v1/acl/auth-method/"+url.QueryEscape(methodName))
923 r.setQueryOptions(q)
924 found, rtt, resp, err := requireNotFoundOrOK(a.c.doRequest(r))
925 if err != nil {
926 return nil, nil, err
927 }
928 defer resp.Body.Close()
929
930 qm := &QueryMeta{}
931 parseQueryMeta(resp, qm)
932 qm.RequestTime = rtt
933
934 if !found {
935 return nil, qm, nil
936 }
937
938 var out ACLAuthMethod
939 if err := decodeBody(resp, &out); err != nil {
940 return nil, nil, err
941 }
942
943 return &out, qm, nil
944}
945
946// AuthMethodList retrieves a listing of all auth methods. The listing does not
947// include some metadata for the auth method as those should be retrieved by
948// subsequent calls to AuthMethodRead.
949func (a *ACL) AuthMethodList(q *QueryOptions) ([]*ACLAuthMethodListEntry, *QueryMeta, error) {
950 r := a.c.newRequest("GET", "/v1/acl/auth-methods")
951 r.setQueryOptions(q)
952 rtt, resp, err := requireOK(a.c.doRequest(r))
953 if err != nil {
954 return nil, nil, err
955 }
956 defer resp.Body.Close()
957
958 qm := &QueryMeta{}
959 parseQueryMeta(resp, qm)
960 qm.RequestTime = rtt
961
962 var entries []*ACLAuthMethodListEntry
963 if err := decodeBody(resp, &entries); err != nil {
964 return nil, nil, err
965 }
966 return entries, qm, nil
967}
968
969// BindingRuleCreate will create a new binding rule. It is not allowed for the
970// binding rule parameter's ID field to be set as this will be generated by
971// Consul while processing the request.
972func (a *ACL) BindingRuleCreate(rule *ACLBindingRule, q *WriteOptions) (*ACLBindingRule, *WriteMeta, error) {
973 if rule.ID != "" {
974 return nil, nil, fmt.Errorf("Cannot specify an ID in Binding Rule Creation")
975 }
976
977 r := a.c.newRequest("PUT", "/v1/acl/binding-rule")
978 r.setWriteOptions(q)
979 r.obj = rule
980 rtt, resp, err := requireOK(a.c.doRequest(r))
981 if err != nil {
982 return nil, nil, err
983 }
984 defer resp.Body.Close()
985
986 wm := &WriteMeta{RequestTime: rtt}
987 var out ACLBindingRule
988 if err := decodeBody(resp, &out); err != nil {
989 return nil, nil, err
990 }
991
992 return &out, wm, nil
993}
994
995// BindingRuleUpdate updates a binding rule. The ID field of the role binding
996// rule parameter must be set to an existing binding rule ID.
997func (a *ACL) BindingRuleUpdate(rule *ACLBindingRule, q *WriteOptions) (*ACLBindingRule, *WriteMeta, error) {
998 if rule.ID == "" {
999 return nil, nil, fmt.Errorf("Must specify an ID in Binding Rule Update")
1000 }
1001
1002 r := a.c.newRequest("PUT", "/v1/acl/binding-rule/"+rule.ID)
1003 r.setWriteOptions(q)
1004 r.obj = rule
1005 rtt, resp, err := requireOK(a.c.doRequest(r))
1006 if err != nil {
1007 return nil, nil, err
1008 }
1009 defer resp.Body.Close()
1010
1011 wm := &WriteMeta{RequestTime: rtt}
1012 var out ACLBindingRule
1013 if err := decodeBody(resp, &out); err != nil {
1014 return nil, nil, err
1015 }
1016
1017 return &out, wm, nil
1018}
1019
1020// BindingRuleDelete deletes a binding rule given its ID.
1021func (a *ACL) BindingRuleDelete(bindingRuleID string, q *WriteOptions) (*WriteMeta, error) {
1022 r := a.c.newRequest("DELETE", "/v1/acl/binding-rule/"+bindingRuleID)
1023 r.setWriteOptions(q)
1024 rtt, resp, err := requireOK(a.c.doRequest(r))
1025 if err != nil {
1026 return nil, err
1027 }
1028 resp.Body.Close()
1029
1030 wm := &WriteMeta{RequestTime: rtt}
1031 return wm, nil
1032}
1033
1034// BindingRuleRead retrieves the binding rule details. Returns nil if not found.
1035func (a *ACL) BindingRuleRead(bindingRuleID string, q *QueryOptions) (*ACLBindingRule, *QueryMeta, error) {
1036 r := a.c.newRequest("GET", "/v1/acl/binding-rule/"+bindingRuleID)
1037 r.setQueryOptions(q)
1038 found, rtt, resp, err := requireNotFoundOrOK(a.c.doRequest(r))
1039 if err != nil {
1040 return nil, nil, err
1041 }
1042 defer resp.Body.Close()
1043
1044 qm := &QueryMeta{}
1045 parseQueryMeta(resp, qm)
1046 qm.RequestTime = rtt
1047
1048 if !found {
1049 return nil, qm, nil
1050 }
1051
1052 var out ACLBindingRule
1053 if err := decodeBody(resp, &out); err != nil {
1054 return nil, nil, err
1055 }
1056
1057 return &out, qm, nil
1058}
1059
1060// BindingRuleList retrieves a listing of all binding rules.
1061func (a *ACL) BindingRuleList(methodName string, q *QueryOptions) ([]*ACLBindingRule, *QueryMeta, error) {
1062 r := a.c.newRequest("GET", "/v1/acl/binding-rules")
1063 if methodName != "" {
1064 r.params.Set("authmethod", methodName)
1065 }
1066 r.setQueryOptions(q)
1067 rtt, resp, err := requireOK(a.c.doRequest(r))
1068 if err != nil {
1069 return nil, nil, err
1070 }
1071 defer resp.Body.Close()
1072
1073 qm := &QueryMeta{}
1074 parseQueryMeta(resp, qm)
1075 qm.RequestTime = rtt
1076
1077 var entries []*ACLBindingRule
1078 if err := decodeBody(resp, &entries); err != nil {
1079 return nil, nil, err
1080 }
1081 return entries, qm, nil
1082}
1083
1084// Login is used to exchange auth method credentials for a newly-minted Consul Token.
1085func (a *ACL) Login(auth *ACLLoginParams, q *WriteOptions) (*ACLToken, *WriteMeta, error) {
1086 r := a.c.newRequest("POST", "/v1/acl/login")
1087 r.setWriteOptions(q)
1088 r.obj = auth
1089
1090 rtt, resp, err := requireOK(a.c.doRequest(r))
1091 if err != nil {
1092 return nil, nil, err
1093 }
1094 defer resp.Body.Close()
1095
1096 wm := &WriteMeta{RequestTime: rtt}
1097 var out ACLToken
1098 if err := decodeBody(resp, &out); err != nil {
1099 return nil, nil, err
1100 }
1101 return &out, wm, nil
1102}
1103
1104// Logout is used to destroy a Consul Token created via Login().
1105func (a *ACL) Logout(q *WriteOptions) (*WriteMeta, error) {
1106 r := a.c.newRequest("POST", "/v1/acl/logout")
1107 r.setWriteOptions(q)
1108 rtt, resp, err := requireOK(a.c.doRequest(r))
1109 if err != nil {
1110 return nil, err
1111 }
1112 resp.Body.Close()
1113
1114 wm := &WriteMeta{RequestTime: rtt}
1115 return wm, nil
1116}