changing Log-On Account for service with powershell - powershell

I have csv file with mass data - service name, computer name, account name.
I wrote a script that:
takes the data from the file
renames for each service the name of the user who runs it
generates a password for it
updates it in AD and in the service itself
then update an external file with a saved password
The problem is that I get a null error for the command Get-WmiObject in the stage Load List Servers to $ServiceObject
I'd love help if possible.
I think there should nested foreach but can't find where
$Computers_list = Import-Csv -Path "C:\PS-Script\Service(sid)_prod.csv" # (CSV file with 3 columns, StartNameCredential, ServiceName, ServerName)
$NameCredential = $Computers_list.StartNameCredential
$ServiceName = $Computers_list.ServiceName
$ServerName = $Computers_list.ServerName
$i = 0
foreach ($ServerName in $ServerName) {
# Generate Random Password
Add-Type -AssemblyName System.Web
$pass = [System.Web.Security.Membership]::GeneratePassword(16, 5)
$ServicePass = $pass
# Load List Servers to $ServiceObject
$ServiceObject = get-wmiobject -Class Win32_Service -ComputerName $ServerName -filter "Name='$ServiceName'"
# Stop Service $ServiceName
$ServiceObject.stopservice() | out-null
# Change $ServiceName Start-Mode
$ServiceObject.ChangeStartMode("Automatic") #Manual \ Automatic
# Update Password In AD for $StartNameCredential
Set-ADAccountPassword -server "sap.technion.ac.il" -Identity $NameCredential -NewPassword (ConvertTo-SecureString -AsPlainText $pass -Force)
# Change Log-On Account for service
$ServiceObject.Change($null, $null, $null, $null, $null, $false, $NameCredential, $ServicePass) | out-null
# Start $ServiceName Service
$ServiceObject.startservice()
# Insert $pass into file
echo $NameCredential[$i] $pass >> SAP_prod_pass.txt
$i++
}
Thanks

Related

Powershell variable script

Another week another powershell question. First off thank you all for your help I am learning a lot and I am thinking that I know the answer but can't seem to get it out of my head into the script today.
I currently have this.
$user = "user"
$pass1 = Read-Host "Enter Techops Password"
$SecurePassword = ConvertTo-SecureString $pass1 -AsPlainText -Force
$Credential = New-Object System.Management.Automation.PSCredential ($user, $SecurePassword)
$querylist = (Import-Csv -Path 'C:\Users\user\Documents\20221110\VIPS\20221115_vips1.csv').ip
$today = '{0:yyyyMMdd}' -f (Get-Date)
Import-Module tm-device42
Connect-D42 -Credential $Credential
$results = foreach ($ip in ($querylist)) {
Get-vServerPrdFromPim {$_.ip}
}
$results | Write-Output
The $results | Write-output wont be staying I'm just using it whilst building the script.
The $querylist = (Import-Csv -Path 'C:\Users\user\Documents\20221110\VIPS\20221115_vips1.csv').ip returns the correct info, currently a single IP address 10.10.10.1 (example)
However I get a result of product not found on the Get-vServerPrdFromPim (this is an internal custom made module) but if I do
Get-vServerPrdFromPim 10.10.10.1 in powershell I get the answers that I would expect.
user> (Import-Csv -Path 'C:\Users\user\Documents\20221110\VIPS\20221115_vips1.csv').ip
10.75.230.74
So I am assuming it is an issue with my foreach statement.
I am just wanting to pull the IP's from a large sheet and check them against a database and then output the data.
Am I correct in thinking that I haven't correctly formatted my foreach statement? If so how do I make $ip reference the info from $querylist?
Kind regards
-------------UPDATE --------------------
I have adjusted the following code as suggested
Get-vServerPrdFromPim $ip
So now the foreach loop looks like
$results = foreach ($ip in ($querylists)) {
Get-vServerPrdFromPim $ip | select Name, ProductCode, NetAddr, InfrastructureOwner, OperatingSystemOwner
}
This seems to work fine for a file with a single IP address but when I add additional IP's to the CSV it only processes the first IP.
Will need to dig in further.
Further Update. As requested this is what the excel sheet looks like. This is just an extract.
Found the mistake in my code. Thanks to #mathias and also other research. Code ended up being
$user = "user"
$pass1 = Read-Host "Enter Techops Password"
$SecurePassword = ConvertTo-SecureString $pass1 -AsPlainText -Force
$Credential = New-Object System.Management.Automation.PSCredential ($user, $SecurePassword)
$ips = (Import-Csv -Path 'C:\Users\user\Documents\20221110\VIPS\20221115_vips.csv').ip
$today = '{0:yyyyMMdd}' -f (Get-Date)
Import-Module device42
Connect-D42 -Credential $Credential
$results = foreach ($ip in $ips){
Get-vServerPrdFromPim $ip | select Name, ProductCode, NetAddr, InfrastructureOwner, OperatingSystemOwner
}
$results | Export-Csv C:\Users\user\Documents\20221110\D42_test.csv

