Add certificates the same way the Certificate Import Wizard does [Powershell] - powershell

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"

Related

Connecting Exchange Online Fails when passing proxy and running in System PowerShell - TokenProvider Returns Object Reference Error

I was connecting Exchange Online using a PowerShell window that is opened with system access. I used PSExec on an elevated Command Prompt to open the System access PowerShell. Below is the command.
PSExec -i -s PowerShell
On the PowerShell, I imported the latest Exchange Online Management PowerShell module version 2.0.3. I use the app-based authentication described here: https://learn.microsoft.com/en-us/powershell/exchange/app-only-auth-powershell-v2?view=exchange-ps#setup-app-only-authentication.
There is one more website that shows how to connect with app-based authentication: https://o365reports.com/2020/07/04/modern-auth-and-unattended-scripts-in-exchange-online-powershell-v2.
Below are the commands used to connect to Exchange Online.
Import-Module .\ExchangeOnlineManagement
$sessopt = New-PSSessionOption -SkipCACheck -SkipCNCheck -SkipRevocationCheck -ProxyAccessType IEConfig
$certkey = ConvertTo-SecureString "<EnterCertificateKeyHere>" -AsPlainText -Force
Connect-ExchangeOnline -CertificateFilePath "pfx Certificate Path" -AppId <EnterAppIdHere> -Organization "domain.onmicrosoft.com" -CertificatePassword $certkey -PSSessionOption $sessopt -verbose
When running the above, it returns Object Reference error. I got excited and went on to find what the error is by decompiling the DLL files and found that inside the 'ExoPowershellGalleryModule.dll -> NewExoPSSession.cs' of the Exchange module, the 'GetAccessToken' function which is called around line:308 causes this error. Any idea what makes the Object reference not set to an instance of an object. System.Management.Automation.RemoteException: Object reference not set to an instance of an object. error. Was the proxy not taken from IE?
I've set the proxy settings in IE using the below Powershell command-lets in system PowerShell.
Set-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings' -name ProxyServer -Value "ProxyServerAddress"
Set-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings' -name ProxyEnable -Value 1
Any help to resolve this is appreciated.
If your using
PSExec -i -s PowerShell
Then the proxy information your entering for the user will have no effect because the local system account will have its own profile information. Also if the proxy needs authentication you also won't be presenting any Network credentials.
If you really want to run under the system account you could try using netsh to configure the proxy https://learn.microsoft.com/en-us/windows/security/threat-protection/microsoft-defender-atp/configure-proxy-internet but if you proxy need authentication this won't work.

TeamCity Remote Powershell Access Denied Suddenly

Disclaimer: I am not a DevOps guy so please forgive any ignorance. I'm learning this stuff to expand my understanding.
I've enabled remote Powershell on a Windows Server 2019 instance in order to stop/start scheduled tasks during deployment of files from my build server (also Windows Server 2019).
I followed the below steps in an Administrator Powershell as the Adminstrator user on the remote server:
1. Enable RSRemoting.
2. Remove existing listener.
3. Create self-signed certificate and export to crt file.
$Cert = New-SelfSignedCertificate -CertstoreLocation Cert:\LocalMachine\My -DnsName "<subdomain.domain.com>"
Create listener.
Create firewall rules to allow secure PSRemoting and disable unsecure connections.
Copy certificate to build server.
Import certificate on build server.
From the build server, I've tested the configuration using the following commands in Powershell:
$username = 'Administrator'
$pass = ConvertTo-SecureString -string '<password here>' -AsPlainText -Force
$cred = New-Object -typename System.Management.Automation.PSCredential -argumentlist $username, $pass
Invoke-Command -ComputerName <subdomain.domain.com> -UseSSL -ScriptBlock {whoami} -Credential $cred
Which responds nicely with win-<some stuff>\administrator. However, when I execute a remote Powersehll command from within a TeamCity build step, I get a big ugly Connecting to remote server <subdomain.domain.com> failed with the following error message : Access is denied..
The weird part is, this worked two days ago and I have several builds that were able to complete all remote operations. From this morning, it's just stopped working - poof!
If I fudge the credentials, I do get an incorrect username/password error so it is definitely reaching the server.
Another interesting find is that if I run
[bool](Test-WSMan)
on the remote server, I get True returned, but if I run the same command with -ComputerName <subdomain.domain.com> on the build server, I get
WinRM cannot complete the operation. Verify that the specified computer name is
valid, that the computer is accessible over the network, and that a firewall exception for the WinRM service is enabled and allows access from this computer. By default, the WinRM firewall exception for public profiles limits
access to remote computers within the same local subnet. returned.
Both the remote host and build server are logged on as the default Administrator.
Any ideas?
After more research and calling in a few favours, I was advised to tweak the TeamCity Build Agent and TeamCity Server services. These need to Log On As a User and not Local System. I can't explain how my previous settings worked. The Access is denied error I experienced has nothing to do with the Remote Powershell configuration mentioned above.

