Powershell To Check Local Admin Credentials - powershell

I'm trying to run a script that requires Administrator input in order to process certain things. Rather than have the script run unsuccessfully I'm trying to trap the error and throw it back into the Credentials, but I can't find a command I can pass Local Admin Credentials with to a Trap. Does anyone have anything that might work?
I've found MANY that will check domain credentials, but this is a LOCAL Admin account.
To clarify, I am using:
$Cred = Get-Credential
I need to verify the output from that is correct and has Admin access to run stuff further down in the script.
Working Solution (Thanks to User978511)
$Cred = Get-Credential
$Computer = (gwmi Win32_ComputerSystem).Name
$User = $Cred.Username
$Pass = $Cred.GetNetworkCredential().Password
$Users = ("$Computer"+"$User")
Add-Type -assemblyname System.DirectoryServices.AccountManagement
$DS = New-Object System.DirectoryServices.AccountManagement.PrincipalContext([System.DirectoryServices.AccountManagement.ContextType]::Machine)
$DS.ValidateCredentials($Users, $pass)
if ($Result -ne "True")
{
<Perform Tasks Here>
}

function Is-Current-User-Admin
{
return ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")
}

This will return you local admins (another answer is probably better fit here):
$group =[ADSI]"WinNT://./Administrators"
$members = #($group.psbase.Invoke("Members"))
$admins = $members | foreach {$_.GetType().InvokeMember("Name", 'GetProperty', $null, $_, $null)}
And this will check credentials:
Add-Type -assemblyname system.DirectoryServices.accountmanagement
$DS = New-Object System.DirectoryServices.AccountManagement.PrincipalContext([System.DirectoryServices.AccountManagement.ContextType]::Machine)
$DS.ValidateCredentials("test", "password")
All you have to do is to check that credentials are ok and that user is member of Admins group

# Test Local User Account Credentials
Write-Verbose "Prompting for password"
$pswd = Read-Host "Type password -- VERIFY BEFORE CLICKING RETURN!!!" -assecurestring
$decodedpswd = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto([System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($pswd))
Foreach ($computer in $computers) {
$temp = New-Object PSobject
$username = "variable with local admin user"
Add-Type -AssemblyName System.DirectoryServices.AccountManagement
$obj = New-Object System.DirectoryServices.AccountManagement.PrincipalContext('machine', $computer)
if ($obj.ValidateCredentials($username, $decodedpswd) -eq $True) {
Write-Host "The password of UserName $($username) in Computer $($computer) it is correct" -BackgroundColor Green}
else {
Write-Host "The password of UserName $($username) in Computer $($computer) does not is correct" -BackgroundColor Red}
}

Related

changing Log-On Account for service with 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

Invoke-VMScript: Do not confirm/re-enter guest credentials

I'm performing an audit on VMs in our environment, and using Invoke-VMScript to get disk info:
$vmErrors = New-Object System.Collections.Generic.List[System.Object]
$report = foreach ($VM in $VMs){
$name = $vm.Name
Write-Host "Retrieving data for $name... " -NoNewline
try{
$output = Invoke-VMScript -ScriptText #'
Get-Disk | Foreach-Object{
[PSCustomObject]#{
ComputerName = $env:COMPUTERNAME
Number = $_.number
Size = [int]($_.size/1GB)
PartitionStyle = $_.PartitionStyle
}
} | ConvertTo-Csv -NoTypeInformation
'# -VM $name -GuestUser $Username -GuestPassword $Password -WarningAction SilentlyContinue -ErrorAction Stop
if($output.ScriptOutput -match 'PartitionStyle')
{
$output.ScriptOutput -replace '(?s)^.+(?="Com)' | ConvertFrom-Csv
}
Write-Host "Done" -ForegroundColor Green
}catch{
$vmErrors.Add($name)
Write-Host "Error!" -ForegroundColor Red
}
}
When running the code in Powershell ISE, I do not need to confirm the credentials for each VM and the script loops perfectly fine, however if I run the script in a standard Powershell window, for each VM I have to enter the username and password for each VM (the credentials will always be the same as what I use to authenticate with the vCenter server.
Example:
Retrieving data for VM NAME...
Specify Credential
Please specify guest credential
User:
How can I run this in a normal window and avoid having to re-enter my credentials each time?
Edit
Example of setting username & password:
$Username = ""
$Password = ""
Function GetUser{
do{
$global:Username = Read-Host "What is your username? (DOMAIN\Username)"
}while($global:Username -eq "")
}
Function GetPassword{
do{
$global:Password = Read-Host "What is your password?" -AsSecureString
$global:Password = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($global:Password))
}while($global:Password -eq "")
}
Solved by changing the credential references in Invoke-VMScript to use $global:Username and $global:Password

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 - New User home folder permissions

