Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added SkipReason support #269

Merged
merged 13 commits into from
Jul 2, 2024
22 changes: 22 additions & 0 deletions powershell/internal/Get-MtSkippedReason.ps1
soulemike marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<#
.SYNOPSIS
Returns the description for why a test was skipped.
#>
function Get-MtSkippedReason {
param(
# The reason for skipping
[string] $SkippedBecause
)

switch($SkippedBecause){
"NotConnectedAzure" { "Not connected to Azure. See [Connecting to Azure](https://maester.dev/docs/installation#optional-modules-and-permissions)" ; break}
"NotConnectedExchange" { "Not connected to Exchange Online. See [Connecting to Exchange Online](https://maester.dev/docs/installation#optional-modules-and-permissions)"; break}
"NotDotGovDomain" { "This test is only for federal, executive branch, departments and agencies. To override use [Test-MtCisaDmarcAggregateCisa -Force](https://maester.dev/docs/commands/Test-MtCisaDmarcAggregateCisa)"; break}
"NotLicensedEntraIDP1" { "This test is for tenants that are licensed for Entra ID P1. See [Entra ID licensing](https://learn.microsoft.com/entra/fundamentals/licensing)"; break}
"NotLicensedEntraIDP2" { "This test is for tenants that are licensed for Entra ID P2. See [Entra ID licensing](https://learn.microsoft.com/entra/fundamentals/licensing)"; break}
"NotLicensedEntraIDGovernance" { "This test is for tenants that are licensed for Entra ID Governance. See [Entra ID Governance licensing](https://learn.microsoft.com/entra/fundamentals/licensing#microsoft-entra-id-governance)"; break}
"NotLicensedEntraWorkloadID" { "This test is for tenants that are licensed for Entra Workload ID. See [Entra Workload ID licensing](https://learn.microsoft.com/entra/workload-id/workload-identities-faqs)"; break}
"LicensedEntraIDPremium" { "This test is for tenants that are not licensed for any Entra ID Premium license. See [Entra ID licensing](https://learn.microsoft.com/entra/fundamentals/licensing)"; break}
default { $SkippedBecause; break}
}
}
32 changes: 28 additions & 4 deletions powershell/public/Add-MtTestResultDetail.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -54,17 +54,30 @@ Function Add-MtTestResultDetail {
# The type of graph object, this will be used to show the right deeplink to the test results report.
[ValidateSet('AuthenticationMethod', 'AuthorizationPolicy', 'ConditionalAccess', 'ConsentPolicy',
'Devices', 'DiagnosticSettings', 'Domains', 'Groups', 'IdentityProtection', 'Users', 'UserRole'
)]
)]
[string] $GraphObjectType,

# Pester test name
# Use the test name from the Pester context by default
[Parameter(Mandatory = $false)]
[string] $TestName = $____Pester.CurrentTest.ExpandedName
[string] $TestName = $____Pester.CurrentTest.ExpandedName,

[ValidateSet('NotConnectedAzure', 'NotConnectedExchange', 'NotDotGovDomain', 'NotLicensedEntraIDP1',
'NotLicensedEntraIDP2', 'NotLicensedEntraIDGovernance', 'NotLicensedEntraWorkloadID', "LicensedEntraIDPremium"
)]
[string] $SkippedBecause
)

$hasGraphResults = $GraphObjects -and $GraphObjectType

if ($SkippedBecause) {
$SkippedReason = Get-MtSkippedReason $SkippedBecause

if ([string]::IsNullOrEmpty($Result)) {
$Result = "Skipped. $SkippedReason"
}
}