Powershell - combining multiple for each into a single output

Good morning everyone,
I am still learning powershell and have a script that my company run's. I have adjusted it slightly and it works well. however...
Overview
Script pulls in a CSV file and then for each device on the CSV it logs in and grabs all of the VIP information and then outputs it to a CSV that is dated and titled with the device name.
Ask
I would like adjust the script so that instead of having 50+ CSV files I could have a single CSV file with an extra column that would like the device name that all the VIPS are on. How do I do that?
Current Script
$user = "user"
$pass1 = Read-Host "Enter Netscaler Password"
$Devicelist = Import-Csv'C:\Users\user\Documents\20221110\20221109_Citrix_inventory_Master1.csv'
foreach ($device in ($Devicelist | ? { $_.fqdn -match "nsr" -and $_.State -match "Primary" -and $_.Configuration_viewable_with_Techops_login -match "Yes" })) {
Write-Host "Attempting to connect to $($device.fqdn)"
$SecurePassword = ConvertTo-SecureString $pass1 -AsPlainText -Force
$Credential = New-Object System.Management.Automation.PSCredential ($user, $SecurePassword)
$session = Connect-NetScaler -Hostname $device."IP address" -Credential $Credential -PassThru
$nsVIPs = Get-NSLBVirtualServer | select name, ipv46, port, curstate
$nsVIPs | Out-File C:\Users\user\Documents\20221110\VIPS\$(get-date -f yyyyMMdd)"_"$($device.fqdn)-"vips.csv"
}
Current CSV Input File format
Current output file format
What I would like to out file format to be
**
What have I tried
**
At the moment nothing except for research, I am guessing that I will need to hold of of the info in an array and then output it at the end. I just don't have a clue how to do that.
Thanks for looking and helping
Neil
You can change the code to first collect all data in one single variable $result and after the loop write all that out in a single CSV file.
To write csv, you need to use Export-Csv, not Out-File, which is intended to write simple text, not objects.
$user = "user"
$pass1 = Read-Host "Enter Netscaler Password"
$SecurePassword = ConvertTo-SecureString $pass1 -AsPlainText -Force
$Credential = New-Object System.Management.Automation.PSCredential ($user, $SecurePassword)
$today = '{0:yyyyMMdd}' -f (Get-Date)
$Devicelist = Import-Csv -Path 'C:\Users\user\Documents\20221110\20221109_Citrix_inventory_Master1.csv' |
Where-Object { $_.fqdn -match "nsr" -and
$_.State -match "Primary" -and
$_.Configuration_viewable_with_Techops_login -match "Yes" }
$result = foreach ($device in $Devicelist) {
Write-Host "Attempting to connect to $($device.fqdn)"
$session = Connect-NetScaler -Hostname $device.'IP address' -Credential $Credential -PassThru
Get-NSLBVirtualServer |
Select-Object name, ipv46, port, curstate, #{Name = 'Device Name'; Expression = {$device.fqdn}}
}
# now write out the csv file just once
$result | Export-Csv -Path "C:\Users\user\Documents\20221110\VIPS\$($today)_vips.csv" -NoTypeInformation

Importing CSV and using Get-Hotfix to export to CSV