I am working on a PS script to automate new network accounts, their home folder and exchange mailbox. We have multiple Domain controllers so am looking for a way of creating a network account on one domain controller but creating the home directory on a different site with its own domain controller. I have tried this but when setting permissions an issue has occurred because the account has not replicated over to the other DC. Anyone have any ideas to get around this?
New Account Function
Function New-BVStandardUser
{
Param (
$FirstName,
$LastName,
$CallRef,
$SiteName,
$EmployeeID,
$ExpiryDate,
$InternetAccess,
$ExternalEmailAccess
)
$ImportGroups = Import-Csv -Path "\\UKSP-FS01\Lawsonja$\Scripts\New-ADUser\SiteGroups.csv" -Delimiter ","
$ImportServers = Import-Csv -Path "\\UKSP-FS01\Lawsonja$\Scripts\New-ADUser\SiteServers.csv" -Delimiter ","
$ImportOUs = Import-Csv -Path "\\UKSP-FS01\Lawsonja$\Scripts\New-ADUser\SiteOUs.csv" -Delimiter ","
# Convert the first and last name so it does not have special characters for the email address/ UPN
$LastNameEdit = $LastName -replace '[^a-zA-Z]', ''
$FirstNameEdit = $FirstName -replace '[^a-zA-Z]', ''
# Fetch a free username from AD based on the provided first and last name from the user
$Username = Get-ADUsername -FirstName $FirstNameEdit -LastName $LastNameEdit
# Generate a random password using the imported module
$Password = Get-Randompassword
# Create the AD account based on the inputted fields
$Params = #{
DisplayName = "$($LastName), $($FirstName)"
DirectoryName = "$($LastName), $($FirstName)"
SamAccountName = "$Username"
UserPrincipalName = "$FirstNameEdit.$LastNameEdit#Bakkavor.com"
Comment = "Created $($env:USERNAME) - $(Get-Date -Format dd/MM/yy) - $($CallRef)"
GivenName = "$FirstNameEdit"
Surname = "$LastNameEdit"
Description = "$($SiteName) User"
Enabled = $true
ChangePasswordAtLogon = $true
Path = "$ImportOUs.$($SiteName)"
HomeDirectory = "\\$ImportServers.$($SiteName)\$Username$"
HomeDrive = "U"
AccountPassword = (ConvertTo-SecureString $Password -AsPlainText -Force)
}
try
{
New-ADUser #Params -ErrorAction Stop
Write-Verbose -Verbose "Network Account Created"
}
catch
{
Write-Warning "Error creating network account. Error: $($_.Exception.Message)"
break
}
New Home Drive Function
Function New-BVUDrive
{
Param
(
$Username,
$Server
)
# Connect to the relevant server in CSV, create new folder, create new SMB Share for the user and add share/ NTFS permissions
Invoke-Command -ComputerName $Server -ArgumentList $Username -ErrorAction Stop -ScriptBlock
{
param($Username)
$FindShare = (Get-SmbShare -Name Users$).Path
if($FindShare -eq $true)
{
try
{
New-Item -ItemType Directory -Path "$FindShare\$Username" -ErrorAction Stop
New-SmbShare -Name "$Username$" -Path "$FindShare\$Username" -FullAccess "AD\Server Admins", "AD\Domain Admins" -ChangeAccess "AD\$Username" -ErrorAction Stop
$Acl = Get-Acl "$FindShare\$Username"
foreach($Rule in $Acl.Access)
{
$Acl.RemoveAccessRule($Rule)
}
$Ar = New-Object system.security.accesscontrol.filesystemaccessrule("Everyone","FullControl","Allow")
$Acl.SetAccessRule($Ar)
$Acl.SetAccessRuleProtection($false, $true)
Set-Acl "$FindShare\$Username" $Acl -ErrorAction Stop
}
catch
{
Write-Warning "U drive failed to create. Error: $($_.Exception.Message)"
}
}
else
{
Write-Warning "Users$ share not found on server"
}
}
}
Have you tried using the SID?
In the second function New-BVUDrive, replace the username with SID. and use the following cmdlet to get the SID:
(Get-ADUser -Identity $SamAccountName).SID.Value
you will be able to set the ACL now, until the data will replicate you will see in the security tab the SID, but the user will be able to access the folder if he will try.
$Ar = New-Object System.Security.AccessControl.FileSystemAccessRule ($SIDIdentity, 'FullControl', ('ContainerInherit','ObjectInherit'), 'None','Allow')
Hope it will help.

