Skip to content

Commit

Permalink
added service principals to aad report and updated LoadObjectDataInto…
Browse files Browse the repository at this point in the history
…PrivilegedUserHashtable to get privileged service principals
  • Loading branch information
dagarwal-mitre committed Feb 7, 2025
1 parent 101c8b0 commit 34b55f1
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 16 deletions.
26 changes: 26 additions & 0 deletions PowerShell/ScubaGear/Modules/CreateReport/CreateReport.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -271,13 +271,39 @@ function New-Report {
# Create a section header for the licensing information
$LicensingHTML = "<h2>Tenant Licensing Information</h2>" + $LicenseTable

if ($null -ne $SettingsExport -and $null -ne $SettingsExport.privileged_service_principals) {

# Create a section for privileged service principals
$privilegedServicePrincipalsTable = $SettingsExport.privileged_service_principals.psobject.properties | ForEach-Object {
$principal = $_.Value
[pscustomobject]@{
"Display Name" = $principal.DisplayName
"Service Principal ID" = $principal.ServicePrincipalId
"Roles" = ($principal.roles -join ", ")
"App ID" = $principal.AppId

}
} | ConvertTo-Html -Fragment

$privilegedServicePrincipalsTable = $privilegedServicePrincipalsTable -replace '^(.*?)<table>', '<table id="privileged-service-principals" style="text-align:center;">'

# Create a section header for the service principal information
$privilegedServicePrincipalsTableHTML = "<h2>Privileged Service Principal Table</h2>" + $privilegedServicePrincipalsTable
$ReportHTML = $ReportHTML.Replace("{SERVICE_PRINCIPAL}", $privilegedServicePrincipalsTableHTML)

}
else{
$ReportHTML = $ReportHTML.Replace("{SERVICE_PRINCIPAL}", "")

}
$ReportHTML = $ReportHTML.Replace("{AADWARNING}", $AADWarning)
$ReportHTML = $ReportHTML.Replace("{LICENSING_INFO}", $LicensingHTML)
$CapJson = ConvertTo-Json $SettingsExport.cap_table_data
}
else {
$ReportHTML = $ReportHTML.Replace("{AADWARNING}", $NoWarning)
$ReportHTML = $ReportHTML.Replace("{LICENSING_INFO}", "")
$ReportHTML = $ReportHTML.Replace("{SERVICE_PRINCIPAL}", "")
$CapJson = "null"
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ <h1>{TITLE}</h1>
<h4>{AADWARNING}</h4>
{TABLES}
{LICENSING_INFO}
{SERVICE_PRINCIPAL}
</main>
</body>
</html>
86 changes: 70 additions & 16 deletions PowerShell/ScubaGear/Modules/Providers/ExportAADProvider.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -112,22 +112,40 @@ function Export-AADProvider {
# The RequiredServicePlan variable is used so that PIM Cmdlets are only executed if the tenant has the premium license
$RequiredServicePlan = $ServicePlans | Where-Object -Property ServicePlanName -eq -Value "AAD_PREMIUM_P2"

# Get-PrivilegedUser provides a list of privileged users and their role assignments.
if ($RequiredServicePlan) {
# If the tenant has the premium license then we also include calls to PIM APIs
$PrivilegedUsers = $Tracker.TryCommand("Get-PrivilegedUser", @{"TenantHasPremiumLicense"=$true; "M365Environment"=$M365Environment})
$PrivilegedObjects = $Tracker.TryCommand("Get-PrivilegedUser", @{"TenantHasPremiumLicense"=$true; "M365Environment"=$M365Environment})
}
else{
$PrivilegedUsers = $Tracker.TryCommand("Get-PrivilegedUser", @{"TenantHasPremiumLicense"=$false; "M365Environment"=$M365Environment})
else {
$PrivilegedObjects = $Tracker.TryCommand("Get-PrivilegedUser", @{"TenantHasPremiumLicense"=$false; "M365Environment"=$M365Environment})
}

# # Split the objects into users and service principals
$PrivilegedUsers = @{}
$PrivilegedServicePrincipals = @{}

if ($PrivilegedObjects.Count -gt 0 -and $null -ne $PrivilegedObjects[0].Keys) {

#PrivilegedObjects is an array because of the tracker.trycommand, and so the first index is the hashtable
foreach ($key in $PrivilegedObjects[0].Keys) {

# Check if it has ServicePrincipalId property instead of AppId
if ($null -ne $PrivilegedObjects[0][$key].ServicePrincipalId) {
$PrivilegedServicePrincipals[$key] = $PrivilegedObjects[0][$key]
}
else {
$PrivilegedUsers[$key] = $PrivilegedObjects[0][$key]
}
}
}
# The Converto-Json call below doesn't need to have the input wrapped in an
# array (e.g, "ConvertTo-Json (@PrivilegedUsers)") because $PrivilegedUsers is
# a dictionary, not an array, and ConvertTo-Json doesn't mess up dictionaries like it does arrays
$PrivilegedUsers = $PrivilegedUsers | ConvertTo-Json
$PrivilegedUsers = ConvertTo-Json $PrivilegedUsers
$PrivilegedServicePrincipals = ConvertTo-Json $PrivilegedServicePrincipals

# While ConvertTo-Json won't mess up a dict as described in the above comment,
# on error, $TryCommand returns an empty list, not a dictionary.
$PrivilegedUsers = if ($null -eq $PrivilegedUsers) {"{}"} else {$PrivilegedUsers}

$PrivilegedServicePrincipals = if ($null -eq $PrivilegedServicePrincipals) {"{}"} else {$PrivilegedServicePrincipals}

# Get-PrivilegedRole provides a list of security configurations for each privileged role and information about Active user assignments
if ($RequiredServicePlan){
# If the tenant has the premium license then we also include calls to PIM APIs
Expand Down Expand Up @@ -208,6 +226,7 @@ function Export-AADProvider {
"cap_table_data": $CapTableData,
"authorization_policies": $AuthZPolicies,
"privileged_users": $PrivilegedUsers,
"privileged_service_principals": $PrivilegedServicePrincipals,
"privileged_roles": $PrivilegedRoles,
"service_plans": $ServicePlans,
"directory_settings": $DirectorySettings,
Expand Down Expand Up @@ -292,12 +311,15 @@ function Get-PrivilegedUser {
foreach ($User in $UsersAssignedRole) {
$Objecttype = $User.AdditionalProperties."@odata.type" -replace "#microsoft.graph."

if ($Objecttype -eq "user") {
LoadObjectDataIntoPrivilegedUserHashtable -RoleName $Role.DisplayName -PrivilegedUsers $PrivilegedUsers -ObjectId $User.Id -TenantHasPremiumLicense $TenantHasPremiumLicense -M365Environment $M365Environment -Objecttype "user"
}
elseif ($Objecttype -eq "group") {
# In this context $User.Id is a group identifier
$GroupId = $User.Id
if ($Objecttype -eq "user") {
LoadObjectDataIntoPrivilegedUserHashtable -RoleName $Role.DisplayName -PrivilegedUsers $PrivilegedUsers -ObjectId $User.Id -TenantHasPremiumLicense $TenantHasPremiumLicense -M365Environment $M365Environment -Objecttype "user"
}
elseif ($Objecttype -eq "servicePrincipal") {
LoadObjectDataIntoPrivilegedUserHashtable -RoleName $Role.DisplayName -PrivilegedUsers $PrivilegedUsers -ObjectId $User.Id -TenantHasPremiumLicense $TenantHasPremiumLicense -M365Environment $M365Environment -Objecttype "serviceprincipal"
}
elseif ($Objecttype -eq "group") {
# In this context $User.Id is a group identifier
$GroupId = $User.Id

# Process all of the group members that are transitively assigned to the current role as Active via group membership
LoadObjectDataIntoPrivilegedUserHashtable -RoleName $Role.DisplayName -PrivilegedUsers $PrivilegedUsers -ObjectId $GroupId -TenantHasPremiumLicense $TenantHasPremiumLicense -M365Environment $M365Environment -Objecttype "group"
Expand Down Expand Up @@ -408,6 +430,23 @@ function LoadObjectDataIntoPrivilegedUserHashtable {
}
}

elseif ($Objecttype -eq "serviceprincipal") {

# In this section we need to add the service principal information to the "service principal" hashtable
if (-Not $PrivilegedUsers.ContainsKey($ObjectId)) {
$AADServicePrincipal = Get-MgBetaServicePrincipal -ServicePrincipalId $ObjectId -ErrorAction Stop
$PrivilegedUsers[$ObjectId] = @{
"DisplayName" = $AADServicePrincipal.DisplayName
"ServicePrincipalId" = $AADServicePrincipal.Id
"AppId" = $AADServicePrincipal.AppId
"roles" = @()
}
}
if ($PrivilegedUsers[$ObjectId].roles -notcontains $RoleName) {
$PrivilegedUsers[$ObjectId].roles += $RoleName
}
}

elseif ($Objecttype -eq "group") {
# In this context $ObjectId is a group identifier so we need to iterate the group members
$GroupId = $ObjectId
Expand All @@ -428,6 +467,22 @@ function LoadObjectDataIntoPrivilegedUserHashtable {
$PrivilegedUsers[$GroupMember.Id].roles += $RoleName
}
}
elseif ($Membertype -eq "serviceprincipal") {

# In this section we need to add the service principal information to the "service principal" hashtable
if (-Not $PrivilegedUsers.ContainsKey($GroupMember.Id)) {
$AADServicePrincipal = Get-MgBetaServicePrincipal -ServicePrincipalId $GroupMember.Id -ErrorAction Stop
$PrivilegedUsers[$GroupMember.Id] = @{
"DisplayName" = $AADServicePrincipal.DisplayName
"ServicePrincipalId" = $AADServicePrincipal.Id
"AppId" = $AADServicePrincipal.AppId
"roles" = @()
}
}
if ($PrivilegedUsers[$GroupMember.Id].roles -notcontains $RoleName) {
$PrivilegedUsers[$GroupMember.Id].roles += $RoleName
}
}
}

# Since this is a group, we need to also process assignments in PIM in case it is in PIM for Groups
Expand All @@ -454,7 +509,6 @@ function LoadObjectDataIntoPrivilegedUserHashtable {
}

}

function AddRuleSource{
<#
.NOTES
Expand Down
5 changes: 5 additions & 0 deletions PowerShell/ScubaGear/RequiredVersions.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -69,5 +69,10 @@ $ModuleList = @(
ModuleName = 'powershell-yaml'
ModuleVersion = [version] '0.4.2'
MaximumVersion = [version] '0.99.99999'
},
@{
ModuleName = 'Microsoft.Graph.Beta.Applications'
ModuleVersion = [version] '2.0.0'
MaximumVersion = [version] '2.99.99999'
}
)

0 comments on commit 34b55f1

Please sign in to comment.