From 7f62571419d6288d14aee238647708d838242fbb Mon Sep 17 00:00:00 2001 From: Kyle Havlovitz Date: Fri, 10 Jun 2022 11:23:51 -0700 Subject: [PATCH] Add dns node lookup support in partitions --- agent/dns.go | 35 +++++++++++++++++++++----- website/content/docs/discovery/dns.mdx | 17 +++++++++---- 2 files changed, 41 insertions(+), 11 deletions(-) diff --git a/agent/dns.go b/agent/dns.go index a973056a1a..9d0d3b9a5b 100644 --- a/agent/dns.go +++ b/agent/dns.go @@ -107,6 +107,14 @@ type serviceLookup struct { acl.EnterpriseMeta } +type nodeLookup struct { + Datacenter string + Node string + Tag string + MaxRecursionLevel int + acl.EnterpriseMeta +} + // DNSServer is used to wrap an Agent and expose various // service discovery endpoints using a DNS interface. type DNSServer struct { @@ -846,13 +854,27 @@ func (d *DNSServer) dispatch(remoteAddr net.Addr, req, resp *dns.Msg, maxRecursi return invalid() } - if !d.parseDatacenter(querySuffixes, &datacenter) { + if !d.parseDatacenterAndEnterpriseMeta(querySuffixes, cfg, &datacenter, &entMeta) { + return invalid() + } + + // Namespace should not be set for node queries + ns := entMeta.NamespaceOrEmpty() + if ns != "" && ns != acl.DefaultNamespaceName { return invalid() } // Allow a "." in the node name, just join all the parts node := strings.Join(queryParts, ".") - return d.nodeLookup(cfg, datacenter, node, req, resp, maxRecursionLevel) + + lookup := nodeLookup{ + Datacenter: datacenter, + Node: node, + MaxRecursionLevel: maxRecursionLevel, + EnterpriseMeta: entMeta, + } + + return d.nodeLookup(cfg, lookup, req, resp) case "query": // ensure we have a query name @@ -959,7 +981,7 @@ func rCodeFromError(err error) int { } // nodeLookup is used to handle a node query -func (d *DNSServer) nodeLookup(cfg *dnsConfig, datacenter, node string, req, resp *dns.Msg, maxRecursionLevel int) error { +func (d *DNSServer) nodeLookup(cfg *dnsConfig, lookup nodeLookup, req, resp *dns.Msg) error { // Only handle ANY, A, AAAA, and TXT type requests qType := req.Question[0].Qtype if qType != dns.TypeANY && qType != dns.TypeA && qType != dns.TypeAAAA && qType != dns.TypeTXT { @@ -968,12 +990,13 @@ func (d *DNSServer) nodeLookup(cfg *dnsConfig, datacenter, node string, req, res // Make an RPC request args := &structs.NodeSpecificRequest{ - Datacenter: datacenter, - Node: node, + Datacenter: lookup.Datacenter, + Node: lookup.Node, QueryOptions: structs.QueryOptions{ Token: d.agent.tokens.UserToken(), AllowStale: cfg.AllowStale, }, + EnterpriseMeta: lookup.EnterpriseMeta, } out, err := d.lookupNode(cfg, args) if err != nil { @@ -996,7 +1019,7 @@ func (d *DNSServer) nodeLookup(cfg *dnsConfig, datacenter, node string, req, res q := req.Question[0] // Only compute A and CNAME record if query is not TXT type if qType != dns.TypeTXT { - records := d.makeRecordFromNode(n, q.Qtype, q.Name, cfg.NodeTTL, maxRecursionLevel) + records := d.makeRecordFromNode(n, q.Qtype, q.Name, cfg.NodeTTL, lookup.MaxRecursionLevel) resp.Answer = append(resp.Answer, records...) } diff --git a/website/content/docs/discovery/dns.mdx b/website/content/docs/discovery/dns.mdx index 3b11a8df12..8a542b4ef2 100644 --- a/website/content/docs/discovery/dns.mdx +++ b/website/content/docs/discovery/dns.mdx @@ -467,9 +467,9 @@ using the [`advertise-wan`](/docs/agent/config/cli-flags#_advertise-wan) and [`translate_wan_addrs`](/docs/agent/config/config-files#translate_wan_addrs) configuration options. -## Namespaced/Partitioned Services +## Namespaced/Partitioned Services and Nodes -Consul Enterprise supports resolving namespaced and partitioned services via DNS. +Consul Enterprise supports resolving namespaced and partitioned services and nodes via DNS. To maintain backwards compatibility existing queries can be used and these will resolve services within the `default` namespace and partition. However, for resolving services from other namespaces or partitions the following form can be used: @@ -478,13 +478,20 @@ services from other namespaces or partitions the following form can be used: [tag.].service..ns..ap..dc. ``` -This is the canonical name of a Consul Enterprise service. Currently all parts must be -present - in a future version (once the +This is the canonical name of a Consul Enterprise service. Currently at least 2 of +`[namespace, partition, datacenter]` must be present - in a future version (once the [`prefer_namespace` configuration](/docs/agent/config/config-files#dns_prefer_namespace) has been -deprecated), the namespace, partition and datacenter components will become optional +deprecated), the namespace, partition and datacenter components will all become optional and may be individually omitted to default to the `default` namespace, local partition or local datacenter respectively. +For node lookups, only the partition and datacenter need to be specified (nodes cannot be +namespaced): + +```text +[tag.].service..ap..dc. +``` + ## DNS with ACLs In order to use the DNS interface when