From a704ebe6392a645f64ce56e87aec30bf1ac3df29 Mon Sep 17 00:00:00 2001 From: Matt Keeler Date: Fri, 6 Dec 2019 11:14:56 -0500 Subject: [PATCH] Add Namespace support to the API module and the CLI commands (#6874) Also update the Docs and fixup the HTTP API to return proper errors when someone attempts to use Namespaces with an OSS agent. Add Namespace HTTP API docs Make all API endpoints disallow unknown fields --- agent/acl_endpoint.go | 105 ++-- agent/agent_endpoint_test.go | 2 +- agent/discovery_chain_endpoint.go | 3 +- agent/http.go | 7 +- agent/http_oss.go | 30 +- agent/kvs_endpoint.go | 4 +- agent/session_endpoint.go | 27 +- agent/structs/acl.go | 11 +- agent/structs/check_definition.go | 4 +- agent/structs/check_type.go | 9 +- agent/structs/config_entry_discoverychain.go | 5 +- agent/structs/connect_ca.go | 3 +- agent/structs/connect_proxy_config.go | 6 +- agent/structs/discovery_chain.go | 4 +- agent/structs/intention.go | 4 +- agent/structs/service_definition.go | 5 +- agent/structs/structs.go | 8 +- api/acl.go | 32 ++ command/acl/acl_helpers.go | 30 ++ .../authmethod/create/authmethod_create.go | 1 + .../authmethod/delete/authmethod_delete.go | 1 + .../acl/authmethod/list/authmethod_list.go | 1 + .../acl/authmethod/read/authmethod_read.go | 1 + .../authmethod/update/authmethod_update.go | 1 + .../bindingrule/create/bindingrule_create.go | 1 + .../bindingrule/delete/bindingrule_delete.go | 1 + .../acl/bindingrule/list/bindingrule_list.go | 1 + .../acl/bindingrule/read/bindingrule_read.go | 1 + .../bindingrule/update/bindingrule_update.go | 1 + command/acl/policy/create/policy_create.go | 1 + command/acl/policy/delete/policy_delete.go | 1 + command/acl/policy/list/policy_list.go | 1 + command/acl/policy/read/policy_read.go | 1 + command/acl/policy/update/policy_update.go | 1 + command/acl/role/create/role_create.go | 1 + command/acl/role/delete/role_delete.go | 1 + command/acl/role/list/role_list.go | 1 + command/acl/role/read/role_read.go | 1 + command/acl/role/update/role_update.go | 1 + command/acl/token/clone/token_clone.go | 1 + command/acl/token/clone/token_clone_test.go | 1 + command/acl/token/create/token_create.go | 1 + command/acl/token/delete/token_delete.go | 1 + command/acl/token/list/token_list.go | 1 + command/acl/token/read/token_read.go | 1 + command/acl/token/update/token_update.go | 1 + command/flags/http.go | 19 +- command/kv/del/kv_delete.go | 1 + command/kv/exp/kv_export.go | 1 + command/kv/get/kv_get.go | 1 + command/kv/imp/kv_import.go | 1 + command/kv/put/kv_put.go | 1 + command/login/login.go | 1 + command/logout/logout.go | 1 + lib/json.go | 27 + website/source/api/acl/acl.html.md | 6 + website/source/api/acl/auth-methods.html.md | 36 +- website/source/api/acl/binding-rules.html.md | 32 ++ website/source/api/acl/policies.html.md | 33 ++ website/source/api/acl/roles.html.md | 39 ++ website/source/api/acl/tokens.html.md | 36 ++ website/source/api/namespaces.html.md | 483 ++++++++++++++++++ ...cl-rules.html.md => acl-rules.html.md.erb} | 64 +++ website/source/docs/acl/acl-system.html.md | 21 +- .../_http_api_namespace_options.html.md | 3 + .../acl/auth-method/create.html.md.erb | 4 + .../acl/auth-method/delete.html.md.erb | 4 + .../commands/acl/auth-method/list.html.md.erb | 4 + .../commands/acl/auth-method/read.html.md.erb | 4 + .../acl/auth-method/update.html.md.erb | 4 + .../acl/binding-rule/create.html.md.erb | 4 + .../acl/binding-rule/delete.html.md.erb | 4 + .../acl/binding-rule/list.html.md.erb | 4 + .../acl/binding-rule/read.html.md.erb | 4 + .../acl/binding-rule/update.html.md.erb | 4 + .../commands/acl/policy/create.html.md.erb | 4 + .../commands/acl/policy/delete.html.md.erb | 4 + .../docs/commands/acl/policy/list.html.md.erb | 4 + .../docs/commands/acl/policy/read.html.md.erb | 4 + .../commands/acl/policy/update.html.md.erb | 4 + .../docs/commands/acl/role/create.html.md.erb | 4 + .../docs/commands/acl/role/delete.html.md.erb | 4 + .../docs/commands/acl/role/list.html.md.erb | 4 + .../docs/commands/acl/role/read.html.md.erb | 4 + .../docs/commands/acl/role/update.html.md.erb | 4 + .../docs/commands/acl/token/clone.html.md.erb | 4 + .../commands/acl/token/create.html.md.erb | 4 + .../commands/acl/token/delete.html.md.erb | 4 + .../docs/commands/acl/token/list.html.md.erb | 4 + .../docs/commands/acl/token/read.html.md.erb | 4 + .../commands/acl/token/update.html.md.erb | 4 + .../docs/commands/kv/delete.html.markdown.erb | 4 + .../docs/commands/kv/export.html.markdown.erb | 4 + .../docs/commands/kv/get.html.markdown.erb | 4 + .../docs/commands/kv/import.html.markdown.erb | 6 +- .../docs/commands/kv/put.html.markdown.erb | 4 + .../docs/commands/namespace.html.md.erb | 71 +++ .../commands/namespace/delete.html.md.erb | 31 ++ .../docs/commands/namespace/list.html.md.erb | 98 ++++ .../docs/commands/namespace/read.html.md.erb | 66 +++ .../docs/commands/namespace/write.html.md.erb | 75 +++ website/source/docs/enterprise/index.html.md | 1 + .../docs/enterprise/namespaces/index.html.md | 104 ++++ website/source/layouts/api.erb | 3 + website/source/layouts/docs.erb | 23 +- 105 files changed, 1648 insertions(+), 82 deletions(-) create mode 100644 lib/json.go create mode 100644 website/source/api/namespaces.html.md rename website/source/docs/acl/{acl-rules.html.md => acl-rules.html.md.erb} (91%) create mode 100644 website/source/docs/commands/_http_api_namespace_options.html.md create mode 100644 website/source/docs/commands/namespace.html.md.erb create mode 100644 website/source/docs/commands/namespace/delete.html.md.erb create mode 100644 website/source/docs/commands/namespace/list.html.md.erb create mode 100644 website/source/docs/commands/namespace/read.html.md.erb create mode 100644 website/source/docs/commands/namespace/write.html.md.erb create mode 100644 website/source/docs/enterprise/namespaces/index.html.md diff --git a/agent/acl_endpoint.go b/agent/acl_endpoint.go index 41bc8be5d9f0..a3ab26c2476d 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 6437b7c15ff0..ef19f0970e8b 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 7e3bd31b71bf..6ed895a9e79f 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 9e4941457772..234fe65b7aec 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 c770ce152aa5..cf1fc63226b9 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 49cde3b62678..20afe7a6af3c 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 7961aa1de690..60ca7cc91f89 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 8a93d112bb17..0d007d14944d 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 8a6727f4730b..0096678c3108 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 1044104934a7..7d87ed447101 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 7b7ffdf2155b..b8861ba3183f 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 c66e0421f26c..4b52db9dbb11 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 e9bf9f4d7ce5..becee9a70710 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 1b00aebcc884..d148515adf45 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 8b2247c7229c..8664f76a3d87 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 7b3643a7e29f..0d9617c0822f 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 94e916172c44..9eb798bc399d 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 d2669752cc13..4057344d89f0 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 57c51ce14b48..e7cbb735fa64 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 b95a9b064812..515d26e751fb 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 1b622db56bd1..82b42fd391bd 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 a95420940224..614c831fd53a 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 b60fd30a1969..a973a04a6bd5 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 48571ed93470..73db051ca453 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 19fb282c7dda..a712433752ff 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 62b571bc6e13..635bee0a1a8d 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 bd1feda0a17a..ddd8fbbec7d4 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 d4788907a64b..20ca39aab308 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 ec028cad42e2..0fdb0950c414 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 13d81b1d1277..ffe05a3a6254 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 d651dc777065..fd4c848e7339 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 25a2b6e67d68..60d1d1694926 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 4b008c2296f7..a087de5450fc 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 629d74878d57..43313c54f5fc 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 244084361f7f..6125c876b30f 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 7714be1f2a1a..e4b0086a93c8 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 dc60a425f8fe..7b5d4a5eeb56 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 8b5b84086aee..dd26d67693e1 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 3041192cf73c..fbd739aca1cc 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 dfb0862786d9..c4816d6381ea 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 55a81a682d10..95292b367e1c 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 5d037c0c64ef..603b4e25dcee 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 30be88a3e96e..fe93d2e6b143 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 9c92ab557af5..2ca5eb80003e 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 eddb9615024b..ce284dc2b169 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 aeaf72c9d234..841c6c284f70 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 c32b7008427e..62597f5f37cd 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 f5546e7e1fe7..78e1967ee76d 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 97030c5ae850..9fbb2838cf9e 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 f541d84d620b..7c7e79648435 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 030c7110c078..40cb27922877 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 abe51a5382e9..0f416273d191 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 34b0665085dc..4f10266560ff 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 c86d33979006..8edd8fd5fcfb 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 000000000000..59c7612d1a73 --- /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 205bdb7dda9a..d09c480c6217 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 0ad79936ed81..333696823313 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 becb7eff5cea..9fbe52820bb2 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 e13854e69c65..6ac20763a800 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 369fd2e9799c..d155ee891444 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 e711fff8a558..705e2ddc6649 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 000000000000..7092f6ad2f77 --- /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 44abde6df6df..bf7339270359 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 37b24469630a..778d432018b4 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 000000000000..9c5461d1ee25 --- /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 4ca4c21d76fc..b2ecbb656caa 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 46c826761ee2..e3442a3e5cdc 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 6f9c830cf239..19eedccd7eb4 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 6f5a69fb721a..7f23f283f471 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 91e80a5c1228..825b9a9e9fbf 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 e14fa029501c..b791f1f76558 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 872e08e91bc5..796db40668d8 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 a28d034fe998..f71ec55dd16b 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 aa1ec22edf18..cbb57e90a95f 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 70abd00e6fdc..7cae275bb86b 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 462958c7a3ef..89377c61d467 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 c7bc61e14e71..56fac5c33010 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 a321737c7981..3b573e6daffc 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 ebe586dca242..732d7985b8f8 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 5e6fe98b4f4c..23f0ed8b23bc 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 092fb73c8e01..bb96a5092117 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 16a0b552048a..3383b69948a9 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 f2f2da4d0ac7..84a967436653 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 483a89925574..b913a67167b5 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 867e2338709b..20018e478e48 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 e6d94eb6adec..3ec458c5eabd 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 a57840447020..aadd4fb468c9 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 6227870a9fff..88a1de4cae98 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 434b4b963f3c..18d38557065c 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 2f37a9d0c921..5cbee72ffe22 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 e2cc6232a3b1..54573fc860a8 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 9bf234a671a1..f74c67a771e0 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 63cc98507da4..72834b42066a 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 a47d17b655cc..92a801826aef 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 107a53bd9311..786101ff4d2b 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 1f2400f1255d..388d37b79a67 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 000000000000..e9915ea17300 --- /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 000000000000..3c3153705068 --- /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 000000000000..f5968f544e8e --- /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 000000000000..b9e28346ac23 --- /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 000000000000..c04ad3f2af9c --- /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 957a204b76ba..2a4206b1f292 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 000000000000..0e8cdb17e327 --- /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 63f5172db4d3..18aec2fabfbd 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 7880478c3af6..ca93660d09ad 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