package api
import (
"encoding/json"
"fmt"
"io"
"io/ioutil"
"net/url"
"time"
"github.com/mitchellh/mapstructure"
)
const (
// ACLClientType is the client type token
ACLClientType = "client"
// ACLManagementType is the management type token
ACLManagementType = "management"
)
type ACLLink struct {
ID string
Name string
}
type ACLTokenPolicyLink = ACLLink
type ACLTokenRoleLink = ACLLink
// ACLToken represents an ACL Token
type ACLToken struct {
CreateIndex uint64
ModifyIndex uint64
AccessorID string
SecretID string
Description string
Policies [ ] * ACLTokenPolicyLink ` json:",omitempty" `
Roles [ ] * ACLTokenRoleLink ` json:",omitempty" `
ServiceIdentities [ ] * ACLServiceIdentity ` json:",omitempty" `
Local bool
AuthMethod string ` json:",omitempty" `
ExpirationTTL time . Duration ` json:",omitempty" `
ExpirationTime * time . Time ` json:",omitempty" `
CreateTime time . Time ` json:",omitempty" `
Hash [ ] byte ` json:",omitempty" `
// DEPRECATED (ACL-Legacy-Compat)
// Rules will only be present for legacy tokens returned via the new APIs
Rules string ` json:",omitempty" `
// Namespace is the namespace the ACLToken is associated with.
// Namespaces is a Consul Enterprise feature.
Namespace string ` json:",omitempty" `
}
type ACLTokenListEntry struct {
CreateIndex uint64
ModifyIndex uint64
AccessorID string
Description string
Policies [ ] * ACLTokenPolicyLink ` json:",omitempty" `
Roles [ ] * ACLTokenRoleLink ` json:",omitempty" `
ServiceIdentities [ ] * ACLServiceIdentity ` json:",omitempty" `
Local bool
AuthMethod string ` json:",omitempty" `
ExpirationTime * time . Time ` json:",omitempty" `
CreateTime time . Time
Hash [ ] byte
Legacy bool
// Namespace is the namespace the ACLTokenListEntry is associated with.
// Namespacing is a Consul Enterprise feature.
Namespace string ` json:",omitempty" `
}
// ACLEntry is used to represent a legacy ACL token
// The legacy tokens are deprecated.
type ACLEntry struct {
CreateIndex uint64
ModifyIndex uint64
ID string
Name string
Type string
Rules string
}
// ACLReplicationStatus is used to represent the status of ACL replication.
type ACLReplicationStatus struct {
Enabled bool
Running bool
SourceDatacenter string
ReplicationType string
ReplicatedIndex uint64
ReplicatedRoleIndex uint64
ReplicatedTokenIndex uint64
LastSuccess time . Time
LastError time . Time
}
// ACLServiceIdentity represents a high-level grant of all necessary privileges
// to assume the identity of the named Service in the Catalog and within
// Connect.
type ACLServiceIdentity struct {
ServiceName string
Datacenters [ ] string ` json:",omitempty" `
}
// ACLPolicy represents an ACL Policy.
type ACLPolicy struct {
ID string
Name string
Description string
Rules string
Datacenters [ ] string
Hash [ ] byte
CreateIndex uint64
ModifyIndex uint64
// Namespace is the namespace the ACLPolicy is associated with.
// Namespacing is a Consul Enterprise feature.
Namespace string ` json:",omitempty" `
}
type ACLPolicyListEntry struct {
ID string
Name string
Description string
Datacenters [ ] string
Hash [ ] byte
CreateIndex uint64
ModifyIndex uint64
// Namespace is the namespace the ACLPolicyListEntry is associated with.
// Namespacing is a Consul Enterprise feature.
Namespace string ` json:",omitempty" `
}
type ACLRolePolicyLink = ACLLink
// ACLRole represents an ACL Role.
type ACLRole struct {
ID string
Name string
Description string
Policies [ ] * ACLRolePolicyLink ` json:",omitempty" `
ServiceIdentities [ ] * ACLServiceIdentity ` json:",omitempty" `
Hash [ ] byte
CreateIndex uint64
ModifyIndex uint64
// Namespace is the namespace the ACLRole is associated with.
// Namespacing is a Consul Enterprise feature.
Namespace string ` json:",omitempty" `
}
// BindingRuleBindType is the type of binding rule mechanism used.
type BindingRuleBindType string
const (
// BindingRuleBindTypeService binds to a service identity with the given name.
BindingRuleBindTypeService BindingRuleBindType = "service"
// BindingRuleBindTypeRole binds to pre-existing roles with the given name.
BindingRuleBindTypeRole BindingRuleBindType = "role"
)
type ACLBindingRule struct {
ID string
Description string
AuthMethod string
Selector string
BindType BindingRuleBindType
BindName string
CreateIndex uint64
ModifyIndex uint64
// Namespace is the namespace the ACLBindingRule is associated with.
// Namespacing is a Consul Enterprise feature.
Namespace string ` json:",omitempty" `
}
type ACLAuthMethod struct {
Name string
Type string
DisplayName string ` json:",omitempty" `
Description string ` json:",omitempty" `
MaxTokenTTL time . Duration ` json:",omitempty" `
// Configuration is arbitrary configuration for the auth method. This
// should only contain primitive values and containers (such as lists and
// maps).
Config map [ string ] interface { }
CreateIndex uint64
ModifyIndex uint64
// NamespaceRules apply only on auth methods defined in the default namespace.
// Namespacing is a Consul Enterprise feature.
NamespaceRules [ ] * ACLAuthMethodNamespaceRule ` json:",omitempty" `
// Namespace is the namespace the ACLAuthMethod is associated with.
// Namespacing is a Consul Enterprise feature.
Namespace string ` json:",omitempty" `
}
func ( m * ACLAuthMethod ) MarshalJSON ( ) ( [ ] byte , error ) {
type Alias ACLAuthMethod
exported := & struct {
MaxTokenTTL string ` json:",omitempty" `
* Alias
} {
MaxTokenTTL : m . MaxTokenTTL . String ( ) ,
Alias : ( * Alias ) ( m ) ,
}
if m . MaxTokenTTL == 0 {
exported . MaxTokenTTL = ""
}
return json . Marshal ( exported )
}
func ( m * ACLAuthMethod ) UnmarshalJSON ( data [ ] byte ) error {
type Alias ACLAuthMethod
aux := & struct {
MaxTokenTTL string
* Alias
} {
Alias : ( * Alias ) ( m ) ,
}
if err := json . Unmarshal ( data , & aux ) ; err != nil {
return err
}
var err error
if aux . MaxTokenTTL != "" {
if m . MaxTokenTTL , err = time . ParseDuration ( aux . MaxTokenTTL ) ; err != nil {
return err
}
}
return nil
}
type ACLAuthMethodNamespaceRule struct {
// Selector is an expression that matches against verified identity
// attributes returned from the auth method during login.
Selector string ` json:",omitempty" `
// BindNamespace is the target namespace of the binding. Can be lightly
// templated using HIL ${foo} syntax from available field names.
//
// If empty it's created in the same namespace as the auth method.
BindNamespace string ` json:",omitempty" `
}
type ACLAuthMethodListEntry struct {
Name string
Type string
DisplayName string ` json:",omitempty" `
Description string ` json:",omitempty" `
CreateIndex uint64
ModifyIndex uint64
// Namespace is the namespace the ACLAuthMethodListEntry is associated with.
// Namespacing is a Consul Enterprise feature.
Namespace string ` json:",omitempty" `
}
// ParseKubernetesAuthMethodConfig takes a raw config map and returns a parsed
// KubernetesAuthMethodConfig.
func ParseKubernetesAuthMethodConfig ( raw map [ string ] interface { } ) ( * KubernetesAuthMethodConfig , error ) {
var config KubernetesAuthMethodConfig
decodeConf := & mapstructure . DecoderConfig {
Result : & config ,
WeaklyTypedInput : true ,
}
decoder , err := mapstructure . NewDecoder ( decodeConf )
if err != nil {
return nil , err
}
if err := decoder . Decode ( raw ) ; err != nil {
return nil , fmt . Errorf ( "error decoding config: %s" , err )
}
return & config , nil
}
// KubernetesAuthMethodConfig is the config for the built-in Consul auth method
// for Kubernetes.
type KubernetesAuthMethodConfig struct {
Host string ` json:",omitempty" `
CACert string ` json:",omitempty" `
ServiceAccountJWT string ` json:",omitempty" `
}
// RenderToConfig converts this into a map[string]interface{} suitable for use
// in the ACLAuthMethod.Config field.
func ( c * KubernetesAuthMethodConfig ) RenderToConfig ( ) map [ string ] interface { } {
return map [ string ] interface { } {
"Host" : c . Host ,
"CACert" : c . CACert ,
"ServiceAccountJWT" : c . ServiceAccountJWT ,
}
}
type ACLLoginParams struct {
AuthMethod string
BearerToken string
Meta map [ string ] string ` json:",omitempty" `
}
// ACL can be used to query the ACL endpoints
type ACL struct {
c * Client
}
// ACL returns a handle to the ACL endpoints
func ( c * Client ) ACL ( ) * ACL {
return & ACL { c }
}
// Bootstrap is used to perform a one-time ACL bootstrap operation on a cluster
// to get the first management token.
func ( a * ACL ) Bootstrap ( ) ( * ACLToken , * WriteMeta , error ) {
r := a . c . newRequest ( "PUT" , "/v1/acl/bootstrap" )
rtt , resp , err := requireOK ( a . c . doRequest ( r ) )
if err != nil {
return nil , nil , err
}
defer resp . Body . Close ( )
wm := & WriteMeta { RequestTime : rtt }
var out ACLToken
if err := decodeBody ( resp , & out ) ; err != nil {
return nil , nil , err
}
return & out , wm , nil
}
// Create is used to generate a new token with the given parameters
//
// Deprecated: Use TokenCreate instead.
func ( a * ACL ) Create ( acl * ACLEntry , q * WriteOptions ) ( string , * WriteMeta , error ) {
r := a . c . newRequest ( "PUT" , "/v1/acl/create" )
r . setWriteOptions ( q )
r . obj = acl
rtt , resp , err := requireOK ( a . c . doRequest ( r ) )
if err != nil {
return "" , nil , err
}
defer resp . Body . Close ( )
wm := & WriteMeta { RequestTime : rtt }
var out struct { ID string }
if err := decodeBody ( resp , & out ) ; err != nil {
return "" , nil , err
}
return out . ID , wm , nil
}
// Update is used to update the rules of an existing token
//
// Deprecated: Use TokenUpdate instead.
func ( a * ACL ) Update ( acl * ACLEntry , q * WriteOptions ) ( * WriteMeta , error ) {
r := a . c . newRequest ( "PUT" , "/v1/acl/update" )
r . setWriteOptions ( q )
r . obj = acl
rtt , resp , err := requireOK ( a . c . doRequest ( r ) )
if err != nil {
return nil , err
}
defer resp . Body . Close ( )
wm := & WriteMeta { RequestTime : rtt }
return wm , nil
}
// Destroy is used to destroy a given ACL token ID
//
// Deprecated: Use TokenDelete instead.
func ( a * ACL ) Destroy ( id string , q * WriteOptions ) ( * WriteMeta , error ) {
r := a . c . newRequest ( "PUT" , "/v1/acl/destroy/" + id )
r . setWriteOptions ( q )
rtt , resp , err := requireOK ( a . c . doRequest ( r ) )
if err != nil {
return nil , err
}
resp . Body . Close ( )
wm := & WriteMeta { RequestTime : rtt }
return wm , nil
}
// Clone is used to return a new token cloned from an existing one
//
// Deprecated: Use TokenClone instead.
func ( a * ACL ) Clone ( id string , q * WriteOptions ) ( string , * WriteMeta , error ) {
r := a . c . newRequest ( "PUT" , "/v1/acl/clone/" + id )
r . setWriteOptions ( q )
rtt , resp , err := requireOK ( a . c . doRequest ( r ) )
if err != nil {
return "" , nil , err
}
defer resp . Body . Close ( )
wm := & WriteMeta { RequestTime : rtt }
var out struct { ID string }
if err := decodeBody ( resp , & out ) ; err != nil {
return "" , nil , err
}
return out . ID , wm , nil
}
// Info is used to query for information about an ACL token
//
// Deprecated: Use TokenRead instead.
func ( a * ACL ) Info ( id string , q * QueryOptions ) ( * ACLEntry , * QueryMeta , error ) {
r := a . c . newRequest ( "GET" , "/v1/acl/info/" + id )
r . setQueryOptions ( q )
rtt , resp , err := requireOK ( a . c . doRequest ( r ) )
if err != nil {
return nil , nil , err
}
defer resp . Body . Close ( )
qm := & QueryMeta { }
parseQueryMeta ( resp , qm )
qm . RequestTime = rtt
var entries [ ] * ACLEntry
if err := decodeBody ( resp , & entries ) ; err != nil {
return nil , nil , err
}
if len ( entries ) > 0 {
return entries [ 0 ] , qm , nil
}
return nil , qm , nil
}
// List is used to get all the ACL tokens
//
// Deprecated: Use TokenList instead.
func ( a * ACL ) List ( q * QueryOptions ) ( [ ] * ACLEntry , * QueryMeta , error ) {
r := a . c . newRequest ( "GET" , "/v1/acl/list" )
r . setQueryOptions ( q )
rtt , resp , err := requireOK ( a . c . doRequest ( r ) )
if err != nil {
return nil , nil , err
}
defer resp . Body . Close ( )
qm := & QueryMeta { }
parseQueryMeta ( resp , qm )
qm . RequestTime = rtt
var entries [ ] * ACLEntry
if err := decodeBody ( resp , & entries ) ; err != nil {
return nil , nil , err
}
return entries , qm , nil
}
// Replication returns the status of the ACL replication process in the datacenter
func ( a * ACL ) Replication ( q * QueryOptions ) ( * ACLReplicationStatus , * QueryMeta , error ) {
r := a . c . newRequest ( "GET" , "/v1/acl/replication" )
r . setQueryOptions ( q )
rtt , resp , err := requireOK ( a . c . doRequest ( r ) )
if err != nil {
return nil , nil , err
}
defer resp . Body . Close ( )
qm := & QueryMeta { }
parseQueryMeta ( resp , qm )
qm . RequestTime = rtt
var entries * ACLReplicationStatus
if err := decodeBody ( resp , & entries ) ; err != nil {
return nil , nil , err
}
return entries , qm , nil
}
// TokenCreate creates a new ACL token. If either the AccessorID or SecretID fields
// of the ACLToken structure are empty they will be filled in by Consul.
func ( a * ACL ) TokenCreate ( token * ACLToken , q * WriteOptions ) ( * ACLToken , * WriteMeta , error ) {
r := a . c . newRequest ( "PUT" , "/v1/acl/token" )
r . setWriteOptions ( q )
r . obj = token
rtt , resp , err := requireOK ( a . c . doRequest ( r ) )
if err != nil {
return nil , nil , err
}
defer resp . Body . Close ( )
wm := & WriteMeta { RequestTime : rtt }
var out ACLToken
if err := decodeBody ( resp , & out ) ; err != nil {
return nil , nil , err
}
return & out , wm , nil
}
// TokenUpdate updates a token in place without modifying its AccessorID or SecretID. A valid
// AccessorID must be set in the ACLToken structure passed to this function but the SecretID may
// be omitted and will be filled in by Consul with its existing value.
func ( a * ACL ) TokenUpdate ( token * ACLToken , q * WriteOptions ) ( * ACLToken , * WriteMeta , error ) {
if token . AccessorID == "" {
return nil , nil , fmt . Errorf ( "Must specify an AccessorID for Token Updating" )
}
r := a . c . newRequest ( "PUT" , "/v1/acl/token/" + token . AccessorID )
r . setWriteOptions ( q )
r . obj = token
rtt , resp , err := requireOK ( a . c . doRequest ( r ) )
if err != nil {
return nil , nil , err
}
defer resp . Body . Close ( )
wm := & WriteMeta { RequestTime : rtt }
var out ACLToken
if err := decodeBody ( resp , & out ) ; err != nil {
return nil , nil , err
}
return & out , wm , nil
}
// TokenClone will create a new token with the same policies and locality as the original
// token but will have its own auto-generated AccessorID and SecretID as well having the
// description passed to this function. The tokenID parameter must be a valid Accessor ID
// of an existing token.
func ( a * ACL ) TokenClone ( tokenID string , description string , q * WriteOptions ) ( * ACLToken , * WriteMeta , error ) {
if tokenID == "" {
return nil , nil , fmt . Errorf ( "Must specify a tokenID for Token Cloning" )
}
r := a . c . newRequest ( "PUT" , "/v1/acl/token/" + tokenID + "/clone" )
r . setWriteOptions ( q )
r . obj = struct { Description string } { description }
rtt , resp , err := requireOK ( a . c . doRequest ( r ) )
if err != nil {
return nil , nil , err
}
defer resp . Body . Close ( )
wm := & WriteMeta { RequestTime : rtt }
var out ACLToken
if err := decodeBody ( resp , & out ) ; err != nil {
return nil , nil , err
}
return & out , wm , nil
}
// TokenDelete removes a single ACL token. The tokenID parameter must be a valid
// Accessor ID of an existing token.
func ( a * ACL ) TokenDelete ( tokenID string , q * WriteOptions ) ( * WriteMeta , error ) {
r := a . c . newRequest ( "DELETE" , "/v1/acl/token/" + tokenID )
r . setWriteOptions ( q )
rtt , resp , err := requireOK ( a . c . doRequest ( r ) )
if err != nil {
return nil , err
}
resp . Body . Close ( )
wm := & WriteMeta { RequestTime : rtt }
return wm , nil
}
// TokenRead retrieves the full token details. The tokenID parameter must be a valid
// Accessor ID of an existing token.
func ( a * ACL ) TokenRead ( tokenID string , q * QueryOptions ) ( * ACLToken , * QueryMeta , error ) {
r := a . c . newRequest ( "GET" , "/v1/acl/token/" + tokenID )
r . setQueryOptions ( q )
rtt , resp , err := requireOK ( a . c . doRequest ( r ) )
if err != nil {
return nil , nil , err
}
defer resp . Body . Close ( )
qm := & QueryMeta { }
parseQueryMeta ( resp , qm )
qm . RequestTime = rtt
var out ACLToken
if err := decodeBody ( resp , & out ) ; err != nil {
return nil , nil , err
}
return & out , qm , nil
}
// TokenReadSelf retrieves the full token details of the token currently
// assigned to the API Client. In this manner its possible to read a token
// by its Secret ID.
func ( a * ACL ) TokenReadSelf ( q * QueryOptions ) ( * ACLToken , * QueryMeta , error ) {
r := a . c . newRequest ( "GET" , "/v1/acl/token/self" )
r . setQueryOptions ( q )
rtt , resp , err := requireOK ( a . c . doRequest ( r ) )
if err != nil {
return nil , nil , err
}
defer resp . Body . Close ( )
qm := & QueryMeta { }
parseQueryMeta ( resp , qm )
qm . RequestTime = rtt
var out ACLToken
if err := decodeBody ( resp , & out ) ; err != nil {
return nil , nil , err
}
return & out , qm , nil
}
// TokenList lists all tokens. The listing does not contain any SecretIDs as those
// may only be retrieved by a call to TokenRead.
func ( a * ACL ) TokenList ( q * QueryOptions ) ( [ ] * ACLTokenListEntry , * QueryMeta , error ) {
r := a . c . newRequest ( "GET" , "/v1/acl/tokens" )
r . setQueryOptions ( q )
rtt , resp , err := requireOK ( a . c . doRequest ( r ) )
if err != nil {
return nil , nil , err
}
defer resp . Body . Close ( )
qm := & QueryMeta { }
parseQueryMeta ( resp , qm )
qm . RequestTime = rtt
var entries [ ] * ACLTokenListEntry
if err := decodeBody ( resp , & entries ) ; err != nil {
return nil , nil , err
}
return entries , qm , nil
}
// PolicyCreate will create a new policy. It is not allowed for the policy parameters
// ID field to be set as this will be generated by Consul while processing the request.
func ( a * ACL ) PolicyCreate ( policy * ACLPolicy , q * WriteOptions ) ( * ACLPolicy , * WriteMeta , error ) {
if policy . ID != "" {
return nil , nil , fmt . Errorf ( "Cannot specify an ID in Policy Creation" )
}
r := a . c . newRequest ( "PUT" , "/v1/acl/policy" )
r . setWriteOptions ( q )
r . obj = policy
rtt , resp , err := requireOK ( a . c . doRequest ( r ) )
if err != nil {
return nil , nil , err
}
defer resp . Body . Close ( )
wm := & WriteMeta { RequestTime : rtt }
var out ACLPolicy
if err := decodeBody ( resp , & out ) ; err != nil {
return nil , nil , err
}
return & out , wm , nil
}
// PolicyUpdate updates a policy. The ID field of the policy parameter must be set to an
// existing policy ID
func ( a * ACL ) PolicyUpdate ( policy * ACLPolicy , q * WriteOptions ) ( * ACLPolicy , * WriteMeta , error ) {
if policy . ID == "" {
return nil , nil , fmt . Errorf ( "Must specify an ID in Policy Update" )
}
r := a . c . newRequest ( "PUT" , "/v1/acl/policy/" + policy . ID )
r . setWriteOptions ( q )
r . obj = policy
rtt , resp , err := requireOK ( a . c . doRequest ( r ) )
if err != nil {
return nil , nil , err
}
defer resp . Body . Close ( )
wm := & WriteMeta { RequestTime : rtt }
var out ACLPolicy
if err := decodeBody ( resp , & out ) ; err != nil {
return nil , nil , err
}
return & out , wm , nil
}
// PolicyDelete deletes a policy given its ID.
func ( a * ACL ) PolicyDelete ( policyID string , q * WriteOptions ) ( * WriteMeta , error ) {
r := a . c . newRequest ( "DELETE" , "/v1/acl/policy/" + policyID )
r . setWriteOptions ( q )
rtt , resp , err := requireOK ( a . c . doRequest ( r ) )
if err != nil {
return nil , err
}
resp . Body . Close ( )
wm := & WriteMeta { RequestTime : rtt }
return wm , nil
}
// PolicyRead retrieves the policy details including the rule set.
func ( a * ACL ) PolicyRead ( policyID string , q * QueryOptions ) ( * ACLPolicy , * QueryMeta , error ) {
r := a . c . newRequest ( "GET" , "/v1/acl/policy/" + policyID )
r . setQueryOptions ( q )
rtt , resp , err := requireOK ( a . c . doRequest ( r ) )
if err != nil {
return nil , nil , err
}
defer resp . Body . Close ( )
qm := & QueryMeta { }
parseQueryMeta ( resp , qm )
qm . RequestTime = rtt
var out ACLPolicy
if err := decodeBody ( resp , & out ) ; err != nil {
return nil , nil , err
}
return & out , qm , nil
}
// PolicyReadByName retrieves the policy details including the rule set with name.
func ( a * ACL ) PolicyReadByName ( policyName string , q * QueryOptions ) ( * ACLPolicy , * QueryMeta , error ) {
r := a . c . newRequest ( "GET" , "/v1/acl/policy/name/" + url . QueryEscape ( policyName ) )
r . setQueryOptions ( q )
found , rtt , resp , err := requireNotFoundOrOK ( a . c . doRequest ( r ) )
if err != nil {
return nil , nil , err
}
defer resp . Body . Close ( )
qm := & QueryMeta { }
parseQueryMeta ( resp , qm )
qm . RequestTime = rtt
if ! found {
return nil , qm , nil
}
var out ACLPolicy
if err := decodeBody ( resp , & out ) ; err != nil {
return nil , nil , err
}
return & out , qm , nil
}
// PolicyList retrieves a listing of all policies. The listing does not include the
// rules for any policy as those should be retrieved by subsequent calls to PolicyRead.
func ( a * ACL ) PolicyList ( q * QueryOptions ) ( [ ] * ACLPolicyListEntry , * QueryMeta , error ) {
r := a . c . newRequest ( "GET" , "/v1/acl/policies" )
r . setQueryOptions ( q )
rtt , resp , err := requireOK ( a . c . doRequest ( r ) )
if err != nil {
return nil , nil , err
}
defer resp . Body . Close ( )
qm := & QueryMeta { }
parseQueryMeta ( resp , qm )
qm . RequestTime = rtt
var entries [ ] * ACLPolicyListEntry
if err := decodeBody ( resp , & entries ) ; err != nil {
return nil , nil , err
}
return entries , qm , nil
}
// RulesTranslate translates the legacy rule syntax into the current syntax.
//
// Deprecated: Support for the legacy syntax translation will be removed
// when legacy ACL support is removed.
func ( a * ACL ) RulesTranslate ( rules io . Reader ) ( string , error ) {
r := a . c . newRequest ( "POST" , "/v1/acl/rules/translate" )
r . body = rules
rtt , resp , err := requireOK ( a . c . doRequest ( r ) )
if err != nil {
return "" , err
}
defer resp . Body . Close ( )
qm := & QueryMeta { }
parseQueryMeta ( resp , qm )
qm . RequestTime = rtt
ruleBytes , err := ioutil . ReadAll ( resp . Body )
if err != nil {
return "" , fmt . Errorf ( "Failed to read translated rule body: %v" , err )
}
return string ( ruleBytes ) , nil
}
// RulesTranslateToken translates the rules associated with the legacy syntax
// into the current syntax and returns the results.
//
// Deprecated: Support for the legacy syntax translation will be removed
// when legacy ACL support is removed.
func ( a * ACL ) RulesTranslateToken ( tokenID string ) ( string , error ) {
r := a . c . newRequest ( "GET" , "/v1/acl/rules/translate/" + tokenID )
rtt , resp , err := requireOK ( a . c . doRequest ( r ) )
if err != nil {
return "" , err
}
defer resp . Body . Close ( )
qm := & QueryMeta { }
parseQueryMeta ( resp , qm )
qm . RequestTime = rtt
ruleBytes , err := ioutil . ReadAll ( resp . Body )
if err != nil {
return "" , fmt . Errorf ( "Failed to read translated rule body: %v" , err )
}
return string ( ruleBytes ) , nil
}
// RoleCreate will create a new role. It is not allowed for the role parameters
// ID field to be set as this will be generated by Consul while processing the request.
func ( a * ACL ) RoleCreate ( role * ACLRole , q * WriteOptions ) ( * ACLRole , * WriteMeta , error ) {
if role . ID != "" {
return nil , nil , fmt . Errorf ( "Cannot specify an ID in Role Creation" )
}
r := a . c . newRequest ( "PUT" , "/v1/acl/role" )
r . setWriteOptions ( q )
r . obj = role
rtt , resp , err := requireOK ( a . c . doRequest ( r ) )
if err != nil {
return nil , nil , err
}
defer resp . Body . Close ( )
wm := & WriteMeta { RequestTime : rtt }
var out ACLRole
if err := decodeBody ( resp , & out ) ; err != nil {
return nil , nil , err
}
return & out , wm , nil
}
// RoleUpdate updates a role. The ID field of the role parameter must be set to an
// existing role ID
func ( a * ACL ) RoleUpdate ( role * ACLRole , q * WriteOptions ) ( * ACLRole , * WriteMeta , error ) {
if role . ID == "" {
return nil , nil , fmt . Errorf ( "Must specify an ID in Role Update" )
}
r := a . c . newRequest ( "PUT" , "/v1/acl/role/" + role . ID )
r . setWriteOptions ( q )
r . obj = role
rtt , resp , err := requireOK ( a . c . doRequest ( r ) )
if err != nil {
return nil , nil , err
}
defer resp . Body . Close ( )
wm := & WriteMeta { RequestTime : rtt }
var out ACLRole
if err := decodeBody ( resp , & out ) ; err != nil {
return nil , nil , err
}
return & out , wm , nil
}
// RoleDelete deletes a role given its ID.
func ( a * ACL ) RoleDelete ( roleID string , q * WriteOptions ) ( * WriteMeta , error ) {
r := a . c . newRequest ( "DELETE" , "/v1/acl/role/" + roleID )
r . setWriteOptions ( q )
rtt , resp , err := requireOK ( a . c . doRequest ( r ) )
if err != nil {
return nil , err
}
resp . Body . Close ( )
wm := & WriteMeta { RequestTime : rtt }
return wm , nil
}
// RoleRead retrieves the role details (by ID). Returns nil if not found.
func ( a * ACL ) RoleRead ( roleID string , q * QueryOptions ) ( * ACLRole , * QueryMeta , error ) {
r := a . c . newRequest ( "GET" , "/v1/acl/role/" + roleID )
r . setQueryOptions ( q )
found , rtt , resp , err := requireNotFoundOrOK ( a . c . doRequest ( r ) )
if err != nil {
return nil , nil , err
}
defer resp . Body . Close ( )
qm := & QueryMeta { }
parseQueryMeta ( resp , qm )
qm . RequestTime = rtt
if ! found {
return nil , qm , nil
}
var out ACLRole
if err := decodeBody ( resp , & out ) ; err != nil {
return nil , nil , err
}
return & out , qm , nil
}
// RoleReadByName retrieves the role details (by name). Returns nil if not found.
func ( a * ACL ) RoleReadByName ( roleName string , q * QueryOptions ) ( * ACLRole , * QueryMeta , error ) {
r := a . c . newRequest ( "GET" , "/v1/acl/role/name/" + url . QueryEscape ( roleName ) )
r . setQueryOptions ( q )
found , rtt , resp , err := requireNotFoundOrOK ( a . c . doRequest ( r ) )
if err != nil {
return nil , nil , err
}
defer resp . Body . Close ( )
qm := & QueryMeta { }
parseQueryMeta ( resp , qm )
qm . RequestTime = rtt
if ! found {
return nil , qm , nil
}
var out ACLRole
if err := decodeBody ( resp , & out ) ; err != nil {
return nil , nil , err
}
return & out , qm , nil
}
// RoleList retrieves a listing of all roles. The listing does not include some
// metadata for the role as those should be retrieved by subsequent calls to
// RoleRead.
func ( a * ACL ) RoleList ( q * QueryOptions ) ( [ ] * ACLRole , * QueryMeta , error ) {
r := a . c . newRequest ( "GET" , "/v1/acl/roles" )
r . setQueryOptions ( q )
rtt , resp , err := requireOK ( a . c . doRequest ( r ) )
if err != nil {
return nil , nil , err
}
defer resp . Body . Close ( )
qm := & QueryMeta { }
parseQueryMeta ( resp , qm )
qm . RequestTime = rtt
var entries [ ] * ACLRole
if err := decodeBody ( resp , & entries ) ; err != nil {
return nil , nil , err
}
return entries , qm , nil
}
// AuthMethodCreate will create a new auth method.
func ( a * ACL ) AuthMethodCreate ( method * ACLAuthMethod , q * WriteOptions ) ( * ACLAuthMethod , * WriteMeta , error ) {
if method . Name == "" {
return nil , nil , fmt . Errorf ( "Must specify a Name in Auth Method Creation" )
}
r := a . c . newRequest ( "PUT" , "/v1/acl/auth-method" )
r . setWriteOptions ( q )
r . obj = method
rtt , resp , err := requireOK ( a . c . doRequest ( r ) )
if err != nil {
return nil , nil , err
}
defer resp . Body . Close ( )
wm := & WriteMeta { RequestTime : rtt }
var out ACLAuthMethod
if err := decodeBody ( resp , & out ) ; err != nil {
return nil , nil , err
}
return & out , wm , nil
}
// AuthMethodUpdate updates an auth method.
func ( a * ACL ) AuthMethodUpdate ( method * ACLAuthMethod , q * WriteOptions ) ( * ACLAuthMethod , * WriteMeta , error ) {
if method . Name == "" {
return nil , nil , fmt . Errorf ( "Must specify a Name in Auth Method Update" )
}
r := a . c . newRequest ( "PUT" , "/v1/acl/auth-method/" + url . QueryEscape ( method . Name ) )
r . setWriteOptions ( q )
r . obj = method
rtt , resp , err := requireOK ( a . c . doRequest ( r ) )
if err != nil {
return nil , nil , err
}
defer resp . Body . Close ( )
wm := & WriteMeta { RequestTime : rtt }
var out ACLAuthMethod
if err := decodeBody ( resp , & out ) ; err != nil {
return nil , nil , err
}
return & out , wm , nil
}
// AuthMethodDelete deletes an auth method given its Name.
func ( a * ACL ) AuthMethodDelete ( methodName string , q * WriteOptions ) ( * WriteMeta , error ) {
if methodName == "" {
return nil , fmt . Errorf ( "Must specify a Name in Auth Method Delete" )
}
r := a . c . newRequest ( "DELETE" , "/v1/acl/auth-method/" + url . QueryEscape ( methodName ) )
r . setWriteOptions ( q )
rtt , resp , err := requireOK ( a . c . doRequest ( r ) )
if err != nil {
return nil , err
}
resp . Body . Close ( )
wm := & WriteMeta { RequestTime : rtt }
return wm , nil
}
// AuthMethodRead retrieves the auth method. Returns nil if not found.
func ( a * ACL ) AuthMethodRead ( methodName string , q * QueryOptions ) ( * ACLAuthMethod , * QueryMeta , error ) {
if methodName == "" {
return nil , nil , fmt . Errorf ( "Must specify a Name in Auth Method Read" )
}
r := a . c . newRequest ( "GET" , "/v1/acl/auth-method/" + url . QueryEscape ( methodName ) )
r . setQueryOptions ( q )
found , rtt , resp , err := requireNotFoundOrOK ( a . c . doRequest ( r ) )
if err != nil {
return nil , nil , err
}
defer resp . Body . Close ( )
qm := & QueryMeta { }
parseQueryMeta ( resp , qm )
qm . RequestTime = rtt
if ! found {
return nil , qm , nil
}
var out ACLAuthMethod
if err := decodeBody ( resp , & out ) ; err != nil {
return nil , nil , err
}
return & out , qm , nil
}
// AuthMethodList retrieves a listing of all auth methods. The listing does not
// include some metadata for the auth method as those should be retrieved by
// subsequent calls to AuthMethodRead.
func ( a * ACL ) AuthMethodList ( q * QueryOptions ) ( [ ] * ACLAuthMethodListEntry , * QueryMeta , error ) {
r := a . c . newRequest ( "GET" , "/v1/acl/auth-methods" )
r . setQueryOptions ( q )
rtt , resp , err := requireOK ( a . c . doRequest ( r ) )
if err != nil {
return nil , nil , err
}
defer resp . Body . Close ( )
qm := & QueryMeta { }
parseQueryMeta ( resp , qm )
qm . RequestTime = rtt
var entries [ ] * ACLAuthMethodListEntry
if err := decodeBody ( resp , & entries ) ; err != nil {
return nil , nil , err
}
return entries , qm , nil
}
// BindingRuleCreate will create a new binding rule. It is not allowed for the
// binding rule parameter's ID field to be set as this will be generated by
// Consul while processing the request.
func ( a * ACL ) BindingRuleCreate ( rule * ACLBindingRule , q * WriteOptions ) ( * ACLBindingRule , * WriteMeta , error ) {
if rule . ID != "" {
return nil , nil , fmt . Errorf ( "Cannot specify an ID in Binding Rule Creation" )
}
r := a . c . newRequest ( "PUT" , "/v1/acl/binding-rule" )
r . setWriteOptions ( q )
r . obj = rule
rtt , resp , err := requireOK ( a . c . doRequest ( r ) )
if err != nil {
return nil , nil , err
}
defer resp . Body . Close ( )
wm := & WriteMeta { RequestTime : rtt }
var out ACLBindingRule
if err := decodeBody ( resp , & out ) ; err != nil {
return nil , nil , err
}
return & out , wm , nil
}
// BindingRuleUpdate updates a binding rule. The ID field of the role binding
// rule parameter must be set to an existing binding rule ID.
func ( a * ACL ) BindingRuleUpdate ( rule * ACLBindingRule , q * WriteOptions ) ( * ACLBindingRule , * WriteMeta , error ) {
if rule . ID == "" {
return nil , nil , fmt . Errorf ( "Must specify an ID in Binding Rule Update" )
}
r := a . c . newRequest ( "PUT" , "/v1/acl/binding-rule/" + rule . ID )
r . setWriteOptions ( q )
r . obj = rule
rtt , resp , err := requireOK ( a . c . doRequest ( r ) )
if err != nil {
return nil , nil , err
}
defer resp . Body . Close ( )
wm := & WriteMeta { RequestTime : rtt }
var out ACLBindingRule
if err := decodeBody ( resp , & out ) ; err != nil {
return nil , nil , err
}
return & out , wm , nil
}
// BindingRuleDelete deletes a binding rule given its ID.
func ( a * ACL ) BindingRuleDelete ( bindingRuleID string , q * WriteOptions ) ( * WriteMeta , error ) {
r := a . c . newRequest ( "DELETE" , "/v1/acl/binding-rule/" + bindingRuleID )
r . setWriteOptions ( q )
rtt , resp , err := requireOK ( a . c . doRequest ( r ) )
if err != nil {
return nil , err
}
resp . Body . Close ( )
wm := & WriteMeta { RequestTime : rtt }
return wm , nil
}
// BindingRuleRead retrieves the binding rule details. Returns nil if not found.
func ( a * ACL ) BindingRuleRead ( bindingRuleID string , q * QueryOptions ) ( * ACLBindingRule , * QueryMeta , error ) {
r := a . c . newRequest ( "GET" , "/v1/acl/binding-rule/" + bindingRuleID )
r . setQueryOptions ( q )
found , rtt , resp , err := requireNotFoundOrOK ( a . c . doRequest ( r ) )
if err != nil {
return nil , nil , err
}
defer resp . Body . Close ( )
qm := & QueryMeta { }
parseQueryMeta ( resp , qm )
qm . RequestTime = rtt
if ! found {
return nil , qm , nil
}
var out ACLBindingRule
if err := decodeBody ( resp , & out ) ; err != nil {
return nil , nil , err
}
return & out , qm , nil
}
// BindingRuleList retrieves a listing of all binding rules.
func ( a * ACL ) BindingRuleList ( methodName string , q * QueryOptions ) ( [ ] * ACLBindingRule , * QueryMeta , error ) {
r := a . c . newRequest ( "GET" , "/v1/acl/binding-rules" )
if methodName != "" {
r . params . Set ( "authmethod" , methodName )
}
r . setQueryOptions ( q )
rtt , resp , err := requireOK ( a . c . doRequest ( r ) )
if err != nil {
return nil , nil , err
}
defer resp . Body . Close ( )
qm := & QueryMeta { }
parseQueryMeta ( resp , qm )
qm . RequestTime = rtt
var entries [ ] * ACLBindingRule
if err := decodeBody ( resp , & entries ) ; err != nil {
return nil , nil , err
}
return entries , qm , nil
}
// Login is used to exchange auth method credentials for a newly-minted Consul Token.
func ( a * ACL ) Login ( auth * ACLLoginParams , q * WriteOptions ) ( * ACLToken , * WriteMeta , error ) {
r := a . c . newRequest ( "POST" , "/v1/acl/login" )
r . setWriteOptions ( q )
r . obj = auth
rtt , resp , err := requireOK ( a . c . doRequest ( r ) )
if err != nil {
return nil , nil , err
}
defer resp . Body . Close ( )
wm := & WriteMeta { RequestTime : rtt }
var out ACLToken
if err := decodeBody ( resp , & out ) ; err != nil {
return nil , nil , err
}
return & out , wm , nil
}
// Logout is used to destroy a Consul Token created via Login().
func ( a * ACL ) Logout ( q * WriteOptions ) ( * WriteMeta , error ) {
r := a . c . newRequest ( "POST" , "/v1/acl/logout" )
r . setWriteOptions ( q )
rtt , resp , err := requireOK ( a . c . doRequest ( r ) )
if err != nil {
return nil , err
}
resp . Body . Close ( )
wm := & WriteMeta { RequestTime : rtt }
return wm , nil
}