Tuesday, September 2, 2025

Powershell: Microsoft Graph to add new roles to application registration

PowerShell Script
 Bulk add new roles to application registration in azure. Update $roles with ,User
 
# Requires: Microsoft.Graph.Applications module
# Connect to Microsoft Graph with sufficient permissions (e.g., Application.ReadWrite.All)
Connect-MgGraph -scope  "application.readwrite.all" -TenantId "<Tenant-ID>"
# Variables
$AppId = "<App-ID>" # ObjectId of the Azure AD Application

$roles = @"
value,allowedMemberTypes
Group1,User
Group2,User
"@ | ConvertFrom-Csv

$roles = $roles | ForEach-Object {
    [PSCustomObject]@{
        displayName = $_.value
        description = $_.value
        value = $_.value
        allowedMemberTypes = $_.allowedMemberTypes -split ";"
    }
}

# Get the application
$app = Get-MgApplication -ApplicationId $AppId

# Add new roles 
$newRoles = @()
foreach ($role in $roles) {
    $appRole = [Microsoft.Graph.PowerShell.Models.MicrosoftGraphAppRole]::new()
    $appRole.Id = [guid]::NewGuid()
    $appRole.DisplayName = $role.displayName
    $appRole.Description = $role.description
    $appRole.Value = $role.value
    $appRole.AllowedMemberTypes = $role.allowedMemberTypes
    $appRole.IsEnabled = $true
    $appRole.Origin = "Application"
    $newRoles += $appRole
}

# Combine existing roles
$allRoles = @($app.AppRoles) + $newRoles

Update-MgApplication -ApplicationId $AppId -AppRoles $allRoles

Write-Host "Roles added successfully."

Sunday, March 30, 2025

KQL - Group Object Audits ADDS

This is a KQL written for Azure Sentinel. 
Purpose is to search for eventid from Active Directory Domain Services related to Group objects.

SecurityEvent
| where EventID in (4728, 4729, 4732, 4733, 4756, 4757, 4727, 4730, 4731, 4734) // Add or remove from group, create or delete group
| extend 
    Action = case(
        EventID == 4728, "Added to Global Group",
        EventID == 4729, "Removed from Global Group",
        EventID == 4732, "Added to Local Group",
        EventID == 4733, "Removed from Local Group",
        EventID == 4756, "Added to Universal Group",
        EventID == 4757, "Removed from Universal Group",
        EventID == 4727, "Created a Security-Enabled Global Group",
        EventID == 4730, "Deleted a Security-Enabled Global Group",
        EventID == 4731, "Created a Security-Enabled Local Group",
        EventID == 4734, "Deleted a Security-Enabled Local Group",
        "Unknown Action"
    ),
    Initiator = coalesce(tostring(SubjectUserName), tostring(AccountName), "Unknown Initiator")
| summarize 
    FirstOccurrence = min(TimeGenerated)    
    by Action, TargetGroup = TargetAccount, Initiator, Domain = TargetDomainName, MemberName, EventID
| project FirstOccurrence, Action, Initiator, Domain, TargetGroup, MemberName, EventID

Powershell - Search Azure/Entra AD for current status of an employeeID accounts using Graph Batch

Graph is a pain to work with if you are like me and just a scripter 

Takes a list of employee IDs via the $employeeIDs variable 
Queries Azure AD via Microsoft Graph in batches of 20
Retrieves userPrincipalName, employeeId, accountEnabled, 
and LastPasswordChangeDateTime
Outputs results to console and CSV

Connect-MgGraph -Scopes "User.Read.All"

$employeeIds = @"
EMPID
0000001
"@ | ConvertFrom-Csv

$employeeIds = $employeeIds.empid   

# Create batch request body
$batchRequests = @()
$batchSize = 20  # Microsoft Graph allows up to 20 requests per batch
$idCounter = 1

for ($i = 0; $i -lt $employeeIds.Count; $i++) {
    $request = @{
        "id" = "$idCounter"
        "method" = "GET"
        "url" = "/users?`$filter=employeeId eq '$($employeeIds[$i])'&`$select=userPrincipalName,employeeId,accountEnabled,LastPasswordChangeDateTime"
    }
    $batchRequests += $request
    $idCounter++
}

# Split into batches of 20 which i believe is the limit 
$batchedResults = @()
for ($i = 0; $i -lt $batchRequests.Count; $i += $batchSize) {
    $batchEnd = [Math]::Min($i + $batchSize, $batchRequests.Count)
    $currentBatch = $batchRequests[$i..($batchEnd-1)]
    
    $batchBody = @{
        "requests" = $currentBatch
    } | ConvertTo-Json -Depth 10

    # Send batch request
    $response = Invoke-MgGraphRequest -Method POST -Uri "https://graph.microsoft.com/v1.0/`$batch" -Body $batchBody
    
    # Process responses
    foreach ($resp in $response.responses) {
        if ($resp.status -eq 200 -and $resp.body.value) {
            $batchedResults += $resp.body.value | Select-Object @{
                Name = "UserPrincipalName"; Expression = {$_.userPrincipalName}
            }, @{
                Name = "EmployeeID"; Expression = {$_.employeeId}
            }, @{
                Name = "AccountEnabled"; Expression = {$_.accountEnabled}
            }, @{
                Name = "LastPasswordChangeDateTime"; Expression = {$_.LastPasswordChangeDateTime}
            }
        }
    }
}

#Tesults
$batchedResults | Format-Table -AutoSize
$batchedResults | Export-Csv -Path "C:\AzureAD_Employee_Search.csv" -NoTypeInformation

Powershell: Microsoft Graph to add new roles to application registration

PowerShell Script Bulk add new roles to application registration in azure. Update $roles with ,Us...