Skip to content
This repository was archived by the owner on Aug 2, 2023. It is now read-only.

Commit 62e0870

Browse files
Add formatting function, clean up docs
1 parent 00d252a commit 62e0870

2 files changed

Lines changed: 236 additions & 83 deletions

File tree

Lines changed: 42 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,43 @@ function AggregateOutputObject
326326
Write-Output $Output
327327
}
328328

329+
function Write-ADFSEventsSummary
330+
{
331+
#Create Table object
332+
$table = New-Object system.Data.DataTable "SummaryTable"
333+
334+
#Define Columns
335+
$col1 = New-Object system.Data.DataColumn Time,([string])
336+
$col2 = New-Object system.Data.DataColumn EventID,([string])
337+
$col3 = New-Object system.Data.DataColumn Details,([string])
338+
$col4 = New-Object system.Data.DataColumn CorrelationID,([string])
339+
$col5 = New-Object system.Data.DataColumn Machine,([string])
340+
$col6 = New-Object system.Data.DataColumn Log,([string])
341+
$table.columns.add( $col1 )
342+
$table.columns.add( $col2 )
343+
$table.columns.add( $col3 )
344+
$table.columns.add( $col4 )
345+
$table.columns.add( $col5 )
346+
$table.columns.add( $col6 )
347+
348+
foreach($Event in $input.Events){
349+
#Create a row
350+
$row = $table.NewRow()
351+
352+
$row.Time = $Event.TimeCreated
353+
$row.EventID = $Event.Id
354+
$row.Details = $Event.Message
355+
$row.CorrelationID = $Event.CorrelationID
356+
$row.Machine = $Event.MachineName
357+
$row.Log = $Event.LogName
358+
359+
#Add the row to the table
360+
$table.Rows.Add($row)
329361

362+
}
363+
364+
return $table
365+
}
330366

331367
function Get-ADFSEvents
332368
{
@@ -359,9 +395,9 @@ function Get-ADFSEvents
359395
#Provide either correlation id, 'All' parameter, or time range along with logs to be queried and list of remote servers
360396
[CmdletBinding(DefaultParameterSetName='CorrelationIDParameterSet')]
361397
param(
362-
[parameter(Mandatory=$true, Position=0)]
398+
[parameter(Mandatory=$false, Position=0)]
363399
[ValidateSet("Admin", "Debug", "Security")]
364-
[string[]]$Logs,
400+
[string[]]$Logs = @("Security","Admin"),
365401

366402
[parameter(Mandatory=$true, Position=1, ParameterSetName="CorrelationIDParameterSet")]
367403
[ValidateNotNullOrEmpty()]
@@ -379,8 +415,8 @@ function Get-ADFSEvents
379415
[parameter(Mandatory=$true, Position=2, ParameterSetName="AllEventsByTimeSet")]
380416
[DateTime]$EndTime,
381417

382-
[parameter(Mandatory=$true, ValueFromPipeline=$True, ValueFromPipelineByPropertyName=$True)]
383-
[string[]]$Server
418+
[parameter(Mandatory=$false, ValueFromPipeline=$True, ValueFromPipelineByPropertyName=$True)]
419+
[string[]]$Server="LocalHost"
384420
)
385421

386422
Begin
@@ -490,4 +526,5 @@ function Get-ADFSEvents
490526

491527

492528
}
493-
Export-ModuleMember -Function Get-ADFSEvents
529+
Export-ModuleMember -Function Get-ADFSEvents
530+
Export-ModuleMember -Function Write-ADFSEventsSummary

README.md

Lines changed: 194 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -1,113 +1,229 @@
11
# AD FS Log Tools
22

3-
## Get-ADFSEvents Overview
3+
## AdfsEventsModule Overview
44

5-
This script gathers ADFS related events from the security, admin, and debug logs,
6-
and allows the user to reconstruct the HTTP request/response headers from the logs.
5+
This module provides tools for gathering related ADFS events from the security, admin, and debug logs,
6+
across multiple servers. This tool also allows the user to reconstruct the HTTP request/response headers
7+
from the logs.
78

8-
Given a correlation id, the script will gather all events with the same identifier and reconstruct the request
9-
and response headers if they exist. Using the 'All' option (either with or without headers enabled) will first collect
10-
all correlation ids and proceed to gather the events for each. If start and end times are provided, all events
11-
that fall into that span will be returned. The start and end times will be assumed to be base times. That is, all
12-
time conversions will be based on the UTC of these values.
9+
## Cmdlets in AdfsEventsModule
1310

