Updates to the Txn API for namespaces (#7172)

* Updates to the Txn API for namespaces

* Update agent/consul/txn_endpoint.go

Co-Authored-By: R.B. Boyer <rb@hashicorp.com>

Co-authored-by: R.B. Boyer <public@richardboyer.net>
This commit is contained in:
Matt Keeler 2020-01-30 13:12:26 -05:00 committed by GitHub
parent 02c0403ff4
commit 26bb1584c1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 34 additions and 16 deletions

View File

@ -40,20 +40,24 @@ func (t *txnResultsFilter) Len() int {
}
func (t *txnResultsFilter) Filter(i int) bool {
// TODO (namespaces) use a real ent authz context for most of these checks
result := t.results[i]
var authzContext acl.AuthorizerContext
switch {
case result.KV != nil:
return t.authorizer.KeyRead(result.KV.Key, nil) != acl.Allow
result.KV.EnterpriseMeta.FillAuthzContext(&authzContext)
return t.authorizer.KeyRead(result.KV.Key, &authzContext) != acl.Allow
case result.Node != nil:
return t.authorizer.NodeRead(result.Node.Node, nil) != acl.Allow
structs.WildcardEnterpriseMeta().FillAuthzContext(&authzContext)
return t.authorizer.NodeRead(result.Node.Node, &authzContext) != acl.Allow
case result.Service != nil:
return t.authorizer.ServiceRead(result.Service.Service, nil) != acl.Allow
result.Service.EnterpriseMeta.FillAuthzContext(&authzContext)
return t.authorizer.ServiceRead(result.Service.Service, &authzContext) != acl.Allow
case result.Check != nil:
result.Check.EnterpriseMeta.FillAuthzContext(&authzContext)
if result.Check.ServiceName != "" {
return t.authorizer.ServiceRead(result.Check.ServiceName, nil) != acl.Allow
return t.authorizer.ServiceRead(result.Check.ServiceName, &authzContext) != acl.Allow
}
return t.authorizer.NodeRead(result.Check.Node, nil) != acl.Allow
return t.authorizer.NodeRead(result.Check.Node, &authzContext) != acl.Allow
}
return false
}

View File

@ -68,6 +68,8 @@ func (t *Txn) preCheck(authorizer acl.Authorizer, ops structs.TxnOps) structs.Tx
}
service := &op.Service.Service
// This is intentionally nil as we will authorize the request
// using vetServiceTxnOp next instead of doing it in servicePreApply
if err := servicePreApply(service, nil); err != nil {
errors = append(errors, &structs.TxnError{
OpIndex: i,

View File

@ -46,6 +46,10 @@ func (m *EnterpriseMeta) NamespaceOrDefault() string {
return "default"
}
func EnterpriseMetaInitializer(_ string) EnterpriseMeta {
return emptyEnterpriseMeta
}
// ReplicationEnterpriseMeta stub
func ReplicationEnterpriseMeta() *EnterpriseMeta {
return &emptyEnterpriseMeta

View File

@ -125,10 +125,11 @@ func (s *HTTPServer) convertOps(resp http.ResponseWriter, req *http.Request) (st
KV: &structs.TxnKVOp{
Verb: verb,
DirEnt: structs.DirEntry{
Key: in.KV.Key,
Value: in.KV.Value,
Flags: in.KV.Flags,
Session: in.KV.Session,
Key: in.KV.Key,
Value: in.KV.Value,
Flags: in.KV.Flags,
Session: in.KV.Session,
EnterpriseMeta: structs.EnterpriseMetaInitializer(in.KV.Namespace),
RaftIndex: structs.RaftIndex{
ModifyIndex: in.KV.Index,
},
@ -188,6 +189,7 @@ func (s *HTTPServer) convertOps(resp http.ResponseWriter, req *http.Request) (st
Warning: svc.Weights.Warning,
},
EnableTagOverride: svc.EnableTagOverride,
EnterpriseMeta: structs.EnterpriseMetaInitializer(svc.Namespace),
RaftIndex: structs.RaftIndex{
ModifyIndex: svc.ModifyIndex,
},
@ -243,6 +245,7 @@ func (s *HTTPServer) convertOps(resp http.ResponseWriter, req *http.Request) (st
Timeout: timeout,
DeregisterCriticalServiceAfter: deregisterCriticalServiceAfter,
},
EnterpriseMeta: structs.EnterpriseMetaInitializer(check.Namespace),
RaftIndex: structs.RaftIndex{
ModifyIndex: check.ModifyIndex,
},

View File

@ -75,12 +75,13 @@ const (
// KVTxnOp defines a single operation inside a transaction.
type KVTxnOp struct {
Verb KVOp
Key string
Value []byte
Flags uint64
Index uint64
Session string
Verb KVOp
Key string
Value []byte
Flags uint64
Index uint64
Session string
Namespace string `json:",omitempty"`
}
// KVTxnOps defines a set of operations to be performed inside a single

View File

@ -74,6 +74,10 @@ The table below shows this endpoint's support for
- `Session` `(string: "")` - Specifies a session. See the table below for more
information.
- `Namespace` `(string: "")` - **(Enterprise Only)** Specifies the namespace to
create the KV data If not provided, the namespace will be inherited from the
request's ACL token or will default to the `default` namespace. Added in Consul 1.7.0.
- `Node` operations have the following fields:
- `Verb` `(string: <required>)` - Specifies the type of operation to perform.