UserLastLogon -Export - azure

Hi I'm trying to export a list of AD users based on "Last Logon"
I've scripted using base powershell however I'd be interested if anyone can find a solution using "AzureAD to Powershell" commands.
I've gotten as far as getting the list however I cannot export it to any file type because of how it generates through the loop.
End result I'm looking for is to be able to organize the data to see which users have been inactive?
Import-Module ActiveDirectory
function Get-ADUserLastLogon([string]$userName) {
$dcs = Get-ADDomainController -Filter {Name -like "*"}
$time = 0
foreach($dc in $dcs) {
$hostname = $dc.HostName
$user = Get-ADUser $userName | Get-ADObject -Properties lastLogon
if($user.LastLogon -gt $time) {
$time = $user.LastLogon
}
}
$dt = [DateTime]::FromFileTime($time)
Write-Host $username "last logged on at:" $dt
}
$unames = Get-ADUser -Filter 'ObjectClass -eq "User"' | Select -Expand SamAccountName
foreach ($uname in $unames) { Get-ADUserLastLogon($uname); }

In Azure AD, we can get all user Sign-ins records on Azure Portal or using Azure AD PowerShell.
If you are looking for a way by PowerShell to export Azure AD users last login list with user account status (enabled or not), just try the code below:
Connect-AzureAD
$AllUsers = Get-AzureADUser -All $true
$AllSiginLogs = Get-AzureADAuditSignInLogs -All $true
$results = #()
foreach($user in $AllUsers){
$LoginRecord = $AllSiginLogs | Where-Object{ $_.UserId -eq $user.ObjectId } | Sort-Object CreatedDateTime -Descending
if($LoginRecord.Count -gt 0){
$lastLogin = $LoginRecord[0].CreatedDateTime
}else{
$lastLogin = 'no login record'
}
$item = #{
userUPN=$user.UserPrincipalName
userDisplayName = $user.DisplayName
lastLogin = $lastLogin
accountEnabled = $user.AccountEnabled
}
$results += New-Object PSObject -Property $item
}
$results | export-csv -Path d:\result.csv -NoTypeInformation
export to .csv file Result:
There is one thing that you should know, for different Azure AD service tier, the time that Azure AD keep these data is different, details see here.

Related

Powershell - Get-AzureADAuditSignInLogs multiple filters

