mirror of https://github.com/hashicorp/consul
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
185 lines
5.8 KiB
185 lines
5.8 KiB
// Copyright (c) HashiCorp, Inc. |
|
// SPDX-License-Identifier: BUSL-1.1 |
|
|
|
//go:build !consulent |
|
|
|
package agent |
|
|
|
import ( |
|
"context" |
|
"testing" |
|
|
|
"github.com/miekg/dns" |
|
"github.com/stretchr/testify/require" |
|
|
|
"github.com/hashicorp/consul/acl" |
|
"github.com/hashicorp/consul/agent/structs" |
|
"github.com/hashicorp/consul/testrpc" |
|
) |
|
|
|
func TestDNS_CE_PeeredServices(t *testing.T) { |
|
if testing.Short() { |
|
t.Skip("too slow for testing.Short") |
|
} |
|
|
|
for name, experimentsHCL := range getVersionHCL(true) { |
|
t.Run(name, func(t *testing.T) { |
|
a := StartTestAgent(t, TestAgent{HCL: ``, Overrides: `peering = { test_allow_peer_registrations = true } ` + experimentsHCL}) |
|
defer a.Shutdown() |
|
testrpc.WaitForTestAgent(t, a.RPC, "dc1") |
|
|
|
makeReq := func() *structs.RegisterRequest { |
|
return &structs.RegisterRequest{ |
|
PeerName: "peer1", |
|
Datacenter: "dc1", |
|
Node: "peernode1", |
|
Address: "198.18.1.1", |
|
Service: &structs.NodeService{ |
|
PeerName: "peer1", |
|
Kind: structs.ServiceKindConnectProxy, |
|
Service: "web-proxy", |
|
Address: "199.0.0.1", |
|
Port: 12345, |
|
Proxy: structs.ConnectProxyConfig{ |
|
DestinationServiceName: "peer-web", |
|
}, |
|
EnterpriseMeta: *acl.DefaultEnterpriseMeta(), |
|
}, |
|
EnterpriseMeta: *acl.DefaultEnterpriseMeta(), |
|
} |
|
} |
|
|
|
dnsQuery := func(t *testing.T, question string, typ uint16) *dns.Msg { |
|
m := new(dns.Msg) |
|
m.SetQuestion(question, typ) |
|
|
|
c := new(dns.Client) |
|
reply, _, err := c.Exchange(m, a.DNSAddr()) |
|
require.NoError(t, err) |
|
require.Len(t, reply.Answer, 1, "zero valid records found for %q", question) |
|
return reply |
|
} |
|
|
|
assertARec := func(t *testing.T, rec dns.RR, expectName, expectIP string) { |
|
aRec, ok := rec.(*dns.A) |
|
require.True(t, ok, "Extra is not an A record: %T", rec) |
|
require.Equal(t, expectName, aRec.Hdr.Name) |
|
require.Equal(t, expectIP, aRec.A.String()) |
|
} |
|
|
|
assertSRVRec := func(t *testing.T, rec dns.RR, expectName string, expectPort uint16) { |
|
srvRec, ok := rec.(*dns.SRV) |
|
require.True(t, ok, "Answer is not a SRV record: %T", rec) |
|
require.Equal(t, expectName, srvRec.Target) |
|
require.Equal(t, expectPort, srvRec.Port) |
|
} |
|
|
|
t.Run("srv-with-addr-reply", func(t *testing.T) { |
|
require.NoError(t, a.RPC(context.Background(), "Catalog.Register", makeReq(), &struct{}{})) |
|
q := dnsQuery(t, "web-proxy.service.peer1.peer.consul.", dns.TypeSRV) |
|
require.Len(t, q.Answer, 1) |
|
require.Len(t, q.Extra, 1) |
|
|
|
addr := "c7000001.addr.consul." |
|
assertSRVRec(t, q.Answer[0], addr, 12345) |
|
assertARec(t, q.Extra[0], addr, "199.0.0.1") |
|
|
|
// Query the addr to make sure it's also valid. |
|
q = dnsQuery(t, addr, dns.TypeA) |
|
require.Len(t, q.Answer, 1) |
|
require.Len(t, q.Extra, 0) |
|
assertARec(t, q.Answer[0], addr, "199.0.0.1") |
|
}) |
|
|
|
t.Run("srv-with-node-reply", func(t *testing.T) { |
|
req := makeReq() |
|
// Clear service address to trigger node response |
|
req.Service.Address = "" |
|
require.NoError(t, a.RPC(context.Background(), "Catalog.Register", req, &struct{}{})) |
|
q := dnsQuery(t, "web-proxy.service.peer1.peer.consul.", dns.TypeSRV) |
|
require.Len(t, q.Answer, 1) |
|
require.Len(t, q.Extra, 1) |
|
|
|
nodeName := "peernode1.node.peer1.peer.consul." |
|
assertSRVRec(t, q.Answer[0], nodeName, 12345) |
|
assertARec(t, q.Extra[0], nodeName, "198.18.1.1") |
|
|
|
// Query the node to make sure it's also valid. |
|
q = dnsQuery(t, nodeName, dns.TypeA) |
|
require.Len(t, q.Answer, 1) |
|
require.Len(t, q.Extra, 0) |
|
assertARec(t, q.Answer[0], nodeName, "198.18.1.1") |
|
}) |
|
|
|
t.Run("srv-with-fqdn-reply", func(t *testing.T) { |
|
req := makeReq() |
|
// Set non-ip address to trigger external response |
|
req.Address = "localhost" |
|
req.Service.Address = "" |
|
require.NoError(t, a.RPC(context.Background(), "Catalog.Register", req, &struct{}{})) |
|
q := dnsQuery(t, "web-proxy.service.peer1.peer.consul.", dns.TypeSRV) |
|
require.Len(t, q.Answer, 1) |
|
require.Len(t, q.Extra, 0) |
|
assertSRVRec(t, q.Answer[0], "localhost.", 12345) |
|
}) |
|
|
|
t.Run("a-reply", func(t *testing.T) { |
|
require.NoError(t, a.RPC(context.Background(), "Catalog.Register", makeReq(), &struct{}{})) |
|
q := dnsQuery(t, "web-proxy.service.peer1.peer.consul.", dns.TypeA) |
|
require.Len(t, q.Answer, 1) |
|
require.Len(t, q.Extra, 0) |
|
assertARec(t, q.Answer[0], "web-proxy.service.peer1.peer.consul.", "199.0.0.1") |
|
}) |
|
}) |
|
} |
|
} |
|
|
|
func getTestCasesParseLocality() []testCaseParseLocality { |
|
testCases := []testCaseParseLocality{ |
|
{ |
|
name: "test [.<datacenter>.dc]", |
|
labels: []string{"test-dc", "dc"}, |
|
enterpriseDNSConfig: enterpriseDNSConfig{}, |
|
expectedResult: queryLocality{ |
|
EnterpriseMeta: acl.EnterpriseMeta{}, |
|
datacenter: "test-dc", |
|
}, |
|
expectedOK: true, |
|
}, |
|
{ |
|
name: "test [.<peer>.peer]", |
|
labels: []string{"test-peer", "peer"}, |
|
enterpriseDNSConfig: enterpriseDNSConfig{}, |
|
expectedResult: queryLocality{ |
|
EnterpriseMeta: acl.EnterpriseMeta{}, |
|
peer: "test-peer", |
|
}, |
|
expectedOK: true, |
|
}, |
|
{ |
|
name: "test 1 label", |
|
labels: []string{"test-peer"}, |
|
enterpriseDNSConfig: enterpriseDNSConfig{}, |
|
expectedResult: queryLocality{ |
|
EnterpriseMeta: acl.EnterpriseMeta{}, |
|
peerOrDatacenter: "test-peer", |
|
}, |
|
expectedOK: true, |
|
}, |
|
{ |
|
name: "test 0 labels", |
|
labels: []string{}, |
|
enterpriseDNSConfig: enterpriseDNSConfig{}, |
|
expectedResult: queryLocality{}, |
|
expectedOK: true, |
|
}, |
|
{ |
|
name: "test 3 labels returns not found", |
|
labels: []string{"test-dc", "dc", "test-blah"}, |
|
enterpriseDNSConfig: enterpriseDNSConfig{}, |
|
expectedResult: queryLocality{}, |
|
expectedOK: false, |
|
}, |
|
} |
|
return testCases |
|
}
|
|
|