Add Namespace support to the API module and the CLI commands (#6874)

Also update the Docs and fixup the HTTP API to return proper errors when someone attempts to use Namespaces with an OSS agent.

Add Namespace HTTP API docs

Make all API endpoints disallow unknown fields
This commit is contained in:
Matt Keeler 2019-12-06 11:14:56 -05:00 committed by GitHub
parent c15c81a7ed
commit b9996e6bbe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
105 changed files with 1648 additions and 82 deletions

View File

@ -9,6 +9,7 @@ import (
"github.com/hashicorp/consul/acl"
"github.com/hashicorp/consul/agent/structs"
"github.com/hashicorp/consul/lib"
)
// aclCreateResponse is used to wrap the ACL ID
@ -186,7 +187,9 @@ func (s *HTTPServer) ACLPolicyList(resp http.ResponseWriter, req *http.Request)
if done := s.parse(resp, req, &args.Datacenter, &args.QueryOptions); done {
return nil, nil
}
s.parseEntMeta(req, &args.EnterpriseMeta)
if err := s.parseEntMeta(req, &args.EnterpriseMeta); err != nil {
return nil, err
}
if args.Datacenter == "" {
args.Datacenter = s.agent.config.Datacenter
@ -244,7 +247,9 @@ func (s *HTTPServer) ACLPolicyRead(resp http.ResponseWriter, req *http.Request,
return nil, nil
}
s.parseEntMeta(req, &args.EnterpriseMeta)
if err := s.parseEntMeta(req, &args.EnterpriseMeta); err != nil {
return nil, err
}
if args.Datacenter == "" {
args.Datacenter = s.agent.config.Datacenter
@ -281,9 +286,11 @@ func (s *HTTPServer) aclPolicyWriteInternal(resp http.ResponseWriter, req *http.
Datacenter: s.agent.config.Datacenter,
}
s.parseToken(req, &args.Token)
s.parseEntMeta(req, &args.Policy.EnterpriseMeta)
if err := s.parseEntMeta(req, &args.Policy.EnterpriseMeta); err != nil {
return nil, err
}
if err := decodeBody(req.Body, &args.Policy); err != nil {
if err := s.rewordUnknownEnterpriseFieldError(lib.DecodeJSON(req.Body, &args.Policy)); err != nil {
return nil, BadRequestError{Reason: fmt.Sprintf("Policy decoding failed: %v", err)}
}
@ -315,7 +322,9 @@ func (s *HTTPServer) ACLPolicyDelete(resp http.ResponseWriter, req *http.Request
PolicyID: policyID,
}
s.parseToken(req, &args.Token)
s.parseEntMeta(req, &args.EnterpriseMeta)
if err := s.parseEntMeta(req, &args.EnterpriseMeta); err != nil {
return nil, err
}
var ignored string
if err := s.agent.RPC("ACL.PolicyDelete", args, &ignored); err != nil {
@ -338,7 +347,9 @@ func (s *HTTPServer) ACLTokenList(resp http.ResponseWriter, req *http.Request) (
return nil, nil
}
s.parseEntMeta(req, &args.EnterpriseMeta)
if err := s.parseEntMeta(req, &args.EnterpriseMeta); err != nil {
return nil, err
}
if args.Datacenter == "" {
args.Datacenter = s.agent.config.Datacenter
@ -442,7 +453,9 @@ func (s *HTTPServer) ACLTokenGet(resp http.ResponseWriter, req *http.Request, to
return nil, nil
}
s.parseEntMeta(req, &args.EnterpriseMeta)
if err := s.parseEntMeta(req, &args.EnterpriseMeta); err != nil {
return nil, err
}
if args.Datacenter == "" {
args.Datacenter = s.agent.config.Datacenter
@ -471,9 +484,11 @@ func (s *HTTPServer) aclTokenSetInternal(resp http.ResponseWriter, req *http.Req
Create: create,
}
s.parseToken(req, &args.Token)
s.parseEntMeta(req, &args.ACLToken.EnterpriseMeta)
if err := s.parseEntMeta(req, &args.ACLToken.EnterpriseMeta); err != nil {
return nil, err
}
if err := decodeBody(req.Body, &args.ACLToken); err != nil {
if err := s.rewordUnknownEnterpriseFieldError(lib.DecodeJSON(req.Body, &args.ACLToken)); err != nil {
return nil, BadRequestError{Reason: fmt.Sprintf("Token decoding failed: %v", err)}
}
@ -499,7 +514,9 @@ func (s *HTTPServer) ACLTokenDelete(resp http.ResponseWriter, req *http.Request,
TokenID: tokenID,
}
s.parseToken(req, &args.Token)
s.parseEntMeta(req, &args.EnterpriseMeta)
if err := s.parseEntMeta(req, &args.EnterpriseMeta); err != nil {
return nil, err
}
var ignored string
if err := s.agent.RPC("ACL.TokenDelete", args, &ignored); err != nil {
@ -518,8 +535,10 @@ func (s *HTTPServer) ACLTokenClone(resp http.ResponseWriter, req *http.Request,
Create: true,
}
s.parseEntMeta(req, &args.ACLToken.EnterpriseMeta)
if err := decodeBody(req.Body, &args.ACLToken); err != nil {
if err := s.parseEntMeta(req, &args.ACLToken.EnterpriseMeta); err != nil {
return nil, err
}
if err := s.rewordUnknownEnterpriseFieldError(lib.DecodeJSON(req.Body, &args.ACLToken)); err != nil {
return nil, BadRequestError{Reason: fmt.Sprintf("Token decoding failed: %v", err)}
}
s.parseToken(req, &args.Token)
@ -544,7 +563,9 @@ func (s *HTTPServer) ACLRoleList(resp http.ResponseWriter, req *http.Request) (i
if done := s.parse(resp, req, &args.Datacenter, &args.QueryOptions); done {
return nil, nil
}
s.parseEntMeta(req, &args.EnterpriseMeta)
if err := s.parseEntMeta(req, &args.EnterpriseMeta); err != nil {
return nil, err
}
if args.Datacenter == "" {
args.Datacenter = s.agent.config.Datacenter
@ -621,7 +642,9 @@ func (s *HTTPServer) ACLRoleRead(resp http.ResponseWriter, req *http.Request, ro
if done := s.parse(resp, req, &args.Datacenter, &args.QueryOptions); done {
return nil, nil
}
s.parseEntMeta(req, &args.EnterpriseMeta)
if err := s.parseEntMeta(req, &args.EnterpriseMeta); err != nil {
return nil, err
}
if args.Datacenter == "" {
args.Datacenter = s.agent.config.Datacenter
@ -654,9 +677,11 @@ func (s *HTTPServer) ACLRoleWrite(resp http.ResponseWriter, req *http.Request, r
Datacenter: s.agent.config.Datacenter,
}
s.parseToken(req, &args.Token)
s.parseEntMeta(req, &args.Role.EnterpriseMeta)
if err := s.parseEntMeta(req, &args.Role.EnterpriseMeta); err != nil {
return nil, err
}
if err := decodeBody(req.Body, &args.Role); err != nil {
if err := s.rewordUnknownEnterpriseFieldError(lib.DecodeJSON(req.Body, &args.Role)); err != nil {
return nil, BadRequestError{Reason: fmt.Sprintf("Role decoding failed: %v", err)}
}
@ -680,7 +705,9 @@ func (s *HTTPServer) ACLRoleDelete(resp http.ResponseWriter, req *http.Request,
RoleID: roleID,
}
s.parseToken(req, &args.Token)
s.parseEntMeta(req, &args.EnterpriseMeta)
if err := s.parseEntMeta(req, &args.EnterpriseMeta); err != nil {
return nil, err
}
var ignored string
if err := s.agent.RPC("ACL.RoleDelete", args, &ignored); err != nil {
@ -700,7 +727,9 @@ func (s *HTTPServer) ACLBindingRuleList(resp http.ResponseWriter, req *http.Requ
return nil, nil
}
s.parseEntMeta(req, &args.EnterpriseMeta)
if err := s.parseEntMeta(req, &args.EnterpriseMeta); err != nil {
return nil, err
}
if args.Datacenter == "" {
args.Datacenter = s.agent.config.Datacenter
@ -760,7 +789,9 @@ func (s *HTTPServer) ACLBindingRuleRead(resp http.ResponseWriter, req *http.Requ
return nil, nil
}
s.parseEntMeta(req, &args.EnterpriseMeta)
if err := s.parseEntMeta(req, &args.EnterpriseMeta); err != nil {
return nil, err
}
if args.Datacenter == "" {
args.Datacenter = s.agent.config.Datacenter
@ -793,9 +824,11 @@ func (s *HTTPServer) ACLBindingRuleWrite(resp http.ResponseWriter, req *http.Req
Datacenter: s.agent.config.Datacenter,
}
s.parseToken(req, &args.Token)
s.parseEntMeta(req, &args.BindingRule.EnterpriseMeta)
if err := s.parseEntMeta(req, &args.BindingRule.EnterpriseMeta); err != nil {
return nil, err
}
if err := decodeBody(req.Body, &args.BindingRule); err != nil {
if err := s.rewordUnknownEnterpriseFieldError(lib.DecodeJSON(req.Body, &args.BindingRule)); err != nil {
return nil, BadRequestError{Reason: fmt.Sprintf("BindingRule decoding failed: %v", err)}
}
@ -819,7 +852,9 @@ func (s *HTTPServer) ACLBindingRuleDelete(resp http.ResponseWriter, req *http.Re
BindingRuleID: bindingRuleID,
}
s.parseToken(req, &args.Token)
s.parseEntMeta(req, &args.EnterpriseMeta)
if err := s.parseEntMeta(req, &args.EnterpriseMeta); err != nil {
return nil, err
}
var ignored bool
if err := s.agent.RPC("ACL.BindingRuleDelete", args, &ignored); err != nil {
@ -838,7 +873,9 @@ func (s *HTTPServer) ACLAuthMethodList(resp http.ResponseWriter, req *http.Reque
if done := s.parse(resp, req, &args.Datacenter, &args.QueryOptions); done {
return nil, nil
}
s.parseEntMeta(req, &args.EnterpriseMeta)
if err := s.parseEntMeta(req, &args.EnterpriseMeta); err != nil {
return nil, err
}
if args.Datacenter == "" {
args.Datacenter = s.agent.config.Datacenter
@ -895,7 +932,9 @@ func (s *HTTPServer) ACLAuthMethodRead(resp http.ResponseWriter, req *http.Reque
if done := s.parse(resp, req, &args.Datacenter, &args.QueryOptions); done {
return nil, nil
}
s.parseEntMeta(req, &args.EnterpriseMeta)
if err := s.parseEntMeta(req, &args.EnterpriseMeta); err != nil {
return nil, err
}
if args.Datacenter == "" {
args.Datacenter = s.agent.config.Datacenter
@ -929,9 +968,11 @@ func (s *HTTPServer) ACLAuthMethodWrite(resp http.ResponseWriter, req *http.Requ
Datacenter: s.agent.config.Datacenter,
}
s.parseToken(req, &args.Token)
s.parseEntMeta(req, &args.AuthMethod.EnterpriseMeta)
if err := s.parseEntMeta(req, &args.AuthMethod.EnterpriseMeta); err != nil {
return nil, err
}
if err := decodeBody(req.Body, &args.AuthMethod); err != nil {
if err := s.rewordUnknownEnterpriseFieldError(lib.DecodeJSON(req.Body, &args.AuthMethod)); err != nil {
return nil, BadRequestError{Reason: fmt.Sprintf("AuthMethod decoding failed: %v", err)}
}
@ -958,7 +999,9 @@ func (s *HTTPServer) ACLAuthMethodDelete(resp http.ResponseWriter, req *http.Req
AuthMethodName: methodName,
}
s.parseToken(req, &args.Token)
s.parseEntMeta(req, &args.EnterpriseMeta)
if err := s.parseEntMeta(req, &args.EnterpriseMeta); err != nil {
return nil, err
}
var ignored bool
if err := s.agent.RPC("ACL.AuthMethodDelete", args, &ignored); err != nil {
@ -978,10 +1021,12 @@ func (s *HTTPServer) ACLLogin(resp http.ResponseWriter, req *http.Request) (inte
Auth: &structs.ACLLoginParams{},
}
s.parseDC(req, &args.Datacenter)
s.parseEntMeta(req, &args.Auth.EnterpriseMeta)
if err := s.parseEntMeta(req, &args.Auth.EnterpriseMeta); err != nil {
return nil, err
}
if err := decodeBody(req.Body, &args.Auth); err != nil {
return nil, BadRequestError{Reason: fmt.Sprintf("Failed to decode request body: %v", err)}
if err := s.rewordUnknownEnterpriseFieldError(lib.DecodeJSON(req.Body, &args.Auth)); err != nil {
return nil, BadRequestError{Reason: fmt.Sprintf("Failed to decode request body:: %v", err)}
}
var out structs.ACLToken

View File

@ -3055,7 +3055,7 @@ func testCreateToken(t *testing.T, a *TestAgent, rules string) string {
policyID := testCreatePolicy(t, a, policyName, rules)
args := map[string]interface{}{
"Name": "User Token",
"Description": "User Token",
"Policies": []map[string]interface{}{
map[string]interface{}{
"ID": policyID,

View File

@ -1,7 +1,6 @@
package agent
import (
"encoding/json"
"fmt"
"net/http"
"strings"
@ -107,7 +106,7 @@ func (t *discoveryChainReadRequest) UnmarshalJSON(data []byte) (err error) {
}{
Alias: (*Alias)(t),
}
if err = json.Unmarshal(data, &aux); err != nil {
if err = lib.UnmarshalJSON(data, &aux); err != nil {
return err
}

View File

@ -25,6 +25,7 @@ import (
"github.com/hashicorp/consul/agent/consul"
"github.com/hashicorp/consul/agent/structs"
"github.com/hashicorp/consul/api"
"github.com/hashicorp/consul/lib"
"github.com/hashicorp/go-cleanhttp"
"github.com/mitchellh/mapstructure"
"github.com/pkg/errors"
@ -573,11 +574,7 @@ func (s *HTTPServer) Index(resp http.ResponseWriter, req *http.Request) {
}
func decodeBody(body io.Reader, out interface{}) error {
if body == nil {
return io.EOF
}
return json.NewDecoder(body).Decode(&out)
return lib.DecodeJSON(body, out)
}
// decodeBodyDeprecated is deprecated, please ues decodeBody above.

View File

@ -3,10 +3,38 @@
package agent
import (
"fmt"
"net/http"
"strings"
"github.com/hashicorp/consul/agent/structs"
)
func (s *HTTPServer) parseEntMeta(req *http.Request, entMeta *structs.EnterpriseMeta) {
func (s *HTTPServer) parseEntMeta(req *http.Request, entMeta *structs.EnterpriseMeta) error {
if headerNS := req.Header.Get("X-Consul-Namespace"); headerNS != "" {
return BadRequestError{Reason: "Invalid header: \"X-Consul-Namespace\" - Namespaces is a Consul Enterprise feature"}
}
if queryNS := req.URL.Query().Get("ns"); queryNS != "" {
return BadRequestError{Reason: "Invalid query parameter: \"ns\" - Namespaces is a Consul Enterprise feature"}
}
return nil
}
func (s *HTTPServer) rewordUnknownEnterpriseFieldError(err error) error {
if err == nil {
return nil
}
msg := err.Error()
if strings.Contains(msg, "json: unknown field ") {
quotedField := strings.TrimPrefix(msg, "json: unknown field ")
switch quotedField {
case `"Namespace"`:
return fmt.Errorf("%v - Namespaces is a Consul Enterprise feature", err)
}
}
return err
}

View File

@ -18,7 +18,9 @@ func (s *HTTPServer) KVSEndpoint(resp http.ResponseWriter, req *http.Request) (i
if done := s.parse(resp, req, &args.Datacenter, &args.QueryOptions); done {
return nil, nil
}
s.parseEntMeta(req, &args.EnterpriseMeta)
if err := s.parseEntMeta(req, &args.EnterpriseMeta); err != nil {
return nil, err
}
// Pull out the key name, validation left to each sub-handler
args.Key = strings.TrimPrefix(req.URL.Path, "/v1/kv/")

View File

@ -7,6 +7,7 @@ import (
"time"
"github.com/hashicorp/consul/agent/structs"
"github.com/hashicorp/consul/lib"
"github.com/hashicorp/consul/types"
)
@ -31,11 +32,13 @@ func (s *HTTPServer) SessionCreate(resp http.ResponseWriter, req *http.Request)
}
s.parseDC(req, &args.Datacenter)
s.parseToken(req, &args.Token)
s.parseEntMeta(req, &args.Session.EnterpriseMeta)
if err := s.parseEntMeta(req, &args.Session.EnterpriseMeta); err != nil {
return nil, err
}
// Handle optional request body
if req.ContentLength > 0 {
if err := decodeBody(req.Body, &args.Session); err != nil {
if err := s.rewordUnknownEnterpriseFieldError(lib.DecodeJSON(req.Body, &args.Session)); err != nil {
resp.WriteHeader(http.StatusBadRequest)
fmt.Fprintf(resp, "Request decode failed: %v", err)
return nil, nil
@ -80,7 +83,9 @@ func (s *HTTPServer) SessionDestroy(resp http.ResponseWriter, req *http.Request)
}
s.parseDC(req, &args.Datacenter)
s.parseToken(req, &args.Token)
s.parseEntMeta(req, &args.Session.EnterpriseMeta)
if err := s.parseEntMeta(req, &args.Session.EnterpriseMeta); err != nil {
return nil, err
}
// Pull out the session id
args.Session.ID = strings.TrimPrefix(req.URL.Path, "/v1/session/destroy/")
@ -103,7 +108,9 @@ func (s *HTTPServer) SessionRenew(resp http.ResponseWriter, req *http.Request) (
if done := s.parse(resp, req, &args.Datacenter, &args.QueryOptions); done {
return nil, nil
}
s.parseEntMeta(req, &args.EnterpriseMeta)
if err := s.parseEntMeta(req, &args.EnterpriseMeta); err != nil {
return nil, err
}
// Pull out the session id
args.SessionID = strings.TrimPrefix(req.URL.Path, "/v1/session/renew/")
@ -131,7 +138,9 @@ func (s *HTTPServer) SessionGet(resp http.ResponseWriter, req *http.Request) (in
if done := s.parse(resp, req, &args.Datacenter, &args.QueryOptions); done {
return nil, nil
}
s.parseEntMeta(req, &args.EnterpriseMeta)
if err := s.parseEntMeta(req, &args.EnterpriseMeta); err != nil {
return nil, err
}
// Pull out the session id
args.SessionID = strings.TrimPrefix(req.URL.Path, "/v1/session/info/")
@ -160,7 +169,9 @@ func (s *HTTPServer) SessionList(resp http.ResponseWriter, req *http.Request) (i
if done := s.parse(resp, req, &args.Datacenter, &args.QueryOptions); done {
return nil, nil
}
s.parseEntMeta(req, &args.EnterpriseMeta)
if err := s.parseEntMeta(req, &args.EnterpriseMeta); err != nil {
return nil, err
}
var out structs.IndexedSessions
defer setMeta(resp, &out.QueryMeta)
@ -181,7 +192,9 @@ func (s *HTTPServer) SessionsForNode(resp http.ResponseWriter, req *http.Request
if done := s.parse(resp, req, &args.Datacenter, &args.QueryOptions); done {
return nil, nil
}
s.parseEntMeta(req, &args.EnterpriseMeta)
if err := s.parseEntMeta(req, &args.EnterpriseMeta); err != nil {
return nil, err
}
// Pull out the node name
args.Node = strings.TrimPrefix(req.URL.Path, "/v1/session/node/")

View File

@ -2,7 +2,6 @@ package structs
import (
"encoding/binary"
"encoding/json"
"errors"
"fmt"
"hash"
@ -12,6 +11,7 @@ import (
"time"
"github.com/hashicorp/consul/acl"
"github.com/hashicorp/consul/lib"
"golang.org/x/crypto/blake2b"
)
@ -270,7 +270,8 @@ func (t *ACLToken) UnmarshalJSON(data []byte) (err error) {
}{
Alias: (*Alias)(t),
}
if err = json.Unmarshal(data, &aux); err != nil {
if err = lib.UnmarshalJSON(data, &aux); err != nil {
return err
}
if aux.ExpirationTTL != nil {
@ -577,7 +578,8 @@ func (t *ACLPolicy) UnmarshalJSON(data []byte) error {
}{
Alias: (*Alias)(t),
}
if err := json.Unmarshal(data, &aux); err != nil {
if err := lib.UnmarshalJSON(data, &aux); err != nil {
return err
}
if aux.Hash != "" {
@ -823,7 +825,8 @@ func (t *ACLRole) UnmarshalJSON(data []byte) error {
}{
Alias: (*Alias)(t),
}
if err := json.Unmarshal(data, &aux); err != nil {
if err := lib.UnmarshalJSON(data, &aux); err != nil {
return err
}
if aux.Hash != "" {

View File

@ -1,10 +1,10 @@
package structs
import (
"encoding/json"
"time"
"github.com/hashicorp/consul/api"
"github.com/hashicorp/consul/lib"
"github.com/hashicorp/consul/types"
)
@ -66,7 +66,7 @@ func (t *CheckDefinition) UnmarshalJSON(data []byte) (err error) {
}{
Alias: (*Alias)(t),
}
if err = json.Unmarshal(data, &aux); err != nil {
if err = lib.UnmarshalJSON(data, &aux); err != nil {
return err
}

View File

@ -1,11 +1,11 @@
package structs
import (
"encoding/json"
"fmt"
"reflect"
"time"
"github.com/hashicorp/consul/lib"
"github.com/hashicorp/consul/types"
)
@ -76,11 +76,16 @@ func (t *CheckType) UnmarshalJSON(data []byte) (err error) {
DockerContainerIDSnake string `json:"docker_container_id"`
TLSSkipVerifySnake bool `json:"tls_skip_verify"`
// These are going to be ignored but since we are disallowing unknown fields
// during parsing we have to be explicit about parsing but not using these.
ServiceID string `json:"ServiceID"`
ServiceIDSnake string `json:"service_id"`
*Alias
}{
Alias: (*Alias)(t),
}
if err = json.Unmarshal(data, aux); err != nil {
if err = lib.UnmarshalJSON(data, aux); err != nil {
return err
}
if aux.DeregisterCriticalServiceAfter == nil {

View File

@ -12,6 +12,7 @@ import (
"github.com/hashicorp/consul/acl"
"github.com/hashicorp/consul/agent/cache"
"github.com/hashicorp/consul/lib"
"github.com/mitchellh/hashstructure"
)
@ -342,7 +343,7 @@ func (e *ServiceRouteDestination) UnmarshalJSON(data []byte) error {
}{
Alias: (*Alias)(e),
}
if err := json.Unmarshal(data, &aux); err != nil {
if err := lib.UnmarshalJSON(data, &aux); err != nil {
return err
}
var err error
@ -624,7 +625,7 @@ func (e *ServiceResolverConfigEntry) UnmarshalJSON(data []byte) error {
}{
Alias: (*Alias)(e),
}
if err := json.Unmarshal(data, &aux); err != nil {
if err := lib.UnmarshalJSON(data, &aux); err != nil {
return err
}
var err error

View File

@ -1,7 +1,6 @@
package structs
import (
"encoding/json"
"fmt"
"reflect"
"time"
@ -310,7 +309,7 @@ func (c *CAConfiguration) UnmarshalJSON(data []byte) (err error) {
}{
Alias: (*Alias)(c),
}
if err = json.Unmarshal(data, &aux); err != nil {
if err = lib.UnmarshalJSON(data, &aux); err != nil {
return err
}
if aux.ForceWithoutCrossSigningSnake {

View File

@ -133,7 +133,7 @@ func (t *ConnectProxyConfig) UnmarshalJSON(data []byte) (err error) {
}{
Alias: (*Alias)(t),
}
if err = json.Unmarshal(data, &aux); err != nil {
if err = lib.UnmarshalJSON(data, &aux); err != nil {
return err
}
if t.DestinationServiceName == "" {
@ -263,7 +263,7 @@ func (t *Upstream) UnmarshalJSON(data []byte) (err error) {
}{
Alias: (*Alias)(t),
}
if err = json.Unmarshal(data, &aux); err != nil {
if err = lib.UnmarshalJSON(data, &aux); err != nil {
return err
}
if t.DestinationType == "" {
@ -430,7 +430,7 @@ func (t *ExposePath) UnmarshalJSON(data []byte) (err error) {
}{
Alias: (*Alias)(t),
}
if err = json.Unmarshal(data, &aux); err != nil {
if err = lib.UnmarshalJSON(data, &aux); err != nil {
return err
}
if t.LocalPathPort == 0 {

View File

@ -4,6 +4,8 @@ import (
"encoding/json"
"fmt"
"time"
"github.com/hashicorp/consul/lib"
)
// CompiledDiscoveryChain is the result from taking a set of related config
@ -155,7 +157,7 @@ func (r *DiscoveryResolver) UnmarshalJSON(data []byte) error {
}{
Alias: (*Alias)(r),
}
if err := json.Unmarshal(data, &aux); err != nil {
if err := lib.UnmarshalJSON(data, &aux); err != nil {
return err
}
var err error

View File

@ -2,7 +2,6 @@ package structs
import (
"encoding/binary"
"encoding/json"
"fmt"
"sort"
"strconv"
@ -10,6 +9,7 @@ import (
"time"
"github.com/hashicorp/consul/agent/cache"
"github.com/hashicorp/consul/lib"
"github.com/hashicorp/go-multierror"
"github.com/mitchellh/hashstructure"
@ -95,7 +95,7 @@ func (t *Intention) UnmarshalJSON(data []byte) (err error) {
}{
Alias: (*Alias)(t),
}
if err = json.Unmarshal(data, &aux); err != nil {
if err = lib.UnmarshalJSON(data, &aux); err != nil {
return err
}

View File

@ -1,8 +1,7 @@
package structs
import (
"encoding/json"
"github.com/hashicorp/consul/lib"
"github.com/hashicorp/go-multierror"
)
@ -44,7 +43,7 @@ func (t *ServiceDefinition) UnmarshalJSON(data []byte) (err error) {
}{
Alias: (*Alias)(t),
}
if err = json.Unmarshal(data, &aux); err != nil {
if err = lib.UnmarshalJSON(data, &aux); err != nil {
return err
}
if aux.EnableTagOverrideSnake {

View File

@ -20,6 +20,7 @@ import (
"github.com/hashicorp/consul/agent/cache"
"github.com/hashicorp/consul/api"
"github.com/hashicorp/consul/lib"
"github.com/hashicorp/consul/types"
)
@ -895,7 +896,7 @@ func (t *ServiceConnect) UnmarshalJSON(data []byte) (err error) {
}{
Alias: (*Alias)(t),
}
if err = json.Unmarshal(data, &aux); err != nil {
if err = lib.UnmarshalJSON(data, &aux); err != nil {
return err
}
if t.SidecarService == nil {
@ -1232,7 +1233,7 @@ func (t *HealthCheckDefinition) UnmarshalJSON(data []byte) (err error) {
}{
Alias: (*Alias)(t),
}
if err := json.Unmarshal(data, &aux); err != nil {
if err := lib.UnmarshalJSON(data, &aux); err != nil {
return err
}
if aux.Interval != nil {
@ -1735,7 +1736,8 @@ func (t *Session) UnmarshalJSON(data []byte) (err error) {
}{
Alias: (*Alias)(t),
}
if err = json.Unmarshal(data, &aux); err != nil {
if err = lib.UnmarshalJSON(data, &aux); err != nil {
return err
}
if aux.LockDelay != nil {

View File

@ -45,6 +45,10 @@ type ACLToken struct {
// 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 {
@ -60,6 +64,10 @@ type ACLTokenListEntry struct {
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
@ -104,6 +112,10 @@ type ACLPolicy struct {
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 {
@ -114,6 +126,10 @@ type ACLPolicyListEntry struct {
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
@ -128,6 +144,10 @@ type ACLRole struct {
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.
@ -151,6 +171,10 @@ type ACLBindingRule struct {
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 {
@ -165,6 +189,10 @@ type ACLAuthMethod struct {
CreateIndex uint64
ModifyIndex uint64
// Namespace is the namespace the ACLAuthMethod is associated with.
// Namespacing is a Consul Enterprise feature.
Namespace string `json:",omitempty"`
}
type ACLAuthMethodListEntry struct {
@ -173,6 +201,10 @@ type ACLAuthMethodListEntry struct {
Description string
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

View File

@ -13,6 +13,9 @@ import (
func PrintToken(token *api.ACLToken, ui cli.Ui, showMeta bool) {
ui.Info(fmt.Sprintf("AccessorID: %s", token.AccessorID))
ui.Info(fmt.Sprintf("SecretID: %s", token.SecretID))
if token.Namespace != "" {
ui.Info(fmt.Sprintf("Namespace: %s", token.Namespace))
}
ui.Info(fmt.Sprintf("Description: %s", token.Description))
ui.Info(fmt.Sprintf("Local: %t", token.Local))
ui.Info(fmt.Sprintf("Create Time: %v", token.CreateTime))
@ -54,6 +57,9 @@ func PrintToken(token *api.ACLToken, ui cli.Ui, showMeta bool) {
func PrintTokenListEntry(token *api.ACLTokenListEntry, ui cli.Ui, showMeta bool) {
ui.Info(fmt.Sprintf("AccessorID: %s", token.AccessorID))
if token.Namespace != "" {
ui.Info(fmt.Sprintf("Namespace: %s", token.Namespace))
}
ui.Info(fmt.Sprintf("Description: %s", token.Description))
ui.Info(fmt.Sprintf("Local: %t", token.Local))
ui.Info(fmt.Sprintf("Create Time: %v", token.CreateTime))
@ -93,6 +99,9 @@ func PrintTokenListEntry(token *api.ACLTokenListEntry, ui cli.Ui, showMeta bool)
func PrintPolicy(policy *api.ACLPolicy, ui cli.Ui, showMeta bool) {
ui.Info(fmt.Sprintf("ID: %s", policy.ID))
ui.Info(fmt.Sprintf("Name: %s", policy.Name))
if policy.Namespace != "" {
ui.Info(fmt.Sprintf("Namespace: %s", policy.Namespace))
}
ui.Info(fmt.Sprintf("Description: %s", policy.Description))
ui.Info(fmt.Sprintf("Datacenters: %s", strings.Join(policy.Datacenters, ", ")))
if showMeta {
@ -107,6 +116,9 @@ func PrintPolicy(policy *api.ACLPolicy, ui cli.Ui, showMeta bool) {
func PrintPolicyListEntry(policy *api.ACLPolicyListEntry, ui cli.Ui, showMeta bool) {
ui.Info(fmt.Sprintf("%s:", policy.Name))
ui.Info(fmt.Sprintf(" ID: %s", policy.ID))
if policy.Namespace != "" {
ui.Info(fmt.Sprintf(" Namespace: %s", policy.Namespace))
}
ui.Info(fmt.Sprintf(" Description: %s", policy.Description))
ui.Info(fmt.Sprintf(" Datacenters: %s", strings.Join(policy.Datacenters, ", ")))
if showMeta {
@ -119,6 +131,9 @@ func PrintPolicyListEntry(policy *api.ACLPolicyListEntry, ui cli.Ui, showMeta bo
func PrintRole(role *api.ACLRole, ui cli.Ui, showMeta bool) {
ui.Info(fmt.Sprintf("ID: %s", role.ID))
ui.Info(fmt.Sprintf("Name: %s", role.Name))
if role.Namespace != "" {
ui.Info(fmt.Sprintf("Namespace: %s", role.Namespace))
}
ui.Info(fmt.Sprintf("Description: %s", role.Description))
if showMeta {
ui.Info(fmt.Sprintf("Hash: %x", role.Hash))
@ -146,6 +161,9 @@ func PrintRole(role *api.ACLRole, ui cli.Ui, showMeta bool) {
func PrintRoleListEntry(role *api.ACLRole, ui cli.Ui, showMeta bool) {
ui.Info(fmt.Sprintf("%s:", role.Name))
ui.Info(fmt.Sprintf(" ID: %s", role.ID))
if role.Namespace != "" {
ui.Info(fmt.Sprintf(" Namespace: %s", role.Namespace))
}
ui.Info(fmt.Sprintf(" Description: %s", role.Description))
if showMeta {
ui.Info(fmt.Sprintf(" Hash: %x", role.Hash))
@ -173,6 +191,9 @@ func PrintRoleListEntry(role *api.ACLRole, ui cli.Ui, showMeta bool) {
func PrintAuthMethod(method *api.ACLAuthMethod, ui cli.Ui, showMeta bool) {
ui.Info(fmt.Sprintf("Name: %s", method.Name))
ui.Info(fmt.Sprintf("Type: %s", method.Type))
if method.Namespace != "" {
ui.Info(fmt.Sprintf("Namespace: %s", method.Namespace))
}
ui.Info(fmt.Sprintf("Description: %s", method.Description))
if showMeta {
ui.Info(fmt.Sprintf("Create Index: %d", method.CreateIndex))
@ -189,6 +210,9 @@ func PrintAuthMethod(method *api.ACLAuthMethod, ui cli.Ui, showMeta bool) {
func PrintAuthMethodListEntry(method *api.ACLAuthMethodListEntry, ui cli.Ui, showMeta bool) {
ui.Info(fmt.Sprintf("%s:", method.Name))
ui.Info(fmt.Sprintf(" Type: %s", method.Type))
if method.Namespace != "" {
ui.Info(fmt.Sprintf(" Namespace: %s", method.Namespace))
}
ui.Info(fmt.Sprintf(" Description: %s", method.Description))
if showMeta {
ui.Info(fmt.Sprintf(" Create Index: %d", method.CreateIndex))
@ -198,6 +222,9 @@ func PrintAuthMethodListEntry(method *api.ACLAuthMethodListEntry, ui cli.Ui, sho
func PrintBindingRule(rule *api.ACLBindingRule, ui cli.Ui, showMeta bool) {
ui.Info(fmt.Sprintf("ID: %s", rule.ID))
if rule.Namespace != "" {
ui.Info(fmt.Sprintf("Namespace: %s", rule.Namespace))
}
ui.Info(fmt.Sprintf("AuthMethod: %s", rule.AuthMethod))
ui.Info(fmt.Sprintf("Description: %s", rule.Description))
ui.Info(fmt.Sprintf("BindType: %s", rule.BindType))
@ -211,6 +238,9 @@ func PrintBindingRule(rule *api.ACLBindingRule, ui cli.Ui, showMeta bool) {
func PrintBindingRuleListEntry(rule *api.ACLBindingRule, ui cli.Ui, showMeta bool) {
ui.Info(fmt.Sprintf("%s:", rule.ID))
if rule.Namespace != "" {
ui.Info(fmt.Sprintf(" Namespace: %s", rule.Namespace))
}
ui.Info(fmt.Sprintf(" AuthMethod: %s", rule.AuthMethod))
ui.Info(fmt.Sprintf(" Description: %s", rule.Description))
ui.Info(fmt.Sprintf(" BindType: %s", rule.BindType))

View File

@ -94,6 +94,7 @@ func (c *cmd) init() {
c.http = &flags.HTTPFlags{}
flags.Merge(c.flags, c.http.ClientFlags())
flags.Merge(c.flags, c.http.ServerFlags())
flags.Merge(c.flags, c.http.NamespaceFlags())
c.help = flags.Usage(help, c.flags)
}

View File

@ -36,6 +36,7 @@ func (c *cmd) init() {
c.http = &flags.HTTPFlags{}
flags.Merge(c.flags, c.http.ClientFlags())
flags.Merge(c.flags, c.http.ServerFlags())
flags.Merge(c.flags, c.http.NamespaceFlags())
c.help = flags.Usage(help, c.flags)
}

View File

@ -38,6 +38,7 @@ func (c *cmd) init() {
c.http = &flags.HTTPFlags{}
flags.Merge(c.flags, c.http.ClientFlags())
flags.Merge(c.flags, c.http.ServerFlags())
flags.Merge(c.flags, c.http.NamespaceFlags())
c.help = flags.Usage(help, c.flags)
}

View File

@ -47,6 +47,7 @@ func (c *cmd) init() {
c.http = &flags.HTTPFlags{}
flags.Merge(c.flags, c.http.ClientFlags())
flags.Merge(c.flags, c.http.ServerFlags())
flags.Merge(c.flags, c.http.NamespaceFlags())
c.help = flags.Usage(help, c.flags)
}

View File

@ -94,6 +94,7 @@ func (c *cmd) init() {
c.http = &flags.HTTPFlags{}
flags.Merge(c.flags, c.http.ClientFlags())
flags.Merge(c.flags, c.http.ServerFlags())
flags.Merge(c.flags, c.http.NamespaceFlags())
c.help = flags.Usage(help, c.flags)
}

View File

@ -79,6 +79,7 @@ func (c *cmd) init() {
c.http = &flags.HTTPFlags{}
flags.Merge(c.flags, c.http.ClientFlags())
flags.Merge(c.flags, c.http.ServerFlags())
flags.Merge(c.flags, c.http.NamespaceFlags())
c.help = flags.Usage(help, c.flags)
}

View File

@ -39,6 +39,7 @@ func (c *cmd) init() {
c.http = &flags.HTTPFlags{}
flags.Merge(c.flags, c.http.ClientFlags())
flags.Merge(c.flags, c.http.ServerFlags())
flags.Merge(c.flags, c.http.NamespaceFlags())
c.help = flags.Usage(help, c.flags)
}

View File

@ -47,6 +47,7 @@ func (c *cmd) init() {
c.http = &flags.HTTPFlags{}
flags.Merge(c.flags, c.http.ClientFlags())
flags.Merge(c.flags, c.http.ServerFlags())
flags.Merge(c.flags, c.http.NamespaceFlags())
c.help = flags.Usage(help, c.flags)
}

View File

@ -49,6 +49,7 @@ func (c *cmd) init() {
c.http = &flags.HTTPFlags{}
flags.Merge(c.flags, c.http.ClientFlags())
flags.Merge(c.flags, c.http.ServerFlags())
flags.Merge(c.flags, c.http.NamespaceFlags())
c.help = flags.Usage(help, c.flags)
}

View File

@ -91,6 +91,7 @@ func (c *cmd) init() {
c.http = &flags.HTTPFlags{}
flags.Merge(c.flags, c.http.ClientFlags())
flags.Merge(c.flags, c.http.ServerFlags())
flags.Merge(c.flags, c.http.NamespaceFlags())
c.help = flags.Usage(help, c.flags)
}

View File

@ -57,6 +57,7 @@ func (c *cmd) init() {
c.http = &flags.HTTPFlags{}
flags.Merge(c.flags, c.http.ClientFlags())
flags.Merge(c.flags, c.http.ServerFlags())
flags.Merge(c.flags, c.http.NamespaceFlags())
c.help = flags.Usage(help, c.flags)
}

View File

@ -34,6 +34,7 @@ func (c *cmd) init() {
c.http = &flags.HTTPFlags{}
flags.Merge(c.flags, c.http.ClientFlags())
flags.Merge(c.flags, c.http.ServerFlags())
flags.Merge(c.flags, c.http.NamespaceFlags())
c.help = flags.Usage(help, c.flags)
}

View File

@ -32,6 +32,7 @@ func (c *cmd) init() {
c.http = &flags.HTTPFlags{}
flags.Merge(c.flags, c.http.ClientFlags())
flags.Merge(c.flags, c.http.ServerFlags())
flags.Merge(c.flags, c.http.NamespaceFlags())
c.help = flags.Usage(help, c.flags)
}

View File

@ -37,6 +37,7 @@ func (c *cmd) init() {
c.http = &flags.HTTPFlags{}
flags.Merge(c.flags, c.http.ClientFlags())
flags.Merge(c.flags, c.http.ServerFlags())
flags.Merge(c.flags, c.http.NamespaceFlags())
c.help = flags.Usage(help, c.flags)
}

View File

@ -57,6 +57,7 @@ func (c *cmd) init() {
c.http = &flags.HTTPFlags{}
flags.Merge(c.flags, c.http.ClientFlags())
flags.Merge(c.flags, c.http.ServerFlags())
flags.Merge(c.flags, c.http.NamespaceFlags())
c.help = flags.Usage(help, c.flags)
}

View File

@ -48,6 +48,7 @@ func (c *cmd) init() {
c.http = &flags.HTTPFlags{}
flags.Merge(c.flags, c.http.ClientFlags())
flags.Merge(c.flags, c.http.ServerFlags())
flags.Merge(c.flags, c.http.NamespaceFlags())
c.help = flags.Usage(help, c.flags)
}

View File

@ -34,6 +34,7 @@ func (c *cmd) init() {
c.http = &flags.HTTPFlags{}
flags.Merge(c.flags, c.http.ClientFlags())
flags.Merge(c.flags, c.http.ServerFlags())
flags.Merge(c.flags, c.http.NamespaceFlags())
c.help = flags.Usage(help, c.flags)
}

View File

@ -32,6 +32,7 @@ func (c *cmd) init() {
c.http = &flags.HTTPFlags{}
flags.Merge(c.flags, c.http.ClientFlags())
flags.Merge(c.flags, c.http.ServerFlags())
flags.Merge(c.flags, c.http.NamespaceFlags())
c.help = flags.Usage(help, c.flags)
}

View File

@ -38,6 +38,7 @@ func (c *cmd) init() {
c.http = &flags.HTTPFlags{}
flags.Merge(c.flags, c.http.ClientFlags())
flags.Merge(c.flags, c.http.ServerFlags())
flags.Merge(c.flags, c.http.NamespaceFlags())
c.help = flags.Usage(help, c.flags)
}

View File

@ -56,6 +56,7 @@ func (c *cmd) init() {
c.http = &flags.HTTPFlags{}
flags.Merge(c.flags, c.http.ClientFlags())
flags.Merge(c.flags, c.http.ServerFlags())
flags.Merge(c.flags, c.http.NamespaceFlags())
c.help = flags.Usage(help, c.flags)
}

View File

@ -35,6 +35,7 @@ func (c *cmd) init() {
c.http = &flags.HTTPFlags{}
flags.Merge(c.flags, c.http.ClientFlags())
flags.Merge(c.flags, c.http.ServerFlags())
flags.Merge(c.flags, c.http.NamespaceFlags())
c.help = flags.Usage(help, c.flags)
}

View File

@ -21,6 +21,7 @@ func parseCloneOutput(t *testing.T, output string) *api.ACLToken {
re := regexp.MustCompile("Token cloned successfully.\n" +
"AccessorID: ([a-zA-Z0-9\\-]{36})\n" +
"SecretID: ([a-zA-Z0-9\\-]{36})\n" +
"(?:Namespace: default\n)?" +
"Description: ([^\n]*)\n" +
"Local: (true|false)\n" +
"Create Time: ([^\n]+)\n" +

View File

@ -62,6 +62,7 @@ func (c *cmd) init() {
c.http = &flags.HTTPFlags{}
flags.Merge(c.flags, c.http.ClientFlags())
flags.Merge(c.flags, c.http.ServerFlags())
flags.Merge(c.flags, c.http.NamespaceFlags())
c.help = flags.Usage(help, c.flags)
}

View File

@ -33,6 +33,7 @@ func (c *cmd) init() {
c.http = &flags.HTTPFlags{}
flags.Merge(c.flags, c.http.ClientFlags())
flags.Merge(c.flags, c.http.ServerFlags())
flags.Merge(c.flags, c.http.NamespaceFlags())
c.help = flags.Usage(help, c.flags)
}

View File

@ -31,6 +31,7 @@ func (c *cmd) init() {
c.http = &flags.HTTPFlags{}
flags.Merge(c.flags, c.http.ClientFlags())
flags.Merge(c.flags, c.http.ServerFlags())
flags.Merge(c.flags, c.http.NamespaceFlags())
c.help = flags.Usage(help, c.flags)
}

View File

@ -39,6 +39,7 @@ func (c *cmd) init() {
c.http = &flags.HTTPFlags{}
flags.Merge(c.flags, c.http.ClientFlags())
flags.Merge(c.flags, c.http.ServerFlags())
flags.Merge(c.flags, c.http.NamespaceFlags())
c.help = flags.Usage(help, c.flags)
}

View File

@ -70,6 +70,7 @@ func (c *cmd) init() {
c.http = &flags.HTTPFlags{}
flags.Merge(c.flags, c.http.ClientFlags())
flags.Merge(c.flags, c.http.ServerFlags())
flags.Merge(c.flags, c.http.NamespaceFlags())
c.help = flags.Usage(help, c.flags)
}

View File

@ -18,11 +18,13 @@ type HTTPFlags struct {
certFile StringValue
keyFile StringValue
tlsServerName StringValue
namespace StringValue
// server flags
datacenter StringValue
stale BoolValue
// namespace flags
namespace StringValue
}
func (f *HTTPFlags) ClientFlags() *flag.FlagSet {
@ -56,11 +58,6 @@ func (f *HTTPFlags) ClientFlags() *flag.FlagSet {
fs.Var(&f.tlsServerName, "tls-server-name",
"The server name to use as the SNI host when connecting via TLS. This "+
"can also be specified via the CONSUL_TLS_SERVER_NAME environment variable.")
// TODO (namespaces) Do we want to allow setting via an env var? CONSUL_NAMESPACE
fs.Var(&f.namespace, "ns",
"Specifies the namespace to query. If not provided, the namespace will be inferred +"+
"from the request's ACL token, or will default to the `default` namespace.")
return fs
}
@ -77,6 +74,16 @@ func (f *HTTPFlags) ServerFlags() *flag.FlagSet {
return fs
}
func (f *HTTPFlags) NamespaceFlags() *flag.FlagSet {
fs := flag.NewFlagSet("", flag.ContinueOnError)
// TODO (namespaces) Do we want to allow setting via an env var? CONSUL_NAMESPACE
fs.Var(&f.namespace, "ns",
"Specifies the namespace to query. If not provided, the namespace will be inferred +"+
"from the request's ACL token, or will default to the `default` namespace. "+
"Namespaces is a Consul Enterprise feature.")
return fs
}
func (f *HTTPFlags) Addr() string {
return f.address.String()
}

View File

@ -39,6 +39,7 @@ func (c *cmd) init() {
c.http = &flags.HTTPFlags{}
flags.Merge(c.flags, c.http.ClientFlags())
flags.Merge(c.flags, c.http.ServerFlags())
flags.Merge(c.flags, c.http.NamespaceFlags())
c.help = flags.Usage(help, c.flags)
}

View File

@ -29,6 +29,7 @@ func (c *cmd) init() {
c.http = &flags.HTTPFlags{}
flags.Merge(c.flags, c.http.ClientFlags())
flags.Merge(c.flags, c.http.ServerFlags())
flags.Merge(c.flags, c.http.NamespaceFlags())
c.help = flags.Usage(help, c.flags)
}

View File

@ -54,6 +54,7 @@ func (c *cmd) init() {
c.http = &flags.HTTPFlags{}
flags.Merge(c.flags, c.http.ClientFlags())
flags.Merge(c.flags, c.http.ServerFlags())
flags.Merge(c.flags, c.http.NamespaceFlags())
c.help = flags.Usage(help, c.flags)
}

View File

@ -38,6 +38,7 @@ func (c *cmd) init() {
c.http = &flags.HTTPFlags{}
flags.Merge(c.flags, c.http.ClientFlags())
flags.Merge(c.flags, c.http.ServerFlags())
flags.Merge(c.flags, c.http.NamespaceFlags())
c.help = flags.Usage(help, c.flags)
}

View File

@ -68,6 +68,7 @@ func (c *cmd) init() {
c.http = &flags.HTTPFlags{}
flags.Merge(c.flags, c.http.ClientFlags())
flags.Merge(c.flags, c.http.ServerFlags())
flags.Merge(c.flags, c.http.NamespaceFlags())
c.help = flags.Usage(help, c.flags)
}

View File

@ -54,6 +54,7 @@ func (c *cmd) init() {
c.http = &flags.HTTPFlags{}
flags.Merge(c.flags, c.http.ClientFlags())
flags.Merge(c.flags, c.http.ServerFlags())
flags.Merge(c.flags, c.http.NamespaceFlags())
c.help = flags.Usage(help, c.flags)
}

View File

@ -26,6 +26,7 @@ func (c *cmd) init() {
c.http = &flags.HTTPFlags{}
flags.Merge(c.flags, c.http.ClientFlags())
flags.Merge(c.flags, c.http.ServerFlags())
c.help = flags.Usage(help, c.flags)
}

27
lib/json.go Normal file
View File

@ -0,0 +1,27 @@
package lib
import (
"bytes"
"encoding/json"
"io"
)
// DecodeJSON is a convenience function to create a JSON decoder
// set it up to disallow unknown fields and then decode into the
// given value
func DecodeJSON(data io.Reader, out interface{}) error {
if data == nil {
return io.EOF
}
decoder := json.NewDecoder(data)
decoder.DisallowUnknownFields()
return decoder.Decode(&out)
}
// UnmarshalJSON is a convenience function around calling
// DecodeJSON. It will mainly be useful in many of our
// UnmarshalJSON methods for structs.
func UnmarshalJSON(data []byte, out interface{}) error {
return DecodeJSON(bytes.NewReader(data), out)
}

View File

@ -305,6 +305,12 @@ replication enabled.
- `Meta` `(map<string|string>: nil)` - Specifies arbitrary KV metadata
linked to the token. Can be useful to track origins.
- `Namespace` `(string: "")` - **Enterprise Only** Specifies the namespace of
the Auth Method to use for Login. If not provided in the JSON body, the value of
the `ns` URL query parameter or in the `X-Consul-Namespace` header will be used.
If not provided at all, the namespace will be inferred from the request's ACL
token, or will default to the `default` namespace. Added in Consul 1.7.0.
### Sample Payload
```json

View File

@ -36,7 +36,7 @@ The table below shows this endpoint's support for
| ---------------- | ----------------- | ------------- | ------------ |
| `NO` | `none` | `none` | `acl:write` |
### Parameters
### Payload Fields
- `Name` `(string: <required>)` - Specifies a name for the ACL auth method. The
name can contain alphanumeric characters, dashes `-`, and underscores `_`.
@ -54,6 +54,12 @@ The table below shows this endpoint's support for
For more information on configuring specific auth method types, see the [auth
method documentation](/docs/acl/acl-auth-methods.html).
- `Namespace` `(string: "")` - **Enterprise Only** Specifies the namespace to
create the auth method within. If not provided in the JSON body, the value of
the `ns` URL query parameter or in the `X-Consul-Namespace` header will be used.
If not provided at all, the namespace will be inherited from the request's ACL
token or will default to the `default` namespace. Added in Consul 1.7.0.
### Sample Payload
```json
@ -119,6 +125,12 @@ The table below shows this endpoint's support for
- `name` `(string: <required>)` - Specifies the name of the ACL auth method to
read. This is required and is specified as part of the URL path.
- `ns` `(string: "")` - **Enterprise Only** Specifies the namespace to lookup
the auth method within. This value can be specified as the `ns` URL query
parameter or in the `X-Consul-Namespace` header. If not provided by either,
the namespace will be inherited from the request's ACL token or will default
to the `default` namespace. Added in Consul 1.7.0.
### Sample Request
```sh
@ -179,6 +191,12 @@ The table below shows this endpoint's support for
For more information on configuring specific auth method types, see the [auth
method documentation](/docs/acl/acl-auth-methods.html).
- `Namespace` `(string: "")` - **Enterprise Only** Specifies the namespace of
the auth method to update. If not provided in the JSON body, the value of
the `ns` URL query parameter or in the `X-Consul-Namespace` header will be used.
If not provided at all, the namespace will be inherited from the request's ACL
token or will default to the `default` namespace. Added in Consul 1.7.0.
### Sample Payload
```json
@ -248,6 +266,12 @@ The table below shows this endpoint's support for
- `name` `(string: <required>)` - Specifies the name of the ACL auth method to
delete. This is required and is specified as part of the URL path.
- `ns` `(string: "")` - **Enterprise Only** Specifies the namespace of the
Auth Method to delete. This value can be specified as the `ns` URL query
parameter or in the `X-Consul-Namespace` header. If not provided by either,
the namespace will be inherited from the request's ACL token or will default
to the `default` namespace. Added in Consul 1.7.0.
### Sample Request
```sh
@ -279,6 +303,16 @@ The table below shows this endpoint's support for
| ---------------- | ----------------- | ------------- | ------------ |
| `YES` | `all` | `none` | `acl:read` |
### Parameters
- `ns` `(string: "")` - **Enterprise Only** Specifies the namespace to list
the auth methods for. This value can be specified as the `ns` URL query
parameter or in the `X-Consul-Namespace` header. If not provided by either,
the namespace will be inherited from the request's ACL token or will default
to the `default` namespace. The namespace may be specified as '*' and then
results will be returned for all namespaces. Added in Consul 1.7.0.
## Sample Request
```sh

View File

@ -88,6 +88,12 @@ The table below shows this endpoint's support for
prefixed-${serviceaccount.name}
```
- `Namespace` `(string: "")` - **Enterprise Only** Specifies the namespace to
create the binding rule. If not provided in the JSON body, the value of
the `ns` URL query parameter or in the `X-Consul-Namespace` header will be used.
If not provided at all, the namespace will be inherited from the request's ACL
token or will default to the `default` namespace. Added in Consul 1.7.0.
### Sample Payload
```json
@ -148,6 +154,13 @@ The table below shows this endpoint's support for
- `id` `(string: <required>)` - Specifies the UUID of the ACL binding rule
to read. This is required and is specified as part of the URL path.
- `ns` `(string: "")` - **Enterprise Only** Specifies the namespace to lookup
the binding rule. This value can be specified as the `ns` URL query
parameter orthe `X-Consul-Namespace` header. If not provided by either,
the namespace will be inherited from the request's ACL token or will default
to the `default` namespace. Added in Consul 1.7.0.
### Sample Request
```sh
@ -245,6 +258,12 @@ The table below shows this endpoint's support for
prefixed-${serviceaccount.name}
```
- `Namespace` `(string: "")` - **Enterprise Only** Specifies the namespace of
the binding rule to update. If not provided in the JSON body, the value of
the `ns` URL query parameter or in the `X-Consul-Namespace` header will be used.
If not provided at all, the namespace will be inherited from the request's ACL
token or will default to the `default` namespace. Added in Consul 1.7.0.
### Sample Payload
```json
@ -305,6 +324,12 @@ The table below shows this endpoint's support for
- `id` `(string: <required>)` - Specifies the UUID of the ACL binding rule to
delete. This is required and is specified as part of the URL path.
- `ns` `(string: "")` - **Enterprise Only** Specifies the namespace of the
binding rule to delete. This value can be specified as the `ns` URL query
parameter orthe `X-Consul-Namespace` header. If not provided by either,
the namespace will be inherited from the request's ACL token or will default
to the `default` namespace. Added in Consul 1.7.0.
### Sample Request
```sh
@ -340,6 +365,13 @@ The table below shows this endpoint's support for
- `authmethod` `(string: "")` - Filters the binding rule list to those binding
rules that are linked with the specific named auth method.
- `ns` `(string: "")` - **Enterprise Only** Specifies the namespace to list
the binding rules for. This value can be specified as the `ns` URL query
parameter orthe `X-Consul-Namespace` header. If not provided by either,
the namespace will be inherited from the request's ACL token or will default
to the `default` namespace. The namespace may be specified as '*' and then
results will be returned for all namespaces. Added in Consul 1.7.0.
## Sample Request
```sh

View File

@ -50,6 +50,12 @@ The table below shows this endpoint's support for
When no datacenters are provided the policy is valid in all datacenters including
those which do not yet exist but may in the future.
- `Namespace` `(string: "")` - **Enterprise Only** Specifies the namespace to
create the policy. If not provided in the JSON body, the value of
the `ns` URL query parameter or in the `X-Consul-Namespace` header will be used.
If not provided at all, the namespace will be inherited from the request's ACL
token or will default to the `default` namespace. Added in Consul 1.7.0.
### Sample Payload
```json
@ -110,6 +116,12 @@ The table below shows this endpoint's support for
- `id` `(string: <required>)` - Specifies the UUID of the ACL policy to
read. This is required and is specified as part of the URL path.
- `ns` `(string: "")` - **Enterprise Only** Specifies the namespace to lookup
the policy. This value can be specified as the `ns` URL query
parameter orthe `X-Consul-Namespace` header. If not provided by either,
the namespace will be inherited from the request's ACL token or will default
to the `default` namespace. Added in Consul 1.7.0.
### Sample Request
```sh
@ -170,6 +182,12 @@ The table below shows this endpoint's support for
When no datacenters are provided the policy is valid in all datacenters including
those which do not yet exist but may in the future.
- `Namespace` `(string: "")` - **Enterprise Only** Specifies the namespace of
the policy to update. If not provided in the JSON body, the value of
the `ns` URL query parameter or in the `X-Consul-Namespace` header will be used.
If not provided at all, the namespace will be inherited from the request's ACL
token or will default to the `default` namespace. Added in Consul 1.7.0.
### Sample Payload
```json
@ -229,6 +247,12 @@ The table below shows this endpoint's support for
- `id` `(string: <required>)` - Specifies the UUID of the ACL policy to
delete. This is required and is specified as part of the URL path.
- `ns` `(string: "")` - **Enterprise Only** Specifies the namespace of the
policy to delete. This value can be specified as the `ns` URL query
parameter orthe `X-Consul-Namespace` header. If not provided by either,
the namespace will be inherited from the request's ACL token or will default
to the `default` namespace. Added in Consul 1.7.0.
### Sample Request
```sh
@ -259,6 +283,15 @@ The table below shows this endpoint's support for
| ---------------- | ----------------- | ------------- | ------------ |
| `YES` | `all` | `none` | `acl:read` |
### Parameters
- `ns` `(string: "")` - **Enterprise Only** Specifies the namespace to list
the Policies for. This value can be specified as the `ns` URL query
parameter orthe `X-Consul-Namespace` header. If not provided by either,
the namespace will be inherited from the request's ACL token or will default
to the `default` namespace. The namespace may be specified as '*' and then
results will be returned for all namespaces. Added in Consul 1.7.0.
## Sample Request
```sh

View File

@ -64,6 +64,12 @@ The table below shows this endpoint's support for
policy is valid in all datacenters including those which do not yet exist
but may in the future.
- `Namespace` `(string: "")` - **Enterprise Only** Specifies the namespace to
create the role. If not provided in the JSON body, the value of
the `ns` URL query parameter or in the `X-Consul-Namespace` header will be used.
If not provided at all, the namespace will be inherited from the request's ACL
token or will default to the `default` namespace. Added in Consul 1.7.0.
### Sample Payload
```json
@ -154,6 +160,12 @@ The table below shows this endpoint's support for
- `id` `(string: <required>)` - Specifies the UUID of the ACL role to
read. This is required and is specified as part of the URL path.
- `ns` `(string: "")` - **Enterprise Only** Specifies the namespace to lookup
the role. This value can be specified as the `ns` URL query
parameter orthe `X-Consul-Namespace` header. If not provided by either,
the namespace will be inherited from the request's ACL token or will default
to the `default` namespace. Added in Consul 1.7.0.
### Sample Request
```sh
@ -214,6 +226,12 @@ The table below shows this endpoint's support for
- `name` `(string: <required>)` - Specifies the Name of the ACL role to
read. This is required and is specified as part of the URL path.
- `ns` `(string: "")` - **Enterprise Only** Specifies the namespace to lookup
the role. This value can be specified as the `ns` URL query
parameter orthe `X-Consul-Namespace` header. If not provided by either,
the namespace will be inherited from the request's ACL token or will default
to the `default` namespace. Added in Consul 1.7.0.
### Sample Request
```sh
@ -292,6 +310,12 @@ The table below shows this endpoint's support for
identities](/docs/acl/acl-system.html#acl-service-identities) that should be
applied to the role. Added in Consul 1.5.0.
- `Namespace` `(string: "")` - **Enterprise Only** Specifies the namespace of
the role to update. If not provided in the JSON body, the value of
the `ns` URL query parameter or in the `X-Consul-Namespace` header will be used.
If not provided at all, the namespace will be inherited from the request's ACL
token or will default to the `default` namespace. Added in Consul 1.7.0.
### Sample Payload
```json
@ -368,6 +392,12 @@ The table below shows this endpoint's support for
- `id` `(string: <required>)` - Specifies the UUID of the ACL role to
delete. This is required and is specified as part of the URL path.
- `ns` `(string: "")` - **Enterprise Only** Specifies the namespace of the
role to delete. This value can be specified as the `ns` URL query
parameter orthe `X-Consul-Namespace` header. If not provided by either,
the namespace will be inherited from the request's ACL token or will default
to the `default` namespace. Added in Consul 1.7.0.
### Sample Request
```sh
@ -403,6 +433,15 @@ The table below shows this endpoint's support for
- `policy` `(string: "")` - Filters the role list to those roles that are
linked with the specific policy ID.
### Parameters
- `ns` `(string: "")` - **Enterprise Only** Specifies the namespace to list
the roles for. This value can be specified as the `ns` URL query
parameter orthe `X-Consul-Namespace` header. If not provided by either,
the namespace will be inherited from the request's ACL token or will default
to the `default` namespace. The namespace may be specified as '*' and then
results will be returned for all namespaces. Added in Consul 1.7.0.
## Sample Request
```sh

View File

@ -90,6 +90,12 @@ The table below shows this endpoint's support for
respectively). This value must be no smaller than 1 minute and no longer than
24 hours. Added in Consul 1.5.0.
- `Namespace` `(string: "")` - **Enterprise Only** Specifies the namespace to
create the token. If not provided in the JSON body, the value of
the `ns` URL query parameter or in the `X-Consul-Namespace` header will be used.
If not provided at all, the namespace will be inherited from the request's ACL
token or will default to the `default` namespace. Added in Consul 1.7.0.
### Sample Payload
```json
@ -164,6 +170,12 @@ The table below shows this endpoint's support for
- `AccessorID` `(string: <required>)` - Specifies the accessor ID of the ACL token to
read. This is required and is specified as part of the URL path.
- `ns` `(string: "")` - **Enterprise Only** Specifies the namespace to lookup
the token. This value can be specified as the `ns` URL query
parameter orthe `X-Consul-Namespace` header. If not provided by either,
the namespace will be inherited from the request's ACL token or will default
to the `default` namespace. Added in Consul 1.7.0.
### Sample Request
```sh
@ -329,6 +341,11 @@ The table below shows this endpoint's support for
match the existing value. If not present then the value will be filled in by
Consul.
- `Namespace` `(string: "")` - **Enterprise Only** Specifies the namespace of
the token to update. If not provided in the JSON body, the value of
the `ns` URL query parameter or in the `X-Consul-Namespace` header will be used.
If not provided at all, the namespace will be inherited from the request's ACL
token or will default to the `default` namespace. Added in Consul 1.7.0.
### Sample Payload
@ -412,6 +429,12 @@ The table below shows this endpoint's support for
- `Description` `(string: "")` - Free form human readable description for the cloned token.
- `Namespace` `(string: "")` - **Enterprise Only** Specifies the namespace of
the token to be cloned. If not provided in the JSON body, the value of
the `ns` URL query parameter or in the `X-Consul-Namespace` header will be used.
If not provided at all, the namespace will be inherited from the request's ACL
token or will default to the `default` namespace. Added in Consul 1.7.0.
### Sample Payload
```json
@ -483,6 +506,12 @@ The table below shows this endpoint's support for
- `AccessorID` `(string: <required>)` - Specifies the accessor ID of the ACL policy to
delete. This is required and is specified as part of the URL path.
- `ns` `(string: "")` - **Enterprise Only** Specifies the namespace of the
token to delete. This value can be specified as the `ns` URL query
parameter orthe `X-Consul-Namespace` header. If not provided by either,
the namespace will be inherited from the request's ACL token or will default
to the `default` namespace. Added in Consul 1.7.0.
### Sample Request
```sh
@ -524,6 +553,13 @@ The table below shows this endpoint's support for
- `authmethod` `(string: "")` - Filters the token list to those tokens that are
linked with the specific named auth method.
- `ns` `(string: "")` - **Enterprise Only** Specifies the namespace to list
the tokens for. This value can be specified as the `ns` URL query
parameter orthe `X-Consul-Namespace` header. If not provided by either,
the namespace will be inherited from the request's ACL token or will default
to the `default` namespace. The namespace may be specified as '*' and then
results will be returned for all namespaces. Added in Consul 1.7.0.
## Sample Request
```sh

View File

@ -0,0 +1,483 @@
---
layout: api
page_title: Namespace - HTTP API
sidebar_current: api-namespaces
description: |-
The /namespace endpoints allow for managing Consul Enterprise Namespaces.
---
# Namespace - HTTP API
~> **Enterprise Only!** These API endpoints and functionality only exists in
Consul Enterprise. This is not present in the open source version of Consul.
The functionality described here is available only in
[Consul Enterprise](https://www.hashicorp.com/products/consul/) version 1.7.0 and later.
## Create a Namespace
This endpoint creates a new ACL token.
| Method | Path | Produces |
| ------ | ---------------------------- | -------------------------- |
| `PUT` | `/namespace` | `application/json` |
The table below shows this endpoint's support for
[blocking queries](/api/features/blocking.html),
[consistency modes](/api/features/consistency.html),
[agent caching](/api/features/caching.html), and
[required ACLs](/api/index.html#authentication).
| Blocking Queries | Consistency Modes | Agent Caching | ACL Required |
| ---------------- | ----------------- | ------------- | ----------------- |
| `NO` | `none` | `none` | `operator:write` |
### Parameters
- `Name` `(string: <required>)` - The namespaces name. This must be a valid
DNS hostname label.
- `Description` `(string: "")` - Free form namespaces description.
- `ACLs` `(object: <optional>)` - ACL configurations for this namespace. Rules from
default policies and roles will be used only when there are no rules from directly linked
policies, roles and service identities that are for the target resource and segment.
Therefore if a directly linked policy grants read access to some resource and a
default policy grants write access, the effective access for the token will be read
due to the default policies not being checked. When there is no rule concerning
the resource in either the directly linked policies, roles and service identities
nor in those linked by the defaults, then the agents default policy configuration
will be used for making the enforcement decision.
- `PolicyDefaults` `(array<ACLLink>)` - This is the list of default policies
that should be applied to all tokens created in this namespace. The ACLLink
struct is an object with an "ID" and/or "Name" field to identify a policy.
When a name is used instead of an ID, Consul will resolve the name to an ID
and store that internally.
- `RoleDefaults` `(array<ACLLink>)` - This is the list of default roles
that should be applied to all tokens created in this namespace. The ACLLink
struct is an object with an "ID" and/or "Name" field to identify a policy.
When a name is used instead of an ID, Consul will resolve the name to an ID
and store that internally.
- `Meta` `(map<string|string>: <optional>)` - Specifies arbitrary KV metadata
to associate with the namespace.
### Sample Payload
```json
{
"Name": "team-1",
"Description": "Namespace for Team 1",
"ACLs": {
"PolicyDefaults": [
{
"ID": "77117cf6-d976-79b0-d63b-5a36ac69c8f1"
},
{
"Name": "node-read"
}
],
"RoleDefaults": [
{
"ID": "69748856-ae69-d620-3ec4-07844b3c6be7"
},
{
"Name": "ns-team-2-read"
}
]
},
"Meta": {
"foo": "bar"
}
}
```
### Sample Request
```sh
$ curl -X PUT \
-H "X-Consul-Token: 5cdcae6c-0cce-4210-86fe-5dff3b984a6e" \
--data @payload.json \
http://127.0.0.1:8500/v1/namespace
```
### SampleResponse
```json
{
"Name": "team-1",
"Description": "Namespace for Team 1",
"ACLs": {
"PolicyDefaults": [
{
"ID": "77117cf6-d976-79b0-d63b-5a36ac69c8f1",
"Name": "service-read"
},
{
"ID": "af937401-9950-fcae-8396-610ce047649a",
"Name": "node-read"
}
],
"RoleDefaults": [
{
"ID": "69748856-ae69-d620-3ec4-07844b3c6be7",
"Name": "service-discovery"
},
{
"ID": "ae4b3542-d824-eb5f-7799-3fd657847e4e",
"Name": "ns-team-2-read"
}
]
},
"Meta": {
"foo": "bar"
},
"CreateIndex": 55,
"ModifyIndex": 55
}
```
## Read a Namespace
This endpoint reads a Namespace with the given name.
| Method | Path | Produces |
| ------ | ---------------------- | -------------------------- |
| `GET` | `/namespace/:name` | `application/json` |
The table below shows this endpoint's support for
[blocking queries](/api/features/blocking.html),
[consistency modes](/api/features/consistency.html),
[agent caching](/api/features/caching.html), and
[required ACLs](/api/index.html#authentication).
| Blocking Queries | Consistency Modes | Agent Caching | ACL Required |
| ---------------- | ----------------- | ------------- | ------------ |
| `YES` | `all` | `none` | `operator:read` or `namespace:*:read`<sup>1<sup> |
<sup>1</sup> Access can be granted to list the Namespace if the token used when making
the request has been granted any access in the namespace (read, list or write).
### Parameters
- `name` `(string: <required>)` - Specifies the namespace to read. This
is required and is specified as part of the URL path.
### Sample Request
```sh
$ curl -H "X-Consul-Token: b23b3cad-5ea1-4413-919e-c76884b9ad60" \
http://127.0.0.1:8500/v1/namespace/team-1
```
### SampleResponse
```json
{
"Name": "team-1",
"Description": "Namespace for Team 1",
"ACLs": {
"PolicyDefaults": [
{
"ID": "77117cf6-d976-79b0-d63b-5a36ac69c8f1",
"Name": "service-read"
},
{
"ID": "af937401-9950-fcae-8396-610ce047649a",
"Name": "node-read"
}
],
"RoleDefaults": [
{
"ID": "69748856-ae69-d620-3ec4-07844b3c6be7",
"Name": "service-discovery"
},
{
"ID": "ae4b3542-d824-eb5f-7799-3fd657847e4e",
"Name": "ns-team-2-read"
}
]
},
"Meta": {
"foo": "bar"
},
"CreateIndex": 55,
"ModifyIndex": 55
}
```
## Update a Namespace
This endpoint updates a new ACL token.
| Method | Path | Produces |
| ------ | ---------------------------- | -------------------------- |
| `PUT` | `/namespace/:name` | `application/json` |
The table below shows this endpoint's support for
[blocking queries](/api/features/blocking.html),
[consistency modes](/api/features/consistency.html),
[agent caching](/api/features/caching.html), and
[required ACLs](/api/index.html#authentication).
| Blocking Queries | Consistency Modes | Agent Caching | ACL Required |
| ---------------- | ----------------- | ------------- | ----------------- |
| `NO` | `none` | `none` | `operator:write` |
### Parameters
- `Name` `(string: <optional>)` - The namespaces name. This must be a valid
DNS hostname label. If present in the payload it must match what was given
in the URL path.
- `Description` `(string: "")` - Free form namespaces description.
- `ACLs` `(object: <optional>)` - ACL configurations for this Namespace. Rules from
default policies and roles will be used only when there are no rules from directly linked
policies, roles and service identities that are for the target resource and segment.
Therefore if a directly linked policy grants read access to some resource and a
default policy grants write access, the effective access for the token will be read
due to the default policies not being checked. When there is no rule concerning
the resource in either the directly linked policies, roles and service identities
nor in those linked by the defaults, then the agents default policy configuration
will be used for making the enforcement decision.
- `PolicyDefaults` `(array<ACLLink>)` - This is the list of default policies
that should be applied to all tokens created in this namespace. The ACLLink
struct is an object with an "ID" and/or "Name" field to identify a policy.
When a name is used instead of an ID, Consul will resolve the name to an ID
and store that internally.
- `RoleDefaults` `(array<ACLLink>)` - This is the list of default roles
that should be applied to all tokens created in this namespace. The ACLLink
struct is an object with an "ID" and/or "Name" field to identify a policy.
When a name is used instead of an ID, Consul will resolve the name to an ID
and store that internally.
- `Meta` `(map<string|string>: <optional>)` - Specifies arbitrary KV metadata
to associate with the namespace.
### Sample Payload
```json
{
"Description": "Namespace for Team 1",
"ACLs": {
"PolicyDefaults": [
{
"ID": "77117cf6-d976-79b0-d63b-5a36ac69c8f1"
},
{
"Name": "node-read"
}
],
"RoleDefaults": [
{
"ID": "69748856-ae69-d620-3ec4-07844b3c6be7"
},
{
"Name": "ns-team-2-read"
}
]
},
"Meta": {
"foo": "bar"
}
}
```
### Sample Request
```sh
$ curl -X PUT \
-H "X-Consul-Token: 5cdcae6c-0cce-4210-86fe-5dff3b984a6e" \
--data @payload.json \
http://127.0.0.1:8500/v1/namespace/team-1
```
### SampleResponse
```json
{
"Name": "team-1",
"Description": "Namespace for Team 1",
"ACLs": {
"PolicyDefaults": [
{
"ID": "77117cf6-d976-79b0-d63b-5a36ac69c8f1",
"Name": "service-read"
},
{
"ID": "af937401-9950-fcae-8396-610ce047649a",
"Name": "node-read"
}
],
"RoleDefaults": [
{
"ID": "69748856-ae69-d620-3ec4-07844b3c6be7",
"Name": "service-discovery"
},
{
"ID": "ae4b3542-d824-eb5f-7799-3fd657847e4e",
"Name": "ns-team-2-read"
}
]
},
"Meta": {
"foo": "bar"
},
"CreateIndex": 55,
"ModifyIndex": 55
}
```
## Delete a Namespace
This endpoint marks a Namespace for deletion. Once marked Consul will
deleted all the associated Namespaced data in the background. Only once
all associated data has been deleted will the Namespace actually disappear.
Until then, further reads can be performed on the namespace and a `DeletedAt`
field will now be populated with the timestamp of when the Namespace was
marked for deletion.
| Method | Path | Produces |
| -------- | ------------------------- | -------------------------- |
| `DELETE` | `/namespace/:name` | N/A |
This endpoint will return no data. Success or failure is indicated by the status
code returned.
The table below shows this endpoint's support for
[blocking queries](/api/features/blocking.html),
[consistency modes](/api/features/consistency.html),
[agent caching](/api/features/caching.html), and
[required ACLs](/api/index.html#authentication).
| Blocking Queries | Consistency Modes | Agent Caching | ACL Required |
| ---------------- | ----------------- | ------------- | ------------ |
| `NO` | `none` | `none` | `operator:write` |
### Parameters
- `name` `(string: <required>)` - Specifies the namespace to delete. This
is required and is specified as part of the URL path.
### Sample Request
```sh
$ curl -X DELETE \
-H "X-Consul-Token: b23b3cad-5ea1-4413-919e-c76884b9ad60" \
http://127.0.0.1:8500/v1/namespace/team-1
```
### Sample Read Output After Deletion Prior to Removal
```json
{
"Name": "team-1",
"Description": "Namespace for Team 1",
"ACLs": {
"PolicyDefaults": [
{
"ID": "77117cf6-d976-79b0-d63b-5a36ac69c8f1",
"Name": "service-read"
},
{
"ID": "af937401-9950-fcae-8396-610ce047649a",
"Name": "node-read"
}
],
"RoleDefaults": [
{
"ID": "69748856-ae69-d620-3ec4-07844b3c6be7",
"Name": "service-discovery"
},
{
"ID": "ae4b3542-d824-eb5f-7799-3fd657847e4e",
"Name": "ns-team-2-read"
}
]
},
"Meta": {
"foo": "bar"
},
"DeletedAt": "2019-12-02T23:00:00Z",
"CreateIndex": 55,
"ModifyIndex": 100
}
```
## List all Namespaces
This endpoint lists all the Namespaces. The output will be filtered based on the
privileges of the ACL token used for the request.
| Method | Path | Produces |
| ------ | ---------------------------- | -------------------------- |
| `GET` | `/namespaces` | `application/json` |
The table below shows this endpoint's support for
[blocking queries](/api/features/blocking.html),
[consistency modes](/api/features/consistency.html),
[agent caching](/api/features/caching.html), and
[required ACLs](/api/index.html#authentication).
| Blocking Queries | Consistency Modes | Agent Caching | ACL Required |
| ---------------- | ----------------- | ------------- | ------------ |
| `YES` | `all` | `none` | `operator:read` or `namespace:*:read`<sup>1</sup> |
<sup>1</sup> Access can be granted to list the Namespace if the token used when making
the request has been granted any access in the namespace (read, list or write).
### Sample Request
```sh
$ curl -H "X-Consul-Token: 0137db51-5895-4c25-b6cd-d9ed992f4a52" \
http://127.0.0.1:8500/v1/namespaces
```
### Sample Response
```json
[
{
"Name": "default",
"Description": "Builtin Default Namespace",
"CreateIndex": 6,
"ModifyIndex": 6
},
{
"Name": "team-1",
"Description": "Namespace for Team 1",
"ACLs": {
"PolicyDefaults": [
{
"ID": "77117cf6-d976-79b0-d63b-5a36ac69c8f1",
"Name": "service-read"
},
{
"ID": "af937401-9950-fcae-8396-610ce047649a",
"Name": "node-read"
}
],
"RoleDefaults": [
{
"ID": "69748856-ae69-d620-3ec4-07844b3c6be7",
"Name": "service-discovery"
},
{
"ID": "ae4b3542-d824-eb5f-7799-3fd657847e4e",
"Name": "ns-team-2-read"
}
]
},
"Meta": {
"foo": "bar"
},
"CreateIndex": 55,
"ModifyIndex": 55
}
]
```

View File

@ -561,3 +561,67 @@ session "admin" {
Session rules are segmented by the node name they apply to. In the example above, the rules allow read-only
access to sessions on node name with the empty prefix, allow creating sessions on the node named "app",
and deny all access to any sessions on the "admin" node.
#### Namespace Rules <span class="label-enterprise label-enterprise-lg">Enterprise</span>
[Consul Enterprise](https://www.hashicorp.com/consul.html) 1.7.0 adds support for namespacing many
Consul resources. ACL rules themselves can then be defined to only to apply to specific namespaces.
A Namespace specific rule would look like this:
```hcl
namespace_prefix "" {
# grant service:read for all services in all namespaces
service_prefix "" {
policy = "read"
}
# grant node:read for all nodes in all namespaces
node_prefix "" {
policy = "read"
}
}
namespace "foo" {
# grants permission to manage ACLs only for the foo namespace
acl = "write"
# grants write permissions to the KV for namespace foo
key_prefix "" {
policy = "write"
}
# grants write permissions for sessions for namespace foo
session_prefix "" {
policy = "write"
}
# grants service:write for all services in the foo namespace
service_prefix "" {
policy = "write"
}
# grants node:read for all nodes
node_prefix "" {
policy = "read"
}
}
```
Note, when a rule is defined in any user created namespace, the following restrictions apply.
1. `operator` rules are not allowed.
2. `event` rules are not allowed.
3. `keyring` rules are not allowed.
4. `query` rules are not allowed.
5. `node` rules that attempt to grant `write` privileges are not allowed.
These restrictions do not apply to the `default` namespace created by Consul. In general all of the
above are permissions that only an operator should have and thus granting these permissions can
only be done within the default namespace.
-> **Implicit namespacing:** Rules and policies created within a namespace will inherit the namespace configuration.
This means that rules and policies will be implicitly namespaced and do not need additional configuration.
The restrictions outlined above will apply to these rules and policies. Additionally, rules and policies within a
specific namespace are prevented from accessing resources in another namespace.

View File

@ -63,6 +63,9 @@ An ACL policy is a named set of rules and is composed of the following elements:
* **Description** - A human readable description of the policy. (Optional)
* **Rules** - Set of rules granting or denying permissions. See the [Rule Specification](/docs/acl/acl-rules.html#rule-specification) documentation for more details.
* **Datacenters** - A list of datacenters the policy is valid within.
* **Namespace** - **Enterprise Only** - The namespace this policy resides within. (Added in Consul Enterprise 1.7.0)
-> **Consul Enterprise Namespacing** - Rules defined in a policy in any namespace other than `default` will be [restricted](/docs/acl/acl-rules.html#namespace-rules-enterprise) to being able to grant a subset of the overall privileges and only affecting that single namespace.
#### Builtin Policies
@ -70,6 +73,9 @@ An ACL policy is a named set of rules and is composed of the following elements:
and will be assigned the reserved ID of `00000000-0000-0000-0000-000000000001`. This policy can be renamed but modification
of anything else including the rule set and datacenter scoping will be prevented by Consul.
* **Namespace Management** - **Enterprise Only** - Every namespace created will have a policy injected with the name `namespace-management`. This policy gets injected with a randomized UUID and may be managed like any other user-defined policy
within the Namespace. (Added in Consul Enterprise 1.7.0)
### ACL Service Identities
-> Added in Consul 1.5.0
@ -111,6 +117,9 @@ node_prefix "" {
The [API documentation for roles](/api/acl/roles.html#sample-payload) has some
examples of using a service identity.
-> **Consul Enterprise Namespacing** - Service Identity rules will be scoped to the single namespace that
the corresponding ACL Token or Role resides within.
### ACL Roles
-> Added in Consul 1.5.0
@ -123,6 +132,9 @@ of the following elements:
* **Description** - A human readable description of the role. (Optional)
* **Policy Set** - The list of policies that are applicable for the role.
* **Service Identity Set** - The list of service identities that are applicable for the role.
* **Namespace** - **Enterprise Only** - The namespace this policy resides within. (Added in Consul Enterprise 1.7.0)
-> **Consul Enterprise Namespacing** - Roles may only link to policies defined in the same namespace as the role itself.
### ACL Tokens
@ -138,6 +150,10 @@ elements:
* **Locality** - Indicates whether the token should be local to the datacenter it was created within or created in
the primary datacenter and globally replicated.
* **Expiration Time** - The time at which this token is revoked. (Optional; Added in Consul 1.5.0)
* **Namespace** - **Enterprise Only** - The namespace this policy resides within. (Added in Consul Enterprise 1.7.0)
-> **Consul Enterprise Namespacing** - Tokens may only link to policies and roles defined in the same namespace as
the token itself.
#### Builtin Tokens
@ -210,6 +226,9 @@ Consul datacenters, and does not allow modification of any state.
Constructing rules from these policies is covered in detail on the
[ACL Rules](/docs/acl/acl-rules.html) page.
-> **Consul Enterprise Namespacing** - In addition to directly linked policies, roles and service identities, Consul Enterprise
will include the ACL policies and roles defined in the [Namespaces definition](/docs/enterprise/namespaces/index.html#namespace-definition). (Added in Consul Enterprise 1.7.0)
## Configuring ACLs
ACLs are configured using several different configuration options. These are marked

View File

@ -0,0 +1,3 @@
* `-ns=<string>` - Specifies the namespace to query. If not provided, the namespace
will be inferred from the request's ACL token, or will default to
the `default` namespace. Namespaces is a Consul Enterprise feature.

View File

@ -42,6 +42,10 @@ Usage: `consul acl auth-method create [options] [args]`
used to access the TokenReview API to validate other JWTs during login. This
flag is required for `-type=kubernetes`.
#### Enterprise Options
<%= partial "docs/commands/http_api_namespace_options" %>
## Examples
Create a new Kubernetes auth method:

View File

@ -23,6 +23,10 @@ Usage: `consul acl auth-method delete [options]`
* `-name=<string>` - The Name of the auth method to delete.
#### Enterprise Options
<%= partial "docs/commands/http_api_namespace_options" %>
## Examples
Delete an auth method:

View File

@ -24,6 +24,10 @@ Usage: `consul acl auth-method list`
* `-meta` - Indicates that auth method metadata such as the raft indices should
be shown for each entry.
#### Enterprise Options
<%= partial "docs/commands/http_api_namespace_options" %>
## Examples
Default listing.

View File

@ -26,6 +26,10 @@ Usage: `consul acl auth-method read [options] [args]`
* `-name=<string>` - The name of the auth method to read.
#### Enterprise Options
<%= partial "docs/commands/http_api_namespace_options" %>
## Examples
Get auth method details:

View File

@ -47,6 +47,10 @@ Usage: `consul acl auth-method update [options] [args]`
to the command. Instead overwrite all fields with the exception of the auth method
ID which is immutable.
#### Enterprise Options
<%= partial "docs/commands/http_api_namespace_options" %>
## Examples
Update an auth method:

View File

@ -37,6 +37,10 @@ Usage: `consul acl binding-rule create [options] [args]`
* `-selector=<string>` - Selector is an expression that matches against
verified identity attributes returned from the auth method during login.
#### Enterprise Options
<%= partial "docs/commands/http_api_namespace_options" %>
## Examples
Create a new binding rule that binds to a service identity:

View File

@ -24,6 +24,10 @@ Usage: `consul acl binding-rule delete [options]`
* `-id=<string>` - The ID of the binding rule to delete. It may be specified as a
unique ID prefix but will error if the prefix matches multiple binding rule IDs.
#### Enterprise Options
<%= partial "docs/commands/http_api_namespace_options" %>
## Examples
Delete a binding rule:

View File

@ -24,6 +24,10 @@ Usage: `consul acl binding-rule list`
* `-meta` - Indicates that binding rule metadata such as the raft indices
should be shown for each entry.
#### Enterprise Options
<%= partial "docs/commands/http_api_namespace_options" %>
## Examples
Default listing.

View File

@ -27,6 +27,10 @@ Usage: `consul acl binding-rule read [options] [args]`
* `-meta` - Indicates that binding rule metadata such as the raft
indices should be shown for each entry.
#### Enterprise Options
<%= partial "docs/commands/http_api_namespace_options" %>
## Examples
Get binding rule details:

View File

@ -44,6 +44,10 @@ Usage: `consul acl binding-rule update [options] [args]`
* `-selector=<string>` - Selector is an expression that matches against
verified identity attributes returned from the auth method during login.
#### Enterprise Options
<%= partial "docs/commands/http_api_namespace_options" %>
## Examples
Update a binding rule:

View File

@ -55,6 +55,10 @@ Usage: `consul acl policy create [options] [args]`
* `-valid-datacenter=<value>` - Datacenter that the policy should be valid within.
This flag may be specified multiple times.
#### Enterprise Options
<%= partial "docs/commands/http_api_namespace_options" %>
## Examples
Create a new policy that is valid in all datacenters:

View File

@ -26,6 +26,10 @@ Usage: `consul acl policy delete [options]`
* `-name=<string>` - The Name of the policy to delete.
#### Enterprise Options
<%= partial "docs/commands/http_api_namespace_options" %>
## Examples
Delete a policy:

View File

@ -24,6 +24,10 @@ Usage: `consul acl policy list`
* `-meta` - Indicates that policy metadata such as the content hash and
Raft indices should be shown for each entry.
#### Enterprise Options
<%= partial "docs/commands/http_api_namespace_options" %>
## Examples
Default listing.

View File

@ -29,6 +29,10 @@ Usage: `consul acl policy read [options] [args]`
* `-name=<string>` - The name of the policy to read.
#### Enterprise Options
<%= partial "docs/commands/http_api_namespace_options" %>
## Examples
Get policy details:

View File

@ -46,6 +46,10 @@ Usage: `consul acl policy update [options] [args]`
* `-valid-datacenter=<value>` - Datacenter that the policy should be valid within.
This flag may be specified multiple times.
#### Enterprise Options
<%= partial "docs/commands/http_api_namespace_options" %>
## Examples
Update a policy:

View File

@ -38,6 +38,10 @@ Usage: `consul acl role create [options] [args]`
role. May be specified multiple times. Format is the `SERVICENAME` or
`SERVICENAME:DATACENTER1,DATACENTER2,...`
#### Enterprise Options
<%= partial "docs/commands/http_api_namespace_options" %>
## Examples
Create a new role with one policy:

View File

@ -26,6 +26,10 @@ Usage: `consul acl role delete [options]`
* `-name=<string>` - The Name of the role to delete.
#### Enterprise Options
<%= partial "docs/commands/http_api_namespace_options" %>
## Examples
Delete a role by prefix:

View File

@ -24,6 +24,10 @@ Usage: `consul acl role list`
* `-meta` - Indicates that role metadata such as the content hash and
Raft indices should be shown for each entry.
#### Enterprise Options
<%= partial "docs/commands/http_api_namespace_options" %>
## Examples
Default listing.

View File

@ -29,6 +29,10 @@ Usage: `consul acl role read [options] [args]`
* `-name=<string>` - The name of the role to read.
#### Enterprise Options
<%= partial "docs/commands/http_api_namespace_options" %>
## Examples
Get role details:

View File

@ -49,6 +49,10 @@ Usage: `consul acl role update [options] [args]`
role. May be specified multiple times. Format is the `SERVICENAME` or
`SERVICENAME:DATACENTER1,DATACENTER2,...`
#### Enterprise Options
<%= partial "docs/commands/http_api_namespace_options" %>
## Examples
Update a role:

View File

@ -28,6 +28,10 @@ Usage: `consul acl token clone [options]`
Accessor IDs. The special value of 'anonymous' may be provided instead of
the anonymous tokens accessor ID
#### Enterprise Options
<%= partial "docs/commands/http_api_namespace_options" %>
## Examples
Clone a token:

View File

@ -52,6 +52,10 @@ Usage: `consul acl token create [options] [args]`
**Note**: The SecretID is used to authorize operations against Consul and should
be generated from an appropriate cryptographic source.
#### Enterprise Options
<%= partial "docs/commands/http_api_namespace_options" %>
## Examples
Create a new token:

View File

@ -24,6 +24,10 @@ Usage: `consul acl token delete [options]`
* `-id=<string>` - The ID of the token to delete. It may be specified as a
unique ID prefix but will error if the prefix matches multiple token IDs.
#### Enterprise Options
<%= partial "docs/commands/http_api_namespace_options" %>
## Examples
Delete a token:

View File

@ -24,6 +24,10 @@ Usage: `consul acl token list`
* `-meta` - Indicates that token metadata such as the content hash and
Raft indices should be shown for each entry.
#### Enterprise Options
<%= partial "docs/commands/http_api_namespace_options" %>
## Examples
Default listing.

View File

@ -30,6 +30,10 @@ Usage: `consul acl token read [options] [args]`
* `-self` - Indicates that the current HTTP token should be read by secret ID
instead of expecting a -id option.
#### Enterprise Options
<%= partial "docs/commands/http_api_namespace_options" %>
## Examples
Get token details:

View File

@ -48,6 +48,10 @@ Usage: `consul acl token update [options]`
token. May be specified multiple times. Format is the `SERVICENAME` or
`SERVICENAME:DATACENTER1,DATACENTER2,...`
#### Enterprise Options
<%= partial "docs/commands/http_api_namespace_options" %>
## Examples
Update the anonymous token:

View File

@ -31,6 +31,10 @@ Usage: `consul kv delete [options] KEY_OR_PREFIX`
* `-recurse` - Recursively delete all keys with the path. The default value is
false.
#### Enterprise Options
<%= partial "docs/commands/http_api_namespace_options" %>
## Examples
To remove the value for the key named "redis/config/connections" in the

View File

@ -22,6 +22,10 @@ Usage: `consul kv export [options] [PREFIX]`
<%= partial "docs/commands/http_api_options_client" %>
<%= partial "docs/commands/http_api_options_server" %>
#### Enterprise Options
<%= partial "docs/commands/http_api_namespace_options" %>
## Examples
To export the tree at "vault/" in the key value store:

View File

@ -42,6 +42,10 @@ Usage: `consul kv get [options] [KEY_OR_PREFIX]`
default value is "/", and only used when paired with the `-keys` flag. This will
limit the prefix of keys returned, only up to the given separator.
#### Enterprise Options
<%= partial "docs/commands/http_api_namespace_options" %>
## Examples
To retrieve the value for the key named "redis/config/connections" in the

View File

@ -20,6 +20,10 @@ Usage: `consul kv import [options] [DATA]`
<%= partial "docs/commands/http_api_options_client" %>
<%= partial "docs/commands/http_api_options_server" %>
#### Enterprise Options
<%= partial "docs/commands/http_api_namespace_options" %>
## Examples
To import from a file, prepend the filename with `@`:
@ -43,5 +47,3 @@ escaping:
$ consul kv import "$(cat values.json)"
# Output
```

View File

@ -19,6 +19,10 @@ Usage: `consul kv put [options] KEY [DATA]`
<%= partial "docs/commands/http_api_options_client" %>
<%= partial "docs/commands/http_api_options_server" %>
#### Enterprise Options
<%= partial "docs/commands/http_api_namespace_options" %>
#### KV Put Options
* `-acquire` - Obtain a lock on the key. If the key does not exist, this

View File

@ -0,0 +1,71 @@
---
layout: "docs"
page_title: "Commands: Namespace"
sidebar_current: "docs-commands-namespace"
description: >
The namespace command provides management of Consul Enterprise namespaces.
---
<%= enterprise_alert :consul %>
# Consul Namespace
Command: `consul namespace`
The `namespace` command provides management of Consul Enterprise namespaces. This was added in Consul Enterprise 1.7.0.
If ACLs are enabled then a token with operator privileges may be required in order to use this command. Write
requests are forwarded to the leader in the primary datacenter. Therefore these commands can be run against
any agent in any datacenter.
## Usage
Usage: `consul namespace <subcommand>`
For the exact documentation for your Consul version, run `consul namespace -h` to view the complete list of subcommands.
```text
Usage: consul namespace <subcommand> [options] [args]
This command has subcommands for interacting with Consul Enterprise
Namespaces. Here are some simple examples. More detailed
examples are available in the subcommands or the documentation.
...
Subcommands:
delete Delete a Namespace
list List all Namespaces
read Read a Namespace
write Create or update a Namespace
```
For more information, examples, and usage about a subcommand, click on the name
of the subcommand in the sidebar.
## Basic Examples
Create or update a Namespace:
```sh
$ consul namespace write ns1.hcl
```
Read a Namespace:
```sh
$ consul namespace read ns1
```
List all Namespaces:
```sh
$ consul namespace list
```
Delete a Namespace:
```sh
$ consul namespace delete ns1
```

View File

@ -0,0 +1,31 @@
---
layout: "docs"
page_title: "Commands: Namespace Delete"
sidebar_current: "docs-commands-namespace-delete"
---
<%= enterprise_alert :consul %>
# Consul Namespace Delete
Command: `consul namespace delete`
This `namespace delete` command deletes a namespace. This was added in Consul Enterprise 1.7.0. If
ACLs are enabled then this command will require a token with `operator:write` privileges.
## Usage
Usage: `consul namespace delete <name>`
#### API Options
<%= partial "docs/commands/http_api_options_client" %>
<%= partial "docs/commands/http_api_options_server" %>
## Examples
Delete a Namespace:
```sh
$ consul namespace delete "team-1"
```

View File

@ -0,0 +1,98 @@
---
layout: "docs"
page_title: "Commands: Namespace List"
sidebar_current: "docs-commands-namespace-list"
---
<%= enterprise_alert :consul %>
# Consul Namespace List
Command: `consul namespace list`
This `namespace list` command lists all namespace configurations. This was added in Consul Enterprise 1.7.0. If
ACLs are enabled then this command will require a token with `operator:read` privileges or any `read` privileges
within the target namespaces. The results will be filtered based on the ACL token and therefore it is possible to
see a partial list.
## Usage
Usage: `consul namespace list`
#### API Options
<%= partial "docs/commands/http_api_options_client" %>
<%= partial "docs/commands/http_api_options_server" %>
#### Command Options
* `-format=<string>` - How to output the results. The choices are: pretty or json
* `-meta` - Indicates that namespace metadata such as the raft indices should be
shown for the namespace
## Examples
List Namespaces:
```sh
$ consul namespace list
default:
Description:
Builtin Default Namespace
foo:
Description:
Example Namespace
team-1:
Description:
```
Showing Raft Metadata:
```sh
$ consul namespace list -meta
default:
Description:
Builtin Default Namespace
Create Index: 4
Modify Index: 4
foo:
Description:
Example Namespace
Create Index: 352
Modify Index: 352
team-1:
Description:
Create Index: 339
Modify Index: 344
```
JSON Format:
```sh
$ consul namespace list -format=json
[
{
"Name": "default",
"Description": "Builtin Default Namespace",
"CreateIndex": 4,
"ModifyIndex": 4
},
{
"Name": "foo",
"Description": "Example Namespace",
"Meta": {
"team-id": "574407f3-8b26-4c84-8e51-028bb8cbdd37"
},
"CreateIndex": 352,
"ModifyIndex": 352
},
{
"Name": "team-1",
"CreateIndex": 339,
"ModifyIndex": 344
}
]
```

View File

@ -0,0 +1,66 @@
---
layout: "docs"
page_title: "Commands: Namespace Read"
sidebar_current: "docs-commands-namespace-read"
---
<%= enterprise_alert :consul %>
# Consul Namespace Read
Command: `consul namespace read`
This `namespace read` command reads a namespaces configuration. This was added in Consul Enterprise 1.7.0. If
ACLs are enabled then this command will require a token with `operator:read` privileges or any `read` privileges
within the target namespace.
## Usage
Usage: `consul namespace read <name>`
#### API Options
<%= partial "docs/commands/http_api_options_client" %>
<%= partial "docs/commands/http_api_options_server" %>
#### Command Options
* `-format=<string>` - How to output the results. The choices are: pretty or json
* `-meta` - Indicates that namespace metadata such as the raft indices should be
shown for the namespace
## Examples
Read a Namespace:
```sh
$ consul namespace read "team-1"
Name: team-1
Description:
```
Showing Raft Metadata:
```sh
$ consul namespace read -meta "team-1"
Name: team-1
Description:
Create Index: 339
Modify Index: 344
```
JSON Format:
```sh
$ consul namespace read -format=json foo
{
"Name": "foo",
"Description": "Example Namespace",
"Meta": {
"team-id": "574407f3-8b26-4c84-8e51-028bb8cbdd37"
},
"CreateIndex": 352,
"ModifyIndex": 352
}
```

Some files were not shown because too many files have changed in this diff Show More