Tag Archives: PowerShell

Getting ElasticSearch Node Versions

Kibana doesn’t tell you what version your nodes are currently running which can be frustrating if you get distracted during an upgrade process. Here is a simple PowerShell script that gets all the nodes and their current version.

$cred = Get-Credential
$nodes_raw = Invoke-RestMethod -Method Get -Uri "http://elasticsearch:9200/_nodes" -Credential $cred

#get the names of each node
$node_names = $nodes_raw.nodes | Get-Member -MemberType NoteProperty | Select -ExpandProperty Name

#convert from object properties to an array of objects
$nodes = foreach ($node_name in $node_names) {
    $nodes_raw.nodes."$node_name"   
}

# Select desired info about the node
$nodes | select name, version

Use PowerShell to export AD User accounts to a CSV with their properties flattened

This queries for specific users (modify this to match your need)

Taking a list of users Flatten-Object will go through their properties and join multivalued attributes with a semi-colon so that you can export it in a useful way to CSV.

# Change this to and LDAP filter that fits your needs
$admins = Get-ADUser -filter "employeeType -eq 'Administrator Acct'" -Properties *

# take multivalued properties and join them with ;
function Flatten-Object {
    [CmdletBinding()]
    param(
        [Parameter(ValueFromPipeline)]
        $object
    )
    process {
        $flattened_object = [pscustomobject]@{}

        foreach ($field in $object | get-member) {
            if ($field.MemberType -eq “Property” -and $field.Name -notlike “__*”) {
                $flattened_object | Add-Member -NotePropertyName $field.Name -NotePropertyValue $($object.$($field.Name) -join ";")
            }
        }
        $flattened_object
    }
}

$admins | Flatten-Object | Export-Csv -Path "user.csv" -NoTypeInformation

Prettify/Format LDAP Queries using Powershell

Here is a simple script to indent add new lines to a PowerShell query.

$ldap = "(&(&(objectCategory=person)(objectClass=user))(lastLogonTimestamp<=128752108510000000)(!(userAccountControl:1.2.840.113556.1.4.803:=2)))"

$ldap = $ldap -replace '\(([\&\|\!]+)', "(`$1`n"
$ldap = $ldap.replace(')', ")`n")

$lines = $ldap.split("`n")
$indent = 0
$new_lines = ForEach ($line in $lines) {
    if  ($line -eq ")") {
        $indent--
    }

    ("`t" * $indent) + $line

    if ($line -eq "(&" -or $line -eq "(|" -or $line -eq "(!") {
        $indent++
    }
}

$new_lines

Results in a nicely formatted query:

(&
	(&
		(objectCategory=person)
		(objectClass=user)
	)
	(lastLogonTimestamp<=128752108510000000)
	(!
		(userAccountControl:1.2.840.113556.1.4.803:=2)
	)
)

Dynamically Getting AD User Properties

Sometimes you want to return properties that match a specific pattern. The following will do that for you:

Get-ADUser Administrator -Properties * | %{Get-Aduser $_.sAMAccountName -Properties @($_ | Get-Member -MemberType Property | Select -ExpandProperty Name | Where {$_ -like "ms*"})}

This gets a user with all properties, then filters those properties by the final like statement and re-gets the user with just those properties. You can also do it with a single get-aduser:

Get-ADUser Administrator -Properties * | %{$_ | Select -Property @($_ | Get-Member -MemberType Property | Select -ExpandProperty Name | Where {$_ -like "ms*"})}

The only downside to this is it doesn’t include the default attributes, so it can be a bit less usefull. If you want to include some specific attributes + all matching a like statement then you can do the following:

Get-ADUser Administrator -Properties * | %{$_ | Select -Property @(@("Name","samACcountName", "Department", "Description", "DisplayName", "DistinguishedName", "employeeType") + ($_ | Get-Member -MemberType Property | Select -ExpandProperty Name | Where {$_ -like "ms*"}))}

And finaly as a code block instead of a one liner:

$user = Get-ADUser Administrator -Properties * 
$msProperties = $user | Get-Member -MemberType Property | Select -ExpandProperty Name | Where {$_ -like "ms*"}
$user | Select -Property @(@("Department", "Description", "DisplayName", "DistinguishedName", "employeeType") + $msProperties)

Use PowerShell to find what process is using a port

Sometimes you just need to know what ports a process is listening on, or what process is listening on a port…so here you go, just replace the process or port and have at it.

$process = "svcHost"
Get-NetTCPConnection | Where OwningProcess -in (Get-Process | Where ProcessName -eq $process | Select -ExpandProperty Id)
$port = 135
Get-Process -Id (Get-NetTCPConnection -LocalPort $port).OwningProcess

Finding who is using a Windows Share in PowerShell

You can find the users and computers connected to a share pretty easily in powershell.

$share_name = "*"
$shares = Get-WmiObject Win32_ServerConnection 
$shares = $shares | Where-Object {$_.ShareName -like $share_name} | `
                    Select-Object ShareName, UserName, `
                                  @{n="Computer";e={[System.Net.Dns]::GetHostEntry($_.ComputerName).HostName}}
$shares | Group-Object -Property ShareName | ` 
          Select Name, `
                 @{n="Computers";e={$_.Group | Select -ExpandProperty Computer | Get-Unique}},`
                 @{n="Users";e={$_.Group | Select -ExpandProperty UserName | Get-Unique}},`
                 Group

$share_name is a filter to narrow down the shares you are checking. Other than that it gets all the share connections then groups them by share. It shows unique users and computers connected to each share.

