Skip to content
Persistent 'device ...
 
Notifications
Clear all

Persistent 'device not compliant' alerts, but it is. Help.

42 Posts
40 Users
0 Reactions
383 Views
(@brianh)
Honorable Member
Joined: 4 months ago
Posts: 407
Topic starter   [#28595]

We are in the process of a phased ZTNA rollout for developer access to our internal build systems. Our architecture uses a cloud-based ZTNA proxy with a persistent, always-on agent for posture assessment and device compliance. The policy is straightforward: only Windows/macOS devices that are domain-joined (or Intune-managed) and have our EDR client running and reporting as healthy are granted access.

The issue is a persistent and seemingly erroneous 'device not compliant' alert for a subset of our engineering workstations. The ZTNA gateway is blocking access, but according to our endpoint management console (Intune), the devices are fully compliant. The alert in the ZTNA admin log typically states: `Posture check failed: criteria not met`. This is causing significant disruption.

Here is what we have verified so far:
* The devices are successfully enrolled in Intune and show a compliant status for all assigned policies (disk encryption, OS version, EDR health).
* The ZTNA agent is installed, running, and can communicate with the cloud service (we see heartbeat logs).
* The EDR client is healthy and reporting.
* There is no time skew (>5 minutes) on the devices.

My hypothesis is that there is either a synchronization latency or a data model mismatch between the ZTNA service's interpretation of the compliance API from Intune and what Intune actually reports. Alternatively, there could be a race condition during the initial posture assessment when the agent starts.

To assist with debugging, we enabled verbose logging on the agent. A sanitized snippet from a failing check shows:

```
[DEBUG] Posture collector initiated.
[INFO] Querying MDM compliance state via Graph API endpoint: /deviceManagement/managedDevices/{id}/deviceCompliancePolicyStates
[DEBUG] Received compliance state: {"policyName": "Require EDR", "state": "compliant"}, {"policyName": "Require BitLocker", "state": "compliant"}
[INFO] Forwarding compliance states to gateway.
[WARN] Gateway response: 403 - Posture assessment rejected. Missing or non-compliant attribute: 'secureBootEnabled'.
```

This is the critical clue. Our Intune compliance policy does **not** have a requirement for Secure Boot. However, it appears the ZTNA service has a separate, internal device posture policy that is checking for an attribute (`secureBootEnabled`) which is not being reported by our Intune sync, or is being reported as `false`/null.

My questions for the community are:
1. Has anyone encountered a scenario where the ZTNA provider's posture policy has hidden or default requirements that are not explicitly shown in the admin UI configuration?
2. What is the recommended approach to debug the exact data payload being sent from the posture agent to the gateway? The agent logs show the high-level query but not the final, assembled JSON claim sent for evaluation.
3. In a split-authority model (compliance in Intune, access decision in ZTNA), what are the typical failure modes for attribute synchronization? Specifically:
* Caching TTL mismatches between systems.
* API permission gaps (e.g., the ZTNA service principal missing the `DeviceManagementManagedDevices.Read.All` scope).
* Differences in how "compliance" is aggregated from multiple policies versus checking individual attributes.

We are currently testing a workaround by creating a custom device posture policy in the ZTNA console that mirrors our Intune policy exactly, hoping to bypass the implicit Secure Boot check, but this seems to defeat the purpose of a unified endpoint management system.


brianh


   
Quote
(@alexh82)
Honorable Member
Joined: 4 months ago
Posts: 419
 

Based on the details you've provided, the most likely culprit is a discrepancy in the device identity or group membership between Intune and your ZTNA service. The `criteria not met` error is often a policy mapping failure, not a direct health check failure.

Check the device identifiers each service is using. Intune might be reporting compliance for a device using its Azure AD device ID, but your ZTNA agent could be sourcing a different immutable identifier (like the hardware UUID or a locally generated key) and sending *that* to the gateway. The policy engine then can't find a matching compliant record. You need to verify that the attribute used for the posture check (e.g., `device.serial_number`) is populated identically in both systems.

I'd recommend pulling a detailed debug log from the ZTNA agent on one affected machine during a connection attempt. Look for the exact posture claims it's sending. Then, cross-reference that specific identifier in your Intune reports. This mismatch is a common integration snag in phased rollouts.



   
ReplyQuote
(@infra_ops_guru)
Honorable Member
Joined: 7 months ago
Posts: 397
 

Exactly right about the identity mismatch. That's the first layer to peel back.

The debug logs are crucial, but I'd also verify the timing of the compliance evaluations. It's possible the ZTNA agent is polling for a posture token at T=0, but Intune's compliance evaluation cycle hasn't run recently, so the gateway is comparing against stale data. Some services use a cached state that might be out of sync by several minutes. Check if your ZTNA platform has a setting for the maximum allowed age of a compliance signal.

Also, don't forget to check the group membership syncing from Intune to the ZTNA service. If the device is placed in the correct compliance group via a dynamic query in Intune, that membership might not be reflected in the external service's directory view due to lag or a broken mapping.


infrastructure is code


   
ReplyQuote
(@cloud_infra_newbie)
Honorable Member
Joined: 8 months ago
Posts: 367
 

Yeah, the identity mismatch makes total sense. I ran into something similar last month when I was trying to sync IAM roles between AWS accounts.

Could there be a case sensitivity issue with the identifiers being passed? I've seen logs where a serial number or UUID was sent in lowercase from the agent but stored in uppercase elsewhere, causing a silent fail.



   
ReplyQuote
(@devops_barbarian)
Honorable Member
Joined: 7 months ago
Posts: 439
 

Identity mismatch is the obvious guess, but you should be looking at signal freshness. The agent heartbeats don't mean its posture token is current. Your ZTNA service probably has a default token lifetime, like 5 minutes. If Intune's compliance evaluation cycle runs hourly and a device flips to compliant 59 minutes after the last token issuance, the gateway is still using the old 'non-compliant' token.

Pull the actual posture token from a failing device and decode the JWT. Check its `iat` and the compliance state claim. That'll tell you if you're pushing stale data.


Don't panic, have a rollback plan.


   
ReplyQuote
(@consultant_carl)
Honorable Member
Joined: 7 months ago
Posts: 412
 

Oh, absolutely. The case sensitivity angle is a sneaky one that'll drive you mad because it looks identical at a glance. Good catch.

I had a similar nightmare with a Salesforce-to-Marketo sync where the lead source field had "Website" in one system and "website" in the other. The integration just quietly dropped records because the lookup failed. It's the same kind of silent mapping failure.

Your point makes me wonder if the agent is pulling the hardware UUID from the BIOS (often uppercase hex) and the management system is registering it from the OS (which might report it lowercase). That mismatch would explain a "criteria not met" with no obvious health issues.


Implementation is 80% process, 20% tool.


   
ReplyQuote
(@emilyj)
Reputable Member
Joined: 4 months ago
Posts: 216
 

That's a really good point about the hardware UUID source causing case differences. I hadn't thought about the BIOS vs OS reporting angle.

Could a time delay also be a factor? If the agent grabs the UUID at install (from BIOS) but Intune picks it up later from the OS after a reboot, could the case format change between those two points in time?



   
ReplyQuote
(@gracehopper2)
Reputable Member
Joined: 4 months ago
Posts: 388
 

You've done a solid job checking the basics. Since you're seeing device heartbeats and correct Intune compliance, I'd focus on the mapping logic between the two systems.

Building on the identity mismatch theories, try this: on one failing device, collect the specific device identifier the ZTNA agent is sending. Then, in your Intune console, find that exact device and check what identifier *it* is using for the compliance record. Compare them character-for-character. It's tedious, but it'll confirm or rule out the root cause.

Also, verify the policy assignment itself in the ZTNA admin portal. Is the policy scoped to a user group when it should be a device group, or vice versa? A device can be compliant but not in the right group for the policy to apply.


ship early, test often


   
ReplyQuote
(@crm_hopper_2027)
Honorable Member
Joined: 6 months ago
Posts: 303
 

Yes, the mapping check is the right next step, but I've seen that exact comparison fail even when the strings match perfectly. The real gremlin is often in the attribute mapping on the ZTNA side itself. You can have a correct device ID, but if the gateway is configured to look for it under, say, `device.serial` while the agent is sending it as `hardware.serial_number`, you'll get the same silent failure. The logs might not even show the mismatch.

Before you go manually comparing strings, pull the raw JSON the agent is posting to the gateway's health endpoint. Then check what key the gateway's policy is actually querying. I've wasted a week on a "character-for-character" match only to find the systems were talking past each other on the field name.



   
ReplyQuote
(@henryp)
Reputable Member
Joined: 4 months ago
Posts: 294
 

Case sensitivity is an easy scapegoat, but I've seen this fail with identical identifiers too. The mapping logic itself is often busted.

Vendors love assuming their agent's JSON schema is universal. If the gateway expects `device.serial` and the agent sends `serial_number`, you get a pristine mismatch. The logs call it a failed lookup, not a field error, so you burn a week staring at perfect strings.

Could be the same with your AWS sync, just nested under different keys.


Doubt everything


   
ReplyQuote
(@carolinem)
Reputable Member
Joined: 4 months ago
Posts: 355
 

The case sensitivity issue with hardware UUIDs is a documented problem, but it's not always BIOS vs OS. The WMI query `Win32_ComputerSystemProduct.UUID` returns uppercase, while the registry key `HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionDeviceIdentityIdentity` can sometimes provide a lowercase version. If the agent and Intune are sourcing from different providers, you get a silent fail.

Your Salesforce-Marketo example is spot-on for illustrating silent mapping failures. The critical factor is whether the comparison function uses a case-sensitive hash. Many lookups convert to a common case before hashing, which would mask the problem, but some legacy systems don't.

The real test is to intercept the raw identifier payload from the agent before it's transformed for the API call, not just compare logs. A packet trace during agent handshake can show the exact byte sequence.


Nullius in verba


   
ReplyQuote
(@billyp)
Reputable Member
Joined: 4 months ago
Posts: 284
 

You're checking all the right things. That `Posture check failed: criteria not met` log is so generic it's painful.

When I've seen this, it often came down to the *order* of evaluation in the ZTNA policy itself. The device might be compliant on all points, but if the policy first checks for domain-join (and the agent sends that signal a split-second late), it can fail the whole check before even evaluating the EDR health. Try looking at the raw posture assessment timeline for a failing device, if your platform provides it.

Also, double-check that your Intune compliance policy and your ZTNA policy are using the exact same definition for "EDR healthy." One might look for the process, the other for a specific registry value or cloud signal. That mismatch would give you compliant devices in Intune but a fail at the gateway.


Always A/B test.


   
ReplyQuote
(@crmsurfer_43)
Honorable Member
Joined: 8 months ago
Posts: 398
 

Good call on checking the attribute mapping. We chased a similar ghost for days where the agent was sending `deviceId` but the gateway's policy condition was looking for `azureADDeviceId`. The strings matched, but the field names didn't, so it was a permanent mismatch.

Your thought about policy evaluation order is a sharp one too. In our case, the policy would first check for a domain-joined flag that wasn't populated for Intune-only devices, causing an immediate fail before it even got to the EDR check. Might be worth seeing if your policy has a hidden "short circuit" logic on the first failing condition.



   
ReplyQuote
(@coffeelover)
Honorable Member
Joined: 4 months ago
Posts: 397
 

Good luck with that. Your checklist is solid, but it's all focused on the client side. The problem is almost certainly on the ZTNA vendor's side.

Their generic "criteria not met" log is a cop-out. It means their cloud service failed a lookup or their policy engine choked. You verified the device is fine. The vendor now needs to prove their side isn't broken.

Ask them for the raw posture assessment data *their gateway received* for a failing device, and the exact policy evaluation trace. Not the sanitized admin log. Bet you a coffee they can't provide it, or it'll show a mapping error in their own schema.


Just my two cents.


   
ReplyQuote
(@amyc)
Reputable Member
Joined: 4 months ago
Posts: 397
 

You're right that we can't ignore the vendor side, especially with that generic log. I've had to ask for the raw assessment data before, and it was eye-opening. They sent a JSON blob where the timestamp format from the agent didn't match the parser's expectation, causing a silent drop.

But be careful about betting on them *not* being able to provide it. Some of the more mature platforms actually have a detailed policy evaluation trace feature, it's just buried or requires a support ticket to enable. Pushing them to show their work is absolutely the right move, though.



   
ReplyQuote
Page 1 / 3