我正在尝试(如标题所示)根据合规性、azure Defender 和 Advisor 建议清理 Azure entra 中未使用的服务原则。
这是我为企业申请 ISO 合规认证的前兆。
从 Chat GPT 获得一些建议后,它给了我这个损坏的脚本......
Install-Module -Name AzureAD
Connect-AzureAD
# Export users with last sign-in date
Get-AzureADUser -All $true | ForEach-Object {
$user = $_
$lastSignIn = (Get-AzureADAuditSignInLogs -Filter "userPrincipalName eq '$($user.UserPrincipalName)'" | Sort-Object createdDateTime -Descending | Select-Object -First 1).createdDateTime
[PSCustomObject]@{
UserPrincipalName = $user.UserPrincipalName
LastSignInDateTime = $lastSignIn
}
} | Export-Csv -Path "C:\temp\InactiveUsers.csv" -NoTypeInformation
# Import the CSV file with inactive users
$inactiveUsers = Import-Csv -Path "C:\temp\InactiveUsers.csv"
# Disable users
foreach ($user in $inactiveUsers) {
if ($user.LastSignInDateTime -lt (Get-Date).AddMonths(-6)) {
Set-AzureADUser -ObjectId $user.UserPrincipalName -AccountEnabled $false
}
}
...我这里有几个问题/问题...
我在想,如果我跳过将初始集删除到文件中,我可以在自动化帐户上将其作为计划任务重新运行,这是一个好主意还是坏主意?
在我的租户中,我几乎没有企业应用程序:
要获取 3 天内不活动的服务主体,我使用了以下脚本:
# Retrieve all service principals
$servicePrincipals = Get-AzureADServicePrincipal -All:$true | ? {$_.Tags -eq "WindowsAzureActiveDirectoryIntegratedApp"}
# Define threshold for inactivity (e.g., 6 months)
$inactiveThreshold = (Get-Date).AddDays(-3)
# Array to store inactive service principals
$inactiveServicePrincipals = @()
# Check each service principal for activity
foreach ($sp in $servicePrincipals) {
# Determine if the service principal has any recent activity
$recentActivity = Get-AzureADAuditSignInLogs -Filter "appId eq '$($sp.AppId)'" | Sort-Object createdDateTime -Descending | Select-Object -First 1
if ($recentActivity -eq $null) {
# No recent activity found for the service principal
$inactiveServicePrincipals += $sp
}
}
# Output inactive service principals
$inactiveServicePrincipals | Select-Object DisplayName, AppId
名称为
Multi-tenant
的应用程序不会在响应中显示是否存在用户交互:
现在您也可以通过修改如下脚本来删除不活动的服务主体:
# Retrieve all service principals tagged as WindowsAzureActiveDirectoryIntegratedApp
$servicePrincipals = Get-AzureADServicePrincipal -All:$true | Where-Object { $_.Tags -eq "WindowsAzureActiveDirectoryIntegratedApp" }
# Define threshold for inactivity (e.g., 6 months)
$inactiveThreshold = (Get-Date).AddDays(-3) # Adjust as needed
# Array to store inactive service principals
$inactiveServicePrincipals = @()
# Check each service principal for activity
foreach ($sp in $servicePrincipals) {
# Determine if the service principal has any recent activity
$recentActivity = Get-AzureADAuditSignInLogs -Filter "appId eq '$($sp.AppId)'" | Sort-Object createdDateTime -Descending | Select-Object -First 1
if ($recentActivity -eq $null) {
# No recent activity found for the service principal
$inactiveServicePrincipals += $sp
}
}
# Output inactive service principals
$inactiveServicePrincipals | Select-Object DisplayName, AppId
# Delete inactive service principals
foreach ($inactiveSP in $inactiveServicePrincipals) {
Write-Host "Deleting $($inactiveSP.DisplayName) with AppId $($inactiveSP.AppId)..."
Remove-AzureADServicePrincipal -ObjectId $inactiveSP.ObjectId -Force
}
Write-Host "Deletion complete."
不活动的服务主体已成功删除:
如果租户有许多服务主体,那么脚本可能会抛出限制错误,因此请尝试以下代码:
# Retrieve all service principals tagged as WindowsAzureActiveDirectoryIntegratedApp
$servicePrincipals = Get-AzureADServicePrincipal -All:$true | Where-Object { $_.Tags -eq "WindowsAzureActiveDirectoryIntegratedApp" }
# Define threshold for inactivity
$inactiveThreshold = (Get-Date).AddDays(-7) # Adjust as needed
# Array to store inactive service principals
$inactiveServicePrincipals = @()
# Function to handle retry logic
function Invoke-RetryableOperation {
param (
[ScriptBlock]$Operation,
[int]$MaxRetries = 3
)
$retryCount = 0
$retryAfter = 10 # Default retry time in seconds
while ($retryCount -lt $MaxRetries) {
try {
& $Operation
return $true
} catch {
if ($_.Exception.Message.Contains("throttled")) {
Write-Host "Throttling encountered. Retrying after $retryAfter seconds..."
Start-Sleep -Seconds $retryAfter
$retryAfter = 2 * $retryAfter # Exponential backoff strategy
$retryCount++
} else {
Write-Error "Error: $($_.Exception.Message)"
return $false
}
}
}
Write-Error "Operation failed after $MaxRetries retries."
return $false
}
# Check each service principal for activity
foreach ($sp in $servicePrincipals) {
$appId = $sp.AppId
# Function to get recent activity for a service principal
function Get-RecentActivity {
$logs = Get-AzureADAuditSignInLogs -Filter "appId eq '$appId'" | Sort-Object createdDateTime -Descending
return $logs | Select-Object -First 1
}
# Attempt to get recent activity, with retry logic
$retryableOperation = {
Get-RecentActivity
}
$recentActivity = Invoke-RetryableOperation -Operation $retryableOperation
# Check if no recent activity found within threshold
if ($recentActivity -eq $null -or $recentActivity.createdDateTime -lt $inactiveThreshold) {
$inactiveServicePrincipals += $sp
}
}
# Output inactive service principals
$inactiveServicePrincipals | Select-Object DisplayName, AppId
获取服务主体需要一些时间:
在我的环境中,共有 240 个应用程序,其中 215 个应用程序在 7 天内处于非活动状态:
$inactiveServicePrincipals | Measure-Object | Select-Object -ExpandProperty Count
我不会删除服务主体,要删除,您可以添加以下脚本:
# Delete inactive service principals
foreach ($inactiveSP in $inactiveServicePrincipals) {
Write-Host "Deleting $($inactiveSP.DisplayName) with AppId $($inactiveSP.AppId)..."
Remove-AzureADServicePrincipal -ObjectId $inactiveSP.ObjectId -Force
}
Write-Host "Deletion complete."