Skip to content

Commit

Permalink
organized scripts in folders
Browse files Browse the repository at this point in the history
  • Loading branch information
adbertram committed Aug 30, 2015
1 parent 1782133 commit 9f4d655
Show file tree
Hide file tree
Showing 60 changed files with 639 additions and 643 deletions.
File renamed without changes.
142 changes: 142 additions & 0 deletions ActiveDirectory/Get-ActiveDirectoryUserActivity.ps1
@@ -0,0 +1,142 @@
#Requires -Module ActiveDirectory

<#
.SYNOPSIS
This script finds all logon and logoff times of all users on all computers in an Active Directory organizational unit.
The appropriate audit policies must be enabled first because the appropriate event IDs will show up.
.EXAMPLE
PS> Get-ActiveDirectoryUserActivity.ps1 -OrganizationalUnit 'OU=My Desktops,DC=lab,DC=local' -EmailToAddress administrator@lab.local
This example will query the security event logs of all computers in the AD OU 'My Desktops' and find
all instances of the events IDs 4647 and 4648 in the security event logs. It will then generate a friendly
report showing the user name, time generated, if the event was a logon or logoff and the computer
the event came from. Once the file is generated, it will then send an email to administrator@lab.local
with the user report attached.
.PARAMETER OrganizationalUnit
The distinguisned name of the AD organizational unit that you'd like to query the security event log of computers.
.PARAMETER EventID
Two event IDs representing logon and logoff events.
.PARAMETER EmailToAddress
The email address that you'd like to send the final report to.
.PARAMETER EmailFromAddress
The email address you'd like the report sent to show it's from.
.PARAMETER EmailSubject
The subject of the email that will contain the user activity report.
.INPUTS
None. You cannot pipe objects to Get-ActiveDirectoryUserActivity.ps1.
.OUTPUTS
None. If successful, this script does not output anything.
#>
[CmdletBinding()]
[OutputType()]
param
(
[Parameter(Mandatory)]
[ValidateNotNullOrEmpty()]
[ValidatePattern('^OU\=')]
[string]$OrganizationalUnit,

[Parameter()]
[string[]]$EventId = @(4647,4648),

[Parameter()]
[ValidateNotNullOrEmpty()]
[string]$EmailToAddress,

[Parameter()]
[ValidateNotNullOrEmpty()]
[string]$EmailFromAddress = 'IT Administrator',

[Parameter()]
[ValidateNotNullOrEmpty()]
[string]$EmailSubject = 'User Activity Report'

)
process {
try
{
#region Gather all applicable computers
$Computers = Get-ADComputer -SearchBase $OrganizationalUnit -Filter * | Select-Object Name
if (-not $Computers)
{
throw "No computers found in OU [$($OrganizationalUnit)]"
}
#endregion

#region Build XPath filter
$XPathElements = @()
foreach ($id in $EventId)
{
$XPathElements += "Event[System[EventID='$Id']]"
}
$EventFilterXPath = $XPathElements -join ' or '
#endregion

#region Build the array that will display the information we want
$LogonId = $EventId[1]
$LogoffId = $EventId[0]

$SelectOuput = @(
@{ n = 'ComputerName'; e = { $_.MachineName } },
@{
n = 'Event'; e = {
if ($_.Id -eq $LogonId)
{
'Logon'
}
else
{
'LogOff'
}
}
},
@{ n = 'Time'; e = { $_.TimeCreated } },
@{
n = 'Account'; e = {
if ($_.Id -eq $LogonId)
{
$i = 1
}
else
{
$i = 3
}
[regex]::Matches($_.Message, 'Account Name:\s+(.*)\n').Groups[$i].Value.Trim()
}
}
)
#endregion

#region Query the computers' event logs and send output to a file to email
$TempFile = 'C:\useractivity.txt'
foreach ($Computer in $Computers) {
Get-WinEvent -ComputerName $Computer -LogName Security -FilterXPath $EventFilterXPath | Select-Object $SelectOuput | Out-File $TempFile
}
#endregion

$emailParams = @{
'To' = $EmailToAddress
'From' = $EmailFromAddress
'Subject' = $EmailSubject
'Attachments' = $TempFile
}

Send-MailMessage @emailParams

} catch {
Write-Error $_.Exception.Message
}
finally
{
## Cleanup the temporary file generated
Remove-Item -Path $TempFile -Force -ErrorAction SilentlyContinue
}
}
File renamed without changes.
164 changes: 164 additions & 0 deletions ActiveDirectory/Get-AdGroupMembershipChange.ps1
@@ -0,0 +1,164 @@
#requires -Module ActiveDirectory

<#
.SYNOPSIS
This script queries multiple Active Directory groups for new members in a domain. It records group membership
in a CSV file in the same location as the script is located. On the script's initial run it will simply record
all members of all groups into this CSV file. On subsequent runs it will query each group's member list and compare
that list to what's in the CSV file. If any differences are found (added or removed) the script will update the
CSV file to reflect current memberships and notify an administrator of which members were either added or removed.
.NOTES
Filename: Get-AdGroupMembershipChange.ps1
.EXAMPLE
PS> .\Get-AdGroupMembershipChange.ps1 -Group 'Enterprise Admins','Domain Admins','Schema Admins' -Email abertram@lab.local
This example will query group memberships of the Enterprise Admins, Domain Admins and Schema Admins groups and email
abertram@lab.local when a member is either added or removed from any of these groups.
.PARAMETER Group
One or more group names to monitor for membership changes
.PARAMETER DomainController
By default the Active Directory module will automatically find a domain controller to query. If this parameter is set
the script will directly query this domain controller.
.PARAMETER Email
The email address of the administrator that would like to get notified of group changes.
.PARAMETER LogFilePath
The path to where the group membership CSV file will be placed. This is the file that will record the most recent
group membership and will be used to compare current to most recent.
#>
[CmdletBinding(SupportsShouldProcess)]
[OutputType('System.Management.Automation.PSCustomObject')]
param (
[Parameter(Mandatory)]
[string[]]$Group,
[Parameter()]
[ValidatePattern('\b[A-Z0-9._%+-]+@(?:[A-Z0-9-]+\.)+[A-Z]{2,4}\b')]
[string]$Email = 'admin@lab.local',
[Parameter()]
[string]$LogFilePath = "$PsScriptRoot\$($MyInvocation.MyCommand.Name).csv"
)

