William Kurkian | ea86948 | 2019-04-09 15:16:11 -0400 | [diff] [blame] | 1 | package api |
| 2 | |
| 3 | import ( |
| 4 | "fmt" |
| 5 | "io" |
| 6 | "io/ioutil" |
Abhilash S.L | 3b49463 | 2019-07-16 15:51:09 +0530 | [diff] [blame] | 7 | "net/url" |
William Kurkian | ea86948 | 2019-04-09 15:16:11 -0400 | [diff] [blame] | 8 | "time" |
Abhilash S.L | 3b49463 | 2019-07-16 15:51:09 +0530 | [diff] [blame] | 9 | |
| 10 | "github.com/mitchellh/mapstructure" |
William Kurkian | ea86948 | 2019-04-09 15:16:11 -0400 | [diff] [blame] | 11 | ) |
| 12 | |
| 13 | const ( |
| 14 | // ACLClientType is the client type token |
| 15 | ACLClientType = "client" |
| 16 | |
| 17 | // ACLManagementType is the management type token |
| 18 | ACLManagementType = "management" |
| 19 | ) |
| 20 | |
| 21 | type ACLTokenPolicyLink struct { |
| 22 | ID string |
| 23 | Name string |
| 24 | } |
Abhilash S.L | 3b49463 | 2019-07-16 15:51:09 +0530 | [diff] [blame] | 25 | type ACLTokenRoleLink struct { |
| 26 | ID string |
| 27 | Name string |
| 28 | } |
William Kurkian | ea86948 | 2019-04-09 15:16:11 -0400 | [diff] [blame] | 29 | |
| 30 | // ACLToken represents an ACL Token |
| 31 | type ACLToken struct { |
Abhilash S.L | 3b49463 | 2019-07-16 15:51:09 +0530 | [diff] [blame] | 32 | 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 Kurkian | ea86948 | 2019-04-09 15:16:11 -0400 | [diff] [blame] | 45 | |
| 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 | |
| 51 | type ACLTokenListEntry struct { |
Abhilash S.L | 3b49463 | 2019-07-16 15:51:09 +0530 | [diff] [blame] | 52 | 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 Kurkian | ea86948 | 2019-04-09 15:16:11 -0400 | [diff] [blame] | 64 | } |
| 65 | |
| 66 | // ACLEntry is used to represent a legacy ACL token |
| 67 | // The legacy tokens are deprecated. |
| 68 | type 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. |
| 78 | type ACLReplicationStatus struct { |
| 79 | Enabled bool |
| 80 | Running bool |
| 81 | SourceDatacenter string |
| 82 | ReplicationType string |
| 83 | ReplicatedIndex uint64 |
Abhilash S.L | 3b49463 | 2019-07-16 15:51:09 +0530 | [diff] [blame] | 84 | ReplicatedRoleIndex uint64 |
William Kurkian | ea86948 | 2019-04-09 15:16:11 -0400 | [diff] [blame] | 85 | ReplicatedTokenIndex uint64 |
| 86 | LastSuccess time.Time |
| 87 | LastError time.Time |
| 88 | } |
| 89 | |
Abhilash S.L | 3b49463 | 2019-07-16 15:51:09 +0530 | [diff] [blame] | 90 | // 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. |
| 93 | type ACLServiceIdentity struct { |
| 94 | ServiceName string |
| 95 | Datacenters []string `json:",omitempty"` |
| 96 | } |
| 97 | |
William Kurkian | ea86948 | 2019-04-09 15:16:11 -0400 | [diff] [blame] | 98 | // ACLPolicy represents an ACL Policy. |
| 99 | type 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 | |
| 110 | type 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.L | 3b49463 | 2019-07-16 15:51:09 +0530 | [diff] [blame] | 120 | type ACLRolePolicyLink struct { |
| 121 | ID string |
| 122 | Name string |
| 123 | } |
| 124 | |
| 125 | // ACLRole represents an ACL Role. |
| 126 | type 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. |
| 138 | type BindingRuleBindType string |
| 139 | |
| 140 | const ( |
| 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 | |
| 148 | type 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 | |
| 160 | type 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 | |
| 174 | type 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. |
| 184 | func 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. |
| 205 | type 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. |
| 213 | func (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 | |
| 221 | type ACLLoginParams struct { |
| 222 | AuthMethod string |
| 223 | BearerToken string |
| 224 | Meta map[string]string `json:",omitempty"` |
| 225 | } |
| 226 | |
William Kurkian | ea86948 | 2019-04-09 15:16:11 -0400 | [diff] [blame] | 227 | // ACL can be used to query the ACL endpoints |
| 228 | type ACL struct { |
| 229 | c *Client |
| 230 | } |
| 231 | |
| 232 | // ACL returns a handle to the ACL endpoints |
| 233 | func (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. |
| 239 | func (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. |
| 258 | func (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. |
| 279 | func (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. |
| 296 | func (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. |
| 312 | func (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. |
| 332 | func (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. |
| 358 | func (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 |
| 379 | func (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.L | 3b49463 | 2019-07-16 15:51:09 +0530 | [diff] [blame] | 399 | // 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 Kurkian | ea86948 | 2019-04-09 15:16:11 -0400 | [diff] [blame] | 401 | func (a *ACL) TokenCreate(token *ACLToken, q *WriteOptions) (*ACLToken, *WriteMeta, error) { |
William Kurkian | ea86948 | 2019-04-09 15:16:11 -0400 | [diff] [blame] | 402 | 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. |
| 423 | func (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. |
| 449 | func (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. |
| 474 | func (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. |
| 489 | func (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. |
| 513 | func (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. |
| 536 | func (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. |
| 558 | func (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 Kurkian | ea86948 | 2019-04-09 15:16:11 -0400 | [diff] [blame] | 562 | 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 |
| 582 | func (a *ACL) PolicyUpdate(policy *ACLPolicy, q *WriteOptions) (*ACLPolicy, *WriteMeta, error) { |
| 583 | if policy.ID == "" { |
Abhilash S.L | 3b49463 | 2019-07-16 15:51:09 +0530 | [diff] [blame] | 584 | return nil, nil, fmt.Errorf("Must specify an ID in Policy Update") |
William Kurkian | ea86948 | 2019-04-09 15:16:11 -0400 | [diff] [blame] | 585 | } |
| 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. |
| 606 | func (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. |
| 620 | func (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. |
| 643 | func (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. |
| 667 | func (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. |
| 692 | func (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.L | 3b49463 | 2019-07-16 15:51:09 +0530 | [diff] [blame] | 710 | |
| 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. |
| 713 | func (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 |
| 738 | func (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. |
| 762 | func (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. |
| 776 | func (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. |
| 802 | func (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. |
| 830 | func (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. |
| 851 | func (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. |
| 875 | func (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. |
| 899 | func (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. |
| 917 | func (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. |
| 949 | func (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. |
| 972 | func (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. |
| 997 | func (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. |
| 1021 | func (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. |
| 1035 | func (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. |
| 1061 | func (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. |
| 1085 | func (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(). |
| 1105 | func (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 | } |