PSPKI icon indicating copy to clipboard operation
PSPKI copied to clipboard

Get-CertificationAuthority raises an exception on a workgroup CA

Open exchange12rocks opened this issue 4 years ago • 16 comments

PS C:\Users\Administrator> Get-CertificationAuthority
Exception calling "GetAdPkiContainer" with "1" argument(s): "Operation is not supported on this platform."
At C:\Program Files\WindowsPowerShell\Modules\PSPKI\Server\Get-CertificationAuthority.ps1:18 char:9
+         $DSList = [SysadminsLV.PKI.Management.ActiveDirectory.DsPkiCo ...
+         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : PlatformNotSupportedException


DisplayName                              ComputerName              IsAccessible ServiceStatus Type
-----------                              ------------              ------------ ------------- ----
My Root CA                               ROOTCA01                  True         Running       Standalone Root CA

exchange12rocks avatar Jul 13 '21 08:07 exchange12rocks

Yes, this is expected. The documentation says that it retrieves only CAs registered in Active Directory, thus depends on AD. For workgroup environments you have to use Connect-CertificationAuthority command instead. Note that remote CAs from workgroup are not supported, only local CAs are supported.

Crypt32 avatar Jul 13 '21 08:07 Crypt32

I see, thank you for the quick response. But it seems the command does return useful results, just with an additional error - I can use the resulting CA object in other commands just fine.

Do you think it would be possible to join Get-CertificationAuthority's and Connect-CertificationAuthority's functionality in a single command?

exchange12rocks avatar Jul 13 '21 10:07 exchange12rocks

I see, thank you for the quick response. But it seems the command does return useful results, just with an additional error - I can use the resulting CA object in other commands just fine.

That's interesting, because there is a check if you are in domain or not: https://github.com/PKISolutions/PSPKI/blob/333caa33639fad444529ad131982459b4142b48f/PSPKI/Server/Get-CertificationAuthority.ps1#L17

and if you are not connected to domain, the Get-CertificationAuthority should return you nothing.

Do you think it would be possible to join Get-CertificationAuthority's and Connect-CertificationAuthority's functionality in a single command?

I don't know if it possible to merge both commands without breaking things.

Crypt32 avatar Jul 13 '21 12:07 Crypt32

It seems that the $NoDomain variable is not defined - I did not find it anywhere in the code besides that line. And when it is not defined, it is effectively processed as $false. And -not $false is $true therefore the condition resolves to $true and the GetAdPkiContainer method tries to execute and then all other code in the function executes as well, because by default $ErrorActionPreference is set to Continue.

exchange12rocks avatar Jul 13 '21 16:07 exchange12rocks

Actually, this variable is defined here: https://github.com/PKISolutions/PSPKI/blob/333caa33639fad444529ad131982459b4142b48f/PSPKI/PSPKI.psm1#L11

and it should be properly initialized with $true because ADSI calls to RootDSE must fail in workgroup environment.

Crypt32 avatar Jul 13 '21 17:07 Crypt32

Interesting: GitHub does not show it in the search results: https://github.com/PKISolutions/PSPKI/search?q=NoDomain

exchange12rocks avatar Jul 13 '21 17:07 exchange12rocks

As for variable initialization, when I run $Domain = ([ADSI]"LDAP://RootDSE").ConfigurationNamingContext on a non-domain machine, I do not receive an exception, therefore the catch section does not get invoked, which, in turn, sets $NoDomain = $false.

exchange12rocks avatar Jul 13 '21 18:07 exchange12rocks

As for variable initialization, when I run $Domain = ([ADSI]"LDAP://RootDSE").ConfigurationNamingContext on a non-domain machine, I do not receive an exception, therefore the catch section does not get invoked, which, in turn, sets $NoDomain = $false.

gotcha! This is an interesting behavior of PowerShell which I need to fix.

Crypt32 avatar Jul 13 '21 18:07 Crypt32

Perhaps we could query (Get-CimInstance -ClassName 'Win32_ComputerSystem').PartOfDomain for better detection?

exchange12rocks avatar Jul 13 '21 18:07 exchange12rocks

Perhaps we could query (Get-CimInstance -ClassName 'Win32_ComputerSystem').PartOfDomain for better detection?

I solved this in slightly different way: https://github.com/PKISolutions/PSPKI/blob/a0eb35d49e1a6d08faedeb14e89d6e12615e9088/PSPKI/PSPKI.psm1#L14 I need to ensure that there is at least one online domain controller rather (because I need to fetch some data from there) than just check domain membership. Anyway, Get-CertificationAuthority should behave like it is intended. But I will take a look if I can make it working in workgroups without breaking existing syntax.

Crypt32 avatar Jul 13 '21 18:07 Crypt32

Maybe it is worth to implement both checks? Querying an non-existent domain controller takes time - the request waits and then fails by timeout. What if first we will check that WMI class and if it returns true, then we will query a DC? It should improve module loading time on workgroup computers.

exchange12rocks avatar Jul 13 '21 18:07 exchange12rocks

I just checked the code: mentioned line fails immediately if you are not part of domain. If you are part of domain, but disconnected -- the delay is inevitable. It appears, the method call already implements domain membership check internally before trying to contact DCs.

Crypt32 avatar Jul 13 '21 18:07 Crypt32

Yes, you are correct - thank you!

exchange12rocks avatar Jul 13 '21 18:07 exchange12rocks

I think, this commit should do the work, though haven't tested: https://github.com/PKISolutions/PSPKI/commit/0b8764b89a686b248b338aa0f5b12765d10a7fb5

In the else clause I mimic Connect-CertificationAuthority command by attempting to reach local CA. This means that in workgroup, the Get-CertificationAuthority will return only one local CA at most or throw the error if one is not found. It would be nice if you would find a time to test this little commit. I think it should do the trick.

Crypt32 avatar Jul 13 '21 18:07 Crypt32

Thank you, Vadims!

exchange12rocks avatar Jul 13 '21 19:07 exchange12rocks

Seems to be working all right on my workgroup CA, but of course currently these two functions are only partially compatible by parameter sets: Connect-CertificationAuthority supports connection to remote servers and more than one computer name.

exchange12rocks avatar Jul 13 '21 19:07 exchange12rocks

Fixed in v4.0.0

Crypt32 avatar Jun 15 '23 07:06 Crypt32