Access denied while running Windows Update using Powershell's Invoke-Command - powershell

I've been trying to setup a Powershell module that would remotely call Windows/Microsoft update on a server using Invoke-Command, then process the updates, and send everything back to the calling server so it can send an email report.
My issue comes when I try and call the downloader: Powershell seems to be requesting Elevated rights on the remote computer.
Here is a snippet of what I'm trying to run and fail:
Invoke-Command -ComputerName $Server -Credential $Credentials -ScriptBlock {
$UpdateSession = New-Object -ComObject "Microsoft.Update.Session"
Write-Progress -Activity "Updating" -Status "Checking for new updates"
$Criteria = "IsInstalled=0 and Type='Software'"
$Updates = $UpdateSession.CreateUpdateSearcher().Search($Criteria).updates
$Downloader = $UpdateSession.CreateUpdateDownloader()
$Downloader.Updates = $Updates
}
I know the issue isn't with remoting, as the first 4 commands work fine.
The $Credentials variable points to pre-defined credentials, which are Local Admin on the remote server.
When the script gets to the 5th line, $Downloader = $UpdateSession.CreateUpdateDownloader(), I get this error from Powershell:
Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))
+ CategoryInfo : OperationStopped: (:) [], UnauthorizedAccessException
+ FullyQualifiedErrorId : System.UnauthorizedAccessException
+ PSComputerName : SERVER.sidlee.inc
What could be causing this exactly ?
Thanks in advance for the help!

As i just hit the same wall, and Google isn't of much help either, here is what i could dig up.
For the record, i am pretty much doing the same thing (using custom PS code to check remote systems for Windows Updates) but using WinRM over Python instead of Invoke-Command and also got stuck on Microsoft.Update.Searcher.Search() throwing a E_ACCESSDENIED error.
The UnauthorizedAccessException is indeed not related to Powershell but the underlying API.
I suspect Microsoft started cutting off impersonation in remote session in some recent update (Powershell v5?) as this was (and still is) working just fine on older Windows versions (e.g. Server 2012 with Powershell v3 or 2012 R2 with v4)
To get around this you will need to authenticate (on the remote server) prior to executing your stuff with a PSCredential object.
So Remote Auth -> Local Auth -> Run stuff for example using Start-Process -Credential ...
e.g.
$pass = ConvertTo-SecureString "PA$$W0RD" -AsPlainText -Force
$creds = New-Object System.Management.Automation.PSCredential "User", $pass
Start-Process -Credential $creds powershell -ArgumentList "-Command & { ... whatever you want to do ... }"
Keep in mind that this poses a security risk as your password will be parsed in clear text, so don't do this over an
unencrypted channel!

Related

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.

How to Install Windows Updates on Remote Computer with PowerShell

