A simulated Microsoft 365 college tenant demonstrating full-cycle identity governance, Conditional Access hardening, and PowerShell-driven lifecycle automation. Built over a single session from tenant zero to fully audited environment — 27 governed users, 4 dynamic security groups, and a complete audit trail.
Built sequentially in a single session — each phase building on the last, from raw tenant to fully audited, hardened, and scripted environment.
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
# ---------- -- -----------------
# xyz.inc 31faeb7a-0aac-4053-9668-2f2ccdf58abb 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 tied to a concrete admin action. Filter by lab phase to follow the execution story from tenant provisioning to full audit coverage. ChatGPT used 14 of 66 available — this gallery uses 43.
Skills demonstrated map directly to M365 Administrator, IAM Analyst, Cloud Support, SOC Tier 2/3, and Identity Engineer roles.