Install a pfx certificate on a remote server with powershell - powershell

By following this,
Install certificate with PowerShell on remote server
I'm trying to install a pfx certificate on a remote server by using the following Powershell command,
Invoke-command -ComputerName myservername -scriptblock { Import-PfxCertificate –FilePath D:\pfxcert.pfx cert:\localMachine\my -Password (ConvertTo-SecureString -String "mypassword" -Force –AsPlainText) }
This is giving below error message for me...
The term 'Import-PfxCertificate' is not recognized as the name of a cmdlet, function, script file, or operable
program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
+ CategoryInfo : ObjectNotFound: (Import-PfxCertificate:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
+ PSComputerName : myservername
Please help me out on this.

The Cmdlet Import-PfxCertificate is part of the module PKIClient.
The PKI Client Cmdlets in Windows PowerShell are only available on
Windows 8.1
Windows PowerShell 4.0
Windows Server 2012 R2
Try to load the PKI Client in your Script:
Invoke-command -ComputerName myservername -scriptblock
{
Get-Command -Module PKIClient;
Import-PfxCertificate –FilePath D:\pfxcert.pfx cert:\localMachine\my -Password (ConvertTo-SecureString -String "mypassword" -Force –AsPlainText)
}
You could try Get-Command -Module PKIClient to see all cmdlets.

The Import-PfxCertificate cmdlet does not exist on the target machine. Probably because it is running a version of Powershell less than 3.
You'll have to install a newer version of PowerShell if possible, or find a different method of importing the certificate.

Well, if you need to call it from C# anyway, then it will be probably worth to install it from C#, like
using System.Security.Cryptography.X509Certificates;
X509Certificate2 certificate = new X509Certificate2("C:\TEMP\yourcerthere.pfx", "yourpasswordhere");
X509Store store = new X509Store(StoreName.TrustedPublisher, StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadWrite);
store.Add(certificate);
store.Close();
It will be approx the same code in powershell actually, since it's no other way but use .net system class or some tool like this.

Related

Set-Service : A parameter cannot be found that matches parameter name 'Credential'

I am trying to use a powershell script to change the login credential of a service. As per this Microsoft documentation (example 8), I am using the following code:
$credential = Get-Credential
Set-Service -Name serviceName -Credential $credential
When I run the script, I am prompted for a username and password, which I enter, but then the following error results:
Set-Service : A parameter cannot be found that matches parameter name 'Credential'.
At line:2 char:28
+ Set-Service -Name serviceName -Credential $credential
+ ~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Set-Service], ParameterBindingException
+ FullyQualifiedErrorId : NamedParameterNotFound,Microsoft.PowerShell.Commands.SetServiceCommand
What might be causing this? This machine is not on a domain, but I am logged on as a local administrator, and running powershell as an administrator. I have permissions to change these services and can enter the login details normally via the usual Services GUI.
The Credential parameter only exist for PowerShell version 6+ (which is out of support).
Probably you are using a version from before PowerShell 6 (most probably 5.1 which is still the main version in Windows 10 and 11).
See below Set-Service in:
PowerShell 5.1
PowerShell 6.0 (Archive)
PowerShell 7.0
Run $PSVersionTable.PSVersion, to your PowerShell version.
If you run (Get-Help -Name Set-Service).Parameters.parameter.Name, you'll find all the available Parameters in the active version.
If you're running 5.1 or older, the Get-Help -Name Set-Service -Parameter Credential should return the error "No parameter matches criteria.".
Installing or updating to PowerShell 7.X is as easy as running winget install Microsoft.PowerShell.
Why don't you want to use:
sc.exe config "[servicename]" obj= "[.\username]" password= "[password]"
If you want the user to enter a username/password each time, then you can use:
$cred = Get-Credential
$username = $cred.username
$password = $cred.GetNetworkCredential().password
&sc.exe config "[servicename]" obj= "$username" password= "$password"
if you need to check that the username and password are valid, then you can use:
$currentdomain = "LDAP://" + ([ADSI]"").distinguishedName
$domain = New-Object System.DirectoryServices.DirectoryEntry($currentdomain,$username,$password)
if ($domain.name -eq $null) {
write-host "Authentication failed - please verify your username and password."
exit
}
else {
write-host "Successfully authenticated with domain $domain.name"
}

When using a function within a Powershell module, a psm1, is it possible to export the ExchangeOnline functions to be accessible in the console?

