A simulated Microsoft 365 college tenant demonstrating identity governance, staged Conditional Access, and PowerShell-driven lifecycle automation. The lab documents 27 governed users, 4 dynamic security groups, and a complete audit trail.
Built as a sequenced lab where each phase builds on the last, from tenant foundation to scripted validation, reporting, and security posture review.
27 users provisioned, job titles, departments, RBAC role assignments per persona
4 dynamic security groups with Entra ID rules, 65.45% Identity Secure Score baseline
MFA for Admins + Block Legacy Auth — staged in report-only mode for safe rollout
Graph API queries for governance, licensing, sign-in telemetry, and lifecycle automation
CSV exports, directory audit logs, SSPR insights, sign-in telemetry, device baseline
Microsoft Graph PowerShell 7.4.13 drove the entire audit, lifecycle, and reporting layer — making every operation repeatable, scriptable, and evidence-backed.
# Install Microsoft Graph module (PSGallery)
Install-Module Microsoft.Graph -Scope CurrentUser
# Connect with full admin scopes
Connect-MgGraph -Scopes "User.ReadWrite.All","Directory.ReadWrite.All",
"Group.ReadWrite.All","AuditLog.Read.All"
# Verify tenant connection
Get-MgOrganization | Select DisplayName,Id,CountryLetterCode,VerifiedDomains
# DisplayName Id CountryLetterCode
# ---------- -- -----------------
# Contoso Lab sanitized-tenant-id CA
# Enumerate all 27 tenant users
Get-MgUser | Select DisplayName,UserPrincipalName
# Full classification audit: name, UPN, job title, department
Get-MgUser -All -Property DisplayName,UserPrincipalName,JobTitle,Department |
Select DisplayName,UserPrincipalName,JobTitle,Department
# Result: 27 users classified
# Students (6), Professors (4), IT Operations (4), Security Operations (1)
# Identify accounts with no assigned license
$unlicensed = Get-MgUser -All -Property DisplayName,AssignedLicenses |
Where-Object { $_.AssignedLicenses.Count -eq 0 }
# Returns: Aisha Rahman, Chloe Martin, Daniel Kim,
# Jason Patel, Ryan Chen, Sarah Ahmed — 6 unlicensed students
# List all groups
Get-MgGroup | Select DisplayName
# Filter: show only Dynamic security groups + their membership rules
Get-MgGroup -All -Property DisplayName,GroupTypes,MembershipRule |
Where-Object { $_.GroupTypes -contains "DynamicMembership" } |
Select DisplayName,MembershipRule
# DisplayName MembershipRule
# ---------------- -----------------------------------------------
# Security Operations (user.jobTitle -eq "Security Operations")
# Students 2 (user.jobTitle -eq "Student")
# Professors (user.jobTitle -eq "Professor")
# IT Operations (user.department -eq "IT Operations")
# Reconnect with write permissions for lifecycle ops
Connect-MgGraph -Scopes "User.ReadWrite.All","Directory.ReadWrite.All","Group.ReadWrite.All"
# Filter unlicensed students
$unlicensedStudents = Get-MgUser -All -Property Id,DisplayName,UserPrincipalName,JobTitle,Department,AssignedLicenses |
Where-Object { $_.JobTitle -eq "Student" -and $_.AssignedLicenses.Count -eq 0 }
# Export backup before any changes
$unlicensedStudents | Select DisplayName,UserPrincipalName,Department |
Export-Csv Unlicensed-Students-Backup.csv -NoTypeInformation
# Bulk deprovision
$unlicensedStudents | ForEach-Object { Remove-MgUser -UserId $_.Id }
# Reprovision from backup CSV
Import-Csv Unlicensed-Students-Backup.csv | ForEach-Object {
New-MgUser -DisplayName $_.DisplayName -UserPrincipalName $_.UserPrincipalName
}
# Export sign-in telemetry to CSV
Get-MgAuditLogSignIn -Top 50 |
Select UserDisplayName,UserPrincipalName,AppDisplayName,
Status,ConditionalAccessStatus,CreatedDateTime,IPAddress,Location |
Export-Csv SignIn-Audit.csv -NoTypeInformation
# MFA registration audit
Get-MgUser -All | ForEach-Object {
$methods = Get-MgUserAuthenticationMethod -UserId $_.Id
[PSCustomObject]@{
User = $_.DisplayName
MFAEnabled = ($methods.Count -gt 1)
}
} | Export-Csv MFA-Audit-Report.csv -NoTypeInformation
# Directory audit — view user creation events
Get-MgDirectoryAuditLog -Filter "activityDisplayName eq 'Add user'" |
Select ActivityDateTime,Result,InitiatedBy
# Last sign-in per user
Get-MgUser -All -Property SignInActivity |
Select DisplayName, @{Name="LastSignIn";Expression={$_.SignInActivity.LastSignInDateTime}}
Every screenshot is tied to a concrete admin action. Filter by lab phase to follow the execution story from tenant provisioning to audit coverage.
Skills demonstrated map directly to M365 Administrator, IAM Analyst, Cloud Support, SOC Tier 2/3, and Identity Engineer roles.