certutil not importing all certs

p12 file with 7 certificates in it.
Following the instruction that came along with the cert file, we have to use MMC and a password to import all certs into a personal store.Instruction also says to check mark private key exportable.
in order to automate this, I tried using certutil -importpfx but that only added 4 out of 7 certificates. I am unable to see other 3 certs. The diff i noticed is the imported certs are the ones with "ext issuing CA" and missing certs are with "issuing CA" in the Subject .
Any pointers please
I found an alternate solution using powershell instead of certutil .
Import-pfx with flag -exportable imported all the certs.
Import-PfxCertificate -CertStoreLocation Cert:\LocalMachine\My -Password $Securepwd -FilePath $findP12Cert.FullName -Exportable -Verbose

Visual studio team services deploymen/buildt certificate error

I am trying to build a click-once application using the Continuous integration and deployment feature in VSTS (Visual studio team services Online)We are trying to build this using the Hosted agent Visual studio 2015 We had difficulties signing the strong name key file with an error of
MSB3326: Cannot import the following key file: xxxx.snk. The key file may be password protected. To correct this, try to import the certificate again or import the certificate manually into the current user's personal certificate store.
And after that
MSB3321: Importing key file "xxxx.pfx" was canceled.
I have tried to both select from store and from file changed the location and made sure to commit but with no success.
Any ideas how i can overcome this errors or what am doing wrong.
Clerification on answer selected
Just wanted to make a clarification if anyone else has the same issue, in addition to the answer i had to place my certificate in my source control code and commit it. Then to select its location add a global variable on the VSTS Build
$cert.Import("$(CertPath)", $password, [System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]"PersistKeySet")
Where $(CertPath) would be something like $(Build.SourcesDirectory)\SharedSolutionFiles\CertificateName.pfx
You can create a PowerShell script and add a PowerShell Script step in your build definition to import the certificate file before the VSBuild step.
Build failed without PowerShell Import Certificate Step:
Build passed with PowerShell Import Certificate Step:
The PowerShell Script I used:
$pfxpath = 'pathtoees.pfx'
$password = 'password'
Add-Type -AssemblyName System.Security
$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2
$cert.Import($pfxpath, $password, [System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]"PersistKeySet")
$store = new-object system.security.cryptography.X509Certificates.X509Store -argumentlist "MY", CurrentUser
$store.Open([System.Security.Cryptography.X509Certificates.OpenFlags]"ReadWrite")
$store.Add($cert)
$store.Close()
The better way is that you can setup a on premise build agent and import the certificate to certificate store, then change build agent service account to the same account.
Instead of using either an on premise build or loading the certificates on to the certificate stores on the build agent (which could be considered insecure) it is possible to overwrite the build task FileSign and construct one that uses a certificate file and password.
I have outlined the steps here:
https://stackoverflow.com/a/55313239/2068626
After failing to use methods in other answers, I found another way to use PowerShell script to import pfx certificate. my script was written for GitHub Actions but you can easily change the syntax to VSTS or Azure pipeline (using 'task: PowerShell#2' for azure pipeline for example). You may also like to update file path from github to your devops path. Also password can be replaced with a secured variable.
- name: Import certificate from the command-line
shell: pwsh
run: |
$Secure_String_Pwd = ConvertTo-SecureString "<password>" -AsPlainText -Force
Import-PfxCertificate -FilePath '${{github.workspace}}\<path>\project1_TemporaryKey.pfx' -CertStoreLocation Cert:\CurrentUser\My -Password $Secure_String_Pwd
Then build your Visual Studio ClickOnce project. The error should be gone.
After the build, you may like to remove the certificate from the machine. Here is a PowerShell example provided by Microsoft:
https://learn.microsoft.com/en-us/answers/questions/360772/powershell-commands-to-delete-personal-certificate.html
$users = "user1","user2","user3","user4","user5"
Get-ChildItem Cert:\CurrentUser\My | ForEach-Object {
$ifkeep = $false
foreach($user in $users){
if($_.Subject -match $user){
$ifkeep = $true
break
}
}
if($ifkeep -eq $false){
Remove-Item $_
}
}

Automatically sign powershell script using Get-PfxCertificate

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)"
}