diff --git a/agent/acl_endpoint.go b/agent/acl_endpoint.go index 41bc8be5d..a3ab26c24 100644 --- a/agent/acl_endpoint.go +++ b/agent/acl_endpoint.go @@ -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 diff --git a/agent/agent_endpoint_test.go b/agent/agent_endpoint_test.go index 6437b7c15..ef19f0970 100644 --- a/agent/agent_endpoint_test.go +++ b/agent/agent_endpoint_test.go @@ -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, diff --git a/agent/discovery_chain_endpoint.go b/agent/discovery_chain_endpoint.go index 7e3bd31b7..6ed895a9e 100644 --- a/agent/discovery_chain_endpoint.go +++ b/agent/discovery_chain_endpoint.go @@ -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 } diff --git a/agent/http.go b/agent/http.go index 9e4941457..234fe65b7 100644 --- a/agent/http.go +++ b/agent/http.go @@ -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. diff --git a/agent/http_oss.go b/agent/http_oss.go index c770ce152..cf1fc6322 100644 --- a/agent/http_oss.go +++ b/agent/http_oss.go @@ -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 } diff --git a/agent/kvs_endpoint.go b/agent/kvs_endpoint.go index 49cde3b62..20afe7a6a 100644 --- a/agent/kvs_endpoint.go +++ b/agent/kvs_endpoint.go @@ -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/") diff --git a/agent/session_endpoint.go b/agent/session_endpoint.go index 7961aa1de..60ca7cc91 100644 --- a/agent/session_endpoint.go +++ b/agent/session_endpoint.go @@ -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/") diff --git a/agent/structs/acl.go b/agent/structs/acl.go index 8a93d112b..0d007d149 100644 --- a/agent/structs/acl.go +++ b/agent/structs/acl.go @@ -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 != "" { diff --git a/agent/structs/check_definition.go b/agent/structs/check_definition.go index 8a6727f47..0096678c3 100644 --- a/agent/structs/check_definition.go +++ b/agent/structs/check_definition.go @@ -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 } diff --git a/agent/structs/check_type.go b/agent/structs/check_type.go index 104410493..7d87ed447 100644 --- a/agent/structs/check_type.go +++ b/agent/structs/check_type.go @@ -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 { diff --git a/agent/structs/config_entry_discoverychain.go b/agent/structs/config_entry_discoverychain.go index 7b7ffdf21..b8861ba31 100644 --- a/agent/structs/config_entry_discoverychain.go +++ b/agent/structs/config_entry_discoverychain.go @@ -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 diff --git a/agent/structs/connect_ca.go b/agent/structs/connect_ca.go index c66e0421f..4b52db9db 100644 --- a/agent/structs/connect_ca.go +++ b/agent/structs/connect_ca.go @@ -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 { diff --git a/agent/structs/connect_proxy_config.go b/agent/structs/connect_proxy_config.go index e9bf9f4d7..becee9a70 100644 --- a/agent/structs/connect_proxy_config.go +++ b/agent/structs/connect_proxy_config.go @@ -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 { diff --git a/agent/structs/discovery_chain.go b/agent/structs/discovery_chain.go index 1b00aebcc..d148515ad 100644 --- a/agent/structs/discovery_chain.go +++ b/agent/structs/discovery_chain.go @@ -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 diff --git a/agent/structs/intention.go b/agent/structs/intention.go index 8b2247c72..8664f76a3 100644 --- a/agent/structs/intention.go +++ b/agent/structs/intention.go @@ -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 } diff --git a/agent/structs/service_definition.go b/agent/structs/service_definition.go index 7b3643a7e..0d9617c08 100644 --- a/agent/structs/service_definition.go +++ b/agent/structs/service_definition.go @@ -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 { diff --git a/agent/structs/structs.go b/agent/structs/structs.go index 94e916172..9eb798bc3 100644 --- a/agent/structs/structs.go +++ b/agent/structs/structs.go @@ -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 { diff --git a/api/acl.go b/api/acl.go index d2669752c..4057344d8 100644 --- a/api/acl.go +++ b/api/acl.go @@ -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 diff --git a/command/acl/acl_helpers.go b/command/acl/acl_helpers.go index 57c51ce14..e7cbb735f 100644 --- a/command/acl/acl_helpers.go +++ b/command/acl/acl_helpers.go @@ -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)) diff --git a/command/acl/authmethod/create/authmethod_create.go b/command/acl/authmethod/create/authmethod_create.go index b95a9b064..515d26e75 100644 --- a/command/acl/authmethod/create/authmethod_create.go +++ b/command/acl/authmethod/create/authmethod_create.go @@ -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) } diff --git a/command/acl/authmethod/delete/authmethod_delete.go b/command/acl/authmethod/delete/authmethod_delete.go index 1b622db56..82b42fd39 100644 --- a/command/acl/authmethod/delete/authmethod_delete.go +++ b/command/acl/authmethod/delete/authmethod_delete.go @@ -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) } diff --git a/command/acl/authmethod/list/authmethod_list.go b/command/acl/authmethod/list/authmethod_list.go index a95420940..614c831fd 100644 --- a/command/acl/authmethod/list/authmethod_list.go +++ b/command/acl/authmethod/list/authmethod_list.go @@ -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) } diff --git a/command/acl/authmethod/read/authmethod_read.go b/command/acl/authmethod/read/authmethod_read.go index b60fd30a1..a973a04a6 100644 --- a/command/acl/authmethod/read/authmethod_read.go +++ b/command/acl/authmethod/read/authmethod_read.go @@ -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) } diff --git a/command/acl/authmethod/update/authmethod_update.go b/command/acl/authmethod/update/authmethod_update.go index 48571ed93..73db051ca 100644 --- a/command/acl/authmethod/update/authmethod_update.go +++ b/command/acl/authmethod/update/authmethod_update.go @@ -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) } diff --git a/command/acl/bindingrule/create/bindingrule_create.go b/command/acl/bindingrule/create/bindingrule_create.go index 19fb282c7..a71243375 100644 --- a/command/acl/bindingrule/create/bindingrule_create.go +++ b/command/acl/bindingrule/create/bindingrule_create.go @@ -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) } diff --git a/command/acl/bindingrule/delete/bindingrule_delete.go b/command/acl/bindingrule/delete/bindingrule_delete.go index 62b571bc6..635bee0a1 100644 --- a/command/acl/bindingrule/delete/bindingrule_delete.go +++ b/command/acl/bindingrule/delete/bindingrule_delete.go @@ -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) } diff --git a/command/acl/bindingrule/list/bindingrule_list.go b/command/acl/bindingrule/list/bindingrule_list.go index bd1feda0a..ddd8fbbec 100644 --- a/command/acl/bindingrule/list/bindingrule_list.go +++ b/command/acl/bindingrule/list/bindingrule_list.go @@ -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) } diff --git a/command/acl/bindingrule/read/bindingrule_read.go b/command/acl/bindingrule/read/bindingrule_read.go index d4788907a..20ca39aab 100644 --- a/command/acl/bindingrule/read/bindingrule_read.go +++ b/command/acl/bindingrule/read/bindingrule_read.go @@ -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) } diff --git a/command/acl/bindingrule/update/bindingrule_update.go b/command/acl/bindingrule/update/bindingrule_update.go index ec028cad4..0fdb0950c 100644 --- a/command/acl/bindingrule/update/bindingrule_update.go +++ b/command/acl/bindingrule/update/bindingrule_update.go @@ -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) } diff --git a/command/acl/policy/create/policy_create.go b/command/acl/policy/create/policy_create.go index 13d81b1d1..ffe05a3a6 100644 --- a/command/acl/policy/create/policy_create.go +++ b/command/acl/policy/create/policy_create.go @@ -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) } diff --git a/command/acl/policy/delete/policy_delete.go b/command/acl/policy/delete/policy_delete.go index d651dc777..fd4c848e7 100644 --- a/command/acl/policy/delete/policy_delete.go +++ b/command/acl/policy/delete/policy_delete.go @@ -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) } diff --git a/command/acl/policy/list/policy_list.go b/command/acl/policy/list/policy_list.go index 25a2b6e67..60d1d1694 100644 --- a/command/acl/policy/list/policy_list.go +++ b/command/acl/policy/list/policy_list.go @@ -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) } diff --git a/command/acl/policy/read/policy_read.go b/command/acl/policy/read/policy_read.go index 4b008c229..a087de545 100644 --- a/command/acl/policy/read/policy_read.go +++ b/command/acl/policy/read/policy_read.go @@ -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) } diff --git a/command/acl/policy/update/policy_update.go b/command/acl/policy/update/policy_update.go index 629d74878..43313c54f 100644 --- a/command/acl/policy/update/policy_update.go +++ b/command/acl/policy/update/policy_update.go @@ -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) } diff --git a/command/acl/role/create/role_create.go b/command/acl/role/create/role_create.go index 244084361..6125c876b 100644 --- a/command/acl/role/create/role_create.go +++ b/command/acl/role/create/role_create.go @@ -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) } diff --git a/command/acl/role/delete/role_delete.go b/command/acl/role/delete/role_delete.go index 7714be1f2..e4b0086a9 100644 --- a/command/acl/role/delete/role_delete.go +++ b/command/acl/role/delete/role_delete.go @@ -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) } diff --git a/command/acl/role/list/role_list.go b/command/acl/role/list/role_list.go index dc60a425f..7b5d4a5ee 100644 --- a/command/acl/role/list/role_list.go +++ b/command/acl/role/list/role_list.go @@ -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) } diff --git a/command/acl/role/read/role_read.go b/command/acl/role/read/role_read.go index 8b5b84086..dd26d6769 100644 --- a/command/acl/role/read/role_read.go +++ b/command/acl/role/read/role_read.go @@ -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) } diff --git a/command/acl/role/update/role_update.go b/command/acl/role/update/role_update.go index 3041192cf..fbd739aca 100644 --- a/command/acl/role/update/role_update.go +++ b/command/acl/role/update/role_update.go @@ -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) } diff --git a/command/acl/token/clone/token_clone.go b/command/acl/token/clone/token_clone.go index dfb086278..c4816d638 100644 --- a/command/acl/token/clone/token_clone.go +++ b/command/acl/token/clone/token_clone.go @@ -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) } diff --git a/command/acl/token/clone/token_clone_test.go b/command/acl/token/clone/token_clone_test.go index 55a81a682..95292b367 100644 --- a/command/acl/token/clone/token_clone_test.go +++ b/command/acl/token/clone/token_clone_test.go @@ -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" + diff --git a/command/acl/token/create/token_create.go b/command/acl/token/create/token_create.go index 5d037c0c6..603b4e25d 100644 --- a/command/acl/token/create/token_create.go +++ b/command/acl/token/create/token_create.go @@ -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) } diff --git a/command/acl/token/delete/token_delete.go b/command/acl/token/delete/token_delete.go index 30be88a3e..fe93d2e6b 100644 --- a/command/acl/token/delete/token_delete.go +++ b/command/acl/token/delete/token_delete.go @@ -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) } diff --git a/command/acl/token/list/token_list.go b/command/acl/token/list/token_list.go index 9c92ab557..2ca5eb800 100644 --- a/command/acl/token/list/token_list.go +++ b/command/acl/token/list/token_list.go @@ -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) } diff --git a/command/acl/token/read/token_read.go b/command/acl/token/read/token_read.go index eddb96150..ce284dc2b 100644 --- a/command/acl/token/read/token_read.go +++ b/command/acl/token/read/token_read.go @@ -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) } diff --git a/command/acl/token/update/token_update.go b/command/acl/token/update/token_update.go index aeaf72c9d..841c6c284 100644 --- a/command/acl/token/update/token_update.go +++ b/command/acl/token/update/token_update.go @@ -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) } diff --git a/command/flags/http.go b/command/flags/http.go index c32b70084..62597f5f3 100644 --- a/command/flags/http.go +++ b/command/flags/http.go @@ -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() } diff --git a/command/kv/del/kv_delete.go b/command/kv/del/kv_delete.go index f5546e7e1..78e1967ee 100644 --- a/command/kv/del/kv_delete.go +++ b/command/kv/del/kv_delete.go @@ -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) } diff --git a/command/kv/exp/kv_export.go b/command/kv/exp/kv_export.go index 97030c5ae..9fbb2838c 100644 --- a/command/kv/exp/kv_export.go +++ b/command/kv/exp/kv_export.go @@ -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) } diff --git a/command/kv/get/kv_get.go b/command/kv/get/kv_get.go index f541d84d6..7c7e79648 100644 --- a/command/kv/get/kv_get.go +++ b/command/kv/get/kv_get.go @@ -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) } diff --git a/command/kv/imp/kv_import.go b/command/kv/imp/kv_import.go index 030c7110c..40cb27922 100644 --- a/command/kv/imp/kv_import.go +++ b/command/kv/imp/kv_import.go @@ -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) } diff --git a/command/kv/put/kv_put.go b/command/kv/put/kv_put.go index abe51a538..0f416273d 100644 --- a/command/kv/put/kv_put.go +++ b/command/kv/put/kv_put.go @@ -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) } diff --git a/command/login/login.go b/command/login/login.go index 34b066508..4f1026656 100644 --- a/command/login/login.go +++ b/command/login/login.go @@ -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) } diff --git a/command/logout/logout.go b/command/logout/logout.go index c86d33979..8edd8fd5f 100644 --- a/command/logout/logout.go +++ b/command/logout/logout.go @@ -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) } diff --git a/lib/json.go b/lib/json.go new file mode 100644 index 000000000..59c7612d1 --- /dev/null +++ b/lib/json.go @@ -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) +} diff --git a/website/source/api/acl/acl.html.md b/website/source/api/acl/acl.html.md index 205bdb7dd..d09c480c6 100644 --- a/website/source/api/acl/acl.html.md +++ b/website/source/api/acl/acl.html.md @@ -304,6 +304,12 @@ replication enabled. - `Meta` `(map: 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 diff --git a/website/source/api/acl/auth-methods.html.md b/website/source/api/acl/auth-methods.html.md index 0ad79936e..333696823 100644 --- a/website/source/api/acl/auth-methods.html.md +++ b/website/source/api/acl/auth-methods.html.md @@ -36,7 +36,7 @@ The table below shows this endpoint's support for | ---------------- | ----------------- | ------------- | ------------ | | `NO` | `none` | `none` | `acl:write` | -### Parameters +### Payload Fields - `Name` `(string: )` - Specifies a name for the ACL auth method. The name can contain alphanumeric characters, dashes `-`, and underscores `_`. @@ -53,6 +53,12 @@ The table below shows this endpoint's support for the chosen auth method. Contents will vary depending upon the type chosen. 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 @@ -118,6 +124,12 @@ The table below shows this endpoint's support for - `name` `(string: )` - 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 @@ -178,6 +190,12 @@ The table below shows this endpoint's support for the chosen auth method. Contents will vary depending upon the type chosen. 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 @@ -247,6 +265,12 @@ The table below shows this endpoint's support for - `name` `(string: )` - 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 @@ -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 diff --git a/website/source/api/acl/binding-rules.html.md b/website/source/api/acl/binding-rules.html.md index becb7eff5..9fbe52820 100644 --- a/website/source/api/acl/binding-rules.html.md +++ b/website/source/api/acl/binding-rules.html.md @@ -87,6 +87,12 @@ The table below shows this endpoint's support for ```text 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 @@ -147,6 +153,13 @@ The table below shows this endpoint's support for - `id` `(string: )` - 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 @@ -244,6 +257,12 @@ The table below shows this endpoint's support for ```text 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 @@ -304,6 +323,12 @@ The table below shows this endpoint's support for - `id` `(string: )` - 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 @@ -339,6 +364,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 diff --git a/website/source/api/acl/policies.html.md b/website/source/api/acl/policies.html.md index e13854e69..6ac20763a 100644 --- a/website/source/api/acl/policies.html.md +++ b/website/source/api/acl/policies.html.md @@ -49,6 +49,12 @@ The table below shows this endpoint's support for - `Datacenters` `(array)` - Specifies the datacenters the policy is valid within. 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 @@ -109,6 +115,12 @@ The table below shows this endpoint's support for - `id` `(string: )` - 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 @@ -169,6 +181,12 @@ The table below shows this endpoint's support for - `Datacenters` `(array)` - Specifies the datacenters this policy is valid within. 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 @@ -228,6 +246,12 @@ The table below shows this endpoint's support for - `id` `(string: )` - 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 @@ -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 diff --git a/website/source/api/acl/roles.html.md b/website/source/api/acl/roles.html.md index 369fd2e97..d155ee891 100644 --- a/website/source/api/acl/roles.html.md +++ b/website/source/api/acl/roles.html.md @@ -63,6 +63,12 @@ The table below shows this endpoint's support for policy is valid within. When no datacenters are provided the effective 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 @@ -153,6 +159,12 @@ The table below shows this endpoint's support for - `id` `(string: )` - 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 @@ -213,6 +225,12 @@ The table below shows this endpoint's support for - `name` `(string: )` - 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 @@ -291,6 +309,12 @@ The table below shows this endpoint's support for - `ServiceIdentities` `(array)` - The list of [service 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 @@ -367,6 +391,12 @@ The table below shows this endpoint's support for - `id` `(string: )` - 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 @@ -402,6 +432,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 diff --git a/website/source/api/acl/tokens.html.md b/website/source/api/acl/tokens.html.md index e711fff8a..705e2ddc6 100644 --- a/website/source/api/acl/tokens.html.md +++ b/website/source/api/acl/tokens.html.md @@ -89,6 +89,12 @@ The table below shows this endpoint's support for specified in the form of `"60s"` or `"5m"` (i.e., 60 seconds or 5 minutes, 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 @@ -163,6 +169,12 @@ The table below shows this endpoint's support for - `AccessorID` `(string: )` - 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 @@ -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 @@ -482,6 +505,12 @@ The table below shows this endpoint's support for - `AccessorID` `(string: )` - 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 @@ -523,6 +552,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 diff --git a/website/source/api/namespaces.html.md b/website/source/api/namespaces.html.md new file mode 100644 index 000000000..7092f6ad2 --- /dev/null +++ b/website/source/api/namespaces.html.md @@ -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: )` - The namespaces name. This must be a valid + DNS hostname label. + +- `Description` `(string: "")` - Free form namespaces description. + +- `ACLs` `(object: )` - 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)` - 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)` - 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: )` - 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`1 | + +1 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: )` - 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: )` - 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: )` - 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)` - 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)` - 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: )` - 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: )` - 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`1 | + +1 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 + } +] +``` diff --git a/website/source/docs/acl/acl-rules.html.md b/website/source/docs/acl/acl-rules.html.md.erb similarity index 91% rename from website/source/docs/acl/acl-rules.html.md rename to website/source/docs/acl/acl-rules.html.md.erb index 44abde6df..bf7339270 100644 --- a/website/source/docs/acl/acl-rules.html.md +++ b/website/source/docs/acl/acl-rules.html.md.erb @@ -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 Enterprise + +[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. diff --git a/website/source/docs/acl/acl-system.html.md b/website/source/docs/acl/acl-system.html.md index 37b244696..778d43201 100644 --- a/website/source/docs/acl/acl-system.html.md +++ b/website/source/docs/acl/acl-system.html.md @@ -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 @@ -121,8 +130,11 @@ of the following elements: * **ID** - The role's auto-generated public identifier. * **Name** - A unique meaningful name for the role. * **Description** - A human readable description of the role. (Optional) -* **Policy Set** - The list of policies that are applicable for the role. +* **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 diff --git a/website/source/docs/commands/_http_api_namespace_options.html.md b/website/source/docs/commands/_http_api_namespace_options.html.md new file mode 100644 index 000000000..9c5461d1e --- /dev/null +++ b/website/source/docs/commands/_http_api_namespace_options.html.md @@ -0,0 +1,3 @@ +* `-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. diff --git a/website/source/docs/commands/acl/auth-method/create.html.md.erb b/website/source/docs/commands/acl/auth-method/create.html.md.erb index 4ca4c21d7..b2ecbb656 100644 --- a/website/source/docs/commands/acl/auth-method/create.html.md.erb +++ b/website/source/docs/commands/acl/auth-method/create.html.md.erb @@ -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: diff --git a/website/source/docs/commands/acl/auth-method/delete.html.md.erb b/website/source/docs/commands/acl/auth-method/delete.html.md.erb index 46c826761..e3442a3e5 100644 --- a/website/source/docs/commands/acl/auth-method/delete.html.md.erb +++ b/website/source/docs/commands/acl/auth-method/delete.html.md.erb @@ -23,6 +23,10 @@ Usage: `consul acl auth-method delete [options]` * `-name=` - The Name of the auth method to delete. +#### Enterprise Options + +<%= partial "docs/commands/http_api_namespace_options" %> + ## Examples Delete an auth method: diff --git a/website/source/docs/commands/acl/auth-method/list.html.md.erb b/website/source/docs/commands/acl/auth-method/list.html.md.erb index 6f9c830cf..19eedccd7 100644 --- a/website/source/docs/commands/acl/auth-method/list.html.md.erb +++ b/website/source/docs/commands/acl/auth-method/list.html.md.erb @@ -23,6 +23,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 diff --git a/website/source/docs/commands/acl/auth-method/read.html.md.erb b/website/source/docs/commands/acl/auth-method/read.html.md.erb index 6f5a69fb7..7f23f283f 100644 --- a/website/source/docs/commands/acl/auth-method/read.html.md.erb +++ b/website/source/docs/commands/acl/auth-method/read.html.md.erb @@ -26,6 +26,10 @@ Usage: `consul acl auth-method read [options] [args]` * `-name=` - The name of the auth method to read. +#### Enterprise Options + +<%= partial "docs/commands/http_api_namespace_options" %> + ## Examples Get auth method details: diff --git a/website/source/docs/commands/acl/auth-method/update.html.md.erb b/website/source/docs/commands/acl/auth-method/update.html.md.erb index 91e80a5c1..825b9a9e9 100644 --- a/website/source/docs/commands/acl/auth-method/update.html.md.erb +++ b/website/source/docs/commands/acl/auth-method/update.html.md.erb @@ -46,6 +46,10 @@ Usage: `consul acl auth-method update [options] [args]` * `-no-merge` - Do not merge the current auth method information with what is provided 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 diff --git a/website/source/docs/commands/acl/binding-rule/create.html.md.erb b/website/source/docs/commands/acl/binding-rule/create.html.md.erb index e14fa0295..b791f1f76 100644 --- a/website/source/docs/commands/acl/binding-rule/create.html.md.erb +++ b/website/source/docs/commands/acl/binding-rule/create.html.md.erb @@ -37,6 +37,10 @@ Usage: `consul acl binding-rule create [options] [args]` * `-selector=` - 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: diff --git a/website/source/docs/commands/acl/binding-rule/delete.html.md.erb b/website/source/docs/commands/acl/binding-rule/delete.html.md.erb index 872e08e91..796db4066 100644 --- a/website/source/docs/commands/acl/binding-rule/delete.html.md.erb +++ b/website/source/docs/commands/acl/binding-rule/delete.html.md.erb @@ -24,6 +24,10 @@ Usage: `consul acl binding-rule delete [options]` * `-id=` - 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: diff --git a/website/source/docs/commands/acl/binding-rule/list.html.md.erb b/website/source/docs/commands/acl/binding-rule/list.html.md.erb index a28d034fe..f71ec55dd 100644 --- a/website/source/docs/commands/acl/binding-rule/list.html.md.erb +++ b/website/source/docs/commands/acl/binding-rule/list.html.md.erb @@ -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. diff --git a/website/source/docs/commands/acl/binding-rule/read.html.md.erb b/website/source/docs/commands/acl/binding-rule/read.html.md.erb index aa1ec22ed..cbb57e90a 100644 --- a/website/source/docs/commands/acl/binding-rule/read.html.md.erb +++ b/website/source/docs/commands/acl/binding-rule/read.html.md.erb @@ -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: diff --git a/website/source/docs/commands/acl/binding-rule/update.html.md.erb b/website/source/docs/commands/acl/binding-rule/update.html.md.erb index 70abd00e6..7cae275bb 100644 --- a/website/source/docs/commands/acl/binding-rule/update.html.md.erb +++ b/website/source/docs/commands/acl/binding-rule/update.html.md.erb @@ -44,6 +44,10 @@ Usage: `consul acl binding-rule update [options] [args]` * `-selector=` - 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: diff --git a/website/source/docs/commands/acl/policy/create.html.md.erb b/website/source/docs/commands/acl/policy/create.html.md.erb index 462958c7a..89377c61d 100644 --- a/website/source/docs/commands/acl/policy/create.html.md.erb +++ b/website/source/docs/commands/acl/policy/create.html.md.erb @@ -55,6 +55,10 @@ Usage: `consul acl policy create [options] [args]` * `-valid-datacenter=` - 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: diff --git a/website/source/docs/commands/acl/policy/delete.html.md.erb b/website/source/docs/commands/acl/policy/delete.html.md.erb index c7bc61e14..56fac5c33 100644 --- a/website/source/docs/commands/acl/policy/delete.html.md.erb +++ b/website/source/docs/commands/acl/policy/delete.html.md.erb @@ -26,6 +26,10 @@ Usage: `consul acl policy delete [options]` * `-name=` - The Name of the policy to delete. +#### Enterprise Options + +<%= partial "docs/commands/http_api_namespace_options" %> + ## Examples Delete a policy: diff --git a/website/source/docs/commands/acl/policy/list.html.md.erb b/website/source/docs/commands/acl/policy/list.html.md.erb index a321737c7..3b573e6da 100644 --- a/website/source/docs/commands/acl/policy/list.html.md.erb +++ b/website/source/docs/commands/acl/policy/list.html.md.erb @@ -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. diff --git a/website/source/docs/commands/acl/policy/read.html.md.erb b/website/source/docs/commands/acl/policy/read.html.md.erb index ebe586dca..732d7985b 100644 --- a/website/source/docs/commands/acl/policy/read.html.md.erb +++ b/website/source/docs/commands/acl/policy/read.html.md.erb @@ -29,6 +29,10 @@ Usage: `consul acl policy read [options] [args]` * `-name=` - The name of the policy to read. +#### Enterprise Options + +<%= partial "docs/commands/http_api_namespace_options" %> + ## Examples Get policy details: diff --git a/website/source/docs/commands/acl/policy/update.html.md.erb b/website/source/docs/commands/acl/policy/update.html.md.erb index 5e6fe98b4..23f0ed8b2 100644 --- a/website/source/docs/commands/acl/policy/update.html.md.erb +++ b/website/source/docs/commands/acl/policy/update.html.md.erb @@ -46,6 +46,10 @@ Usage: `consul acl policy update [options] [args]` * `-valid-datacenter=` - 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: diff --git a/website/source/docs/commands/acl/role/create.html.md.erb b/website/source/docs/commands/acl/role/create.html.md.erb index 092fb73c8..bb96a5092 100644 --- a/website/source/docs/commands/acl/role/create.html.md.erb +++ b/website/source/docs/commands/acl/role/create.html.md.erb @@ -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: diff --git a/website/source/docs/commands/acl/role/delete.html.md.erb b/website/source/docs/commands/acl/role/delete.html.md.erb index 16a0b5520..3383b6994 100644 --- a/website/source/docs/commands/acl/role/delete.html.md.erb +++ b/website/source/docs/commands/acl/role/delete.html.md.erb @@ -26,6 +26,10 @@ Usage: `consul acl role delete [options]` * `-name=` - The Name of the role to delete. +#### Enterprise Options + +<%= partial "docs/commands/http_api_namespace_options" %> + ## Examples Delete a role by prefix: diff --git a/website/source/docs/commands/acl/role/list.html.md.erb b/website/source/docs/commands/acl/role/list.html.md.erb index f2f2da4d0..84a967436 100644 --- a/website/source/docs/commands/acl/role/list.html.md.erb +++ b/website/source/docs/commands/acl/role/list.html.md.erb @@ -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. diff --git a/website/source/docs/commands/acl/role/read.html.md.erb b/website/source/docs/commands/acl/role/read.html.md.erb index 483a89925..b913a6716 100644 --- a/website/source/docs/commands/acl/role/read.html.md.erb +++ b/website/source/docs/commands/acl/role/read.html.md.erb @@ -29,6 +29,10 @@ Usage: `consul acl role read [options] [args]` * `-name=` - The name of the role to read. +#### Enterprise Options + +<%= partial "docs/commands/http_api_namespace_options" %> + ## Examples Get role details: diff --git a/website/source/docs/commands/acl/role/update.html.md.erb b/website/source/docs/commands/acl/role/update.html.md.erb index 867e23387..20018e478 100644 --- a/website/source/docs/commands/acl/role/update.html.md.erb +++ b/website/source/docs/commands/acl/role/update.html.md.erb @@ -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: diff --git a/website/source/docs/commands/acl/token/clone.html.md.erb b/website/source/docs/commands/acl/token/clone.html.md.erb index e6d94eb6a..3ec458c5e 100644 --- a/website/source/docs/commands/acl/token/clone.html.md.erb +++ b/website/source/docs/commands/acl/token/clone.html.md.erb @@ -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: diff --git a/website/source/docs/commands/acl/token/create.html.md.erb b/website/source/docs/commands/acl/token/create.html.md.erb index a57840447..aadd4fb46 100644 --- a/website/source/docs/commands/acl/token/create.html.md.erb +++ b/website/source/docs/commands/acl/token/create.html.md.erb @@ -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: diff --git a/website/source/docs/commands/acl/token/delete.html.md.erb b/website/source/docs/commands/acl/token/delete.html.md.erb index 6227870a9..88a1de4ca 100644 --- a/website/source/docs/commands/acl/token/delete.html.md.erb +++ b/website/source/docs/commands/acl/token/delete.html.md.erb @@ -24,6 +24,10 @@ Usage: `consul acl token delete [options]` * `-id=` - 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: diff --git a/website/source/docs/commands/acl/token/list.html.md.erb b/website/source/docs/commands/acl/token/list.html.md.erb index 434b4b963..18d385570 100644 --- a/website/source/docs/commands/acl/token/list.html.md.erb +++ b/website/source/docs/commands/acl/token/list.html.md.erb @@ -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. diff --git a/website/source/docs/commands/acl/token/read.html.md.erb b/website/source/docs/commands/acl/token/read.html.md.erb index 2f37a9d0c..5cbee72ff 100644 --- a/website/source/docs/commands/acl/token/read.html.md.erb +++ b/website/source/docs/commands/acl/token/read.html.md.erb @@ -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: diff --git a/website/source/docs/commands/acl/token/update.html.md.erb b/website/source/docs/commands/acl/token/update.html.md.erb index e2cc6232a..54573fc86 100644 --- a/website/source/docs/commands/acl/token/update.html.md.erb +++ b/website/source/docs/commands/acl/token/update.html.md.erb @@ -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: diff --git a/website/source/docs/commands/kv/delete.html.markdown.erb b/website/source/docs/commands/kv/delete.html.markdown.erb index 9bf234a67..f74c67a77 100644 --- a/website/source/docs/commands/kv/delete.html.markdown.erb +++ b/website/source/docs/commands/kv/delete.html.markdown.erb @@ -30,6 +30,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 diff --git a/website/source/docs/commands/kv/export.html.markdown.erb b/website/source/docs/commands/kv/export.html.markdown.erb index 63cc98507..72834b420 100644 --- a/website/source/docs/commands/kv/export.html.markdown.erb +++ b/website/source/docs/commands/kv/export.html.markdown.erb @@ -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: diff --git a/website/source/docs/commands/kv/get.html.markdown.erb b/website/source/docs/commands/kv/get.html.markdown.erb index a47d17b65..92a801826 100644 --- a/website/source/docs/commands/kv/get.html.markdown.erb +++ b/website/source/docs/commands/kv/get.html.markdown.erb @@ -41,6 +41,10 @@ Usage: `consul kv get [options] [KEY_OR_PREFIX]` * `-separator=` - String to use as a separator for recursive lookups. The 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 diff --git a/website/source/docs/commands/kv/import.html.markdown.erb b/website/source/docs/commands/kv/import.html.markdown.erb index 107a53bd9..786101ff4 100644 --- a/website/source/docs/commands/kv/import.html.markdown.erb +++ b/website/source/docs/commands/kv/import.html.markdown.erb @@ -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 ``` - - diff --git a/website/source/docs/commands/kv/put.html.markdown.erb b/website/source/docs/commands/kv/put.html.markdown.erb index 1f2400f12..388d37b79 100644 --- a/website/source/docs/commands/kv/put.html.markdown.erb +++ b/website/source/docs/commands/kv/put.html.markdown.erb @@ -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 diff --git a/website/source/docs/commands/namespace.html.md.erb b/website/source/docs/commands/namespace.html.md.erb new file mode 100644 index 000000000..e9915ea17 --- /dev/null +++ b/website/source/docs/commands/namespace.html.md.erb @@ -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 ` + +For the exact documentation for your Consul version, run `consul namespace -h` to view the complete list of subcommands. + +```text +Usage: consul namespace [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 +``` diff --git a/website/source/docs/commands/namespace/delete.html.md.erb b/website/source/docs/commands/namespace/delete.html.md.erb new file mode 100644 index 000000000..3c3153705 --- /dev/null +++ b/website/source/docs/commands/namespace/delete.html.md.erb @@ -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 ` + +#### 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" +``` diff --git a/website/source/docs/commands/namespace/list.html.md.erb b/website/source/docs/commands/namespace/list.html.md.erb new file mode 100644 index 000000000..f5968f544 --- /dev/null +++ b/website/source/docs/commands/namespace/list.html.md.erb @@ -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=` - 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 + } +] +``` diff --git a/website/source/docs/commands/namespace/read.html.md.erb b/website/source/docs/commands/namespace/read.html.md.erb new file mode 100644 index 000000000..b9e28346a --- /dev/null +++ b/website/source/docs/commands/namespace/read.html.md.erb @@ -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 ` + +#### API Options + +<%= partial "docs/commands/http_api_options_client" %> +<%= partial "docs/commands/http_api_options_server" %> + +#### Command Options + +* `-format=` - 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 +} +``` diff --git a/website/source/docs/commands/namespace/write.html.md.erb b/website/source/docs/commands/namespace/write.html.md.erb new file mode 100644 index 000000000..c04ad3f2a --- /dev/null +++ b/website/source/docs/commands/namespace/write.html.md.erb @@ -0,0 +1,75 @@ +--- +layout: "docs" +page_title: "Commands: Namespace Write" +sidebar_current: "docs-commands-namespace-write" +--- + +<%= enterprise_alert :consul %> + +# Consul Namespace Write + +Command: `consul namespace write` + +This `namespace write` command creates or updates a namespaces configuration. This was added in Consul Enterprise 1.7.0. + +## Usage + +Usage: `consul namespace write ` + +The `` must either be a file path or `-` to indicate that +the definition should be read from stdin. The definition can be in either JSON +or HCL format. See [here](/docs/enterprise/namespaces/index.html#namespace-definition) for a description of the namespace definition. + +#### API Options + +<%= partial "docs/commands/http_api_options_client" %> +<%= partial "docs/commands/http_api_options_server" %> + +#### Command Options + +* `-format=` - 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 + +Create a new Namespace: + +```sh +$ consul namespace write - <<< 'Name = "team-1"' +Name: team-1 +Description: +``` + +Showing Raft Metadata: + +```sh +$ consul namespace write -meta - <<< 'Name = "team-1"' +Name: team-1 +Description: +Create Index: 339 +Modify Index: 344 +``` + +JSON Format: + +```sh +$ cat ns.hcl +Name = "foo" +Description = "Example Namespace" +Meta { + team-id = "574407f3-8b26-4c84-8e51-028bb8cbdd37" +} +$ consul namespace write -format=json ns.hcl +{ + "Name": "foo", + "Description": "Example Namespace", + "Meta": { + "team-id": "574407f3-8b26-4c84-8e51-028bb8cbdd37" + }, + "CreateIndex": 352, + "ModifyIndex": 352 +} +``` diff --git a/website/source/docs/enterprise/index.html.md b/website/source/docs/enterprise/index.html.md index 957a204b7..2a4206b1f 100644 --- a/website/source/docs/enterprise/index.html.md +++ b/website/source/docs/enterprise/index.html.md @@ -22,6 +22,7 @@ Features include: - [Advanced Federation for Complex Network Topologies](/docs/enterprise/federation/index.html) - [Network Segments](/docs/enterprise/network-segments/index.html) +- [Namespaces](/docs/enterprise/namespaces/index.html) - [Sentinel](/docs/enterprise/sentinel/index.html) These features are part of [Consul diff --git a/website/source/docs/enterprise/namespaces/index.html.md b/website/source/docs/enterprise/namespaces/index.html.md new file mode 100644 index 000000000..0e8cdb17e --- /dev/null +++ b/website/source/docs/enterprise/namespaces/index.html.md @@ -0,0 +1,104 @@ +--- +layout: "docs" +page_title: "Consul Enterprise Namespaces" +sidebar_current: "docs-enterprise-namespaces" +description: |- + Consul Enterprise enables data isolation with Namespaces. +--- + +# Consul Enterprise Namespaces + +With [Consul Enterprise](https://www.hashicorp.com/consul.html) v1.7.0, data for different users or teams +can be isolated from each other with the use of Namespaces. Namespaces help reduce operational challenges +by removing restrictions around uniqueness of resource names across distinct teams, and enable operators +to provide self-service through delegation of administrative privileges. + +## Namespace Definition + +Namespaces are managed exclusively through the [HTTP API](/api/namespaces.html) and the [Consul CLI](/docs/commands/namespace.html). +The HTTP API accepts only JSON formatted definitions while the CLI will parse either JSON or HCL. + +An example Namespace definition looks like the following: + +JSON: + +```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" + } +} +``` + +HCL: + +```hcl +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" +} +``` + +### Fields + +- `Name` `(string: )` - The Namespaces name must be a valid DNS hostname label. + +- `Description` `(string: "")` - This field is intended to be a human readable description of the + namespace's purpose. It is not used internally. + +- `ACLs` `(object: )` - This fields is a nested JSON/HCL object to contain the Namespaces + ACL configuration. + + - `PolicyDefaults` `(array)` - A list of default policies to be applied to all tokens + created in this namespace. The ACLLink object can contain an `ID` and/or `Name` field. When the + policies ID is omitted Consul will resolve the name to an ID before writing the Namespace + definition internally. Note that all policies linked in a Namespace definition must be defined + within the `default namespace. + + - `RoleDefaults` `(array)` - A list of default roles to be applied to all tokens + created in this namespace. The ACLLink object can contain an `ID` and/or `Name` field. When the + roles' ID is omitted Consul will resolve the name to an ID before writing the Namespace + definition internally. Note that all roles linked in a Namespace definition must be defined + within the `default namespace. + +- `Meta` `(map: )` - Specifies arbitrary KV metadata to associate with + this namespace. diff --git a/website/source/layouts/api.erb b/website/source/layouts/api.erb index 63f5172db..18aec2fab 100644 --- a/website/source/layouts/api.erb +++ b/website/source/layouts/api.erb @@ -116,6 +116,9 @@ + > + Namespaces + > Prepared Queries diff --git a/website/source/layouts/docs.erb b/website/source/layouts/docs.erb index 7880478c3..ca93660d0 100644 --- a/website/source/layouts/docs.erb +++ b/website/source/layouts/docs.erb @@ -326,6 +326,24 @@ > monitor + + > + namespace + + > operator @@ -647,9 +665,12 @@ > Advanced Federation - > + > Network Segments + > + Namespaces + > Sentinel