PSPKI
PSPKI copied to clipboard
Get-CertificationAuthority raises an exception on a workgroup CA
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
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.
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?
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.
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.
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.
Interesting: GitHub does not show it in the search results: https://github.com/PKISolutions/PSPKI/search?q=NoDomain
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.
As for variable initialization, when I run
$Domain = ([ADSI]"LDAP://RootDSE").ConfigurationNamingContexton a non-domain machine, I do not receive an exception, therefore thecatchsection does not get invoked, which, in turn, sets$NoDomain = $false.
gotcha! This is an interesting behavior of PowerShell which I need to fix.
Perhaps we could query (Get-CimInstance -ClassName 'Win32_ComputerSystem').PartOfDomain for better detection?
Perhaps we could query
(Get-CimInstance -ClassName 'Win32_ComputerSystem').PartOfDomainfor 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.
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.
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.
Yes, you are correct - thank you!
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.
Thank you, Vadims!
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.
Fixed in v4.0.0