We use user certificates for authenticating to various services, but the certificates expire after a year unless renewed manually. I am attempting to create a logon script that will detect if the certificate is about to expire and renew it proactively.
The manual process we use currently is having the user log in, launching certmgr.msc, expanding Personal > Certificates, right-clicking the certificate, All Tasks > Renew Certificate with New Key (or Request New if it's already expired).
cd cert:\
$certs = Get-ChildItem -Recurse -ExpiringInDays 180 | Where subject -Like "*(foo)*"
if ($certs)
{
ForEach ($cert in $certs)
{
certreq -enroll -user -q -policyserver * $cert.thumbprint renew
}
}
I ran this successfully once, but I get the following error when I run the script:
Certificate Request Processor: The parameter is incorrect. 0x80070057
(WIN32: 87 ERROR_INVALID_PARAMATER)
I get the same result if enter garbage data or identify the certificate by serial number or thumbprint. The script is able to reliably find the certificate I want, but the certreq command is failing.
Any advice is greatly appreciated.
-cert parameter missing
Get-ChildItem cert:\ -Recurse -ExpiringInDays 180 | Where subject -Like "*(foo)*" | % {
certreq -enroll -user -q -policyserver * -cert $($_.thumbprint) renew
}
Related
Is there any way to get the Certification Authority, that issued a certificate by a certutil command or by some interface where I can put the serial number of a certificate into?
Our company has hundred thousands of certificates issued by 5 different issuing CA's.
Whenever I pull the complete dump (example) via:
certutil -view -config "Issuing-CA01" -restrict "notbefore>22/09/2021" csv > C:\Users\XYZ\Desktop\dump.csv
I do not find the information about the issuing CA in this dump, which contains all possible columns that the certutil command can deliver. Same with the SAN entrys, those are not readable from any dump, except from the certificate itself - but this belongs to a different question.
Is there any way that I can extract the issuing CA via the command line?
The Issuer is not a column in the ADCS database schema. So the only way would be to get the certificate itself out, parse it and print out the issuer name.
$tempFileName = "C:\Users\$env:UserName\AppData\Local\Temp\cert.cer";
& certutil -view -config "Issuing-CA01" -restrict "notbefore>22/09/2021" -out "RawCertificate" `
| Out-File -FilePath $tempFileName;
[regex]::Matches( `
(Get-Content $tempFileName), `
"-----BEGIN CERTIFICATE-----[\s\r\n]{1}" +
"(?<cert>[a-z|A-Z|0-9|\+|\-|\\|\/|\s|\r|\n|=]*)" +
"-----END CERTIFICATE-----", `
[System.Text.RegularExpressions.RegexOptions]::Multiline) `
| Foreach-Object {
[System.IO.File]::WriteAllText(`
$tempFileName, `
$_.Groups["cert"].Value.Replace(" ", ""));
$certificate = `
New-Object System.Security.Cryptography.X509Certificates.X509Certificate2(`
$tempFileName);
Write-Host $certificate.Issuer;
}
Remove-Item $tempFileName;
I am trying to install a certificate provided by mitmproxy.org via powershell and windows is not saving the certificate in the correct location.
Commands I tried to run:
Get-ChildItem -Path c:\mitmproxy-ca-cert.p12 | Import-PfxCertificate -CertStoreLocation cert:\LocalMachine\Root Instead of inserting a cert into Trusted Root Certification Authorities, it put it in Intermediate Certification Authorities.
Get-ChildItem -Path c:\mitmproxy-ca-cert.p12 | Import-PfxCertificate -CertStoreLocation cert:\CurrentUser\Root Did the same as the first command.
Even setting the working location to PS Cert:\localmachine\Root> did not manage to import into the Root location. Get-ChildItem -Path c:\mitmproxy-ca-cert.p12 | Import-PfxCertificate -CertStoreLocation .
There are no errors, all commands ran their course. I ran them with admin privileges.
Manually left-clicking on the mitmproxy-ca-cert.p12 however does start an import GUI that successfully imports it into the Root location. Why is the powershell not working tho?
Following mitmproxy.org own guide for command-line installation is of no use because it simply doesn't work:
How to install on Windows (Automated)
certutil.exe -importpfx Root mitmproxy-ca-cert.p12
C:\>certutil -importpfx Root mitmproxy-ca-cert.p12
Enter PFX password:
CertUtil: -importPFX command FAILED: 0x80092007 (-2146885625 CRYPT_E_SELF_SIGNED)
CertUtil: The specified certificate is self signed.
Can anyone shed some light what is going on here? Thank you.
I make a script for you, tell me if you don't understand.
$in_cert = "C:\Users\Marian\Desktop\Pfx Certificate.pfx";
$password = Read-Host -AsSecureString;
# Read the pfx certificate data:
$pfx = (Get-PfxData -FilePath $in_cert -Password $password -ErrorAction Stop);
# Get the root and publisher certificate:
$root = $pfx.OtherCertificates[0];
$publisher = $pfx.EndEntityCertificates[0];
# Add the root:
$rootStore = Get-Item "Cert:\CurrentUser\Root";
$rootStore.Open('ReadWrite');
$rootStore.add($root);
$rootStore.close();
# Add the publisher:
$rootStore = Get-Item "Cert:\CurrentUser\TrustedPublisher";
$rootStore.Open('ReadWrite');
$rootStore.add($publisher);
$rootStore.close();
Pause;
I posted to my post too: My Post
I am trying to export a certificate public and private key to a PFX file via a powershell script. I am currently using the following code
Get-ChildItem -Path Cert:\CurrentUser\My\$Thumbprint | Export-PfxCertificate -FilePath $OutputFile -Password $privateKeyPass -ChainOption EndEntityCertOnly
However, when I work with the resulting PFX file in something like certutil, it doesn't ask for a private key password. For example here is an example of what I get when i dump the cert with certutil:
> certutil -dump cert.pfx
Certificates: Not Encrypted
================ Certificate 0 ================
[cert data removed]
---------------- End Nesting Level 1 ----------------
Key Container = PfxContainer
Provider = PfxProvider
Encryption test FAILED
CertUtil: -dump command completed successfully.
If I use the certificates MMC snapin to export the cert I can select the "Enable certificate privacy" option and it will export an encrypted certificate.
My question is...
Is there a way to tell the export-pfxcertificate cmdlet to enable certificate privacy so that it is encypted? If not, what other solution do I have?
I am using Windows 7, and want to run signed scripts from Powershell, the security-settings of Powershell are set to "all-signed", and my scripts are signed with a valid certificate from my company. I have also added the .pfx-file to my local certificate store (right-clicked the pfx-file and installed).
However, when I start a signed script, I get a message that says:
"Do you want to run software from this untrusted publisher?
File Z:\Powershell Signed Scripts\signed.ps1 is published by CN=[MyCompanyName] and is not trusted on your system. Only run scripts from
trusted publishers.
[V] Never run [D] Do not run [R] Run once [A] Always run [?] Help
(default is "D"):"
Since I want to automatically call these scripts on my systems, I would like to add my imported certificate to the trusted list on my system, so that I do not get a message anymore when I run a signed script for the first time. How can I make my certificate a trusted one?
How to trust a certificate in Windows Powershell
Indeed, you can do this without any mmc :)
First, check the location of your personal certificate named for example "Power" :
Get-ChildItem -Recurse cert:\CurrentUser\ |where {$_ -Match "Power"} | Select PSParentPath,Subject,Issuer,HasPrivateKey |ft -AutoSize
(This one should be empty:)
gci cert:\CurrentUser\TrustedPublisher
Build the command with the path to your certificate:
$cert = Get-ChildItem Certificate::CurrentUser\My\ABLALAH
Next work on certificate store (Here I work on two certificate store : user & computer)
$store = New-Object System.Security.Cryptography.X509Certificates.X509Store "TrustedPublisher","LocalMachine"
$store.Open("ReadWrite")
$store.Add($cert)
$store.Close()
Check, you should find your certificate :
ls cert:\CurrentUser\TrustedPublisher
Sounds like you need to verify that the script is signed properly and that you have the correct certificate installed in the correct certificate store.
Use the Get-AuthenticodeSignature cmdlet to get information about the signed script.
Also review Scott's guide for signing certificates.
I have to sign remote scripts with a certificate from the remote machine from which I have a .pfx file.
I would like to automate the scripting by supplying the password to the Get-PfxCertificate programmatically.
So the question is:
Is it possible to somehow supply programmatically the required password to
Get-PfxCertificate?
$CertPath = "my.pfx"
$CertPass = "mypw"
$Cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2($CertPath, $CertPass)
Set-AuthenticodeSignature -Certificate $Cert -TimeStampServer http://timestamp.verisign.com/scripts/timstamp.dll -FilePath $OutputFilename
Make sure you have the proper permissions otherwise you won't be able to create an instance of the X509Certificate2 object.
I did a bit of checking around on this and couldn't find a clean way to provide the password programmatically. I suspect it is meant to be this way for security reasons. Either that or the PowerShell development team just blew it by not including a Credential parameter for this cmdlet. The only other option I can think of is to use someting like SendKeys to send the individual password character key presses to the PowerShell console at the right time via a background job (blech - just threw up in my mouth a little). :-)
Another way of doing this is by loading your certificate directly from your certificate store using PS Providers. Use Get-PSProviders to determine available PSProviders on your machine.
Once you have cert provider loaded, you can now get the certificate using Get-ChildItem
Launch certmgr.msc from run to launch the certificate store
Assuming that your certificate is stored under Personal folder in your cert store and has "Company Name" set in the subject property of the certificate, and there is only certificate in that folder with Company Name in the subject - you can get the certificate like so
$my_cert = Get-ChildItem cert:\CurrentUser\My | ? {$_.Subject -match "Company Name"}
$my_cert will be your certificate object that you can pass directly to Set-AuthenticodeSignature cmdlet
Set-AuthenticodeSignature -Certificate $my_cert -FilePath fqn_to_dll.dll -Timestampserver "http://timestampurl"
post signing, you can retrieve the sign status by querying on the Status property for "Valid" or not like
$result = Set-AuthenticodeSignature -Certificate $my_cert -FilePath fqn_to_dll.dll -Timestampserver "http://timestampurl" | Select Status
if(-Not ($result -eq "Valid")){
Write-Output "Error Signing file: Status: $($result.Status)"
}