I'm trying to Get last signin date for Global Admins
$role = Get-AzureADDirectoryRole | Where-Object {$_.displayName -eq 'Global Administrator'}
$admins = #(Get-AzureADDirectoryRoleMember -ObjectId $role.ObjectId | select DisplayName, UserPrincipalName)
Foreach ($admin in $admins){
$upn = $admin.UserPrincipalName
$signons = Get-AzureADAuditSignInLogs -Filter "UserPrincipalName eq '$upn' " -Top 1 | select UserDisplayName, #{Name = 'LastSignIn'; Expression = {$_.CreatedDateTime}}
}
And above code works as expected for users who have entry in AuditSignInLogs, but i want to return users who never logged in too, so modified above filter
(all users in for loop)
$signons = Get-AzureADAuditSignInLogs -Filter "UserPrincipalName eq '$upn' or CreatedDateTime eq '$null'" -Top 1 | select UserDisplayName, #{Name = 'LastSignIn'; Expression = {$_.CreatedDateTime}}
But getting error "Message: Invalid filter clause"
also tried or CreatedDateTime eq '' but same error
Please check below powershell commands.
I have initially checked the same for users .
Then checked the same for admin role i.e;admins and could get the lastlogon for all the admins including who has no recored yet in signins.
$AllSiginLogs = Get-AzureADAuditSignInLogs -All $true
$role = Get-AzureADDirectoryRole | Where-Object {$_.displayName -eq 'Global Administrator'}
$admins = #(Get-AzureADDirectoryRoleMember -ObjectId $role.ObjectId | select DisplayName, UserPrincipalName)
$results = #()
Foreach ($admin in $admins){
$LoginRecord = $AllSiginLogs | Where-Object{ $_.UserId -eq $admin.ObjectId } | Sort-Object CreatedDateTime -Descending
if($LoginRecord.Count -gt 0){
$lastLogin = $LoginRecord[0].CreatedDateTime
}else{
$lastLogin = 'no login record'
}
$item = #{
userUPN=$admin.UserPrincipalName
userDisplayName = $admin.DisplayName
lastLogin = $lastLogin
accountEnabled = $admin.AccountEnabled
}
$results += New-Object PSObject -Property $item
Write-Output $results
}
#$results | export-csv -Path d:\result.csv -NoTypeInformation
Result:
Reference:
userlastlogon-export
thanks #kavyasaraboju-MT
Your hint helped me a lot, based on it, i modified my code which gets what i want
$role = Get-AzureADDirectoryRole | Where-Object {$_.displayName -eq 'Global Administrator'}
$admins = #(Get-AzureADDirectoryRoleMember -ObjectId $role.ObjectId | select DisplayName, UserPrincipalName)
$results = #()
Foreach ($admin in $admins){
$upn = $admin.UserPrincipalName
$LoginRecord = Get-AzureADAuditSignInLogs -Filter "UserPrincipalName eq '$upn'" -Top 1
Start-Sleep -Seconds 2
if($LoginRecord.Count -gt 0){
$lastLogin = $LoginRecord.CreatedDateTime
}
else{
$lastLogin = 'no login record'
}
$item = #{
userUPN=$admin.UserPrincipalName
userDisplayName = $admin.DisplayName
lastLogin = $lastLogin
}
$results += New-Object PSObject -Property $item
}
$results | export-csv -Path c:\result.csv -NoTypeInformation -Encoding UTF8

How to add resource group as one factor to filter the output