14-
The output produced by Get-ADFSEvents is a list of objects with each containing the following properties:
15-
16-
1. CorrelationID
17-
18-
2. Events
19-
20-
3. Headers
21-
22-
The CorrelationID property contains a string representation of the correlation id that all events and headers within that object share.
23-
24-
The Events property contains a list of [EventLogRecord](https://msdn.microsoft.com/en-us/library/system.diagnostics.eventing.reader.eventlogrecord)
25-
objects that share the particular correlation id.
26-
27-
The Headers property contains a list of objects, each composed of the following properties:
28-
29-
1.QueryString
11+
This module exposes two cmdlets:
3012

31-
2.ResponseString
13+
__```Get-ADFSEvents```__
3214

33-
3.RequestHeader
15+
and
3416

35-
4.ResponseHeader
17+
__```Write-ADFSEventsSummary```__
3618

37-
The QueryString property contains the HTTP verb (GET, POST, etc) and the corresponding query string.
38-
39-
The ResponseString property contains the HTTP response string (ex. 200 ok)
40-
41-
The RequestHeader property is a dictionary representing the various headers included in the HTTP request
42-
43-
The ResponseHeader property is a dictionary representing the various headers included in the HTTP response
44-
45-
As a final note, the output is, by default, merely dumped to the console to allow users to manipulate the objects returned.
46-
While this will likely prove sufficient for many users, those who desire future access to the output should use ```Export-Clixml```
47-
to write the output to an xml file. ```Import-Clixml``` can then be used to reconstruct the objects from the file. Examples of both are
48-
included in the Using Get-ADFSEvents section below.
49-
50-
## Using Get-ADFSEvents
51-
52-
1. Import the PowerShell Module
19+
The detailed parameters for each are provided below.
5320

54-
In a PowerShell window, run the following:
5521

56-
```ipmo Get-ADFSEvents.psm1```
22+
The ```Get-ADFSEvents``` cmdlet is used to aggregate events by correlation ID, while the ```Write-ADFSEventsSummary```
23+
cmdlet is used to generate a PowerShell Table of only the most relevant logging information from the events that are piped
24+
in.
5725

58-
2. Run Get-ADFSEvents
59-
60-
EXAMPLE
26+
## Get-ADFSEvents Parameters
6127

62-
```Get-ADFSEvents -Logs Security, Admin, Debug -CorrelationID 669bced6-d6ae-4e69-889b-09ceb8db78c9 -Server LocalHost, MyServer```
28+
* __Logs__ - A list of AD FS logs to include in the aggregation. Current options are: "Admin", "Debug", "Security".
29+
The default will pull from both Security and Admin.
30+
* __CorrelationID__ - The correlation ID for a single request. This will aggregate all chosen logs for this request
31+
* __AllWithoutHeaders__ - this flag will cause all requests to be grouped by correlation ID, but the HTTP headers
32+
will not be extracted from the logs
33+
* __AllWithHeaders__ - this flag will cause all requests to be grouped by correlation ID, and the HTTP headers of
34+
each request will be extracted from the logs
35+
* __StartTime__ - the UTC start time to use when aggregating multiple requests. All requests that start after this
36+
time will be aggregated
37+
* __EndTime__ - the UTC end time to use when aggregating multiple requests. All requests that end before this time
38+
will be aggregated
39+
* __Server__ - a comma-separated list of server names to pull logs from.
40+
The default will pull from LocalHost
6341

64-
EXAMPLE
42+
## Get-ADFSEvents Output
6543

66-
```Get-ADFSEvents -Logs Admin -AllWithHeaders -Server LocalHost```
44+
The output produced by Get-ADFSEvents is a list of objects with each containing the following properties:
6745

68-
EXAMPLE
46+
1. __CorrelationID__
47+
2. __Events__
48+
3. __Headers__
6949

70-
```Get-ADFSEvents -Logs Debug, Security -AllWithoutHeaders -Server LocalHost, Server1, Server2```
50+
The __CorrelationID__ property contains a string representation of the Correlation ID that all events and headers within that object share.
7151

72-
EXAMPLE
52+
The __Events__ property contains a list of [EventLogRecord](https://msdn.microsoft.com/en-us/library/system.diagnostics.eventing.reader.eventlogrecord)
53+
objects for the matching Correlation ID.
7354

74-
```Get-ADFSEvents -Logs Debug -StartTime (Get-Date -Date "1970-01-01 00:00:00Z") -EndTime (Get-Date) -Server localhost```
55+
The __Headers__ property contains a list of objects, each containing of the following properties:
7556

76-
EXAMPLE
57+
1. __QueryString__
58+
2. __ResponseString__
59+
3. __RequestHeader__
60+
4. __ResponseHeader__
7761

78-
```$Result = Get-ADFSEvents -Logs Admin -AllWithHeaders -Server LocalHost```
62+
The __QueryString__ property contains the HTTP verb (GET, POST, etc) and the corresponding query string.
7963

80-
```$CorrelationID = $Result[0].CorrelationID #Obtain correlation id for first entry in output```
64+
The __ResponseString__ property contains the HTTP response string (ex. 200 ok)
8165

82-
```$Events = $Result[0].Events #List of EventLogRecord objects```
66+
The __RequestHeader__ property is a dictionary containing the headers included in the HTTP request
8367

84-
```$QueryString = $Result[0].Headers[0].QueryString #Query String for first header in list```
68+
The __ResponseHeader__ property is a dictionary containing the headers included in the HTTP response
8569

86-
EXAMPLE
8770

88-
```Get-ADFSEvents -Logs Security, Admin, Debug -AllWithHeaders -Server localhost | Export-Clixml "output.xml" #Store output in file```
71+
## Using Get-ADFSEvents
8972

90-
```$ReconstructedOutput = Import-Clixml output.xml #Rebuild objects from xml file```
73+
1. Import the PowerShell Module
9174

92-
## Get-ADFSEvents Parameters
75+
In a PowerShell window, run the following:
76+
77+
```ipmo AdfsEventsModule.psm1```
78+
79+
2. Run Get-ADFSEvents with your desired parameters to get a list of PowerShell objects
80+
81+
EXAMPLE: Retrieve all logs from two servers for a specific request
82+
83+
```$logs = Get-ADFSEvents -Logs Security, Admin, Debug -CorrelationID 0c0fd6ee-4b1e-4260-0300-0080070000e3 -Server LocalHost, MyServer```
84+
85+
OUTPUT:
86+
87+
```
88+
Events Headers CorrelationID
89+
------ ------- -------------
90+
91+
{EventLogRecord, EventLogRecord} {} 0c0fd6ee-4b1e-4260-0300-0080070000e3
92+
```
93+
94+
3. To view specific records:
95+
96+
```$logs.Events[0]```
97+
98+
OUTPUT:
99+
100+
```
101+
Message : An HTTP request was received. See audit 510 with the same Instance ID for headers.
102+
103+
Instance ID: 64fb88c5-7f4e-4888-8b61-7d0d85563b82
104+
105+
Activity ID: 0c0fd6ee-4b1e-4260-0300-0080070000e3
106+
107+
Request Details:
108+
Date And Time: 2017-09-19 20:50:43
109+
Client IP: 123.45.67.9
110+
HTTP Method: GET
111+
Url Absolute Path: /adfs/portal/logo/logo.png
112+
Query string: ?id=12345
113+
Local Port: 443
114+
Local IP: 123.45.67.8
115+
User Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36
116+
Content Length: 0
117+
Caller Identity: -
118+
Certificate Identity (if any): -
119+
Targeted relying party: -
120+
Through proxy: False
121+
Proxy DNS name: -
122+
CorrelationID : 0c0fd6ee-4b1e-4260-0300-0080070000e3
123+
PSComputerName : LocalHost
124+
RunspaceId : 6d3d7715-08db-4aa1-b299-40d51d5db682
125+
Id : 403
126+
Version :
127+
Qualifiers : 0
128+
Level : 0
129+
Task : 3
130+
Opcode :
131+
Keywords : 12345
132+
RecordId : 12345
133+
ProviderName : AD FS Auditing
134+
ProviderId :
135+
LogName : Security
136+
ProcessId :
137+
ThreadId :
138+
MachineName : contoso.com
139+
UserId :
140+
TimeCreated : 9/19/2017 1:50:43 PM
141+
ActivityId :
142+
RelatedActivityId :
143+
ContainerLog : security
144+
MatchedQueryIds : {}
145+
Bookmark : System.Diagnostics.Eventing.Reader.EventBookmark
146+
LevelDisplayName : Information
147+
OpcodeDisplayName : Info
148+
TaskDisplayName :
149+
KeywordsDisplayNames : {Audit Success, Classic}
150+
Properties : {}
151+
```
152+
153+
4. You can pipe your output to ```Write-ADFSEventsSummary```
154+
155+
EXAMPLE:
156+
157+
```Get-ADFSEvents -Logs Security, Admin, Debug -CorrelationID 0c0fd6ee-4b1e-4260-0300-0080070000e3 -Server LocalHost, MyServer | Write-ADFSEventsSummary```
158+
159+
OUTPUT:
160+
161+
```
162+
Time : 9/19/2017 1:50:43 PM
163+
EventID : 403
164+
Details : An HTTP request was received. See audit 510 with the same Instance ID for headers.
165+
166+
Instance ID: 64fb88c5-7f4e-4888-8b61-7d0d85563b82
167+
168+
Activity ID: 0c0fd6ee-4b1e-4260-0300-0080070000e3
169+
170+
Request Details:
171+
Date And Time: 2017-09-19 20:50:43
172+
Client IP: 123.45.67.9
173+
HTTP Method: GET
174+
Url Absolute Path: /adfs/portal/logo/logo.png
175+
Query string: ?id=12345
176+
Local Port: 443
177+
Local IP: 123.45.67.8
178+
User Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36
179+
Content Length: 0
180+
Caller Identity: -
181+
Certificate Identity (if any): -
182+
Targeted relying party: -
183+
Through proxy: False
184+
Proxy DNS name: -
185+
CorrelationID : 0c0fd6ee-4b1e-4260-0300-0080070000e3
186+
Machine : contoso.com
187+
Log : Security
188+
189+
Time : 9/19/2017 1:50:43 PM
190+
EventID : 410
191+
Details : Following request context headers present :
192+
193+
Activity ID: 0c0fd6ee-4b1e-4260-0300-0080070000e3
194+
195+
X-MS-Client-Application: -
196+
X-MS-Client-User-Agent: -
197+
client-request-id: -
198+
X-MS-Endpoint-Absolute-Path: /adfs/portal/logo/logo.png
199+
X-MS-Forwarded-Client-IP: -
200+
X-MS-Proxy: -
201+
X-MS-ADFS-Proxy-Client-IP: -
202+
CorrelationID : 0c0fd6ee-4b1e-4260-0300-0080070000e3
203+
Machine : contoso.com
204+
Log : Security
205+
```
206+
207+
5. You can pipe the output of ```Write-ADFSEventsSummary``` to a CSV
208+
209+
```Get-ADFSEvents -Logs Security, Admin, Debug -CorrelationID 0c0fd6ee-4b1e-4260-0300-0080070000e3 -Server LocalHost, MyServer | Write-ADFSEventsSummary | Export-CSV mylogs.csv```
210+
211+
212+
6. You can output the full data objects from ```Get-ADFSEvents``` to XML using:
213+
214+
```Export-Clixml```
215+
216+
```Import-Clixml```
93217
94-
* Logs - A list of AD FS logs to include in the aggregation. Current options are: "Admin", "Debug", "Security"
95-
* CorrelationID - The correlation ID for a single request. This will aggregate all chosen logs for this request
96-
* AllWithoutHeaders - this flag will cause all requests to be grouped by correlation ID, but the HTTP headers
97-
will not be extracted from the logs
98-
* AllWithHeaders - this flag will cause all requests to be grouped by correlation ID, and the HTTP headers of
99-
each request will be extracted from the logs
100-
* StartTime - the UTC start time to use when aggregating multiple requests. All requests that start after this
101-
time will be aggregated
102-
* EndTime - the UTC end time to use when aggregating multiple requests. All requests that end before this time
103-
will be aggregated
104-
* Server - a comma-separated list of server names to pull logs from
105218
106219
## Contributing
107220
108-
This project welcomes contributions and suggestions. Most contributions require you to agree to a
109-
Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us
110-
the rights to use your contribution. For details, visit https://cla.microsoft.com.
221+
This project welcomes contributions and suggestions. We encourage you to fork this project, include any scripts you
222+
use for parsing, managing, or manipulating ADFS logs, and then do a pull request to master. If your scripts work,
223+
we'll include them so everyone can benefit.
224+
225+
Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that you have the
226+
right to, and actually do, grant us the rights to use your contribution. For details, visit https://cla.microsoft.com.
111227
112228
When you submit a pull request, a CLA-bot will automatically determine whether you need to provide
113229
a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the instructions

0 commit comments

Comments
 (0)