Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Get-EntraUserInactiveSignIn #1191

Open
wants to merge 27 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
e05df00
GA command
SteveMutungi254 Nov 6, 2024
666b08b
Adding params variable
SteveMutungi254 Nov 7, 2024
0f80780
Adding pagesize param
SteveMutungi254 Nov 7, 2024
fa24c6d
Fixing query operand mismatch
SteveMutungi254 Nov 7, 2024
304c665
Fixing custom object outputs
SteveMutungi254 Nov 7, 2024
4ced9a6
Formatting with PowerShell
SteveMutungi254 Nov 7, 2024
87425ce
Added unit tests
SteveMutungi254 Nov 7, 2024
90abf7a
Adding GA documentation
SteveMutungi254 Nov 7, 2024
f5f9e02
Adding Beta command (code, docs, tests)
SteveMutungi254 Nov 7, 2024
75dbad2
Adding required scopes
SteveMutungi254 Nov 7, 2024
e13fbdd
Adding note section.
SteveMutungi254 Nov 7, 2024
b6c83bc
Adding debug information
SteveMutungi254 Nov 7, 2024
23446a1
Fixing build error
SteveMutungi254 Nov 7, 2024
7248719
Fixing test build failures
SteveMutungi254 Nov 7, 2024
6c45e17
Adding a new test, invalid Ago data type
SteveMutungi254 Nov 7, 2024
4f7b1ce
Adding Mail as a required mock property
SteveMutungi254 Nov 7, 2024
813964c
Additional Unit test properties coverage
SteveMutungi254 Nov 7, 2024
c87b3e8
Date formatting fixes
SteveMutungi254 Nov 7, 2024
d762d82
Adding required mock properties
SteveMutungi254 Nov 7, 2024
3a33330
Adding empty value for lastNonInteractiveSignInRequestId
SteveMutungi254 Nov 7, 2024
b715a5b
Adding missing property - LastNonInteractiveSignInRequestId
SteveMutungi254 Nov 7, 2024
69e0f08
Fixing build errors
SteveMutungi254 Nov 7, 2024
61cc761
Merge branch 'main' into Get-EntraUserInactiveSignIn
SteveMutungi254 Nov 13, 2024
6b1b095
Testing return type
SteveMutungi254 Nov 13, 2024
579d784
Reverting changes
SteveMutungi254 Nov 13, 2024
db1f3f5
Experiment with Graph object
SteveMutungi254 Nov 13, 2024
06d2568
Adding custom object
SteveMutungi254 Nov 13, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# ------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All Rights Reserved.
# Licensed under the MIT License. See License in the project root for license information.
# ------------------------------------------------------------------------------

