mirror of https://github.com/status-im/consul.git
Catalog + Namespace OSS changes. (#7219)
* Various Prepared Query + Namespace things * Last round of OSS changes for a namespaced catalog
This commit is contained in:
parent
20600403b2
commit
d0cd092e3b
|
@ -110,7 +110,6 @@ func (s *HTTPServer) ACLRulesTranslate(resp http.ResponseWriter, req *http.Reque
|
||||||
}
|
}
|
||||||
// Should this require lesser permissions? Really the only reason to require authorization at all is
|
// Should this require lesser permissions? Really the only reason to require authorization at all is
|
||||||
// to prevent external entities from DoS Consul with repeated rule translation requests
|
// to prevent external entities from DoS Consul with repeated rule translation requests
|
||||||
// TODO (namespaces) - pass through a real ent authz ctx
|
|
||||||
if rule != nil && rule.ACLRead(nil) != acl.Allow {
|
if rule != nil && rule.ACLRead(nil) != acl.Allow {
|
||||||
return nil, acl.ErrPermissionDenied
|
return nil, acl.ErrPermissionDenied
|
||||||
}
|
}
|
||||||
|
|
|
@ -1107,7 +1107,6 @@ func (s *HTTPServer) AgentNodeMaintenance(resp http.ResponseWriter, req *http.Re
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
// TODO (namespaces) - pass through a real ent authz ctx?
|
|
||||||
if rule != nil && rule.NodeWrite(s.agent.config.NodeName, nil) != acl.Allow {
|
if rule != nil && rule.NodeWrite(s.agent.config.NodeName, nil) != acl.Allow {
|
||||||
return nil, acl.ErrPermissionDenied
|
return nil, acl.ErrPermissionDenied
|
||||||
}
|
}
|
||||||
|
@ -1325,12 +1324,15 @@ func (s *HTTPServer) AgentConnectCALeafCert(resp http.ResponseWriter, req *http.
|
||||||
// not the ID of the service instance.
|
// not the ID of the service instance.
|
||||||
serviceName := strings.TrimPrefix(req.URL.Path, "/v1/agent/connect/ca/leaf/")
|
serviceName := strings.TrimPrefix(req.URL.Path, "/v1/agent/connect/ca/leaf/")
|
||||||
|
|
||||||
// TODO (namespaces) add namespacing to connect leaf cert generation request
|
|
||||||
args := cachetype.ConnectCALeafRequest{
|
args := cachetype.ConnectCALeafRequest{
|
||||||
Service: serviceName, // Need name not ID
|
Service: serviceName, // Need name not ID
|
||||||
}
|
}
|
||||||
var qOpts structs.QueryOptions
|
var qOpts structs.QueryOptions
|
||||||
|
|
||||||
|
if err := s.parseEntMetaNoWildcard(req, &args.EnterpriseMeta); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
// Store DC in the ConnectCALeafRequest but query opts separately
|
// Store DC in the ConnectCALeafRequest but query opts separately
|
||||||
if done := s.parse(resp, req, &args.Datacenter, &qOpts); done {
|
if done := s.parse(resp, req, &args.Datacenter, &qOpts); done {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
|
|
|
@ -226,7 +226,7 @@ func (s *HTTPServer) catalogServiceNodes(resp http.ResponseWriter, req *http.Req
|
||||||
|
|
||||||
// Set default DC
|
// Set default DC
|
||||||
args := structs.ServiceSpecificRequest{Connect: connect}
|
args := structs.ServiceSpecificRequest{Connect: connect}
|
||||||
if err := s.parseEntMeta(req, &args.EnterpriseMeta); err != nil {
|
if err := s.parseEntMetaNoWildcard(req, &args.EnterpriseMeta); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -487,9 +487,12 @@ func (s *ConnectCA) Sign(
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
var authzContext acl.AuthorizerContext
|
||||||
|
var entMeta structs.EnterpriseMeta
|
||||||
if isService {
|
if isService {
|
||||||
// TODO (namespaces) use actual ent authz context
|
entMeta.Merge(serviceID.GetEnterpriseMeta())
|
||||||
if rule != nil && rule.ServiceWrite(serviceID.Service, nil) != acl.Allow {
|
entMeta.FillAuthzContext(&authzContext)
|
||||||
|
if rule != nil && rule.ServiceWrite(serviceID.Service, &authzContext) != acl.Allow {
|
||||||
return acl.ErrPermissionDenied
|
return acl.ErrPermissionDenied
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -500,8 +503,8 @@ func (s *ConnectCA) Sign(
|
||||||
"we are %s", serviceID.Datacenter, s.srv.config.Datacenter)
|
"we are %s", serviceID.Datacenter, s.srv.config.Datacenter)
|
||||||
}
|
}
|
||||||
} else if isAgent {
|
} else if isAgent {
|
||||||
// TODO (namespaces) use actual ent authz context
|
structs.DefaultEnterpriseMeta().FillAuthzContext(&authzContext)
|
||||||
if rule != nil && rule.NodeWrite(agentID.Agent, nil) != acl.Allow {
|
if rule != nil && rule.NodeWrite(agentID.Agent, &authzContext) != acl.Allow {
|
||||||
return acl.ErrPermissionDenied
|
return acl.ErrPermissionDenied
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -588,10 +591,11 @@ func (s *ConnectCA) Sign(
|
||||||
|
|
||||||
// Set the response
|
// Set the response
|
||||||
*reply = structs.IssuedCert{
|
*reply = structs.IssuedCert{
|
||||||
SerialNumber: connect.EncodeSerialNumber(cert.SerialNumber),
|
SerialNumber: connect.EncodeSerialNumber(cert.SerialNumber),
|
||||||
CertPEM: pem,
|
CertPEM: pem,
|
||||||
ValidAfter: cert.NotBefore,
|
ValidAfter: cert.NotBefore,
|
||||||
ValidBefore: cert.NotAfter,
|
ValidBefore: cert.NotAfter,
|
||||||
|
EnterpriseMeta: entMeta,
|
||||||
RaftIndex: structs.RaftIndex{
|
RaftIndex: structs.RaftIndex{
|
||||||
ModifyIndex: modIdx,
|
ModifyIndex: modIdx,
|
||||||
CreateIndex: modIdx,
|
CreateIndex: modIdx,
|
||||||
|
|
|
@ -139,13 +139,14 @@ func (c *Coordinate) Update(args *structs.CoordinateUpdateRequest, reply *struct
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch the ACL token, if any, and enforce the node policy if enabled.
|
// Fetch the ACL token, if any, and enforce the node policy if enabled.
|
||||||
rule, err := c.srv.ResolveToken(args.Token)
|
authz, err := c.srv.ResolveToken(args.Token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if rule != nil && c.srv.config.ACLEnforceVersion8 {
|
if authz != nil && c.srv.config.ACLEnforceVersion8 {
|
||||||
// TODO (namespaces) use actual ent authz context
|
var authzContext acl.AuthorizerContext
|
||||||
if rule.NodeWrite(args.Node, nil) != acl.Allow {
|
structs.DefaultEnterpriseMeta().FillAuthzContext(&authzContext)
|
||||||
|
if authz.NodeWrite(args.Node, &authzContext) != acl.Allow {
|
||||||
return acl.ErrPermissionDenied
|
return acl.ErrPermissionDenied
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -211,13 +212,15 @@ func (c *Coordinate) Node(args *structs.NodeSpecificRequest, reply *structs.Inde
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch the ACL token, if any, and enforce the node policy if enabled.
|
// Fetch the ACL token, if any, and enforce the node policy if enabled.
|
||||||
rule, err := c.srv.ResolveToken(args.Token)
|
|
||||||
|
authz, err := c.srv.ResolveToken(args.Token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if rule != nil && c.srv.config.ACLEnforceVersion8 {
|
if authz != nil && c.srv.config.ACLEnforceVersion8 {
|
||||||
// TODO (namespaces) use actual ent authz context
|
var authzContext acl.AuthorizerContext
|
||||||
if rule.NodeRead(args.Node, nil) != acl.Allow {
|
structs.WildcardEnterpriseMeta().FillAuthzContext(&authzContext)
|
||||||
|
if authz.NodeRead(args.Node, &authzContext) != acl.Allow {
|
||||||
return acl.ErrPermissionDenied
|
return acl.ErrPermissionDenied
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,11 @@ func (m *Internal) NodeInfo(args *structs.NodeSpecificRequest,
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_, err := m.srv.ResolveTokenAndDefaultMeta(args.Token, &args.EnterpriseMeta, nil)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
return m.srv.blockingQuery(
|
return m.srv.blockingQuery(
|
||||||
&args.QueryOptions,
|
&args.QueryOptions,
|
||||||
&reply.QueryMeta,
|
&reply.QueryMeta,
|
||||||
|
@ -49,6 +54,11 @@ func (m *Internal) NodeDump(args *structs.DCSpecificRequest,
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_, err := m.srv.ResolveTokenAndDefaultMeta(args.Token, &args.EnterpriseMeta, nil)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
filter, err := bexpr.CreateFilter(args.Filter, nil, reply.Dump)
|
filter, err := bexpr.CreateFilter(args.Filter, nil, reply.Dump)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -83,6 +93,11 @@ func (m *Internal) ServiceDump(args *structs.ServiceDumpRequest, reply *structs.
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_, err := m.srv.ResolveTokenAndDefaultMeta(args.Token, &args.EnterpriseMeta, nil)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
filter, err := bexpr.CreateFilter(args.Filter, nil, reply.Nodes)
|
filter, err := bexpr.CreateFilter(args.Filter, nil, reply.Nodes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -548,6 +548,7 @@ func (p *PreparedQuery) execute(query *structs.PreparedQuery,
|
||||||
|
|
||||||
// Capture the nodes and pass the DNS information through to the reply.
|
// Capture the nodes and pass the DNS information through to the reply.
|
||||||
reply.Service = query.Service.Service
|
reply.Service = query.Service.Service
|
||||||
|
reply.EnterpriseMeta = query.Service.EnterpriseMeta
|
||||||
reply.Nodes = nodes
|
reply.Nodes = nodes
|
||||||
reply.DNS = query.DNS
|
reply.DNS = query.DNS
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,7 @@ func testServerACLConfig(cb func(*Config)) func(*Config) {
|
||||||
c.ACLsEnabled = true
|
c.ACLsEnabled = true
|
||||||
c.ACLMasterToken = TestDefaultMasterToken
|
c.ACLMasterToken = TestDefaultMasterToken
|
||||||
c.ACLDefaultPolicy = "deny"
|
c.ACLDefaultPolicy = "deny"
|
||||||
|
c.ACLEnforceVersion8 = true
|
||||||
|
|
||||||
if cb != nil {
|
if cb != nil {
|
||||||
cb(c)
|
cb(c)
|
||||||
|
|
|
@ -1206,7 +1206,7 @@ func (s *Store) getPolicyWithTxn(tx *memdb.Txn, ws memdb.WatchSet, value string,
|
||||||
}
|
}
|
||||||
ws.Add(watchCh)
|
ws.Add(watchCh)
|
||||||
|
|
||||||
if err != nil || policy == nil {
|
if policy == nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -528,7 +528,6 @@ func (s *Store) deleteNodeCASTxn(tx *memdb.Txn, idx, cidx uint64, nodeName strin
|
||||||
|
|
||||||
// deleteNodeTxn is the inner method used for removing a node from
|
// deleteNodeTxn is the inner method used for removing a node from
|
||||||
// the store within a given transaction.
|
// the store within a given transaction.
|
||||||
// TODO (namespaces) (catalog) access to catalog tables needs to become namespace aware for services/checks
|
|
||||||
func (s *Store) deleteNodeTxn(tx *memdb.Txn, idx uint64, nodeName string) error {
|
func (s *Store) deleteNodeTxn(tx *memdb.Txn, idx uint64, nodeName string) error {
|
||||||
// Look up the node.
|
// Look up the node.
|
||||||
node, err := tx.First("nodes", "id", nodeName)
|
node, err := tx.First("nodes", "id", nodeName)
|
||||||
|
|
|
@ -256,8 +256,6 @@ func TestDiscoveryChainRead(t *testing.T) {
|
||||||
})
|
})
|
||||||
}))
|
}))
|
||||||
|
|
||||||
// TODO(namespaces): add a test
|
|
||||||
|
|
||||||
expectTarget_DC2 := newTarget("web", "", "default", "dc2")
|
expectTarget_DC2 := newTarget("web", "", "default", "dc2")
|
||||||
expectTarget_DC2.MeshGateway = structs.MeshGatewayConfig{
|
expectTarget_DC2.MeshGateway = structs.MeshGatewayConfig{
|
||||||
Mode: structs.MeshGatewayModeLocal,
|
Mode: structs.MeshGatewayModeLocal,
|
||||||
|
|
|
@ -108,7 +108,7 @@ RETRY_ONCE:
|
||||||
func (s *HTTPServer) HealthServiceChecks(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
func (s *HTTPServer) HealthServiceChecks(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||||
// Set default DC
|
// Set default DC
|
||||||
args := structs.ServiceSpecificRequest{}
|
args := structs.ServiceSpecificRequest{}
|
||||||
if err := s.parseEntMeta(req, &args.EnterpriseMeta); err != nil {
|
if err := s.parseEntMetaNoWildcard(req, &args.EnterpriseMeta); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
s.parseSource(req, &args.Source)
|
s.parseSource(req, &args.Source)
|
||||||
|
@ -164,7 +164,7 @@ func (s *HTTPServer) HealthServiceNodes(resp http.ResponseWriter, req *http.Requ
|
||||||
func (s *HTTPServer) healthServiceNodes(resp http.ResponseWriter, req *http.Request, connect bool) (interface{}, error) {
|
func (s *HTTPServer) healthServiceNodes(resp http.ResponseWriter, req *http.Request, connect bool) (interface{}, error) {
|
||||||
// Set default DC
|
// Set default DC
|
||||||
args := structs.ServiceSpecificRequest{Connect: connect}
|
args := structs.ServiceSpecificRequest{Connect: connect}
|
||||||
if err := s.parseEntMeta(req, &args.EnterpriseMeta); err != nil {
|
if err := s.parseEntMetaNoWildcard(req, &args.EnterpriseMeta); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
s.parseSource(req, &args.Source)
|
s.parseSource(req, &args.Source)
|
||||||
|
|
|
@ -305,6 +305,9 @@ type PreparedQueryExecuteResponse struct {
|
||||||
// Service is the service that was queried.
|
// Service is the service that was queried.
|
||||||
Service string
|
Service string
|
||||||
|
|
||||||
|
// EnterpriseMeta of the service that was queried.
|
||||||
|
EnterpriseMeta
|
||||||
|
|
||||||
// Nodes has the nodes that were output by the query.
|
// Nodes has the nodes that were output by the query.
|
||||||
Nodes CheckServiceNodes
|
Nodes CheckServiceNodes
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,6 @@ func (d *DiscoveryChain) Get(name string, opts *DiscoveryChainOptions, q *QueryO
|
||||||
if opts.EvaluateInDatacenter != "" {
|
if opts.EvaluateInDatacenter != "" {
|
||||||
r.params.Set("compile-dc", opts.EvaluateInDatacenter)
|
r.params.Set("compile-dc", opts.EvaluateInDatacenter)
|
||||||
}
|
}
|
||||||
// TODO(namespaces): handle possible EvaluateInNamespace here
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if method == "POST" {
|
if method == "POST" {
|
||||||
|
|
|
@ -25,6 +25,9 @@ type ServiceQuery struct {
|
||||||
// Service is the service to query.
|
// Service is the service to query.
|
||||||
Service string
|
Service string
|
||||||
|
|
||||||
|
// Namespace of the service to query
|
||||||
|
Namespace string `json:",omitempty"`
|
||||||
|
|
||||||
// Near allows baking in the name of a node to automatically distance-
|
// Near allows baking in the name of a node to automatically distance-
|
||||||
// sort from. The magic "_agent" value is supported, which sorts near
|
// sort from. The magic "_agent" value is supported, which sorts near
|
||||||
// the agent which initiated the request by default.
|
// the agent which initiated the request by default.
|
||||||
|
@ -119,6 +122,9 @@ type PreparedQueryExecuteResponse struct {
|
||||||
// Service is the service that was queried.
|
// Service is the service that was queried.
|
||||||
Service string
|
Service string
|
||||||
|
|
||||||
|
// Namespace of the service that was queried
|
||||||
|
Namespace string `json:",omitempty"`
|
||||||
|
|
||||||
// Nodes has the nodes that were output by the query.
|
// Nodes has the nodes that were output by the query.
|
||||||
Nodes []ServiceEntry
|
Nodes []ServiceEntry
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue