Script to Add a Computer to Our Domain Is Failing - powershell

I am just trying out Powershell scripting for the first time and am having a hard time figuring out the issue with a script that is failing when adding a computer to our domain. The majority of the script is pulled from a functional one we already use in our environment, and I modified it to change the name of the computer when adding it. Here is the relevant code:
$DeptName = "JACCSV"
$NewName = $DeptName + $($env:computername)
Add-Computer -Domain "notareal.domain" -Credential $joinCred -NewName $NewName -Restart
Edit: After more testing, the script works if it is run in an elevated powershell instance, but I am unsure why this doesn't work when pushed from Altiris, while our other script to add to our domain does.

Related

How to move file on remote server to another location on the same remote server using PowerShell

Currently, I run the following command to fetch the files to my local system.
Get-SCPFile
-ComputerName $server
-Credential $credential
-RemoteFile ($origin + $target + ".csv")
-LocalFile ($destination + $target + ".csv")
It works as I'd like (although it sucks that I can't copy multiple files by regex and/or wildcard). However, after the operation has been carried out, I'd like to move the remote files to another directory on the remote server so instead of residing in $origin at $server, I want them to be placed in $origin + "/done" at the same server. Today, I have to use PuTTY for that but it would be so much more convenient to do that from PS.
Googling gave me a lot of material but I couldn't make it work. At the moment, I'm not sure if I'm specifying the path incorrectly somehow or if it's not possible to use the plain commands when working against an external, secured, Unix-server.
For copying files, I can't use Copy-Item, hence the function Get-SCPFile. I can imagine that remote moving, renaming and listing the items isn't possible neither for the same reason (whatever that reason is).
This example as well as this one produce error cannot find path despite the value being used for copying the file successfully with the script at the top. I'm pretty sure it's a misleading error message (not being enitrely sure, though).
$file = "\\" + $server + "" + $origin + "" + $target + ".csv"
# \\L234231.vds.afm.se/var/trans/ut/drish/sxx/meta001.csv
Remove-Item $file -force
Many answers (like this) are very simple, which supports my theory that the combination of Unix and secure raise an extra challenge. Perhaps I'm wording the question insufficiently well.
There's also more advanced examples, still not working, just hanging up the window with no error messages. I feel my competence prevents me from estimating the degree of screwuppiness in this approach.
In PowerShell you can create a PowerShell Session (PSSession) from your System remotly on another System (and into another Session on your System but thats details... ) and execute your commands there.
You can create a PSSession with New-PSSession but a lot of cmdlets have a-ComputerName parameter (or something similar) so that they can be executed remotley without creating a PSSession first.
A PSSession can be used with Enter-PSSession to get an interactive Session or with Invoke-Command to execute a ScriptBlock. That way you could test your Remove-Item command directly on the target server. Depending on the setup you might need to use Linux syntax within the remote session.
Here are some more infos about_PSSessions and using it with SSH to connect to Linux

Powershell calls another PS1 in loop finishes after first foreach loop run completes

I have 2 Powershell scripts, one which is the primary (ServerInfo.ps1) and a secondary script which is intended to work as a wrapper, launching the first script within a loop that will use different credentials on each loop due to queries being made to different AD Domains/Forests that require different domain creds for each respective domain.
The primary script runs fine when run on its own if I run it manually and locally from a machine in each respective domain, and does as needed (grabbing details from remote machines and exporting to a csv)
The following is the Wrapper script (domain name examples changed for security reasons).
# This is a Wrapper Script for ServerInfo.ps1
$username = Read-Host -Prompt 'Enter User Account to be used - Do not specify domain'
$Password = Read-Host -Prompt 'Input User Password - NOTE must be the same on all domains' -AsSecureString
$domains = "d1.contoso.com","d2.contoso.com","dev.contosodev1.com","test.contosotest1.com"
$Arguments = "-file c:\serverinfo\ServerInfo.ps1", "-ServerType 'DCs'"
ForEach ($domain in $domains) {
$Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList "$domain\$username", $Password
Start-Process powershell.exe -Credential $credential -NoNewWindow -ArgumentList $Arguments -WorkingDirectory 'c:\Serverinfo\' -Wait
}
Specifically this will be used to query Domain Controllers with an elevated permissions account that is identical on each domain, as the account used on member computers does not have Builtin Admin or AD (Domain/Enterprise Admin) level rights on the Domain Controllers. The intention is also to run the scripts from a Domain member, not locally on a DC.
As the primary script (serverinfo.ps1) is over 1000 lines of code, I will simply say that with the wrapper passing the argument "-ServerType DCS", ServerInfo.ps1 initially grabs all Domain Controller names from AD of the respective domain the account belongs to, and performs things such as WMI & Registry queries of each DC, exporting the output to a CSV file.
For the first domain, this runs fine without any issue and the ServerInfo.ps1 script does it job querying every DC in the first domain, but then both PowerShell scripts close/stop running without it continuing to the second domain in the wrapper loop aka, the "foreach ($Domain in $Domains)" loop is not working once the first domain completes.
As I don't see any scripting error in the wrapper, and there is no Exit or other cancellation/Finish command in ServerInfo.Ps1, I am at a loss as to why the wrapper is not working as expected.
For the first domain, this runs fine without any issue and the
ServerInfo.ps1 script does it job querying every DC in the first
domain, but then both PowerShell scripts close/stop running without it
continuing to the second domain in the wrapper loop aka, the "foreach
($Domain in $Domains)" loop is not working once the first domain
completes.
I am pretty sure that your loop works. Just insert a Write-Host "Iteration for domain: $domain" inside that loop and you will see, that it indeed iterates over all domains.
I am more concerned about the way you call that other script. With Start-Process -Credential the process will be executed in the user space of the provided user. In your scenario, this will require any trust relationships between your domains, if you want to run it on any domain computer for all domains. Do you have any?
If not, you have to pass the credentials to the called script in some secure way, so that it can authenticate itself when using remote control cmdlets.

Powershell - Copying File to Remote Host and Executing Install exe using WMI

