Category Archives: Quick Scripts

Prettify/Format LDAP Queries using Powershell

When working with LDAP queries in PowerShell, it can be challenging to keep track of all the parentheses and other syntax that’s required. This is especially true for complex queries that include multiple filters and logical operators. Fortunately, there’s a simple PowerShell script that can help make these queries more readable and easier to work with.

Here’s the script:

$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

What this script does is take an LDAP query string, such as the one shown above, and format it so that each filter and operator is on its own line with appropriate indentation. This makes it much easier to read and understand the query, especially if it’s a complex one.

To use the script, simply replace the query string in the first line with your own LDAP query. Then, run the script and the formatted query will be output to the console.

By using this script to format your LDAP queries, you’ll save time and reduce errors when working with complex filters and logical operators. Plus, it’s a great way to make your PowerShell scripts more readable and maintainable.

Results in a nicely formatted query:

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

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)

Reducing the number of replicas in Elasticsearch

Sometimes you just want to run a single Elasticsearch node and not have it constantly alert that it has no were to write its replicas. Since Elasticsearch and more templates default to at least 1 replica we have to make changes to Elasticsearch and to the templates. First change the default:

curl -XPUT 'localhost:9200/_settings' -d '
{
    "index" : {
        "number_of_replicas" : 0
    }
}
'

Then we can list all the templates and figure out which ones need updates as well

curl -XGET -H 'Content-Type: application/json' 'localhost:9200/_template/*?pretty'

Then for each of the templates you want to update. For instance to update a Logstash template use the following:

curl -XPUT -H 'Content-Type: application/json' 'localhost:9200/logstash-*/_settings' -d '{ "number_of_replicas" : 0 } }'

Python OAuth2 auth and bearer token caching

To access many APIs you need to use OAuth2, sending a client id and secret to an endpoint to get a token back. Then send that token with future calls as authentication.

The particular API I was calling would also return a number of seconds the bearer token would be good for.

Hopefully this code will help jumpstart someone else along the way to using python and APIs.

#!/usr/bin/env python3

import requests
import json
import datetime

import os.path
from os import path

cache_file = "/var/tmp/oauth.json"
client_id = '**your client_id here**'
client_secret = '**your secret here**'

def getToken():
    url = "https://api.wherever.com/oauth2/token"

    data = {
      'client_id': client_id,
      'client_secret': client_secret,
      'grant_type': 'client_credentials'
    }

    response = requests.post(url, data=data)

    data = json.loads(response.text)
    expiration_time =  datetime.datetime.now() +  datetime.timedelta(seconds=data['expires_in'])
    data['expiration_date'] =   int(expiration_time.utcnow().timestamp())

    with open(cache_file, "w") as outfile:
        json.dump(data, outfile)
    return data



if path.exists(cache_file):
    #Reading cache
    with open(cache_file, "r") as infile:
        access_token = json.load(infile)
    if int(datetime.datetime.now().timestamp()) > access_token['expiration_date']:
        #Token expired, get new
        access_token = getToken()
else:
    #No cached value, get and cache
    access_token = getToken()


bearer_token = access_token["access_token"]
headers = {
        'Authorization': f'bearer {bearer_token}'
}

#The rest of the requests go here and pass that header

4/24/2023: updated to fix typo!

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 $_}}

 

Querying the BitLocker SQL Database

Just a quick snippet to get all the Recovery Key’s for a specific user in the BitLocker database.

With MBAMRecoveryandHardware selected:

SELECT DomainName, u.Name Username, m.Name MachineName, k.LastUpdateTime KeyUpdate, VolumeGuid, RecoveryKey,RecoveryKeyId, Disclosed
  FROM [RecoveryAndHardwareCore].[Users] u 
  JOIN [RecoveryAndHardwareCore].[Domains] d ON (u.DomainId = d.Id)
  JOIN [RecoveryAndHardwareCore].[Volumes_Users] v_u ON (u.Id = v_u.UserId)
  JOIN [RecoveryAndHardwareCore].[Volumes] v ON (v_u.VolumeId = v.Id)
  JOIN [RecoveryAndHardwareCore].[Keys] k ON (v.Id = k.VolumeId)
  JOIN [RecoveryAndHardwareCore].[Machines_Volumes] m_v ON (m_v.VolumeId = v.Id)
  JOIN [RecoveryAndHardwareCore].[Machines] m ON (m.Id = m_v.MachineId)
  WHERE u.Name = '**username here**'

 

Running anything as a Service

You can use NSSM to run anything you want as a service very quickly.  In my case, I was looking to run AcuRite even when not logged in or while locked so that my weather station is always updating the cloud.

  1. Download NSSM and extract somewhere on your C Drive (i just put it in c:\nssm\
  2. Open a command prompt and change directories to where NSSM was extracted and run the following command (replace AcuRite with the name of the service you want to create)
  3. nssm.exe install AcuRite
  4. In the path field select the exe you would normally be running
  5. On the details tab set a description so you remember in the future why you created this.
  6. Click “Install Service”
  7. Start the service from the Services control panel

Easy and quick you now have AcuRite (or whatever you want) running as a service.

Finding Recently Updated Files

So I needed to find what log files were getting updated.  The files where inC:\ProgramData\VMware\vCenterServer\logs and that folder has many many folders and I wasn’t sure which one would have the files I needed. I was sure that they would have been updated recently.  So a quick little PowerShell to the rescue

Get-ChildItem -Recurse | Where {$_.LastWriteTime -gt (Get-Date).AddMinutes(-15)}

This returns all the files in the current folder and below that have been modified in the last 15 minutes.  It is easy enough to change up to look for other criteria, like *.log files int he last 5 minutes

Get-ChildItem -Recurse -Filter *.log | Where {$_.LastWriteTime -gt (Get-Date).AddMinutes(-5)}

Or all files with pid in their name

Get-ChildItem -Recurse -Filter *pid*

Powershell can be very very handy in a pinch! Hope this helps