Powershell, svn, and authentication - powershell

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

Related

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.

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

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!

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

How to run w32tm in non-elevated powershell

I am writing a helper script that will go through a list of servers and verify they are in sync with the NTP. The script shall be run as a normal script on request by the facility operator and shall request for Admin credentials if the target is not in sync. We unfortunately cannot change the NTP configuration at the moment so we have to make workaround.
What I have right now (and it works beautifully if the script is run as administrator) is a command ("w32tm /query /status" of a remote computer) that is executed via "Invoke-Command" so I can pass it Admin credentials.
My idea was to avoid using WinRM since the hostname resolution is not working properly in our system (it requires some painful host-to-IP-and-back-to-proper-hostname resolution) which makes the WinRM useless.
The command w32tm can obtain status of a remote computer but it needs to be run as administrator for it.
In both cases (run as administrator and run as normal user and later providing the credentials) the $script is executed as domain\administrator (confirmed with the check of Admin role and the "WhoAmI" command) but the status is only obtained when the whole script is executed as administrator.
For the execution as normal user I receive the error:
The following error occurred: Access is denied. (0x80070005)
All machines I use obviously allow remote execution since it works with administrator user.
So basically my question is why is the "w32tm ..." command not allowed in the $script if the role of the user is appropriate (it is administrator role) for the task?
The part of the script which I can't resolve:
function synchronize_remote_machine ($target, $username, $cred)
{
$script = {
param( [String] $compName )
$user = [Security.Principal.WindowsIdentity]::GetCurrent();
$userIsAdmin = (New-Object Security.Principal.WindowsPrincipal $user).`
IsInRole([Security.Principal.WindowsBuiltinRole]::Administrator)
if (-not $userIsAdmin)
{
Write-Warning "You do not have Administrator rights to run this script!`n
Please re-run this script as an Administrator!"
}
else
{
whoAmI
w32tm /query /status /computer:$compName
#w32tm /resync /rediscover /computer:$compName
}
}
# resync via WinRM
try
{
#execute_resync_command $target $username $cred
if ($username -eq 'Administrator')
{
# when run as admin
invoke-command -ScriptBlock $script -ArgumentList $target;
}
else
{
# for normal user the initalized credential cals is used
invoke-command -computername "localhost" -Credential $cred -ScriptBlock $script -ArgumentList $target
}
}
catch
{
Write-Error "Error executing resync command on host $target."# -foregroundcolor "red"
throw
}
}
Rather than (re-)running the script with elevated privileges, I'd grant the operators group the SeSystemtimePrivilege on those servers. You can do that either with a group policy or by running ntrights.exe from the Server 2003 Resource Kit Tools on each server:
ntrights +r SeSystemtimePrivilege -u DOMAIN\operators
Even if you execute it as administrator, do to try to run you script in an elevated process ?
You can acheive that using Start-Process CmdLet.
start-process 'c:\system32\WindowsPowerShell\v1.0\powershell.exe' -verb runas -argumentlist "-file YourScript.ps1"

invoke command on remote machine is not working using powershell

I ran the below commands on my machine to download data from one server to another server using the invoke command
Enable-PSRemoting -force
Enter-PSSession Server1
invoke-command -computername Server1 -credential:'dom\jack' {c:\temp.ps1 -server serverX -id 4231e429-d238-4e32-a1bb-0ee812cd3124 -download $true}
ERROR is: Failed: Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))
but when i run the above command on my machine as
c:\temp.ps1 -server serverX -id 4231e429-d238-4e32-a1bb-0ee812cd3124 -download $true
it works as expected.
Is there something i am missing when i execute it remotely....please help me.
thanks
Try this good References:
http://www.ravichaganti.com/blog/?p=1108
http://technet.microsoft.com/en-us/magazine/ff700227.aspx
It might be something to do with the TrustedHosts or Authentication
setting of a client. You can set it like this:WinRM set
winrm/config/client #{TrustedHosts="*"}
Read more about this here:
http://blogs.dirteam.com/blogs/sanderberkouwer/archive/2008/02/23/remotely-managing-your-server-core-using-winrm-and-winrs.aspx
I use
powershell.exe -ExecutionPolicy Unrestricted -WindowStyle Hidden -NoLogo
I use this code:
try
{
Invoke-Command -credential $testCred -computer $ServerName -scriptblock {
param([String]$scriptDeploy, [String]$destino) &"$scriptDeploy" 'parametro1' $destino
$ScriptBlockOutput = $Error
} -ArgumentList $RutaRemotaParaScriptDeInstalacion, "$dirRemotoDestino"
"`r`n`r`nOK para script de despliegue"
exit 0;
}
catch
{
"`r`n`r`nError en script de despliegue"
"`r`nError in " + $_.InvocationInfo.ScriptName + " at line: " + $_.InvocationInfo.ScriptLineNumber + ", offset: " + $_.InvocationInfo.OffsetInLine + ".";
exit -1
}
You need to enable remoting on the remote machine. You also need to make sure the firewall/anti virus does not block the remoting ports. These are port 5985 for http, or port 5986 for https.
If both machines on the same domain it's fairly easy to get working. If the machines are on different domains however then it's more complex. There's a registry setting that needs to be changed on the remote server, and you need to pass credentials. Have a read here for more info. There is of course ssl which can also be enabled, but that's another story.
There is a bug in your script.
You should not be executing Enter-PSSession before the Invoke-Command, because the Invoke-Command itself sets up the PSSession.
Use only this:
Invoke-command -computername Server1 -credential:'dom\jack' {c:\temp.ps1 -server serverX -id 4231e429-d238-4e32-a1bb-0ee812cd3124 -download $true}
... Without the Enter-PSSession