begin {
$ErrorActionPreference = [System.Management.Automation.ActionPreference]::Stop
Set-StrictMode -Version Latest

function Write-Log {
<#
.SYNOPSIS
This function creates or appends a line to a log file
.DESCRIPTION
This function writes a log line to a log file
.PARAMETER Message
The message parameter is the log message you'd like to record to the log file
.PARAMETER LogLevel
The logging level is the severity rating for the message you're recording.
You have 3 severity levels available; 1, 2 and 3 from informational messages
for FYI to critical messages. This defaults to 1.
.EXAMPLE
PS C:\> Write-Log -Message 'Value1' -LogLevel 'Value2'
This example shows how to call the Write-Log function with named parameters.
#>
[CmdletBinding()]
param (
[Parameter(Mandatory)]
[string]$Message,
[Parameter()]
[ValidateSet(1, 2, 3)]
[int]$LogLevel = 1
)

try {
$TimeGenerated = "$(Get-Date -Format HH:mm:ss).$((Get-Date).Millisecond)+000"
## Build the line which will be recorded to the log file
$Line = '{2} {1}: {0}'
$LineFormat = $Message, $TimeGenerated, (Get-Date -Format MM-dd-yyyy)
$Line = $Line -f $LineFormat

Add-Content -Value $Line -Path $LogFilePath
} catch {
Write-Error $_.Exception.Message
}
}

function Add-GroupMemberToLogFile ($GroupName,[string[]]$Member) {
foreach ($m in $Member) {
[pscustomobject]@{'Group' = $GroupName; 'Member' = $m} | Export-Csv -Path $LogFilePath -Append -NoTypeInformation
}
}

function Get-GroupMemberFromLogFile ([string]$GroupName) {
(Import-Csv -Path $LogFilePath | Where-Object { $_.Group -eq $GroupName }).Member
}

function Send-ChangeNotification ($GroupName,$ChangeType,$Members) {
$EmailBody = "
The following group has changed: $GroupName`n`r
The following members were $ChangeType`n`r
$($Members -join ',')
"

$Params = @{
'From' = 'Active Directory Administrator <admin@mycompany.com>'
'To' = $Email
'Subject' = 'AD Group Change'
'SmtpServer' = 'my.smptpserver.local'
'Body' = $EmailBody
}
Send-MailMessage @Params
}
}

process {
try {
Write-Log -Message 'Querying Active directory domain for group memberships...'
foreach ($g in $Group) {
Write-Log -Message "Querying the [$g] group for members..."
$CurrentMembers = (Get-ADGroupMember -Identity $g).Name
if (-not $CurrentMembers) {
Write-Log -Message "No members found in the [$g] group."
} else {
Write-Log -Message "Found [$($CurrentMembers.Count)] members in the [$g] group"
if (-not (Test-Path -Path $LogFilePath -PathType Leaf)) {
Write-Log -Message "The log file [$LogFilePath] does not exist yet. This must be the first run. Dumping all members into it..."
Add-GroupMemberToLogFile -GroupName $g -Member $CurrentMembers
} else {
Write-Log -Message 'Existing log file found. Reading previous group members...'
$PreviousMembers = Get-GroupMemberFromLogFile -GroupName $g
$ComparedMembers = Compare-Object -ReferenceObject $PreviousMembers -DifferenceObject $CurrentMembers
if (-not $ComparedMembers) {
Write-Log "No differences found in group $g"
} else {
$RemovedMembers = ($ComparedMembers | Where-Object { $_.SideIndicator -eq '<=' }).InputObject
if (-not $RemovedMembers) {
Write-Log -Message 'No members have been removed since last check'
} else {
Write-Log -Message "Found [$($RemovedMembers.Count)] members that have been removed since last check"
Send-ChangeNotification -GroupName $g -ChangeType 'Removed' -Members $RemovedMembers
Write-Log -Message "Emailed change notification to $Email"
## Remove the members from the CSV file to keep the file current
(Import-Csv -Path $LogFilePath | Where-Object {$RemovedMembers -notcontains $_.Member}) | Export-Csv -Path $LogFilePath -NoTypeInformation
}
$AddedMembers = ($ComparedMembers | Where-Object { $_.SideIndicator -eq '=>' }).InputObject
if (-not $AddedMembers) {
Write-Log -Message 'No members have been removed since last check'
} else {
Write-Log -Message "Found [$($AddedMembers.Count)] members that have been added since last check"
Send-ChangeNotification -GroupName $g -ChangeType 'Added' -Members $AddedMembers
Write-Log -Message "Emailed change notification to $Email"
## Add the members from the CSV file to keep the file current
$AddedMembers | foreach {[pscustomobject]@{'Group' = $g; 'Member' = $_}} | Export-Csv -Path $LogFilePath -Append -NoTypeInformation
}

}
}
}

}

} catch {
Write-Error "$($_.Exception.Message) - Line Number: $($_.InvocationInfo.ScriptLineNumber)"
}
}
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

0 comments on commit 9f4d655

Please sign in to comment.