I'm trying to install Windows Updates on a Remote Computer with this command:
$InstallSplat = #{
AcceptAll = $true
SendReport = $true
IgnoreReboot = if ($Reboot) { $false } else { $true }
PSWUSettings = #{
SmtpServer = "my mail server"
From = "myfrom <myfrom#myfrom.com>"
To = "myto <myto#myto.com>"
Port = 25
}
}
Invoke-Command -ComputerName $_ -Credential $cred -AsJob -ArgumentList $InstallSplat -ScriptBlock {
param([hashtable]$InstallSplat)
Import-Module PSWindowsUpdate
Install-WindowsUpdate #InstallSplat
$Error | out-file C:\install\installwinupdate.log -Append
}
I pass a credential Object with domain admin privileges in $cred but I still always get this error
Install-WindowsUpdate : Access denied (Ausnahme von HRESULT: 0x80070005 (E_ACCESSDENIED)) In Zeile:4 Zeichen:25
+ Install-WindowsUpdate #InstallSplat
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Get-WindowsUpdate], UnauthorizedAccessException
+ FullyQualifiedErrorId : System.UnauthorizedAccessException,PSWindowsUpdate.GetWindowsUpdate
The Command Install-WindowsUpdate itself does not have a credential parameter I could use. The Command needs to run in an elevated PowerShell, but I use an elevated PowerShell when starting this command on my Computer.
I Also tried creating a New-PSSession with my $cred and run Invoke-Command -Session $session instead of Invoke-Command -ComputerName $_ with the same result.
Does anybody know what's happening here? Why do I get Access denied?
It can't have anything to do with passing the $InstallSplat because the same thing happens if I don't pass any parameter at all and write the parameters and their Values directly at the command instead of splatting.
The Problem was, that you can't Download or Install Updates on a machine from another remote machine. Here's a list what you can or can't do remotely when it comes to Windows Updates
The solution is, to create a scheduled task on each server you want to install updates from a remote script, and start that task.
luckily, when you use the PSWindowsUpdate module, you don't have to do that yourself, you can just use Invoke-WUJob (formerly Invoke-WUInstall) which does the trick for you.
I used it like so ($ServerData.Value contains a list of my Servers) and it works like a charm. It creates a scheduled task on each server, and runs them immediately, if you add the -RunNow Parameter.
invoke-WUJob -ComputerName $ServerData.Value -Script { Import-Module PSWindowsUpdate ; Install-WindowsUpdate -AcceptAll -SendReport -IgnoreReboot -PSWUSettings #{From='xy';Port=25;SmtpServer='xy';To='xy'} | Out-File C:\install\PSWindowsUpdateLog.txt -Append} -Confirm:$false -verbose -RunNow
Note that what you specify as a script block in -Script will be pasted to -Command " <here> " in your scheduled task, so you should work with ' inside -Script.

Powershell, svn, and authentication

I can remote desktop into a given machine and run svn, without giving authentication information, and it works; my AD authentication allows me access to the repository I want.
I can use Powershell to connect to the machine and execute svn commands, as well. However, when I do, I get "access forbidden". [Environment]::UserName appears with the username I expected (my AD username) when run from the script that's being remotely executed.
What am I missing to make this work?
Some code:
$Session = New-PSSession -ComputerName $computerName;
if (-Not ($Session)) {
Write-Host "Did not create session!";
Return;
}
Invoke-Command -Session $Session -FilePath 'switchAllRepositories.ps1' -ArgumentList $branchName;
Remove-PSSession $Session;
and in switchAllRepositories, I have a parameter:
Param(
[string]$branchURL
)
a series of calls like:
If(Test-Path "C:\webfiles\repositoryname") {
Write-Host "Switching repositoryname"
SwitchRepo "repositoryname" ($branchURL) "C:\webfiles\repositoryname";
}
which call:
Function SwitchRepo ($repoName, $branchPath, $workingCopy)
{
$to = ("https://[url]/svn/" + $repoName + $branchPath);
Write-Host "to $to";
#debug
$user = [Environment]::UserName
Write-Host "as $user";
$exe = "C:\Program Files\TortoiseSVN\bin\svn.exe";
&$exe switch "$to" "$WorkingCopy" --username [redacted] --password [redacted] --no-auth-cache --non-interactive --trust-server-cert
if ($process.ExitCode -ne 0) {
#$wshell = New-Object -ComObject Wscript.Shell
#$wshell.Popup("Error switching " + $repoName,0,"Done",0x1)
Write-Host "Error detected!"
}
}
The exact error is:
svn: E175013: Unable to connect to a repository at URL
'[snipped]'
+ CategoryInfo : NotSpecified: (svn: E175013: U...eases/20150620':String) [], RemoteException
+ FullyQualifiedErrorId : NativeCommandError svn: E175013: Access to '[snipped]' forbidden
It would help to see the code you're using, but if it's what I suspect then you're using PowerShell remoting with either Enter-PSSession or Invoke-Command.
Since those will default to using kerberos authentication, and the SVN server is probably on a 3rd machine, you're likely running into the kerberos double-hop authentication issue.
Simply put, you can't remote into machine B from machine A, then from within that session try to access machine C using the same authentication context.
You may be able to workaround this in a few ways: CredSSP is often brought up in these but I find it's complicated and typically a re-thinking of the workflow turns out better.
So for example, you might be able to explicitly specify credentials for the SVN commands.
Or, you can create your own endpoint on the server that uses a RunAs user. Then all the commands will be from Machine B as a specific user:
https://stackoverflow.com/a/30061125/3905079
https://stackoverflow.com/a/26077172/3905079

Powershell : Accessing shared drive from remote server

I am trying to access shared drive vai remote server in my Powershell script. My code is below:
$bypass1 = "config"
$bypass2 = "web.config"
$Username = "test\newtest"
$Password = "xxxxxxxxx"
$srv = "xxx.xxx.xxx.xxx"
$securePassword = ConvertTo-SecureString -AsPlainText -Force $Password
$cred = New-Object System.Management.Automation.PSCredential $Username, $securePassword
$session = New-PSSession -ComputerName $srv -port 22 -Credential $cred
Invoke-Command -Session $session -ScriptBlock {
$computer = "xxx.xxx.xxx.xxx"
test-path \\$computer\netlog\php
Get-ChildItem \\$computer\netlog\
}
Remove-PSSession -Session $session
When I tried to access shared from Remote Desktop Connection on the server it is working but through powershell it is throwing following error.
False
Cannot find path '\\xxx.xxx.xxx.xxx\netlog\' because it does not exist.
+ CategoryInfo : ObjectNotFound: (\\xxx.xxx.xxx.xxx\netlog\:String) [Get-Ch
ildItem], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetChildItemCom
mand
+ PSComputerName : xxx.xxx.xxx.xxx
I am having Powershell 4 and remote server is windows 2008 R2.
Regards,
Vj
Did you try accessing the following path \\xxx.xxx.xxx.xxx\netlog\ locally? You have the creds to access the server. And also you say the drive is shared. Try accessing the path locally. Not via power-shell. But try the old fashioned way. Using Run. If you are prompted for any credentials to be entered. You may strike off any issues related to permissions. If not... The folder you are trying to access isn't shared at all. Try giving it the required permissions. If this isn't the case please leave a comment.
You might need to enable Multihop Remoting when you access a share from a remote machine and use CredSSP.
The credentials you use to create the remote session are not passed to the share access action by default. I think everyone runs into this problem at least once. :)
http://blogs.technet.com/b/heyscriptingguy/archive/2013/04/04/enabling-multihop-remoting.aspx
http://blogs.technet.com/b/heyscriptingguy/archive/2012/11/14/enable-powershell-quot-second-hop-quot-functionality-with-credssp.aspx

Connect-MsolService error after importing MSOnline module

I'm receive the following error when I run Connect-MsolService -
Exception of type 'Microsoft.Online.Administration.Automation.MicrosoftOnlineException' was thrown.
+ CategoryInfo : OperationStopped: (:) [Connect-MsolService], MicrosoftOnlineException
+ FullyQualifiedErrorId : 0x80090345,Microsoft.Online.Administration.Automation.ConnectMsolService
+ PSComputerName : xxxxx
Background -
I am using powershell to manage Active Directory, Exchange and Sharepoint Online user data. I have an SSIS package that dynamically builds arguments passed to powershell scripts for creating new and updating existing AD user data, adding/updating necessary security and distribution groups for each user, enabling exchange mailboxes, and passing custom attribute data to Sharepoint online user profiles.
In effort to maintain the purity of the SQL server running the SSIS package, dynamic sessions are created to servers having the modules necessary for import. This allows me to do all of the things mentioned above without having to install the different modules on my SQL server.
My final hurdle is automating the Office 365 licensing. To script licensing assignments I create a session to our server having the necessary MSOnline module and import it giving me access to the Cmdlets, like Set-MsolUserLicense. However, before I can use the Cmdlets I have to connect to the MSOLService.
When I run Connect-MsolService, the credentials modal pops as expected, the appropriate credentials are entered (which have been verified a thousand times over), and I receive the error shown above.
These commands all work fine when I run them from the server where the MSOnline cmdlets are installed, but return the error when run post successful import-module on my SQL server.
Here are the commands used for establishing the session and importing the MSOnline module -
$securePassword = ConvertTo-SecureString $Password -AsPlainText -Force
$cred = new-object -typename System.Management.Automation.PSCredential -argumentlist $Username, $securePassword
$outputSession = $Null
foreach($session in Get-PSSession){
if(($session.ComputerName -eq $Server) -and ($session.Availability -eq "Available")){
$outputSession = $session
}
}
if ($outputSession -eq $Null){
$outputSession = New-PSSession -ComputerName $Server -Credential $cred -Name 'MSOnline'
Invoke-Command -Session $outputSession -ScriptBlock {Import-Module MSOnline}
Import-PSSession -session $outputSession -module MSOnline -AllowClobber
}
Connect-MSOLService is the only Cmdlet giving me an issues using these methods. Any help you can provide will be appreciated.
Sigh. This appears to be a bug with single sign on assistant and MSOL module. I have had this issue reproduced reliably and had it reported to Office 365 support. It went nowhere. To state it simply, Connect-MSOnline works only in local sessions.
Mind you, MSOL module is a very strange beast, it is not using PSSession to maintain connection with Azure but uses some internal mechanisms that must rely on single sign-on assistant. This may be why in remote session MSOL commandlet cannot connect to Azure AD.
It was a dead end for me, and the only way to work around it is to write an application that runs on the server using MSOL module and accepts commands from the client or is invoked on server directly via service or scheduled task.