Consider team settings when getting detail queries (#32141)

For #28133.

This fixes a bug that prevented TPM PIN detail queries to be included if
the required settings are only set at the Team level.
This commit is contained in:
Juan Fernandez
2025-08-22 11:14:32 -04:00
committed by GitHub
parent 3259bc0eb8
commit 9ec63e37a2
7 changed files with 120 additions and 67 deletions
+5 -5
View File
@@ -10794,7 +10794,7 @@ func (s *integrationTestSuite) TestDirectIngestScheduledQueryStats() {
App: config.AppConfig{
EnableScheduledQueryStats: true,
},
}, appConfig, &appConfig.Features, osquery_utils.Integrations{})
}, appConfig, &appConfig.Features, osquery_utils.Integrations{}, nil)
task := async.NewTask(s.ds, nil, clock.C, config.OsqueryConfig{})
err = detailQueries["scheduled_query_stats"].DirectTaskIngestFunc(
context.Background(),
@@ -10949,7 +10949,7 @@ func (s *integrationTestSuite) TestDirectIngestSoftwareWithLongFields() {
"installed_path": "C:\\Program Files\\Wireshark",
},
}
detailQueries := osquery_utils.GetDetailQueries(context.Background(), config.FleetConfig{}, appConfig, &appConfig.Features, osquery_utils.Integrations{})
detailQueries := osquery_utils.GetDetailQueries(context.Background(), config.FleetConfig{}, appConfig, &appConfig.Features, osquery_utils.Integrations{}, nil)
err = detailQueries["software_windows"].DirectIngestFunc(
context.Background(),
log.NewNopLogger(),
@@ -11085,7 +11085,7 @@ func (s *integrationTestSuite) TestDirectIngestSoftwareWithInvalidFields() {
}
var w1 bytes.Buffer
logger1 := log.NewJSONLogger(&w1)
detailQueries := osquery_utils.GetDetailQueries(context.Background(), config.FleetConfig{}, appConfig, &appConfig.Features, osquery_utils.Integrations{})
detailQueries := osquery_utils.GetDetailQueries(context.Background(), config.FleetConfig{}, appConfig, &appConfig.Features, osquery_utils.Integrations{}, nil)
err = detailQueries["software_windows"].DirectIngestFunc(
context.Background(),
logger1,
@@ -11120,7 +11120,7 @@ func (s *integrationTestSuite) TestDirectIngestSoftwareWithInvalidFields() {
"last_opened_at": "foobar",
},
}
detailQueries = osquery_utils.GetDetailQueries(context.Background(), config.FleetConfig{}, appConfig, &appConfig.Features, osquery_utils.Integrations{})
detailQueries = osquery_utils.GetDetailQueries(context.Background(), config.FleetConfig{}, appConfig, &appConfig.Features, osquery_utils.Integrations{}, nil)
var w2 bytes.Buffer
logger2 := log.NewJSONLogger(&w2)
err = detailQueries["software_windows"].DirectIngestFunc(
@@ -11160,7 +11160,7 @@ func (s *integrationTestSuite) TestDirectIngestSoftwareWithInvalidFields() {
}
var w3 bytes.Buffer
logger3 := log.NewJSONLogger(&w3)
detailQueries = osquery_utils.GetDetailQueries(context.Background(), config.FleetConfig{}, appConfig, &appConfig.Features, osquery_utils.Integrations{})
detailQueries = osquery_utils.GetDetailQueries(context.Background(), config.FleetConfig{}, appConfig, &appConfig.Features, osquery_utils.Integrations{}, nil)
err = detailQueries["software_windows"].DirectIngestFunc(
context.Background(),
logger3,
+2 -2
View File
@@ -5487,7 +5487,7 @@ func (s *integrationMDMTestSuite) TestSSO() {
ac, err := s.ds.AppConfig(context.Background())
require.NoError(t, err)
detailQueries := osquery_utils.GetDetailQueries(context.Background(), config.FleetConfig{}, ac, &ac.Features, osquery_utils.Integrations{})
detailQueries := osquery_utils.GetDetailQueries(context.Background(), config.FleetConfig{}, ac, &ac.Features, osquery_utils.Integrations{}, nil)
// simulate osquery reporting mdm information
rows := []map[string]string{
@@ -5831,7 +5831,7 @@ func (s *integrationMDMTestSuite) TestSSOWithSCIM() {
ac, err := s.ds.AppConfig(context.Background())
require.NoError(t, err)
detailQueries := osquery_utils.GetDetailQueries(context.Background(), config.FleetConfig{}, ac, &ac.Features, osquery_utils.Integrations{})
detailQueries := osquery_utils.GetDetailQueries(context.Background(), config.FleetConfig{}, ac, &ac.Features, osquery_utils.Integrations{}, nil)
// simulate osquery reporting mdm information, doesn't change anything
rows := []map[string]string{
+62 -12
View File
@@ -176,9 +176,15 @@ func (svc *Service) EnrollAgent(ctx context.Context, enrollSecret, hostIdentifie
}
// Save enrollment details if provided
detailQueries := osquery_utils.GetDetailQueries(ctx, svc.config, appConfig, features, osquery_utils.Integrations{
ConditionalAccessMicrosoft: false, // here we are just using a few ingestion functions, so no need to set.
})
detailQueries := osquery_utils.GetDetailQueries(
ctx,
svc.config,
appConfig,
features,
osquery_utils.Integrations{
ConditionalAccessMicrosoft: false, // here we are just using a few ingestion functions, so no need to set.
}, nil, // Ok ... the following queries do not need the Team's MDM config
)
save := false
if r, ok := hostDetails["os_version"]; ok {
err := detailQueries["os_version"].IngestFunc(ctx, svc.logger, host, []map[string]string{r})
@@ -722,12 +728,25 @@ func (svc *Service) detailQueriesForHost(ctx context.Context, host *fleet.Host)
return nil, nil, ctxerr.Wrap(ctx, err, "read host features")
}
var mdmTeamConfig *fleet.TeamMDM
if appConfig != nil && appConfig.MDM.EnabledAndConfigured && host.TeamID != nil {
mdmTeamConfig, err = svc.ds.TeamMDMConfig(ctx, *host.TeamID)
if err != nil {
return nil, nil, ctxerr.Wrap(ctx, err, "reading MDM Team Config")
}
}
queries = make(map[string]string)
discovery = make(map[string]string)
detailQueries := osquery_utils.GetDetailQueries(ctx, svc.config, appConfig, features, osquery_utils.Integrations{
ConditionalAccessMicrosoft: svc.hostRequiresConditionalAccessMicrosoftIngestion(ctx, host),
})
detailQueries := osquery_utils.GetDetailQueries(
ctx,
svc.config,
appConfig,
features,
osquery_utils.Integrations{
ConditionalAccessMicrosoft: svc.hostRequiresConditionalAccessMicrosoftIngestion(ctx, host),
}, mdmTeamConfig)
for name, query := range detailQueries {
if criticalQueriesOnly && !criticalDetailQueries[name] {
continue
@@ -1589,9 +1608,24 @@ func (svc *Service) directIngestDetailQuery(ctx context.Context, host *fleet.Hos
return false, newOsqueryError("ingest detail query: " + err.Error())
}
detailQueries := osquery_utils.GetDetailQueries(ctx, svc.config, appConfig, features, osquery_utils.Integrations{
ConditionalAccessMicrosoft: svc.hostRequiresConditionalAccessMicrosoftIngestion(ctx, host),
})
var mdmTeamConfig *fleet.TeamMDM
if appConfig != nil && appConfig.MDM.EnabledAndConfigured && host.TeamID != nil {
mdmTeamConfig, err = svc.ds.TeamMDMConfig(ctx, *host.TeamID)
if err != nil {
return false, newOsqueryError("ingest detail query: " + err.Error())
}
}
detailQueries := osquery_utils.GetDetailQueries(
ctx,
svc.config,
appConfig,
features,
osquery_utils.Integrations{
ConditionalAccessMicrosoft: svc.hostRequiresConditionalAccessMicrosoftIngestion(ctx, host),
},
mdmTeamConfig,
)
query, ok := detailQueries[name]
if !ok {
return false, newOsqueryError("unknown detail query " + name)
@@ -1733,9 +1767,25 @@ func (svc *Service) ingestDetailQuery(ctx context.Context, host *fleet.Host, nam
return newOsqueryError("ingest detail query: " + err.Error())
}
detailQueries := osquery_utils.GetDetailQueries(ctx, svc.config, appConfig, features, osquery_utils.Integrations{
ConditionalAccessMicrosoft: svc.hostRequiresConditionalAccessMicrosoftIngestion(ctx, host),
})
var mdmTeamConfig *fleet.TeamMDM
if appConfig != nil && appConfig.MDM.EnabledAndConfigured && host.TeamID != nil {
mdmTeamConfig, err = svc.ds.TeamMDMConfig(ctx, *host.TeamID)
if err != nil {
return newOsqueryError("ingest detail query: " + err.Error())
}
}
detailQueries := osquery_utils.GetDetailQueries(
ctx,
svc.config,
appConfig,
features,
osquery_utils.Integrations{
ConditionalAccessMicrosoft: svc.hostRequiresConditionalAccessMicrosoftIngestion(ctx, host),
},
mdmTeamConfig,
)
query, ok := detailQueries[name]
if !ok {
return newOsqueryError("unknown detail query " + name)
+4 -10
View File
@@ -256,16 +256,10 @@ func TestAgentOptionsForHost(t *testing.T) {
assert.JSONEq(t, `{"foo":"override2"}`, string(opt))
}
var allDetailQueries = osquery_utils.GetDetailQueries(
context.Background(),
config.FleetConfig{Vulnerabilities: config.VulnerabilitiesConfig{DisableWinOSVulnerabilities: true}},
nil,
&fleet.Features{
EnableHostUsers: true,
EnableSoftwareInventory: true,
},
osquery_utils.Integrations{},
)
var allDetailQueries = osquery_utils.GetDetailQueries(context.Background(), config.FleetConfig{Vulnerabilities: config.VulnerabilitiesConfig{DisableWinOSVulnerabilities: true}}, nil, &fleet.Features{
EnableHostUsers: true,
EnableSoftwareInventory: true,
}, osquery_utils.Integrations{}, nil)
func expectedDetailQueriesForPlatform(platform string) map[string]osquery_utils.DetailQuery {
queries := make(map[string]osquery_utils.DetailQuery)
+14 -16
View File
@@ -16,24 +16,22 @@ import (
)
func main() {
detailQueriesMap := osquery_utils.GetDetailQueries(context.Background(),
config.FleetConfig{
Vulnerabilities: config.VulnerabilitiesConfig{
DisableWinOSVulnerabilities: false,
},
App: config.AppConfig{
EnableScheduledQueryStats: true,
},
detailQueriesMap := osquery_utils.GetDetailQueries(context.Background(), config.FleetConfig{
Vulnerabilities: config.VulnerabilitiesConfig{
DisableWinOSVulnerabilities: false,
},
&fleet.AppConfig{MDM: fleet.MDM{EnabledAndConfigured: true, WindowsEnabledAndConfigured: true}},
&fleet.Features{
EnableSoftwareInventory: true,
EnableHostUsers: true,
App: config.AppConfig{
EnableScheduledQueryStats: true,
},
osquery_utils.Integrations{
ConditionalAccessMicrosoft: true,
},
)
}, &fleet.AppConfig{MDM: fleet.MDM{
EnabledAndConfigured: true,
WindowsEnabledAndConfigured: true,
}}, &fleet.Features{
EnableSoftwareInventory: true,
EnableHostUsers: true,
}, osquery_utils.Integrations{
ConditionalAccessMicrosoft: true,
}, nil)
var b strings.Builder
b.WriteString(`<!-- DO NOT EDIT. This document is automatically generated. -->
+16 -5
View File
@@ -2645,6 +2645,7 @@ func GetDetailQueries(
appConfig *fleet.AppConfig,
features *fleet.Features,
integrations Integrations,
teamMDMConfig *fleet.TeamMDM,
) map[string]DetailQuery {
generatedMap := make(map[string]DetailQuery)
for key, query := range hostDetailQueries {
@@ -2689,12 +2690,22 @@ func GetDetailQueries(
generatedMap[key] = query
}
if appConfig.MDM.WindowsEnabledAndConfigured &&
appConfig.MDM.EnableDiskEncryption.Value &&
appConfig.MDM.RequireBitLockerPIN.Value {
// Add TPM PIN Queries iff Win MDM is enabled and ready to go
if appConfig.MDM.WindowsEnabledAndConfigured {
enableDiskEncryption := appConfig.MDM.EnableDiskEncryption.Value
requireTPMPin := appConfig.MDM.RequireBitLockerPIN.Value
for key, query := range tpmPINQueries {
generatedMap[key] = query
// If the host is part of a team, we need to look at the related team config
// instead of the App config ...
if teamMDMConfig != nil {
enableDiskEncryption = teamMDMConfig.EnableDiskEncryption
requireTPMPin = teamMDMConfig.RequireBitLockerPIN
}
if enableDiskEncryption && requireTPMPin {
for key, query := range tpmPINQueries {
generatedMap[key] = query
}
}
}
}
+17 -17
View File
@@ -70,7 +70,7 @@ func TestDetailQueryNetworkInterfaces(t *testing.T) {
var initialHost fleet.Host
host := initialHost
ingest := GetDetailQueries(context.Background(), config.FleetConfig{}, nil, nil, Integrations{})["network_interface_unix"].IngestFunc
ingest := GetDetailQueries(context.Background(), config.FleetConfig{}, nil, nil, Integrations{}, nil)["network_interface_unix"].IngestFunc
assert.NoError(t, ingest(context.Background(), log.NewNopLogger(), &host, nil))
assert.Equal(t, initialHost, host)
@@ -116,7 +116,7 @@ func TestDetailQueryScheduledQueryStats(t *testing.T) {
return nil
}
ingest := GetDetailQueries(context.Background(), config.FleetConfig{App: config.AppConfig{EnableScheduledQueryStats: true}}, nil, nil, Integrations{})["scheduled_query_stats"].DirectTaskIngestFunc
ingest := GetDetailQueries(context.Background(), config.FleetConfig{App: config.AppConfig{EnableScheduledQueryStats: true}}, nil, nil, Integrations{}, nil)["scheduled_query_stats"].DirectTaskIngestFunc
ctx := context.Background()
assert.NoError(t, ingest(ctx, log.NewNopLogger(), &host, task, nil))
@@ -295,7 +295,7 @@ func sortedKeysCompare(t *testing.T, m map[string]DetailQuery, expectedKeys []st
}
func TestGetDetailQueries(t *testing.T) {
queriesNoConfig := GetDetailQueries(context.Background(), config.FleetConfig{}, nil, nil, Integrations{})
queriesNoConfig := GetDetailQueries(context.Background(), config.FleetConfig{}, nil, nil, Integrations{}, nil)
baseQueries := []string{
"network_interface_unix",
@@ -330,16 +330,16 @@ func TestGetDetailQueries(t *testing.T) {
require.Len(t, queriesNoConfig, len(baseQueries))
sortedKeysCompare(t, queriesNoConfig, baseQueries)
queriesWithoutWinOSVuln := GetDetailQueries(context.Background(), config.FleetConfig{Vulnerabilities: config.VulnerabilitiesConfig{DisableWinOSVulnerabilities: true}}, nil, nil, Integrations{})
queriesWithoutWinOSVuln := GetDetailQueries(context.Background(), config.FleetConfig{Vulnerabilities: config.VulnerabilitiesConfig{DisableWinOSVulnerabilities: true}}, nil, nil, Integrations{}, nil)
require.Len(t, queriesWithoutWinOSVuln, 26)
queriesWithUsers := GetDetailQueries(context.Background(), config.FleetConfig{App: config.AppConfig{EnableScheduledQueryStats: true}}, nil, &fleet.Features{EnableHostUsers: true}, Integrations{})
queriesWithUsers := GetDetailQueries(context.Background(), config.FleetConfig{App: config.AppConfig{EnableScheduledQueryStats: true}}, nil, &fleet.Features{EnableHostUsers: true}, Integrations{}, nil)
qs := baseQueries
qs = append(qs, "users", "users_chrome", "scheduled_query_stats")
require.Len(t, queriesWithUsers, len(qs))
sortedKeysCompare(t, queriesWithUsers, qs)
queriesWithUsersAndSoftware := GetDetailQueries(context.Background(), config.FleetConfig{App: config.AppConfig{EnableScheduledQueryStats: true}}, nil, &fleet.Features{EnableHostUsers: true, EnableSoftwareInventory: true}, Integrations{})
queriesWithUsersAndSoftware := GetDetailQueries(context.Background(), config.FleetConfig{App: config.AppConfig{EnableScheduledQueryStats: true}}, nil, &fleet.Features{EnableHostUsers: true, EnableSoftwareInventory: true}, Integrations{}, nil)
qs = baseQueries
qs = append(qs, "users", "users_chrome", "software_macos", "software_linux", "software_windows", "software_vscode_extensions",
"software_chrome", "software_python_packages", "software_python_packages_with_users_dir", "scheduled_query_stats", "software_macos_firefox", "software_macos_codesign", "software_windows_last_opened_at", "software_deb_last_opened_at", "software_rpm_last_opened_at")
@@ -359,14 +359,14 @@ func TestGetDetailQueries(t *testing.T) {
ac := fleet.AppConfig{}
ac.MDM.EnabledAndConfigured = true
// windows mdm is disabled by default, windows mdm queries should not be present
gotQueries := GetDetailQueries(context.Background(), config.FleetConfig{}, &ac, nil, Integrations{})
gotQueries := GetDetailQueries(context.Background(), config.FleetConfig{}, &ac, nil, Integrations{}, nil)
wantQueries := baseQueries
wantQueries = append(wantQueries, mdmQueriesBase...)
require.Len(t, gotQueries, len(wantQueries))
sortedKeysCompare(t, gotQueries, wantQueries)
// enable windows mdm, windows mdm queries should be present
ac.MDM.WindowsEnabledAndConfigured = true
gotQueries = GetDetailQueries(context.Background(), config.FleetConfig{}, &ac, nil, Integrations{})
gotQueries = GetDetailQueries(context.Background(), config.FleetConfig{}, &ac, nil, Integrations{}, nil)
wantQueries = append(wantQueries, mdmQueriesWindows...)
require.Len(t, gotQueries, len(wantQueries))
sortedKeysCompare(t, gotQueries, wantQueries)
@@ -414,7 +414,7 @@ func TestGetDetailQueries(t *testing.T) {
for _, tt := range testCases {
t.Run(tt.name, func(t *testing.T) {
got := GetDetailQueries(context.Background(), config.FleetConfig{}, &tt.ac, nil, Integrations{})
got := GetDetailQueries(context.Background(), config.FleetConfig{}, &tt.ac, nil, Integrations{}, nil)
for _, name := range tt.want {
_, ok := got[name]
require.True(t, ok)
@@ -427,7 +427,7 @@ func TestDetailQueriesOSVersionUnixLike(t *testing.T) {
var initialHost fleet.Host
host := initialHost
ingest := GetDetailQueries(context.Background(), config.FleetConfig{}, nil, nil, Integrations{})["os_version"].IngestFunc
ingest := GetDetailQueries(context.Background(), config.FleetConfig{}, nil, nil, Integrations{}, nil)["os_version"].IngestFunc
assert.NoError(t, ingest(context.Background(), log.NewNopLogger(), &host, nil))
assert.Equal(t, initialHost, host)
@@ -501,7 +501,7 @@ func TestDetailQueriesOSVersionWindows(t *testing.T) {
var initialHost fleet.Host
host := initialHost
ingest := GetDetailQueries(context.Background(), config.FleetConfig{}, nil, nil, Integrations{})["os_version_windows"].IngestFunc
ingest := GetDetailQueries(context.Background(), config.FleetConfig{}, nil, nil, Integrations{}, nil)["os_version_windows"].IngestFunc
assert.NoError(t, ingest(context.Background(), log.NewNopLogger(), &host, nil))
assert.Equal(t, initialHost, host)
@@ -556,7 +556,7 @@ func TestDetailQueriesOSVersionChrome(t *testing.T) {
var initialHost fleet.Host
host := initialHost
ingest := GetDetailQueries(context.Background(), config.FleetConfig{}, nil, nil, Integrations{})["os_version"].IngestFunc
ingest := GetDetailQueries(context.Background(), config.FleetConfig{}, nil, nil, Integrations{}, nil)["os_version"].IngestFunc
assert.NoError(t, ingest(context.Background(), log.NewNopLogger(), &host, nil))
assert.Equal(t, initialHost, host)
@@ -1376,29 +1376,29 @@ func TestDirectIngestOSUnixLike(t *testing.T) {
}
func TestAppConfigReplaceQuery(t *testing.T) {
queries := GetDetailQueries(context.Background(), config.FleetConfig{}, nil, &fleet.Features{EnableHostUsers: true}, Integrations{})
queries := GetDetailQueries(context.Background(), config.FleetConfig{}, nil, &fleet.Features{EnableHostUsers: true}, Integrations{}, nil)
originalQuery := queries["users"].Query
replacementMap := make(map[string]*string)
replacementMap["users"] = ptr.String("select 1 from blah")
queries = GetDetailQueries(context.Background(), config.FleetConfig{}, nil, &fleet.Features{EnableHostUsers: true, DetailQueryOverrides: replacementMap}, Integrations{})
queries = GetDetailQueries(context.Background(), config.FleetConfig{}, nil, &fleet.Features{EnableHostUsers: true, DetailQueryOverrides: replacementMap}, Integrations{}, nil)
assert.NotEqual(t, originalQuery, queries["users"].Query)
assert.Equal(t, "select 1 from blah", queries["users"].Query)
replacementMap["users"] = nil
queries = GetDetailQueries(context.Background(), config.FleetConfig{}, nil, &fleet.Features{EnableHostUsers: true, DetailQueryOverrides: replacementMap}, Integrations{})
queries = GetDetailQueries(context.Background(), config.FleetConfig{}, nil, &fleet.Features{EnableHostUsers: true, DetailQueryOverrides: replacementMap}, Integrations{}, nil)
_, exists := queries["users"]
assert.False(t, exists)
// put the query back again
replacementMap["users"] = ptr.String("select 1 from blah")
queries = GetDetailQueries(context.Background(), config.FleetConfig{}, nil, &fleet.Features{EnableHostUsers: true, DetailQueryOverrides: replacementMap}, Integrations{})
queries = GetDetailQueries(context.Background(), config.FleetConfig{}, nil, &fleet.Features{EnableHostUsers: true, DetailQueryOverrides: replacementMap}, Integrations{}, nil)
assert.NotEqual(t, originalQuery, queries["users"].Query)
assert.Equal(t, "select 1 from blah", queries["users"].Query)
// empty strings are also ignored
replacementMap["users"] = ptr.String("")
queries = GetDetailQueries(context.Background(), config.FleetConfig{}, nil, &fleet.Features{EnableHostUsers: true, DetailQueryOverrides: replacementMap}, Integrations{})
queries = GetDetailQueries(context.Background(), config.FleetConfig{}, nil, &fleet.Features{EnableHostUsers: true, DetailQueryOverrides: replacementMap}, Integrations{}, nil)
_, exists = queries["users"]
assert.False(t, exists)
}