if ([string]::IsNullOrEmpty($Description)) {
# Check if a markdown file exists for the cmdlet and parse the content
$cmdletPath = $MyInvocation.PSCommandPath
Expand All @@ -78,7 +91,11 @@ Function Add-MtTestResultDetail {

if (![string]::IsNullOrEmpty($Result)) {
# If a result was provided in the parameter insert it into the markdown content
$mdResult = $mdResult -replace "%TestResult%", $Result
if ($mdResult -match "%TestResult%") {
$mdResult = $mdResult -replace "%TestResult%", $Result
} else {
$mdResult = $Result
}
}

$Description = $mdDescription
Expand All @@ -94,6 +111,8 @@ Function Add-MtTestResultDetail {
$testInfo = @{
TestDescription = $Description
TestResult = $Result
TestSkipped = $SkippedBecause
SkippedReason = $SkippedReason
}

Write-MtProgress -Activity "Running tests" -Status $testName
Expand All @@ -107,4 +126,9 @@ Function Add-MtTestResultDetail {
$__MtSession.TestResultDetail[$testName] = $testInfo
}
}
}

if ($SkippedBecause) {
#This needs to be set at the end.
Set-ItResult -Skipped -Because $SkippedReason
}
}
soulemike marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ Function Test-MtCisaAntiSpamAllowList {
[OutputType([bool])]
param()

if(!(Test-MtConnection ExchangeOnline)){
Add-MtTestResultDetail -SkippedBecause NotConnectedExchange
return $null
}

$policy = Get-HostedConnectionFilterPolicy

$resultPolicy = $policy | Where-Object {`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ Function Test-MtCisaAntiSpamSafeList {
[OutputType([bool])]
param()

if(!(Test-MtConnection ExchangeOnline)){
Add-MtTestResultDetail -SkippedBecause NotConnectedExchange
return $null
}

$policy = Get-HostedConnectionFilterPolicy

$resultPolicy = $policy | Where-Object {`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ Function Test-MtCisaAutoExternalForwarding {
[OutputType([bool])]
param()

if(!(Test-MtConnection ExchangeOnline)){
Add-MtTestResultDetail -SkippedBecause NotConnectedExchange
return $null
}

$domains = Get-RemoteDomain

$forwardingDomains = $domains | Where-Object { `
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ Function Test-MtCisaCalendarSharing {
[OutputType([bool])]
param()

if(!(Test-MtConnection ExchangeOnline)){
Add-MtTestResultDetail -SkippedBecause NotConnectedExchange
return $null
}

$policies = Get-SharingPolicy

$resultPolicies = $policies | Where-Object {`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ Function Test-MtCisaContactSharing {
[OutputType([bool])]
param()

if(!(Test-MtConnection ExchangeOnline)){
Add-MtTestResultDetail -SkippedBecause NotConnectedExchange
return $null
}

$policies = Get-SharingPolicy

$resultPolicies = $policies | Where-Object {`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ Function Test-MtCisaExternalSenderWarning {
[OutputType([bool])]
param()

if(!(Test-MtConnection ExchangeOnline)){
Add-MtTestResultDetail -SkippedBecause NotConnectedExchange
return $null
}

$rules = Get-TransportRule

$resultRules = $rules | Where-Object {`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ Function Test-MtCisaMailboxAuditing {
[OutputType([bool])]
param()

if(!(Test-MtConnection ExchangeOnline)){
Add-MtTestResultDetail -SkippedBecause NotConnectedExchange
return $null
}

$config = Get-OrganizationConfig

$testResult = (-not $config.AuditDisabled)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ Function Test-MtCisaSmtpAuthentication {
[OutputType([bool])]
param()

if(!(Test-MtConnection ExchangeOnline)){
Add-MtTestResultDetail -SkippedBecause NotConnectedExchange
return $null
}

$config = Get-TransportConfig

$testResult = $config.SmtpClientAuthenticationDisabled
Expand Down
62 changes: 62 additions & 0 deletions powershell/public/Test-MtAppManagementPolicyEnabled.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
By default Microsoft Entra ID allows service principals and applications to be configured with weak credentials.

This can include

- client secrets instead of certificates
- secrets and certificates with long expiry (e.g. 10 year)

## How to fix

Using shorter expiry periods and certificates instead of secrets can help reduce the risk of credentials being compromised and used by an attacker.

The sample policy below can be used to enforce credential configurations on apps and service principals.

```powershell
Import-Module Microsoft.Graph.Identity.SignIns

$params = @{
isEnabled = $true
applicationRestrictions = @{
passwordCredentials = @(
@{
restrictionType = "passwordAddition"
maxLifetime = $null
restrictForAppsCreatedAfterDateTime = [System.DateTime]::Parse("2021-01-01T10:37:00Z")
}
@{
restrictionType = "passwordLifetime"
maxLifetime = "P365D"
restrictForAppsCreatedAfterDateTime = [System.DateTime]::Parse("2017-01-01T10:37:00Z")
}
@{
restrictionType = "symmetricKeyAddition"
maxLifetime = $null
restrictForAppsCreatedAfterDateTime = [System.DateTime]::Parse("2021-01-01T10:37:00Z")
}
@{
restrictionType = "customPasswordAddition"
maxLifetime = $null
restrictForAppsCreatedAfterDateTime = [System.DateTime]::Parse("2015-01-01T10:37:00Z")
}
@{
restrictionType = "symmetricKeyLifetime"
maxLifetime = "P365D"
restrictForAppsCreatedAfterDateTime = [System.DateTime]::Parse("2015-01-01T10:37:00Z")
}
)
keyCredentials = @(
@{
restrictionType = "asymmetricKeyLifetime"
maxLifetime = "P365D"
restrictForAppsCreatedAfterDateTime = [System.DateTime]::Parse("2015-01-01T10:37:00Z")
}
)
}
}

Update-MgPolicyDefaultAppManagementPolicy -BodyParameter $params
```

## Learn more

- [Tenant App Management Policy - Microsoft Graph Reference](https://learn.microsoft.com/graph/api/resources/tenantappmanagementpolicy?view=graph-rest-1.0)
18 changes: 16 additions & 2 deletions powershell/public/Test-MtAppManagementPolicyEnabled.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,22 @@ Function Test-MtAppManagementPolicyEnabled {
[OutputType([bool])]
param()

$result = Invoke-MtGraphRequest -RelativeUri "policies/defaultAppManagementPolicy"
if (!(Get-MtLicenseInformation EntraWorkloadID)) {
Add-MtTestResultDetail -SkippedBecause NotLicensedEntraWorkloadID
return $null
}

$defaultAppManagementPolicy = Invoke-MtGraphRequest -RelativeUri "policies/defaultAppManagementPolicy"
Write-Verbose -Message "Default App Management Policy: $($result.isEnabled)"
return $result.isEnabled -eq 'True'
$result = $defaultAppManagementPolicy.isEnabled -eq 'True'

if ($result) {
$resultMarkdown = "Well done. Your tenant has an app management policy enabled."
} else {
$resultMarkdown = "Your tenant does not have an app management policy defined."
}

Add-MtTestResultDetail -Result $resultMarkdown

return $result
}
5 changes: 5 additions & 0 deletions powershell/public/Test-MtCaAllAppsExists.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ Function Test-MtCaAllAppsExists {
[switch] $SkipCheckAllUsers = $false
)

if ( ( Get-MtLicenseInformation EntraID ) -eq "Free" ) {
Add-MtTestResultDetail -SkippedBecause NotLicensedEntraIDP1
return $null
}

$policies = Get-MtConditionalAccessPolicy | Where-Object { $_.state -eq "enabled" } | Where-Object { $_.grantcontrols.builtincontrols -notcontains 'passwordChange' }

$testDescription = "
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ Function Test-MtCaApplicationEnforcedRestriction {
[OutputType([bool])]
param ()

if ( ( Get-MtLicenseInformation EntraID ) -eq "Free" ) {
Add-MtTestResultDetail -SkippedBecause NotLicensedEntraIDP1
return $null
}

$policies = Get-MtConditionalAccessPolicy | Where-Object { $_.state -eq "enabled" }

$result = $false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ Function Test-MtCaBlockLegacyExchangeActiveSyncAuthentication {
[OutputType([bool])]
param ()

if ( ( Get-MtLicenseInformation EntraID ) -eq "Free" ) {
Add-MtTestResultDetail -SkippedBecause NotLicensedEntraIDP1
return $null
}

$policies = Get-MtConditionalAccessPolicy | Where-Object { $_.state -eq "enabled" }

$testDescription = "
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ Function Test-MtCaBlockLegacyOtherAuthentication {
[OutputType([bool])]
param ()

if ( ( Get-MtLicenseInformation EntraID ) -eq "Free" ) {
Add-MtTestResultDetail -SkippedBecause NotLicensedEntraIDP1
return $null
}

$policies = Get-MtConditionalAccessPolicy | Where-Object { $_.state -eq "enabled" }
# Remove policies that require password change, as they are related to user risk and not MFA on signin
$policies = $policies | Where-Object { $_.grantcontrols.builtincontrols -notcontains 'passwordChange' }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ Function Test-MtCaBlockUnknownOrUnsupportedDevicePlatform {
[OutputType([bool])]
param ()

if ( ( Get-MtLicenseInformation EntraID ) -eq "Free" ) {
Add-MtTestResultDetail -SkippedBecause NotLicensedEntraIDP1
return $null
}

$policies = Get-MtConditionalAccessPolicy | Where-Object { $_.state -eq "enabled" }

$testDescription = "
Expand Down
9 changes: 7 additions & 2 deletions powershell/public/Test-MtCaDeviceComplianceAdminsExists.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ Function Test-MtCaDeviceComplianceAdminsExists {
[OutputType([bool])]
param ()

if ( ( Get-MtLicenseInformation EntraID ) -eq "Free" ) {
Add-MtTestResultDetail -SkippedBecause NotLicensedEntraIDP1
return $null
}

$AdministrativeRolesToCheck = @(
"62e90394-69f5-4237-9190-012177145e10",
"194ae4cb-b126-40b2-bd5b-6091b380977d",
Expand Down Expand Up @@ -65,8 +70,8 @@ See [Require compliant or Microsoft Entra hybrid joined device for administrator
$PolicyIncludesAllRoles = $true
$AdministrativeRolesToCheck | ForEach-Object {
if ( ( $_ -notin $policy.conditions.users.includeRoles `
-and $policy.conditions.users.includeUsers -ne 'All' ) `
-or $_ -in $policy.conditions.users.excludeRoles `
-and $policy.conditions.users.includeUsers -ne 'All' ) `
-or $_ -in $policy.conditions.users.excludeRoles `
) {
$PolicyIncludesAllRoles = $false
}
Expand Down
5 changes: 5 additions & 0 deletions powershell/public/Test-MtCaDeviceComplianceExists.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ Function Test-MtCaDeviceComplianceExists {
[OutputType([bool])]
param ()

if ( ( Get-MtLicenseInformation EntraID ) -eq "Free" ) {
Add-MtTestResultDetail -SkippedBecause NotLicensedEntraIDP1
return $null
}

$policies = Get-MtConditionalAccessPolicy

$result = $false
Expand Down
5 changes: 5 additions & 0 deletions powershell/public/Test-MtCaEmergencyAccessExists.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ Function Test-MtCaEmergencyAccessExists {
[OutputType([bool])]
param ()

if ( ( Get-MtLicenseInformation EntraID ) -eq "Free" ) {
Add-MtTestResultDetail -SkippedBecause NotLicensedEntraIDP1
return $null
}

# Only check policies that are not related to authentication context
$policies = Get-MtConditionalAccessPolicy | Where-Object { -not $_.conditions.applications.includeAuthenticationContextClassReferences }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ Function Test-MtCaEnforceNonPersistentBrowserSession {
[switch]$AllDevices
)

if ( ( Get-MtLicenseInformation EntraID ) -eq "Free" ) {
Add-MtTestResultDetail -SkippedBecause NotLicensedEntraIDP1
return $null
}

$policies = Get-MtConditionalAccessPolicy | Where-Object { $_.state -eq "enabled" }

$testDescription = "
Expand Down
Loading
Loading