forked from o365soa/Scripts
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathGet-InactiveUsers.ps1
More file actions
154 lines (116 loc) · 6.61 KB
/
Get-InactiveUsers.ps1
File metadata and controls
154 lines (116 loc) · 6.61 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
##############################################################################################
#This sample script is not supported under any Microsoft standard support program or service.
#This sample script is provided AS IS without warranty of any kind.
#Microsoft further disclaims all implied warranties including, without limitation, any implied
#warranties of merchantability or of fitness for a particular purpose. The entire risk arising
#out of the use or performance of the sample script and documentation remains with you. In no
#event shall Microsoft, its authors, or anyone else involved in the creation, production, or
#delivery of the scripts be liable for any damages whatsoever (including, without limitation,
#damages for loss of business profits, business interruption, loss of business information,
#or other pecuniary loss) arising out of the use of or inability to use the sample script or
#documentation, even if Microsoft has been advised of the possibility of such damages.
##############################################################################################
<#
.SYNOPSIS
Inactive users standalone script
.DESCRIPTION
This script is designed to collect a list of users who have not signed in for 30 days or more.
The Office 365: Security Optimization Assessment Azure AD application must exist
for this to function.
.PARAMETER SignInType
Filter users on interactive or non-interactive sign-ins. Valid value is Interactive or NonInterctive.
Interactive is the default.
.NOTES
Version 1.2
April 22, 2023
.LINK
about_functions_advanced
#>
#Requires -Modules AzureADPreview, ExchangeOnlineManagement
[CmdletBinding()]
param (
[ValidateSet('Interactive','NonInteractive')]$SignInType = 'Interactive'
)
Start-Transcript -Path "Transcript-inactiveusers.txt" -Append
# Connect to Azure AD. This is required to get the access token.
Write-Host -ForegroundColor Green "$(Get-Date) Connecting to Azure AD. Use an account with the ability to manage Azure AD applications."
Import-Module AzureADPreview
Connect-AzureAD
# Get the AzureAD Application and create a secret
Write-Host -ForegroundColor Green "$(Get-Date) Creating a new client secret for the SOA application."
$GraphApp = Get-AzureADApplication -Filter "displayName eq 'Office 365 Security Optimization Assessment'"
$clientID = $GraphApp.AppId
$secret = New-AzureADApplicationPasswordCredential -ObjectId $GraphApp.ObjectId -EndDate (Get-Date).AddDays(2) -CustomKeyIdentifier "$(Get-Date -Format "dd-MMM-yyyy")"
# Let the secret settle
Write-Host -ForegroundColor Green "$(Get-Date) Sleeping for 60 seconds to let the client secret replicate."
Start-sleep 60
# Find a suitable MSAL library - Requires that the ExchangeOnlineManagement module is installed
$ExoModule = Get-Module -Name "ExchangeOnlineManagement" -ListAvailable | Sort-Object Version -Descending | Select-Object -First 1
# Add support for the .Net Core version of the library. Variable doesn't exist in PowerShell v4 and below,
# so if it doesn't exist it is assumed that 'Desktop' edition is used
If ($PSEdition -eq 'Core'){
$Folder = "netCore"
} Else {
$Folder = "NetFramework"
}
$MSAL = Join-Path $ExoModule.ModuleBase "$($Folder)\Microsoft.Identity.Client.dll"
Write-Verbose "$(Get-Date) Loading module from $MSAL"
Try {Add-Type -LiteralPath $MSAL | Out-Null} Catch {} # Load the MSAL library
# Get a token
Write-Host -ForegroundColor Green "$(Get-Date) Getting an access token"
$GraphAppDomain = (Get-AzureADTenantDetail | Select-Object -ExpandProperty VerifiedDomains | Where-Object { $_.Initial }).Name
$authority = "https://login.microsoftonline.com/$graphappdomain"
$resource = "https://graph.microsoft.com"
$ccApp = [Microsoft.Identity.Client.ConfidentialClientApplicationBuilder]::Create($ClientID).WithClientSecret($Secret.Value).WithAuthority($Authority).Build()
$Scopes = New-Object System.Collections.Generic.List[string]
$Scopes.Add("$($Resource)/.default")
$Token = $ccApp.AcquireTokenForClient($Scopes).ExecuteAsync().GetAwaiter().GetResult()
If ($Token){Write-Verbose "$(Get-Date) Successfully got a token using MSAL for $($Resource)"}
# Set authentication headers
$GraphAuthHeader = @{'Authorization'="$($Token.TokenType) $($Token.AccessToken)"}
# Get Graph data and continue paging until data collection is complete
Write-Host -ForegroundColor Green "$(Get-Date) Get Graph data and continue paging until data collection is complete"
$targetdate = (Get-Date).AddDays(-30).ToString("yyyy-MM-dd")
$Result = @()
if ($SignInType -eq 'Interactive') {
$siFilter = 'signInActivity/lastSignInDateTime'
}
else {
$siFilter = 'signInActivity/lastNonInteractiveSignInDateTime'
}
$ApiUrl = "https://graph.microsoft.com/beta/users?`$filter=$siFilter lt $($targetdate)T00:00:00Z&`$select=accountEnabled,id,userType,signInActivity,userprincipalname"
$Response = Invoke-RestMethod -Headers $GraphAuthHeader -Uri $ApiUrl -Method Get
$Users = $Response.value
$Result = $Users
While ($null -ne $Response.'@odata.nextLink') {
$Response = Invoke-RestMethod -Headers $GraphAuthHeader -Uri $Response.'@odata.nextLink' -Method Get
$Users = $Response.value
$Result += $Users
}
# Processing user data to prepare export
Write-Host -ForegroundColor Green "$(Get-Date) Processing user data to prepare export"
$return=@()
foreach ($item in $result) {
if ( $null -ne $item.userPrincipalName -and $item.accountEnabled -eq $true) {
$Return += New-Object -TypeName PSObject -Property @{
UserPrincipalName=$item.userprincipalname
LastInteractiveSignIn=$item.signinactivity.lastsignindatetime
LastNonInteractiveSignInDateTime=$item.signinactivity.lastNonInteractiveSignInDateTime
UserType=$item.usertype
}
}
}
# Exporting CSV
Write-Host -ForegroundColor Green "$(Get-Date) Exporting AAD-InactiveUsers.csv in current directory."
$return | Select-Object -Property UserPrincipalName,UserType,LastInteractiveSignIn,LastNonInteractiveSignInDateTime | Export-CSV AAD-InactiveUsers.csv -NoTypeInformation
# Remove client secret
Write-Host -ForegroundColor Green "$(Get-Date) Removing client secrets for the SOA application."
$secrets = Get-AzureADApplicationPasswordCredential -ObjectId $GraphApp.ObjectId
foreach ($secret in $secrets) {
# Suppress errors in case a secret no longer exists
try {
Remove-AzureADApplicationPasswordCredential -ObjectId $GraphApp.ObjectId -KeyId $secret.KeyId
}
catch {}
}
Stop-Transcript