EDITED: Here is my code now. The install file does copy to the remote host. However, the WMI portion does not install the .exe file, and no errors are returned. Perhaps this is a syntax error with WMI? Is there a way to just run the installer silently with PsExec? Thanks again for all the help sorry for the confusion:
#declare params
param (
[string]$finalCountdownPath = "",
[string]$slashes = "\\",
[string]$pathOnRemoteHost = "c:\temp\",
[string]$targetJavaComputer = "",
[string]$compname = "",
[string]$tempPathTarget = "\C$\temp\"
)
# user enters target host/computer
$targetJavaComputer = Read-Host "Enter the name of the computer on which you wish to install Java:"
[string]$compname = $slashes + $targetJavaComputer
[string]$finalCountdownPath = $compname + $tempPathTarget
#[string]$tempPathTarget2 =
#[string]$finalCountdownPath2 = $compname + $
# say copy install media to remote host
echo "Copying install file and running installer silently please wait..."
# create temp dir if does not exist, if exist copy install media
# if does not exist create dir, copy dummy file, copy install media
# either case will execute install of .exe via WMII
#[string]$finalCountdownPath = $compname + $tempPathTarget;
if ((Test-Path -Path $finalCountdownPath) )
{
copy c:\hdatools\java\jre-7u60-windows-i586.exe $finalCountdownPath
([WMICLASS]"\\$targetJavaComputer\ROOT\CIMV2:win32_process").Create("cmd.exe /c c:\temp\java\jre-7u60-windows-i586.exe /s /v`" /qn")
}
else {
New-Item -Path $finalCountdownPath -type directory -Force
copy c:\hdatools\dummy.txt $finalCountdownPath
copy "c:\hdatools\java\jre-7u60-windows-i586.exe" $finalCountdownPath
([WMICLASS]"\\$targetJavaComputer\ROOT\CIMV2:win32_process").Create("cmd.exe /c c:\temp\java\jre-7u60-windows-i586.exe /s /v`" /qn")
}
I was trying to get $Job = Invoke-Command -Session $Session -Scriptblock $Script to allow me to copy files on a different server, because I needed to off load it from the server it was running from. I was using the PowerShell Copy-Item to do it. But the running PowerShell script waits until the file is done copying to return.
I want it to take as little resources as possible on the server that the powershell is running to spawn off the process on another server to copy the file. I tried to user various other schemes out there, but they didn't work or the way I needed them to work. (Seemed kind of kludgey or too complex to me.) Maybe some of them could have worked? But I found a solution that I like that works best for me, which is pretty easy. (Except for some of the back end configuration that may be needed if it is is not already setup.)
Background:
I am running a SQLServer Job which invokes Powershell to run a script which backups databases, copies backup files, and deletes older backup files, with parameters passed into it. Our server is configured to allow PowerShell to run and under the pre-setup User account with SQL Server Admin and dbo privileges in an Active Directory account to allow it to see various places on our Network as well.
But we don't want it to take the resources away from the main server. The PowerShell script that was to be run would backup the database Log file and then use the another server to asynchronously copy the file itself and not make the SQL Server Job/PowerShell wait for it. We wanted it to happen right after the backup.
Here is my new way, using WMI, using Windows Integrate Security:
$ComputerName = "kithhelpdesk"
([Wmiclass]'Win32_Process').GetMethodParameters('Create')
Invoke-WmiMethod -ComputerName RemoteServerToRunOn -Path win32_process -Name create -ArgumentList 'powershell.exe -Command "Copy-Item -Path \\YourShareSource\SQLBackup\YourDatabase_2018-08-07_11-45.log.bak -Destination \\YourShareDestination\YourDatabase_2018-08-07_11-45.log.bak"'
Here is my new way using passed in Credentials, and building arg list variable:
$Username = "YouDomain\YourDomainUser"
$Password = "P#ssw0rd27"
$ComputerName = "RemoteServerToRunOn"
$FromFile = "\\YourShareSource\SQLBackup\YourDatabase_2018-08-07_11-45.log.bak"
$ToFile = "\\YourShareDestination\SQLBackup\YourDatabase_2018-08-07_11-45.log.bak"
$ArgumentList = 'powershell.exe -Command "Copy-Item -Path ' + $FromFile + ' -Destination ' + $ToFile + '"'
$SecurePassWord = ConvertTo-SecureString -AsPlainText $Password -Force
$Cred = New-Object -TypeName "System.Management.Automation.PSCredential" -ArgumentList $Username, $SecurePassWord
([Wmiclass]'Win32_Process').GetMethodParameters('Create')
Invoke-WmiMethod -ComputerName $ComputerName -Path win32_process -Name create -ArgumentList $ArgumentList -Credential $Cred
We think that this above one is the preferred one to use.
You can also run a specific powershell that will do what you want it to do (even passing in parameters to it):
Invoke-WmiMethod -ComputerName RemoteServerToRunOn -Path win32_process -Name create -ArgumentList 'powershell.exe -file "C:\PS\Test1.ps1"'
This example could be changed to pass in parameters to the Test1.ps1 PowerShell script to make it more flexible and reusable. And you may also want to pass in a Credential like we used in a previous example above.
Help configuring WMI:
I got the main gist of this working from: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.management/invoke-wmimethod?view=powershell-5.1
But it may have also needed WMI configuration using:
https://helpcenter.gsx.com/hc/en-us/articles/202447926-How-to-Configure-Windows-Remote-PowerShell-Access-for-Non-Privileged-User-Accounts?flash_digest=bec1f6a29327161f08e1f2db77e64856b433cb5a
https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/enable-psremoting?view=powershell-5.1
Powershell New-PSSession Access Denied - Administrator Account
https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.management/invoke-wmimethod?view=powershell-5.1 (I used to get how to call Invoke-WmiMethod).
https://learn.microsoft.com/en-us/powershell/scripting/core-powershell/console/powershell.exe-command-line-help?view=powershell-6 (I used to get syntax of command line)
I didn't use this one, but could have: How to execute a command in a remote computer?
I don't know for sure if all of the steps in the web articles above are needed, I suspect not. But I thought I was going to be using the Invoke-Command PowerShell statement to copy the files on a remote server, but left my changes from the articles above that I did intact mostly I believe.
You will need a dedicated User setup in Active Directory, and to configure the user accounts that SQL Server and SQL Server Agent are running under to give the main calling PowerShell the privileges needed to access the network and other things to, and can be used to run the PowerShell on the remote server as well. And you may need to configure SQLServer to allow SQL Server Jobs or Stored Procedures to be able to call PowerShell scripts like I did. But this is outside the scope of this post. You Google other places on the internet to show you how to do that.

Cannot find service when attempting to remotely stop via Powershell / MSBuild

I have a task to deploy two Windows services created using Topshelf to a test server as part of our continuous integration build process.
My MSBuild target file is as follows:
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Condition="'$(ConfigurationName)'=='Release'" Name="StopService">
<Exec Command="powershell.exe -NonInteractive -executionpolicy Unrestricted -command "& { &&apos;.\ServiceStop.ps1&apos; } "" ContinueOnError="true" />
</Target>
</Project>
This executes a Powershell script (well, a couple of lines) situated within the same folder within the project called ServiceStop.ps:
$service = get-service -ComputerName MyServerName -Name 'MyServiceName'
stop-service -InputObject $service -Verbose
The problem
When I queue a new build from within TFS, the script does successfully execute; however, the get-service command fails to find the service in question - despite the fact that it is definitely there and running. The specific error from the build log is as follows:
Get-Service : Cannot find any service with service name 'MyServiceName' (TaskId:198)
When the script is run locally from my machine, the service on the remote machine is found and stopped successfully, making me think it is some sort of permissions issue.
What I've tried
I have very limited experience with Powershell. I read that credentials could be stored within a Powershell object like so:
$pw = Read-Host -AsSecureString "Enter password"
$pw | ConvertFrom-SecureString | Out-File -Path .\storedPassword.txt
$password = get-content .\storedPassword.txt | convertto-securestring
$credentials = new-object -typename System.Management.Automation.PSCredential -argumentlist "myAdminAccountName",$password
However, it would appear that get-service does not have any method to pass credentials to it.
I also experimented with using PSExec to remotely start and stop the service, but ran into similar issues.
Some questions I reviewed
Using PowerShell credentials without being prompted for a password
Powershell stop-service error: cannot find any service with service name
Powershell Get-WmiObject Access is denied
Saving credentials for reuse by powershell and error ConvertTo-SecureString : Key not valid for use in specified state
I have spent more time on this issue than I can really afford, so would appreciate any help / guidance / comments that may help.
Thank you!
UPDATE
I was able to confirm that the Powershell script was receiving information from the MSBuild task, as the log showed Powershell output.
However, I ran out of time to find a solution and instead worked around the issue by dropping the updated services binaries onto the target server and wrote a Powershell script that installed them from there.
Thanks a lot to those that commented on the issue.
It appears that nothing is being passed from the MSBuild target file to the powershell script. You are defining the name of the service involved via ' marks, so its taking that rather than what the MSBuild target file is doing.
I would suggest you find out how to pass this variable, otherwise the script won't be able to pick this up correctly.
I'm making a complete stab in the dark, but your service name needs the TopShelf instance name including when you call get-service.
For example your service might be called "MyWindowsService" but what you need to programmatically look for is "MyWindowsService$default"

Second hop authentication in vmware vco workflow

I'm writing a flow that suppose to copy files from the Netapp storage to one of my VMs, but i have a problem regarding Second Hop authentication.
I found a way to enable a second hop functionality using powershell -CredSSP, but that option does not exist in vco powershell plugin
Are any other way to do that? Or some way to enable cressp in the plugin..
Thanks =)
One workaround that I've used is to deceive the second hop by not using the second hop. First I copy the files that I want each computer to run to the local computer before remoting and running the command. You can accomplish this by using Windows administrative shares. By default, Windows shares their local drives (\\ComputerName\c$ or \\ComputerName\e$). So my script sorta went like this:
$Computers = Get-Content Computerlist.txt
$File = \\Server1\applications$\file.exe
foreach($Computer in $Computers){
copy $file "\\$Computer\c$"
invoke-command -ComputerName $Computer -ScriptBlock {& 'C:\file.exe'}
del "\\$Computer\c$\file.exe"
}