How to run Azure VM CustomScriptExtension as domain user? (part 1) - powershell

What I have working is a Powershell script that takes a JSON file to create a new VM; the JSON file contains instructions for the VM to join a domain and run a custom script. Both things do happen, but the script runs as the user workgroup\system and therefore doesn't have access to a network drive.
Does listing the extensions in this order guarantee that the script runs after the domain join is complete (or is it haphazard)?
Is there something I can do to ensure that the script does not run until the domain join is complete? How can I best detect (locally from the new VM) that the domain join is complete? How would you delay the running of the script until a better time (something like a once-off cron job)?
Update: Split question in two, other half is here.
Also, immense thanks to Dewi Jones for more than an hour of interactive support. I'm indebted by being able to give only a single check mark in return.

Get the domain and if the domain is equal to the one you are joining then continue.
$domain = gc env:UserDNSDomain
While ($domain -neq "FQDN")
{
Start-Sleep -seconds 2
}
Otherwise you can call a script using credentials as follows
$username = 'user'
$password = 'password'
$PSArgs = 'Script file name'
$securePassword = ConvertTo-SecureString $password -AsPlainText -Force
$credential = New-Object System.Management.Automation.PSCredential $username, $securePassword
Start-Process Powershell.exe -Credential $credential $PSArgs

Related

Modifying new user registry in Powerhsell

I'm writting here because this problem is making me crazy.
I'm coding a script to configure a new windows installation. Due to company rules it must be done in Powershell and no windows policies can be used.
I must create a new user and modify (via registry) a couple of configurations. No issue with those topics. Windows 10 creates the user registry file ntuser.dat once the user is logged in for the first time. My problem is that I wanted to modify the registry without ever logging in this new user. I thought I could start a job or a process in the background as the user to trigger the file generation. But it seems it's not working at all:
$USERNAME = $cfgData.cfg.userSettings.userName
$USERPWD = ConvertTo-SecureString -String $USERNAME -AsPlainText -Force
$PC_USER = $env:COMPUTERNAME + "\" + $USERNAME
$userCreds = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $PC_USER, $USERPWD
$output = Start-Job -ScriptBlock { Get-Process -Name explorer } -Credential $userCreds -Verbose
Wait-Job $output | Out-Null
It looks like I can edit the registry but once I log in for the first time with the user, no changes were made.
Any ideas are welcome! I thought about scheduling a task to be performed once the user logs in for the first time, but I have no idea where to start with if I choose this way of solving this problem.
Thx in advance for your time!
Ben
Just to keep everything posted.
I tried the solution from #Jeff Zeitlin (modify the default user NTUSER.DAT file) and it worked like a charm.
Thank you Jeff!
Ben

How to store local administrator username and password in powershell script

I am creating a PowerShell script that a user can just run to edit an entry in registry. My problem is that I cannot figure out how to store local admin username and password in the same script so that the user can just double click the script and run it without having to enter username and password manually.
Here is my code:
$username = "testpc\administrator"
$pasword = get-content C:\Users\test1\documents\testpassword.txt
$credential = new-object -typename system.management.automation.pscredential -argumentlist $username, $password
This does not work at all. Please let me know what I am doing wrong here.
Usually I'd ask for an error, but in this case I'll advise different, just because your approach isn't acceptable.
Don't store passwords unencrpted in script. Never.
Don't store passwords encrypted in scripts, which are meant to be read by someone else, especially not a user with less privileges. Never!
Go, figure other ways to solve your problem. Always!
In this case I see two solutions with the given information:
change the ACL for the registry key that need to be changed by the user
Create a scheduled task which runs as SYSTEM. Make sure the user cannot edit the script.
Actually #vrdse is right.
you can create the script with the KEY as parameter and:
create a scheduled job with the credentials of your user and add the script as task.
give the user the right to execute the job but NOT to edit or to delete
give a shortcut to the scheduled job (or a runner script) to the user and make a how-to document to show him,/her how the parameter should be used.
I use clear text passwords as temporary testing stuff to make sure users CANNOT use my script (so it is exactly the opposite of your action).
You can capture credential during execution:
$cred = get-gredential -message 'This script needs a real admin user'
Enter-PSSession -Credential $cred -ComputerName 127.0.0.127
You can build a credential (do not store privileged user data):
$user = 'SuchAGreatDomainName\IAmLowPrivilegedUserName'
$Password = 'SuperSecretPassEverybodyKnows'
$secpassword = ConvertTo-SecureString $Password -AsPlainText -Force
$credential = New-Object System.Management.Automation.PSCredential($user, $secpassword)
Invoke-RestMethod -Uri $Uri -Credential $Credential

