I have a client side cert PFX from some idiot to allow some users access his website and I need to script it so I can allow multiple users to auto import this cert into the local store during a logon to our RDS environment.
This cert also came with a long complicated password that I need to pass to said function.
So I had the bright idea of using PS function Import-PFXCertificate to do this.
$PlainTextPass = "f4#)]\as1"
$pfxpass = $PlainTextPass |ConvertTo-SecureString -AsPlainText -Force
Import-PfxCertificate -filepath C:\important.pfx cert:\CurrentUser\my -
Password $pfxpass
It fails with this error, and I can't find any direct reference to it on the web.
Import-PfxCertificate : The PFX file you are trying to import requires either a different password or membership in an Active Directory principal to which it is protected.
The test user I am running against is a domain admin. Not that should matter as it's installing the cert into CurrentUser
Try surrounding the plain text password with single quotes instead of double quotes. I had a password with $ in it that gave me the same error until I swapped the quotes.
I was able to resolve the same issue in my case after I have stumbled upon similar post in ServerFault - Wrong password during pfx certificate import Windows(10, 2016)
My certificate was encoded during export to PFX using AES256-SHA256, switching to TripleDES-SHA1 resolved the problem.
Try changing the password. Just keep alphabetic letters. This solved the issue for me.
Related
I have been trying to get a new Sectigo code signing certificate working, with no luck, and Sectigo support is utterly useless. I am testing with this code, with the executable of course pathed to an actual PS1 file.
$executable = 'PATH TO.ps1'
$cert = Get-ChildItem cert:\CurrentUser\My -codesign
$timeStampServer = "http://timestamp.sectigo.com"
The time server seems to be working, since $timeStampServer echos http://timestamp.sectigo.com to the console. And the certificate SEEMS to be working because $cert echos a Thumbprint and Subject to the console.
But
Set-AuthenticodeSignature -filePath:$executable -certificate:$cert -timeStampServer:$timeStampServer -force
produces a blank SignerCertificate and UnknownError for the Status. For what it is worth the Path is just the file name, not the full path.
Unlike this thread, $cert.privatekey produces
PublicOnly : False
CspKeyContainerInfo : System.Security.Cryptography.CspKeyContainerInfo
KeySize : 4096
KeyExchangeAlgorithm : RSA-PKCS1-KeyEx
SignatureAlgorithm : http://www.w3.org/2000/09/xmldsig#rsa-sha1
PersistKeyInCsp : True
LegalKeySizes : {System.Security.Cryptography.KeySizes}
I wonder, is there anything else I can do to test the situation? I am waiting (about 110 minutes to go) on Sectigo support before I try downloading and installing a reissued certificate, but as crap as their support has been, I don't expect the new cert to work any better than the old, nor do I expect any insight from them as to the problem. They have my money, I expect them to say "PowerShell is your problem". So, hoping for some suggestions here as to what could be the issue, and what steps to take to isolate the problem.
One thing that does perk my ears up is that this link suggests I should also see EnhancedKeyUsageList for $cert and I do not. And when I look at the cert with Certlm I don't see an Intended Purposes column at all. But I think that's an OS issue as actually looking at the Cert there under the General tab, I have Enable all purposes for this certificate selected, and Code Signing is checked in the greyed out list.
Now, oddly, I get a single line with only UnknownError when I run Set-AuthenticodeSignature without dumping a variable to the console. But, if I dump $cert to the console right before I get
SignerCertificate :
TimeStamperCertificate :
Status : UnknownError
StatusMessage : The data is invalid
Path : PATH TO.ps1
SignatureType : None
IsOSBinary : False
Again with the correct local path. The StatusMessage doesn't exactly add much, but the fact that the TimeStamperCertificate is also blank makes me wonder if that's the issue. Given how much it seems Sectigo sucks, can I use some other generic timestamp server I can use, or am I limited to using the Timestamp Server of the certificate issuer? I tried using the timestamp server I had been using with my old GlobalSign EV cert, "http://timestamp.globalsign.com/scripts/timestamp.dll", and that produces the same results.
Also for what it is worth, the PS1 I am trying to sign for testing is one line
$scriptPath = Split-Path $script:myInvocation.myCommand.path -parent
I have never had such problems before. I had a Sectigo certificate last year and everything worked fine, but that was a different reseller, and in the meantime the Sectigo process seems to have changed. Last year my signed PDF from the KVK (Dutch Better Business Bureau) was fine for validation. But this year they demanded I provide a plain text translation of that document. And for years before I never had issues but then I was using a EV cert on a thumb drive. Which I gave up when GlobalSign took 4 months to get a thumb drive from London to Rotterdam.
But back on topic, suggestions?
EDIT: Further searching led to this, so I tried
$Cert = Get-PfxCertificate -FilePath "PATH TO.pfx"
And I put both the PFX and target PS1 in the root of C. Same results.
EDIT #2: After days of really horrible support from Comodo/Sectigo I demanded a refund, and bought a new certificate from SSL.Com. MUCH better experience with the validation process, but exactly the same issues with signing code. Now verified on both a Windows 10 and an old Windows 7 VM. So the code signing problem is definitely on my end. Meaning, more than ever I hope someone here can provide some insight.
We're sorry you're experiencing an issue. Here is some information to help resolve the issue. If you have any further questions, please feel free to contact Sectigo Support at https://sectigo.com/support and a member of our team will reach out to you.
Powershell ISE uses 'Unicode Big Endian' encoding and that could be the problem. Please try recreating the file using UTF-8 and set the Authenticode signature.
#creating the script into a new file
type \path\scriptfile.ps1 | out-file \path\scriptfile_utf.ps1 -encoding utf8
#get the certificate
$cert = Get-ChildItem cert:\CurrentUser\My -codesigning
#add Authenticode Signature to the script
Set-AuthenticodeSignature \path\scriptfile_utf.ps1
I had the same error. I tried to sign a .cmd file with a CodeSigningCert and received Unknown Error with a blank SignerCertificate as well.
When I tried signing a PowerShell script it worked fine. That is because you cannot sign a non-Executable with a CodeSigningCert. Might not be your issue, but that was what was wrong for me.
I did not use an official certificate though, I created one with the New-SelfSignedCertificate Cmdlet. Maybe you can try with a self-signed one and check if the error occurs as well?
I have configured a powershell script, which creates a vpn conection profile.
To make it work i need to add proper certificate.
Everything works fine when i add a certificate manually to local machine:
More detailed regarding importing certificate manualy:
Info
I'm trying to perform this task via powershell, but it doesn't work (script seems to work, but i am not sure to which stores should i copy certificate). In contrary to manual method - the certificate added by my powershell script is invisible for vpn connection.
#add certificate
$cert_name=$env:USERNAME+"#vpn.contoso.com.p12"
$cert_loc="\\ad\deploy\other\certs\"+$cert_name
$secure_pwd = ConvertTo-SecureString "contoso987%#" -AsPlainText -Force
Import-PfxCertificate -FilePath $cert_loc -CertStoreLocation Cert:\LocalMachine\My -Password $secure_pwd
# Add vpn connection
Add-VpnConnection -Name "Example VPNX" -ServerAddress "vpn.example.com" -AuthenticationMethod "MachineCertificate" -TunnelType "IKEv2" -EncryptionLevel "Maximum" -SplitTunneling $True
I would like to do it the same way the certificate import wizard does. Does anyone have experience in that ?
PS
I've changed addresses in codes etc.
Kind Regards,
Tamara
I've decided to post the solution. Although it is not developed in powershell it solves the problem completely. It is possible to import these kind of certificates from command prompt:
certutil -f -p Some_password -importpfx "\\ad\somepath\certificate.p12"
My question is this: how would I go about installing a .pfx cert into TrustedRootCA with its private key from command line using powershell in windows 7?
I've got it to install the cert using this command: certutil -importpfx -p "mypasswordhere" "cert path location here"
The above installs it to the personal store of the local computer fine (With the private key intact) And also installs it to TRCA, only without the private key. This is my issue as the program requires the TRCA to have the private key.
but when I try to use the program that needs the cert it says : "It is likely that "My cert" may not have a private key that is capable of key exchange or the process may not have axxess rights for the private key. Please see inner exception for more detail.
However, I checked the TRCA store and verfied that my cert indeed does not have its private key.
So again my question is there anyway using powershell to automate this process on windows 7? Thanks in advance.
You can use the command
Import-PfxCertificate -FilePath C:\setup\TestCertImport.pfx -CertStoreLocation 'Cert:\LocalMachine\Root'
Root = Trusted root,
My = Local Machine Personal certificate folder
if the certificate has password you can add the -Password parameter and if you want it to be exportable the -Exportable
I am trying to use the New-AzureRmADAppCredential cmdlet. I am trying to create a new credential using the following syntax:
New-SelfSignedCertificateEx -Subject "CN=$ClientId" -KeySpec "Exchange" -FriendlyName "$ClientId"
$start = (Get-Date).ToUniversalTime()
$end = $start.AddDays(4)
New-AzureRmADAppCredential -ApplicationId $application.ObjectId -CertValue $keyValue -StartDate $start -EndDate $end
I've noticed that if I try to create a new credential with a certificate, it failed on a specific apps with the following error:
New-AzureRmADAppCredential : Update to existing credential with KeyId 'keyid' is not allowed.
This app has 2 credentials, one is a password and the other is a certificate. The keyid belong to the certificate credential. The weird part is that on other app it worked fine, even if the app has multiple certificate credentials. I've tried to look at the documentation, but couldn't find anything useful.
So, my question is - why this error happens? and how I can solve this?
Update: By looking in the code of the cmdlet, it seems like it always updating the whole list, so I think it might be something related to permission, but I am not sure.
Thanks,
Omer
Yeah, New-AzureRmADAppCredential isn't strong enough, if AAD App has keys, it will update the latest key in the key list and of course won't work(Update to existing credential with KeyId is not allowed), I think it's a bug; if no key existed, it will create a new key. You can use New-AzureADApplicationPasswordCredential instead.
Ok, so we found out this happens because the first certificate was uploaded to Azure AD by modifying the application manifest. After deleting it and adding it again using powershell everything worked...
I have a Powershell script that is going to be run through an automation tool against multiple servers.
It works fine on Windows machines, as the remote calls use the tool's service account without any need for prompting or exposing any credentials in code.
This script also runs against Linux machines via SSH using the SharpSSH package. SharpSSH does not automatically use the Powershell user's credentials but requires either a username and password, an RSA key file, or a PSCredential object.
I can't prompt for credentials using Get-Credential, because it's being run through the automation tool. I don't want to expose the username and password in code or have an RSA key sitting out there. I would like to construct a PSCredential object from the current Powershell user (the service account).
Trying [System.Net.CredentialCache]::DefaultNetworkCredentials shows a blank, and [System.Security.Principal.WindowsIdentity]::GetCurrent() doesn't provide the object or information I need.
Does anyone have a method for creating a PSCredential object from the current user? Or maybe a completely different alternative for this problem?
Many thanks!
The Windows API will not expose the information you need, which is why Powershell can't get to them. Its an intentional feature of the security subsystem. The only way for this to work is for the Linux machines to trust the calling machine, such as joining them to an Active Directory (or any kerberos setup really).
Aside from that, you'd need to store and pass this information somehow.
You could store the RSA key in the user's keystore and extract it at runtime (using the .NET Crypto/Keystore libs), so you aren't storing the key around with the code. That way the key itself would be protected by the OS and available only when the calling user was authenticated. You'd have one more thing to install, but may be the only way to achieve what you are aiming for.
"Trying [System.Net.CredentialCache]::DefaultNetworkCredentials shows a blank, and [System.Security.Principal.WindowsIdentity]::GetCurrent() doesn't provide the object or information I need."
You already have your answer. I use this to pass the currently logged in user's credentials along in several scripts:
$Credentials = [System.Net.CredentialCache]::DefaultNetworkCredentials
$Username = $Credentials.UserName
$Password = $Credentials.Password
If you try to dump them to any kind of readable output, those values are empty when you dump them (for obvious security reasons), however they do work where you need a PSCredential object.
How about encrypting the password using the service account's encryption key?
A quick example:
Run PowerShell as the service account, run the following and save the output to a text file (or embed it in the scheduled task call):
$String = '<PASSWORD>'
ConvertFrom-SecureString -SecureString (ConvertTo-SecureString -String $String -AsPlainText -Force)
Use the following in your scheduled task in order to decrypt and utilize the password:
$EncryptedString = '<ENCRYPTED PASSWORD FROM ABOVE>'
[Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR((ConvertTo-SecureString -String $EncryptedString)))
That should do the trick. You cannot reuse the encrypted password on a different computer, though, or if you for whatever reason destroy you local key store :)
Since you can get the password in plaintext from a credential object, I doubt you can get this without prompting.