So, I'm having some difficulty with some code I'm trying to use to get hotfixes from a lot of computers (which are listed in a CSV file under the column "IP Address") and export that result to a csv. They each require a local computer account to log in (in the same CSV under the column "CPU Name"). I don't really care if it's one csv for the whole thing or a csv for each result. Here's the code so far:
$ipaddress = [What do I put here?]
$cpuname = [What do I put here?]
$OutputFile = 'MyFolder\Computer.csv'
$Username = '$cpuname\MyUsername' [Is this ok?]
$Password = 'MyPassword'
$pass = ConvertTo-SecureString -AsPlainText $Password -Force
$SecureString = $pass
$MySecureCreds = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $Username,$SecureString
$Computers = Import-CSV "C:\MyFolder\Computers.csv"
ForEach ($ipaddress in $Computers) {
}
try
{
Get-HotFix -Credential $MySecureCreds -ipaddress $IPAddress | Select-Object PSComputerName,HotFixID,Description,InstalledBy,InstalledOn | export-csv $OutputFile
}
catch
{
Write-Warning "System Not reachable:$ipaddress"
}
Am I close?
The IP Address and the Computer Name are coming from the CSV, so you don't need to statically define them.
Regarding the username, a couple things:
You need to use double quotes to expand.
Also you'll need to read the 'CPU Name' property one way to do this
would be using a subexpression inside of the double quoted larger expression e.g. "$($variable.property)more text". Or you could concatenate the string $variable.property + 'more text'
Since CPU Name has a space in the column name you'll need to enclose that in quotes.
Since the User name comes from the Computer name which comes from the
CSV, defining the User name variable needs to be in the foreach loop.
The security practices in this script are questionable, but outside the scope of the question. e.g. Saving passwords in scripts, especially a local account with administrative privileges to a large number of networked machines that all have that same password...
$InputFile = 'C:\MyFolder\Input.csv'
$OutputFile = 'C:\MyFolder\Output.csv'
$Password = Read-Host | ConvertTo-SecureString -AsPlainText -Force
$Computers = Import-CSV $InputFile
$HotfixOutput = foreach ($Computer in $Computers) {
$Username = "$($Computer.'CPU Name')\MyUsername"
$MySecureCreds = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $Username,$Password
try {
Get-HotFix -Credential $MySecureCreds -ipaddress $Computer.'IP Address' | Select-Object PSComputerName, HotFixID, Description, InstalledBy, InstalledOn
}
catch {
Write-Warning "System Not reachable: $($Computer.'IP Address')"
}
}
$HotfixOutput | Export-Csv $OutputFile -NoTypeInformation
Remove-Variable Password
Remove-Variable MySecureCreds

Powershell Get-Acl for folders without access permissions

I wrote a script, which gives me all the permissions of a folder + subfolders for a user/group. However, the script only works, if my user has at least read permissions on all these folders. If he has no permissions, get-acl is denied.
Is there any way to work around this, as I don't want to manually switch my user everytime I execute this script.
Can I execute a powershell script with a different user? And if yes, how?
Thank you in advance, Colin
You have a few options that I can think of:
Option 1:
Create a helper file with the actual code you want to run and call it script.ps1 for instance:
[array]$users = "user1","user2","user3"
foreach($user in $users){
$creds = Get-Credential -UserName $user -Message "Enter the Users Password"
$Session = New-PSSession -Credential $creds
Invoke-Command -Session $Session -FilePath C:\Path\to\some\script.ps1
}
Option 2: Run a job for each user. After every task is finished, the new user credentials will be asked. Just add the code to the scriptblock
[array]$users = "user1","user2","user3"
foreach($user in $users){
$creds = Get-Credential -UserName $user -Message "Enter the Users Password"
$target = $user
$job = Start-Job -scriptblock {
param ($username)
Get-Acl C:\Users\$user #Bla bla the rest of your script
} -Args $user -credential $creds
do{
#Wait for the job to finish
}until($job.State -ne "Running")
Write-Host "Job finished with state $($job.State)"
}
Hope this helps!
Note that the creds object can also be automated, if you don't wish to type all the time. (Security principles not taken into account ;) )
$users = #()
$users += #{
username = "User1"
password = "Pass123!"
}
$users += #{
username = "User2"
password = "Pass123!"
}
foreach($user in $users){
$creds = New-Object System.Management.Automation.PSCredential($user.username,($user.password | ConvertTo-SecureString -AsPlainText -Force))
#Add the rest of the script from the chosen option
}

Powershell - Retrieve List of Groups, Use List To Find Specific Group Member

