diff --git a/app/mock_reporter_test.go b/app/mock_reporter_test.go index ad7463677..c097b74f6 100644 --- a/app/mock_reporter_test.go +++ b/app/mock_reporter_test.go @@ -18,10 +18,10 @@ func (s StaticReport) Report() report.Report { var testReport = report.Report{ Endpoint: report.Topology{ Adjacency: report.Adjacency{ - report.MakeAdjacencyID("hostA", report.MakeEndpointNodeID("hostA", "192.168.1.1", "12345")): report.MakeIDList(report.MakeEndpointNodeID("hostB", "192.168.1.2", "80")), - report.MakeAdjacencyID("hostA", report.MakeEndpointNodeID("hostA", "192.168.1.1", "12346")): report.MakeIDList(report.MakeEndpointNodeID("hostB", "192.168.1.2", "80")), - report.MakeAdjacencyID("hostA", report.MakeEndpointNodeID("hostA", "192.168.1.1", "8888")): report.MakeIDList(report.MakeEndpointNodeID("", "1.2.3.4", "22")), - report.MakeAdjacencyID("hostB", report.MakeEndpointNodeID("hostB", "192.168.1.2", "80")): report.MakeIDList(report.MakeEndpointNodeID("hostA", "192.168.1.1", "12345")), + report.MakeAdjacencyID(report.MakeEndpointNodeID("hostA", "192.168.1.1", "12345")): report.MakeIDList(report.MakeEndpointNodeID("hostB", "192.168.1.2", "80")), + report.MakeAdjacencyID(report.MakeEndpointNodeID("hostA", "192.168.1.1", "12346")): report.MakeIDList(report.MakeEndpointNodeID("hostB", "192.168.1.2", "80")), + report.MakeAdjacencyID(report.MakeEndpointNodeID("hostA", "192.168.1.1", "8888")): report.MakeIDList(report.MakeEndpointNodeID("", "1.2.3.4", "22")), + report.MakeAdjacencyID(report.MakeEndpointNodeID("hostB", "192.168.1.2", "80")): report.MakeIDList(report.MakeEndpointNodeID("hostA", "192.168.1.1", "12345")), }, EdgeMetadatas: report.EdgeMetadatas{ report.MakeEdgeID(report.MakeEndpointNodeID("hostA", "192.168.1.1", "12345"), report.MakeEndpointNodeID("hostB", "192.168.1.2", "80")): report.EdgeMetadata{ @@ -79,8 +79,8 @@ func (s StaticReport) Report() report.Report { Address: report.Topology{ Adjacency: report.Adjacency{ - report.MakeAdjacencyID("hostA", report.MakeAddressNodeID("hostA", "192.168.1.1")): report.MakeIDList(report.MakeAddressNodeID("hostB", "192.168.1.2"), report.MakeAddressNodeID("", "1.2.3.4")), - report.MakeAdjacencyID("hostB", report.MakeAddressNodeID("hostB", "192.168.1.2")): report.MakeIDList(report.MakeAddressNodeID("hostA", "192.168.1.1")), + report.MakeAdjacencyID(report.MakeAddressNodeID("hostA", "192.168.1.1")): report.MakeIDList(report.MakeAddressNodeID("hostB", "192.168.1.2"), report.MakeAddressNodeID("", "1.2.3.4")), + report.MakeAdjacencyID(report.MakeAddressNodeID("hostB", "192.168.1.2")): report.MakeIDList(report.MakeAddressNodeID("hostA", "192.168.1.1")), }, EdgeMetadatas: report.EdgeMetadatas{ report.MakeEdgeID(report.MakeAddressNodeID("hostA", "192.168.1.1"), report.MakeAddressNodeID("hostB", "192.168.1.2")): report.EdgeMetadata{ diff --git a/experimental/demoprobe/generate.go b/experimental/demoprobe/generate.go index 90fae1ad1..83577aab7 100644 --- a/experimental/demoprobe/generate.go +++ b/experimental/demoprobe/generate.go @@ -59,12 +59,12 @@ func DemoReport(nodeCount int) report.Report { srcPort = rand.Intn(50000) + 10000 srcPortID = report.MakeEndpointNodeID("", src, strconv.Itoa(srcPort)) dstPortID = report.MakeEndpointNodeID("", dst, strconv.Itoa(c.dstPort)) - srcID = report.MakeAdjacencyID("hostX", srcPortID) - dstID = report.MakeAdjacencyID("hostX", dstPortID) + srcID = report.MakeAdjacencyID(srcPortID) + dstID = report.MakeAdjacencyID(dstPortID) srcAddressID = report.MakeAddressNodeID("", src) dstAddressID = report.MakeAddressNodeID("", dst) - nodeSrcAddressID = report.MakeAdjacencyID("hostX", srcAddressID) - nodeDstAddressID = report.MakeAdjacencyID("hostX", dstAddressID) + nodeSrcAddressID = report.MakeAdjacencyID(srcAddressID) + nodeDstAddressID = report.MakeAdjacencyID(dstAddressID) ) // Endpoint topology diff --git a/experimental/genreport/generate.go b/experimental/genreport/generate.go index 1aafe1ee9..ecbeef789 100644 --- a/experimental/genreport/generate.go +++ b/experimental/genreport/generate.go @@ -59,12 +59,12 @@ func DemoReport(nodeCount int) report.Report { srcPort = rand.Intn(50000) + 10000 srcPortID = report.MakeEndpointNodeID("", src, strconv.Itoa(srcPort)) dstPortID = report.MakeEndpointNodeID("", dst, strconv.Itoa(c.dstPort)) - srcID = report.MakeAdjacencyID("hostX", srcPortID) - dstID = report.MakeAdjacencyID("hostX", dstPortID) + srcID = report.MakeAdjacencyID(srcPortID) + dstID = report.MakeAdjacencyID(dstPortID) srcAddressID = report.MakeAddressNodeID("", src) dstAddressID = report.MakeAddressNodeID("", dst) - nodeSrcAddressID = report.MakeAdjacencyID("hostX", srcAddressID) - nodeDstAddressID = report.MakeAdjacencyID("hostX", dstAddressID) + nodeSrcAddressID = report.MakeAdjacencyID(srcAddressID) + nodeDstAddressID = report.MakeAdjacencyID(dstAddressID) ) // Endpoint topology diff --git a/probe/spy.go b/probe/spy.go index e6e98af45..aa7b03ef4 100644 --- a/probe/spy.go +++ b/probe/spy.go @@ -45,7 +45,7 @@ func addConnection( var ( scopedLocal = report.MakeAddressNodeID(hostID, c.LocalAddress.String()) scopedRemote = report.MakeAddressNodeID(hostID, c.RemoteAddress.String()) - key = report.MakeAdjacencyID(hostID, scopedLocal) + key = report.MakeAdjacencyID(scopedLocal) edgeKey = report.MakeEdgeID(scopedLocal, scopedRemote) ) @@ -67,7 +67,7 @@ func addConnection( var ( scopedLocal = report.MakeEndpointNodeID(hostID, c.LocalAddress.String(), strconv.Itoa(int(c.LocalPort))) scopedRemote = report.MakeEndpointNodeID(hostID, c.RemoteAddress.String(), strconv.Itoa(int(c.RemotePort))) - key = report.MakeAdjacencyID(hostID, scopedLocal) + key = report.MakeAdjacencyID(scopedLocal) edgeKey = report.MakeEdgeID(scopedLocal, scopedRemote) ) diff --git a/probe/spy_test.go b/probe/spy_test.go index 09b193d34..c2574c7d4 100644 --- a/probe/spy_test.go +++ b/probe/spy_test.go @@ -82,7 +82,7 @@ func TestSpyNoProcesses(t *testing.T) { var ( scopedLocal = report.MakeAddressNodeID(nodeID, fixLocalAddress.String()) scopedRemote = report.MakeAddressNodeID(nodeID, fixRemoteAddress.String()) - localKey = report.MakeAdjacencyID(nodeID, scopedLocal) + localKey = report.MakeAdjacencyID(scopedLocal) ) if want, have := 1, len(r.Address.Adjacency[localKey]); want != have { @@ -112,7 +112,7 @@ func TestSpyWithProcesses(t *testing.T) { var ( scopedLocal = report.MakeEndpointNodeID(nodeID, fixLocalAddress.String(), strconv.Itoa(int(fixLocalPort))) scopedRemote = report.MakeEndpointNodeID(nodeID, fixRemoteAddress.String(), strconv.Itoa(int(fixRemotePort))) - localKey = report.MakeAdjacencyID(nodeID, scopedLocal) + localKey = report.MakeAdjacencyID(scopedLocal) ) if want, have := 1, len(r.Endpoint.Adjacency[localKey]); want != have { diff --git a/report/id.go b/report/id.go index f53644e6e..f94cc5a46 100644 --- a/report/id.go +++ b/report/id.go @@ -22,26 +22,17 @@ const ( EdgeDelim = "|" ) -// MakeAdjacencyID produces an adjacency ID from composite parts. -func MakeAdjacencyID(hostID, srcNodeID string) string { - // Here we rely on the fact that every possible source node ID has the - // host ID as the first scope-delimited field, and therefore don't - // duplicate that information. +// MakeAdjacencyID produces an adjacency ID from a node id. +func MakeAdjacencyID(srcNodeID string) string { return ">" + srcNodeID } -// ParseAdjacencyID splits an adjacency ID to its composite parts. -func ParseAdjacencyID(adjacencyID string) (hostID, srcNodeID string, ok bool) { +// ParseAdjacencyID produces a node id from an adjancency id +func ParseAdjacencyID(adjacencyID string) (string, bool) { if !strings.HasPrefix(adjacencyID, ">") { - return "", "", false + return "", false } - // This relies on every node ID having hostID as its first scoped field. - adjacencyID = adjacencyID[1:] - fields := strings.SplitN(adjacencyID, ScopeDelim, 2) - if len(fields) != 2 { - return "", "", false - } - return fields[0], adjacencyID, true + return adjacencyID[1:], true } // MakeEdgeID produces an edge ID from composite parts. @@ -81,6 +72,15 @@ func MakeHostNodeID(hostID string) string { return hostID + ScopeDelim + "" } +// ParseNodeID produces the scope and remainder from a node ID +func ParseNodeID(nodeID string) (string, string, bool) { + fields := strings.SplitN(nodeID, ScopeDelim, 2) + if len(fields) != 2 { + return "", "", false + } + return fields[0], fields[1], true +} + // MakePseudoNodeID produces a pseudo node ID from its composite parts. func MakePseudoNodeID(parts ...string) string { return strings.Join(append([]string{"pseudo"}, parts...), ScopeDelim) diff --git a/report/id_test.go b/report/id_test.go index ab8a10e14..23c7d65e3 100644 --- a/report/id_test.go +++ b/report/id_test.go @@ -20,36 +20,31 @@ func TestAdjacencyID(t *testing.T) { unknownAddressNodeID, clientHostNodeID, serverHostNodeID, - ">1.2.3.4", - ">", ";", "", } { - if hostID, srcNodeID, ok := report.ParseAdjacencyID(bad); ok { - t.Errorf("%q: expected failure, but got (%q, %q)", bad, hostID, srcNodeID) + if srcNodeID, ok := report.ParseAdjacencyID(bad); ok { + t.Errorf("%q: expected failure, but got (%q)", bad, srcNodeID) } } - for input, want := range map[string]struct{ hostID, srcNodeID string }{ - report.MakeAdjacencyID("a", report.MakeEndpointNodeID("a", "b", "c")): {"a", report.MakeEndpointNodeID("a", "b", "c")}, - report.MakeAdjacencyID("a", report.MakeAddressNodeID("a", "b")): {"a", report.MakeAddressNodeID("a", "b")}, - report.MakeAdjacencyID("a", report.MakeProcessNodeID("a", "b")): {"a", report.MakeProcessNodeID("a", "b")}, - report.MakeAdjacencyID("a", report.MakeHostNodeID("a")): {"a", report.MakeHostNodeID("a")}, - ">host.com;1.2.3.4": {"host.com", "host.com;1.2.3.4"}, - ">a;b;c": {"a", "a;b;c"}, - ">a;b": {"a", "a;b"}, - ">a;": {"a", "a;"}, - ">;b": {"", ";b"}, - ">;": {"", ";"}, + for input, want := range map[string]struct{ srcNodeID string }{ + report.MakeAdjacencyID(report.MakeEndpointNodeID("a", "b", "c")): {report.MakeEndpointNodeID("a", "b", "c")}, + report.MakeAdjacencyID(report.MakeAddressNodeID("a", "b")): {report.MakeAddressNodeID("a", "b")}, + report.MakeAdjacencyID(report.MakeProcessNodeID("a", "b")): {report.MakeProcessNodeID("a", "b")}, + report.MakeAdjacencyID(report.MakeHostNodeID("a")): {report.MakeHostNodeID("a")}, + ">host.com;1.2.3.4": {"host.com;1.2.3.4"}, + ">a;b;c": {"a;b;c"}, + ">a;b": {"a;b"}, + ">a;": {"a;"}, + ">;b": {";b"}, + ">;": {";"}, } { - hostID, srcNodeID, ok := report.ParseAdjacencyID(input) + srcNodeID, ok := report.ParseAdjacencyID(input) if !ok { t.Errorf("%q: not OK", input) continue } - if want, have := want.hostID, hostID; want != have { - t.Errorf("%q: want %q, have %q", input, want, have) - } if want, have := want.srcNodeID, srcNodeID; want != have { t.Errorf("%q: want %q, have %q", input, want, have) } diff --git a/report/mapping.go b/report/mapping.go index 215bb6cfa..221bc122d 100644 --- a/report/mapping.go +++ b/report/mapping.go @@ -205,5 +205,8 @@ func trySplitAddr(addr string) (string, string) { if len(fields) == 3 { return fields[1], fields[2] } - return fields[1], "" + if len(fields) == 2 { + return fields[1], "" + } + panic(addr) } diff --git a/report/report_fixture_test.go b/report/report_fixture_test.go index 010f3651b..0534047ed 100644 --- a/report/report_fixture_test.go +++ b/report/report_fixture_test.go @@ -7,9 +7,9 @@ import ( var reportFixture = report.Report{ Endpoint: report.Topology{ Adjacency: report.Adjacency{ - report.MakeAdjacencyID(clientHostID, client54001EndpointNodeID): report.MakeIDList(server80EndpointNodeID), - report.MakeAdjacencyID(clientHostID, client54002EndpointNodeID): report.MakeIDList(server80EndpointNodeID), - report.MakeAdjacencyID(serverHostID, server80EndpointNodeID): report.MakeIDList(client54001EndpointNodeID, client54002EndpointNodeID, unknown1EndpointNodeID, unknown2EndpointNodeID, unknown3EndpointNodeID), + report.MakeAdjacencyID(client54001EndpointNodeID): report.MakeIDList(server80EndpointNodeID), + report.MakeAdjacencyID(client54002EndpointNodeID): report.MakeIDList(server80EndpointNodeID), + report.MakeAdjacencyID(server80EndpointNodeID): report.MakeIDList(client54001EndpointNodeID, client54002EndpointNodeID, unknown1EndpointNodeID, unknown2EndpointNodeID, unknown3EndpointNodeID), }, NodeMetadatas: report.NodeMetadatas{ client54001EndpointNodeID: report.NodeMetadata{ @@ -71,8 +71,8 @@ var reportFixture = report.Report{ }, Address: report.Topology{ Adjacency: report.Adjacency{ - report.MakeAdjacencyID(clientHostID, clientAddressNodeID): report.MakeIDList(serverAddressNodeID), - report.MakeAdjacencyID(serverHostID, serverAddressNodeID): report.MakeIDList(clientAddressNodeID, unknownAddressNodeID), + report.MakeAdjacencyID(clientAddressNodeID): report.MakeIDList(serverAddressNodeID), + report.MakeAdjacencyID(serverAddressNodeID): report.MakeIDList(clientAddressNodeID, unknownAddressNodeID), }, NodeMetadatas: report.NodeMetadatas{ clientAddressNodeID: report.NodeMetadata{ diff --git a/report/report_test.go b/report/report_test.go index a2b5ce4be..8f8ef9f1e 100644 --- a/report/report_test.go +++ b/report/report_test.go @@ -25,9 +25,9 @@ func TestReportLocalNetworks(t *testing.T) { func TestReportSquash(t *testing.T) { { want := report.Adjacency{ - report.MakeAdjacencyID(clientHostID, client54001EndpointNodeID): report.MakeIDList(server80EndpointNodeID), - report.MakeAdjacencyID(clientHostID, client54002EndpointNodeID): report.MakeIDList(server80EndpointNodeID), - report.MakeAdjacencyID(serverHostID, server80EndpointNodeID): report.MakeIDList(client54001EndpointNodeID, client54002EndpointNodeID, report.TheInternet), + report.MakeAdjacencyID(client54001EndpointNodeID): report.MakeIDList(server80EndpointNodeID), + report.MakeAdjacencyID(client54002EndpointNodeID): report.MakeIDList(server80EndpointNodeID), + report.MakeAdjacencyID(server80EndpointNodeID): report.MakeIDList(client54001EndpointNodeID, client54002EndpointNodeID, report.TheInternet), } have := reportFixture.Squash().Endpoint.Adjacency if !reflect.DeepEqual(want, have) { @@ -36,8 +36,8 @@ func TestReportSquash(t *testing.T) { } { want := report.Adjacency{ - report.MakeAdjacencyID(clientHostID, clientAddressNodeID): report.MakeIDList(serverAddressNodeID), - report.MakeAdjacencyID(serverHostID, serverAddressNodeID): report.MakeIDList(clientAddressNodeID, report.TheInternet), + report.MakeAdjacencyID(clientAddressNodeID): report.MakeIDList(serverAddressNodeID), + report.MakeAdjacencyID(serverAddressNodeID): report.MakeIDList(clientAddressNodeID, report.TheInternet), } have := reportFixture.Squash().Address.Adjacency if !reflect.DeepEqual(want, have) { diff --git a/report/topology.go b/report/topology.go index 59527379f..f9abed7c6 100644 --- a/report/topology.go +++ b/report/topology.go @@ -113,19 +113,20 @@ func (t Topology) RenderBy(mapFunc MapFunc, pseudoFunc PseudoFunc) map[string]Re // Walk the graph and make connections. for src, dsts := range t.Adjacency { var ( - srcOriginHostID, srcNodeAddress, ok = ParseAdjacencyID(src) - srcRenderableID = address2mapped[srcNodeAddress] // must exist - srcRenderableNode = nodes[srcRenderableID] // must exist + srcNodeID, ok1 = ParseAdjacencyID(src) + srcOriginHostID, _, ok2 = ParseNodeID(srcNodeID) + srcRenderableID = address2mapped[srcNodeID] // must exist + srcRenderableNode = nodes[srcRenderableID] // must exist ) - if !ok { + if !ok1 || !ok2 { log.Printf("bad adjacency ID %q", src) continue } - for _, dstNodeAddress := range dsts { - dstRenderableID, ok := address2mapped[dstNodeAddress] + for _, dstNodeID := range dsts { + dstRenderableID, ok := address2mapped[dstNodeID] if !ok { - pseudoNode, ok := pseudoFunc(srcNodeAddress, srcRenderableNode, dstNodeAddress) + pseudoNode, ok := pseudoFunc(srcNodeID, srcRenderableNode, dstNodeID) if !ok { continue } @@ -137,13 +138,13 @@ func (t Topology) RenderBy(mapFunc MapFunc, pseudoFunc PseudoFunc) map[string]Re Pseudo: true, Metadata: AggregateMetadata{}, // populated below - or not? } - address2mapped[dstNodeAddress] = dstRenderableID + address2mapped[dstNodeID] = dstRenderableID } srcRenderableNode.Adjacency = srcRenderableNode.Adjacency.Add(dstRenderableID) srcRenderableNode.Origins = srcRenderableNode.Origins.Add(MakeHostNodeID(srcOriginHostID)) - srcRenderableNode.Origins = srcRenderableNode.Origins.Add(srcNodeAddress) - edgeID := MakeEdgeID(srcNodeAddress, dstNodeAddress) + srcRenderableNode.Origins = srcRenderableNode.Origins.Add(srcNodeID) + edgeID := MakeEdgeID(srcNodeID, dstNodeID) if md, ok := t.EdgeMetadatas[edgeID]; ok { srcRenderableNode.Metadata.Merge(md.Transform()) } @@ -184,12 +185,29 @@ func (t Topology) EdgeMetadata(mapFunc MapFunc, srcRenderableID, dstRenderableID // Squash squashes all non-local nodes in the topology to a super-node called // the Internet. +// We rely on the values in the t.Adjacency lists being valid keys in +// t.NodeMetadata (or t.Adjacency). func (t Topology) Squash(f IDAddresser, localNets []*net.IPNet) Topology { - isRemote := func(ip net.IP) bool { return !netsContain(localNets, ip) } + isRemote := func(id string) bool { + if _, ok := t.NodeMetadatas[id]; ok { + return false // it is a node, cannot possibly be remote + } + + if _, ok := t.Adjacency[MakeAdjacencyID(id)]; ok { + return false // it is in our adjacency list, cannot possibly be remote + } + + if ip := f(id); ip != nil && netsContain(localNets, ip) { + return false // it is in our local nets, so it is not remote + } + + return true + } + for srcID, dstIDs := range t.Adjacency { newDstIDs := make(IDList, 0, len(dstIDs)) for _, dstID := range dstIDs { - if ip := f(dstID); ip != nil && isRemote(ip) { + if isRemote(dstID) { dstID = TheInternet } newDstIDs = newDstIDs.Add(dstID) diff --git a/report/topology_test.go b/report/topology_test.go index 658cbf289..79b56925f 100644 --- a/report/topology_test.go +++ b/report/topology_test.go @@ -36,9 +36,9 @@ var ( report = Report{ Endpoint: Topology{ Adjacency: Adjacency{ - MakeAdjacencyID("client.hostname.com", client54001): MakeIDList(server80), - MakeAdjacencyID("client.hostname.com", client54002): MakeIDList(server80), - MakeAdjacencyID("server.hostname.com", server80): MakeIDList(client54001, client54002, unknownClient1, unknownClient2, unknownClient3), + MakeAdjacencyID(client54001): MakeIDList(server80), + MakeAdjacencyID(client54002): MakeIDList(server80), + MakeAdjacencyID(server80): MakeIDList(client54001, client54002, unknownClient1, unknownClient2, unknownClient3), }, NodeMetadatas: NodeMetadatas{ // NodeMetadata is arbitrary. We're free to put only precisely what we @@ -101,9 +101,9 @@ var ( }, Address: Topology{ Adjacency: Adjacency{ - MakeAdjacencyID("client.hostname.com", clientIP): MakeIDList(serverIP), - MakeAdjacencyID("random.hostname.com", randomIP): MakeIDList(serverIP), - MakeAdjacencyID("server.hostname.com", serverIP): MakeIDList(clientIP, unknownIP), // no backlink to random + MakeAdjacencyID(clientIP): MakeIDList(serverIP), + MakeAdjacencyID(randomIP): MakeIDList(serverIP), + MakeAdjacencyID(serverIP): MakeIDList(clientIP, unknownIP), // no backlink to random }, NodeMetadatas: NodeMetadatas{ clientIP: NodeMetadata{