Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ADSRootKey: Fails with 'String was not recognized as a valid DateTime' exception #702

Closed
Borgquite opened this issue Feb 1, 2024 · 4 comments · Fixed by #703
Closed
Labels
bug The issue is a bug. good first issue The issue should be easier to fix and can be taken up by a beginner to learn to contribute on GitHub

Comments

@Borgquite
Copy link
Contributor

Borgquite commented Feb 1, 2024

Problem description

Trying to use KDSRootKey to validate an existing KDSRootKey on a server with the English (United Kingdom) locale set.

Receiving this error:

Verbose logs

VERBOSE: [REDACTED]: LCM:  [ Start  Resource ]  [[ADKDSKey]ADKDSKey::[DomainController]REDACTED]                                                                                                                  VERBOSE: [REDACTED]: LCM:  [ Start  Test     ]  [[ADKDSKey]ADKDSKey::[DomainController]REDACTED]                                                                                                                  VERBOSE: [REDACTED]:                            [[ADKDSKey]ADKDSKey::[DomainController]REDACTED] Retrieving KDS Root Key with effective date of '<redacted>'. (KDSK0001)                        VERBOSE: [REDACTED]:                            [[ADKDSKey]ADKDSKey::[DomainController]REDACTED] Perform operation 'Enumerate CimInstances' with following parameters, ''namespaceName' = root\cimv2,'className'  = Win32_OperatingSystem'.                                                                                                                                                                                       VERBOSE: [REDACTED]:                            [[ADKDSKey]ADKDSKey::[DomainController]REDACTED] Operation 'Enumerate CimInstances' complete.                                                                     VERBOSE: [REDACTED]:                            [[ADKDSKey]ADKDSKey::[DomainController]REDACTED] Checking if the user 'NT AUTHORITY\SYSTEM' has valid Domain Admin permissions. (KDSK0019)                        VERBOSE: [REDACTED]:                            [[ADKDSKey]ADKDSKey::[DomainController]REDACTED] Checking if the node 'REDACTED' is a Domain Controller. The node has a product type of '2'. If the product type   is 2, then it is a domain controller. (KDSK0020)                                                                                                                                                                VERBOSE: [REDACTED]:                            [[ADKDSKey]ADKDSKey::[DomainController]REDACTED] Found KDS Root Key with the effective date of '<redacted>'. (KDSK0010)                         WARNING: [REDACTED]:                            [[ADKDSKey]ADKDSKey::[DomainController]REDACTED] Found more than one KDS Root Keys. This shouldn't be an issue, but having only one key per domain is             recommended. (KDSK0009)                                                                                                                                                                                         
Exception calling "Parse" with "1" argument(s): "String was not recognized as a valid DateTime."
    + CategoryInfo          : NotSpecified: (:) [], CimException
    + FullyQualifiedErrorId : FormatException
    + PSComputerName        : REDACTED

VERBOSE: [REDACTED]:                            [[ADKDSKey]ADKDSKey::[DomainController]REDACTED] Retrieved the root domain distinguished name of '<redacted>'. (KDSK0021)
VERBOSE: [REDACTED]:                            [[ADKDSKey]ADKDSKey::[DomainController]REDACTED] KDS Root Key with the effective date of '2024-01-25T10:59:31.0141932Z' is in the desired state. (KDSK0015)
VERBOSE: [REDACTED]: LCM:  [ End    Test     ]  [[ADKDSKey]ADKDSKey::[DomainController]REDACTED] False in 0.3600 seconds.
VERBOSE: [REDACTED]: LCM:  [ *FAILED*Compare  ]     Completed processing compare operation. The operation returned False.
The PowerShell DSC resource '[ADKDSKey]ADKDSKey::[DomainController]REDACTED' with SourceInfo '' threw one or more non-terminating errors while running the Test-TargetResource functionality. These errors are 
logged to the ETW channel called Microsoft-Windows-DSC/Operational. Refer to this channel for more details.
    + CategoryInfo          : InvalidOperation: (root/Microsoft/...gurationManager:String) [], CimException
    + FullyQualifiedErrorId : NonTerminatingErrorFromProvider
    + PSComputerName        : REDACTED

DSC configuration

ADKDSKey "ADKDSKey"
{
     EffectiveTime = "<redacted>"
     AllowUnsafeEffectiveTime = $true
}

Suggested solution

Having stepped through the code in MSFT_ADKDSKey.psm1 it looks like this is failing in Get-TargetResource, line 110. If I run these commands on my system:

$effectiveTimeObject = [DateTime]::Parse("01 February 2024 12:21:51")
$kdsRootKeys = Get-KdsRootKey
    $kdsRootKey = $null
    if ($kdsRootKeys)
    {
        $kdsRootKey = $kdsRootKeys.GetEnumerator() |
            Where-Object -FilterScript {
                $_.EffectiveTime -eq $effectiveTimeObject
            }
    }
$targetResource['EffectiveTime'] = ([DateTime]::Parse($kdsRootKey.EffectiveTime)).ToString()

I get:

