diff --git a/integration-tests/integration_test.go b/integration-tests/integration_test.go index 56ee693570..f3247bc45a 100644 --- a/integration-tests/integration_test.go +++ b/integration-tests/integration_test.go @@ -1,9 +1,13 @@ package integrationtests import ( + "fmt" "strings" "testing" + sensorAPI "github.com/stackrox/rox/generated/internalapi/sensor" + "github.com/stackrox/rox/generated/storage" + "github.com/stretchr/testify/suite" "github.com/stackrox/collector/integration-tests/pkg/collector" @@ -13,6 +17,10 @@ import ( "github.com/stackrox/collector/integration-tests/suites" ) +const ( + placeholderIP = "0.0.0.0" +) + func TestProcessNetwork(t *testing.T) { suite.Run(t, new(suites.ProcessNetworkTestSuite)) } @@ -162,17 +170,19 @@ func TestDuplicateEndpoints(t *testing.T) { func TestConnectionsAndEndpointsNormal(t *testing.T) { // Server uses a normal port. Client is assigned a port in the ephemeral range in the normal way + port := 40 normalPorts := &suites.ConnectionsAndEndpointsTestSuite{ Server: suites.Container{ Name: "socat-server-0", Cmd: "socat TCP4-LISTEN:40,reuseaddr,fork - &", - ExpectedNetwork: []types.NetworkInfo{ + ExpectedNetwork: []*sensorAPI.NetworkConnection{ { - LocalAddress: ":40", - RemoteAddress: "CLIENT_IP", - Role: "ROLE_SERVER", - SocketFamily: "SOCKET_FAMILY_UNKNOWN", - CloseTimestamp: types.NilTimestamp, + LocalAddress: types.CreateNetworkAddress("", "", uint32(port)), + RemoteAddress: types.CreateNetworkAddress("", placeholderIP, 0), + Protocol: storage.L4Protocol_L4_PROTOCOL_TCP, + Role: sensorAPI.ClientServerRole_ROLE_SERVER, + SocketFamily: sensorAPI.SocketFamily_SOCKET_FAMILY_UNKNOWN, + CloseTimestamp: types.NotNilTimestamp, }, }, ExpectedEndpoints: []types.EndpointInfo{ @@ -180,7 +190,7 @@ func TestConnectionsAndEndpointsNormal(t *testing.T) { Protocol: "L4_PROTOCOL_TCP", Address: types.ListenAddress{ AddressData: "\x00\x00\x00\x00", - Port: 40, + Port: port, IpNetwork: "\x00\x00\x00\x00 ", }, }, @@ -188,14 +198,15 @@ func TestConnectionsAndEndpointsNormal(t *testing.T) { }, Client: suites.Container{ Name: "socat-client-0", - Cmd: "echo hello | socat - TCP4:SERVER_IP:40", - ExpectedNetwork: []types.NetworkInfo{ + Cmd: fmt.Sprintf("echo hello | socat - TCP4:SERVER_IP:%d", port), + ExpectedNetwork: []*sensorAPI.NetworkConnection{ { - LocalAddress: "", - RemoteAddress: "SERVER_IP:40", - Role: "ROLE_CLIENT", - SocketFamily: "SOCKET_FAMILY_UNKNOWN", - CloseTimestamp: types.NilTimestamp, + LocalAddress: nil, + RemoteAddress: types.CreateNetworkAddress("", placeholderIP, uint32(port)), + Protocol: storage.L4Protocol_L4_PROTOCOL_TCP, + Role: sensorAPI.ClientServerRole_ROLE_CLIENT, + SocketFamily: sensorAPI.SocketFamily_SOCKET_FAMILY_UNKNOWN, + CloseTimestamp: types.NotNilTimestamp, }, }, ExpectedEndpoints: nil, @@ -207,17 +218,19 @@ func TestConnectionsAndEndpointsNormal(t *testing.T) { func TestConnectionsAndEndpointsHighLowPorts(t *testing.T) { // The server is assigned a port in the ephemeral ports range. // The client is assigned a source port in a non-ephemeral ports range + port := 40000 mixedHighLowPorts := &suites.ConnectionsAndEndpointsTestSuite{ Server: suites.Container{ Name: "socat-server-1", - Cmd: "socat TCP4-LISTEN:40000,reuseaddr,fork - &", - ExpectedNetwork: []types.NetworkInfo{ + Cmd: fmt.Sprintf("socat TCP4-LISTEN:%d,reuseaddr,fork - &", port), + ExpectedNetwork: []*sensorAPI.NetworkConnection{ { - LocalAddress: ":40000", - RemoteAddress: "CLIENT_IP", - Role: "ROLE_SERVER", - SocketFamily: "SOCKET_FAMILY_UNKNOWN", - CloseTimestamp: types.NilTimestamp, + LocalAddress: types.CreateNetworkAddress("", "", uint32(port)), + RemoteAddress: types.CreateNetworkAddress("", placeholderIP, 0), + Protocol: storage.L4Protocol_L4_PROTOCOL_TCP, + Role: sensorAPI.ClientServerRole_ROLE_SERVER, + SocketFamily: sensorAPI.SocketFamily_SOCKET_FAMILY_UNKNOWN, + CloseTimestamp: types.NotNilTimestamp, }, }, ExpectedEndpoints: []types.EndpointInfo{ @@ -225,7 +238,7 @@ func TestConnectionsAndEndpointsHighLowPorts(t *testing.T) { Protocol: "L4_PROTOCOL_TCP", Address: types.ListenAddress{ AddressData: "\x00\x00\x00\x00", - Port: 40000, + Port: port, IpNetwork: "\x00\x00\x00\x00 ", }, }, @@ -233,14 +246,15 @@ func TestConnectionsAndEndpointsHighLowPorts(t *testing.T) { }, Client: suites.Container{ Name: "socat-client-1", - Cmd: "echo hello | socat - TCP4:SERVER_IP:40000,sourceport=10000", - ExpectedNetwork: []types.NetworkInfo{ + Cmd: fmt.Sprintf("echo hello | socat - TCP4:SERVER_IP:%d,sourceport=10000", port), + ExpectedNetwork: []*sensorAPI.NetworkConnection{ { - LocalAddress: "", - RemoteAddress: "SERVER_IP:40000", - Role: "ROLE_CLIENT", - SocketFamily: "SOCKET_FAMILY_UNKNOWN", - CloseTimestamp: types.NilTimestamp, + LocalAddress: nil, + RemoteAddress: types.CreateNetworkAddress("", placeholderIP, uint32(port)), + Protocol: storage.L4Protocol_L4_PROTOCOL_TCP, + Role: sensorAPI.ClientServerRole_ROLE_CLIENT, + SocketFamily: sensorAPI.SocketFamily_SOCKET_FAMILY_UNKNOWN, + CloseTimestamp: types.NotNilTimestamp, }, }, ExpectedEndpoints: nil, @@ -252,17 +266,19 @@ func TestConnectionsAndEndpointsHighLowPorts(t *testing.T) { func TestConnectionsAndEndpointsServerHigh(t *testing.T) { // The server is assigned a port in the ephemeral ports range. // The client is assigned a port in the ephemeral ports range in the normal way. + port := 60999 mixedHighLowPorts := &suites.ConnectionsAndEndpointsTestSuite{ Server: suites.Container{ Name: "socat-server-2", - Cmd: "socat TCP4-LISTEN:60999,reuseaddr,fork - &", - ExpectedNetwork: []types.NetworkInfo{ + Cmd: fmt.Sprintf("socat TCP4-LISTEN:%d,reuseaddr,fork - &", port), + ExpectedNetwork: []*sensorAPI.NetworkConnection{ { - LocalAddress: ":60999", - RemoteAddress: "CLIENT_IP", - Role: "ROLE_SERVER", - SocketFamily: "SOCKET_FAMILY_UNKNOWN", - CloseTimestamp: types.NilTimestamp, + LocalAddress: types.CreateNetworkAddress("", "", uint32(port)), + RemoteAddress: types.CreateNetworkAddress("", placeholderIP, 0), + Protocol: storage.L4Protocol_L4_PROTOCOL_TCP, + Role: sensorAPI.ClientServerRole_ROLE_SERVER, + SocketFamily: sensorAPI.SocketFamily_SOCKET_FAMILY_UNKNOWN, + CloseTimestamp: types.NotNilTimestamp, }, }, ExpectedEndpoints: []types.EndpointInfo{ @@ -270,7 +286,7 @@ func TestConnectionsAndEndpointsServerHigh(t *testing.T) { Protocol: "L4_PROTOCOL_TCP", Address: types.ListenAddress{ AddressData: "\x00\x00\x00\x00", - Port: 60999, + Port: port, IpNetwork: "\x00\x00\x00\x00 ", }, }, @@ -279,13 +295,14 @@ func TestConnectionsAndEndpointsServerHigh(t *testing.T) { Client: suites.Container{ Name: "socat-client-2", Cmd: "echo hello | socat - TCP4:SERVER_IP:60999", - ExpectedNetwork: []types.NetworkInfo{ + ExpectedNetwork: []*sensorAPI.NetworkConnection{ { - LocalAddress: "", - RemoteAddress: "SERVER_IP:60999", - Role: "ROLE_CLIENT", - SocketFamily: "SOCKET_FAMILY_UNKNOWN", - CloseTimestamp: types.NilTimestamp, + LocalAddress: nil, + RemoteAddress: types.CreateNetworkAddress("", placeholderIP, uint32(port)), + Protocol: storage.L4Protocol_L4_PROTOCOL_TCP, + Role: sensorAPI.ClientServerRole_ROLE_CLIENT, + SocketFamily: sensorAPI.SocketFamily_SOCKET_FAMILY_UNKNOWN, + CloseTimestamp: types.NotNilTimestamp, }, }, ExpectedEndpoints: nil, @@ -297,17 +314,19 @@ func TestConnectionsAndEndpointsServerHigh(t *testing.T) { func TestConnectionsAndEndpointsSourcePort(t *testing.T) { // The server is assigned a port in the ephemeral ports range. // The client is assigned a source port in a non-ephemeral ports range + port := 10000 mixedHighLowPorts := &suites.ConnectionsAndEndpointsTestSuite{ Server: suites.Container{ Name: "socat-server-1", - Cmd: "socat TCP4-LISTEN:10000,reuseaddr,fork - &", - ExpectedNetwork: []types.NetworkInfo{ + Cmd: fmt.Sprintf("socat TCP4-LISTEN:%d,reuseaddr,fork - &", port), + ExpectedNetwork: []*sensorAPI.NetworkConnection{ { - LocalAddress: ":10000", - RemoteAddress: "CLIENT_IP", - Role: "ROLE_SERVER", - SocketFamily: "SOCKET_FAMILY_UNKNOWN", - CloseTimestamp: types.NilTimestamp, + LocalAddress: types.CreateNetworkAddress("", "", uint32(port)), + RemoteAddress: types.CreateNetworkAddress("", placeholderIP, 0), + Protocol: storage.L4Protocol_L4_PROTOCOL_TCP, + Role: sensorAPI.ClientServerRole_ROLE_SERVER, + SocketFamily: sensorAPI.SocketFamily_SOCKET_FAMILY_UNKNOWN, + CloseTimestamp: types.NotNilTimestamp, }, }, ExpectedEndpoints: []types.EndpointInfo{ @@ -315,7 +334,7 @@ func TestConnectionsAndEndpointsSourcePort(t *testing.T) { Protocol: "L4_PROTOCOL_TCP", Address: types.ListenAddress{ AddressData: "\x00\x00\x00\x00", - Port: 10000, + Port: port, IpNetwork: "\x00\x00\x00\x00 ", }, }, @@ -323,14 +342,15 @@ func TestConnectionsAndEndpointsSourcePort(t *testing.T) { }, Client: suites.Container{ Name: "socat-client-1", - Cmd: "echo hello | socat - TCP4:SERVER_IP:10000,sourceport=40000", - ExpectedNetwork: []types.NetworkInfo{ + Cmd: fmt.Sprintf("echo hello | socat - TCP4:SERVER_IP:%d,sourceport=40000", port), + ExpectedNetwork: []*sensorAPI.NetworkConnection{ { - LocalAddress: "", - RemoteAddress: "SERVER_IP:10000", - Role: "ROLE_CLIENT", - SocketFamily: "SOCKET_FAMILY_UNKNOWN", - CloseTimestamp: types.NilTimestamp, + LocalAddress: nil, + RemoteAddress: types.CreateNetworkAddress("", placeholderIP, uint32(port)), + Protocol: storage.L4Protocol_L4_PROTOCOL_TCP, + Role: sensorAPI.ClientServerRole_ROLE_CLIENT, + SocketFamily: sensorAPI.SocketFamily_SOCKET_FAMILY_UNKNOWN, + CloseTimestamp: types.NotNilTimestamp, }, }, ExpectedEndpoints: nil, @@ -341,10 +361,11 @@ func TestConnectionsAndEndpointsSourcePort(t *testing.T) { func TestConnectionsAndEndpointsUDPNormal(t *testing.T) { // A test for UDP + port := 53 mixedHighLowPorts := &suites.ConnectionsAndEndpointsTestSuite{ Server: suites.Container{ Name: "socat-server-udp", - Cmd: "socat UDP-LISTEN:53,reuseaddr,fork - &", + Cmd: fmt.Sprintf("socat UDP-LISTEN:%d,reuseaddr,fork - &", port), // TODO UDP connections are not always reported on the server side ExpectedNetwork: nil, // ExpectedNetwork: []types.NetworkInfo{ @@ -361,14 +382,15 @@ func TestConnectionsAndEndpointsUDPNormal(t *testing.T) { }, Client: suites.Container{ Name: "socat-client-udp", - Cmd: "echo hello | socat - UDP:SERVER_IP:53", - ExpectedNetwork: []types.NetworkInfo{ + Cmd: fmt.Sprintf("echo hello | socat - UDP:SERVER_IP:%d", port), + ExpectedNetwork: []*sensorAPI.NetworkConnection{ { - LocalAddress: "", - RemoteAddress: "SERVER_IP:53", - Role: "ROLE_CLIENT", - SocketFamily: "SOCKET_FAMILY_UNKNOWN", - CloseTimestamp: types.NilTimestamp, + LocalAddress: nil, + RemoteAddress: types.CreateNetworkAddress("", placeholderIP, uint32(port)), + Protocol: storage.L4Protocol_L4_PROTOCOL_UDP, + Role: sensorAPI.ClientServerRole_ROLE_CLIENT, + SocketFamily: sensorAPI.SocketFamily_SOCKET_FAMILY_UNKNOWN, + CloseTimestamp: types.NotNilTimestamp, }, }, ExpectedEndpoints: nil, @@ -379,10 +401,11 @@ func TestConnectionsAndEndpointsUDPNormal(t *testing.T) { func TestConnectionsAndEndpointsUDPNoReuseaddr(t *testing.T) { // A test for UDP without reuseaddr + port := 53 mixedHighLowPorts := &suites.ConnectionsAndEndpointsTestSuite{ Server: suites.Container{ Name: "socat-server-udp", - Cmd: "socat UDP-LISTEN:53,fork - &", + Cmd: fmt.Sprintf("socat UDP-LISTEN:%d,fork - &", port), // TODO UDP connections are not always reported on the server side ExpectedNetwork: nil, // ExpectedNetwork: []types.NetworkInfo{ @@ -399,14 +422,15 @@ func TestConnectionsAndEndpointsUDPNoReuseaddr(t *testing.T) { }, Client: suites.Container{ Name: "socat-client-udp", - Cmd: "echo hello | socat - UDP:SERVER_IP:53", - ExpectedNetwork: []types.NetworkInfo{ + Cmd: fmt.Sprintf("echo hello | socat - UDP:SERVER_IP:%d", port), + ExpectedNetwork: []*sensorAPI.NetworkConnection{ { - LocalAddress: "", - RemoteAddress: "SERVER_IP:53", - Role: "ROLE_CLIENT", - SocketFamily: "SOCKET_FAMILY_UNKNOWN", - CloseTimestamp: types.NilTimestamp, + LocalAddress: nil, + RemoteAddress: types.CreateNetworkAddress("", placeholderIP, uint32(port)), + Protocol: storage.L4Protocol_L4_PROTOCOL_UDP, + Role: sensorAPI.ClientServerRole_ROLE_CLIENT, + SocketFamily: sensorAPI.SocketFamily_SOCKET_FAMILY_UNKNOWN, + CloseTimestamp: types.NotNilTimestamp, }, }, ExpectedEndpoints: nil, @@ -417,10 +441,11 @@ func TestConnectionsAndEndpointsUDPNoReuseaddr(t *testing.T) { func TestConnectionsAndEndpointsUDPNoFork(t *testing.T) { // A test for UDP without fork or reuseaddr + port := 53 mixedHighLowPorts := &suites.ConnectionsAndEndpointsTestSuite{ Server: suites.Container{ Name: "socat-server-udp", - Cmd: "socat UDP-LISTEN:53 - &", + Cmd: fmt.Sprintf("socat UDP-LISTEN:%d - &", port), // TODO UDP connections are not always reported on the server side ExpectedNetwork: nil, // ExpectedNetwork: []types.NetworkInfo{ @@ -437,14 +462,15 @@ func TestConnectionsAndEndpointsUDPNoFork(t *testing.T) { }, Client: suites.Container{ Name: "socat-client-udp", - Cmd: "echo hello | socat - UDP:SERVER_IP:53", - ExpectedNetwork: []types.NetworkInfo{ + Cmd: fmt.Sprintf("echo hello | socat - UDP:SERVER_IP:%d", port), + ExpectedNetwork: []*sensorAPI.NetworkConnection{ { - LocalAddress: "", - RemoteAddress: "SERVER_IP:53", - Role: "ROLE_CLIENT", - SocketFamily: "SOCKET_FAMILY_UNKNOWN", - CloseTimestamp: types.NilTimestamp, + LocalAddress: nil, + RemoteAddress: types.CreateNetworkAddress("", placeholderIP, uint32(port)), + Protocol: storage.L4Protocol_L4_PROTOCOL_UDP, + Role: sensorAPI.ClientServerRole_ROLE_CLIENT, + SocketFamily: sensorAPI.SocketFamily_SOCKET_FAMILY_UNKNOWN, + CloseTimestamp: types.NotNilTimestamp, }, }, ExpectedEndpoints: nil, diff --git a/integration-tests/pkg/mock_sensor/expect_conn.go b/integration-tests/pkg/mock_sensor/expect_conn.go index 2ba3800027..6d929602e1 100644 --- a/integration-tests/pkg/mock_sensor/expect_conn.go +++ b/integration-tests/pkg/mock_sensor/expect_conn.go @@ -9,17 +9,19 @@ import ( collectorAssert "github.com/stackrox/collector/integration-tests/pkg/assert" "github.com/stackrox/collector/integration-tests/pkg/types" + + sensorAPI "github.com/stackrox/rox/generated/internalapi/sensor" ) // ExpectConnections waits up to the timeout for the gRPC server to receive // the list of expected Connections. It will first check to see if the connections // have been received already, and then monitor the live feed of connections // until timeout or until all the events have been received. -func (s *MockSensor) ExpectConnections(t *testing.T, containerID string, timeout time.Duration, expected ...types.NetworkInfo) bool { +func (s *MockSensor) ExpectConnections(t *testing.T, containerID string, timeout time.Duration, expected ...*sensorAPI.NetworkConnection) bool { - to_find := funk.Filter(expected, func(x types.NetworkInfo) bool { + to_find := funk.Filter(expected, func(x *sensorAPI.NetworkConnection) bool { return !s.HasConnection(containerID, x) - }).([]types.NetworkInfo) + }).([]*sensorAPI.NetworkConnection) if len(to_find) == 0 { return true @@ -39,9 +41,9 @@ loop: continue loop } - to_find = funk.Filter(expected, func(x types.NetworkInfo) bool { + to_find = funk.Filter(expected, func(x *sensorAPI.NetworkConnection) bool { return !s.HasConnection(containerID, x) - }).([]types.NetworkInfo) + }).([]*sensorAPI.NetworkConnection) if len(to_find) == 0 { return true @@ -57,7 +59,7 @@ loop: // // It does not consider the content of the events, just that a certain number // have been received -func (s *MockSensor) ExpectConnectionsN(t *testing.T, containerID string, timeout time.Duration, n int) []types.NetworkInfo { +func (s *MockSensor) ExpectConnectionsN(t *testing.T, containerID string, timeout time.Duration, n int) []*sensorAPI.NetworkConnection { if len(s.Connections(containerID)) == n { return s.Connections(containerID) } @@ -82,11 +84,11 @@ loop: // ExpectSameElementsConnections compares a list of expected connections to the observed connections. This comparison is done at the beginning, when a new // connection arrives, and after a timeout period. The number of connections must match and the expected and observed connections must match, but the order // does not matter. -func (s *MockSensor) ExpectSameElementsConnections(t *testing.T, containerID string, timeout time.Duration, expected ...types.NetworkInfo) bool { +func (s *MockSensor) ExpectSameElementsConnections(t *testing.T, containerID string, timeout time.Duration, expected ...*sensorAPI.NetworkConnection) bool { types.SortConnections(expected) - equal := func(c1, c2 types.NetworkInfo) bool { - return c1.Equal(c2) + equal := func(c1, c2 *sensorAPI.NetworkConnection) bool { + return types.EqualNetworkConnection(c1, c2) } connections := s.Connections(containerID) @@ -113,8 +115,8 @@ func (s *MockSensor) ExpectSameElementsConnections(t *testing.T, containerID str } } -func (s *MockSensor) ExpectSameElementsConnectionsScrapes(t *testing.T, containerID string, timeout time.Duration, expected []types.NetworkInfoBatch) bool { - equal := func(c1, c2 types.NetworkInfoBatch) bool { +func (s *MockSensor) ExpectSameElementsConnectionsScrapes(t *testing.T, containerID string, timeout time.Duration, expected []types.NetworkConnectionBatch) bool { + equal := func(c1, c2 types.NetworkConnectionBatch) bool { if len(c1) != len(c2) { return false } @@ -123,7 +125,7 @@ func (s *MockSensor) ExpectSameElementsConnectionsScrapes(t *testing.T, containe types.SortConnections(c2) for i := range c2 { - if !c1[i].Equal(c2[i]) { + if !types.EqualNetworkConnection(c1[i], c2[i]) { return false } } diff --git a/integration-tests/pkg/mock_sensor/server.go b/integration-tests/pkg/mock_sensor/server.go index 93b50187cb..7b6e07223c 100644 --- a/integration-tests/pkg/mock_sensor/server.go +++ b/integration-tests/pkg/mock_sensor/server.go @@ -46,7 +46,7 @@ type MockSensor struct { processLineages map[string]LineageMap processMutex sync.Mutex - connections map[string][]types.NetworkInfoBatch + connections map[string][]types.NetworkConnectionBatch endpoints map[string]EndpointMap networkMutex sync.Mutex @@ -64,7 +64,7 @@ func NewMockSensor(test string) *MockSensor { testName: test, processes: make(map[string]ProcessMap), processLineages: make(map[string]LineageMap), - connections: make(map[string][]types.NetworkInfoBatch), + connections: make(map[string][]types.NetworkConnectionBatch), endpoints: make(map[string]EndpointMap), } } @@ -149,12 +149,12 @@ func (m *MockSensor) LiveConnections() <-chan *sensorAPI.NetworkConnection { // Connections returns a list of all connections that have been received for // a given container ID -func (m *MockSensor) GetConnectionsInBatches(containerID string) []types.NetworkInfoBatch { +func (m *MockSensor) GetConnectionsInBatches(containerID string) []types.NetworkConnectionBatch { m.networkMutex.Lock() defer m.networkMutex.Unlock() if connections, ok := m.connections[containerID]; ok { - conns := make([]types.NetworkInfoBatch, len(connections)) + conns := make([]types.NetworkConnectionBatch, len(connections)) copy(conns, connections) for _, conn := range conns { types.SortConnections(conn) @@ -162,18 +162,18 @@ func (m *MockSensor) GetConnectionsInBatches(containerID string) []types.Network return conns } - return make([]types.NetworkInfoBatch, 0) + return make([]types.NetworkConnectionBatch, 0) } // Connections returns a list of all connections that have been received for // a given container ID -func (m *MockSensor) Connections(containerID string) []types.NetworkInfo { +func (m *MockSensor) Connections(containerID string) []*sensorAPI.NetworkConnection { m.networkMutex.Lock() defer m.networkMutex.Unlock() - allConns := make([]types.NetworkInfo, 0) + allConns := make([]*sensorAPI.NetworkConnection, 0) if connections, ok := m.connections[containerID]; ok { - conns := make([]types.NetworkInfoBatch, len(connections)) + conns := make([]types.NetworkConnectionBatch, len(connections)) copy(conns, connections) for _, conn := range conns { allConns = append(allConns, conn...) @@ -183,16 +183,16 @@ func (m *MockSensor) Connections(containerID string) []types.NetworkInfo { return allConns } - return make([]types.NetworkInfo, 0) + return make([]*sensorAPI.NetworkConnection, 0) } // HasConnection returns whether a given connection has been seen for a given // container ID -func (m *MockSensor) HasConnection(containerID string, conn types.NetworkInfo) bool { +func (m *MockSensor) HasConnection(containerID string, conn *sensorAPI.NetworkConnection) bool { conns := m.Connections(containerID) if len(conns) > 0 { - return slices.ContainsFunc(conns, func(c types.NetworkInfo) bool { - return c.Equal(conn) + return slices.ContainsFunc(conns, func(c *sensorAPI.NetworkConnection) bool { + return types.EqualNetworkConnection(c, conn) }) } @@ -292,7 +292,7 @@ func (m *MockSensor) Stop() { m.processes = make(map[string]ProcessMap) m.processLineages = make(map[string]LineageMap) - m.connections = make(map[string][]types.NetworkInfoBatch) + m.connections = make(map[string][]types.NetworkConnectionBatch) m.endpoints = make(map[string]EndpointMap) m.processChannel.Stop() @@ -348,30 +348,15 @@ func (m *MockSensor) PushSignals(stream sensorAPI.SignalService_PushSignalsServe } } -func (m *MockSensor) convertConnection(connection *sensorAPI.NetworkConnection) types.NetworkInfo { - conn := types.NetworkInfo{ - LocalAddress: types.TranslateAddress(connection.LocalAddress), - RemoteAddress: types.TranslateAddress(connection.RemoteAddress), - Role: connection.GetRole().String(), - SocketFamily: connection.GetSocketFamily().String(), - CloseTimestamp: connection.GetCloseTimestamp().String(), - } - - m.logger.Printf("NetworkInfo: %s, %s\n", connection.GetContainerId(), conn) - - return conn -} - -func (m *MockSensor) convertToContainerConnsMap(connections []*sensorAPI.NetworkConnection) map[string][]types.NetworkInfo { - containerConnsMap := make(map[string][]types.NetworkInfo) +func (m *MockSensor) convertToContainerConnsMap(connections []*sensorAPI.NetworkConnection) map[string][]*sensorAPI.NetworkConnection { + containerConnsMap := make(map[string][]*sensorAPI.NetworkConnection) for _, connection := range connections { - conn := m.convertConnection(connection) containerID := connection.GetContainerId() if c, ok := containerConnsMap[containerID]; ok { - containerConnsMap[containerID] = append(c, conn) + containerConnsMap[containerID] = append(c, connection) } else { - containerConnsMap[containerID] = []types.NetworkInfo{conn} + containerConnsMap[containerID] = []*sensorAPI.NetworkConnection{connection} } } @@ -462,7 +447,7 @@ func (m *MockSensor) pushLineage(containerID string, process *storage.ProcessSig } } -func (m *MockSensor) pushConnections(containerConnsMap map[string][]types.NetworkInfo) { +func (m *MockSensor) pushConnections(containerConnsMap map[string][]*sensorAPI.NetworkConnection) { m.networkMutex.Lock() defer m.networkMutex.Unlock() @@ -470,7 +455,7 @@ func (m *MockSensor) pushConnections(containerConnsMap map[string][]types.Networ if c, ok := m.connections[containerID]; ok { m.connections[containerID] = append(c, connections) } else { - m.connections[containerID] = []types.NetworkInfoBatch{connections} + m.connections[containerID] = []types.NetworkConnectionBatch{connections} } } } diff --git a/integration-tests/pkg/types/network.go b/integration-tests/pkg/types/network.go index 458daf865e..ca5df3dfa3 100644 --- a/integration-tests/pkg/types/network.go +++ b/integration-tests/pkg/types/network.go @@ -1,103 +1,135 @@ package types import ( - "fmt" + "bytes" + "net" "sort" + "time" + + "google.golang.org/protobuf/proto" + timestamppb "google.golang.org/protobuf/types/known/timestamppb" sensorAPI "github.com/stackrox/rox/generated/internalapi/sensor" - utils "github.com/stackrox/rox/pkg/net" ) const ( NilTimestamp = "" ) -type NetworkInfo struct { - LocalAddress string - RemoteAddress string - Role string - SocketFamily string - CloseTimestamp string +var ( + NotNilTimestamp = timestamppb.New(time.Date(2025, 1, 1, 0, 0, 0, 0, time.UTC)) +) + +type NetworkConnectionBatch []*sensorAPI.NetworkConnection + +func IsActive(conn *sensorAPI.NetworkConnection) bool { + // no close timestamp means the connection is open, and active + return conn.GetCloseTimestamp() == nil } -type NetworkInfoBatch []NetworkInfo +// Equal is not called directly because it returns false when close timestamps have different non-nil values. +func EqualNetworkConnection(conn1 *sensorAPI.NetworkConnection, conn2 *sensorAPI.NetworkConnection) bool { + adjustNetworkConnectionForComparison := func(conn *sensorAPI.NetworkConnection) *sensorAPI.NetworkConnection { + if conn.CloseTimestamp != nil { + conn = conn.CloneVT() + conn.CloseTimestamp = NotNilTimestamp + } -// TranslateAddress is a helper function for converting binary representations -// of network addresses (in the signals) to usable forms for testing -func TranslateAddress(addr *sensorAPI.NetworkAddress) string { - peerId := utils.NetworkPeerID{Port: uint16(addr.GetPort())} - addressData := addr.GetAddressData() - if len(addressData) > 0 { - peerId.Address = utils.IPFromBytes(addressData) - return peerId.String() + return conn } - // If there is no address data, this is either the source address or - // IpNetwork should be set and represent a CIDR block or external IP address. - ipNetworkData := addr.GetIpNetwork() - if len(ipNetworkData) == 0 { - return peerId.String() - } + conn1 = adjustNetworkConnectionForComparison(conn1) + conn2 = adjustNetworkConnectionForComparison(conn2) - ipNetwork := utils.IPNetworkFromCIDRBytes(ipNetworkData) - prefixLen := ipNetwork.PrefixLen() - // If this is IPv4 and the prefix length is 32 or this is IPv6 and the prefix length - // is 128 this is a regular IP address and not a CIDR block - if (ipNetwork.Family() == utils.IPv4 && prefixLen == byte(32)) || - (ipNetwork.Family() == utils.IPv6 && prefixLen == byte(128)) { - peerId.Address = ipNetwork.IP() - } else { - peerId.IPNetwork = ipNetwork - } - return peerId.String() + return proto.Equal(conn1, conn2) } -func (n *NetworkInfo) String() string { - return fmt.Sprintf("%s|%s|%s|%s|%s", - n.LocalAddress, - n.RemoteAddress, - n.Role, - n.SocketFamily, - n.CloseTimestamp) -} +func EqualNetworkConnectionDontCompareCloseTimestamps(conn1 *sensorAPI.NetworkConnection, conn2 *sensorAPI.NetworkConnection) bool { + adjustNetworkConnectionForComparison := func(conn *sensorAPI.NetworkConnection) *sensorAPI.NetworkConnection { + if conn.CloseTimestamp != nil { + conn = conn.CloneVT() + conn.CloseTimestamp = nil + } -func (n *NetworkInfo) IsActive() bool { - // no close timestamp means the connection is open, and active - return n.CloseTimestamp == NilTimestamp + return conn + } + + conn1 = adjustNetworkConnectionForComparison(conn1) + conn2 = adjustNetworkConnectionForComparison(conn2) + + return proto.Equal(conn1, conn2) } -func (n *NetworkInfo) Equal(other NetworkInfo) bool { - return n.LocalAddress == other.LocalAddress && - n.RemoteAddress == other.RemoteAddress && - n.Role == other.Role && - n.SocketFamily == other.SocketFamily && - n.IsActive() == other.IsActive() +func LessNetworkAddress(addr1 *sensorAPI.NetworkAddress, addr2 *sensorAPI.NetworkAddress) bool { + comp := bytes.Compare(addr1.GetAddressData(), addr2.GetAddressData()) + + if comp != 0 { + return comp < 0 + } + + comp = bytes.Compare(addr1.GetIpNetwork(), addr2.GetIpNetwork()) + + if comp != 0 { + return comp < 0 + } + + return addr1.GetPort() < addr2.GetPort() } -func (n *NetworkInfo) Less(other NetworkInfo) bool { - if n.LocalAddress != other.LocalAddress { - return n.LocalAddress < other.LocalAddress +func LessNetworkConnection(conn1 *sensorAPI.NetworkConnection, conn2 *sensorAPI.NetworkConnection) bool { + if !proto.Equal(conn1.GetLocalAddress(), conn2.GetLocalAddress()) { + return LessNetworkAddress(conn1.GetLocalAddress(), conn2.GetLocalAddress()) } - if n.RemoteAddress != other.RemoteAddress { - return n.RemoteAddress < other.RemoteAddress + if !proto.Equal(conn1.GetRemoteAddress(), conn2.GetRemoteAddress()) { + return LessNetworkAddress(conn1.GetRemoteAddress(), conn2.GetRemoteAddress()) } - if n.Role != other.Role { - return n.Role < other.Role + if conn1.Role != conn2.Role { + return conn1.Role < conn2.Role } - if n.SocketFamily != other.SocketFamily { - return n.SocketFamily < other.SocketFamily + if conn1.SocketFamily != conn2.SocketFamily { + return conn1.SocketFamily < conn2.SocketFamily } - if n.IsActive() != other.IsActive() { - return n.IsActive() + if IsActive(conn1) != IsActive(conn2) { + return IsActive(conn1) } return false } -func SortConnections(connections []NetworkInfo) { - sort.Slice(connections, func(i, j int) bool { return connections[i].Less(connections[j]) }) +func stringToIPBytes(ipStr string) []byte { + ip := net.ParseIP(ipStr) + + if ip == nil { + return nil + } + + return ip.To4() + +} + +func stringToIPNetworkBytes(ipStr string) []byte { + ip := net.ParseIP(ipStr) + + if ip == nil { + return nil + } + + return append(ip.To4(), 32) +} + +func CreateNetworkAddress(ipAddress string, ipNetwork string, port uint32) *sensorAPI.NetworkAddress { + + return &sensorAPI.NetworkAddress{ + AddressData: stringToIPBytes(ipAddress), + IpNetwork: stringToIPNetworkBytes(ipNetwork), + Port: port, + } +} + +func SortConnections(connections []*sensorAPI.NetworkConnection) { + sort.Slice(connections, func(i, j int) bool { return LessNetworkConnection(connections[i], connections[j]) }) } diff --git a/integration-tests/suites/base.go b/integration-tests/suites/base.go index 2d8e18b11d..551361169d 100644 --- a/integration-tests/suites/base.go +++ b/integration-tests/suites/base.go @@ -434,8 +434,12 @@ func (s *IntegrationTestSuiteBase) getIPAddress(containerName string) (string, e return s.Executor().GetContainerIP(containerName) } -func (s *IntegrationTestSuiteBase) getPort(containerName string) (string, error) { - return s.Executor().GetContainerPort(containerName) +// unit16 makes more sense for ports, but sensor.NetworkConnection uses uint32 for +// ports, so uint32 is used for ports. +func (s *IntegrationTestSuiteBase) getPort(containerName string) (uint32, error) { + portStr, err := s.Executor().GetContainerPort(containerName) + port, _ := strconv.ParseUint(portStr, 10, 32) + return uint32(port), err } func (s *IntegrationTestSuiteBase) StartContainerStats() { diff --git a/integration-tests/suites/connections_and_endpoints.go b/integration-tests/suites/connections_and_endpoints.go index 9137edb9f7..601621651d 100644 --- a/integration-tests/suites/connections_and_endpoints.go +++ b/integration-tests/suites/connections_and_endpoints.go @@ -5,6 +5,8 @@ import ( "strings" "time" + sensorAPI "github.com/stackrox/rox/generated/internalapi/sensor" + "github.com/stackrox/collector/integration-tests/pkg/collector" "github.com/stackrox/collector/integration-tests/pkg/common" "github.com/stackrox/collector/integration-tests/pkg/config" @@ -18,7 +20,7 @@ type Container struct { Cmd string ContainerID string IP string - ExpectedNetwork []types.NetworkInfo + ExpectedNetwork []*sensorAPI.NetworkConnection ExpectedEndpoints []types.EndpointInfo } @@ -106,12 +108,10 @@ func (s *ConnectionsAndEndpointsTestSuite) TestConnectionsAndEndpoints() { } lastNetwork := clientNetworks[nNetwork-1] lastExpectedNetwork := s.Client.ExpectedNetwork[nExpectedNetwork-1] - expectedLocalAddress := strings.Replace(lastExpectedNetwork.LocalAddress, "CLIENT_IP", s.Client.IP, -1) - expectedRemoteAddress := strings.Replace(lastExpectedNetwork.RemoteAddress, "SERVER_IP", s.Server.IP, -1) - assert.Equal(s.T(), expectedLocalAddress, lastNetwork.LocalAddress) - assert.Equal(s.T(), expectedRemoteAddress, lastNetwork.RemoteAddress) - assert.Equal(s.T(), "ROLE_CLIENT", lastNetwork.Role) - assert.Equal(s.T(), lastExpectedNetwork.SocketFamily, lastNetwork.SocketFamily) + lastExpectedNetwork.RemoteAddress = types.CreateNetworkAddress(s.Server.IP, "", lastExpectedNetwork.RemoteAddress.Port) + lastExpectedNetwork.ContainerId = s.Client.ContainerID + + assert.True(s.T(), types.EqualNetworkConnectionDontCompareCloseTimestamps(lastExpectedNetwork, lastNetwork)) } if s.Client.ExpectedEndpoints != nil { @@ -133,12 +133,10 @@ func (s *ConnectionsAndEndpointsTestSuite) TestConnectionsAndEndpoints() { } lastNetwork := serverNetworks[nNetwork-1] lastExpectedNetwork := s.Server.ExpectedNetwork[nExpectedNetwork-1] - expectedLocalAddress := strings.Replace(lastExpectedNetwork.LocalAddress, "SERVER_IP", s.Server.IP, -1) - expectedRemoteAddress := strings.Replace(lastExpectedNetwork.RemoteAddress, "CLIENT_IP", s.Client.IP, -1) - assert.Equal(s.T(), expectedLocalAddress, lastNetwork.LocalAddress) - assert.Equal(s.T(), expectedRemoteAddress, lastNetwork.RemoteAddress) - assert.Equal(s.T(), "ROLE_SERVER", lastNetwork.Role) - assert.Equal(s.T(), lastExpectedNetwork.SocketFamily, lastNetwork.SocketFamily) + lastExpectedNetwork.RemoteAddress = types.CreateNetworkAddress(s.Client.IP, "", lastExpectedNetwork.RemoteAddress.Port) + lastExpectedNetwork.ContainerId = s.Server.ContainerID + + assert.True(s.T(), types.EqualNetworkConnectionDontCompareCloseTimestamps(lastExpectedNetwork, lastNetwork)) } serverEndpoints := s.Sensor().Endpoints(s.Server.ContainerID) diff --git a/integration-tests/suites/listening_ports.go b/integration-tests/suites/listening_ports.go index b146cf9812..c45dd615ab 100644 --- a/integration-tests/suites/listening_ports.go +++ b/integration-tests/suites/listening_ports.go @@ -58,7 +58,7 @@ func (s *ProcessListeningOnPortTestSuite) SetupSuite() { port, err := s.getPort(serverName) s.Require().NoError(err) - s.serverURL = fmt.Sprintf("http://%s:%s", ip, port) + s.serverURL = fmt.Sprintf("http://%s:%d", ip, port) // Wait 5 seconds for the plop service to start common.Sleep(5 * time.Second) diff --git a/integration-tests/suites/process_network.go b/integration-tests/suites/process_network.go index 9d41fa7f5d..48d17b02e9 100644 --- a/integration-tests/suites/process_network.go +++ b/integration-tests/suites/process_network.go @@ -7,6 +7,9 @@ import ( "github.com/stackrox/collector/integration-tests/pkg/common" "github.com/stackrox/collector/integration-tests/pkg/config" "github.com/stackrox/collector/integration-tests/pkg/types" + + sensorAPI "github.com/stackrox/rox/generated/internalapi/sensor" + "github.com/stackrox/rox/generated/storage" ) type ProcessNetworkTestSuite struct { @@ -15,7 +18,7 @@ type ProcessNetworkTestSuite struct { clientIP string serverContainer string serverIP string - serverPort string + serverPort uint32 } // Launches collector @@ -72,7 +75,7 @@ func (s *ProcessNetworkTestSuite) SetupSuite() { s.serverPort, err = s.getPort("nginx") s.Require().NoError(err) - _, err = s.execContainer("nginx-curl", []string{"curl", fmt.Sprintf("%s:%s", s.serverIP, s.serverPort)}, false) + _, err = s.execContainer("nginx-curl", []string{"curl", fmt.Sprintf("%s:%d", s.serverIP, s.serverPort)}, false) s.Require().NoError(err) s.clientIP, err = s.getIPAddress("nginx-curl") @@ -147,22 +150,26 @@ func (s *ProcessNetworkTestSuite) TestProcessLineageInfo() { func (s *ProcessNetworkTestSuite) TestNetworkFlows() { s.Sensor().ExpectConnections(s.T(), s.serverContainer, 10*time.Second, - types.NetworkInfo{ - LocalAddress: fmt.Sprintf(":%s", s.serverPort), - RemoteAddress: s.clientIP, - Role: "ROLE_SERVER", - SocketFamily: "SOCKET_FAMILY_UNKNOWN", - CloseTimestamp: types.NilTimestamp, + &sensorAPI.NetworkConnection{ + LocalAddress: types.CreateNetworkAddress("", "", s.serverPort), + RemoteAddress: types.CreateNetworkAddress(s.clientIP, "", 0), + Protocol: storage.L4Protocol_L4_PROTOCOL_TCP, + Role: sensorAPI.ClientServerRole_ROLE_SERVER, + SocketFamily: sensorAPI.SocketFamily_SOCKET_FAMILY_UNKNOWN, + ContainerId: s.serverContainer, + CloseTimestamp: nil, }, ) s.Sensor().ExpectConnections(s.T(), s.clientContainer, 10*time.Second, - types.NetworkInfo{ - LocalAddress: "", - RemoteAddress: fmt.Sprintf("%s:%s", s.serverIP, s.serverPort), - Role: "ROLE_CLIENT", - SocketFamily: "SOCKET_FAMILY_UNKNOWN", - CloseTimestamp: types.NilTimestamp, + &sensorAPI.NetworkConnection{ + LocalAddress: nil, + RemoteAddress: types.CreateNetworkAddress(s.serverIP, "", s.serverPort), + Protocol: storage.L4Protocol_L4_PROTOCOL_TCP, + Role: sensorAPI.ClientServerRole_ROLE_CLIENT, + SocketFamily: sensorAPI.SocketFamily_SOCKET_FAMILY_UNKNOWN, + ContainerId: s.clientContainer, + CloseTimestamp: nil, }, ) } diff --git a/integration-tests/suites/repeated_network_flow.go b/integration-tests/suites/repeated_network_flow.go index 9a04dc1e04..e305f8a46a 100644 --- a/integration-tests/suites/repeated_network_flow.go +++ b/integration-tests/suites/repeated_network_flow.go @@ -5,9 +5,12 @@ import ( "strconv" "time" + "github.com/stackrox/rox/pkg/protoassert" + "github.com/stackrox/collector/integration-tests/pkg/collector" "github.com/stackrox/collector/integration-tests/pkg/common" "github.com/stackrox/collector/integration-tests/pkg/config" + "github.com/stackrox/collector/integration-tests/pkg/types" "github.com/stretchr/testify/assert" ) @@ -20,7 +23,7 @@ type RepeatedNetworkFlowTestSuite struct { ClientIP string ServerContainer string ServerIP string - ServerPort string + ServerPort uint32 EnableAfterglow bool AfterglowPeriod int ScrapeInterval int @@ -86,7 +89,7 @@ func (s *RepeatedNetworkFlowTestSuite) SetupSuite() { s.ServerPort, err = s.getPort("nginx") s.Require().NoError(err) - serverAddress := fmt.Sprintf("%s:%s", s.ServerIP, s.ServerPort) + serverAddress := fmt.Sprintf("%s:%d", s.ServerIP, s.ServerPort) numMetaIter := strconv.Itoa(s.NumMetaIter) numIter := strconv.Itoa(s.NumIter) @@ -108,13 +111,13 @@ func (s *RepeatedNetworkFlowTestSuite) TearDownSuite() { } func (s *RepeatedNetworkFlowTestSuite) TestRepeatedNetworkFlow() { - networkInfos := s.Sensor().ExpectConnectionsN(s.T(), s.ServerContainer, 10*time.Second, s.ExpectedActive+s.ExpectedInactive) + networkConnections := s.Sensor().ExpectConnectionsN(s.T(), s.ServerContainer, 10*time.Second, s.ExpectedActive+s.ExpectedInactive) observedActive := 0 observedInactive := 0 - for _, info := range networkInfos { - if info.IsActive() { + for _, info := range networkConnections { + if types.IsActive(info) { observedActive++ } else { observedInactive++ @@ -126,12 +129,15 @@ func (s *RepeatedNetworkFlowTestSuite) TestRepeatedNetworkFlow() { // Server side checks - actualServerEndpoint := networkInfos[0].LocalAddress - actualClientEndpoint := networkInfos[0].RemoteAddress + actualServerEndpoint := networkConnections[0].LocalAddress + actualClientEndpoint := networkConnections[0].RemoteAddress // From server perspective, network connection info only has local port and remote IP - assert.Equal(s.T(), fmt.Sprintf(":%s", s.ServerPort), actualServerEndpoint) - assert.Equal(s.T(), s.ClientIP, actualClientEndpoint) + expectedServerEndpoint := types.CreateNetworkAddress("", "", s.ServerPort) + expectedClientEndpoint := types.CreateNetworkAddress(s.ClientIP, "", 0) + + protoassert.Equal(s.T(), expectedServerEndpoint, actualServerEndpoint) + protoassert.Equal(s.T(), expectedClientEndpoint, actualClientEndpoint) // client side checks @@ -139,8 +145,8 @@ func (s *RepeatedNetworkFlowTestSuite) TestRepeatedNetworkFlow() { // See the comment above for the server container endpoint test for more info. assert.Equal(s.T(), 0, len(s.Sensor().Endpoints(s.ClientContainer))) - networkInfos = s.Sensor().Connections(s.ClientContainer) + networkConnections = s.Sensor().Connections(s.ClientContainer) - actualClientEndpoint = networkInfos[0].LocalAddress - actualServerEndpoint = networkInfos[0].RemoteAddress + actualClientEndpoint = networkConnections[0].LocalAddress + actualServerEndpoint = networkConnections[0].RemoteAddress } diff --git a/integration-tests/suites/runtime_config_file.go b/integration-tests/suites/runtime_config_file.go index 1f7267cb34..214d75f02b 100644 --- a/integration-tests/suites/runtime_config_file.go +++ b/integration-tests/suites/runtime_config_file.go @@ -11,44 +11,56 @@ import ( "github.com/stackrox/collector/integration-tests/pkg/common" "github.com/stackrox/collector/integration-tests/pkg/config" "github.com/stackrox/collector/integration-tests/pkg/types" + + sensorAPI "github.com/stackrox/rox/generated/internalapi/sensor" + "github.com/stackrox/rox/generated/storage" + "github.com/stackrox/rox/pkg/protoconv" ) -var ( +const ( normalizedIp = "255.255.255.255" externalIp = "8.8.8.8" serverPort = 53 - externalUrl = fmt.Sprintf("http://%s:%d", externalIp, serverPort) - - activeNormalizedConnection = types.NetworkInfo{ - LocalAddress: "", - RemoteAddress: fmt.Sprintf("%s:%d", normalizedIp, serverPort), - Role: "ROLE_CLIENT", - SocketFamily: "SOCKET_FAMILY_UNKNOWN", - CloseTimestamp: types.NilTimestamp, +) + +var ( + externalUrl = fmt.Sprintf("http://%s:%d", externalIp, serverPort) + notNilTime = protoconv.ConvertTimeToTimestamp(time.Now()) + + activeNormalizedConnection = sensorAPI.NetworkConnection{ + LocalAddress: nil, + RemoteAddress: types.CreateNetworkAddress(normalizedIp, "", serverPort), + Protocol: storage.L4Protocol_L4_PROTOCOL_TCP, + Role: sensorAPI.ClientServerRole_ROLE_CLIENT, + SocketFamily: sensorAPI.SocketFamily_SOCKET_FAMILY_UNKNOWN, + CloseTimestamp: nil, } - activeUnnormalizedConnection = types.NetworkInfo{ - LocalAddress: "", - RemoteAddress: fmt.Sprintf("%s:%d", externalIp, serverPort), - Role: "ROLE_CLIENT", - SocketFamily: "SOCKET_FAMILY_UNKNOWN", - CloseTimestamp: types.NilTimestamp, + activeUnnormalizedConnection = sensorAPI.NetworkConnection{ + LocalAddress: nil, + RemoteAddress: types.CreateNetworkAddress("", externalIp, serverPort), + Protocol: storage.L4Protocol_L4_PROTOCOL_TCP, + Role: sensorAPI.ClientServerRole_ROLE_CLIENT, + SocketFamily: sensorAPI.SocketFamily_SOCKET_FAMILY_UNKNOWN, + CloseTimestamp: nil, } - inactiveNormalizedConnection = types.NetworkInfo{ - LocalAddress: "", - RemoteAddress: fmt.Sprintf("%s:%d", normalizedIp, serverPort), - Role: "ROLE_CLIENT", - SocketFamily: "SOCKET_FAMILY_UNKNOWN", - CloseTimestamp: "Not nill time", + inactiveNormalizedConnection = sensorAPI.NetworkConnection{ + LocalAddress: nil, + RemoteAddress: types.CreateNetworkAddress(normalizedIp, "", serverPort), + Protocol: storage.L4Protocol_L4_PROTOCOL_TCP, + Role: sensorAPI.ClientServerRole_ROLE_CLIENT, + SocketFamily: sensorAPI.SocketFamily_SOCKET_FAMILY_UNKNOWN, + CloseTimestamp: notNilTime, } - inactiveUnnormalizedConnection = types.NetworkInfo{ - LocalAddress: "", - RemoteAddress: fmt.Sprintf("%s:%d", externalIp, serverPort), - Role: "ROLE_CLIENT", - SocketFamily: "SOCKET_FAMILY_UNKNOWN", - CloseTimestamp: "Not nill time", + inactiveUnnormalizedConnection = sensorAPI.NetworkConnection{ + LocalAddress: nil, + RemoteAddress: types.CreateNetworkAddress("", externalIp, serverPort), + Protocol: storage.L4Protocol_L4_PROTOCOL_TCP, + Role: sensorAPI.ClientServerRole_ROLE_CLIENT, + SocketFamily: sensorAPI.SocketFamily_SOCKET_FAMILY_UNKNOWN, + CloseTimestamp: notNilTime, } runtimeConfigDir = "/tmp/collector-test" @@ -89,6 +101,11 @@ func (s *RuntimeConfigFileTestSuite) SetupTest() { s.Require().NoError(err) s.ClientContainer = common.ContainerShortID(containerID) + activeNormalizedConnection.ContainerId = s.ClientContainer + inactiveNormalizedConnection.ContainerId = s.ClientContainer + activeUnnormalizedConnection.ContainerId = s.ClientContainer + inactiveUnnormalizedConnection.ContainerId = s.ClientContainer + collectorOptions := collector.StartupOptions{ Env: map[string]string{ "ROX_AFTERGLOW_PERIOD": "6", @@ -116,7 +133,7 @@ func (s *RuntimeConfigFileTestSuite) TestRuntimeConfigFileEnable() { // Default configuration is external IPs disabled. // We expect normalized connections. assert.AssertNoRuntimeConfig(s.T(), collectorIP) - expectedConnections := []types.NetworkInfoBatch{[]types.NetworkInfo{activeNormalizedConnection}} + expectedConnections := []types.NetworkConnectionBatch{[]*sensorAPI.NetworkConnection{&activeNormalizedConnection}} connectionSuccess := s.Sensor().ExpectSameElementsConnectionsScrapes(s.T(), s.ClientContainer, 10*time.Second, expectedConnections) s.Require().True(connectionSuccess) @@ -125,7 +142,7 @@ func (s *RuntimeConfigFileTestSuite) TestRuntimeConfigFileEnable() { // Unnormalized connection will now be reported. s.setExternalIpsEnabled(runtimeConfigFile, "ENABLED") assert.AssertExternalIps(s.T(), "ENABLED", collectorIP) - expectedConnections = append(expectedConnections, []types.NetworkInfo{activeUnnormalizedConnection, inactiveNormalizedConnection}) + expectedConnections = append(expectedConnections, []*sensorAPI.NetworkConnection{&activeUnnormalizedConnection, &inactiveNormalizedConnection}) connectionSuccess = s.Sensor().ExpectSameElementsConnectionsScrapes(s.T(), s.ClientContainer, 10*time.Second, expectedConnections) s.Require().True(connectionSuccess) @@ -133,14 +150,14 @@ func (s *RuntimeConfigFileTestSuite) TestRuntimeConfigFileEnable() { // and the unnormalized connection shoul be inactive. s.deleteFile(runtimeConfigFile) assert.AssertNoRuntimeConfig(s.T(), collectorIP) - expectedConnections = append(expectedConnections, []types.NetworkInfo{activeNormalizedConnection, inactiveUnnormalizedConnection}) + expectedConnections = append(expectedConnections, []*sensorAPI.NetworkConnection{&activeNormalizedConnection, &inactiveUnnormalizedConnection}) connectionSuccess = s.Sensor().ExpectSameElementsConnectionsScrapes(s.T(), s.ClientContainer, 10*time.Second, expectedConnections) s.Require().True(connectionSuccess) // Back to having external IPs enabled. s.setExternalIpsEnabled(runtimeConfigFile, "ENABLED") assert.AssertExternalIps(s.T(), "ENABLED", collectorIP) - expectedConnections = append(expectedConnections, []types.NetworkInfo{activeUnnormalizedConnection, inactiveNormalizedConnection}) + expectedConnections = append(expectedConnections, []*sensorAPI.NetworkConnection{&activeUnnormalizedConnection, &inactiveNormalizedConnection}) connectionSuccess = s.Sensor().ExpectSameElementsConnectionsScrapes(s.T(), s.ClientContainer, 10*time.Second, expectedConnections) s.Require().True(connectionSuccess) } @@ -150,7 +167,7 @@ func (s *RuntimeConfigFileTestSuite) TestRuntimeConfigFileDisable() { // Default configuration is external IPs disabled. // We expect normalized connections. assert.AssertNoRuntimeConfig(s.T(), collectorIP) - expectedConnections := []types.NetworkInfo{activeNormalizedConnection} + expectedConnections := []*sensorAPI.NetworkConnection{&activeNormalizedConnection} connectionSuccess := s.Sensor().ExpectSameElementsConnections(s.T(), s.ClientContainer, 10*time.Second, expectedConnections...) s.Require().True(connectionSuccess) @@ -175,7 +192,7 @@ func (s *RuntimeConfigFileTestSuite) TestRuntimeConfigFileInvalid() { // Default configuration is external IPs disabled. // We expect normalized connections. assert.AssertNoRuntimeConfig(s.T(), collectorIP) - expectedConnections := []types.NetworkInfo{activeNormalizedConnection} + expectedConnections := []*sensorAPI.NetworkConnection{&activeNormalizedConnection} connectionSuccess := s.Sensor().ExpectSameElementsConnections(s.T(), s.ClientContainer, 10*time.Second, expectedConnections...) s.Require().True(connectionSuccess) diff --git a/integration-tests/suites/udp_networkflow.go b/integration-tests/suites/udp_networkflow.go index adfd664d62..37c30ffb1c 100644 --- a/integration-tests/suites/udp_networkflow.go +++ b/integration-tests/suites/udp_networkflow.go @@ -5,6 +5,9 @@ import ( "strconv" "time" + sensorAPI "github.com/stackrox/rox/generated/internalapi/sensor" + "github.com/stackrox/rox/generated/storage" + "github.com/stackrox/collector/integration-tests/pkg/collector" "github.com/stackrox/collector/integration-tests/pkg/common" "github.com/stackrox/collector/integration-tests/pkg/config" @@ -29,7 +32,7 @@ type UdpNetworkFlow struct { type containerData struct { id string ip string - port uint16 + port uint32 } func (c *containerData) String() string { @@ -88,7 +91,7 @@ func (s *UdpNetworkFlow) TestUdpNetorkflow() { recvSyscalls := []string{"recvfrom", "recvmsg", "recvmmsg"} image := config.Images().QaImageByKey("qa-udp") - port := uint16(9090) + port := uint32(9090) for _, send := range sendSyscalls { for _, recv := range recvSyscalls { testName := fmt.Sprintf("%s_%s", send, recv) @@ -101,7 +104,7 @@ func (s *UdpNetworkFlow) TestUdpNetorkflow() { } } -func (s *UdpNetworkFlow) runTest(image, recv, send string, port uint16) { +func (s *UdpNetworkFlow) runTest(image, recv, send string, port uint32) { server := s.runServer(config.ContainerStartConfig{ Name: UDP_SERVER, Image: image, @@ -115,22 +118,25 @@ func (s *UdpNetworkFlow) runTest(image, recv, send string, port uint16) { }) log.Info("Server: %s - Client: %s\n", server.String(), client.String()) - // Expected client connection - clientConnection := types.NetworkInfo{ - LocalAddress: "", - RemoteAddress: fmt.Sprintf("%s:%d", server.ip, server.port), - Role: "ROLE_CLIENT", - SocketFamily: "SOCKET_FAMILY_UNKNOWN", - CloseTimestamp: types.NilTimestamp, + clientConnection := &sensorAPI.NetworkConnection{ + LocalAddress: nil, + RemoteAddress: types.CreateNetworkAddress(server.ip, "", server.port), + Protocol: storage.L4Protocol_L4_PROTOCOL_UDP, + Role: sensorAPI.ClientServerRole_ROLE_CLIENT, + SocketFamily: sensorAPI.SocketFamily_SOCKET_FAMILY_UNKNOWN, + ContainerId: client.id, + CloseTimestamp: nil, } // Expected server connection - serverConnection := types.NetworkInfo{ - LocalAddress: fmt.Sprintf(":%d", server.port), - RemoteAddress: client.ip, - Role: "ROLE_SERVER", - SocketFamily: "SOCKET_FAMILY_UNKNOWN", - CloseTimestamp: types.NilTimestamp, + serverConnection := &sensorAPI.NetworkConnection{ + LocalAddress: types.CreateNetworkAddress("", "", server.port), + RemoteAddress: types.CreateNetworkAddress(client.ip, "", 0), + Protocol: storage.L4Protocol_L4_PROTOCOL_UDP, + Role: sensorAPI.ClientServerRole_ROLE_SERVER, + SocketFamily: sensorAPI.SocketFamily_SOCKET_FAMILY_UNKNOWN, + ContainerId: server.id, + CloseTimestamp: nil, } s.Sensor().ExpectConnections(s.T(), client.id, 5*time.Second, clientConnection) @@ -141,25 +147,16 @@ func (s *UdpNetworkFlow) TestMultipleDestinations() { image := config.Images().QaImageByKey("qa-udp") servers := make([]containerData, CONTAINER_COUNT) - clientConnections := make([]types.NetworkInfo, CONTAINER_COUNT) + clientConnections := make([]*sensorAPI.NetworkConnection, CONTAINER_COUNT) for i := 0; i < CONTAINER_COUNT; i++ { name := fmt.Sprintf("%s-%d", UDP_SERVER, i) - port := uint16(9000 + i) + port := uint32(9000 + i) servers[i] = s.runServer(config.ContainerStartConfig{ Name: name, Image: image, Command: newServerCmd("recvfrom", port), }, port) log.Info("Server: %s\n", servers[i].String()) - - // Load the client connection collector has to send for this server. - clientConnections[i] = types.NetworkInfo{ - LocalAddress: "", - RemoteAddress: fmt.Sprintf("%s:%d", servers[i].ip, servers[i].port), - Role: "ROLE_CLIENT", - SocketFamily: "SOCKET_FAMILY_UNKNOWN", - CloseTimestamp: types.NilTimestamp, - } } // We give a big period here to ensure the syscall happens just once @@ -173,13 +170,28 @@ func (s *UdpNetworkFlow) TestMultipleDestinations() { }) log.Info("Client: %s\n", client.String()) + for i := 0; i < CONTAINER_COUNT; i++ { + // Load the client connection collector has to send for this server. + clientConnections[i] = &sensorAPI.NetworkConnection{ + LocalAddress: nil, + RemoteAddress: types.CreateNetworkAddress(servers[i].ip, "", servers[i].port), + Protocol: storage.L4Protocol_L4_PROTOCOL_UDP, + Role: sensorAPI.ClientServerRole_ROLE_CLIENT, + SocketFamily: sensorAPI.SocketFamily_SOCKET_FAMILY_UNKNOWN, + ContainerId: client.id, + CloseTimestamp: nil, + } + } + for _, server := range servers { - serverConnection := types.NetworkInfo{ - LocalAddress: fmt.Sprintf(":%d", server.port), - RemoteAddress: client.ip, - Role: "ROLE_SERVER", - SocketFamily: "SOCKET_FAMILY_UNKNOWN", - CloseTimestamp: types.NilTimestamp, + serverConnection := &sensorAPI.NetworkConnection{ + LocalAddress: types.CreateNetworkAddress("", "", server.port), + RemoteAddress: types.CreateNetworkAddress(client.ip, "", 0), + Protocol: storage.L4Protocol_L4_PROTOCOL_UDP, + Role: sensorAPI.ClientServerRole_ROLE_SERVER, + SocketFamily: sensorAPI.SocketFamily_SOCKET_FAMILY_UNKNOWN, + ContainerId: server.id, + CloseTimestamp: nil, } s.Sensor().ExpectConnections(s.T(), server.id, 5*time.Second, serverConnection) } @@ -188,7 +200,7 @@ func (s *UdpNetworkFlow) TestMultipleDestinations() { func (s *UdpNetworkFlow) TestMultipleSources() { image := config.Images().QaImageByKey("qa-udp") - port := uint16(9100) + port := uint32(9100) server := s.runServer(config.ContainerStartConfig{ Name: UDP_SERVER, @@ -198,7 +210,8 @@ func (s *UdpNetworkFlow) TestMultipleSources() { log.Info("Server: %s\n", server.String()) clients := make([]containerData, CONTAINER_COUNT) - serverConnections := make([]types.NetworkInfo, CONTAINER_COUNT) + serverConnections := make([]*sensorAPI.NetworkConnection, CONTAINER_COUNT) + clientConnections := make([]*sensorAPI.NetworkConnection, CONTAINER_COUNT) for i := 0; i < CONTAINER_COUNT; i++ { name := fmt.Sprintf("%s-%d", UDP_CLIENT, i) clients[i] = s.runClient(config.ContainerStartConfig{ @@ -210,37 +223,40 @@ func (s *UdpNetworkFlow) TestMultipleSources() { log.Info("Client: %s\n", clients[i].String()) // Load the server connection collector has to send for this client. - serverConnections[i] = types.NetworkInfo{ - LocalAddress: fmt.Sprintf(":%d", server.port), - RemoteAddress: clients[i].ip, - Role: "ROLE_SERVER", - SocketFamily: "SOCKET_FAMILY_UNKNOWN", - CloseTimestamp: types.NilTimestamp, + serverConnections[i] = &sensorAPI.NetworkConnection{ + LocalAddress: types.CreateNetworkAddress("", "", server.port), + RemoteAddress: types.CreateNetworkAddress(clients[i].ip, "", 0), + Protocol: storage.L4Protocol_L4_PROTOCOL_UDP, + Role: sensorAPI.ClientServerRole_ROLE_SERVER, + ContainerId: server.id, + SocketFamily: sensorAPI.SocketFamily_SOCKET_FAMILY_UNKNOWN, + CloseTimestamp: nil, + } + clientConnections[i] = &sensorAPI.NetworkConnection{ + LocalAddress: nil, + RemoteAddress: types.CreateNetworkAddress(server.ip, "", server.port), + Protocol: storage.L4Protocol_L4_PROTOCOL_UDP, + Role: sensorAPI.ClientServerRole_ROLE_CLIENT, + SocketFamily: sensorAPI.SocketFamily_SOCKET_FAMILY_UNKNOWN, + ContainerId: clients[i].id, + CloseTimestamp: nil, } } - clientConnection := types.NetworkInfo{ - LocalAddress: "", - RemoteAddress: fmt.Sprintf("%s:%d", server.ip, server.port), - Role: "ROLE_CLIENT", - SocketFamily: "SOCKET_FAMILY_UNKNOWN", - CloseTimestamp: types.NilTimestamp, - } - - for _, client := range clients { - s.Sensor().ExpectConnections(s.T(), client.id, 5*time.Second, clientConnection) + for i, client := range clients { + s.Sensor().ExpectConnections(s.T(), client.id, 5*time.Second, clientConnections[i]) } s.Sensor().ExpectConnections(s.T(), server.id, 5*time.Second, serverConnections...) } -func newServerCmd(recv string, port uint16) []string { +func newServerCmd(recv string, port uint32) []string { return []string{ "--syscall", recv, "--port", strconv.FormatUint(uint64(port), 10), } } -func (s *UdpNetworkFlow) runServer(cfg config.ContainerStartConfig, port uint16) containerData { +func (s *UdpNetworkFlow) runServer(cfg config.ContainerStartConfig, port uint32) containerData { return s.runContainer(cfg, port) } @@ -269,7 +285,7 @@ func (s *UdpNetworkFlow) runClient(cfg config.ContainerStartConfig) containerDat return s.runContainer(cfg, 0) } -func (s *UdpNetworkFlow) runContainer(cfg config.ContainerStartConfig, port uint16) containerData { +func (s *UdpNetworkFlow) runContainer(cfg config.ContainerStartConfig, port uint32) containerData { id, err := s.Executor().StartContainer(cfg) s.Require().NoError(err)