Find GPOs with LoopBack Enabled

You can get a list of all Group Policy Objects (GPOs) with loopback very easily:


Get-GPO -All | Where { $($_ | Get-GPRegistryValue -Key "HKLM\Software\Policies\Microsoft\Windows\System" -Value UserPolicyMode -ErrorAction SilentlyContinue -WarningAction SilentlyContinue | Select -ExpandProperty Value) -eq 1}

This will query all GPOs and then conditionally return them if they have the value for UserPolicyMode set.

You could replace the “Get-GPO -all” with a filtered version if you were only interested in certain GPOs

A little longer version if you want to abstract it or modify it earlier:

Function GetLoopBack {
    param($gpo)
    $gpo | Get-GPRegistryValue -Key "HKLM\Software\Policies\Microsoft\Windows\System" -Value UserPolicyMode `
                               -WarningAction SilentlyContinue | Select -ExpandProperty Value
}

$GPOs = $GPOs | SELECT -Property *, @{Name='LoopBack';Expression={GetLoopBack2 $_}}

 

Finding Orphaned GPO Folders with PowerShell

During years and years of working in AD occasionally the sysvol folders gets out of sync with the actual GPOs. The following script will return all folders in sysvol\policies that no long have a corresponding GPO. **Please be sure to backup folders before taking any action based on this**

#Initial Source: https://4sysops.com/archives/find-orphaned-active-directory-gpos-in-the-sysvol-share-with-powershell/

function Get-OrphanedGPOs {
    

    [CmdletBinding()]
    param (
        [parameter(Mandatory=$true,ValueFromPipelineByPropertyName)]
        [string]$Domain
    )
    begin {
        $orphaned = @()
    }
    process {
        Write-Verbose "Domain: $Domain"
        # Get GPOs and convert guid into same format as folders
        $gpos = Get-GPO -All -Domain $domain | Select @{ n='GUID'; e = {'{' + $_.Id.ToString().ToUpper() + '}'}}| Select -ExpandProperty GUID
        Write-Verbose "GPOs: $($gpos | Measure-Object | Select -ExpandProperty Count)"
        
        # Get GPOs policy folder
        $polPath = "\\$domain\SYSVOL\$domain\Policies\"
        Write-Verbose "Policy Path: $polPath"

        # Get all folders in the policy path
        $folders = Get-ChildItem $polPath -Exclude 'PolicyDefinitions'
        Write-Verbose "Folders: $($folders | Measure-Object | SElect -ExpandProperty Count)"

        #compare and return only the Folders that exist without a GPO
        $gpoArray = $gpos.GUID
        ForEach ($folder in $folders) {
            if (-not $gpos.contains($folder.Name)) {
                $orphaned += $folder
            }
        }
        Write-Verbose "Orphaned: $($orphaned | Measure-Object | SElect -ExpandProperty Count)"
        return $orphaned
    }
    end {
    }

}

Setting a DHCP Option Value to Hex Bytes

So sometimes, some annoying times, you have a Vendor scoped DHCP option that you need to set and it is hex bytes. This can be quite frustrating as the GUI doesn’t provide an option to set the value (at least I haven’t found a way) and even when it does, you have to set it using the hex value. The second problem being, I don’t speak Hex.

The way I’d always done it before, and that comes up when I search for it right now uses netsh.

netsh dhcp server scope 10.200.100.0 set optionvalue 125 ENCAPSULATED 000003045669643A697070686F6E652E6D6974656C2E636F6D3B73775F746674703D3139322E3136382E312E313B63616C6C5F7372763D3139322E3136382E312E312C3139322E3136382E312E323B

This is fine if you already have the hex value, or the way to get it. It just isn’t idea if you want to do it for a ton of scopes, or if you don’t have the hex value.

Format-Hex will take a string and make it into an array of hex bytes nicely, so you can either use Powershell to produce that hex string

$hex  = [convert]::ToChar(0) + [convert]::ToChar(0)+ [convert]::ToChar(3) +  [convert]::ToChar(4) + "Vid:ipphone.mitel.com;sw_tftp=192.168.1.1;call_srv=192.168.1.1,192.168.1.2;"  | Format-Hex
$string = ($hex.Bytes|ForEach-Object ToString X2) -join ''

and Set-DhcpServerv4OptionValue will take that array and save it into the DHCP server for us, so you can then bulk setup scopes:

$hex  = [convert]::ToChar(0) + [convert]::ToChar(0)+ [convert]::ToChar(3) +  [convert]::ToChar(4) + "Vid:ipphone.mitel.com;sw_tftp=192.168.1.1;call_srv=192.168.1.1,192.168.1.2;"  | Format-Hex
Set-DhcpServerv4OptionValue -ComputerName dhcpserver -ScopeId 10.200.100.0 -OptionID 125 -Value $hex.Bytes

Replace the dchpserver with your actual dhcp server name, the scope ID would be the IP of the scope, etc… The nice thing in powershell is we can then script this and loop over scopes. Building the string per scope and setting it, which would be more complicated with the netsh version. Also sense it is in plain text instead of HEX it is far easier to read and update in the future.

We can reverse the process though it is slightly messier

$value = Get-DhcpServerv4OptionValue -computername dhcpserver -scopeid 10.200.100.0 -OptionId 125 
($value.value|ForEach-Object {[char][byte]"$_"}) -join ''

This will grab the value as an array of strings, in the form of “0x00”, convert that to bytes, then convert that to chars, then join it all back together into a string for viewing.