Exception calling "Parse" with "1" argument(s): "String was not recognized as a valid DateTime."
At line:1 char:1
+ $targetResource['EffectiveTime'] = ([DateTime]::Parse($kdsRootKey.Eff ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : FormatException

Running '$kdsRootKey.EffectiveTime' returns the value '01 February 2024 12:21:51', but this is not accepted by [DateTime]::Parse() - possibly down to system locale (which is en-GB)? To be honest I'm not sure why we are running [DateTime]::Parse() on $kdsRootKey.EffectiveTime in line 110 or line 423 anyway, as it's already a [DateTime] object, so this could be a fix?

Operating system the target node is running

OsName               : Microsoft Windows Server 2022 Standard
OsOperatingSystemSKU : StandardServerEdition
OsArchitecture       : 64-bit
WindowsVersion       : 2009
WindowsBuildLabEx    : 20348.1.amd64fre.fe_release.210507-1500
OsLanguage           : en-US
OsMuiLanguages       : {en-US}

PowerShell version and build the target node is running

Name                           Value
----                           -----
PSVersion                      5.1.20348.2227
PSEdition                      Desktop
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
BuildVersion                   10.0.20348.2227
CLRVersion                     4.0.30319.42000
WSManStackVersion              3.0
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1

ActiveDirectoryDsc version

Name               Version Path
----               ------- ----
ActiveDirectoryDsc 6.3.0   C:\Program Files\WindowsPowerShell\Modules\ActiveDirectoryDsc\6.3.0\ActiveDirectoryDsc....
@johlju
Copy link
Member

johlju commented Feb 6, 2024

This is most likely trying to return the value from DateTime to a string. Since the parameter EffectiveTime is a string.

$targetResource['EffectiveTime'] = ([DateTime]::Parse($kdsRootKey.EffectiveTime)).ToString()

Because Get-TargetResource returns EffectiveTime as string (need by the schema, and done by line 110 above) the line at 423 seems to try to convert the value back to DateTime. Line 422 and 423 prepares the values as DateTime so the comparison compares two DateTime values (instead of comparing strings).

$PSBoundParameters['EffectiveTime'] = [DateTime]::Parse($EffectiveTime)
$getTargetResourceResult['EffectiveTime'] = [DateTime]::Parse($getTargetResourceResult.EffectiveTime)

The problem seems to be that the parsing should always be done through a known format, that works regardless of locale. 🤔

@johlju johlju added bug The issue is a bug. help wanted The issue is up for grabs for anyone in the community. good first issue The issue should be easier to fix and can be taken up by a beginner to learn to contribute on GitHub labels Feb 6, 2024
@johlju
Copy link
Member

johlju commented Feb 6, 2024

Maybe line 110 should be changed to something like this, assuming the property EffectiveTime is a DateTime in all supported OS:

$targetResource['EffectiveTime'] = $kdsRootKey.EffectiveTime.ToString('yyyy-MM-dd HH:mm:ss.fff')

or

$targetResource['EffectiveTime'] = $kdsRootKey.EffectiveTime.GetDateTimeFormats('o')

@Borgquite
Copy link
Contributor Author

On your last point, the property EffectiveTime appears to be a DateTime on Windows Server 2012 R2 and Windows Server 2022 - doubt it's changed between?

OsName               : Microsoft Windows Server 2012 R2 Standard
OsOperatingSystemSKU : StandardServerEdition
OsArchitecture       : 64-bit
WindowsBuildLabEx    : 9600.21620.amd64fre.winblue_ltsb_escrow.230929-1158
OsLanguage           : en-US
OsMuiLanguages       : {en-US}

PS C:\Windows\system32> (Get-KdsRootKey)[1].EffectiveTime.gettype()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     DateTime                                 System.ValueType
OsName               : Microsoft Windows Server 2022 Standard
OsOperatingSystemSKU : StandardServerEdition
OsArchitecture       : 64-bit
WindowsVersion       : 2009
WindowsBuildLabEx    : 20348.1.amd64fre.fe_release.210507-1500
OsLanguage           : en-US
OsMuiLanguages       : {en-US}

PS C:\Windows\system32> (Get-KdsRootKey)[1].EffectiveTime.GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     DateTime                                 System.ValueType

@Borgquite
Copy link
Contributor Author

OK so there's a load of weirdness going on when DateTime attempts to process dates in non-US cultures, in what I'm pretty sure is buggy behaviour (see my report at https://stackoverflow.com/questions/77968235/how-is-powershell-datetimeparse-processing-broken-in-certain-locales)

But it looks like all that's needed to fix it here is to bypass the unnecessary Parse() call - have tested the attached PR on my system & seems to work perfecly now.

Borgquite added a commit to Borgquite/ActiveDirectoryDsc that referenced this issue Feb 12, 2024
johlju pushed a commit that referenced this issue Feb 12, 2024
…in non-US cultures (#703)

- ADSRootKey
  -  Resolved 'String was not recognized as a valid DateTime' in non-US cultures (issue #702).
@johlju johlju removed the help wanted The issue is up for grabs for anyone in the community. label Feb 12, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug The issue is a bug. good first issue The issue should be easier to fix and can be taken up by a beginner to learn to contribute on GitHub
Projects
None yet
2 participants