Repository navigation
Windows MDM client certificate is backdated by the renewal period, halving its lifetime and opening the renewal window at issuance #52601
Description
Fleet versions
- Discovered: 4.90.2. Present since Windows MDM WSTEP certificate management shipped (introduced in 410cbc3, Add certificate management for Microsoft MDM (WSTEP) #12543, June 2023).
💥 Actual behavior
Fleet backdates every Windows MDM client certificate by the full renewal period, so the certificate is issued already 180 days old and expires 185 days after enrollment instead of the 365 days Fleet advertises.
populateClientCert computes NotBefore by subtracting the renewal period from the current time, then adds a hardcoded 365 days to get NotAfter:
certRenewalPeriodInSecsInt, err := strconv.Atoi(syncml.PolicyCertRenewalPeriodInSecs) // 15552000s = 180 days
notBeforeDuration := time.Now().Add(time.Duration(certRenewalPeriodInSecsInt) * -time.Second) // now - 180d
yearDuration := 365 * 24 * time.Hour
NotBefore: notBeforeDuration, // now - 180d
NotAfter: notBeforeDuration.Add(yearDuration), // now + 185dThree separate problems fall out of this.
The certificate lives half as long as advertised. Fleet tells Windows one thing and issues another.
The renewal window is already open when the certificate is installed. The certificate is renewal-eligible from the instant it is issued, 180 days before the device even enrolled. Windows then retries every RetryInterval = 4 days for the entire life of the enrollment. This is why the EnrollmentState = 3 symptom in #50611 shows up on freshly enrolled hosts rather than only on hosts approaching expiry.
RenewPeriod and the advertised renewal period disagree. GetPolicies advertises RenewalPeriodSeconds = 15552000 (180 days) while the provisioning doc sends RenewPeriod = 365 days. The backdating has to be fixed for the renewal window to land anywhere sensible.
🛠️ Expected behavior
Fleet should issue a certificate whose validity matches what it advertises, and whose renewal window opens near the end of that validity rather than at the start.
- Set
NotBeforeto the current time. If a clock-skew allowance is wanted, use minutes or a few hours, not the 180 day renewal period. - Derive
NotAfterfromsyncml.PolicyCertValidityPeriodInSecs(the same constant Fleet advertises in GetPolicies) instead of the hardcodedyearDuration, so the advertised policy and the issued certificate cannot drift apart. - Make the provisioning doc's
RenewPeriodagree withPolicyCertRenewalPeriodInSecs, so a 365 day certificate with a 180 day renewal period opens its renewal window at day 185 rather than at day 0.
This bug is independent of the ROBO question. #51468 set WstepROBOSupport = "false" to stop Windows from attempting a renewal Fleet cannot service, and #52492 tracks the fact that Windows attempts renewal anyway. Even with ROBO fully implemented, the certificate lifetime and the renewal window would still be wrong.
🧑💻 Steps to reproduce
These steps:
- Have been confirmed to consistently lead to reproduction in multiple Fleet instances.
- Describe the workflow that led to the error, but have not yet been reproduced in multiple Fleet instances.
- Turn on Windows MDM on a Fleet server and enroll a Windows 10 or 11 host.
- On the host, open
certlm.mscand find the Fleet-issued client certificate inPersonal > Certificates(issued by the Fleet WSTEP identity CA, withOU = Fleet). Alternatively runGet-ChildItem Cert:\LocalMachine\My | Where-Object { $_.Issuer -like '*Fleet*' } | Select-Object Subject, NotBefore, NotAfter. - Observe that
NotBeforeis roughly 180 days in the past, dated well before the host enrolled, and thatNotAfteris roughly 185 days in the future rather than 365 days. - Read the provisioning doc values Fleet sent by checking
HKLM\SOFTWARE\Microsoft\Enrollments\<GUID>for the enrollment withProviderID = Fleet, and confirm the WSTEP renew settings show a 365 dayRenewPeriodagainst a certificate with 185 days of remaining life. - Confirm that Windows treats the certificate as renewal-eligible immediately: the scheduled task "Schedule created by enrollment client for renewal of certificate warning" under
\Microsoft\Windows\EnterpriseMgmt\<GUID>runs and attempts renewal within the firstRetryIntervalwindow rather than waiting until the certificate is near expiry.
🕯️ More info (optional)
The enrollment client logs its renewal schedule as a single line, event ID 3004 in Microsoft-Windows-DeviceManagement-Enterprise-Diagnostics-Provider/Enrollment:
(Get-WinEvent -FilterHashtable @{
LogName = "Microsoft-Windows-DeviceManagement-Enterprise-Diagnostics-Provider/Enrollment"; Id = 3004
} -MaxEvents 1 -ErrorAction SilentlyContinue).Message -replace "\s+"," "On a freshly enrolled host this prints:
[MDM Schedule Enrollment Cert Renew Session Start] EnrollmentId: 6AAC703B-..., Renew period: 180; Renew retry interval: 4; Robo mode: 1; Cert Expiration: 2027-09-08T15:02:42.00
The same line on pre-fix code:
[MDM Schedule Enrollment Cert Renew Session Start] EnrollmentId: B77E051E-..., Renew period: 365; Renew retry interval: 4; Robo mode: 1; Cert Expiration: 2027-03-12T13:52:51.00
Metadata
Metadata
Assignees
Labels
Type
Projects
- StatusShow more project fieldsDone
Activity
fix(mdm): prevent windows client certificate lifetime truncation (#52601
Bump the Win MDM cert skew to 1-day (#52709)
thisisjoegrant commentedon Oct 1, 2026
Confirmed cert issued today is now valid from roughly [Today - 1 day] to [Today + 1 year]
fleet-release commentedon Oct 8, 2026
Certificates backdated
now renewed when just issued
fix the time to heal