FYI: This is a special use case.
The import_collection describes a logic:
When the client id is not specified or “auto”, the client is calculated according to the following rules:
If the collection contains a client id (i.e. it is a flow export), and the client id exists on this server, then we use that client id.
If the collection contains a hostname and that hostname exists on this server, then we use the client id corresponding to this host.
If the collection contains a host id, we create a client id based on that.
Otherwise we create a random client id.
This logic is only correct for a collection, and partially work for a hunt.
Given the use case where the clients already exists on the server, importing a hunt will create duplicate clients on the server if the clientId is different. In other words, it will not perform this step _ If the collection contains a hostname and that hostname exists on this server, then we use the client id corresponding to this host._
This use case happens if multiple clients are remapped and started as virtual clients (which will give them a new clientId), and then the hunt is imported afterwards. This mismatch in clientId will cause the hunt logic to create a new client instead of matching the clients by hostname, creating duplicates.
The proposed solution is to change the code in import.go to support the above logic, making the hunt import similar to the collection logic. My plan is to create a PR with this change.
This is the proposed fix that will be set in the importHunt function:
// --- FIX START ---
// Attempt to map the client by hostname if the ID is unknown.
// 1. Check if the Client ID exists
client_manager, err := services.GetClientInfoManager(config_obj)
if err == nil {
_, err := client_manager.Get(ctx, client_info.ClientId)
// 2. Client ID not found locally.
if err != nil && client_info.Hostname != "" {
// 3. Search for the hostname
indexer, err := services.GetIndexer(config_obj)
if err == nil {
search_resp, err := indexer.SearchClients(ctx, config_obj,
&api_proto.SearchClientsRequest{
Query: "host:" + client_info.Hostname,
}, "")
if err == nil {
for _, item := range search_resp.Items {
// 4. Found a match? Merge with existing client.
if strings.EqualFold(item.OsInfo.Hostname, client_info.Hostname) {
scope.Log("Mapping hunt client %v to existing client %v (%v)",
client_info.ClientId, item.ClientId, client_info.Hostname)
client_info.ClientId = item.ClientId
break
}
}
}
}
}
}
// If neither ID nor Hostname matched, we fall through to checkClientIdExists
// which will create a new client using the ID from the zip.
// --- FIX END ---
Verification. I have verified that the change works by changing the import.go and building from source. Running the import_collection did not create duplicate clients on the server when the clients were already remapped. I have also tested that the normal logic of importing a hunt when the clients does not exists on the server works as expected. I have not tested the logic that if the clientId already exists on the server it will "merge" the hunt data with this client.
FYI: This is a special use case.
The import_collection describes a logic:
This logic is only correct for a collection, and partially work for a hunt.
Given the use case where the clients already exists on the server, importing a hunt will create duplicate clients on the server if the clientId is different. In other words, it will not perform this step _ If the collection contains a hostname and that hostname exists on this server, then we use the client id corresponding to this host._
This use case happens if multiple clients are remapped and started as virtual clients (which will give them a new clientId), and then the hunt is imported afterwards. This mismatch in clientId will cause the hunt logic to create a new client instead of matching the clients by hostname, creating duplicates.
The proposed solution is to change the code in import.go to support the above logic, making the hunt import similar to the collection logic. My plan is to create a PR with this change.
This is the proposed fix that will be set in the
importHuntfunction:Verification. I have verified that the change works by changing the import.go and building from source. Running the import_collection did not create duplicate clients on the server when the clients were already remapped. I have also tested that the normal logic of importing a hunt when the clients does not exists on the server works as expected. I have not tested the logic that if the clientId already exists on the server it will "merge" the hunt data with this client.