<#
NAME
AzureSubscriptionRBACAudit.ps1
SYNOPSIS
Gathers Azure Role Based Access Control Data for Audit Purposes.
DESCRIPTION
Gathers Azure Role Based Access Control Data for Audit Purposes. The script will prompt the user to
select a subscription to run the audit against. The user is only presented the scriptions currently
available to the users credentials.
OUTPUTS
Outputs a CSV file in the same directory that the script is located in. The CSV file will have the
name of the subscription in its title followed by "Azure RBAC Audit.csv"
#>
Functions
Function Login {
<#
.SYNOPSIS
Runs the Azure Login Command
#>
$needLogin = $true
Try {
$content = Get-AzContext
if ($content) {
$needLogin = ([string]::IsNullOrEmpty($content.Account))
}
}
Catch {
if ($_ -like "*Login-AzAccount to login*") {
$needLogin = $true
}
else {
throw
}
}
if ($needLogin) {
#Login-AzAccount
Select-Azure
}
}
Function Select-Azure{
<#
.SYNOPSIS
Provides a list of Azure Environments for the user to select from.
AzureGov, AzureCloud, etc.
#>
Clear-Host
$ErrorActionPreference = 'SilentlyContinue'
$Menu = 0
$AzEnvironment = #(Get-AzEnvironment |select-object Name)
Write-Host "Please select the Azure Environment you want to use:" -ForegroundColor Green;
ForEach-Object {Write-Host ""}
$AzEnvironment | ForEach-Object {Write-Host "[$($Menu)]" -ForegroundColor Cyan -NoNewline ; Write-host ". $($_.Name)"; $Menu++; }
ForEach-Object {Write-Host ""}
ForEach-Object {Write-Host "[Q]" -ForegroundColor Red -NoNewline ; Write-host ". To quit."}
ForEach-Object {Write-Host ""}
$selection = Read-Host "Please select the Azure Environment Number - Valid numbers are 0 - $($AzEnvironment.count -1) or Q to quit"
If ($selection -eq 'Q') {
Clear-Host
Exit
}
If ($AzEnvironment.item($selection) -ne $null)
{ Connect-AzAccount -EnvironmentName $AzEnvironment.item($selection).Name -ErrorAction Stop}
}
Function Select-Subs {
<#
.SYNOPSIS
Provides a list of subscriptions for the user to select from.
#>
Clear-Host
$ErrorActionPreference = 'SilentlyContinue'
$Menu = 0
$Subs = #(Get-AzSubscription | Select-Object Name, ID, TenantId)
Write-Host "Please select the subscription you want to use:" -ForegroundColor Green;
ForEach-Object {Write-Host ""}
$Subs | ForEach-Object {Write-Host "[$($Menu)]" -ForegroundColor Cyan -NoNewline ; Write-host ". $($_.Name)"; $Menu++; }
ForEach-Object {Write-Host ""}
ForEach-Object {Write-Host "[S]" -ForegroundColor Yellow -NoNewline ; Write-host ". To switch Azure Account."}
ForEach-Object {Write-Host ""}
ForEach-Object {Write-Host "[Q]" -ForegroundColor Red -NoNewline ; Write-host ". To quit."}
ForEach-Object {Write-Host ""}
$selection = Read-Host "Please select the Subscription Number - Valid numbers are 0 - $($Subs.count -1), S to switch Azure Account or Q to quit"
If ($selection -eq 'S') {
Get-AzContext | ForEach-Object {Clear-AzContext -Scope CurrentUser -Force}
Select-Azure
Select-Subs
}
If ($selection -eq 'Q') {
Clear-Host
Exit
}
If ($Subs.item($selection) -ne $null)
{ Return #{name = $subs[$selection].Name; ID = $subs[$selection].ID}
}
}
Function Resolve-AzAdGroupMembers {
<#
.SYNOPSIS
Gets list of Azure Active Directory groups and its members
#>
param(
[guid]
$GroupObjectId,
$GroupList
)
$VerbosePreference = 'continue'
Write-Verbose -Message ('Resolving {0}' -f $GroupObjectId)
$group = $GroupList | Where-Object -Property Id -EQ -Value $GroupObjectId
$groupMembers = Get-AzADGroupMember -GroupObjectId $GroupObjectId
Write-Verbose -Message ('Found members {0}' -f ($groupMembers.DisplayName -join ', '))
$parentGroup = #{
Id = $group.Id
DisplayName = $group.DisplayName
}
$groupMembers |
Where-Object -Property Type -NE -Value Group |
Select-Object -Property Id, DisplayName, #{
Name = 'ParentGroup'
Expression = { $parentGroup }
}
$groupMembers |
Where-Object -Property type -EQ -Value Group |
ForEach-Object -Process {
Resolve-AzAdGroupMembers -GroupObjectId $_.Id -GroupList $GroupList
}
}
Main Part of Script
Write-Output "Running login script"
Login # Login to Azure
$SubscriptionSelection = Select-Subs # Runs function to get Azure subscriptions available to user and sets the subscription to the users choice.
Select-AzSubscription -SubscriptionName $SubscriptionSelection.Name -ErrorAction Stop
## Get current Azure Subscription Name to be used in reporting output
$Azuresub = $SubscriptionSelection.Name -replace , '/'
ForEach-Object {Write-Host "Getting Azure AD Groups" -ForegroundColor Yellow -NoNewline}
ForEach-Object {Write-Host "`r`n========================================" -ForegroundColor Yellow -NoNewline}
ForEach-Object {Write-Host "`nThis process can take a while to run since it is checking every Azure Role and its corresponding assignments." -ForegroundColor Yellow -NoNewline }
$GroupList = (Get-AzADGroup)
ForEach-Object {Write-Host "Getting Role Assignments" -ForegroundColor Yellow -NoNewline}
ForEach-Object {Write-Host "`r`n========================================" -ForegroundColor Yellow -NoNewline}
$roleAssignments = Get-AzRoleAssignment -IncludeClassicAdministrators
## Loop through each role assignment to determine the user assigned to that role.
$members = $roleAssignments | ForEach-Object -Process {
Write-Verbose -Message ('Processing Assignment {0}' -f $_.RoleDefinitionName)
$roleAssignment = $_
if($roleAssignment.ObjectType -eq 'Group')
{
Resolve-AzAdGroupMembers -GroupObjectId $roleAssignment.ObjectId -GroupList $GroupList `
| Select-Object -Property Id,
DisplayName,
ParentGroup, #{
Name = 'RoleDefinitionName'
Expression = { $roleAssignment.RoleDefinitionName }
}, #{
Name = 'Scope'
Expression = { $roleAssignment.Scope }
}, #{
Name = 'CanDelegate'
Expression = { $roleAssignment.CanDelegate }
}
}
else
{
$roleAssignment | Select-Object -Property #{
Name = 'Id'
Expression = { $_.ObjectId }
},
DisplayName,
#{
Name = 'RoleDefinitionName'
Expression = { $roleAssignment.RoleDefinitionName }
},
Scope,
CanDelegate
}
}
Generating CSV Output for reporting
$outtbl = #()
$members | ForEach-Object {
$x = New-Object PSObject -Property #{
Subscription = $Azuresub -join ','
ActiveDirID = $_.Id -join ','
DisplayName = $_.DisplayName -join ','
ParentGroupID = $_.ParentGroup.Id -join ','
ParentGroupDisplayName = $_.ParentGroup.DisplayName -join ','
RoleDefinitionName = $_.RoleDefinitionName -join ','
Scope = $_.Scope
}
$outtbl += $x
}
$outtbl | Select-Object Subscription,ActiveDirID,DisplayName,ParentGroupID,ParentGroupDisplayName,RoleDefinitionName, Scope |Export-CSV -path $($PSScriptRoot + "\" + "$Azuresub" + " Azure RBAC Audit.csv") -NoTypeInformation
ForEach-Object {Write-Host " `r`nRBAC Audit has completed. Your CSV file is located: $($PSScriptRoot + "\" + "$Azuresub" + " Azure RBAC Audit.csv")" -ForegroundColor Green -NoNewline }
Above code is working fine for complete subscription but we need to filter the output only for resoucegroup. so how to add one more function to get output only based on reouce group.
https://github.com/arnoldna/RBACReporting/blob/master/AzureSubscriptionRBACAudit.ps1
For your requirement, just use the -ResourceGroupName parameter in the command Get-AzRoleAssignment to specify the resource group you want in Main Part of Script.
$roleAssignments = Get-AzRoleAssignment -IncludeClassicAdministrators -ResourceGroupName <ResourceGroupName>
Note: The RBAC role permissions are inherited, e.g. if a user/service principal/AAD group has an RBAC role at the subscription/management group scope, it will also have the permission at all the resource groups located in the subscription/management group, so the command above will also get the role assignments that assigned at the subscription/management group scope, the management group is a higher scope than subscription, refer to this link.
So if you just want to get the role assignment that directly assigned to the resource group/single resource in the resource group, modify the command as below, it depends on your reqirement.
$roleAssignments = Get-AzRoleAssignment -IncludeClassicAdministrators -ResourceGroupName <ResourceGroupName> | Where-Object {$_.Scope -like '/subscriptions/*/resourceGroups/*'}

I need power shell script to get pricing tier and App type of all the App services (Web apps and Function Apps) in Azure

Example:
Get all the details of App service with Pricing Tier and App type
Below given is power shell script to export Web app details but i am unable to fetch Pricing tier and App type of App service.
#Provide the subscription Id where the Webapps ,function apps resides
$subscriptionId = "XXXXXXXXXXXXXXXXXXXXXXX"
$currentTime=$(get-date).ToString("yyyyMMddHHmmss");
$outputFilePath=".\AzureWebAppsReport-"+$currentTime+".csv"
Set-AzureRmContext $subscriptionId
$result=#()
# Get all the webapps
$webapps =Get-AzureRMWebApp
$AzSubscription = Get-AzureRmSubscription -SubscriptionId $subscriptionId
$rmresources = Get-AzureRmResource | ?{ $_.Sku -NE $null}
# Loop through the webapps
foreach($webapp in $webapps)
{
$info = "" | Select Name,State,LOCATION,ResourceGroup,SUBSCRIPTION,AppServicePlan,PricingTier
foreach($rmResource in $rmresources) {
if($webapp.ResourceGroup -eq $rmResource.ResourceGroupName) {
$info.PricingTier = $rmResource.Sku
}
}
$info.Name = $webapp.Name
$info.State = $webapp.State
$info.LOCATION = $webapp.LOCATION
$info.ResourceGroup = $webapp.ResourceGroup
$info.SUBSCRIPTION = $AzSubscription.Name
$info.AppServicePlan=$webapp.ServerFarmId
#Add the object with above properties to the Array
$result+=$info
}
$result | ft Name,State,LOCATION,ResourceGroup,SUBSCRIPTION,AppServicePlan,PricingTier
#Export the result Array to CSV file
$result | Export-CSV $outputFilePath -NoTypeInformation
You could try my sample below, it works fine on my side.
$AzSubscription = Get-AzSubscription -SubscriptionId "<subscription-id>"
$result=#()
$webapps = Get-AzWebApp
foreach($webapp in $webapps){
$Tier = (Get-AzResource -ResourceId $webapp.ServerFarmId).Sku.Tier
$obj = [PSCustomObject]#{
Name = $webapp.Name
State = $webapp.State
Location = $webapp.Location
PricingTier = $Tier
AppType = $webapp.Kind
ResourceGroup = $webapp.ResourceGroup
Subscription = $AzSubscription.Name
}
$result += $obj
}
$result | Export-Csv -Path "C:\Users\joyw\Desktop\webapps.csv" -NoTypeInformation
The .csv file will be like below:

Exporting Group Types from Azure AD Powershell

I am trying to export all Azure AD groups, their owners, description, email and its group type. Such as Office 365, Security or Distrubution. I have managed to export everything correctly into a .csv except the group type. Get-AzureADGroup will return only "Group" and I can't get any results from get-msolgroup -grouptype.
Script I have been using:
$array = #()
$Properties=#{}
$Properties.add("GroupDisplayName","1")
$Properties.add("OwnerObjectId","2")
$Properties.add("OwnerObjectType","3")
$Properties.add("OwnerUserType","4")
$Properties.add("OwnerUserPrincipalName","5")
$Properties.add("GroupDescription","6")
$Properties.add("Email","7")
$Properties.add("GroupTypes","8")
$groups = Get-AzureADGroup -All $true
$GroupType = Get-MsolGroup -Grouptype
Foreach($group in $groups){
$Owners = Get-AzureADGroupOwner -ObjectId $group.ObjectId -All $true
$Properties.GroupDisplayName=$group.DisplayName
$Properties.GroupDescription=$group.description
$Properties.Email=$group.mail
$Properties.GroupTypes=$group.GroupType
if($Owners -ne $null){
# group has owner
Foreach($Owner in $Owners){
$Properties.OwnerObjectId=$Owner.ObjectId
$Properties.OwnerObjectType=$Owner.ObjectType
$Properties.OwnerUserType=$Owner.UserType
$Properties.OwnerUserPrincipalName=$Owner.UserPrincipalName
$obj=New-Object PSObject -Property $Properties
$array +=$obj
}
}
else{
#group has no owner
$Properties.OwnerObjectId=$null
$Properties.OwnerObjectType=$null
$Properties.OwnerUserType=$null
$Properties.OwnerUserPrincipalName=$null
$obj=New-Object PSObject -Property $Properties
$array +=$obj
}
}
$array | export-csv -Path C:\scripts\Owners13.csv -NoTypeInformation -Encoding UTF8
According to my research, the command Get-MsolGroup is a command of Azure AD V1 module : MSOnline. But the other commands you use are the command of Azure AD V2 module: AzureAD. They are in different modules. So if you want to use the command Get-MsolGroup, you need to run the command Connect-MsolService at frist.
For example:
Connect-MsolService
Get-MsolGroup -all | Select-Object DisplayName, GroupType
Besides, if you just want to use AzureAD module to get group type, we can use the command Get-AzureADMSGroup to get it. But if we use the command, we need to make some judgments by the response's properties. For more details, please refer to the document
For example
Connect-AzureAD
Get-AzureADMSGroup -All $true | Select-Object DisplayName, GroupTypes,MailEnabled, SecurityEnabled
Update
You can use the following script to implement your need.
connect-AzureAD
$array = #()
$Properties=#{}
$Properties.add("GroupDisplayName","1")
$Properties.add("OwnerObjectId","2")
$Properties.add("OwnerObjectType","3")
$Properties.add("OwnerUserType","4")
$Properties.add("OwnerUserPrincipalName","5")
$Properties.add("GroupDescription","6")
$Properties.add("Email","7")
$Properties.add("GroupTypes","8")
$groups = Get-AzureADGroup -All $true
Foreach($group in $groups){
$Owners = Get-AzureADGroupOwner -ObjectId $group.ObjectId -All $true
$Properties.GroupDisplayName=$group.DisplayName
$Properties.GroupDescription=$group.description
$Properties.Email=$group.mail
$result=Get-AzureADMSGroup -Id $group.ObjectId | Select-Object GroupTypes,MailEnabled, SecurityEnabled, DisplayName
If($result.GroupTypes -contains "Unified"){
$Properties.GroupTypes="O365"
}
elseif($result.SecurityEnabled ){
$Properties.GroupTypes="Security"
}
else{
$Properties.GroupTypes="Distrubution"
}
if($Owners -ne $null){
# group has owner
Foreach($Owner in $Owners){
$Properties.OwnerObjectId=$Owner.ObjectId
$Properties.OwnerObjectType=$Owner.ObjectType
$Properties.OwnerUserType=$Owner.UserType
$Properties.OwnerUserPrincipalName=$Owner.UserPrincipalName
$obj=New-Object PSObject -Property $Properties
$array +=$obj
}
}
else{
#group has no owner
$Properties.OwnerObjectId=$null
$Properties.OwnerObjectType=$null
$Properties.OwnerUserType=$null
$Properties.OwnerUserPrincipalName=$null
$obj=New-Object PSObject -Property $Properties
$array +=$obj
}
}
$array | export-csv -Path E:\test.csv -Encoding UTF8 -NoTypeInformation

Disable all site creation except for a certain group

I want to lock down site creation to a certain group of admin suresh. We have created a group for this, but what do I tell the SharePoint Admin to do in order to achieve this?
To lock down site creation, you basically need to run a few PowerShell commands as below using Azure AD PowerShell. Run them commands with Global admin priviledges.
I am assuming that you have created an Azure AD group with certain users who will have access to create the site.
$creds = Get-Credential
Connect-AzureAD -Credential $creds
$group = Get-AzureADGroup -All $True | Where-Object {$_.DisplayName -eq "ENTER GROUP DISPLAY NAME HERE"}
$policySetting = Get-AzureADDirectorySetting | where-object {$_.displayname -eq "Group.Unified"}
if($policySetting -eq $null) {
$template = Get-AzureADDirectorySettingTemplate | Where-Object {$_.DisplayName -eq "Group.Unified"}
$settings = $template.CreateDirectorySetting()
$settings["EnableGroupCreation"] = $false
$settings["GroupCreationAllowedGroupId"] = $group.ObjectId
$policySetting = New-AzureADDirectorySetting -DirectorySetting $settings
}
else{
$policySetting["EnableGroupCreation"] = $false
$policySetting["GroupCreationAllowedGroupId"] = $group.ObjectId
Set-AzureADDirectorySetting -Id $policySetting.Id -DirectorySetting $policySetting
}
Links:
Installing the Azure AD module
Code modified from - Managing Office 365 group creation using Azure AD PowerShell v2

Resources