add: App Authentication test
This commit is contained in:
43
source/Classes/CISAuthenticationParameters.ps1
Normal file
43
source/Classes/CISAuthenticationParameters.ps1
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
class CISAuthenticationParameters {
|
||||||
|
[string]$ClientCertThumbPrint
|
||||||
|
[string]$ClientId
|
||||||
|
[string]$TenantId
|
||||||
|
[string]$OnMicrosoftUrl
|
||||||
|
[string]$SpAdminUrl
|
||||||
|
|
||||||
|
# Constructor with validation
|
||||||
|
CISAuthenticationParameters(
|
||||||
|
[string]$ClientCertThumbPrint,
|
||||||
|
[string]$ClientId,
|
||||||
|
[string]$TenantId,
|
||||||
|
[string]$OnMicrosoftUrl,
|
||||||
|
[string]$SpAdminUrl
|
||||||
|
) {
|
||||||
|
# Validate ClientCertThumbPrint
|
||||||
|
if (-not $ClientCertThumbPrint -or $ClientCertThumbPrint.Length -ne 40 -or $ClientCertThumbPrint -notmatch '^[0-9a-fA-F]{40}$') {
|
||||||
|
throw [ArgumentException]::new("ClientCertThumbPrint must be a 40-character hexadecimal string.")
|
||||||
|
}
|
||||||
|
# Validate ClientId
|
||||||
|
if (-not $ClientId -or $ClientId -notmatch '^[0-9a-fA-F\-]{36}$') {
|
||||||
|
throw [ArgumentException]::new("ClientId must be a valid GUID in the format 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'.")
|
||||||
|
}
|
||||||
|
# Validate TenantId
|
||||||
|
if (-not $TenantId -or $TenantId -notmatch '^[0-9a-fA-F\-]{36}$') {
|
||||||
|
throw [ArgumentException]::new("TenantId must be a valid GUID in the format 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'.")
|
||||||
|
}
|
||||||
|
# Validate OnMicrosoftUrl
|
||||||
|
if (-not $OnMicrosoftUrl -or $OnMicrosoftUrl -notmatch '^[a-zA-Z0-9]+\.onmicrosoft\.com$') {
|
||||||
|
throw [ArgumentException]::new("OnMicrosoftUrl must be in the format 'example.onmicrosoft.com'.")
|
||||||
|
}
|
||||||
|
# Validate SpAdminUrl
|
||||||
|
if (-not $SpAdminUrl -or $SpAdminUrl -notmatch '^https:\/\/[a-zA-Z0-9\-]+\-admin\.sharepoint\.com$') {
|
||||||
|
throw [ArgumentException]::new("SpAdminUrl must be in the format 'https://[name]-admin.sharepoint.com'.")
|
||||||
|
}
|
||||||
|
# Assign validated properties
|
||||||
|
$this.ClientCertThumbPrint = $ClientCertThumbPrint
|
||||||
|
$this.ClientId = $ClientId
|
||||||
|
$this.TenantId = $TenantId
|
||||||
|
$this.OnMicrosoftUrl = $OnMicrosoftUrl
|
||||||
|
$this.SpAdminUrl = $SpAdminUrl
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,13 +2,21 @@ function Connect-M365Suite {
|
|||||||
[OutputType([void])]
|
[OutputType([void])]
|
||||||
[CmdletBinding()]
|
[CmdletBinding()]
|
||||||
param (
|
param (
|
||||||
[Parameter(Mandatory = $false)]
|
[Parameter(
|
||||||
|
Mandatory = $false
|
||||||
|
)]
|
||||||
[string]$TenantAdminUrl,
|
[string]$TenantAdminUrl,
|
||||||
|
[Parameter(
|
||||||
[Parameter(Mandatory)]
|
Mandatory = $false
|
||||||
|
)]
|
||||||
|
[CISAuthenticationParameters]$AuthParams, # Custom authentication parameters
|
||||||
|
[Parameter(
|
||||||
|
Mandatory
|
||||||
|
)]
|
||||||
[string[]]$RequiredConnections,
|
[string[]]$RequiredConnections,
|
||||||
|
[Parameter(
|
||||||
[Parameter(Mandatory = $false)]
|
Mandatory = $false
|
||||||
|
)]
|
||||||
[switch]$SkipConfirmation
|
[switch]$SkipConfirmation
|
||||||
)
|
)
|
||||||
if (!$SkipConfirmation) {
|
if (!$SkipConfirmation) {
|
||||||
@@ -19,25 +27,17 @@ function Connect-M365Suite {
|
|||||||
}
|
}
|
||||||
$tenantInfo = @()
|
$tenantInfo = @()
|
||||||
$connectedServices = @()
|
$connectedServices = @()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if ($RequiredConnections -contains "AzureAD" -or $RequiredConnections -contains "AzureAD | EXO" -or $RequiredConnections -contains "AzureAD | EXO | Microsoft Graph") {
|
|
||||||
Write-Verbose "Connecting to Azure Active Directory..."
|
|
||||||
Connect-AzureAD -WarningAction SilentlyContinue | Out-Null
|
|
||||||
$tenantDetails = Get-AzureADTenantDetail -WarningAction SilentlyContinue
|
|
||||||
$tenantInfo += [PSCustomObject]@{
|
|
||||||
Service = "Azure Active Directory"
|
|
||||||
TenantName = $tenantDetails.DisplayName
|
|
||||||
TenantID = $tenantDetails.ObjectId
|
|
||||||
}
|
|
||||||
$connectedServices += "AzureAD"
|
|
||||||
Write-Verbose "Successfully connected to Azure Active Directory."
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($RequiredConnections -contains "Microsoft Graph" -or $RequiredConnections -contains "EXO | Microsoft Graph") {
|
if ($RequiredConnections -contains "Microsoft Graph" -or $RequiredConnections -contains "EXO | Microsoft Graph") {
|
||||||
Write-Verbose "Connecting to Microsoft Graph with scopes: Directory.Read.All, Domain.Read.All, Policy.Read.All, Organization.Read.All"
|
Write-Verbose "Connecting to Microsoft Graph"
|
||||||
try {
|
if ($AuthParams) {
|
||||||
|
# Use application-based authentication
|
||||||
|
Connect-MgGraph -CertificateThumbprint $AuthParams.ClientCertThumbPrint -AppId $AuthParams.ClientId -TenantId $AuthParams.TenantId -NoWelcome | Out-Null
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
# Use interactive authentication with scopes
|
||||||
Connect-MgGraph -Scopes "Directory.Read.All", "Domain.Read.All", "Policy.Read.All", "Organization.Read.All" -NoWelcome | Out-Null
|
Connect-MgGraph -Scopes "Directory.Read.All", "Domain.Read.All", "Policy.Read.All", "Organization.Read.All" -NoWelcome | Out-Null
|
||||||
|
}
|
||||||
$graphOrgDetails = Get-MgOrganization
|
$graphOrgDetails = Get-MgOrganization
|
||||||
$tenantInfo += [PSCustomObject]@{
|
$tenantInfo += [PSCustomObject]@{
|
||||||
Service = "Microsoft Graph"
|
Service = "Microsoft Graph"
|
||||||
@@ -45,25 +45,18 @@ function Connect-M365Suite {
|
|||||||
TenantID = $graphOrgDetails.Id
|
TenantID = $graphOrgDetails.Id
|
||||||
}
|
}
|
||||||
$connectedServices += "Microsoft Graph"
|
$connectedServices += "Microsoft Graph"
|
||||||
Write-Verbose "Successfully connected to Microsoft Graph with specified scopes."
|
Write-Verbose "Successfully connected to Microsoft Graph.`n"
|
||||||
}
|
}
|
||||||
catch {
|
|
||||||
Write-Verbose "Failed to connect to MgGraph, attempting device auth."
|
|
||||||
Connect-MgGraph -Scopes "Directory.Read.All", "Domain.Read.All", "Policy.Read.All", "Organization.Read.All" -UseDeviceCode -NoWelcome | Out-Null
|
|
||||||
$graphOrgDetails = Get-MgOrganization
|
|
||||||
$tenantInfo += [PSCustomObject]@{
|
|
||||||
Service = "Microsoft Graph"
|
|
||||||
TenantName = $graphOrgDetails.DisplayName
|
|
||||||
TenantID = $graphOrgDetails.Id
|
|
||||||
}
|
|
||||||
$connectedServices += "Microsoft Graph"
|
|
||||||
Write-Verbose "Successfully connected to Microsoft Graph with specified scopes."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($RequiredConnections -contains "EXO" -or $RequiredConnections -contains "AzureAD | EXO" -or $RequiredConnections -contains "Microsoft Teams | EXO" -or $RequiredConnections -contains "EXO | Microsoft Graph") {
|
if ($RequiredConnections -contains "EXO" -or $RequiredConnections -contains "AzureAD | EXO" -or $RequiredConnections -contains "Microsoft Teams | EXO" -or $RequiredConnections -contains "EXO | Microsoft Graph") {
|
||||||
Write-Verbose "Connecting to Exchange Online..."
|
Write-Verbose "Connecting to Exchange Online..."
|
||||||
|
if ($AuthParams) {
|
||||||
|
# Use application-based authentication
|
||||||
|
Connect-ExchangeOnline -AppId $AuthParams.ClientId -CertificateThumbprint $AuthParams.ClientCertThumbPrint -Organization $AuthParams.OnMicrosoftUrl -ShowBanner:$false | Out-Null
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
# Use interactive authentication
|
||||||
Connect-ExchangeOnline -ShowBanner:$false | Out-Null
|
Connect-ExchangeOnline -ShowBanner:$false | Out-Null
|
||||||
|
}
|
||||||
$exoTenant = (Get-OrganizationConfig).Identity
|
$exoTenant = (Get-OrganizationConfig).Identity
|
||||||
$tenantInfo += [PSCustomObject]@{
|
$tenantInfo += [PSCustomObject]@{
|
||||||
Service = "Exchange Online"
|
Service = "Exchange Online"
|
||||||
@@ -71,25 +64,44 @@ function Connect-M365Suite {
|
|||||||
TenantID = "N/A"
|
TenantID = "N/A"
|
||||||
}
|
}
|
||||||
$connectedServices += "EXO"
|
$connectedServices += "EXO"
|
||||||
Write-Verbose "Successfully connected to Exchange Online."
|
Write-Verbose "Successfully connected to Exchange Online.`n"
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($RequiredConnections -contains "SPO") {
|
if ($RequiredConnections -contains "SPO") {
|
||||||
Write-Verbose "Connecting to SharePoint Online..."
|
Write-Verbose "Connecting to SharePoint Online..."
|
||||||
|
if ($AuthParams) {
|
||||||
|
# Use application-based authentication
|
||||||
|
Connect-PnPOnline -Url $AuthParams.SpAdminUrl -ClientId $AuthParams.ClientId -Tenant $AuthParams.OnMicrosoftUrl -Thumbprint $AuthParams.ClientCertThumbPrint | Out-Null
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
# Use interactive authentication
|
||||||
Connect-SPOService -Url $TenantAdminUrl | Out-Null
|
Connect-SPOService -Url $TenantAdminUrl | Out-Null
|
||||||
|
}
|
||||||
|
# Assuming that Get-SPOCrossTenantHostUrl and Get-UrlLine are valid commands in your context
|
||||||
|
if ($AuthParams) {
|
||||||
|
$spoContext = Get-PnPSite
|
||||||
|
$tenantName = $spoContext.Url
|
||||||
|
}
|
||||||
|
else {
|
||||||
$spoContext = Get-SPOCrossTenantHostUrl
|
$spoContext = Get-SPOCrossTenantHostUrl
|
||||||
$tenantName = Get-UrlLine -Output $spoContext
|
$tenantName = Get-UrlLine -Output $spoContext
|
||||||
|
}
|
||||||
$tenantInfo += [PSCustomObject]@{
|
$tenantInfo += [PSCustomObject]@{
|
||||||
Service = "SharePoint Online"
|
Service = "SharePoint Online"
|
||||||
TenantName = $tenantName
|
TenantName = $tenantName
|
||||||
}
|
}
|
||||||
$connectedServices += "SPO"
|
$connectedServices += "SPO"
|
||||||
Write-Verbose "Successfully connected to SharePoint Online."
|
Write-Verbose "Successfully connected to SharePoint Online.`n"
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($RequiredConnections -contains "Microsoft Teams" -or $RequiredConnections -contains "Microsoft Teams | EXO") {
|
if ($RequiredConnections -contains "Microsoft Teams" -or $RequiredConnections -contains "Microsoft Teams | EXO") {
|
||||||
Write-Verbose "Connecting to Microsoft Teams..."
|
Write-Verbose "Connecting to Microsoft Teams..."
|
||||||
|
if ($AuthParams) {
|
||||||
|
# Use application-based authentication
|
||||||
|
Connect-MicrosoftTeams -TenantId $AuthParams.TenantId -CertificateThumbprint $AuthParams.ClientCertThumbPrint -ApplicationId $AuthParams.ClientId | Out-Null
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
# Use interactive authentication
|
||||||
Connect-MicrosoftTeams | Out-Null
|
Connect-MicrosoftTeams | Out-Null
|
||||||
|
}
|
||||||
$teamsTenantDetails = Get-CsTenant
|
$teamsTenantDetails = Get-CsTenant
|
||||||
$tenantInfo += [PSCustomObject]@{
|
$tenantInfo += [PSCustomObject]@{
|
||||||
Service = "Microsoft Teams"
|
Service = "Microsoft Teams"
|
||||||
@@ -97,9 +109,8 @@ function Connect-M365Suite {
|
|||||||
TenantID = $teamsTenantDetails.TenantId
|
TenantID = $teamsTenantDetails.TenantId
|
||||||
}
|
}
|
||||||
$connectedServices += "Microsoft Teams"
|
$connectedServices += "Microsoft Teams"
|
||||||
Write-Verbose "Successfully connected to Microsoft Teams."
|
Write-Verbose "Successfully connected to Microsoft Teams.`n"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Display tenant information and confirm with the user
|
# Display tenant information and confirm with the user
|
||||||
if (-not $SkipConfirmation) {
|
if (-not $SkipConfirmation) {
|
||||||
Write-Verbose "Connected to the following tenants:"
|
Write-Verbose "Connected to the following tenants:"
|
||||||
@@ -109,7 +120,7 @@ function Connect-M365Suite {
|
|||||||
#Write-Verbose "Tenant ID: $($tenant.TenantID)"
|
#Write-Verbose "Tenant ID: $($tenant.TenantID)"
|
||||||
}
|
}
|
||||||
$confirmation = Read-Host "Do you want to proceed with these connections? (Y/N)"
|
$confirmation = Read-Host "Do you want to proceed with these connections? (Y/N)"
|
||||||
if ($confirmation -notlike 'Y') {
|
if ($confirmation -notLike 'Y') {
|
||||||
Write-Verbose "Connection setup aborted by user."
|
Write-Verbose "Connection setup aborted by user."
|
||||||
Disconnect-M365Suite -RequiredConnections $connectedServices
|
Disconnect-M365Suite -RequiredConnections $connectedServices
|
||||||
throw "User aborted connection setup."
|
throw "User aborted connection setup."
|
||||||
@@ -117,10 +128,9 @@ function Connect-M365Suite {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch {
|
catch {
|
||||||
|
$CatchError = $_
|
||||||
$VerbosePreference = "Continue"
|
$VerbosePreference = "Continue"
|
||||||
Write-Verbose "There was an error establishing one or more connections: $_"
|
throw $CatchError
|
||||||
throw $_
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$VerbosePreference = "Continue"
|
$VerbosePreference = "Continue"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,10 +38,16 @@ function Disconnect-M365Suite {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
if ($RequiredConnections -contains "SPO") {
|
if ($RequiredConnections -contains "SPO") {
|
||||||
|
if (($script:PnpAuth)) {
|
||||||
|
Write-Verbose "Disconnecting from PnPOnline..."
|
||||||
|
Disconnect-PnPOnline | Out-Null
|
||||||
|
}
|
||||||
|
else {
|
||||||
Write-Verbose "Disconnecting from SharePoint Online..."
|
Write-Verbose "Disconnecting from SharePoint Online..."
|
||||||
Disconnect-SPOService | Out-Null
|
Disconnect-SPOService | Out-Null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
catch {
|
catch {
|
||||||
Write-Warning "Failed to disconnect from SharePoint Online: $_"
|
Write-Warning "Failed to disconnect from SharePoint Online: $_"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ function Get-CISExoOutput {
|
|||||||
#>
|
#>
|
||||||
}
|
}
|
||||||
process {
|
process {
|
||||||
|
try {
|
||||||
Write-Verbose "Get-CISExoOutput: Retuning data for Rec: $Rec"
|
Write-Verbose "Get-CISExoOutput: Retuning data for Rec: $Rec"
|
||||||
switch ($Rec) {
|
switch ($Rec) {
|
||||||
'1.2.2' {
|
'1.2.2' {
|
||||||
@@ -479,6 +480,10 @@ function Get-CISExoOutput {
|
|||||||
default { throw "No match found for test: $Rec" }
|
default { throw "No match found for test: $Rec" }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch {
|
||||||
|
throw "Get-CISExoOutput: `n$_"
|
||||||
|
}
|
||||||
|
}
|
||||||
end {
|
end {
|
||||||
Write-Verbose "Retuning data for Rec: $Rec"
|
Write-Verbose "Retuning data for Rec: $Rec"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ function Get-CISMSTeamsOutput {
|
|||||||
#>
|
#>
|
||||||
}
|
}
|
||||||
process {
|
process {
|
||||||
|
try {
|
||||||
Write-Verbose "Get-CISMSTeamsOutput: Retuning data for Rec: $Rec"
|
Write-Verbose "Get-CISMSTeamsOutput: Retuning data for Rec: $Rec"
|
||||||
switch ($Rec) {
|
switch ($Rec) {
|
||||||
'8.1.1' {
|
'8.1.1' {
|
||||||
@@ -326,6 +327,10 @@ function Get-CISMSTeamsOutput {
|
|||||||
default { throw "No match found for test: $Rec" }
|
default { throw "No match found for test: $Rec" }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch {
|
||||||
|
throw "Get-CISMSTeamsOutput: `n$_"
|
||||||
|
}
|
||||||
|
}
|
||||||
end {
|
end {
|
||||||
Write-Verbose "Retuning data for Rec: $Rec"
|
Write-Verbose "Retuning data for Rec: $Rec"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ function Get-CISMgOutput {
|
|||||||
#>
|
#>
|
||||||
}
|
}
|
||||||
process {
|
process {
|
||||||
|
try {
|
||||||
Write-Verbose "Get-CISMgOutput: Retuning data for Rec: $Rec"
|
Write-Verbose "Get-CISMgOutput: Retuning data for Rec: $Rec"
|
||||||
switch ($rec) {
|
switch ($rec) {
|
||||||
'1.1.1' {
|
'1.1.1' {
|
||||||
@@ -59,6 +60,11 @@ function Get-CISMgOutput {
|
|||||||
$allGroups = Get-MgGroup -All | Where-Object { $_.Visibility -eq "Public" } | Select-Object DisplayName, Visibility
|
$allGroups = Get-MgGroup -All | Where-Object { $_.Visibility -eq "Public" } | Select-Object DisplayName, Visibility
|
||||||
return $allGroups
|
return $allGroups
|
||||||
}
|
}
|
||||||
|
'1.2.2' {
|
||||||
|
# Test-BlockSharedMailboxSignIn.ps1
|
||||||
|
$users = Get-MgUser
|
||||||
|
return $users
|
||||||
|
}
|
||||||
'1.3.1' {
|
'1.3.1' {
|
||||||
# Test-PasswordNeverExpirePolicy.ps1
|
# Test-PasswordNeverExpirePolicy.ps1
|
||||||
$domains = if ($DomainName) {
|
$domains = if ($DomainName) {
|
||||||
@@ -83,11 +89,11 @@ function Get-CISMgOutput {
|
|||||||
}
|
}
|
||||||
'6.1.2' {
|
'6.1.2' {
|
||||||
# Test-MailboxAuditingE3
|
# Test-MailboxAuditingE3
|
||||||
$tenantSkus = Get-MgSubscribedSku -All
|
$tenantSKUs = Get-MgSubscribedSku -All
|
||||||
$e3SkuPartNumber = "SPE_E3"
|
$e3SkuPartNumber = "SPE_E3"
|
||||||
$founde3Sku = $tenantSkus | Where-Object { $_.SkuPartNumber -eq $e3SkuPartNumber }
|
$foundE3Sku = $tenantSKUs | Where-Object { $_.SkuPartNumber -eq $e3SkuPartNumber }
|
||||||
if ($founde3Sku.Count -ne 0) {
|
if ($foundE3Sku.Count -ne 0) {
|
||||||
$allE3Users = Get-MgUser -Filter "assignedLicenses/any(x:x/skuId eq $($founde3Sku.SkuId) )" -All
|
$allE3Users = Get-MgUser -Filter "assignedLicenses/any(x:x/skuId eq $($foundE3Sku.SkuId) )" -All
|
||||||
return $allE3Users
|
return $allE3Users
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -96,11 +102,11 @@ function Get-CISMgOutput {
|
|||||||
}
|
}
|
||||||
'6.1.3' {
|
'6.1.3' {
|
||||||
# Test-MailboxAuditingE5
|
# Test-MailboxAuditingE5
|
||||||
$tenantSkus = Get-MgSubscribedSku -All
|
$tenantSKUs = Get-MgSubscribedSku -All
|
||||||
$e5SkuPartNumber = "SPE_E5"
|
$e5SkuPartNumber = "SPE_E5"
|
||||||
$founde5Sku = $tenantSkus | Where-Object { $_.SkuPartNumber -eq $e5SkuPartNumber }
|
$foundE5Sku = $tenantSKUs | Where-Object { $_.SkuPartNumber -eq $e5SkuPartNumber }
|
||||||
if ($founde5Sku.Count -ne 0) {
|
if ($foundE5Sku.Count -ne 0) {
|
||||||
$allE5Users = Get-MgUser -Filter "assignedLicenses/any(x:x/skuId eq $($founde5Sku.SkuId) )" -All
|
$allE5Users = Get-MgUser -Filter "assignedLicenses/any(x:x/skuId eq $($foundE5Sku.SkuId) )" -All
|
||||||
return $allE5Users
|
return $allE5Users
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -110,6 +116,10 @@ function Get-CISMgOutput {
|
|||||||
default { throw "No match found for test: $Rec" }
|
default { throw "No match found for test: $Rec" }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch {
|
||||||
|
throw "Get-CISMgOutput: `n$_"
|
||||||
|
}
|
||||||
|
}
|
||||||
end {
|
end {
|
||||||
Write-Verbose "Retuning data for Rec: $Rec"
|
Write-Verbose "Retuning data for Rec: $Rec"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,3 @@
|
|||||||
<#
|
|
||||||
.SYNOPSIS
|
|
||||||
This is a sample Private function only visible within the module.
|
|
||||||
.DESCRIPTION
|
|
||||||
This sample function is not exported to the module and only return the data passed as parameter.
|
|
||||||
.EXAMPLE
|
|
||||||
$null = Get-CISSpoOutput -PrivateData 'NOTHING TO SEE HERE'
|
|
||||||
.PARAMETER PrivateData
|
|
||||||
The PrivateData parameter is what will be returned without transformation.
|
|
||||||
#>
|
|
||||||
function Get-CISSpoOutput {
|
function Get-CISSpoOutput {
|
||||||
[cmdletBinding()]
|
[cmdletBinding()]
|
||||||
param(
|
param(
|
||||||
@@ -15,186 +5,45 @@ function Get-CISSpoOutput {
|
|||||||
[String]$Rec
|
[String]$Rec
|
||||||
)
|
)
|
||||||
begin {
|
begin {
|
||||||
# Begin Block #
|
if (($script:PnpAuth)) {
|
||||||
<#
|
$UsePnP = $true
|
||||||
# Tests
|
}
|
||||||
7.2.1
|
# Determine the prefix based on the switch
|
||||||
7.2.2
|
$prefix = if ($UsePnP) { "PnP" } else { "SPO" }
|
||||||
7.2.3
|
# Define a hashtable to map the function calls
|
||||||
7.2.4
|
$commandMap = @{
|
||||||
7.2.5
|
'7.2.1' = "Get-${prefix}Tenant | Select-Object -Property LegacyAuthProtocolsEnabled"
|
||||||
7.2.6
|
'7.2.2' = "Get-${prefix}Tenant | Select-Object EnableAzureADB2BIntegration"
|
||||||
7.2.7
|
'7.2.3' = "Get-${prefix}Tenant | Select-Object SharingCapability"
|
||||||
7.2.9
|
'7.2.4' = "Get-${prefix}Tenant | Select-Object OneDriveSharingCapability"
|
||||||
7.2.10
|
'7.2.5' = "Get-${prefix}Tenant | Select-Object PreventExternalUsersFromResharing"
|
||||||
7.3.1
|
'7.2.6' = "Get-${prefix}Tenant | Select-Object SharingDomainRestrictionMode, SharingAllowedDomainList"
|
||||||
7.3.2
|
'7.2.7' = "Get-${prefix}Tenant | Select-Object DefaultSharingLinkType"
|
||||||
7.3.4
|
'7.2.9' = "Get-${prefix}Tenant | Select-Object ExternalUserExpirationRequired, ExternalUserExpireInDays"
|
||||||
|
'7.2.10' = "Get-${prefix}Tenant | Select-Object EmailAttestationRequired, EmailAttestationReAuthDays"
|
||||||
# Test number array
|
'7.3.1' = "Get-${prefix}Tenant | Select-Object DisallowInfectedFileDownload"
|
||||||
$testNumbers = @('7.2.1', '7.2.2', '7.2.3', '7.2.4', '7.2.5', '7.2.6', '7.2.7', '7.2.9', '7.2.10', '7.3.1', '7.3.2', '7.3.4')
|
'7.3.2' = "Get-${prefix}TenantSyncClientRestriction | Select-Object TenantRestrictionEnabled, AllowedDomainList"
|
||||||
#>
|
'7.3.4' = if ($prefix -eq "SPO") {"Get-${prefix}Site -Limit All | Select-Object Title, Url, DenyAddAndCustomizePages"} else {"Get-${Prefix}TenantSite | Select-Object Title, Url, DenyAddAndCustomizePages"}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
process {
|
process {
|
||||||
Write-Verbose "Retuning data for Rec: $Rec"
|
try {
|
||||||
switch ($Rec) {
|
Write-Verbose "Returning data for Rec: $Rec"
|
||||||
'7.2.1' {
|
if ($commandMap.ContainsKey($Rec)) {
|
||||||
# Test-ModernAuthSharePoint.ps1
|
$command = $commandMap[$Rec]
|
||||||
# $SPOTenant Mock Object
|
$result = Invoke-Expression $command
|
||||||
<#
|
return $result
|
||||||
$SPOTenant = [PSCustomObject]@{
|
|
||||||
LegacyAuthProtocolsEnabled = $true
|
|
||||||
}
|
}
|
||||||
#>
|
else {
|
||||||
$SPOTenant = Get-SPOTenant | Select-Object -Property LegacyAuthProtocolsEnabled
|
throw "No match found for test: $Rec"
|
||||||
return $SPOTenant
|
|
||||||
}
|
}
|
||||||
'7.2.2' {
|
|
||||||
# Test-SharePointAADB2B.ps1
|
|
||||||
# 7.2.2 (L1) Ensure SharePoint and OneDrive integration with Azure AD B2B is enabled
|
|
||||||
# $SPOTenantAzureADB2B Mock Object
|
|
||||||
<#
|
|
||||||
$SPOTenantAzureADB2B = [PSCustomObject]@{
|
|
||||||
EnableAzureADB2BIntegration = $false
|
|
||||||
}
|
}
|
||||||
#>
|
catch {
|
||||||
$SPOTenantAzureADB2B = Get-SPOTenant | Select-Object EnableAzureADB2BIntegration
|
throw "Get-CISSpoOutput: `n$_"
|
||||||
return $SPOTenantAzureADB2B
|
|
||||||
}
|
|
||||||
'7.2.3' {
|
|
||||||
# Test-RestrictExternalSharing.ps1
|
|
||||||
# 7.2.3 (L1) Ensure external content sharing is restricted
|
|
||||||
# Retrieve the SharingCapability setting for the SharePoint tenant
|
|
||||||
# $SPOTenantSharingCapability Mock Object
|
|
||||||
<#
|
|
||||||
$SPOTenantSharingCapability = [PSCustomObject]@{
|
|
||||||
SharingCapability = "ExternalUserAndGuestSharing"
|
|
||||||
}
|
|
||||||
#>
|
|
||||||
$SPOTenantSharingCapability = Get-SPOTenant | Select-Object SharingCapability
|
|
||||||
return $SPOTenantSharingCapability
|
|
||||||
}
|
|
||||||
'7.2.4' {
|
|
||||||
# Test-OneDriveContentRestrictions.ps1
|
|
||||||
# 7.2.4 (L2) Ensure OneDrive content sharing is restricted
|
|
||||||
# $SPOTenant Mock Object
|
|
||||||
<#
|
|
||||||
$SPOTenant = [PSCustomObject]@{
|
|
||||||
OneDriveSharingCapability = "ExternalUserAndGuestSharing"
|
|
||||||
}
|
|
||||||
#>
|
|
||||||
$SPOTenant = Get-SPOTenant | Select-Object OneDriveSharingCapability
|
|
||||||
return $SPOTenant
|
|
||||||
}
|
|
||||||
'7.2.5' {
|
|
||||||
# Test-SharePointGuestsItemSharing.ps1
|
|
||||||
# 7.2.5 (L2) Ensure that SharePoint guest users cannot share items they don't own
|
|
||||||
# $SPOTenant Mock Object
|
|
||||||
<#
|
|
||||||
$SPOTenant = [PSCustomObject]@{
|
|
||||||
PreventExternalUsersFromResharing = $false
|
|
||||||
}
|
|
||||||
#>
|
|
||||||
$SPOTenant = Get-SPOTenant | Select-Object PreventExternalUsersFromResharing
|
|
||||||
return $SPOTenant
|
|
||||||
}
|
|
||||||
'7.2.6' {
|
|
||||||
# Test-SharePointExternalSharingDomains.ps1
|
|
||||||
# 7.2.6 (L2) Ensure SharePoint external sharing is managed through domain whitelist/blacklists
|
|
||||||
# Add Authorized Domains?
|
|
||||||
# $SPOTenant Mock Object
|
|
||||||
<#
|
|
||||||
$SPOTenant = [PSCustomObject]@{
|
|
||||||
SharingDomainRestrictionMode = "AllowList"
|
|
||||||
SharingAllowedDomainList = "domain1.com", "domain2.com"
|
|
||||||
}
|
|
||||||
#>
|
|
||||||
$SPOTenant = Get-SPOTenant | Select-Object SharingDomainRestrictionMode, SharingAllowedDomainList
|
|
||||||
return $SPOTenant
|
|
||||||
}
|
|
||||||
'7.2.7' {
|
|
||||||
# Test-LinkSharingRestrictions.ps1
|
|
||||||
# Retrieve link sharing configuration for SharePoint and OneDrive
|
|
||||||
# $SPOTenantLinkSharing Mock Object
|
|
||||||
<#
|
|
||||||
$$SPOTenantLinkSharing = [PSCustomObject]@{
|
|
||||||
DefaultSharingLinkType = "Direct"
|
|
||||||
}
|
|
||||||
#>
|
|
||||||
$SPOTenantLinkSharing = Get-SPOTenant | Select-Object DefaultSharingLinkType
|
|
||||||
return $SPOTenantLinkSharing
|
|
||||||
}
|
|
||||||
'7.2.9' {
|
|
||||||
# Test-GuestAccessExpiration.ps1
|
|
||||||
# Retrieve SharePoint tenant settings related to guest access expiration
|
|
||||||
# $SPOTenantGuestAccess Mock Object
|
|
||||||
<#
|
|
||||||
$SPOTenantGuestAccess = [PSCustomObject]@{
|
|
||||||
ExternalUserExpirationRequired = "$false"
|
|
||||||
ExternalUserExpireInDays = "60"
|
|
||||||
}
|
|
||||||
#>
|
|
||||||
$SPOTenantGuestAccess = Get-SPOTenant | Select-Object ExternalUserExpirationRequired, ExternalUserExpireInDays
|
|
||||||
return $SPOTenantGuestAccess
|
|
||||||
}
|
|
||||||
'7.2.10' {
|
|
||||||
# Test-ReauthWithCode.ps1
|
|
||||||
# 7.2.10 (L1) Ensure reauthentication with verification code is restricted
|
|
||||||
# Retrieve reauthentication settings for SharePoint Online
|
|
||||||
# $SPOTenantReauthentication Mock Object
|
|
||||||
<#
|
|
||||||
$SPOTenantReauthentication = [PSCustomObject]@{
|
|
||||||
EmailAttestationRequired = "$false"
|
|
||||||
EmailAttestationReAuthDays = "30"
|
|
||||||
}
|
|
||||||
#>
|
|
||||||
$SPOTenantReauthentication = Get-SPOTenant | Select-Object EmailAttestationRequired, EmailAttestationReAuthDays
|
|
||||||
return $SPOTenantReauthentication
|
|
||||||
}
|
|
||||||
'7.3.1' {
|
|
||||||
# Test-DisallowInfectedFilesDownload.ps1
|
|
||||||
# Retrieve the SharePoint tenant configuration
|
|
||||||
# $SPOTenantDisallowInfectedFileDownload Mock Object
|
|
||||||
<#
|
|
||||||
$SPOTenantDisallowInfectedFileDownload = [PSCustomObject]@{
|
|
||||||
DisallowInfectedFileDownload = $false
|
|
||||||
}
|
|
||||||
#>
|
|
||||||
$SPOTenantDisallowInfectedFileDownload = Get-SPOTenant | Select-Object DisallowInfectedFileDownload
|
|
||||||
return $SPOTenantDisallowInfectedFileDownload
|
|
||||||
}
|
|
||||||
'7.3.2' {
|
|
||||||
# Test-OneDriveSyncRestrictions.ps1
|
|
||||||
# Retrieve OneDrive sync client restriction settings
|
|
||||||
# Add isHybrid paramter?
|
|
||||||
# $SPOTenantSyncClientRestriction Mock Object
|
|
||||||
<#
|
|
||||||
$SPOTenantSyncClientRestriction = [PSCustomObject]@{
|
|
||||||
TenantRestrictionEnabled = $true
|
|
||||||
AllowedDomainList = "786548DD-877B-4760-A749-6B1EFBC1190A", "877564FF-877B-4760-A749-6B1EFBC1190A"
|
|
||||||
}
|
|
||||||
#>
|
|
||||||
$SPOTenantSyncClientRestriction = Get-SPOTenantSyncClientRestriction | Select-Object TenantRestrictionEnabled, AllowedDomainList
|
|
||||||
return $SPOTenantSyncClientRestriction
|
|
||||||
}
|
|
||||||
'7.3.4' {
|
|
||||||
# Test-RestrictCustomScripts.ps1
|
|
||||||
# Retrieve all site collections and select necessary properties
|
|
||||||
# $SPOSitesCustomScript Mock Object
|
|
||||||
<#
|
|
||||||
$SPOSitesCustomScript = [PSCustomObject]@{
|
|
||||||
Title = "Site Collection 1"
|
|
||||||
Url = "https://contoso.sharepoint.com/sites/site1"
|
|
||||||
DenyAddAndCustomizePages = "Enabled"
|
|
||||||
}
|
|
||||||
#>
|
|
||||||
$SPOSitesCustomScript = Get-SPOSite -Limit All | Select-Object Title, Url, DenyAddAndCustomizePages
|
|
||||||
return $SPOSitesCustomScript
|
|
||||||
}
|
|
||||||
default { throw "No match found for test: $Rec" }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
end {
|
end {
|
||||||
Write-Verbose "Retuning data for Rec: $Rec"
|
Write-Verbose "Finished processing for Rec: $Rec"
|
||||||
}
|
}
|
||||||
} # end function Get-CISMSTeamsOutput
|
}
|
||||||
|
|||||||
@@ -4,21 +4,28 @@ function Get-RequiredModule {
|
|||||||
param (
|
param (
|
||||||
[Parameter(Mandatory = $true, ParameterSetName = 'AuditFunction')]
|
[Parameter(Mandatory = $true, ParameterSetName = 'AuditFunction')]
|
||||||
[switch]$AuditFunction,
|
[switch]$AuditFunction,
|
||||||
|
|
||||||
[Parameter(Mandatory = $true, ParameterSetName = 'SyncFunction')]
|
[Parameter(Mandatory = $true, ParameterSetName = 'SyncFunction')]
|
||||||
[switch]$SyncFunction
|
[switch]$SyncFunction
|
||||||
)
|
)
|
||||||
|
|
||||||
switch ($PSCmdlet.ParameterSetName) {
|
switch ($PSCmdlet.ParameterSetName) {
|
||||||
'AuditFunction' {
|
'AuditFunction' {
|
||||||
|
if (($script:PnpAuth)) {
|
||||||
|
return @(
|
||||||
|
@{ ModuleName = "ExchangeOnlineManagement"; RequiredVersion = "3.3.0"; SubModules = @() },
|
||||||
|
@{ ModuleName = "Microsoft.Graph"; RequiredVersion = "2.4.0"; SubModules = @("DeviceManagement", "Users", "Identity.DirectoryManagement", "Identity.SignIns") },
|
||||||
|
@{ ModuleName = "PnP.PowerShell"; RequiredVersion = "2.5.0"; SubModules = @() },
|
||||||
|
@{ ModuleName = "MicrosoftTeams"; RequiredVersion = "5.5.0"; SubModules = @() }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
else {
|
||||||
return @(
|
return @(
|
||||||
@{ ModuleName = "ExchangeOnlineManagement"; RequiredVersion = "3.3.0"; SubModules = @() },
|
@{ ModuleName = "ExchangeOnlineManagement"; RequiredVersion = "3.3.0"; SubModules = @() },
|
||||||
@{ ModuleName = "AzureAD"; RequiredVersion = "2.0.2.182"; SubModules = @() },
|
|
||||||
@{ ModuleName = "Microsoft.Graph"; RequiredVersion = "2.4.0"; SubModules = @("DeviceManagement", "Users", "Identity.DirectoryManagement", "Identity.SignIns") },
|
@{ ModuleName = "Microsoft.Graph"; RequiredVersion = "2.4.0"; SubModules = @("DeviceManagement", "Users", "Identity.DirectoryManagement", "Identity.SignIns") },
|
||||||
@{ ModuleName = "Microsoft.Online.SharePoint.PowerShell"; RequiredVersion = "16.0.24009.12000"; SubModules = @() },
|
@{ ModuleName = "Microsoft.Online.SharePoint.PowerShell"; RequiredVersion = "16.0.24009.12000"; SubModules = @() },
|
||||||
@{ ModuleName = "MicrosoftTeams"; RequiredVersion = "5.5.0"; SubModules = @() }
|
@{ ModuleName = "MicrosoftTeams"; RequiredVersion = "5.5.0"; SubModules = @() }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
'SyncFunction' {
|
'SyncFunction' {
|
||||||
return @(
|
return @(
|
||||||
@{ ModuleName = "ImportExcel"; RequiredVersion = "7.8.9"; SubModules = @() }
|
@{ ModuleName = "ImportExcel"; RequiredVersion = "7.8.9"; SubModules = @() }
|
||||||
|
|||||||
@@ -8,10 +8,7 @@ function Get-UniqueConnection {
|
|||||||
|
|
||||||
$uniqueConnections = @()
|
$uniqueConnections = @()
|
||||||
|
|
||||||
if ($Connections -contains "AzureAD" -or $Connections -contains "AzureAD | EXO" -or $Connections -contains "AzureAD | EXO | Microsoft Graph") {
|
if ($Connections -contains "Microsoft Graph" -or $Connections -contains "AzureAD | EXO | Microsoft Graph" -or $Connections -contains "EXO | Microsoft Graph") {
|
||||||
$uniqueConnections += "AzureAD"
|
|
||||||
}
|
|
||||||
if ($Connections -contains "Microsoft Graph" -or $Connections -contains "AzureAD | EXO | Microsoft Graph") {
|
|
||||||
$uniqueConnections += "Microsoft Graph"
|
$uniqueConnections += "Microsoft Graph"
|
||||||
}
|
}
|
||||||
if ($Connections -contains "EXO" -or $Connections -contains "AzureAD | EXO" -or $Connections -contains "Microsoft Teams | EXO" -or $Connections -contains "AzureAD | EXO | Microsoft Graph") {
|
if ($Connections -contains "EXO" -or $Connections -contains "AzureAD | EXO" -or $Connections -contains "Microsoft Teams | EXO" -or $Connections -contains "AzureAD | EXO | Microsoft Graph") {
|
||||||
|
|||||||
@@ -18,8 +18,8 @@ function Measure-AuditResult {
|
|||||||
$passPercentage = if ($totalTests -eq 0) { 0 } else { [math]::Round(($passedTests / $totalTests) * 100, 2) }
|
$passPercentage = if ($totalTests -eq 0) { 0 } else { [math]::Round(($passedTests / $totalTests) * 100, 2) }
|
||||||
|
|
||||||
# Display the pass percentage to the user
|
# Display the pass percentage to the user
|
||||||
Write-Verbose "Audit completed. $passedTests out of $totalTests tests passed."
|
Write-Information "Audit completed. $passedTests out of $totalTests tests passed."
|
||||||
Write-Verbose "Your passing percentage is $passPercentage%."
|
Write-Information "Your passing percentage is $passPercentage%."
|
||||||
|
|
||||||
# Display details of failed tests
|
# Display details of failed tests
|
||||||
if ($FailedTests.Count -gt 0) {
|
if ($FailedTests.Count -gt 0) {
|
||||||
|
|||||||
@@ -37,6 +37,8 @@
|
|||||||
If specified, the cmdlet will not check for the presence of required modules.
|
If specified, the cmdlet will not check for the presence of required modules.
|
||||||
.PARAMETER DoNotConfirmConnections
|
.PARAMETER DoNotConfirmConnections
|
||||||
If specified, the cmdlet will not prompt for confirmation before proceeding with established connections and will disconnect from all of them.
|
If specified, the cmdlet will not prompt for confirmation before proceeding with established connections and will disconnect from all of them.
|
||||||
|
.PARAMETER AuthParams
|
||||||
|
Specifies an authentication object containing parameters for application-based authentication. If provided, this will be used for connecting to services.
|
||||||
.EXAMPLE
|
.EXAMPLE
|
||||||
PS> Invoke-M365SecurityAudit
|
PS> Invoke-M365SecurityAudit
|
||||||
|
|
||||||
@@ -203,13 +205,18 @@ function Invoke-M365SecurityAudit {
|
|||||||
[Parameter(Mandatory = $false, HelpMessage = "Specifies that the cmdlet will not check for the presence of required modules.")]
|
[Parameter(Mandatory = $false, HelpMessage = "Specifies that the cmdlet will not check for the presence of required modules.")]
|
||||||
[switch]$NoModuleCheck,
|
[switch]$NoModuleCheck,
|
||||||
[Parameter(Mandatory = $false, HelpMessage = "Specifies that the cmdlet will not prompt for confirmation before proceeding with established connections and will disconnect from all of them.")]
|
[Parameter(Mandatory = $false, HelpMessage = "Specifies that the cmdlet will not prompt for confirmation before proceeding with established connections and will disconnect from all of them.")]
|
||||||
[switch]$DoNotConfirmConnections
|
[switch]$DoNotConfirmConnections,
|
||||||
|
[Parameter(Mandatory = $false, HelpMessage = "Specifies an authentication object containing parameters for application-based authentication.")]
|
||||||
|
[CISAuthenticationParameters]$AuthParams
|
||||||
)
|
)
|
||||||
Begin {
|
Begin {
|
||||||
if ($script:MaximumFunctionCount -lt 8192) {
|
if ($script:MaximumFunctionCount -lt 8192) {
|
||||||
Write-Verbose "Setting the `$script:MaximumFunctionCount to 8192 for the test run."
|
Write-Verbose "Setting the `$script:MaximumFunctionCount to 8192 for the test run."
|
||||||
$script:MaximumFunctionCount = 8192
|
$script:MaximumFunctionCount = 8192
|
||||||
}
|
}
|
||||||
|
if ($AuthParams) {
|
||||||
|
$script:PnpAuth = $true
|
||||||
|
}
|
||||||
# Ensure required modules are installed
|
# Ensure required modules are installed
|
||||||
$requiredModules = Get-RequiredModule -AuditFunction
|
$requiredModules = Get-RequiredModule -AuditFunction
|
||||||
# Format the required modules list
|
# Format the required modules list
|
||||||
@@ -267,7 +274,7 @@ function Invoke-M365SecurityAudit {
|
|||||||
$actualUniqueConnections = Get-UniqueConnection -Connections $requiredConnections
|
$actualUniqueConnections = Get-UniqueConnection -Connections $requiredConnections
|
||||||
if (!($DoNotConnect) -and $PSCmdlet.ShouldProcess("Establish connections to Microsoft 365 services: $($actualUniqueConnections -join ', ')", "Connect")) {
|
if (!($DoNotConnect) -and $PSCmdlet.ShouldProcess("Establish connections to Microsoft 365 services: $($actualUniqueConnections -join ', ')", "Connect")) {
|
||||||
Write-Information "Establishing connections to Microsoft 365 services: $($actualUniqueConnections -join ', ')"
|
Write-Information "Establishing connections to Microsoft 365 services: $($actualUniqueConnections -join ', ')"
|
||||||
Connect-M365Suite -TenantAdminUrl $TenantAdminUrl -RequiredConnections $requiredConnections -SkipConfirmation:$DoNotConfirmConnections
|
Connect-M365Suite -TenantAdminUrl $TenantAdminUrl -RequiredConnections $requiredConnections -SkipConfirmation:$DoNotConfirmConnections -AuthParams $AuthParams
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch {
|
catch {
|
||||||
|
|||||||
61
source/Public/New-CISAuthenticationParameters.ps1
Normal file
61
source/Public/New-CISAuthenticationParameters.ps1
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
<#
|
||||||
|
.SYNOPSIS
|
||||||
|
Creates a new CISAuthenticationParameters object for Microsoft 365 authentication.
|
||||||
|
.DESCRIPTION
|
||||||
|
The New-CISAuthenticationParameters function constructs a new CISAuthenticationParameters object
|
||||||
|
containing the necessary credentials and URLs for authenticating to various Microsoft 365 services.
|
||||||
|
It validates input parameters to ensure they conform to expected formats and length requirements.
|
||||||
|
.PARAMETER ClientCertThumbPrint
|
||||||
|
The thumbprint of the client certificate used for authentication. It must be a 40-character hexadecimal string.
|
||||||
|
This certificate is used to authenticate the application in Azure AD.
|
||||||
|
.PARAMETER ClientId
|
||||||
|
The Client ID (Application ID) of the Azure AD application. It must be a valid GUID format.
|
||||||
|
.PARAMETER TenantId
|
||||||
|
The Tenant ID of the Azure AD directory. It must be a valid GUID format representing your Microsoft 365 tenant.
|
||||||
|
.PARAMETER OnMicrosoftUrl
|
||||||
|
The URL of your onmicrosoft.com domain. It should be in the format 'example.onmicrosoft.com'.
|
||||||
|
.PARAMETER SpAdminUrl
|
||||||
|
The SharePoint admin URL, which should end with '-admin.sharepoint.com'. This URL is used for connecting to SharePoint Online.
|
||||||
|
.INPUTS
|
||||||
|
None. You cannot pipe objects to this function.
|
||||||
|
.OUTPUTS
|
||||||
|
CISAuthenticationParameters
|
||||||
|
The function returns an instance of the CISAuthenticationParameters class containing the authentication details.
|
||||||
|
.EXAMPLE
|
||||||
|
PS> $authParams = New-CISAuthenticationParameters -ClientCertThumbPrint "ABCDEF1234567890ABCDEF1234567890ABCDEF12" `
|
||||||
|
-ClientId "6aa0efb0-31c8-4215-9071-662ba6b2443c" `
|
||||||
|
-TenantId "54407279-440c-4691-90af-ed56de3ef801" `
|
||||||
|
-OnMicrosoftUrl "yourcompany.onmicrosoft.com" `
|
||||||
|
-SpAdminUrl "https://yourcompany-admin.sharepoint.com"
|
||||||
|
Creates a new CISAuthenticationParameters object with the specified credentials and URLs, validating each parameter's format and length.
|
||||||
|
#>
|
||||||
|
function New-CISAuthenticationParameters {
|
||||||
|
[CmdletBinding()]
|
||||||
|
[OutputType([CISAuthenticationParameters])]
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory = $true, HelpMessage = "The 40-character hexadecimal thumbprint of the client certificate.")]
|
||||||
|
[ValidatePattern("^[0-9a-fA-F]{40}$")] # Regex for a valid thumbprint format
|
||||||
|
[ValidateLength(40, 40)] # Enforce exact length
|
||||||
|
[string]$ClientCertThumbPrint,
|
||||||
|
[Parameter(Mandatory = $true, HelpMessage = "The Client ID (GUID format) of the Azure AD application.")]
|
||||||
|
[ValidatePattern("^[0-9a-fA-F\-]{36}$")] # Regex for a valid GUID
|
||||||
|
[string]$ClientId,
|
||||||
|
[Parameter(Mandatory = $true, HelpMessage = "The Tenant ID (GUID format) of the Azure AD directory.")]
|
||||||
|
[ValidatePattern("^[0-9a-fA-F\-]{36}$")] # Regex for a valid GUID
|
||||||
|
[string]$TenantId,
|
||||||
|
[Parameter(Mandatory = $true, HelpMessage = "The onmicrosoft.com domain URL (e.g., 'example.onmicrosoft.com').")]
|
||||||
|
[ValidatePattern("^[a-zA-Z0-9]+\.onmicrosoft\.com$")] # Regex for a valid onmicrosoft.com URL
|
||||||
|
[string]$OnMicrosoftUrl,
|
||||||
|
[Parameter(Mandatory = $true, HelpMessage = "The SharePoint admin URL ending with '-admin.sharepoint.com'.")]
|
||||||
|
[ValidatePattern("^https:\/\/[a-zA-Z0-9\-]+\-admin\.sharepoint\.com$")] # Regex for a valid SharePoint admin URL
|
||||||
|
[string]$SpAdminUrl
|
||||||
|
)
|
||||||
|
# Create and return the authentication parameters object
|
||||||
|
return [CISAuthenticationParameters]::new(
|
||||||
|
$ClientCertThumbPrint,
|
||||||
|
$ClientId,
|
||||||
|
$TenantId,
|
||||||
|
$OnMicrosoftUrl,
|
||||||
|
$SpAdminUrl
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
1,Test-AdministrativeAccountCompliance.ps1,1.1.1,Ensure Administrative accounts are separate and cloud-only,E3,L1,5.4,Restrict Administrator Privileges to Dedicated Administrator Accounts,TRUE,TRUE,TRUE,FALSE,Microsoft Graph
|
1,Test-AdministrativeAccountCompliance.ps1,1.1.1,Ensure Administrative accounts are separate and cloud-only,E3,L1,5.4,Restrict Administrator Privileges to Dedicated Administrator Accounts,TRUE,TRUE,TRUE,FALSE,Microsoft Graph
|
||||||
2,Test-GlobalAdminsCount.ps1,1.1.3,Ensure that between two and four global admins are designated,E3,L1,5.1,Establish and Maintain an Inventory of Accounts,TRUE,TRUE,TRUE,TRUE,Microsoft Graph
|
2,Test-GlobalAdminsCount.ps1,1.1.3,Ensure that between two and four global admins are designated,E3,L1,5.1,Establish and Maintain an Inventory of Accounts,TRUE,TRUE,TRUE,TRUE,Microsoft Graph
|
||||||
3,Test-ManagedApprovedPublicGroups.ps1,1.2.1,Ensure that only organizationally managed/approved public groups exist,E3,L2,3.3,Configure Data Access Control Lists,TRUE,TRUE,TRUE,TRUE,Microsoft Graph
|
3,Test-ManagedApprovedPublicGroups.ps1,1.2.1,Ensure that only organizationally managed/approved public groups exist,E3,L2,3.3,Configure Data Access Control Lists,TRUE,TRUE,TRUE,TRUE,Microsoft Graph
|
||||||
4,Test-BlockSharedMailboxSignIn.ps1,1.2.2,Ensure sign-in to shared mailboxes is blocked,E3,L1,0,Explicitly Not Mapped,FALSE,FALSE,FALSE,TRUE,AzureAD | EXO
|
4,Test-BlockSharedMailboxSignIn.ps1,1.2.2,Ensure sign-in to shared mailboxes is blocked,E3,L1,0,Explicitly Not Mapped,FALSE,FALSE,FALSE,TRUE,EXO | Microsoft Graph
|
||||||
5,Test-PasswordNeverExpirePolicy.ps1,1.3.1,Ensure the 'Password expiration policy' is set to 'Set passwords to never expire',E3,L1,5.2,Use Unique Passwords,TRUE,TRUE,TRUE,TRUE,Microsoft Graph
|
5,Test-PasswordNeverExpirePolicy.ps1,1.3.1,Ensure the 'Password expiration policy' is set to 'Set passwords to never expire',E3,L1,5.2,Use Unique Passwords,TRUE,TRUE,TRUE,TRUE,Microsoft Graph
|
||||||
6,Test-ExternalSharingCalendars.ps1,1.3.3,Ensure 'External sharing' of calendars is not available,E3,L2,4.8,Uninstall or Disable Unnecessary Services on Enterprise Assets and Software,FALSE,TRUE,TRUE,TRUE,EXO
|
6,Test-ExternalSharingCalendars.ps1,1.3.3,Ensure 'External sharing' of calendars is not available,E3,L2,4.8,Uninstall or Disable Unnecessary Services on Enterprise Assets and Software,FALSE,TRUE,TRUE,TRUE,EXO
|
||||||
7,Test-CustomerLockbox.ps1,1.3.6,Ensure the customer lockbox feature is enabled,E5,L2,0,Explicitly Not Mapped,FALSE,FALSE,FALSE,TRUE,EXO
|
7,Test-CustomerLockbox.ps1,1.3.6,Ensure the customer lockbox feature is enabled,E5,L2,0,Explicitly Not Mapped,FALSE,FALSE,FALSE,TRUE,EXO
|
||||||
|
|||||||
|
@@ -58,9 +58,9 @@ function Test-BlockSharedMailboxSignIn {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
#>
|
#>
|
||||||
$users = Get-CISAadOutput -Rec $recnum
|
$users = Get-CISMgOutput -Rec $recnum
|
||||||
# Step: Retrieve details of shared mailboxes from Azure AD (Condition B: Pass/Fail)
|
# Step: Retrieve details of shared mailboxes from Azure AD (Condition B: Pass/Fail)
|
||||||
$sharedMailboxDetails = $users | Where-Object {$_.objectid -in $objectids}
|
$sharedMailboxDetails = $users | Where-Object {$_.id -in $objectids}
|
||||||
# Step: Identify enabled mailboxes (Condition B: Pass/Fail)
|
# Step: Identify enabled mailboxes (Condition B: Pass/Fail)
|
||||||
$enabledMailboxes = $sharedMailboxDetails | Where-Object { $_.AccountEnabled } | ForEach-Object { $_.DisplayName }
|
$enabledMailboxes = $sharedMailboxDetails | Where-Object { $_.AccountEnabled } | ForEach-Object { $_.DisplayName }
|
||||||
$allBlocked = $enabledMailboxes.Count -eq 0
|
$allBlocked = $enabledMailboxes.Count -eq 0
|
||||||
|
|||||||
Reference in New Issue
Block a user