Working on several Powershell functions which connect to Office365 services and automate many of my usual tasks. Found when I have the function in a psm1, running the function to connect to ExchangeOnline the functions are not exposed to the console and only functions within the same module.
While I know I can export-modulemember, this only works for functions when the module is loaded, happens well before I connect-office365 -exchangeonline.
Is there anyway to export the commands loaded when connecting to Office 365 after connecting?
By placing the following function in a psm1 instead of a ps1 and loading it, and then running connect-off365 -exchangeonline, all Exchange Online related commands are not usable in the console. Yet, having the same function in a ps1 and loading it, the ExchangeOnline functions work.
Function Connect-Office365 {
Param(
[Switch]$ExchangeOnline,
[Switch]$EO
)
if ($EO) { $ExchangeOnline = $true }
elseif ($EO -and $ExchangeOnline) { Write-Warning "No need to declare ExchangeOnline and EO" }
$Credential = Get-Credential -message "Enter Office 365 credentials,`r`nor cancel to not connect to Office 365"
if ($null -eq $Credential) { Write-Host "Skipped entering credentials"; $TryAgain = $False }
if ($ExchangeOnline) {
Write-Host "Connecting to Exchange Online Services"
$global:ExchangeSession = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Credential $Credential -Authentication Basic -AllowRedirection -EA stop
Import-PSSession $global:ExchangeSession -AllowClobber -DisableNameChecking
}
}
For example
PS C:\Users\TechWithAHammer> import-module C:\scripts\Connect-Office365.psm1
PS C:\Users\TechWithAHammer> connect-office365 -eo Connecting to MSOL Services Connecting to Exchange Online Services
ModuleType Version Name ExportedCommands
---------- ------- ---- ----------------
Script 1.0 tmp_3zvdxnnc.gd0 {Add-AvailabilityAddressSpace, Add-DistributionGroupMember...
PS C:\Users\TechWithAHammer> get-mailbox
get-mailbox : The term 'get-mailbox' is not recognized as the name of a cmdlet, function, script file, or operable
program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At line:1 char:1
+ get-mailbox
+ ~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (get-mailbox:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
As per the answer in Commands from implicit remoting module not available when created from another module's function, found that I had to use Import-Module to import the Exchange Online and Compliance and Security center modules into the global session.
Import-Module (Import-PSSession $global:ExchangeSession -AllowClobber -DisableNameChecking) -Global

Use Connect-SPOService with Powershell 6 (core version)

I'm trying to connect to a sharepoint environment and I want to do that with Powershell version 6. Why? Eventually, I want to put the PS commands in a .net core 3 application. And as far as I know I cannot use PS5.1 in .net core.
It is about this powershell script:
Import-Module -Force -name Microsoft.Online.SharePoint.PowerShell;
Import-Module -Force -name Microsoft.Online.SharePoint.PowerShell -DisableNameChecking;
$username = 'admin#shootme.com';
$password = 'right now';
$cred = New-Object -TypeName System.Management.Automation.PSCredential -argumentlist $userName, $(convertto-securestring $Password -asplaintext -force);
Connect-SPOService -Url https://shootme.sharepoint.com -Credential $cred;
When I try this in the default PS 5.1 it just works fine. When I try this with PS 6.2.3, I get an error:
Connect-SPOService : The remote server returned an error: (400) Bad Request.
At line:1 char:1
+ Connect-SPOService -Url https://shootme.sharepoint.com -Credent ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Connect-SPOService], WebException
+ FullyQualifiedErrorId : System.Net.WebException,Microsoft.Online.SharePoint.PowerShell.ConnectSPOService
Does the newer Powershell have different syntax orso, of what am I doing wrong?
Also, maybe there is a way to run scripts in ps 5.1 when running them in .net core?
Have you tried connecting manually by removing the credentials portion and letting it prompt you for a login and test if that resolves successfully?
Edit: I do know you can also call powershell from a .bat like so:
powershell -version 2 .\xyz.ps1
But not knowing what you're going for exactly makes it tough to suggest if that's even a viable option.

Get-CsUser error powershell

I am running this command in powershell Get-CsUser and i am getting the following error
Get-CsUser : The term 'Get-CsUser' is not recognized as the name of a
cmdlet, function, script file, or operable program. Check the spelling
of the name, or if a path was included, verify that the path is
correct and try again. At line:1 char:1
+ Get-CsUser
+ ~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (Get-CsUser:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
What do I have to do to avoid this error? I have imported:
Import-Module "C:\Program Files\Common Files\Skype for Business Online\Modules\SkypeOnlineConnector\SkypeOnlineConnector.psd1"
and then made connection to Office 365 Skype for business service with the following script:
$credential = Get-Credential
Import-Module MSOnline
Connect-MsolService -Credential $credential
Import-Module SkypeOnlineConnector
$lyncSession = New-CsOnlineSession -Credential $credential
Import-PSSession $lyncSession
Does anyone knows what's the cause of this error?
Does anyone knows what s the cause of this error? thank you in advance
Problem is office 365 skype for business does not have a command "Get-CsUser" under User cmdlets.
Available User cmdlets are as follows.
Set-CsUser
Get-CsUserPstnSettings
Set-CsUserPstnSettings
Get-CsUserSession
Source "Skype for Business Online cmdlets"
Get-CsUser is available for on-premises lync servers.
.
PS:
Your connection for "office 365 skype for business" and the session import should be ok, for example if you type Get-CsUserSession, it should not say "The term 'Get-CsUserSession' is not recognized as the name of a cmdlet, function, script file, or operable program"
(1) You can view available commands in your imported module using below
Get-Command -Module MSOnline
Get-Command -Module SkypeOnlineConnector
(2) You can also view available commands in your current session by using Get-Command and your temporary session name.
Get-Command -Module tmp_aqu5qmxt.frb
tmp_aqu5qmxt.frb is my temperory session id name .. change it to whatever you get at this screen.
(3) To view all imported commands from all your sources, (modules+sessions) you can use,
Get-Command -ListImported
None of them has a command called "Get-CsUser"
In Skype for Business Online you should use Get-CsOnlineUser instead of Get-CsUser.
As stated in the documentation os Get-CsUser it's not available for Skype for Business Online.
If you use Get-Command Get-Cs*User you'll find only the following 3 commands:
Get-CsOnlineDialInConferencingUser
Get-CsOnlineUser
Get-CsOnlineVoiceUser
The second one is the one you should use to display users homed online. I already requested a change to MS documentation to include that as a hint, hopefully they you'll accept that.

Running a Setup.exe from a network share, via Invoke-Command in Powershell

PSEXEC started to give me some trouble, and I decided to recode in PowerShell.
This batch command used to work for me, before PSEXEC started messing things up:
psexec -accepteula \\<ServerToBeUpdated> -u <User> -p <Password> cmd /c "\\<ServerWithInstallationFile>\SystemEnv\Bin\Setup.exe /silent /Update"
I'm trying to do this with Invoke-Command in Powershell, but with no luck so far.
I've tried many combinations, and googled a lot, and overall it seems that PowerShell is not fond of the UNC path I'm trying to install from.
Here is what I've got:
Invoke-Command -ComputerName <ServerToBeUpdated> -ScriptBlock { Start-Process -FilePath "\\<ServerWithInstallationFile>\SystemEnv\Bin\Setup.exe" -ArgumentList "/update /silent" -wait }
I get this error message:
This command cannot be run due to the error: Access is denied.
+ CategoryInfo : InvalidOperation: (:) [Start-Process], InvalidOperationException
+ FullyQualifiedErrorId : InvalidOperationException,Microsoft.PowerShell.Commands.StartProcessCommand
+ PSComputerName : DE5441
Some people say that the setup.exe has be copied locally on the remote server. But this does not seem to be an option for me, mainly for two reasons.
My setup.exe identifies that it is not in the right path, then it kills the local the setup.exe process, and automatically starts a new setup.exe from the UNC path.
I also need the ExitCode from my setup.exe, which gets lost when the "killing" starts as mentioned in reason number 1.
As a final note, I did grant access for PowerShell to run remotely with the Enable-PSRemoting command, and I also get expected results from this simple test:
Invoke-Command -ComputerName <ServerToBeUpdated> -ScriptBlock { Hostname }
You are experiencing a so called double-hop authentication issue. If using normal authentication you will not be able to authenticate to a second computer from the machine you are invoking the command on.
To solve this you can use CredSSP.
To enable CredSSP on the machine that is being called:
Enable-WSManCredSSP -Role Server -force
To enable CredSSP on the client:
Enable-WSManCredSSP -Role Client -DelegateComputer server.domain.com -force
The -delegateComputer parameter expects a FQDN but also takes wildcards.
After enabling CredSSP you can use it to invoke your command with the parameter -authentication CredSSP