new push
This commit is contained in:
76
Asteroid.ps1
Normal file
76
Asteroid.ps1
Normal file
@@ -0,0 +1,76 @@
|
||||
Function Start-AdfsServerTrace {
|
||||
param (
|
||||
[string]$ActivityId,
|
||||
[switch]$IncludeDebug,
|
||||
[string[]]$ComputerName
|
||||
)
|
||||
|
||||
$jobs = @()
|
||||
foreach ($computer in $ComputerName) {
|
||||
$jobs += Start-Job -ScriptBlock {
|
||||
param ($ActivityId, $IncludeDebug, $computer)
|
||||
|
||||
$logNames = @("Security", "Application", "System")
|
||||
if ($IncludeDebug) { $logNames += "AD FS Tracing/Debug" }
|
||||
|
||||
$events = @()
|
||||
foreach ($log in $logNames) {
|
||||
try {
|
||||
$events += Get-WinEvent -ComputerName $computer -LogName $log -ErrorAction SilentlyContinue |
|
||||
Where-Object { $_.ActivityId -eq $ActivityId }
|
||||
} catch {
|
||||
Write-Error "Failed to retrieve events from $computer for log $log"
|
||||
}
|
||||
}
|
||||
|
||||
return [PSCustomObject]@{
|
||||
ComputerName = $computer
|
||||
Events = $events
|
||||
}
|
||||
} -ArgumentList $ActivityId, $IncludeDebug, $computer
|
||||
}
|
||||
|
||||
return $jobs
|
||||
}
|
||||
|
||||
Function Receive-AdfsServerTrace {
|
||||
param (
|
||||
[Parameter(Mandatory = $true)]
|
||||
[System.Management.Automation.Job[]]$Jobs
|
||||
)
|
||||
|
||||
$results = @()
|
||||
foreach ($job in $Jobs) {
|
||||
$jobResult = Receive-Job -Job $job -Wait -AutoRemoveJob
|
||||
$results += $jobResult
|
||||
}
|
||||
|
||||
return $results
|
||||
}
|
||||
|
||||
Function Get-AdfsServerTrace {
|
||||
[CmdletBinding()]
|
||||
param (
|
||||
[Parameter(Mandatory = $true)]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[string]$ActivityId,
|
||||
|
||||
[switch]$IncludeDebug,
|
||||
|
||||
[string]$OutHtmlFilePath,
|
||||
|
||||
[string[]]$ComputerName = @("localhost")
|
||||
)
|
||||
|
||||
# Start jobs to search all computers in parallel and retrieve results
|
||||
$jobs = Start-AdfsServerTrace -ActivityId $ActivityId -IncludeDebug:$IncludeDebug -ComputerName $ComputerName
|
||||
$results = Receive-AdfsServerTrace -Jobs $jobs
|
||||
|
||||
if ($OutHtmlFilePath) {
|
||||
$results | ConvertTo-Html -Property ComputerName, Events | Out-File $OutHtmlFilePath -Force
|
||||
Write-Output "Report Generated at $OutHtmlFilePath"
|
||||
Start-Process $OutHtmlFilePath
|
||||
} else {
|
||||
Write-Output $results
|
||||
}
|
||||
}
|
||||
51
Binoculars.ps1
Normal file
51
Binoculars.ps1
Normal file
@@ -0,0 +1,51 @@
|
||||
## Created by Zak Bearman - Intel - Datacom - For use on any domain that WinRM is enabled and supported for remote log searching##
|
||||
cls
|
||||
# Define the username you are searching for
|
||||
$username = read-host "Please enter users account" # Replace with the username of the locked-out user
|
||||
# Get the PDC Emulator
|
||||
$pdcemulator = (Get-ADDomain).PDCEmulator
|
||||
$DomainControllers = Get-ADDomainController $pdcemulator | Select-Object -ExpandProperty HostName
|
||||
|
||||
# Define log file path
|
||||
$logFile = "C:\Temp\AccountLockoutLog.txt"
|
||||
|
||||
# Create the log file if it doesn't exist
|
||||
if (-not (Test-Path $logFile)) {
|
||||
New-Item -Path $logFile -ItemType File -Force
|
||||
}
|
||||
|
||||
# Loop indefinitely every 5 minutes
|
||||
while ($true) {
|
||||
foreach ($DC in $DomainControllers) {
|
||||
Write-Host "Searching on: $DC"
|
||||
Add-Content -Path $logFile -Value "Searching on: $DC - $(Get-Date)"
|
||||
|
||||
# Use Invoke-Command to remotely query the domain controller
|
||||
Invoke-Command -ComputerName $DC -ScriptBlock {
|
||||
param ($username)
|
||||
|
||||
# Query the Security event log for Event ID 4625 (Failed Login Attempt)
|
||||
$events4625 = Get-EventLog -LogName "Security" -InstanceId 4625 -Newest 1000 | Where-Object { $_.Message -like "*$username*" }
|
||||
foreach ($event in $events4625) {
|
||||
$timeGenerated = $event.TimeGenerated
|
||||
$message = $event.Message
|
||||
|
||||
Write-Host "Failed login attempt: $message at $timeGenerated"
|
||||
Add-Content -Path $using:logFile -Value "Failed login attempt: $message at $timeGenerated"
|
||||
}
|
||||
|
||||
# Query the Security event log for Event ID 4740 (Account Lockout)
|
||||
$events4740 = Get-EventLog -LogName "Security" -InstanceId 4740 -Newest 1000 | Where-Object { $_.Message -like "*$username*" }
|
||||
foreach ($event in $events4740) {
|
||||
$timeGenerated = $event.TimeGenerated
|
||||
$message = $event.Message
|
||||
|
||||
Write-Host "Account locked out: $message at $timeGenerated"
|
||||
Add-Content -Path $using:logFile -Value "Account locked out: $message at $timeGenerated"
|
||||
}
|
||||
} -ArgumentList $username
|
||||
}
|
||||
|
||||
# Wait for 10 seconds (10 seconds)
|
||||
Start-Sleep -Seconds 10
|
||||
}
|
||||
317
Cartographer.ps1
Normal file
317
Cartographer.ps1
Normal file
@@ -0,0 +1,317 @@
|
||||
# Cartographer - DNS Record Mapping Tool with GUI - Map - IP to DNS record based on subnet
|
||||
# Import required assemblies for GUI
|
||||
Add-Type -AssemblyName System.Windows.Forms
|
||||
Add-Type -AssemblyName System.Drawing
|
||||
|
||||
# Convert IP addresses to integers for comparison
|
||||
function Convert-IPToInt {
|
||||
param (
|
||||
[string]$IPAddress
|
||||
)
|
||||
[array]$octets = $IPAddress.Split('.')
|
||||
return [int]($octets[0]) * 16777216 + [int]($octets[1]) * 65536 + [int]($octets[2]) * 256 + [int]($octets[3])
|
||||
}
|
||||
|
||||
# Convert integer back to IP address
|
||||
function Convert-IntToIP {
|
||||
param (
|
||||
[int64]$Integer
|
||||
)
|
||||
$octet1 = [Math]::Floor($Integer / 16777216)
|
||||
$remainder = $Integer % 16777216
|
||||
$octet2 = [Math]::Floor($remainder / 65536)
|
||||
$remainder = $remainder % 65536
|
||||
$octet3 = [Math]::Floor($remainder / 256)
|
||||
$octet4 = $remainder % 256
|
||||
return "$octet1.$octet2.$octet3.$octet4"
|
||||
}
|
||||
|
||||
# Get subnet range based on IP and mask
|
||||
function Get-SubnetRange {
|
||||
param (
|
||||
[string]$IPAddress
|
||||
)
|
||||
|
||||
# Assuming /24 subnet
|
||||
$octets = $IPAddress.Split('.')
|
||||
$networkPrefix = "$($octets[0]).$($octets[1]).$($octets[2])"
|
||||
$rangeStart = "$networkPrefix.1"
|
||||
$rangeEnd = "$networkPrefix.254"
|
||||
|
||||
return @{
|
||||
Start = $rangeStart
|
||||
End = $rangeEnd
|
||||
}
|
||||
}
|
||||
|
||||
# Get available DNS servers
|
||||
function Get-AvailableDnsServers {
|
||||
# $dnsServers = @("localhost")
|
||||
|
||||
$clientDnsServers = Get-DnsClientServerAddress |
|
||||
Where-Object { $_.ServerAddresses -ne $null } |
|
||||
ForEach-Object {
|
||||
$_.ServerAddresses | Where-Object { $_ -match '^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$' }
|
||||
} |
|
||||
Select-Object -Unique
|
||||
|
||||
$dnsServers += $clientDnsServers
|
||||
|
||||
# Try to add domain controllers if we're in a domain environment
|
||||
try {
|
||||
$domainControllers = Get-ADDomainController -Filter * |
|
||||
ForEach-Object { $_.HostName }
|
||||
$dnsServers += $domainControllers
|
||||
} catch {
|
||||
# Not in a domain environment or AD module not available, continue without it
|
||||
}
|
||||
|
||||
return $dnsServers | Select-Object -Unique
|
||||
}
|
||||
|
||||
# Query DNS for records
|
||||
function Search-DnsRecords {
|
||||
param (
|
||||
[string]$DnsServer,
|
||||
[string]$IPRangeStart,
|
||||
[string]$IPRangeEnd
|
||||
)
|
||||
|
||||
$StartInt = Convert-IPToInt $IPRangeStart
|
||||
$EndInt = Convert-IPToInt $IPRangeEnd
|
||||
|
||||
$Results = @()
|
||||
|
||||
try {
|
||||
$Zones = Get-DnsServerZone -ComputerName $DnsServer -ErrorAction Stop
|
||||
|
||||
foreach ($Zone in $Zones) {
|
||||
$Records = Get-DnsServerResourceRecord -ZoneName $Zone.ZoneName -ComputerName $DnsServer -ErrorAction SilentlyContinue
|
||||
foreach ($Record in $Records) {
|
||||
if ($Record.RecordType -eq "A") {
|
||||
$IPInt = Convert-IPToInt $Record.RecordData.IPv4Address.ToString()
|
||||
if ($IPInt -ge $StartInt -and $IPInt -le $EndInt) {
|
||||
$Results += [PSCustomObject]@{
|
||||
IPAddress = $Record.RecordData.IPv4Address
|
||||
Hostname = $Record.HostName
|
||||
Zone = $Zone.ZoneName
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
[System.Windows.Forms.MessageBox]::Show("Error querying DNS server: $_", "Error", [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error)
|
||||
}
|
||||
|
||||
return $Results
|
||||
}
|
||||
|
||||
# Create the main form
|
||||
$form = New-Object System.Windows.Forms.Form
|
||||
$form.Text = "Cartographer - DNS Record Mapping Tool"
|
||||
$form.Size = New-Object System.Drawing.Size(800, 600)
|
||||
$form.StartPosition = "CenterScreen"
|
||||
$form.FormBorderStyle = [System.Windows.Forms.FormBorderStyle]::FixedDialog
|
||||
$form.MaximizeBox = $false
|
||||
|
||||
# DNS Server selection
|
||||
$dnsServerLabel = New-Object System.Windows.Forms.Label
|
||||
$dnsServerLabel.Text = "DNS Server:"
|
||||
$dnsServerLabel.Location = New-Object System.Drawing.Point(20, 20)
|
||||
$dnsServerLabel.Size = New-Object System.Drawing.Size(100, 20)
|
||||
$form.Controls.Add($dnsServerLabel)
|
||||
|
||||
$dnsServerComboBox = New-Object System.Windows.Forms.ComboBox
|
||||
$dnsServerComboBox.Location = New-Object System.Drawing.Point(130, 20)
|
||||
$dnsServerComboBox.Size = New-Object System.Drawing.Size(200, 20)
|
||||
$dnsServerComboBox.DropDownStyle = [System.Windows.Forms.ComboBoxStyle]::DropDownList
|
||||
$form.Controls.Add($dnsServerComboBox)
|
||||
|
||||
# Populate DNS Server dropdown
|
||||
$dnsServers = Get-AvailableDnsServers
|
||||
foreach ($server in $dnsServers) {
|
||||
$dnsServerComboBox.Items.Add($server)
|
||||
}
|
||||
if ($dnsServerComboBox.Items.Count -gt 0) {
|
||||
$dnsServerComboBox.SelectedIndex = 0
|
||||
}
|
||||
|
||||
# IP Range Selection Group
|
||||
$ipRangeGroupBox = New-Object System.Windows.Forms.GroupBox
|
||||
$ipRangeGroupBox.Text = "IP Range Selection"
|
||||
$ipRangeGroupBox.Location = New-Object System.Drawing.Point(20, 50)
|
||||
$ipRangeGroupBox.Size = New-Object System.Drawing.Size(750, 120)
|
||||
$form.Controls.Add($ipRangeGroupBox)
|
||||
|
||||
# Radio buttons for range selection
|
||||
$subnetRadioButton = New-Object System.Windows.Forms.RadioButton
|
||||
$subnetRadioButton.Text = "Scan Full /24 Subnet"
|
||||
$subnetRadioButton.Location = New-Object System.Drawing.Point(20, 20)
|
||||
$subnetRadioButton.Size = New-Object System.Drawing.Size(150, 20)
|
||||
$subnetRadioButton.Checked = $true
|
||||
$ipRangeGroupBox.Controls.Add($subnetRadioButton)
|
||||
|
||||
$customRangeRadioButton = New-Object System.Windows.Forms.RadioButton
|
||||
$customRangeRadioButton.Text = "Custom IP Range"
|
||||
$customRangeRadioButton.Location = New-Object System.Drawing.Point(20, 50)
|
||||
$customRangeRadioButton.Size = New-Object System.Drawing.Size(150, 20)
|
||||
$ipRangeGroupBox.Controls.Add($customRangeRadioButton)
|
||||
|
||||
# Subnet IP entry
|
||||
$subnetIPLabel = New-Object System.Windows.Forms.Label
|
||||
$subnetIPLabel.Text = "Subnet IP Address:"
|
||||
$subnetIPLabel.Location = New-Object System.Drawing.Point(180, 20)
|
||||
$subnetIPLabel.Size = New-Object System.Drawing.Size(120, 20)
|
||||
$ipRangeGroupBox.Controls.Add($subnetIPLabel)
|
||||
|
||||
$subnetIPTextBox = New-Object System.Windows.Forms.TextBox
|
||||
$subnetIPTextBox.Location = New-Object System.Drawing.Point(300, 20)
|
||||
$subnetIPTextBox.Size = New-Object System.Drawing.Size(150, 20)
|
||||
$subnetIPTextBox.Text = "192.168.1.1"
|
||||
$ipRangeGroupBox.Controls.Add($subnetIPTextBox)
|
||||
|
||||
# Custom range IP entries
|
||||
$startIPLabel = New-Object System.Windows.Forms.Label
|
||||
$startIPLabel.Text = "Start IP Address:"
|
||||
$startIPLabel.Location = New-Object System.Drawing.Point(180, 50)
|
||||
$startIPLabel.Size = New-Object System.Drawing.Size(120, 20)
|
||||
$ipRangeGroupBox.Controls.Add($startIPLabel)
|
||||
|
||||
$startIPTextBox = New-Object System.Windows.Forms.TextBox
|
||||
$startIPTextBox.Location = New-Object System.Drawing.Point(300, 50)
|
||||
$startIPTextBox.Size = New-Object System.Drawing.Size(150, 20)
|
||||
$startIPTextBox.Text = "192.168.1.1"
|
||||
$startIPTextBox.Enabled = $false
|
||||
$ipRangeGroupBox.Controls.Add($startIPTextBox)
|
||||
|
||||
$endIPLabel = New-Object System.Windows.Forms.Label
|
||||
$endIPLabel.Text = "End IP Address:"
|
||||
$endIPLabel.Location = New-Object System.Drawing.Point(460, 50)
|
||||
$endIPLabel.Size = New-Object System.Drawing.Size(120, 20)
|
||||
$ipRangeGroupBox.Controls.Add($endIPLabel)
|
||||
|
||||
$endIPTextBox = New-Object System.Windows.Forms.TextBox
|
||||
$endIPTextBox.Location = New-Object System.Drawing.Point(580, 50)
|
||||
$endIPTextBox.Size = New-Object System.Drawing.Size(150, 20)
|
||||
$endIPTextBox.Text = "192.168.1.254"
|
||||
$endIPTextBox.Enabled = $false
|
||||
$ipRangeGroupBox.Controls.Add($endIPTextBox)
|
||||
|
||||
# Radio button event handlers
|
||||
$subnetRadioButton.Add_CheckedChanged({
|
||||
if ($subnetRadioButton.Checked) {
|
||||
$subnetIPTextBox.Enabled = $true
|
||||
$startIPTextBox.Enabled = $false
|
||||
$endIPTextBox.Enabled = $false
|
||||
}
|
||||
})
|
||||
|
||||
$customRangeRadioButton.Add_CheckedChanged({
|
||||
if ($customRangeRadioButton.Checked) {
|
||||
$subnetIPTextBox.Enabled = $false
|
||||
$startIPTextBox.Enabled = $true
|
||||
$endIPTextBox.Enabled = $true
|
||||
}
|
||||
})
|
||||
|
||||
# Auto-calculate subnet range from subnet IP
|
||||
$subnetIPTextBox.Add_TextChanged({
|
||||
if ($subnetRadioButton.Checked -and $subnetIPTextBox.Text -match '^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$') {
|
||||
$range = Get-SubnetRange -IPAddress $subnetIPTextBox.Text
|
||||
$startIPTextBox.Text = $range.Start
|
||||
$endIPTextBox.Text = $range.End
|
||||
}
|
||||
})
|
||||
|
||||
# Search Button
|
||||
$searchButton = New-Object System.Windows.Forms.Button
|
||||
$searchButton.Text = "Search DNS Records"
|
||||
$searchButton.Location = New-Object System.Drawing.Point(20, 180)
|
||||
$searchButton.Size = New-Object System.Drawing.Size(150, 30)
|
||||
$form.Controls.Add($searchButton)
|
||||
|
||||
# Status Label
|
||||
$statusLabel = New-Object System.Windows.Forms.Label
|
||||
$statusLabel.Text = "Ready"
|
||||
$statusLabel.Location = New-Object System.Drawing.Point(180, 185)
|
||||
$statusLabel.Size = New-Object System.Drawing.Size(590, 20)
|
||||
$form.Controls.Add($statusLabel)
|
||||
|
||||
# Results DataGridView
|
||||
$resultsDataGridView = New-Object System.Windows.Forms.DataGridView
|
||||
$resultsDataGridView.Location = New-Object System.Drawing.Point(20, 220)
|
||||
$resultsDataGridView.Size = New-Object System.Drawing.Size(750, 300)
|
||||
$resultsDataGridView.AutoSizeColumnsMode = [System.Windows.Forms.DataGridViewAutoSizeColumnsMode]::Fill
|
||||
$resultsDataGridView.AllowUserToAddRows = $false
|
||||
$resultsDataGridView.AllowUserToDeleteRows = $false
|
||||
$resultsDataGridView.ReadOnly = $true
|
||||
$resultsDataGridView.MultiSelect = $false
|
||||
$resultsDataGridView.SelectionMode = [System.Windows.Forms.DataGridViewSelectionMode]::FullRowSelect
|
||||
$form.Controls.Add($resultsDataGridView)
|
||||
|
||||
# Export Button
|
||||
$exportButton = New-Object System.Windows.Forms.Button
|
||||
$exportButton.Text = "Export Results"
|
||||
$exportButton.Location = New-Object System.Drawing.Point(20, 530)
|
||||
$exportButton.Size = New-Object System.Drawing.Size(120, 30)
|
||||
$exportButton.Enabled = $false
|
||||
$form.Controls.Add($exportButton)
|
||||
|
||||
# Search button click event
|
||||
$searchButton.Add_Click({
|
||||
$statusLabel.Text = "Searching DNS records..."
|
||||
$resultsDataGridView.DataSource = $null
|
||||
$exportButton.Enabled = $false
|
||||
|
||||
$selectedDnsServer = $dnsServerComboBox.SelectedItem.ToString()
|
||||
|
||||
$ipRangeStart = ""
|
||||
$ipRangeEnd = ""
|
||||
|
||||
if ($subnetRadioButton.Checked) {
|
||||
$range = Get-SubnetRange -IPAddress $subnetIPTextBox.Text
|
||||
$ipRangeStart = $range.Start
|
||||
$ipRangeEnd = $range.End
|
||||
} else {
|
||||
$ipRangeStart = $startIPTextBox.Text
|
||||
$ipRangeEnd = $endIPTextBox.Text
|
||||
}
|
||||
|
||||
$results = Search-DnsRecords -DnsServer $selectedDnsServer -IPRangeStart $ipRangeStart -IPRangeEnd $ipRangeEnd
|
||||
|
||||
if ($results.Count -gt 0) {
|
||||
$dataTable = New-Object System.Data.DataTable
|
||||
$dataTable.Columns.Add("IPAddress", [string])
|
||||
$dataTable.Columns.Add("Hostname", [string])
|
||||
$dataTable.Columns.Add("Zone", [string])
|
||||
|
||||
foreach ($result in $results) {
|
||||
$dataTable.Rows.Add($result.IPAddress.ToString(), $result.Hostname, $result.Zone)
|
||||
}
|
||||
|
||||
$resultsDataGridView.DataSource = $dataTable
|
||||
$statusLabel.Text = "Found $($results.Count) DNS records"
|
||||
$exportButton.Enabled = $true
|
||||
} else {
|
||||
$statusLabel.Text = "No DNS records found in the specified range"
|
||||
}
|
||||
})
|
||||
|
||||
# Export button click event
|
||||
$exportButton.Add_Click({
|
||||
$saveFileDialog = New-Object System.Windows.Forms.SaveFileDialog
|
||||
$saveFileDialog.Filter = "CSV Files (*.csv)|*.csv|All Files (*.*)|*.*"
|
||||
$saveFileDialog.Title = "Export DNS Records"
|
||||
$saveFileDialog.FileName = "DNSRecords_$(Get-Date -Format 'yyyyMMdd_HHmmss').csv"
|
||||
|
||||
if ($saveFileDialog.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK) {
|
||||
$dataTable = $resultsDataGridView.DataSource
|
||||
$dataTable | Export-Csv -Path $saveFileDialog.FileName -NoTypeInformation
|
||||
$statusLabel.Text = "Exported to $($saveFileDialog.FileName)"
|
||||
}
|
||||
})
|
||||
|
||||
# Show the form
|
||||
[void]$form.ShowDialog()
|
||||
|
||||
203
Contrast.ps1
Normal file
203
Contrast.ps1
Normal file
@@ -0,0 +1,203 @@
|
||||
Add-Type -AssemblyName System.Windows.Forms
|
||||
|
||||
#Set Domain Controller Variable
|
||||
|
||||
$domaincontroller = "fqdn.domain.placeholder" ##################### UPDATE THIS LINE #####################
|
||||
|
||||
# Create a form
|
||||
$form = New-Object Windows.Forms.Form
|
||||
$form.Text = "Compare AD Group Memberships"
|
||||
$form.Width = 600
|
||||
$form.Height = 900
|
||||
$form.FormBorderStyle = [System.Windows.Forms.FormBorderStyle]::FixedSingle
|
||||
|
||||
# Signature for UPNs
|
||||
$labelSignature = New-Object Windows.Forms.Label
|
||||
$labelSignature.Text = "Made by Zak Bearman - Intel"
|
||||
$labelSignature.Location = New-Object Drawing.Point(10, 832)
|
||||
$form.Controls.Add($labelSignature)
|
||||
|
||||
# Labels and Textboxes for UPNs
|
||||
$labelPrimaryUser = New-Object Windows.Forms.Label
|
||||
$labelPrimaryUser.Text = "Primary User UPN:"
|
||||
$labelPrimaryUser.Location = New-Object Drawing.Point(10, 23)
|
||||
$form.Controls.Add($labelPrimaryUser)
|
||||
|
||||
$textBoxPrimaryUser = New-Object Windows.Forms.TextBox
|
||||
$textBoxPrimaryUser.Location = New-Object Drawing.Point(120, 20)
|
||||
$textBoxPrimaryUser.Width = 200
|
||||
$form.Controls.Add($textBoxPrimaryUser)
|
||||
|
||||
# ComboBox for selecting the number of users to compare against
|
||||
$labelNumUsers = New-Object Windows.Forms.Label
|
||||
$labelNumUsers.Text = "How many other users?"
|
||||
$labelNumUsers.Location = New-Object Drawing.Point(10, 50)
|
||||
$form.Controls.Add($labelNumUsers)
|
||||
|
||||
$comboBoxNumUsers = New-Object Windows.Forms.ComboBox
|
||||
$comboBoxNumUsers.Location = New-Object Drawing.Point(250, 50)
|
||||
$comboBoxNumUsers.DropDownStyle = [System.Windows.Forms.ComboBoxStyle]::DropDownList
|
||||
$comboBoxNumUsers.Items.Add("1")
|
||||
$comboBoxNumUsers.Items.Add("2")
|
||||
$comboBoxNumUsers.Items.Add("3")
|
||||
$comboBoxNumUsers.SelectedIndex = 0
|
||||
$form.Controls.Add($comboBoxNumUsers)
|
||||
|
||||
# GroupBox for UPNs of users to compare against
|
||||
$groupBoxUsers = New-Object Windows.Forms.GroupBox
|
||||
$groupBoxUsers.Text = "Users to Compare Against:"
|
||||
$groupBoxUsers.Location = New-Object Drawing.Point(10, 80)
|
||||
$groupBoxUsers.Width = 340
|
||||
$groupBoxUsers.Height = 100
|
||||
$form.Controls.Add($groupBoxUsers)
|
||||
|
||||
# Textboxes for entering UPNs based on the selected number of users
|
||||
$textBoxUser1 = New-Object Windows.Forms.TextBox
|
||||
$textBoxUser1.Location = New-Object Drawing.Point(10, 20)
|
||||
$textBoxUser1.Width = 200
|
||||
$groupBoxUsers.Controls.Add($textBoxUser1)
|
||||
|
||||
$textBoxUser2 = New-Object Windows.Forms.TextBox
|
||||
$textBoxUser2.Location = New-Object Drawing.Point(10, 50)
|
||||
$textBoxUser2.Width = 200
|
||||
$textBoxUser2.Visible = $false
|
||||
$groupBoxUsers.Controls.Add($textBoxUser2)
|
||||
|
||||
$textBoxUser3 = New-Object Windows.Forms.TextBox
|
||||
$textBoxUser3.Location = New-Object Drawing.Point(10, 80)
|
||||
$textBoxUser3.Width = 200
|
||||
$textBoxUser3.Visible = $false
|
||||
$groupBoxUsers.Controls.Add($textBoxUser3)
|
||||
|
||||
# Button to initiate comparison
|
||||
$buttonCompare = New-Object Windows.Forms.Button
|
||||
$buttonCompare.Text = "Compare"
|
||||
$buttonCompare.Location = New-Object Drawing.Point(120, 195)
|
||||
$form.Controls.Add($buttonCompare)
|
||||
|
||||
# Help button to display usage instructions
|
||||
$buttonHelp = New-Object Windows.Forms.Button
|
||||
$buttonHelp.Text = "Click Me"
|
||||
$buttonHelp.Location = New-Object Drawing.Point(215, 195)
|
||||
$form.Controls.Add($buttonHelp)
|
||||
|
||||
# Scrollable and selectable textbox for displaying output
|
||||
$textBoxOutput = New-Object Windows.Forms.TextBox
|
||||
$textBoxOutput.Location = New-Object Drawing.Point(10, 230)
|
||||
$textBoxOutput.Width = 560
|
||||
$textBoxOutput.Height = 600
|
||||
$textBoxOutput.Multiline = $true
|
||||
$textBoxOutput.ScrollBars = "Vertical"
|
||||
$textBoxOutput.ReadOnly = $true
|
||||
$form.Controls.Add($textBoxOutput)
|
||||
|
||||
# Event handler for the ComboBox selection change
|
||||
$comboBoxNumUsers.Add_SelectedIndexChanged({
|
||||
$numUsers = [int]$comboBoxNumUsers.SelectedItem
|
||||
|
||||
# Show/hide textboxes based on the selected number of users
|
||||
$textBoxUser1.Visible = $numUsers -ge 1
|
||||
$textBoxUser2.Visible = $numUsers -ge 2
|
||||
$textBoxUser3.Visible = $numUsers -ge 3
|
||||
})
|
||||
|
||||
# Event handler for the Compare button
|
||||
$buttonCompare.Add_Click({
|
||||
# Get the entered UPNs and the selected number of users
|
||||
$primaryUserUPN = $textBoxPrimaryUser.Text
|
||||
$numUsers = [int]$comboBoxNumUsers.SelectedItem
|
||||
|
||||
# Get the UPNs of the users to compare against based on the selected number
|
||||
$usersToCompareUPNs = @()
|
||||
if ($textBoxUser1.Visible) { $usersToCompareUPNs += $textBoxUser1.Text }
|
||||
if ($textBoxUser2.Visible) { $usersToCompareUPNs += $textBoxUser2.Text }
|
||||
if ($textBoxUser3.Visible) { $usersToCompareUPNs += $textBoxUser3.Text }
|
||||
|
||||
# Function to get group memberships for a user using UPN
|
||||
function Get-ADUserGroupsByUPN {
|
||||
param (
|
||||
[string]$userUPN
|
||||
)
|
||||
|
||||
$user = Get-ADUser -Filter { UserPrincipalName -eq $userUPN } -Server $domaincontroller
|
||||
if ($user) {
|
||||
$groups = Get-ADPrincipalGroupMembership -Identity $user -Server $domaincontroller
|
||||
return $groups | Select-Object -ExpandProperty Name
|
||||
} else {
|
||||
Write-Host "User with UPN $userUPN not found."
|
||||
return $null
|
||||
}
|
||||
}
|
||||
|
||||
# Get group memberships for the primary user
|
||||
$primaryUserGroups = Get-ADUserGroupsByUPN -userUPN $primaryUserUPN
|
||||
|
||||
if ($primaryUserGroups -ne $null) {
|
||||
# Compare group memberships for the primary user with other users
|
||||
$missingGroups = @()
|
||||
|
||||
foreach ($userUPN in $usersToCompareUPNs) {
|
||||
$userGroups = Get-ADUserGroupsByUPN -userUPN $userUPN
|
||||
if ($userGroups -ne $null) {
|
||||
foreach ($group in $userGroups) {
|
||||
if ($primaryUserGroups -notcontains $group -and $missingGroups -notcontains $group) {
|
||||
$missingGroups += $group
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Display the missing groups in the output textbox
|
||||
if ($missingGroups.Count -gt 0) {
|
||||
$missingGroupsText = $missingGroups -join "`r`n"
|
||||
$textBoxOutput.Text = "Groups missing for $primaryUserUPN compared to the other users:`r`n`r`n$missingGroupsText"
|
||||
} else {
|
||||
$textBoxOutput.Text = "No missing groups found for $primaryUserUPN."
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
# Event handler for the Help button
|
||||
$buttonHelp.Add_Click({
|
||||
# Display usage instructions in a new window
|
||||
$helpForm = New-Object Windows.Forms.Form
|
||||
$helpForm.Text = "Usage Instructions"
|
||||
$helpForm.Width = 400
|
||||
$helpForm.Height = 350
|
||||
|
||||
$helpLabel = New-Object Windows.Forms.Label
|
||||
$helpLabel.Text = "Instructions:"
|
||||
$helpLabel.Location = New-Object Drawing.Point(10, 10)
|
||||
$helpForm.Controls.Add($helpLabel)
|
||||
|
||||
$helpText = @"
|
||||
1. Enter the UPN of the primary user in the 'Primary User UPN' field.
|
||||
|
||||
2. Select the number of users to compare against from the dropdown 1, 2 or 3.
|
||||
|
||||
3. Enter the UPNs of the users to compare against in the 'Users to Compare Against' section.
|
||||
|
||||
4. Click the 'Compare' button to compare group memberships that the primary user is missing.
|
||||
|
||||
5. The results will be displayed in the textbox below. Find the membership that is most likely what they need and apply this in AD.
|
||||
|
||||
6. If this is an admin account, Please supply this information to Wintel via the ticket to be actioned accordingly.
|
||||
"@
|
||||
$helpTextBox = New-Object Windows.Forms.TextBox
|
||||
$helpTextBox.Location = New-Object Drawing.Point(10, 40)
|
||||
$helpTextBox.Width = 360
|
||||
$helpTextBox.Height = 250
|
||||
$helpTextBox.Multiline = $true
|
||||
$helpTextBox.ScrollBars = "Vertical"
|
||||
$helpTextBox.Text = $helpText
|
||||
$helpTextBox.ReadOnly = $true
|
||||
$helpForm.Controls.Add($helpTextBox)
|
||||
|
||||
$helpForm.ShowDialog()
|
||||
})
|
||||
|
||||
# Show the form
|
||||
$form.ShowDialog()
|
||||
|
||||
|
||||
# Disclaimer: TWFkZSBieSBaYWsgQmVhcm1hbiAtIERhdGFjb20gV2ludGVsIC0gUHJvdmlkZWQgYXMgaXMgd2hlcmUgaXMuIElmIGJyb2tlbiB3aWxsIGJlIGxvb2tlZCBhdCBpbiBhIGJlc3QgZWZmb3J0IGF0dGVtcHQ=
|
||||
80
Conversation.ps1
Normal file
80
Conversation.ps1
Normal file
@@ -0,0 +1,80 @@
|
||||
## After running the powershell scriopt run the following after the fact changing the port number to what you need.
|
||||
|
||||
## $msg = Receive-TCPMessage -Port 9999
|
||||
|
||||
## from the remote server that you need to send the traffic from. Run the following with the port number you set to listen
|
||||
|
||||
## Test-NetConnection win1962 -Port 9999
|
||||
|
||||
Function Receive-TCPMessage {
|
||||
|
||||
Param (
|
||||
|
||||
[Parameter(Mandatory=$true, Position=0)]
|
||||
|
||||
[ValidateNotNullOrEmpty()]
|
||||
|
||||
[int] $Port
|
||||
|
||||
)
|
||||
|
||||
Process {
|
||||
|
||||
Try {
|
||||
|
||||
# Set up endpoint and start listening
|
||||
|
||||
$endpoint = new-object System.Net.IPEndPoint([ipaddress]::any,$port)
|
||||
|
||||
$listener = new-object System.Net.Sockets.TcpListener $EndPoint
|
||||
|
||||
$listener.start()
|
||||
|
||||
|
||||
|
||||
# Wait for an incoming connection
|
||||
|
||||
$data = $listener.AcceptTcpClient()
|
||||
|
||||
|
||||
|
||||
# Stream setup
|
||||
|
||||
$stream = $data.GetStream()
|
||||
|
||||
$bytes = New-Object System.Byte[] 1024
|
||||
|
||||
|
||||
|
||||
# Read data from stream and write it to host
|
||||
|
||||
while (($i = $stream.Read($bytes,0,$bytes.Length)) -ne 0){
|
||||
|
||||
$EncodedText = New-Object System.Text.ASCIIEncoding
|
||||
|
||||
$data = $EncodedText.GetString($bytes,0, $i)
|
||||
|
||||
Write-Output $data
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
# Close TCP connection and stop listening
|
||||
|
||||
$stream.close()
|
||||
|
||||
$listener.stop()
|
||||
|
||||
}
|
||||
|
||||
Catch {
|
||||
|
||||
"Receive Message failed with: `n" + $Error[0]
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
111
Darth-SPooN.ps1
Normal file
111
Darth-SPooN.ps1
Normal file
@@ -0,0 +1,111 @@
|
||||
param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$MachineName,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$ServiceAccount,
|
||||
|
||||
[int]$SqlPort = 1433,
|
||||
|
||||
[string[]]$HadrListeners
|
||||
)
|
||||
|
||||
Import-Module ActiveDirectory
|
||||
|
||||
Write-Host "=== MSSQLSvc + HADR SPN Validation Tool ===" -ForegroundColor Cyan
|
||||
Write-Host "Machine: $MachineName"
|
||||
Write-Host "Service Account: $ServiceAccount"
|
||||
Write-Host "SQL Port: $SqlPort"
|
||||
if ($HadrListeners) {
|
||||
Write-Host "HADR Listener(s): $($HadrListeners -join ', ')"
|
||||
}
|
||||
Write-Host "-------------------------------------------"
|
||||
|
||||
# Get domain FQDN
|
||||
$domainFQDN = (Get-ADDomain).DNSRoot
|
||||
|
||||
# Lookup service account (user or computer)
|
||||
try {
|
||||
$svcObj = Get-ADUser -Identity $ServiceAccount -Properties ServicePrincipalName -ErrorAction Stop
|
||||
} catch {
|
||||
try {
|
||||
$svcObj = Get-ADComputer -Identity $ServiceAccount -Properties ServicePrincipalName -ErrorAction Stop
|
||||
} catch {
|
||||
Write-Host "ERROR: Service account '$ServiceAccount' not found in AD." -ForegroundColor Red
|
||||
exit
|
||||
}
|
||||
}
|
||||
|
||||
# Build expected MSSQLSvc SPNs for machine and HADR listeners
|
||||
$namesToCheck = @($MachineName)
|
||||
if ($HadrListeners) {
|
||||
$namesToCheck += $HadrListeners
|
||||
}
|
||||
$expectedSPNs = foreach ($name in $namesToCheck) {
|
||||
"MSSQLSvc/${name}.${domainFQDN}:$SqlPort"
|
||||
"MSSQLSvc/${name}:$SqlPort"
|
||||
}
|
||||
|
||||
Write-Host "`nExpected MSSQLSvc SPNs:" -ForegroundColor Yellow
|
||||
$expectedSPNs | ForEach-Object { Write-Host " $_" }
|
||||
|
||||
# Case-insensitive missing SPN check (fixed grouping)
|
||||
$missingSPNs = $expectedSPNs | Where-Object {
|
||||
$expectedLower = $_.ToLower()
|
||||
-not (( $svcObj.ServicePrincipalName | ForEach-Object { $_.ToLower() } ) -contains $expectedLower)
|
||||
}
|
||||
|
||||
if ($missingSPNs) {
|
||||
Write-Host "`n[!] Missing MSSQLSvc SPNs on service account:" -ForegroundColor Red
|
||||
$missingSPNs | ForEach-Object { Write-Host " $_" -ForegroundColor Red }
|
||||
|
||||
$addPrompt = Read-Host "`nDo you want to add the missing SPNs now? (Y/N)"
|
||||
if ($addPrompt -match '^[Yy]$') {
|
||||
foreach ($spn in $missingSPNs) {
|
||||
Write-Host "Adding SPN: $spn" -ForegroundColor Green
|
||||
# Use -S to avoid duplicates, requires running as an account with permission
|
||||
setspn -S $spn $ServiceAccount
|
||||
}
|
||||
Write-Host "`n[OK] Missing SPNs have been added." -ForegroundColor Green
|
||||
} else {
|
||||
Write-Host "Skipping SPN creation." -ForegroundColor Yellow
|
||||
}
|
||||
} else {
|
||||
Write-Host "`n[OK] All expected MSSQLSvc SPNs are present." -ForegroundColor Green
|
||||
}
|
||||
|
||||
# Pull all SPNs in the domain
|
||||
$allSPNs = Get-ADObject -Filter {ServicePrincipalName -like "*"} -Properties ServicePrincipalName |
|
||||
ForEach-Object {
|
||||
foreach ($spn in $_.ServicePrincipalName) {
|
||||
[PSCustomObject]@{
|
||||
SPN = $spn
|
||||
ADObject = $_.SamAccountName
|
||||
DN = $_.DistinguishedName
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Check for duplicates of MSSQLSvc SPNs
|
||||
Write-Host "`nChecking for duplicate MSSQLSvc SPNs in the domain..." -ForegroundColor Yellow
|
||||
foreach ($spn in $svcObj.ServicePrincipalName | Where-Object { $_ -like "MSSQLSvc/*" }) {
|
||||
$owners = $allSPNs | Where-Object { $_.SPN -eq $spn }
|
||||
if ($owners.Count -gt 1) {
|
||||
Write-Host "[DUPLICATE] SPN '$spn' is owned by multiple objects:" -ForegroundColor Red
|
||||
$owners | ForEach-Object { Write-Host " -> $($_.ADObject) ($($_.DN))" }
|
||||
}
|
||||
}
|
||||
|
||||
# Check for MSSQLSvc SPNs on service account that aren't expected
|
||||
$expectedLowerList = $expectedSPNs | ForEach-Object { $_.ToLower() }
|
||||
$wrongSPNs = $svcObj.ServicePrincipalName | Where-Object {
|
||||
$_ -like "MSSQLSvc/*" -and ($_.ToLower() -notin $expectedLowerList)
|
||||
}
|
||||
if ($wrongSPNs) {
|
||||
Write-Host "`n[!] Warning: Service account has MSSQLSvc SPNs not in expected list:" -ForegroundColor Red
|
||||
$wrongSPNs | ForEach-Object { Write-Host " $_" }
|
||||
} else {
|
||||
Write-Host "`n[OK] No unexpected MSSQLSvc SPNs found." -ForegroundColor Green
|
||||
}
|
||||
|
||||
Write-Host "`n=== MSSQLSvc + HADR SPN Check Complete ==="
|
||||
132
EggBasket.ps1
Normal file
132
EggBasket.ps1
Normal file
@@ -0,0 +1,132 @@
|
||||
# Load required assemblies
|
||||
Add-Type -AssemblyName System.Windows.Forms
|
||||
Add-Type -AssemblyName System.Drawing
|
||||
|
||||
# Create the form
|
||||
$form = New-Object System.Windows.Forms.Form
|
||||
$form.Text = "MSA Creator - Khan Mayker"
|
||||
$form.Size = New-Object System.Drawing.Size(400,400)
|
||||
$form.StartPosition = "CenterScreen"
|
||||
|
||||
# Create Labels and Textboxes for Variables
|
||||
$labelSVCAccount = New-Object System.Windows.Forms.Label
|
||||
$labelSVCAccount.Text = "Service Account Name:"
|
||||
$labelSVCAccount.Location = New-Object System.Drawing.Point(10,20)
|
||||
$labelSVCAccount.Size = New-Object System.Drawing.Size(150,20)
|
||||
$form.Controls.Add($labelSVCAccount)
|
||||
|
||||
$textSVCAccount = New-Object System.Windows.Forms.TextBox
|
||||
$textSVCAccount.Location = New-Object System.Drawing.Point(180,20)
|
||||
$textSVCAccount.Size = New-Object System.Drawing.Size(180,20)
|
||||
$form.Controls.Add($textSVCAccount)
|
||||
|
||||
$labelDNS = New-Object System.Windows.Forms.Label
|
||||
$labelDNS.Text = "DNS Host Name:"
|
||||
$labelDNS.Location = New-Object System.Drawing.Point(10,60)
|
||||
$labelDNS.Size = New-Object System.Drawing.Size(150,20)
|
||||
$form.Controls.Add($labelDNS)
|
||||
|
||||
$textDNS = New-Object System.Windows.Forms.TextBox
|
||||
$textDNS.Location = New-Object System.Drawing.Point(180,60)
|
||||
$textDNS.Size = New-Object System.Drawing.Size(180,20)
|
||||
$textDNS.Text = ".domain.placeholder.nz" # Enter your domain "domain.govt.nz" ##################### UPDATE THIS LINE #####################
|
||||
$textDNS.Enabled = $false
|
||||
$form.Controls.Add($textDNS)
|
||||
|
||||
$labelPath = New-Object System.Windows.Forms.Label
|
||||
$labelPath.Text = "OU Path:"
|
||||
$labelPath.Location = New-Object System.Drawing.Point(10,100)
|
||||
$labelPath.Size = New-Object System.Drawing.Size(150,20)
|
||||
$form.Controls.Add($labelPath)
|
||||
|
||||
$textPath = New-Object System.Windows.Forms.TextBox
|
||||
$textPath.Location = New-Object System.Drawing.Point(180,100)
|
||||
$textPath.Size = New-Object System.Drawing.Size(180,20)
|
||||
$textPath.Text = "OU=grMSA,OU=Service Accounts,OU=_Administration,DC=domain,DC=placeholder,DC=nz" ##################### UPDATE THIS LINE #####################
|
||||
$textPath.Enabled = $false
|
||||
$form.Controls.Add($textPath)
|
||||
|
||||
$labelMachines = New-Object System.Windows.Forms.Label
|
||||
$labelMachines.Text = "Machine Names (comma-separated):"
|
||||
$labelMachines.Location = New-Object System.Drawing.Point(10,140)
|
||||
$labelMachines.Size = New-Object System.Drawing.Size(220,20)
|
||||
$form.Controls.Add($labelMachines)
|
||||
|
||||
$textMachines = New-Object System.Windows.Forms.TextBox
|
||||
$textMachines.Location = New-Object System.Drawing.Point(10,170)
|
||||
$textMachines.Size = New-Object System.Drawing.Size(350,20)
|
||||
$form.Controls.Add($textMachines)
|
||||
|
||||
# Event to update DNS field based on Service Account Name input
|
||||
$textSVCAccount.Add_TextChanged({
|
||||
$textDNS.Text = "$($textSVCAccount.Text).domain.placeholder.nz" ##################### UPDATE THIS LINE #####################
|
||||
})
|
||||
|
||||
# Create the Submit Button
|
||||
$buttonSubmit = New-Object System.Windows.Forms.Button
|
||||
$buttonSubmit.Text = "Create MSA and AD Group"
|
||||
$buttonSubmit.Location = New-Object System.Drawing.Point(120, 210)
|
||||
$buttonSubmit.Size = New-Object System.Drawing.Size(150,30)
|
||||
$form.Controls.Add($buttonSubmit)
|
||||
|
||||
# Action on Submit Button Click
|
||||
$buttonSubmit.Add_Click({
|
||||
$SVCAccount = $textSVCAccount.Text
|
||||
$dns = $textDNS.Text
|
||||
$path = "OU=grMSA,OU=Service Accounts,OU=_Administration,DC=domain,DC=placeholder,DC=nz" ##################### UPDATE THIS LINE #####################
|
||||
$machines = $textMachines.Text.Split(',')
|
||||
|
||||
if (-not [string]::IsNullOrWhiteSpace($SVCAccount) -and -not [string]::IsNullOrWhiteSpace($dns) -and -not [string]::IsNullOrWhiteSpace($path) -and $machines.Count -gt 0) {
|
||||
|
||||
$grMSA = "grMSA_$SVCAccount"
|
||||
|
||||
try {
|
||||
# Create AD Group
|
||||
New-ADGroup -Name $grMSA -Path $path -GroupScope Global -PassThru -Verbose
|
||||
|
||||
# Add Machines to AD Group
|
||||
foreach ($machine in $machines) {
|
||||
$machineTrimmed = $machine.Trim() + '$'
|
||||
Add-AdGroupMember -Identity $grMSA -Members $machineTrimmed -Verbose
|
||||
}
|
||||
|
||||
# Create MSA with the AD Group allowed to retrieve the password
|
||||
New-ADServiceAccount -Name $SVCAccount -DNSHostName $dns -PrincipalsAllowedToRetrieveManagedPassword $grMSA -Verbose
|
||||
|
||||
[System.Windows.Forms.MessageBox]::Show("MSA and AD Group created successfully.", "Success", [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Information)
|
||||
} catch {
|
||||
[System.Windows.Forms.MessageBox]::Show("Error: $_", "Error", [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error)
|
||||
}
|
||||
} else {
|
||||
[System.Windows.Forms.MessageBox]::Show("Please fill in all fields.", "Input Error", [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Warning)
|
||||
}
|
||||
})
|
||||
|
||||
# Hidden Feature: Click bottom-left corner to open a new window with the message
|
||||
$form.Add_MouseClick({
|
||||
param($sender, $e)
|
||||
|
||||
# Check if the click is at the bottom-left corner
|
||||
if ($e.X -eq 0 -and $e.Y -eq $form.ClientSize.Height - 1) {
|
||||
$hiddenForm = New-Object System.Windows.Forms.Form
|
||||
$hiddenForm.Text = "Hidden Message"
|
||||
$hiddenForm.Size = New-Object System.Drawing.Size(500,200)
|
||||
$hiddenForm.StartPosition = "CenterScreen"
|
||||
|
||||
$textBoxMessage = New-Object System.Windows.Forms.TextBox
|
||||
$textBoxMessage.Multiline = $true
|
||||
$textBoxMessage.ReadOnly = $true
|
||||
$textBoxMessage.Text = "dKU0fKP6Ob9ne29wOpCkepUyeV5me20yg2oudV9OdJIxA01khZwbLcs+RqUohKT9YJkoMWLzV2kkelXbPH1khZwbMWLze3LoPmE0dJXveZIselXbPJIxgJIqe25sf3ToPmEyClXbPHUye20oPmEIgJYbepIvOj== d"
|
||||
$textBoxMessage.Location = New-Object System.Drawing.Point(10,20)
|
||||
$textBoxMessage.Size = New-Object System.Drawing.Size(460,100)
|
||||
$textBoxMessage.ScrollBars = "Vertical"
|
||||
$hiddenForm.Controls.Add($textBoxMessage)
|
||||
|
||||
$hiddenForm.ShowDialog()
|
||||
}
|
||||
})
|
||||
|
||||
# Show the form
|
||||
$form.Topmost = $true
|
||||
$form.Add_Shown({$form.Activate()})
|
||||
[void]$form.ShowDialog()
|
||||
91
Haystack.ps1
Normal file
91
Haystack.ps1
Normal file
@@ -0,0 +1,91 @@
|
||||
##############################################################
|
||||
## Change Log #
|
||||
## 1.0 Initial release #
|
||||
## 1.1 Added logic for resolved IP to be displayed on screen.#
|
||||
##############################################################
|
||||
|
||||
|
||||
Add-Type -AssemblyName System.Windows.Forms
|
||||
Add-Type -AssemblyName System.Drawing
|
||||
|
||||
# Create form controls
|
||||
$form = New-Object System.Windows.Forms.Form
|
||||
$form.Text = "Haystack"
|
||||
$form.ClientSize = New-Object System.Drawing.Size(400, 270)
|
||||
|
||||
$dnsNameLabel = New-Object System.Windows.Forms.Label
|
||||
$dnsNameLabel.Text = "A Record:"
|
||||
$dnsNameLabel.Location = New-Object System.Drawing.Point(10, 20)
|
||||
$dnsNameLabel.AutoSize = $true
|
||||
|
||||
$dnsNameTextbox = New-Object System.Windows.Forms.TextBox
|
||||
$dnsNameTextbox.Location = New-Object System.Drawing.Point(120, 20)
|
||||
$dnsNameTextbox.Size = New-Object System.Drawing.Size(250, 20)
|
||||
|
||||
$zoneLabel = New-Object System.Windows.Forms.Label
|
||||
$zoneLabel.Text = "DNS Zone:"
|
||||
$zoneLabel.Location = New-Object System.Drawing.Point(10, 50)
|
||||
$zoneLabel.AutoSize = $true
|
||||
|
||||
$zoneTextbox = New-Object System.Windows.Forms.TextBox
|
||||
$zoneTextbox.Location = New-Object System.Drawing.Point(120, 50)
|
||||
$zoneTextbox.Size = New-Object System.Drawing.Size(250, 20)
|
||||
|
||||
$ipLabel = New-Object System.Windows.Forms.Label
|
||||
$ipLabel.Text = "IP Address:"
|
||||
$ipLabel.Location = New-Object System.Drawing.Point(10, 80)
|
||||
$ipLabel.Size = New-Object System.Drawing.Size(62, 10)
|
||||
$form.Controls.Add($ipLabel)
|
||||
|
||||
$ipTextBox = New-Object System.Windows.Forms.TextBox
|
||||
$ipTextBox.Location = New-Object System.Drawing.Point(10, 100)
|
||||
$ipTextBox.ReadOnly = $true
|
||||
$form.Controls.Add($ipTextBox)
|
||||
|
||||
$createButton = New-Object System.Windows.Forms.Button
|
||||
$createButton.Location = New-Object System.Drawing.Point(120, 80)
|
||||
$createButton.Size = New-Object System.Drawing.Size(150, 23)
|
||||
$createButton.Text = "Create Zone and A Record"
|
||||
$createButton.Add_Click({
|
||||
# Combine fields and ping DNS name
|
||||
$combined = $dnsNameTextbox.Text + "." + $zoneTextbox.Text
|
||||
$pingResult = Test-Connection -ComputerName $combined -Count 1 -Quiet
|
||||
|
||||
# Get IP address using Resolve-DnsName
|
||||
$ipAddress = ""
|
||||
$dnsResult = Resolve-DnsName -Name $combined -Type A -ErrorAction SilentlyContinue
|
||||
if ($dnsResult) {
|
||||
$ipAddress = $dnsResult.IPAddress
|
||||
}
|
||||
|
||||
# If ping failed and Resolve-DnsName didn't return an IP address, show error message and exit
|
||||
if (!$pingResult -and !$dnsResult) {
|
||||
[System.Windows.Forms.MessageBox]::Show("Could not resolve DNS name.")
|
||||
return
|
||||
}
|
||||
|
||||
# Create DNS zone and A record
|
||||
$zoneName = $zoneTextbox.Text
|
||||
$aRecord = $dnsNameTextbox.Text
|
||||
if ($ipAddress) {
|
||||
$aRecord = $ipAddress
|
||||
}
|
||||
Add-DnsServerPrimaryZone -Name $combined -ZoneFile $zoneName
|
||||
Add-DnsServerResourceRecordA -Name $combined -ZoneName $combined -IPv4Address $aRecord
|
||||
[System.Windows.Forms.MessageBox]::Show("DNS zone and A record created successfully.")
|
||||
})
|
||||
|
||||
$ipTextBox.Text = $ipAddress
|
||||
|
||||
# Add controls to form
|
||||
$form.Controls.Add($dnsNameLabel)
|
||||
$form.Controls.Add($dnsNameTextbox)
|
||||
$form.Controls.Add($zoneLabel)
|
||||
$form.Controls.Add($zoneTextbox)
|
||||
$form.Controls.Add($createButton)
|
||||
$form.Controls.Add($pictureBox)
|
||||
$form.Controls.Add($ipLabel)
|
||||
$form.Controls.Add($ipTextBox)
|
||||
|
||||
# Show the form
|
||||
$form.ShowDialog() | Out-Null
|
||||
29
Ledger.ps1
Normal file
29
Ledger.ps1
Normal file
@@ -0,0 +1,29 @@
|
||||
#This script will read a CSV file with users in samaccountname format in a column named username and query AD for the last password set time based on the day count on line 11.
|
||||
|
||||
# Define the path to the CSV file
|
||||
$csvPath = "C:\temp\password-last-set.csv" # create a CSV file in a specific path with a column named username
|
||||
|
||||
# Import the CSV file
|
||||
$users = Import-Csv -Path $csvPath
|
||||
|
||||
# Set the threshold in days
|
||||
$thresholdDays = 0
|
||||
|
||||
# Calculate the threshold date
|
||||
$thresholdDate = (Get-Date).AddDays(-$thresholdDays)
|
||||
|
||||
# Iterate through each user in the CSV
|
||||
foreach ($user in $users) {
|
||||
# Get the SamAccountName from the CSV
|
||||
$samAccountName = $user.username
|
||||
|
||||
# Get the user object from Active Directory
|
||||
$adUser = Get-ADUser -Filter { SamAccountName -eq $samAccountName } -Properties LastLogon
|
||||
|
||||
# Check if the PasswordLastSet property exists and compare it with the threshold date
|
||||
if ($null -eq $adUser.LastLogon) {
|
||||
Write-Output "$samAccountName Password still unset"
|
||||
} elseif ($adUser.LastLogon -lt $thresholdDate) {
|
||||
Write-Output "$samAccountName Password was last set on $($adUser.PasswordLastSet)"
|
||||
}
|
||||
}
|
||||
108
Perfmon-Template.xml
Normal file
108
Perfmon-Template.xml
Normal file
@@ -0,0 +1,108 @@
|
||||
<?xml version="1.0" encoding="UTF-16"?>
|
||||
<DataCollectorSet>
|
||||
<Status>0</Status>
|
||||
<Duration>0</Duration>
|
||||
<Description>
|
||||
</Description>
|
||||
<DescriptionUnresolved>
|
||||
</DescriptionUnresolved>
|
||||
<DisplayName>
|
||||
</DisplayName>
|
||||
<DisplayNameUnresolved>
|
||||
</DisplayNameUnresolved>
|
||||
<SchedulesEnabled>-1</SchedulesEnabled>
|
||||
<LatestOutputLocation>
|
||||
</LatestOutputLocation>
|
||||
<Name>Overall</Name>
|
||||
<OutputLocation>C:\temp\Perf\</OutputLocation>
|
||||
<RootPath>C:\temp\Perf</RootPath>
|
||||
<Segment>0</Segment>
|
||||
<SegmentMaxDuration>0</SegmentMaxDuration>
|
||||
<SegmentMaxSize>0</SegmentMaxSize>
|
||||
<SerialNumber>1</SerialNumber>
|
||||
<Server>
|
||||
</Server>
|
||||
<Subdirectory>
|
||||
</Subdirectory>
|
||||
<SubdirectoryFormat>0</SubdirectoryFormat>
|
||||
<SubdirectoryFormatPattern>
|
||||
</SubdirectoryFormatPattern>
|
||||
<Task>
|
||||
</Task>
|
||||
<TaskRunAsSelf>0</TaskRunAsSelf>
|
||||
<TaskArguments>
|
||||
</TaskArguments>
|
||||
<TaskUserTextArguments>
|
||||
</TaskUserTextArguments>
|
||||
<UserAccount>local_admin</UserAccount>
|
||||
<Security>O:BAG:DUD:AI(A;;FA;;;SY)(A;;FA;;;BA)(A;;FR;;;LU)(A;;0x1301ff;;;S-1-5-80-2661322625-712705077-2999183737-3043590567-590698655)(A;ID;FA;;;SY)(A;ID;FA;;;BA)(A;ID;0x1200ab;;;LU)(A;ID;FR;;;AU)(A;ID;FR;;;LS)(A;ID;FR;;;NS)</Security>
|
||||
<StopOnCompletion>0</StopOnCompletion>
|
||||
<PerformanceCounterDataCollector>
|
||||
<DataCollectorType>0</DataCollectorType>
|
||||
<Name>System Monitor Log</Name>
|
||||
<FileName>P2 Performance Log</FileName>
|
||||
<FileNameFormat>1</FileNameFormat>
|
||||
<FileNameFormatPattern>
|
||||
</FileNameFormatPattern>
|
||||
<LogAppend>0</LogAppend>
|
||||
<LogCircular>0</LogCircular>
|
||||
<LogOverwrite>0</LogOverwrite>
|
||||
<LatestOutputLocation>
|
||||
</LatestOutputLocation>
|
||||
<DataSourceName>
|
||||
</DataSourceName>
|
||||
<SampleInterval>1</SampleInterval>
|
||||
<SegmentMaxRecords>0</SegmentMaxRecords>
|
||||
<LogFileFormat>3</LogFileFormat>
|
||||
<Counter>\Processor Information(_Total)\% Processor Time</Counter>
|
||||
<Counter>\LogicalDisk(_Total)\% Disk Time</Counter>
|
||||
<Counter>\LogicalDisk(_Total)\Avg. Disk Queue Length</Counter>
|
||||
<Counter>\LogicalDisk(_Total)\Disk Reads/sec</Counter>
|
||||
<Counter>\LogicalDisk(_Total)\Disk Writes/sec</Counter>
|
||||
<Counter>\LogicalDisk(_Total)\Avg. Disk sec/Read</Counter>
|
||||
<Counter>\LogicalDisk(_Total)\Avg. Disk sec/Write</Counter>
|
||||
<Counter>\Memory\% Committed Bytes In Use</Counter>
|
||||
<Counter>\Memory\Available MBytes</Counter>
|
||||
<Counter>\Memory\Cache Faults/sec</Counter>
|
||||
<Counter>\Memory\Committed Bytes</Counter>
|
||||
<Counter>\Memory\Pages/sec</Counter>
|
||||
<Counter>\Processor(*)\% Idle Time</Counter>
|
||||
<Counter>\Processor(*)\% Privileged Time</Counter>
|
||||
<Counter>\Processor(_Total)\% Processor Time</Counter>
|
||||
<Counter>\System\Processor Queue Length</Counter>
|
||||
<Counter>\System\Context Switches/sec</Counter>
|
||||
<Counter>\System\System Calls/sec</Counter>
|
||||
<Counter>\System\Threads</Counter>
|
||||
<CounterDisplayName>\Processor Information(_Total)\% Processor Time</CounterDisplayName>
|
||||
<CounterDisplayName>\LogicalDisk(_Total)\% Disk Time</CounterDisplayName>
|
||||
<CounterDisplayName>\LogicalDisk(_Total)\Avg. Disk Queue Length</CounterDisplayName>
|
||||
<CounterDisplayName>\LogicalDisk(_Total)\Disk Reads/sec</CounterDisplayName>
|
||||
<CounterDisplayName>\LogicalDisk(_Total)\Disk Writes/sec</CounterDisplayName>
|
||||
<CounterDisplayName>\LogicalDisk(_Total)\Avg. Disk sec/Read</CounterDisplayName>
|
||||
<CounterDisplayName>\LogicalDisk(_Total)\Avg. Disk sec/Write</CounterDisplayName>
|
||||
<CounterDisplayName>\Memory\% Committed Bytes In Use</CounterDisplayName>
|
||||
<CounterDisplayName>\Memory\Available MBytes</CounterDisplayName>
|
||||
<CounterDisplayName>\Memory\Cache Faults/sec</CounterDisplayName>
|
||||
<CounterDisplayName>\Memory\Committed Bytes</CounterDisplayName>
|
||||
<CounterDisplayName>\Memory\Pages/sec</CounterDisplayName>
|
||||
<CounterDisplayName>\Processor(*)\% Idle Time</CounterDisplayName>
|
||||
<CounterDisplayName>\Processor(*)\% Privileged Time</CounterDisplayName>
|
||||
<CounterDisplayName>\Processor(_Total)\% Processor Time</CounterDisplayName>
|
||||
<CounterDisplayName>\System\Processor Queue Length</CounterDisplayName>
|
||||
<CounterDisplayName>\System\Context Switches/sec</CounterDisplayName>
|
||||
<CounterDisplayName>\System\System Calls/sec</CounterDisplayName>
|
||||
<CounterDisplayName>\System\Threads</CounterDisplayName>
|
||||
</PerformanceCounterDataCollector>
|
||||
<DataManager>
|
||||
<Enabled>0</Enabled>
|
||||
<CheckBeforeRunning>0</CheckBeforeRunning>
|
||||
<MinFreeDisk>0</MinFreeDisk>
|
||||
<MaxSize>0</MaxSize>
|
||||
<MaxFolderCount>0</MaxFolderCount>
|
||||
<ResourcePolicy>0</ResourcePolicy>
|
||||
<ReportFileName>report.html</ReportFileName>
|
||||
<RuleTargetFileName>report.xml</RuleTargetFileName>
|
||||
<EventsFileName>
|
||||
</EventsFileName>
|
||||
</DataManager>
|
||||
</DataCollectorSet>
|
||||
58
Scope.ps1
Normal file
58
Scope.ps1
Normal file
@@ -0,0 +1,58 @@
|
||||
param (
|
||||
[string]$CAName, # Specify the CA name to search for
|
||||
[switch]$Valid, # Show only valid certificates
|
||||
[switch]$Invalid # Show only invalid certificates
|
||||
)
|
||||
|
||||
if (-not $CAName) {
|
||||
$CAName = "NZGOVTCA*"
|
||||
}
|
||||
|
||||
# Define certificate stores
|
||||
$rootStore = "Cert:\LocalMachine\Root"
|
||||
$intermediateStore = "Cert:\LocalMachine\CA"
|
||||
|
||||
# Function to check certificate validity
|
||||
function Check-CertificateValidity {
|
||||
param ($Cert, $StoreName)
|
||||
|
||||
# Get current date
|
||||
$currentDate = Get-Date
|
||||
|
||||
# Check expiration and validity period
|
||||
$isValid = $currentDate -ge $Cert.NotBefore -and $currentDate -le $Cert.NotAfter
|
||||
|
||||
# Prepare result object
|
||||
[PSCustomObject]@{
|
||||
Store = $StoreName
|
||||
Subject = $Cert.Subject
|
||||
Issuer = $Cert.Issuer
|
||||
Thumbprint = $Cert.Thumbprint
|
||||
ValidFrom = $Cert.NotBefore
|
||||
ValidTo = $Cert.NotAfter
|
||||
Status = if ($isValid) { "Valid" } else { "Invalid" }
|
||||
}
|
||||
}
|
||||
|
||||
# Get all root and intermediate certificates issued by the specified CA
|
||||
$rootCerts = Get-ChildItem -Path $rootStore | Where-Object { $_.Issuer -like "*$CAName*" }
|
||||
$intermediateCerts = Get-ChildItem -Path $intermediateStore | Where-Object { $_.Issuer -like "*$CAName*" }
|
||||
|
||||
# Check certificates
|
||||
$results = @()
|
||||
$results += $rootCerts | ForEach-Object { Check-CertificateValidity -Cert $_ -StoreName "Root CA" }
|
||||
$results += $intermediateCerts | ForEach-Object { Check-CertificateValidity -Cert $_ -StoreName "Intermediate CA" }
|
||||
|
||||
# Apply filtering based on switches
|
||||
if ($Valid) {
|
||||
$results = $results | Where-Object { $_.Status -eq "Valid" }
|
||||
} elseif ($Invalid) {
|
||||
$results = $results | Where-Object { $_.Status -eq "Invalid" }
|
||||
}
|
||||
|
||||
# Output results
|
||||
if ($results.Count -eq 0) {
|
||||
Write-Host "No certificates found matching the criteria." -ForegroundColor Red
|
||||
} else {
|
||||
$results | Format-Table -AutoSize
|
||||
}
|
||||
33
Stacker.ps1
Normal file
33
Stacker.ps1
Normal file
@@ -0,0 +1,33 @@
|
||||
# Variables
|
||||
$CsrFolder = "C:\Temp\CSRs" # Path to folder with CSR files
|
||||
$DnsZone = "record.domain.govt.nz" # Your DNS zone (AD-integrated)
|
||||
$TargetIP = "managementboxIP" # The IP for all A records
|
||||
$DnsServer = "DC01.example.local" # AD Domain Controller / DNS server
|
||||
|
||||
# Loop through CSR files
|
||||
Get-ChildItem -Path $CsrFolder -Filter *.csr | ForEach-Object {
|
||||
# Get just the file name without extension
|
||||
$fqdn = $_.BaseName.Trim()
|
||||
Write-Host "Processing $fqdn ..."
|
||||
|
||||
try {
|
||||
# If the filename is a full FQDN, strip the zone name
|
||||
if ($fqdn.ToLower().EndsWith(".$($DnsZone.ToLower())")) {
|
||||
$hostname = $fqdn.Substring(0, $fqdn.Length - $DnsZone.Length - 1)
|
||||
} else {
|
||||
$hostname = $fqdn
|
||||
}
|
||||
|
||||
Write-Host " -> Adding DNS A record for $hostname.$DnsZone -> $TargetIP"
|
||||
|
||||
Add-DnsServerResourceRecordA `
|
||||
-Name $hostname `
|
||||
-ZoneName $DnsZone `
|
||||
-IPv4Address $TargetIP `
|
||||
-ComputerName $DnsServer `
|
||||
-ErrorAction Stop
|
||||
|
||||
} catch {
|
||||
Write-Warning "Could not add DNS record for $fqdn : $_"
|
||||
}
|
||||
}
|
||||
46
Tentacles.ps1
Normal file
46
Tentacles.ps1
Normal file
@@ -0,0 +1,46 @@
|
||||
# Paths
|
||||
$WacsPath = "C:\ProgramData\Wacs\wacs.exe"
|
||||
$CsrFolder = "C:\Temp\Renew\Video"
|
||||
$OutFolder = "C:\Temp\Renew\Output"
|
||||
|
||||
# Collect CSR files
|
||||
$csrFiles = Get-ChildItem -Path $CsrFolder -Include *.csr, *.pem -File -Recurse
|
||||
|
||||
if (-not $csrFiles) {
|
||||
Write-Host "No CSR files found in $CsrFolder"
|
||||
exit
|
||||
}
|
||||
|
||||
foreach ($csr in $csrFiles) {
|
||||
# Use the base filename (without extension) as the hostname
|
||||
$baseName = [System.IO.Path]::GetFileNameWithoutExtension($csr.Name)
|
||||
$outPath = Join-Path $OutFolder ($baseName + ".pfx")
|
||||
|
||||
# Ensure the output directory exists
|
||||
$outDir = Split-Path $outPath -Parent
|
||||
if (-not (Test-Path $outDir)) {
|
||||
New-Item -Path $outDir -ItemType Directory -Force | Out-Null
|
||||
}
|
||||
|
||||
# Build argument array (manual target, hostname from filename)
|
||||
$args = @(
|
||||
"--target", "manual",
|
||||
"--host", $baseName,
|
||||
"--store", "pfxfile",
|
||||
"--pfxfilepath", "C:\programdata\wacs\output\",
|
||||
"--baseuri", "https://acmeprod.domain.govt.nz:9999/acme/rsa/",
|
||||
"--validation", "selfhosting",
|
||||
"--validationport", "9998",
|
||||
"--verbose"
|
||||
)
|
||||
|
||||
# Print command for verification
|
||||
Write-Host "`nReady to run WACS command for $($csr.Name):"
|
||||
Write-Host "& $WacsPath $($args -join ' ')"
|
||||
|
||||
# Run WACS
|
||||
& $WacsPath @args
|
||||
Write-Host "Done processing $($csr.Name)"
|
||||
}
|
||||
|
||||
Write-Host "`nAll CSR filenames processed as hostnames."
|
||||
153
Warden.ps1
Normal file
153
Warden.ps1
Normal file
@@ -0,0 +1,153 @@
|
||||
Add-Type -AssemblyName System.Windows.Forms
|
||||
|
||||
# Create the form
|
||||
$form = New-Object System.Windows.Forms.Form
|
||||
$form.Text = "Instructions"
|
||||
$form.Size = New-Object System.Drawing.Size(800, 550)
|
||||
$form.StartPosition = "CenterScreen"
|
||||
|
||||
# Create a label to display the instructions
|
||||
$label = New-Object System.Windows.Forms.Label
|
||||
$label.Text = @"
|
||||
This script will read a CSV file with users in samaccountname format in a column named 'username' and will set the -ChangePasswordAtLogon property to $true.
|
||||
|
||||
Please select the CSV file.
|
||||
|
||||
Clicking Accept will proceed with the operation. Make sure you have confirmed the CSV file is correct before proceeding.
|
||||
"@
|
||||
$label.AutoSize = $true
|
||||
$label.MaximumSize = New-Object System.Drawing.Size(560, 0) # Set maximum width and allow height to adjust
|
||||
$label.Location = New-Object System.Drawing.Point(10, 80)
|
||||
$form.Controls.Add($label)
|
||||
|
||||
# Define author information
|
||||
$authorName = "Zak Bearman"
|
||||
$department = "Wintel Platforms"
|
||||
$year = "2025"
|
||||
|
||||
# Create a label to display the author
|
||||
$label2 = New-Object System.Windows.Forms.Label
|
||||
$label2.Text = "Written by $authorName - $department $year."
|
||||
$label2.AutoSize = $true
|
||||
$label2.MaximumSize = New-Object System.Drawing.Size(560, 0) # Set maximum width and allow height to adjust
|
||||
$label2.Location = New-Object System.Drawing.Point(160, 420)
|
||||
$form.Controls.Add($label2)
|
||||
|
||||
# Create a TextBox to display the CSV content
|
||||
$textBox = New-Object System.Windows.Forms.TextBox
|
||||
$textBox.Multiline = $true
|
||||
$textBox.ScrollBars = "Vertical"
|
||||
$textBox.ReadOnly = $true
|
||||
$textBox.Size = New-Object System.Drawing.Size(200, 500)
|
||||
$textBox.Location = New-Object System.Drawing.Point(568, 5)
|
||||
$form.Controls.Add($textBox)
|
||||
|
||||
# Create a button to browse for the CSV file
|
||||
$browseButton = New-Object System.Windows.Forms.Button
|
||||
$browseButton.Text = "Browse"
|
||||
$browseButton.Location = New-Object System.Drawing.Point(250, 240)
|
||||
$script:csvPath = $null
|
||||
$browseButton.Add_Click({
|
||||
$script:csvPath = $null
|
||||
$openFileDialog = New-Object System.Windows.Forms.OpenFileDialog
|
||||
$openFileDialog.Filter = "CSV files (*.csv)|*.csv"
|
||||
if ($openFileDialog.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK) {
|
||||
$script:csvPath = $openFileDialog.FileName
|
||||
$textBox.Text = Get-Content -Path $script:csvPath -Raw
|
||||
}
|
||||
})
|
||||
$form.Controls.Add($browseButton)
|
||||
|
||||
# Create an Accept button
|
||||
$acceptButton = New-Object System.Windows.Forms.Button
|
||||
$acceptButton.Text = "Accept"
|
||||
$acceptButton.Location = New-Object System.Drawing.Point(200, 300)
|
||||
$acceptButton.Add_Click({
|
||||
if (-not $script:csvPath) {
|
||||
[System.Windows.Forms.MessageBox]::Show("No CSV file selected. Please select a CSV file to proceed.", "Error", [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error)
|
||||
return
|
||||
}
|
||||
$form.Tag = "Accept"
|
||||
$form.Close()
|
||||
})
|
||||
$form.Controls.Add($acceptButton)
|
||||
|
||||
# Create a Cancel button
|
||||
$cancelButton = New-Object System.Windows.Forms.Button
|
||||
$cancelButton.Text = "Cancel"
|
||||
$cancelButton.Location = New-Object System.Drawing.Point(300, 300)
|
||||
$cancelButton.Add_Click({
|
||||
$form.Tag = "Cancel"
|
||||
$form.Close()
|
||||
})
|
||||
$form.Controls.Add($cancelButton)
|
||||
|
||||
# Show the form
|
||||
$form.ShowDialog()
|
||||
|
||||
# Check the form result
|
||||
if ($form.Tag -eq "Cancel") {
|
||||
Write-Output "Operation cancelled by the user."
|
||||
exit
|
||||
}
|
||||
|
||||
# Import the CSV file
|
||||
$userList = Import-Csv -Path $script:csvPath
|
||||
|
||||
# Check if the path exists, if not create it
|
||||
$destinationPath = "C:\temp\useroutput\done"
|
||||
if (-not (Test-Path -Path $destinationPath)) {
|
||||
New-Item -ItemType Directory -Path $destinationPath | Out-Null
|
||||
}
|
||||
|
||||
# Get today's date
|
||||
$todaysDate = Get-Date -Format "yyyyMMdd"
|
||||
|
||||
# Set the output CSV file path
|
||||
$outputCsvPath = "$destinationPath\users-done-$todaysDate.csv"
|
||||
|
||||
# Loop through each user in the CSV
|
||||
foreach ($user in $userList) {
|
||||
$samAccountName = $user.username
|
||||
|
||||
try {
|
||||
# Get the user object by SamAccountName
|
||||
$userObject = Get-ADUser -Filter {SamAccountName -eq $samAccountName}
|
||||
|
||||
if ($null -eq $userObject) {
|
||||
throw "User '$samAccountName' does not exist."
|
||||
}
|
||||
|
||||
# Set the password to expired
|
||||
Set-ADUser -Identity $samAccountName -ChangePasswordAtLogon $true
|
||||
|
||||
Write-Output "Password for user '$samAccountName' has been set to expired."
|
||||
}
|
||||
catch {
|
||||
Write-Output "Failed to set password for user '$samAccountName': $_"
|
||||
}
|
||||
}
|
||||
catch {
|
||||
Write-Output "Failed to set password for user '$samAccountName': $_"
|
||||
}
|
||||
# Export the updated user list to the new CSV file
|
||||
$userList | Export-Csv -Path $outputCsvPath -NoTypeInformation
|
||||
|
||||
Write-Output "The updated user list has been exported to $outputCsvPath."
|
||||
|
||||
# Rename the source CSV file
|
||||
$originalFileName = [System.IO.Path]::GetFileNameWithoutExtension($script:csvPath)
|
||||
$originalFileExtension = [System.IO.Path]::GetExtension($script:csvPath)
|
||||
$directory = [System.IO.Path]::GetDirectoryName($script:csvPath)
|
||||
$newFileName = "$originalFileName-done-$todaysDate$originalFileExtension"
|
||||
$newFilePath = [System.IO.Path]::Combine($directory, $newFileName)
|
||||
|
||||
Rename-Item -Path $script:csvPath -NewName $newFileName
|
||||
|
||||
Write-Output "The original CSV file has been renamed to $newFilePath."
|
||||
|
||||
# Open the folder containing the renamed CSV file
|
||||
Start-Process -FilePath "explorer.exe" -ArgumentList "/select,`"$newFilePath`""
|
||||
|
||||
# Clear all variables from active memory
|
||||
Remove-Variable -Name form, label, label2, textBox, browseButton, acceptButton, cancelButton, csvPath, userList, destinationPath, todaysDate, outputCsvPath, originalFileName, originalFileExtension, directory, newFileName, newFilePath -ErrorAction SilentlyContinue
|
||||
Reference in New Issue
Block a user