Tweak MDM detection query to return the proper enrollment when there are multiple entries (#29360)
This change is deceptively simple but helps us choose the right one in cases like #29042 where there are multiple enrollments in the registry. In this case the customer seems to have been using something like co-management(though even using their MDM we have not repro'd internally) which leads to 2 registry keys in the registry with a UPN node. I believe the way some MDM services handle unenroll can also leave the registry keys in this state. Either way, because of this, and the fact that we have a LIMIT 1 in the query, we were, in 50% of the cases where we had multiple keys, returning the less useful of the nodes from the query and because no Server URL was coming back we were treating it as if the host was not MDM enrolled and thus, not unenrolling it, and leading to enrollment failing. With this change we'll return the proper registry key which should allow us to, in the case of migration, properly unenroll the host and even in the case where a customer isn't using Fleet MDM will allow us to display the correct information from the registry. # Checklist for submitter If some of the following don't apply, delete the relevant line. <!-- Note that API documentation changes are now addressed by the product design team. --> - [x] Changes file added for user-visible changes in `changes/`, `orbit/changes/` or `ee/fleetd-chrome/changes`. See [Changes files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/guides/committing-changes.md#changes-files) for more information. - [x] Input data is properly validated, `SELECT *` is avoided, SQL injection is prevented (using placeholders for values in statements) - [x] Manual QA for all new/changed functionality
This commit is contained in:
@@ -0,0 +1 @@
|
||||
* Modified the Windows MDM detection query to more accurately detect existing MDM enrollment details on hosts with multiple enrollments
|
||||
@@ -198,38 +198,43 @@ WITH
|
||||
- Query:
|
||||
```sql
|
||||
WITH registry_keys AS (
|
||||
SELECT *
|
||||
FROM registry
|
||||
WHERE path LIKE 'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Enrollments\%%'
|
||||
),
|
||||
enrollment_info AS (
|
||||
SELECT
|
||||
MAX(CASE WHEN name = 'UPN' THEN data END) AS upn,
|
||||
MAX(CASE WHEN name = 'DiscoveryServiceFullURL' THEN data END) AS discovery_service_url,
|
||||
MAX(CASE WHEN name = 'ProviderID' THEN data END) AS provider_id,
|
||||
MAX(CASE WHEN name = 'EnrollmentState' THEN data END) AS state,
|
||||
MAX(CASE WHEN name = 'AADResourceID' THEN data END) AS aad_resource_id
|
||||
FROM registry_keys
|
||||
GROUP BY key
|
||||
),
|
||||
installation_info AS (
|
||||
SELECT data AS installation_type
|
||||
FROM registry
|
||||
WHERE path = 'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\InstallationType'
|
||||
LIMIT 1
|
||||
)
|
||||
SELECT
|
||||
e.aad_resource_id,
|
||||
e.discovery_service_url,
|
||||
e.provider_id,
|
||||
i.installation_type
|
||||
FROM installation_info i
|
||||
LEFT JOIN enrollment_info e ON e.upn IS NOT NULL
|
||||
-- coalesce to 'unknown' and keep that state in the list
|
||||
-- in order to account for hosts that might not have this
|
||||
-- key, and servers
|
||||
WHERE COALESCE(e.state, '0') IN ('0', '1', '2', '3')
|
||||
LIMIT 1;
|
||||
SELECT *
|
||||
FROM registry
|
||||
WHERE path LIKE 'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Enrollments\%%'
|
||||
),
|
||||
enrollment_info AS (
|
||||
SELECT
|
||||
MAX(CASE WHEN name = 'UPN' THEN data END) AS upn,
|
||||
MAX(CASE WHEN name = 'DiscoveryServiceFullURL' THEN data END) AS discovery_service_url,
|
||||
MAX(CASE WHEN name = 'ProviderID' THEN data END) AS provider_id,
|
||||
MAX(CASE WHEN name = 'EnrollmentState' THEN data END) AS state,
|
||||
MAX(CASE WHEN name = 'AADResourceID' THEN data END) AS aad_resource_id
|
||||
FROM registry_keys
|
||||
GROUP BY key
|
||||
),
|
||||
installation_info AS (
|
||||
SELECT data AS installation_type
|
||||
FROM registry
|
||||
WHERE path = 'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\InstallationType'
|
||||
LIMIT 1
|
||||
)
|
||||
SELECT
|
||||
e.aad_resource_id,
|
||||
e.discovery_service_url,
|
||||
e.provider_id,
|
||||
i.installation_type
|
||||
FROM installation_info i
|
||||
LEFT JOIN enrollment_info e ON e.upn IS NOT NULL
|
||||
-- coalesce to 'unknown' and keep that state in the list
|
||||
-- in order to account for hosts that might not have this
|
||||
-- key, and servers
|
||||
WHERE COALESCE(e.state, '0') IN ('0', '1', '2', '3')
|
||||
-- old enrollments that aren't completely cleaned up may still be aronud
|
||||
-- in the registry so we want to make sure we return the one with an actual
|
||||
-- discovery URL set if there is one. LENGTH is used here to prefer those
|
||||
-- with actual URLs over empty string/null if there are multiple
|
||||
ORDER BY LENGTH(e.discovery_service_url) DESC
|
||||
LIMIT 1;
|
||||
```
|
||||
|
||||
## munki_info
|
||||
|
||||
@@ -516,39 +516,44 @@ var extraDetailQueries = map[string]DetailQuery{
|
||||
//
|
||||
// [1]: https://learn.microsoft.com/en-us/graph/api/resources/intune-shared-enrollmentstate
|
||||
Query: `
|
||||
WITH registry_keys AS (
|
||||
SELECT *
|
||||
FROM registry
|
||||
WHERE path LIKE 'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Enrollments\%%'
|
||||
),
|
||||
enrollment_info AS (
|
||||
SELECT
|
||||
MAX(CASE WHEN name = 'UPN' THEN data END) AS upn,
|
||||
MAX(CASE WHEN name = 'DiscoveryServiceFullURL' THEN data END) AS discovery_service_url,
|
||||
MAX(CASE WHEN name = 'ProviderID' THEN data END) AS provider_id,
|
||||
MAX(CASE WHEN name = 'EnrollmentState' THEN data END) AS state,
|
||||
MAX(CASE WHEN name = 'AADResourceID' THEN data END) AS aad_resource_id
|
||||
FROM registry_keys
|
||||
GROUP BY key
|
||||
),
|
||||
installation_info AS (
|
||||
SELECT data AS installation_type
|
||||
FROM registry
|
||||
WHERE path = 'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\InstallationType'
|
||||
LIMIT 1
|
||||
)
|
||||
SELECT
|
||||
e.aad_resource_id,
|
||||
e.discovery_service_url,
|
||||
e.provider_id,
|
||||
i.installation_type
|
||||
FROM installation_info i
|
||||
LEFT JOIN enrollment_info e ON e.upn IS NOT NULL
|
||||
-- coalesce to 'unknown' and keep that state in the list
|
||||
-- in order to account for hosts that might not have this
|
||||
-- key, and servers
|
||||
WHERE COALESCE(e.state, '0') IN ('0', '1', '2', '3')
|
||||
LIMIT 1;
|
||||
WITH registry_keys AS (
|
||||
SELECT *
|
||||
FROM registry
|
||||
WHERE path LIKE 'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Enrollments\%%'
|
||||
),
|
||||
enrollment_info AS (
|
||||
SELECT
|
||||
MAX(CASE WHEN name = 'UPN' THEN data END) AS upn,
|
||||
MAX(CASE WHEN name = 'DiscoveryServiceFullURL' THEN data END) AS discovery_service_url,
|
||||
MAX(CASE WHEN name = 'ProviderID' THEN data END) AS provider_id,
|
||||
MAX(CASE WHEN name = 'EnrollmentState' THEN data END) AS state,
|
||||
MAX(CASE WHEN name = 'AADResourceID' THEN data END) AS aad_resource_id
|
||||
FROM registry_keys
|
||||
GROUP BY key
|
||||
),
|
||||
installation_info AS (
|
||||
SELECT data AS installation_type
|
||||
FROM registry
|
||||
WHERE path = 'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\InstallationType'
|
||||
LIMIT 1
|
||||
)
|
||||
SELECT
|
||||
e.aad_resource_id,
|
||||
e.discovery_service_url,
|
||||
e.provider_id,
|
||||
i.installation_type
|
||||
FROM installation_info i
|
||||
LEFT JOIN enrollment_info e ON e.upn IS NOT NULL
|
||||
-- coalesce to 'unknown' and keep that state in the list
|
||||
-- in order to account for hosts that might not have this
|
||||
-- key, and servers
|
||||
WHERE COALESCE(e.state, '0') IN ('0', '1', '2', '3')
|
||||
-- old enrollments that aren't completely cleaned up may still be aronud
|
||||
-- in the registry so we want to make sure we return the one with an actual
|
||||
-- discovery URL set if there is one. LENGTH is used here to prefer those
|
||||
-- with actual URLs over empty string/null if there are multiple
|
||||
ORDER BY LENGTH(e.discovery_service_url) DESC
|
||||
LIMIT 1;
|
||||
`,
|
||||
DirectIngestFunc: directIngestMDMWindows,
|
||||
Platforms: []string{"windows"},
|
||||
|
||||
Reference in New Issue
Block a user