Good afternoon. So I have the below line of code that retrieves any AD group with the suffix of -blah1 and blah2.
import-module activedirectory
$group = Get-ADGroup -Filter { (name -like "*-blah1") -or (name -like "*-blah2") } | Select Name
The above code shows groups:
abc-blah1
abc-blah2
I want to be able to query these groups for a specific user (for example: blahuser). If the user does not exist in the group, I want to script to tell me. Any ideas? Thanks.
You are looking for Get-ADGroupMember and a Where-Object command.
Get-ADGroup -Filter { (name -like "*-blah1") -or (name -like "*-blah2") } |
Get-ADGroupMember |
Where-Object {$_.SamAccountName -match 'blahuser'}
Function Connect-Mstsc {
<#
.SYNOPSIS
Function to connect an RDP session without the password prompt
.DESCRIPTION
This function provides the functionality to start an RDP session without having to type in the password
.PARAMETER ComputerName
This can be a single computername or an array of computers to which RDP session will be opened
.PARAMETER User
The user name that will be used to authenticate
.PARAMETER Password
The password that will be used to authenticate
.PARAMETER Credential
The PowerShell credential object that will be used to authenticate against the remote system
.PARAMETER Admin
Sets the /admin switch on the mstsc command: Connects you to the session for administering a server
.PARAMETER MultiMon
Sets the /multimon switch on the mstsc command: Configures the Remote Desktop Services session monitor layout to be identical to the current client-side configuration
.PARAMETER FullScreen
Sets the /f switch on the mstsc command: Starts Remote Desktop in full-screen mode
.PARAMETER Public
Sets the /public switch on the mstsc command: Runs Remote Desktop in public mode
.PARAMETER Width
Sets the /w: parameter on the mstsc command: Specifies the width of the Remote Desktop window
.PARAMETER Height
Sets the /h: parameter on the mstsc command: Specifies the height of the Remote Desktop window
.NOTES
Name: Connect-Mstsc
Author: Jaap Brasser
DateUpdated: 2016-10-28
Version: 1.2.5
Blog: http://www.jaapbrasser.com
.LINK
http://www.jaapbrasser.com
.EXAMPLE
. .\Connect-Mstsc.ps1
Description
This command dot sources the script to ensure the Connect-Mstsc function is available in your current PowerShell session
.EXAMPLE
Connect-Mstsc -ComputerName server01 -User contoso\jaapbrasser -Password (ConvertTo-SecureString 'supersecretpw' -AsPlainText -Force)
Description
A remote desktop session to server01 will be created using the credentials of contoso\jaapbrasser
.EXAMPLE
Connect-Mstsc server01,server02 contoso\jaapbrasser (ConvertTo-SecureString 'supersecretpw' -AsPlainText -Force)
Description
Two RDP sessions to server01 and server02 will be created using the credentials of contoso\jaapbrasser
.EXAMPLE
server01,server02 | Connect-Mstsc -User contoso\jaapbrasser -Password (ConvertTo-SecureString 'supersecretpw' -AsPlainText -Force) -Width 1280 -Height 720
Description
Two RDP sessions to server01 and server02 will be created using the credentials of contoso\jaapbrasser and both session will be at a resolution of 1280x720.
.EXAMPLE
server01,server02 | Connect-Mstsc -User contoso\jaapbrasser -Password (ConvertTo-SecureString 'supersecretpw' -AsPlainText -Force) -Wait
Description
RDP sessions to server01 will be created, once the mstsc process is closed the session next session is opened to server02. Using the credentials of contoso\jaapbrasser and both session will be at a resolution of 1280x720.
.EXAMPLE
Connect-Mstsc -ComputerName server01:3389 -User contoso\jaapbrasser -Password (ConvertTo-SecureString 'supersecretpw' -AsPlainText -Force) -Admin -MultiMon
Description
A RDP session to server01 at port 3389 will be created using the credentials of contoso\jaapbrasser and the /admin and /multimon switches will be set for mstsc
.EXAMPLE
Connect-Mstsc -ComputerName server01:3389 -User contoso\jaapbrasser -Password (ConvertTo-SecureString 'supersecretpw' -AsPlainText -Force) -Public
Description
A RDP session to server01 at port 3389 will be created using the credentials of contoso\jaapbrasser and the /public switches will be set for mstsc
.EXAMPLE
Connect-Mstsc -ComputerName 192.168.1.10 -Credential $Cred
Description
A RDP session to the system at 192.168.1.10 will be created using the credentials stored in the $cred variable.
.EXAMPLE
Get-AzureVM | Get-AzureEndPoint -Name 'Remote Desktop' | ForEach-Object { Connect-Mstsc -ComputerName ($.Vip,$.Port -join ':') -User contoso\jaapbrasser -Password (ConvertTo-SecureString 'supersecretpw' -AsPlainText -Force) }
Description
A RDP session is started for each Azure Virtual Machine with the user contoso\jaapbrasser and password supersecretpw
.EXAMPLE
PowerShell.exe -Command "& {. .\Connect-Mstsc.ps1; Connect-Mstsc server01 contoso\jaapbrasser (ConvertTo-SecureString 'supersecretpw' -AsPlainText -Force) -Admin}"
Description
An remote desktop session to server01 will be created using the credentials of contoso\jaapbrasser connecting to the administrative session, this example can be used when scheduling tasks or for batch files.
>
[cmdletbinding(SupportsShouldProcess,DefaultParametersetName='UserPassword')]
param (
[Parameter(Mandatory=$true,
ValueFromPipeline=$true,
ValueFromPipelineByPropertyName=$true,
Position=0)]
[Alias('CN')]
[string[]] $ComputerName,
[Parameter(ParameterSetName='UserPassword',Mandatory=$true,Position=1)]
[Alias('U')]
[string] $User,
[Parameter(ParameterSetName='UserPassword',Mandatory=$true,Position=2)]
[Alias('P')]
[string] $Password,
[Parameter(ParameterSetName='Credential',Mandatory=$true,Position=1)]
[Alias('C')]
[PSCredential] $Credential,
[Alias('A')]
[switch] $Admin,
[Alias('MM')]
[switch] $MultiMon,
[Alias('F')]
[switch] $FullScreen,
[Alias('Pu')]
[switch] $Public,
[Alias('W')]
[int] $Width,
[Alias('H')]
[int] $Height,
[Alias('WT')]
[switch] $Wait
)
begin {
[string]$MstscArguments = ''
switch ($true) {
{$Admin} {$MstscArguments += '/admin '}
{$MultiMon} {$MstscArguments += '/multimon '}
{$FullScreen} {$MstscArguments += '/f '}
{$Public} {$MstscArguments += '/public '}
{$Width} {$MstscArguments += "/w:$Width "}
{$Height} {$MstscArguments += "/h:$Height "}
}
if ($Credential) {
$User = $Credential.UserName
$Password = $Credential.GetNetworkCredential().Password
}
}
process {
foreach ($Computer in $ComputerName) {
$ProcessInfo = New-Object System.Diagnostics.ProcessStartInfo
$Process = New-Object System.Diagnostics.Process
# Remove the port number for CmdKey otherwise credentials are not entered correctly
if ($Computer.Contains(':')) {
$ComputerCmdkey = ($Computer -split ':')[0]
} else {
$ComputerCmdkey = $Computer
}
$ProcessInfo.FileName = "$($env:SystemRoot)\system32\cmdkey.exe"
$ProcessInfo.Arguments = "/generic:TERMSRV/$ComputerCmdkey /user:$User /pass:$($Password)"
$ProcessInfo.WindowStyle = [System.Diagnostics.ProcessWindowStyle]::Hidden
$Process.StartInfo = $ProcessInfo
if ($PSCmdlet.ShouldProcess($ComputerCmdkey,'Adding credentials to store')) {
[void]$Process.Start()
}
$ProcessInfo.FileName = "$($env:SystemRoot)\system32\mstsc.exe"
$ProcessInfo.Arguments = "$MstscArguments /v $Computer"
$ProcessInfo.WindowStyle = [System.Diagnostics.ProcessWindowStyle]::Normal
$Process.StartInfo = $ProcessInfo
if ($PSCmdlet.ShouldProcess($Computer,'Connecting mstsc')) {
[void]$Process.Start()
if ($Wait) {
$null = $Process.WaitForExit()
}
}
}
}
}
You can do it like this:
$userName = "ThisIsMyUserName"
$Groups = Get-ADGroup -Filter { (name -like "*-blah1") -or (name -like "*-blah2") } | Where-Object { $userName -notin ($_ | Get-ADGroupMember).SamAccountName} |select -ExpandProperty name