function Get-EntraUserInactiveSignIn {
[CmdletBinding(DefaultParameterSetName = 'GetQuery')]
[OutputType([string])]
param (
# User Last Sign In Activity is before Days ago
[Parameter(
Mandatory = $true,
ValueFromPipeline = $true,
HelpMessage = "Number of days to check for Last Sign In Activity"
)]
[Alias("LastSignInBeforeDaysAgo")]
[int]
$Ago,

# Return results for All, Member, or Guest userTypes
[Parameter(
HelpMessage = "Specifies the type of user to filter. Choose 'All' for all users, 'Member' for internal users, or 'Guest' for external users."
)]
[ValidateSet("All", "Member", "Guest")]
[System.String]
$UserType = "All"
)

process {
$params = @{}
$customHeaders = New-EntraCustomHeaders -Command $MyInvocation.MyCommand

foreach ($param in @("Debug", "WarningVariable", "InformationVariable", "InformationAction", "OutVariable", "OutBuffer", "ErrorVariable", "PipelineVariable", "ErrorAction", "WarningAction")) {
if ($PSBoundParameters.ContainsKey($param)) {
$params[$param] = $PSBoundParameters[$param]
}
}

$queryDate = Get-Date (Get-Date).AddDays($(0 - $Ago)) -UFormat %Y-%m-%dT00:00:00Z
$queryFilter = ("(signInActivity/lastSignInDateTime le {0})" -f $queryDate)

Write-Debug ("Retrieving Users with Filter {0}" -f $queryFilter)

Write-Debug("============================ TRANSFORMATIONS ============================")
$params.Keys | ForEach-Object { "$_ : $($params[$_])" } | Write-Debug
Write-Debug("=========================================================================`n")

$queryUsers = Get-MgUser -Filter $queryFilter -PageSize 999 -All:$true -Property signInActivity, UserPrincipalName, Id, DisplayName, mail, userType, createdDateTime, accountEnabled -Headers $customHeaders

$users = if ($UserType -eq "All") {
$queryUsers
}
else {
$queryUsers | Where-Object { $_.userType -eq $UserType }
}

foreach ($userObject in $users) {
$checkedUser = [ordered] @{
UserID = $userObject.Id
DisplayName = $userObject.DisplayName
UserPrincipalName = $userObject.UserPrincipalName
Mail = $userObject.Mail
UserType = $userObject.UserType
AccountEnabled = $userObject.AccountEnabled
LastSignInDateTime = $userObject.signInActivity.LastSignInDateTime
LastSigninDaysAgo = if ($null -eq $userObject.signInActivity.LastSignInDateTime) { "Unknown" } else { (New-TimeSpan -Start $userObject.signInActivity.LastSignInDateTime -End (Get-Date)).Days }
lastSignInRequestId = $userObject.signInActivity.lastSignInRequestId
lastNonInteractiveSignInDateTime = if ($null -eq $userObject.signInActivity.lastNonInteractiveSignInDateTime) { "Unknown" } else { $userObject.signInActivity.lastNonInteractiveSignInDateTime }
LastNonInteractiveSigninDaysAgo = if ($null -eq $userObject.signInActivity.lastNonInteractiveSignInDateTime) { "Unknown" } else { (New-TimeSpan -Start $userObject.signInActivity.lastNonInteractiveSignInDateTime -End (Get-Date)).Days }
lastNonInteractiveSignInRequestId = $userObject.signInActivity.lastNonInteractiveSignInRequestId
CreatedDateTime = if ($null -eq $userObject.CreatedDateTime) { "Unknown" } else { $userObject.CreatedDateTime }
CreatedDaysAgo = if ($null -eq $userObject.CreatedDateTime) { "Unknown" } else { (New-TimeSpan -Start $userObject.CreatedDateTime -End (Get-Date)).Days }
}

Write-Output ([pscustomobject]$checkedUser)
SteveMutungi254 marked this conversation as resolved.
Show resolved Hide resolved
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# ------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All Rights Reserved.
# Licensed under the MIT License. See License in the project root for license information.
# ------------------------------------------------------------------------------

function Get-EntraBetaUserInactiveSignIn {
[CmdletBinding(DefaultParameterSetName = 'GetQuery')]
[OutputType([string])]
param (
# User Last Sign In Activity is before Days ago
[Parameter(
Mandatory = $true,
ValueFromPipeline = $true,
HelpMessage = "Number of days to check for Last Sign In Activity"
)]
[Alias("LastSignInBeforeDaysAgo")]
[int]
$Ago,

# Return results for All, Member, or Guest userTypes
[Parameter(
HelpMessage = "Specifies the type of user to filter. Choose 'All' for all users, 'Member' for internal users, or 'Guest' for external users."
)]
[ValidateSet("All", "Member", "Guest")]
[System.String]
$UserType = "All"
)

process {
$params = @{}
$customHeaders = New-EntraBetaCustomHeaders -Command $MyInvocation.MyCommand

foreach ($param in @("Debug", "WarningVariable", "InformationVariable", "InformationAction", "OutVariable", "OutBuffer", "ErrorVariable", "PipelineVariable", "ErrorAction", "WarningAction")) {
if ($PSBoundParameters.ContainsKey($param)) {
$params[$param] = $PSBoundParameters[$param]
}
}

$queryDate = Get-Date (Get-Date).AddDays($(0 - $Ago)) -UFormat %Y-%m-%dT00:00:00Z
$queryFilter = ("(signInActivity/lastSignInDateTime le {0})" -f $queryDate)

Write-Debug ("Retrieving Users with Filter {0}" -f $queryFilter)

Write-Debug("============================ TRANSFORMATIONS ============================")
$params.Keys | ForEach-Object { "$_ : $($params[$_])" } | Write-Debug
Write-Debug("=========================================================================`n")

$queryUsers = Get-MgBetaUser -Filter $queryFilter -PageSize 999 -All:$true -Property signInActivity, UserPrincipalName, Id, DisplayName, mail, userType, createdDateTime, accountEnabled -Headers $customHeaders

$users = if ($UserType -eq "All") {
$queryUsers
}
else {
$queryUsers | Where-Object { $_.userType -eq $UserType }
}

foreach ($userObject in $users) {
$checkedUser = [ordered] @{
UserID = $userObject.Id
DisplayName = $userObject.DisplayName
UserPrincipalName = $userObject.UserPrincipalName
Mail = $userObject.Mail
UserType = $userObject.UserType
AccountEnabled = $userObject.AccountEnabled
LastSignInDateTime = $userObject.signInActivity.LastSignInDateTime
LastSigninDaysAgo = if ($null -eq $userObject.signInActivity.LastSignInDateTime) { "Unknown" } else { (New-TimeSpan -Start $userObject.signInActivity.LastSignInDateTime -End (Get-Date)).Days }
lastSignInRequestId = $userObject.signInActivity.lastSignInRequestId
lastNonInteractiveSignInDateTime = if ($null -eq $userObject.signInActivity.lastNonInteractiveSignInDateTime) { "Unknown" } else { $userObject.signInActivity.lastNonInteractiveSignInDateTime }
LastNonInteractiveSigninDaysAgo = if ($null -eq $userObject.signInActivity.lastNonInteractiveSignInDateTime) { "Unknown" } else { (New-TimeSpan -Start $userObject.signInActivity.lastNonInteractiveSignInDateTime -End (Get-Date)).Days }
lastNonInteractiveSignInRequestId = $userObject.signInActivity.lastNonInteractiveSignInRequestId
CreatedDateTime = if ($null -eq $userObject.CreatedDateTime) { "Unknown" } else { $userObject.CreatedDateTime }
CreatedDaysAgo = if ($null -eq $userObject.CreatedDateTime) { "Unknown" } else { (New-TimeSpan -Start $userObject.CreatedDateTime -End (Get-Date)).Days }
}

Write-Output ([pscustomobject]$checkedUser)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
---
title: Get-EntraBetaUserInactiveSignIn
description: This article provides details on the Get-EntraBetaUserInactiveSignIn command.


ms.topic: reference
ms.date: 11/08/2024
ms.author: eunicewaweru
ms.reviewer: stevemutungi
manager: CelesteDG
author: msewaweru
external help file: Microsoft.Graph.Entra.Beta-Help.xml
Module Name: Microsoft.Graph.Entra.Beta
online version: https://learn.microsoft.com/powershell/module/Microsoft.Graph.Entra.Beta/Get-EntraBetaUserInactiveSignIn

schema: 2.0.0
---

# Get-EntraBetaUserInactiveSignIn

## Synopsis

Retrieve users without interactive sign-ins in the last N days.

## Syntax

```powershell
Get-EntraBetaUserInactiveSignIn
-Ago <Int32>
[-UserType <String>]
[<CommonParameters>]
```

## Description

This cmdlet retrieves users without interactive sign-ins in the last N days.

## Examples

### Example 1: Retrieve users without interactive sign-ins in the last 10 days

```powershell
Connect-Entra -Scopes 'User.Read.All','AuditLog.Read.All'
Get-EntraBetaUserInactiveSignIn -Ago 10
```

```Output
UserID : cccccccc-2222-3333-4444-dddddddddddd
DisplayName : Allan Deyoung
UserPrincipalName : [email protected]
Mail : [email protected]
UserType : Member
AccountEnabled : True
LastSignInDateTime : 10/7/2024 12:15:17 PM
LastSigninDaysAgo : 30
lastSignInRequestId : eeeeeeee-4444-5555-6666-ffffffffffff
lastNonInteractiveSignInDateTime : 10/7/2024 12:13:13 PM
LastNonInteractiveSigninDaysAgo : 30
lastNonInteractiveSignInRequestId : dddddddd-3333-4444-5555-eeeeeeeeeeee
CreatedDateTime : 10/7/2024 12:32:30 AM
CreatedDaysAgo : 31
```

This example shows how to find users who haven’t signed in within the past 30 days.

### Example 2: Retrieve guest users without interactive sign-ins in the last 10 days

```powershell
Connect-Entra -Scopes 'User.Read.All','AuditLog.Read.All'
Get-EntraBetaUserInactiveSignIn -Ago 10 -UserType 'Guest'
```

```Output
UserID : cccccccc-2222-3333-4444-dddddddddddd
DisplayName : Allan Deyoung
UserPrincipalName : [email protected]
Mail : [email protected]
UserType : Guest
AccountEnabled : True
LastSignInDateTime : 10/7/2024 12:15:17 PM
LastSigninDaysAgo : 30
lastSignInRequestId : eeeeeeee-4444-5555-6666-ffffffffffff
lastNonInteractiveSignInDateTime : 10/7/2024 12:13:13 PM
LastNonInteractiveSigninDaysAgo : 30
lastNonInteractiveSignInRequestId : dddddddd-3333-4444-5555-eeeeeeeeeeee
CreatedDateTime : 10/7/2024 12:32:30 AM
CreatedDaysAgo : 31
```

This example shows how to find guest users who haven’t signed in within the past 30 days. Choose `All` for all users, `Member` for internal users, or `Guest` for external users.

## Parameters

### -Ago

Number of days to check for Last Sign In Activity.

```yaml
Type: System.Int32
Parameter Sets: (All)
Aliases: LastSignInBeforeDaysAgo

Required: True
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```

### -UserType

Specifies the type of user to filter. Choose `All` for all users, `Member` for internal users, or `Guest` for external users.

```yaml
Type: System.String
Parameter Sets: (All)
Aliases:

Required: False
Position: Named
Default value: All
Accept pipeline input: False
Accept wildcard characters: False
```

### CommonParameters

This cmdlet supports the common parameters: `-Debug`, `-ErrorAction`, `-ErrorVariable`, `-InformationAction`, `-InformationVariable`, `-OutVariable`, `-OutBuffer`, `-PipelineVariable`, `-Verbose`, `-WarningAction`, and `-WarningVariable`. For more information, see [about_CommonParameters](https://go.microsoft.com/fwlink/?LinkID=113216).

## Inputs

### System.String

## Outputs

### System.Object

## Notes

Updating Role Assignable Groups or Privileged Access Groups require `PrivilegedAccess.ReadWrite.AzureADGroup` permission scope.

## Related Links

[Get-EntraBetaUser](Get-EntraBetaUser.md)
Loading