Looking to map an Azure Fileshare as a mapped network drive on an Azure Windows VM via another machine/Custom Script Execution

I'm attempting to provision a Windows VM and I need to map some Azure fileshares to drives for the VM user that will be interacting with the VM.
I've been trying to make "az vm extension set"/Custom Script Execution work for me by calling some PowerShell scripts to setup the mapping to the fileshare, but since the process runs as NT AUTHORITY\SYSTEM, the mappings aren't working, obviously. I've tried to switch user contexts in my scripts via having an intermediate script that changes context to my VM user and then calling another script that does the work, but that doesn't seem to be working.
$scriptFile = $args[0]
$username = $args[1]
$password = $args[2]
$securePassword = ConvertTo-SecureString $password -AsPlainText -Force
$credential = New-Object System.Management.Automation.PSCredential $username,
$securePassword
Start-Process Powershell.exe -Credential $credential $scriptFile
Unfortunately it seems nothing gets run in the $scriptFile that I call, and I can't get any errors out of standard out/err, so I'm at a loss as to how this can be done.
Certainly someone out there has had to run scripts as another user via the Custom Script Execution method before, I'm hoping they happen to read this post.
Is there a way to set what user the Custom Script Execution runs as?
No, there is no way of setting a user under which script extension runs.
You also should use -PassThru and -Wait and\or -RedirectStandardError\-RedirectStandardInput to your command invocation. Also, add -ErrorAction Stop to your commands to propagate errors.

Run powershell as another user

I can't wrap my head around this at all. I have a powershell script that works fine as long as the user has admin rights, because it is moving data to a NAS share that requires write permissions. My issue is I am putting the script in the GPO Startup process. So I need to run the powershell script as another user.
Do I somehow add the new user credentals inside the script itself, or use another process to runas the other user?
I've tried creating another .ps1 script to start the original script, but it didn't work.
I really want to be able to do this in the original script that's doing all the work.
$username = 'domain\user'
$password = 'password'
$cred = New-Object System.Management.Automation.PSCredential -ArgumentList #($username,(ConvertTo-SecureString -String $password -AsPlainText -Force))
Start-Process -FilePath D:\Scripts\Monitor.ps1 -ComputerName localhost -Credential $cred
and I've tried:
Start-Process -FilePath D:\Scripts\Monitor.ps1 -ComputerName (NAS IP Address) -Credential $cred
This works fine inside a powershell script, so how do I get this to run as another user?
& D:\Scripts\monitor.ps1
We have decided to run this as a task under task scheduler at boot up run by a service account that has all the correct permissions. Not what I really wanted but it does work

Powershell Special characters / Automating build - PSRemoting

I am using Teamcity and Powershell to automate few builds. Teamcity runs under lets say account A. There are few executable that needs to be run under account B. Account B has access to DB (windows auth integrated security access) and needs to go and create few tables on install. Passwords for account B is saved in the text file. I am having few issues with this.
1) Account B can have any special characters. I am reading XML file (as this file can be saved in a location where only Account A has access) and new up PSCredential to do the PSRemoting. I am using something like
$secpasswd = ConvertTo-SecureString $passwordFromXMLFile -AsPlainText -Force
$mycreds = New-Object System.Management.Automation.PSCredential ("username", $secpasswd)
$PasswordFromXMLFile can have any special characters. How should I deal with this?
2) When I try to run the executable in context of account B (after I somehow escaped and connected using this account), I am seeing the executable runs under anonymous account instead of domainname\B account. Is there some setting that I need to make sure it runs under account B.
My code looks something like - this is not the exact code I am just extracting some relevant portion.
$secpasswd = ConvertTo-SecureString $passwordFromXMLFile -AsPlainText -Force
$mycreds = New-Object System.Management.Automation.PSCredential ("B", $secpasswd)
$session = New-PSSession -ComputerName $serverName -Credential $mycreds
I see the session connects fine. to the computer
$scriptblock = {
Start-Process $exeName $arguments - wait
}
invoke-command -session $session -scriptblock $scriptblock
Thoughts? Start-Process runs but it executes on anonymous authority instead of account B.