How to use obtained credentials in powershell to find groups of the Authenticated user?

I wrote a script, which on execution asks for credentials; it goes like this;
$cred = Get-Credential #Read credentials
$username = $cred.username
$password = $cred.GetNetworkCredential().password
$CurrentDomain = "LDAP://" + ([ADSI] "" ).distinguishedName
$domain = New-Object System.DirectoryServices.DirectoryEntry($CurrentDomain, $UserName, $Password)
if ($domain.name -eq $null)
{
[System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
[System.Windows.Forms.MessageBox]::Show("Authentication failed - please verify your username and password.")
exit
}
else
{
[System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
[System.Windows.Forms.MessageBox]::Show("Authentication Success")
$Groups = [System.Security.Principal.WindowsIdentity]::GetCurrent().Groups
-> I recognized my mistake later, the last line collects the groups of user who is logged into the windows machine.I need the groups of the person who authenticated via script; how to change this and obtain the groups for the person who authenticated into script rather the one using windows authentication?
Please do let me know of any questions or clarifications.
You can try this:
[System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")$cred = Get-Credential #Read credentials
$username = $cred.username
$password = $cred.GetNetworkCredential().password
$CurrentDomain = "LDAP://" + ([ADSI] "" ).distinguishedName
$domain = New-Object System.DirectoryServices.DirectoryEntry($CurrentDomain, $UserName, $Password)
if ($domain.name -eq $null)
{
[System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
[System.Windows.Forms.MessageBox]::Show("Authentication failed - please verify your username and password.")
exit
}
else
{
Add-Type -AssemblyName System.DirectoryServices.AccountManagement
[System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
$cred = Get-Credential #Read credentials
$username = $cred.username
$password = $cred.GetNetworkCredential().password
$CurrentDomain = "LDAP://" + ([ADSI] "" ).distinguishedName
$domain = New-Object System.DirectoryServices.DirectoryEntry($CurrentDomain, $UserName, $Password)
if ($domain.name -eq $null)
{
[System.Windows.Forms.MessageBox]::Show("Authentication failed - please verify your username and password.")
exit
}
else
{
[System.Windows.Forms.MessageBox]::Show("Authentication Success")
$ct = [System.DirectoryServices.AccountManagement.ContextType]::Domain
$user = [System.DirectoryServices.AccountManagement.UserPrincipal]::FindByIdentity($ct, $username)
$groups = $user.GetGroups()
foreach($i in $groups){
$i.SamAccountName
}
}
}
if you're able to install quest activesrole it will be as simple as :
(get-qaduser $user).memberof
otherwise you can use invoke-command and provide the credentials:
$groups=Invoke-Command -ComputerName $env:COMPUTERNAME -Credential $cred -ScriptBlock {
[System.Security.Principal.WindowsIdentity]::GetCurrent().Groups
}