I'm writing a Powershell script that creates self signed certificates which works fine as an Administrator but fails as Admin:
The piece of code that fails when I call the Create method:
$PrivateKey = New-Object -ComObject X509Enrollment.CX509PrivateKey
$PrivateKey.ProviderName = "Microsoft RSA SChannel Cryptographic Provider"
$PrivateKey.KeySpec = 0x1
$PrivateKey.Length = 2048
# set security descriptor
$PrivateKey.SecurityDescriptor = "D:PAI(A;;0xd01f01ff;;;SY)(A;;0xd01f01ff;;;BA)(A;;0x80120089;;;NS)"
# key will be stored in local machine certificate store
$PrivateKey.MachineContext = 0x1
# export will be allowed
$PrivateKey.ExportPolicy = 0x1
$PrivateKey.Create()
It throws this error:
Exception calling "Create" with "0" argument(s): "CertEnroll::CX509PrivateKey::Create: Access is denied. 0x80070005
(WIN32: 5)"
At C:\dev\LinoaSSC.ps1:106 char:1
+ $PrivateKey.Create()
+ ~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : ComMethodTargetInvocation
How should I troubleshoot or solve this error? Thanks guys!
You need to be an administrator on the local machine to perform this and I believe most actions with certificates. I'm not aware of any acceptable methods to work around this, but there are ways to elevate your permissions.
You can absolutely allow a non-admin to create machine key sets. You just need to allow the account you would like to create private keys to have write permissions to the following default directories.
C:\ProgramData\Microsoft\Crypto\Keys
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\SystemCertificates
C:\ProgramData\Microsoft\Crypto\RSA
Then, in your code, provide a SecurityDescriptor
on the CX509PrivateKey
object before calling the Create
method. The default SD is "D:P(A;;0xd01f01ff;;;CO)(A;;0xd01f01ff;;;SY)(A;;0xd01f01ff;;;BA)"
, but simply add an entry for the account SID.
Curiously, the SecuityDescriptor does allow “CO”, which means CreatorOwner, but for CNG certificates, the private key gets created by lsass.exe running as SYSTEM, which is impersonating the account that requests the certificate. By default, this doesn’t allow the account that requested the certificate for some reason. It does appear that with CryptoAPI certs, the CreatorOwner SecurityDescriptor does allow the requesting account with the default SecurityDescriptor.
Note: carefully consider the security implications for your environment. This will allow the account to have access to the private keys in the machine store. In my scenario, principal of least privilege was a better trade off than granting the account full admin privileges.
User contributions licensed under CC BY-SA 3.0