From ea3a84b2f0fbdeb20cd90425063276dcaf641fc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Blomart=20C=C3=A9dric?= Date: Thu, 30 Jun 2022 16:12:55 +0200 Subject: [PATCH 1/6] reco typo and unecessary files --- src/AADRecommendations.xml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/AADRecommendations.xml b/src/AADRecommendations.xml index e510f4e..671a4f1 100644 --- a/src/AADRecommendations.xml +++ b/src/AADRecommendations.xml @@ -203,7 +203,7 @@ Access Surface Area AR0006 Grants for high level permissions - Application can request high level permission trough fishing. Such permissions include those allowing "ReadWrite" actions or "Mail" operations. Regular reviews should be in place and non-necessary grants should be removed + Applications can request high level permission trough consent fishing. Such permissions include those allowing "ReadWrite" actions or "Mail" operations. Regular reviews should be in place and non-necessary grants should be removed Review applications having high permissions and remove unnecessary grants @@ -286,7 +286,7 @@ Entitlement Management AR0009 Assignment of Apps with "All users" group - The "All users" group contains both Members and Guests. Resource owners might misunderstand this group to contain only members. As a result, special condsideration should be takeb when using this group for application assignment or grant access tor resource such as SharePoint Content or Azure resources + The "All users" group contains both Members and Guests. Resource owners might misunderstand this group to contain only members. As a result, special condsideration should be taken when using this group for application assignment or grant access tor resource such as SharePoint Content or Azure resources Fix the entittlements by creating the right groups (e.g. "all members") @@ -2186,7 +2186,6 @@ roleDefinitions.csv - RoleAssignmentReport.csv conditionalAccessPolicies.json From acf00e9e1db0dd5eb9d39d32d7ac6dc9374892e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Blomart=20C=C3=A9dric?= Date: Fri, 15 Jul 2022 01:36:42 +0200 Subject: [PATCH 2/6] Warn on potential package issues --- src/AzureADAssessment.psd1 | 4 +- src/Complete-AADAssessmentReports.ps1 | 36 +++++++++- src/Export-AADAssessmentReportData.ps1 | 2 +- src/Get-AADAssessUserReport.ps1 | 5 ++ src/Invoke-AADAssessmentDataCollection.ps1 | 29 ++++++-- src/New-AADAssessmentRecommendations.ps1 | 4 +- src/Test-AADAssessmentPackage.ps1 | 75 +++++++++++++++++++++ src/internal/Expand-MsGraphRelationship.ps1 | 12 ++-- 8 files changed, 152 insertions(+), 15 deletions(-) create mode 100644 src/Test-AADAssessmentPackage.ps1 diff --git a/src/AzureADAssessment.psd1 b/src/AzureADAssessment.psd1 index 2f8a78d..792e598 100644 --- a/src/AzureADAssessment.psd1 +++ b/src/AzureADAssessment.psd1 @@ -56,7 +56,7 @@ RequiredModules = @( ) # Assemblies that must be loaded prior to importing this module -# RequiredAssemblies = @() +RequiredAssemblies = @("System.IO.Compression.FileSystem.dll") # Script files (.ps1) that are run in the caller's environment prior to importing this module. # ScriptsToProcess = @() @@ -123,6 +123,7 @@ NestedModules = @( '.\Import-AADAssessmentEvidence.ps1' '.\Export-AADAssessmentReportData.ps1' '.\analysis\AccessManagement\AuthenticationExperience\Test-AADAssessmentEmailOtp.ps1' + '.\Test-AADAssessmentPackage.ps1' ) # Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export. @@ -151,6 +152,7 @@ FunctionsToExport = @( 'Export-AADAssessmentRecommendations' 'Test-AADAssessmentEmailOtp' 'Export-AADAssessmentReportData' + 'Test-AADAssessmentPackage' ) # Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export. diff --git a/src/Complete-AADAssessmentReports.ps1 b/src/Complete-AADAssessmentReports.ps1 index 67e760a..935c025 100644 --- a/src/Complete-AADAssessmentReports.ps1 +++ b/src/Complete-AADAssessmentReports.ps1 @@ -64,11 +64,45 @@ function Complete-AADAssessmentReports { $OutputDirectoryData = Join-Path $OutputDirectory ([IO.Path]::GetFileNameWithoutExtension($Path)) $AssessmentDetailPath = Join-Path $OutputDirectoryData "AzureADAssessment.json" + ## Check the provided archive + $archiveState = Test-AADAssessmentPackage -Path $Path + if (!$archiveState) { + Write-Warning "The provided package is incomplete. Please review how data was collected and any related errors" + Write-Warning "If reporting has been skipped this command will generate the reports" + } + ## Expand Data Package Write-Progress -Id 0 -Activity 'Microsoft Azure AD Assessment Complete Reports' -Status 'Expand Data' -PercentComplete 0 - Expand-Archive $Path -DestinationPath $OutputDirectoryData -Force -ErrorAction Stop + #Expand-Archive $Path -DestinationPath $OutputDirectoryData -Force -ErrorAction Stop + [System.IO.Compression.ZipFile]::ExtractToDirectory($Path,$OutputDirectoryData) $AssessmentDetail = Get-Content $AssessmentDetailPath -Raw | ConvertFrom-Json + # Check assessment version + $moduleVersion = $MyInvocation.MyCommand.ScriptBlock.Module.Version + [System.Version]$packageVersion = $AssessmentDetail.AssessmentVersion + if ($packageVersion.Build -eq -1) { + Write-Warning "The package was not generate with a module installed from the PowerShell Gallery" + Write-Warning "Please install the module from the gallery to generate the package:" + Write-Warning "PS > Install-Module -Name AzureADAssessment" + } + elseif ($moduleVersion.Build -eq -1) { + Write-Warning "The Azure AD Assessment module was not installed from the PowerShell Gallery" + Write-Warning "Please install the module from the gallery to complete the assessment:" + Write-Warning "PS > Install-Module -Name AzureADAssessment" + } + elseif ($moduleVersion -ne $packageVersion) { + Write-Warning "The module version differs from the provided package and the Assessment module version used to run the complete command" + Write-Warning "Please use the same module version to generate the package and complete the assessment" + Write-Warning "" + Write-Warning "package version: $packageVersion" + Write-Warning "module version: $moduleVersion" + Write-Warning "" + Write-Warning "To install a specific version of the module:" + Write-Warning "PS > Remove-Module -Name AzureADAssessment" + Write-Warning "PS > Install-Module -Name AzureADAssessment -RequiredVersion $packageVersion" + Write-Warning "PS > Import-Module -Name AzureADAssessment -RequiredVersion $packageVersion" + } + ## Load Data Write-Progress -Id 0 -Activity ('Microsoft Azure AD Assessment Complete Reports - {0}' -f $AssessmentDetail.AssessmentTenantDomain) -Status 'Load Data' -PercentComplete 10 $OutputDirectoryAAD = Join-Path $OutputDirectoryData 'AAD-*' -Resolve -ErrorAction Stop diff --git a/src/Export-AADAssessmentReportData.ps1 b/src/Export-AADAssessmentReportData.ps1 index 487cf03..f192b4c 100644 --- a/src/Export-AADAssessmentReportData.ps1 +++ b/src/Export-AADAssessmentReportData.ps1 @@ -148,7 +148,7 @@ function Export-AADAssessmentReportData { } # generate the report - Set-Content -Path (Join-Path $OutputDirectory "users.csv") -Value 'id,userPrincipalName,displayName,userType,accountEnabled,onPremisesSyncEnabled,onPremisesImmutableId,mail,otherMails,AADLicense,lastInteractiveSignInDateTime,lastNonInteractiveSignInDateTime,isMfaRegistered,isMfaCapable,methodsRegistered' + Set-Content -Path (Join-Path $OutputDirectory "users.csv") -Value 'id,userPrincipalName,displayName,userType,accountEnabled,onPremisesSyncEnabled,onPremisesImmutableId,mail,otherMails,AADLicense,lastInteractiveSignInDateTime,lastNonInteractiveSignInDateTime,isMfaRegistered,isMfaCapable,methodsRegistered,defaultMfaMethod' Get-AADAssessUserReport -Offline -UserData $LookupCache.user -RegistrationDetailsData $LookupCache.userRegistrationDetails` | Use-Progress -Activity 'Exporting UserReport' -Property id -PassThru -WriteSummary ` | Format-Csv ` diff --git a/src/Get-AADAssessUserReport.ps1 b/src/Get-AADAssessUserReport.ps1 index f46b195..643b2e3 100644 --- a/src/Get-AADAssessUserReport.ps1 +++ b/src/Get-AADAssessUserReport.ps1 @@ -57,10 +57,14 @@ function Get-AADAssessUserReport { $isMfaCapable = $false $isMfaRegistered = $false $methodsRegistered = "" + $defaultMfaMethod = "" if ($registerationDetails) { $isMfaRegistered = $registerationDetails.isMfaRegistered $isMfaCapable = $registerationDetails.isMfaCapable $methodsRegistered = $registerationDetails.methodsRegistered -join ";" + if ($registerationDetails.defaultMfaMethod -ne "none") { + $defaultMfaMethod = $registerationDetails.defaultMfaMethod + } } else { Write-Warning "authentication method registration not found for $($InputObject.id)" } @@ -81,6 +85,7 @@ function Get-AADAssessUserReport { "isMfaRegistered" = $isMfaRegistered "isMfaCapable" = $isMfaCapable "methodsRegistered" = $methodsRegistered + "defaultMfaMethod" = $defaultMfaMethod } } } diff --git a/src/Invoke-AADAssessmentDataCollection.ps1 b/src/Invoke-AADAssessmentDataCollection.ps1 index 7382e9d..f86b4f1 100644 --- a/src/Invoke-AADAssessmentDataCollection.ps1 +++ b/src/Invoke-AADAssessmentDataCollection.ps1 @@ -64,13 +64,13 @@ function Invoke-AADAssessmentDataCollection { #$OutputDirectory = Join-Path $OutputDirectory "AzureADAssessment" $OutputDirectoryData = Join-Path $OutputDirectory "AzureADAssessmentData" $AssessmentDetailPath = Join-Path $OutputDirectoryData "AzureADAssessment.json" - $PackagePath = Join-Path $OutputDirectory "AzureADAssessmentData.zip" + $PackagePath = Join-Path $OutputDirectory "AzureADAssessmentData.aad" ### Organization Data - 0 Write-Progress -Id 0 -Activity 'Microsoft Azure AD Assessment Data Collection' -Status 'Organization Details' -PercentComplete 0 $OrganizationData = Get-MsGraphResults 'organization?$select=id,displayName,verifiedDomains,technicalNotificationMails' -ErrorAction Stop $InitialTenantDomain = $OrganizationData.verifiedDomains | Where-Object isInitial -EQ $true | Select-Object -ExpandProperty name -First 1 - $PackagePath = $PackagePath.Replace("AzureADAssessmentData.zip", "AzureADAssessmentData-$InitialTenantDomain.zip") + $PackagePath = $PackagePath.Replace("AzureADAssessmentData.aad", "AzureADAssessmentData-$InitialTenantDomain.aad") $OutputDirectoryAAD = Join-Path $OutputDirectoryData "AAD-$InitialTenantDomain" Assert-DirectoryExists $OutputDirectoryAAD @@ -322,6 +322,15 @@ function Invoke-AADAssessmentDataCollection { Remove-Item -Path (Join-Path $OutputDirectoryAAD "*") -Include "*Data.csv" -ErrorAction Ignore } + ### Check if folder is healthy + $dataFiles = @() + $dataFiles += Get-Item (Join-Path $OutputDirectoryAAD "*") -Include "*Data.xml" -ErrorAction Ignore + $dataFiles += Get-Item (Join-Path $OutputDirectoryAAD "*") -Include "*Data.csv" -ErrorAction Ignore + if ($dataFiles.Count -gt 0) { + Write-Warning "Either reporting has been turned off or there was an error during data collection or reporting" + Write-Warning "The generated package won't have the necessary information for the Assessment" + } + ### Complete Write-Progress -Id 0 -Activity ('Microsoft Azure AD Assessment Data Collection - {0}' -f $InitialTenantDomain) -Completed @@ -334,10 +343,18 @@ function Invoke-AADAssessmentDataCollection { if (!$SkipPackaging) { ### Package Output - Compress-Archive (Join-Path $OutputDirectoryData '\*') -DestinationPath $PackagePath -Force -ErrorAction Stop - - ### Clean-Up Data Files - Remove-Item $OutputDirectoryData -Recurse -Force + #Compress-Archive (Join-Path $OutputDirectoryData '\*') -DestinationPath $PackagePath -Force -ErrorAction Stop + [System.IO.Compression.ZipFile]::CreateFromDirectory($OutputDirectoryData,$PackagePath) + + if (Test-AADAssessmentPackage -Path $PackagePath) { + ### Clean-Up Data Files + Remove-Item $OutputDirectoryData -Recurse -Force + } else { + Write-Warning "The generated package is missing some data" + Write-Warning "If you are working with microsoft or a provider on the assessment please warn them" + Write-Warning "Don't hesitate to fill in a github issue mentionning the errors seen" + Write-warning "https://github.com/AzureAD/AzureADAssessment/issues/new" + } } ### Open Directory diff --git a/src/New-AADAssessmentRecommendations.ps1 b/src/New-AADAssessmentRecommendations.ps1 index ea8688d..538627b 100644 --- a/src/New-AADAssessmentRecommendations.ps1 +++ b/src/New-AADAssessmentRecommendations.ps1 @@ -27,7 +27,7 @@ function New-AADAssessmentRecommendations { [string] $InterviewSpreadsheetPath ) - #Start-AppInsightsRequest $MyInvocation.MyCommand.Name + Start-AppInsightsRequest $MyInvocation.MyCommand.Name ## Expand extracted data if (-not $SkipExpand) { @@ -185,7 +185,7 @@ function New-AADAssessmentRecommendations { Write-Error "No Tenant Data found" } - #Complete-AppInsightsRequest $MyInvocation.MyCommand.Name -Success $? + Complete-AppInsightsRequest $MyInvocation.MyCommand.Name -Success $? } function Set-TypeQnAResult($data, $recommendationDef, $recommendation){ diff --git a/src/Test-AADAssessmentPackage.ps1 b/src/Test-AADAssessmentPackage.ps1 new file mode 100644 index 0000000..00bbab0 --- /dev/null +++ b/src/Test-AADAssessmentPackage.ps1 @@ -0,0 +1,75 @@ +<# +.SYNOPSIS + Test that the provided Azure AD Assessment package has the necessary content +.DESCRIPTION + Test that the provided Azure AD Assessment package has the necessary content +.EXAMPLE + PS C:\>Test-AADAssessmentPackage 'C:\AzureADAssessmentData-contoso.onmicrosoft.com.aad' + Test that the package for contoso.onmicrosoft.com has the necesary content for the assessment. +.INPUTS + System.String +#> +function Test-AADAssessmentPackage { + [CmdletBinding()] + param + ( + # Path to the file where the exported events will be stored + [Parameter(Mandatory = $true)] + [string] $Path + ) + + if (!(Test-Path -path $Path)) { + Write-Warning "Assessment package not found" + return $false + } + + $fullPath = Convert-Path $Path + + $requiredEntries = @( + "AAD-*.onmicrosoft.com/administrativeUnits.csv", + "AAD-*.onmicrosoft.com/AppCredentialsReport.csv", + "AAD-*.onmicrosoft.com/applications.json", + "AAD-*.onmicrosoft.com/appRoleAssignments.csv", + "AAD-*.onmicrosoft.com/conditionalAccessPolicies.json", + "AAD-*.onmicrosoft.com/ConsentGrantReport.csv", + "AAD-*.onmicrosoft.com/emailOTPMethodPolicy.json", + "AAD-*.onmicrosoft.com/groups.csv", + "AAD-*.onmicrosoft.com/namedLocations.json", + "AAD-*.onmicrosoft.com/NotificationsEmailsReport.csv", + "AAD-*.onmicrosoft.com/oauth2PermissionGrants.csv", + "AAD-*.onmicrosoft.com/organization.json", + "AAD-*.onmicrosoft.com/RoleAssignmentReport.csv", + "AAD-*.onmicrosoft.com/roleDefinitions.csv", + "AAD-*.onmicrosoft.com/servicePrincipals.csv", + "AAD-*.onmicrosoft.com/servicePrincipals.json", + "AAD-*.onmicrosoft.com/subscribedSkus.json", + "AAD-*.onmicrosoft.com/userRegistrationDetails.json", + "AAD-*.onmicrosoft.com/users.csv", + "AzureADAssessment.json" + ) + + $entries = [IO.Compression.ZipFile]::OpenRead($fullPath).Entries + + $effectiveEntries = $entries | Where-Object { $_.Length -gt 0} + + if ($effectiveEntries -match "Data\.(xml|csv)$") { + Write-Warning "Assessment package contains data files which should have been removed by reporting" + } + + $validPackage = $true + foreach($requiredEntry in $requiredEntries) { + $found = $false + foreach ($effectiveEntry in $effectiveEntries) { + if (($effectiveEntry.FullName -replace "\\","/") -like $requiredEntry) { + $found = $true + } + } + if (!$found) { + Write-Warning "Required entry '$requiredEntry' not found or empty" + $validPackage = $false + } + } + + # retrun package vaility + return $validPackage +} diff --git a/src/internal/Expand-MsGraphRelationship.ps1 b/src/internal/Expand-MsGraphRelationship.ps1 index bf8cae2..c36360f 100644 --- a/src/internal/Expand-MsGraphRelationship.ps1 +++ b/src/internal/Expand-MsGraphRelationship.ps1 @@ -53,9 +53,11 @@ function Expand-MsGraphRelationship { [array] $Results = $InputObjects[0..($BatchSize - 1)] | Get-MsGraphResults $uri -DisableUniqueIdDeduplication -GroupOutputByRequest } for ($i = 0; $i -lt $InputObjects.Count; $i++) { - [array] $refValues = $Results[$i] + $refValues = @() + if ($i -lt $Results.Count) { + [array] $refValues = $Results[$i] + } if ($References) { $refValues = $refValues | Expand-ODataId | Select-Object -Property "*" -ExcludeProperty '@odata.id' } - if ($null -eq $refValues) { $refValues = @() } $InputObjects[$i] | Add-Member -Name $PropertyName -MemberType NoteProperty -Value $refValues -PassThru -ErrorAction Ignore } $InputObjects.RemoveRange(0, $BatchSize) @@ -72,9 +74,11 @@ function Expand-MsGraphRelationship { [array] $Results = $InputObjects | Get-MsGraphResults $uri -DisableUniqueIdDeduplication -GroupOutputByRequest } for ($i = 0; $i -lt $InputObjects.Count; $i++) { - [array] $refValues = $Results[$i] + $refValues = @() + if ($Results.Count -gt $i) { + [array] $refValues = $Results[$i] + } if ($References) { $refValues = $refValues | Expand-ODataId | Select-Object -Property "*" -ExcludeProperty '@odata.id' } - if ($null -eq $refValues) { $refValues = @() } $InputObjects[$i] | Add-Member -Name $PropertyName -MemberType NoteProperty -Value $refValues -PassThru -ErrorAction Ignore } } From f61a0404acfe15609b04d91de26d51639adb4441 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Blomart=20C=C3=A9dric?= Date: Fri, 15 Jul 2022 01:37:57 +0200 Subject: [PATCH 3/6] update readme on generated package --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ece89f8..82356b0 100644 --- a/README.md +++ b/README.md @@ -42,9 +42,9 @@ On each server running hybrid components, install the same module and run the In Invoke-AADAssessmentHybridDataCollection ``` -The output package will be named according to the following pattern: `AzureADAssessmentData-.zip` +The output package will be named according to the following pattern: `AzureADAssessmentData-.aad` -Once data collection is complete, provide the output packages to whoever is completing the assessment. Please avoid making any changes to the generated zip files including the name of the file. +Once data collection is complete, provide the output packages to whoever is completing the assessment. ## Complete Assessment Reports If you are generating and reviewing the output yourself, please see the Wiki for the [Assessment Guide](https://github.com/AzureAD/AzureADAssessment/wiki). From a1d6c1b43f243ca1ea1e19fc21e2e4be9832c8f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Blomart=20C=C3=A9dric?= Date: Sat, 16 Jul 2022 16:21:40 +0200 Subject: [PATCH 4/6] Always chck when gen package & furhter on complete --- src/Complete-AADAssessmentReports.ps1 | 27 +++++--- src/Invoke-AADAssessmentDataCollection.ps1 | 42 ++++++------ src/Test-AADAssessmentPackage.ps1 | 74 ++++++++++++++-------- 3 files changed, 88 insertions(+), 55 deletions(-) diff --git a/src/Complete-AADAssessmentReports.ps1 b/src/Complete-AADAssessmentReports.ps1 index 935c025..1f41eb1 100644 --- a/src/Complete-AADAssessmentReports.ps1 +++ b/src/Complete-AADAssessmentReports.ps1 @@ -64,18 +64,27 @@ function Complete-AADAssessmentReports { $OutputDirectoryData = Join-Path $OutputDirectory ([IO.Path]::GetFileNameWithoutExtension($Path)) $AssessmentDetailPath = Join-Path $OutputDirectoryData "AzureADAssessment.json" - ## Check the provided archive - $archiveState = Test-AADAssessmentPackage -Path $Path - if (!$archiveState) { - Write-Warning "The provided package is incomplete. Please review how data was collected and any related errors" - Write-Warning "If reporting has been skipped this command will generate the reports" - } - ## Expand Data Package Write-Progress -Id 0 -Activity 'Microsoft Azure AD Assessment Complete Reports' -Status 'Expand Data' -PercentComplete 0 #Expand-Archive $Path -DestinationPath $OutputDirectoryData -Force -ErrorAction Stop + # Remove destination before extract + if (Test-Path -Path $OutputDirectoryData) { + Remove-Item $OutputDirectoryData -Recurse -Force + } + # Extract content [System.IO.Compression.ZipFile]::ExtractToDirectory($Path,$OutputDirectoryData) $AssessmentDetail = Get-Content $AssessmentDetailPath -Raw | ConvertFrom-Json + #Check for DataFiles + $OutputDirectoryAAD = Join-Path $OutputDirectoryData 'AAD-*' -Resolve -ErrorAction Stop + [array] $DataFiles = Get-Item -Path (Join-Path $OutputDirectoryAAD "*") -Include "*Data.xml" + $SkippedReportOutput = $DataFiles -and $DataFiles.Count -eq 9 + + ## Check the provided archive + $archiveState = Test-AADAssessmentPackage -Path $Path -SkippedReportOutput $SkippedReportOutput + if (!$archiveState) { + Write-Warning "The provided package is incomplete. Please review how data was collected and any related errors" + Write-Warning "If reporting has been skipped this command will generate the reports" + } # Check assessment version $moduleVersion = $MyInvocation.MyCommand.ScriptBlock.Module.Version @@ -105,11 +114,9 @@ function Complete-AADAssessmentReports { ## Load Data Write-Progress -Id 0 -Activity ('Microsoft Azure AD Assessment Complete Reports - {0}' -f $AssessmentDetail.AssessmentTenantDomain) -Status 'Load Data' -PercentComplete 10 - $OutputDirectoryAAD = Join-Path $OutputDirectoryData 'AAD-*' -Resolve -ErrorAction Stop ## Generate Reports - [array] $DataFiles = Get-Item -Path (Join-Path $OutputDirectoryAAD "*") -Include "*Data.xml" - if ($DataFiles -and $DataFiles.Count -eq 9) { + if ($SkippedReportOutput) { Write-Progress -Id 0 -Activity ('Microsoft Azure AD Assessment Complete Reports - {0}' -f $AssessmentDetail.AssessmentTenantDomain) -Status 'Output Report Data' -PercentComplete 20 Export-AADAssessmentReportData -SourceDirectory $OutputDirectoryAAD -OutputDirectory $OutputDirectoryAAD diff --git a/src/Invoke-AADAssessmentDataCollection.ps1 b/src/Invoke-AADAssessmentDataCollection.ps1 index f86b4f1..fbc6164 100644 --- a/src/Invoke-AADAssessmentDataCollection.ps1 +++ b/src/Invoke-AADAssessmentDataCollection.ps1 @@ -322,15 +322,6 @@ function Invoke-AADAssessmentDataCollection { Remove-Item -Path (Join-Path $OutputDirectoryAAD "*") -Include "*Data.csv" -ErrorAction Ignore } - ### Check if folder is healthy - $dataFiles = @() - $dataFiles += Get-Item (Join-Path $OutputDirectoryAAD "*") -Include "*Data.xml" -ErrorAction Ignore - $dataFiles += Get-Item (Join-Path $OutputDirectoryAAD "*") -Include "*Data.csv" -ErrorAction Ignore - if ($dataFiles.Count -gt 0) { - Write-Warning "Either reporting has been turned off or there was an error during data collection or reporting" - Write-Warning "The generated package won't have the necessary information for the Assessment" - } - ### Complete Write-Progress -Id 0 -Activity ('Microsoft Azure AD Assessment Data Collection - {0}' -f $InitialTenantDomain) -Completed @@ -342,19 +333,14 @@ function Invoke-AADAssessmentDataCollection { } if (!$SkipPackaging) { + ### Remove pre existing package + Remove-Item $PackagePath -Force + ### Package Output #Compress-Archive (Join-Path $OutputDirectoryData '\*') -DestinationPath $PackagePath -Force -ErrorAction Stop [System.IO.Compression.ZipFile]::CreateFromDirectory($OutputDirectoryData,$PackagePath) - if (Test-AADAssessmentPackage -Path $PackagePath) { - ### Clean-Up Data Files - Remove-Item $OutputDirectoryData -Recurse -Force - } else { - Write-Warning "The generated package is missing some data" - Write-Warning "If you are working with microsoft or a provider on the assessment please warn them" - Write-Warning "Don't hesitate to fill in a github issue mentionning the errors seen" - Write-warning "https://github.com/AzureAD/AzureADAssessment/issues/new" - } + Remove-Item $OutputDirectoryData -Recurse -Force } ### Open Directory @@ -362,5 +348,23 @@ function Invoke-AADAssessmentDataCollection { } catch { if ($MyInvocation.CommandOrigin -eq 'Runspace') { Write-AppInsightsException $_.Exception }; throw } - finally { Complete-AppInsightsRequest $MyInvocation.MyCommand.Name -Success $? } + finally { + # check generated package and issue warning + $issue = $false + if (!(Test-Path -PathType Leaf -Path $PackagePath) -and !$SkipPackaging) { + Write-Warning "The export package has not been generated" + $issue = $true + } elseif (!$SkipPackaging) { + if (!(Test-AADAssessmentPackage -Path $PackagePath -SkippedReportOutput $SkipReportOutput)) { + Write-Warning "The generated package is missing some data" + $issue = $true + } + } + if ($issue) { + Write-Warning "If you are working with microsoft or a provider on the assessment please warn them" + Write-Warning "Please check GitHub issues and fill a new one or reply on existing ones mentionning the errors seen" + Write-warning "https://github.com/AzureAD/AzureADAssessment/issues" + } + Complete-AppInsightsRequest $MyInvocation.MyCommand.Name -Success $? + } } diff --git a/src/Test-AADAssessmentPackage.ps1 b/src/Test-AADAssessmentPackage.ps1 index 00bbab0..da54258 100644 --- a/src/Test-AADAssessmentPackage.ps1 +++ b/src/Test-AADAssessmentPackage.ps1 @@ -4,8 +4,8 @@ .DESCRIPTION Test that the provided Azure AD Assessment package has the necessary content .EXAMPLE - PS C:\>Test-AADAssessmentPackage 'C:\AzureADAssessmentData-contoso.onmicrosoft.com.aad' - Test that the package for contoso.onmicrosoft.com has the necesary content for the assessment. + PS C:\>Test-AADAssessmentPackage 'C:\AzureADAssessmentData-contoso.aad' + Test that the package for contoso has the necesary content for the assessment. .INPUTS System.String #> @@ -15,7 +15,10 @@ function Test-AADAssessmentPackage { ( # Path to the file where the exported events will be stored [Parameter(Mandatory = $true)] - [string] $Path + [string] $Path, + # Reports should have been generated + [Parameter(Mandatory = $false)] + [bool] $SkippedReportOutput ) if (!(Test-Path -path $Path)) { @@ -26,36 +29,55 @@ function Test-AADAssessmentPackage { $fullPath = Convert-Path $Path $requiredEntries = @( - "AAD-*.onmicrosoft.com/administrativeUnits.csv", - "AAD-*.onmicrosoft.com/AppCredentialsReport.csv", - "AAD-*.onmicrosoft.com/applications.json", - "AAD-*.onmicrosoft.com/appRoleAssignments.csv", - "AAD-*.onmicrosoft.com/conditionalAccessPolicies.json", - "AAD-*.onmicrosoft.com/ConsentGrantReport.csv", - "AAD-*.onmicrosoft.com/emailOTPMethodPolicy.json", - "AAD-*.onmicrosoft.com/groups.csv", - "AAD-*.onmicrosoft.com/namedLocations.json", - "AAD-*.onmicrosoft.com/NotificationsEmailsReport.csv", - "AAD-*.onmicrosoft.com/oauth2PermissionGrants.csv", - "AAD-*.onmicrosoft.com/organization.json", - "AAD-*.onmicrosoft.com/RoleAssignmentReport.csv", - "AAD-*.onmicrosoft.com/roleDefinitions.csv", - "AAD-*.onmicrosoft.com/servicePrincipals.csv", - "AAD-*.onmicrosoft.com/servicePrincipals.json", - "AAD-*.onmicrosoft.com/subscribedSkus.json", - "AAD-*.onmicrosoft.com/userRegistrationDetails.json", - "AAD-*.onmicrosoft.com/users.csv", + "AAD-*/administrativeUnits.csv", + "AAD-*/AppCredentialsReport.csv", + "AAD-*/applications.json", + "AAD-*/appRoleAssignments.csv", + "AAD-*/conditionalAccessPolicies.json", + "AAD-*/ConsentGrantReport.csv", + "AAD-*/emailOTPMethodPolicy.json", + "AAD-*/groups.csv", + "AAD-*/namedLocations.json", + "AAD-*/NotificationsEmailsReport.csv", + "AAD-*/oauth2PermissionGrants.csv", + "AAD-*/organization.json", + "AAD-*/RoleAssignmentReport.csv", + "AAD-*/roleDefinitions.csv", + "AAD-*/servicePrincipals.csv", + "AAD-*/servicePrincipals.json", + "AAD-*/subscribedSkus.json", + "AAD-*/userRegistrationDetails.json", + "AAD-*/users.csv", "AzureADAssessment.json" ) + if ($SkippedReportOutput) { + $requiredEntries = @( + "AAD-*/administrativeUnits.csv", + "AAD-*/applicationData.xml", + "AAD-*/appRoleAssignmentData.xml", + "AAD-*/conditionalAccessPolicies.json", + "AAD-*/directoryRoleData.xml" + "AAD-*/emailOTPMethodPolicy.json", + "AAD-*/groupData.xml", + "AAD-*/namedLocations.json", + "AAD-*/oauth2PermissionGrantData.xml", + "AAD-*/organization.json", + "AAD-*/roleAssignmentSchedulesData.xml", + "AAD-*/roleDefinitions.csv", + "AAD-*/roleEligibilitySchedulesData.xml", + "AAD-*/servicePrincipalData.xml", + "AAD-*/subscribedSkus.json", + "AAD-*/userData.xml", + "AAD-*/userRegistrationDetails.json", + "AzureADAssessment.json" + ) + } + $entries = [IO.Compression.ZipFile]::OpenRead($fullPath).Entries $effectiveEntries = $entries | Where-Object { $_.Length -gt 0} - if ($effectiveEntries -match "Data\.(xml|csv)$") { - Write-Warning "Assessment package contains data files which should have been removed by reporting" - } - $validPackage = $true foreach($requiredEntry in $requiredEntries) { $found = $false From 03fcc02236eb58d44114d6262f2778c461424daf Mon Sep 17 00:00:00 2001 From: Merill Fernando Date: Sun, 17 Jul 2022 18:38:02 +1000 Subject: [PATCH 5/6] Added check before removing to avoid error message being printed --- src/Invoke-AADAssessmentDataCollection.ps1 | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Invoke-AADAssessmentDataCollection.ps1 b/src/Invoke-AADAssessmentDataCollection.ps1 index fbc6164..cb3f986 100644 --- a/src/Invoke-AADAssessmentDataCollection.ps1 +++ b/src/Invoke-AADAssessmentDataCollection.ps1 @@ -333,8 +333,11 @@ function Invoke-AADAssessmentDataCollection { } if (!$SkipPackaging) { - ### Remove pre existing package - Remove-Item $PackagePath -Force + ### Remove pre existing package (zip) if it exists + if (Test-Path -Path $PackagePath) { + Remove-Item $PackagePath -Force + } + ### Package Output #Compress-Archive (Join-Path $OutputDirectoryData '\*') -DestinationPath $PackagePath -Force -ErrorAction Stop From 1c32b814ab6e8579223b2049582afb54802e8863 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Blomart=20C=C3=A9dric?= Date: Sun, 17 Jul 2022 11:19:20 +0200 Subject: [PATCH 6/6] Ensure administrative units extract have headers --- src/Invoke-AADAssessmentDataCollection.ps1 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Invoke-AADAssessmentDataCollection.ps1 b/src/Invoke-AADAssessmentDataCollection.ps1 index cb3f986..33f46b9 100644 --- a/src/Invoke-AADAssessmentDataCollection.ps1 +++ b/src/Invoke-AADAssessmentDataCollection.ps1 @@ -228,9 +228,10 @@ function Invoke-AADAssessmentDataCollection { $ReferencedIdCache.servicePrincipal.Clear() ### Administrative units data - 14 + Set-Content -Path (Join-Path $OutputDirectoryAAD "administrativeUnits.csv") -Value 'id,displayName,visibility' Write-Progress -Id 0 -Activity ('Microsoft Azure AD Assessment Data Collection - {0}' -f $InitialTenantDomain) -Status 'Administrative Units' -PercentComplete 65 Get-MsGraphResults 'directory/administrativeUnits' -Select 'id,displayName,visibility' ` - | Export-Csv (Join-Path $OutputDirectoryAAD "administrativeUnits.csv") + | Export-Csv (Join-Path $OutputDirectoryAAD "administrativeUnits.csv") -NoTypeInformation -Append ### Registration details data - 15 if ($licenseType -ne "Free") {