Merged PR 61172: updated custom roles, Optimized table and blob check scripts, Added user last login script

- Added new subscriptions to custom roles
- Optimized table and blob check scripts
- Added user last login script
This commit is contained in:
Jurjen Ladenius Effectory
2025-07-11 12:53:00 +00:00
parent 1f5d3bc0ed
commit 847173c58e
7 changed files with 22454 additions and 8876 deletions

View File

@@ -1,7 +1,9 @@
param (
[string] $subscriptionId = "",
[string] $resourcegroupName = "",
[string] $storageAccountName = ""
[string] $storageAccountName = "",
[bool] $containersOnly = $false,
[string[]] $excludedContainers = @()
)
if (("" -eq $subscriptionId) -or ("" -eq $resourcegroupName) -or ("" -eq $storageAccountName)) {
@@ -14,6 +16,20 @@ else {
# .\AzureStoragebloblist.ps1 -subscriptionId "7feeb150-9ee0-4aea-992a-5f3a89d933e6" -resourcegroupName "results-activity" -storageAccountName "effactivity"
# .\AzureStoragebloblist.ps1 -subscriptionId "7feeb150-9ee0-4aea-992a-5f3a89d933e6" -resourcegroupName "Results" -storageAccountName "myeffectoryresults"
# .\AzureStoragebloblist.ps1 -subscriptionId "a134faf1-7a89-4f2c-8389-06d00bd5e2a7" -resourcegroupName "Default-Storage-WestEurope" -storageAccountName "ecestore"
# .\AzureStoragebloblist.ps1 -subscriptionId "1ab2120c-947c-40e2-96c7-460d3e9659de" -resourcegroupName "sa-backups" -storageAccountName "archivecommvault"
# .\AzureStoragebloblist.ps1 -subscriptionId "1ab2120c-947c-40e2-96c7-460d3e9659de" -resourcegroupName "sa-backups" -storageAccountName "backupcommvault"
# .\AzureStoragebloblist.ps1 -subscriptionId "2a07dfa7-69ee-4608-b2d5-14124fcccc31" -resourcegroupName "questionnaire-server-weu" -storageAccountName "questionnairestoreweu"
# .\AzureStoragebloblist.ps1 -subscriptionId "a134faf1-7a89-4f2c-8389-06d00bd5e2a7" -resourcegroupName "Default-Storage-WestEurope" -storageAccountName "mailingstore"
# .\AzureStoragebloblist.ps1 -subscriptionId "a134faf1-7a89-4f2c-8389-06d00bd5e2a7" -resourcegroupName "Default-Storage-WestEurope" -storageAccountName "projectcenter"
# .\AzureStoragebloblist.ps1 -subscriptionId "a134faf1-7a89-4f2c-8389-06d00bd5e2a7" -resourcegroupName "effectorycore" -storageAccountName "corerightsaggregator" -ContainersOnly $true
# .\AzureStoragebloblist.ps1 -subscriptionId "3190b0fd-4a66-4636-a204-5b9f18be78a6" -resourcegroupName "authorization" -storageAccountName "authorizationv2"
# .\AzureStoragebloblist.ps1 -subscriptionId "86945e42-fa5a-4bbc-948f-3f5407f15d3e" -resourcegroupName "hierarchy" -storageAccountName "hierarchyeff"
# .\AzureStoragebloblist.ps1 -subscriptionId "f9ab522b-4895-492d-b8a8-ca6e1f60c2a8" -resourcegroupName "participant-exchange" -storageAccountName "participantexchangev2" -excludedContainers "leases","insights-metrics-pt1m","insights-logs-partitionkeystatistics","insights-logs-dataplanerequests","insights-logs-controlplanerequests","event-attachments","command-handlers","aggregates-streaming","aggregates","`$logs","`$blobchangefeed"
# .\AzureStoragebloblist.ps1 -subscriptionId "14c2354d-45a9-4e0f-98ff-be58cdbcddc7" -resourcegroupName "ec-automation-prod" -storageAccountName "stecautomationprod"
# .\AzureStoragebloblist.ps1 -subscriptionId "14c2354d-45a9-4e0f-98ff-be58cdbcddc7" -resourcegroupName "ec-measurement" -storageAccountName "stecmeasurementprod"
# .\AzureStoragebloblist.ps1 -subscriptionId "2a07dfa7-69ee-4608-b2d5-14124fcccc31" -resourcegroupName "questionnaire-server-weu" -storageAccountName "questionnairedataweu"
# .\AzureStoragebloblist.ps1 -subscriptionId "54794e27-b714-4346-81bc-05eae7ccb5a5" -resourcegroupName "question-management-api-weu" -storageAccountName "qmprojectionsweu" -excludedContainers "`$logs","`$blobchangefeed"
class BlobCheck {
[string] $SubscriptionId = ""
@@ -35,43 +51,77 @@ $fileName = ".\$date - $storageAccountName - bloblist.csv"
$subscription = Set-AzContext -SubscriptionId $subscriptionId
$storageAccount = Get-AzStorageAccount -ResourceGroupName $resourcegroupName -Name $storageAccountName
do {
$containers = Get-AzStorageContainer -Context $storageAccount.Context -MaxCount $maxCount -ContinuationToken $containerToken
foreach ($container in $containers) {
do {
[BlobCheck[]]$Result = @()
$blobList = Get-AzStorageBlob -Container $Container.Name -Context $storageAccount.Context -MaxCount $maxCount -ContinuationToken $blobToken #-Prefix "projects"
if ($blobList.Length -le 0) {
Break;
}
foreach($blob in $blobList) {
[BlobCheck] $blobCheck = [BlobCheck]::new()
$blobCheck.SubscriptionId = $subscription.Subscription.Id
$blobCheck.SubscriptionName = $subscription.Subscription.Name
$blobCheck.ResourcegroupName = $resourcegroupName
$blobCheck.StorageAccountName = $storageAccountName
$blobCheck.ContainerName = $container.Name
$blobCheck.BlobName = $blob.Name
$blobCheck.LastModifiedDate = $blob.LastModified
$Result += $blobCheck
}
$Result | Export-Csv -Path $fileName -NoTypeInformation -Append
$blobToken = $blobList[$blobList.Count -1].ContinuationToken;
if ($containersOnly -eq $true) {
do {
[BlobCheck[]]$Result = @()
$containers = Get-AzStorageContainer -Context $storageAccount.Context -MaxCount $maxCount -ContinuationToken $containerToken
if ($excludedContainers.Length -gt 0) {
$containers = $containers | Where-Object { $excludedContainers -notcontains $_.Name }
}
while ($null -ne $blobToken)
foreach ($container in $containers) {
[BlobCheck] $blobCheck = [BlobCheck]::new()
$blobCheck.SubscriptionId = $subscription.Subscription.Id
$blobCheck.SubscriptionName = $subscription.Subscription.Name
$blobCheck.ResourcegroupName = $resourcegroupName
$blobCheck.StorageAccountName = $storageAccountName
$blobCheck.ContainerName = $container.Name
$blobCheck.BlobName = ""
$blobCheck.LastModifiedDate = $container.LastModified
$Result += $blobCheck
}
if ($Result.Length -gt 0) {
$Result | Export-Csv -Path $fileName -NoTypeInformation -Append
}
if ($containers.Length -le 0)
{
Break;
}
$containerToken = $containers[$containers.Count -1].ContinuationToken;
}
if ($containers.Length -le 0)
{
Break;
}
$containerToken = $containers[$containers.Count -1].ContinuationToken;
while ($null -ne $containerToken)
}
while ($null -ne $containerToken)
elseif ($containersOnly -eq $false) {
do {
$containers = Get-AzStorageContainer -Context $storageAccount.Context -MaxCount $maxCount -ContinuationToken $containerToken
if ($excludedContainers.Length -gt 0) {
$containers = $containers | Where-Object { $excludedContainers -notcontains $_.Name }
}
foreach ($container in $containers) {
do {
[BlobCheck[]]$Result = @()
$blobList = Get-AzStorageBlob -Container $Container.Name -Context $storageAccount.Context -MaxCount $maxCount -ContinuationToken $blobToken #-Prefix "projects"
if ($blobList.Length -le 0) {
Break;
}
foreach($blob in $blobList) {
[BlobCheck] $blobCheck = [BlobCheck]::new()
$blobCheck.SubscriptionId = $subscription.Subscription.Id
$blobCheck.SubscriptionName = $subscription.Subscription.Name
$blobCheck.ResourcegroupName = $resourcegroupName
$blobCheck.StorageAccountName = $storageAccountName
$blobCheck.ContainerName = $container.Name
$blobCheck.BlobName = $blob.Name
$blobCheck.LastModifiedDate = $blob.LastModified
$Result += $blobCheck
}
$Result | Export-Csv -Path $fileName -NoTypeInformation -Append
$blobToken = $blobList[$blobList.Count -1].ContinuationToken;
}
while ($null -ne $blobToken)
}
if ($containers.Length -le 0)
{
Break;
}
$containerToken = $containers[$containers.Count -1].ContinuationToken;
}
while ($null -ne $containerToken)
}

View File

@@ -0,0 +1,35 @@
param (
[string] $subscriptionId = "",
[string] $resourcegroupName = "",
[string] $storageAccountName = "",
[string] $tableName = ""
)
if (("" -eq $subscriptionId) -or ("" -eq $resourcegroupName) -or ("" -eq $storageAccountName) -or ("" -eq $tableName)) {
throw "Parameter(s) missing."
}
else {
Import-Module AzTable
}
[string] $date = Get-Date -Format "yyyy-MM-dd HHmm"
$fileName = ".\$date - $storageAccountName - tablecheck.csv"
# .\AzureStorageTableListEntities.ps1 -subscriptionId "86945e42-fa5a-4bbc-948f-3f5407f15d3e" -resourcegroupName "hierarchy" -storageAccountName "hierarchyeff" -tableName "auditlog"
$subscription = Set-AzContext -SubscriptionId $subscriptionId
$storageAccount = Get-AzStorageAccount -ResourceGroupName $resourcegroupName -Name $storageAccountName
$tables = Get-AzStorageTable -Context $storageAccount.Context -Name $tableName
foreach ($table in $tables) {
$rows = Get-AzTableRow -table $table.CloudTable
if (($null -ne $rows) -and ($rows.Length -gt 0)) {
Write-Host "Processing subscription [$subscriptionId], resource group [$resourcegroupName], storage account [$storageAccountName] -> table [$($table.Name)]"
$rows | Export-Csv -Path $fileName -NoTypeInformation -Append
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,107 @@
Import-Module Microsoft.Graph
# .\UserLastLoginList.ps1 -GroupName "# Developer ADM"
param(
[Parameter(Mandatory = $true)]
[string]$GroupName
)
function Get-EntraGroupByName {
param(
[Parameter(Mandatory = $true)]
[string]$EntraGroupName
)
try {
Write-Debug "Retrieving group ID for group: $EntraGroupName"
# Get group by name
$group = Get-MgGroup -Filter "displayName eq '$EntraGroupName'"
if ($group) {
return $group.Id
}
else {
Write-Warning "Group '$EntraGroupName' not found"
return $null
}
}
catch {
Write-Error "Error retrieving group: $($_.Exception.Message)"
return $null
}
}
Write-Debug "Connecting to Microsoft Graph..."
# Connect to Microsoft Graph if not already connected
if (-not (Get-MgContext)) {
Connect-MgGraph -Scopes "User.Read.All", "Group.Read.All"
}
function Get-EntraGroupUsersRecursive {
param(
[Parameter(Mandatory = $true)]
[string]$GroupId,
[hashtable]$ProcessedGroups = @{}
)
try {
# Prevent infinite recursion by tracking processed groups
if ($ProcessedGroups.ContainsKey($GroupId)) {
Write-Debug "Group $GroupId already processed, skipping to prevent recursion"
return @()
}
$ProcessedGroups[$GroupId] = $true
Write-Debug "Retrieving users recursively from group with ID: $GroupId"
# Get group members
$groupMembers = Get-MgGroupMember -GroupId $GroupId -All
$users = @()
foreach ($member in $groupMembers) {
if ($member.AdditionalProperties["@odata.type"] -eq "#microsoft.graph.user") {
Write-Debug "Processing user: $($member.DisplayName) ($($member.Id))"
$user = Get-MgUser -UserId $member.Id -Property "signInActivity,displayName,userPrincipalName"
$users += [PSCustomObject]@{
UserPrincipalName = $user.UserPrincipalName
DisplayName = $user.DisplayName
LastSignInDateTime = if ($user.SignInActivity) { $user.SignInActivity.LastSignInDateTime } else { "No sign-in data available" }
}
}
elseif ($member.AdditionalProperties["@odata.type"] -eq "#microsoft.graph.group") {
Write-Debug "Processing nested group: $($member.DisplayName) ($($member.Id))"
$nestedUsers = Get-EntraGroupUsersRecursive -GroupId $member.Id -ProcessedGroups $ProcessedGroups
$users += $nestedUsers
}
}
return $users
}
catch {
Write-Error "Error retrieving group users recursively: $($_.Exception.Message)"
return @()
}
}
$groupId = Get-EntraGroupByName -EntraGroupName $GroupName
if ($groupId) {
# Get users recursively from the group
Write-Host "Getting users recursively from group..."
$recursiveUsers = Get-EntraGroupUsersRecursive -GroupId $groupId
if ($recursiveUsers) {
Write-Host "Found $($recursiveUsers.Count) users (including nested groups):"
$recursiveUsers | Sort-Object DisplayName | Format-Table -AutoSize
}
else {
Write-Warning "No users found in the group hierarchy or an error occurred."
}
}
else {
Write-Warning "Group not found."
}