diff --git a/.vscode/settings.json b/.vscode/settings.json index 165562eb..444a7564 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -7,6 +7,7 @@ "count", "cpu", "datafile", + "dbachecks", "dbcconfig", "djfcc", "dstrait", @@ -51,4 +52,4 @@ "cSpell.enableFiletypes": [ "powershell" ] -} +} \ No newline at end of file diff --git a/source/checks/Databasev5.Tests.ps1 b/source/checks/Databasev5.Tests.ps1 index a9c95041..bea0c23d 100644 --- a/source/checks/Databasev5.Tests.ps1 +++ b/source/checks/Databasev5.Tests.ps1 @@ -304,3 +304,18 @@ Describe "Page Verify" -Tag PageVerify, Medium, Database -ForEach $InstancesToTe } } } + +Describe "Foreign keys and check constraints not trusted" -Tag FKCKTrusted, Low, Database -ForEach $InstancesToTest { + $Skip = ($__dbcconfig | Where-Object Name -EQ 'skip.database.fkcktrusted').Value + Context "Testing Foreign Keys and Check Constraints are not trusted <_.Name>" { + + It "Database <_.Database> Foreign Key <_.Name> on table <_.Parent> should be trusted on <_.SqlInstance>" -Skip:$skip -ForEach $psitem.Databases.Where{ if ($Database) { $_.Name -in $Database } else { $psitem.ConfigValues.fkcktrustedexclude -notcontains $psitem.Name } }.ForeignKeys { + $psitem.IsChecked | Should -Be $true -Because "This can have a huge performance impact on queries. SQL Server won't use untrusted constraints to build better execution plans. It will also avoid data violation" + } + + It "Database <_.Database> Foreign Key <_.Name> on table <_.Parent> should be trusted on <_.SqlInstance>" -Skip:$skip -ForEach $psitem.Databases.Where{ if ($Database) { $_.Name -in $Database } else { $psitem.ConfigValues.fkcktrustedexclude -notcontains $psitem.Name } }.Constraints { + $psitem.IsChecked | Should -Be $true -Because "This can have a huge performance impact on queries. SQL Server won't use untrusted constraints to build better execution plans. It will also avoid data violation" + } + } +} + diff --git a/source/internal/configurations/configuration.ps1 b/source/internal/configurations/configuration.ps1 index f56e50bd..895abed2 100644 --- a/source/internal/configurations/configuration.ps1 +++ b/source/internal/configurations/configuration.ps1 @@ -18,7 +18,7 @@ $EmailValidationSb = { } Register-PSFConfigValidation -Name validation.EmailValidation -ScriptBlock $EmailValidationSb -$__dbachecksNotv5 = 'ADUser', 'BuiltInAdmin', 'EngineServiceAdmin', 'FullTextServiceAdmin', 'LocalWindowsGroup', 'PublicPermission', 'SqlBrowserServiceAccount', 'TempDbConfiguration'',CertificateExpiration', 'DatabaseExists', 'DatabaseGrowthEvent', 'DatafileAutoGrowthType', 'DisabledIndex', 'DuplicateIndex', 'FileGroupBalanced', 'FKCKTrusted', 'FutureFileGrowth', 'IdentityUsage', 'LastDiffBackup', 'LastFullBackup', 'LastGoodCheckDb', 'LastLogBackup', 'LogfilePercentUsed', 'LogfileSize', 'MaxDopDatabase', 'OrphanedUser', 'SymmetricKeyEncryptionLevel', 'TestLastBackup', 'TestLastBackupVerifyOnly', 'UnusedIndex', 'PowerPlan', 'SPN', 'DiskCapacity', 'PingComputer', 'CPUPrioritisation', 'DiskAllocationUnit', 'NonStandardPort', 'ServerProtocol', 'OlaInstalled', 'SystemFull', 'UserFull', 'UserDiff', 'UserLog', 'CommandLog', 'SystemIntegrityCheck', 'UserIntegrityCheck', 'UserIndexOptimize', 'OutputFileCleanup', 'DeleteBackupHistory', 'PurgeJobHistory', 'DomainName', 'OrganizationalUnit', 'ClusterHealth', 'LogShippingPrimary', 'LogShippingSecondary' +$__dbachecksNotv5 = 'ADUser', 'BuiltInAdmin', 'EngineServiceAdmin', 'FullTextServiceAdmin', 'LocalWindowsGroup', 'PublicPermission', 'SqlBrowserServiceAccount', 'TempDbConfiguration','CertificateExpiration', 'DatabaseExists', 'DatabaseGrowthEvent', 'DatafileAutoGrowthType', 'DisabledIndex', 'DuplicateIndex', 'FileGroupBalanced', 'FutureFileGrowth', 'IdentityUsage', 'LastDiffBackup', 'LastFullBackup', 'LastGoodCheckDb', 'LastLogBackup', 'LogfilePercentUsed', 'LogfileSize', 'MaxDopDatabase', 'OrphanedUser', 'SymmetricKeyEncryptionLevel', 'TestLastBackup', 'TestLastBackupVerifyOnly', 'UnusedIndex', 'PowerPlan', 'SPN', 'DiskCapacity', 'PingComputer', 'CPUPrioritisation', 'DiskAllocationUnit', 'NonStandardPort', 'ServerProtocol', 'OlaInstalled', 'SystemFull', 'UserFull', 'UserDiff', 'UserLog', 'CommandLog', 'SystemIntegrityCheck', 'UserIntegrityCheck', 'UserIndexOptimize', 'OutputFileCleanup', 'DeleteBackupHistory', 'PurgeJobHistory', 'DomainName', 'OrganizationalUnit', 'ClusterHealth', 'LogShippingPrimary', 'LogShippingSecondary' Set-PSFConfig -Module dbachecks -Name checks.notv5ready -Value @($__dbachecksNotv5) -Initialize -Description "Checks that have not been converted to v5 yet" @@ -254,6 +254,7 @@ Set-PSFConfig -Module dbachecks -Name policy.autoupdatestats.excludedb -Value @( Set-PSFConfig -Module dbachecks -Name policy.autoupdatestatisticsasynchronously.excludedb -Value @() -Initialize -Description "Databases to exclude from the auto update stats asynchronously checks" Set-PSFConfig -Module dbachecks -Name policy.database.statusexcludedb -Value @() -Initialize -Description "Databases to exclude from the database status checks" Set-PSFConfig -Module dbachecks -Name policy.database.symmetrickeyencryptionlevelexcludedb -Value @('master', 'msdb', 'tempdb') -Initialize -Description "Databases to exclude from the Symmetric Key Encryption Level checks" +Set-PSFConfig -Module dbachecks -Name policy.database.fkcktrustedexclude -Value @() -Initialize -Description "Databases to exclude from the foreign key and constraints trusted checks" @@ -342,6 +343,7 @@ Set-PSFConfig -Module dbachecks -Name skip.database.compatibilitylevel -Validati Set-PSFConfig -Module dbachecks -Name skip.database.recoverymodel -Validation bool -Value $false -Initialize -Description "Skip the database recovery model test" Set-PSFConfig -Module dbachecks -Name skip.database.pseudosimple -Validation bool -Value $false -Initialize -Description "Skip the database PseudoSimple recovery model test" Set-PSFConfig -Module dbachecks -Name skip.database.pageverify -Validation bool -Value $false -Initialize -Description "Skip the database page verify test" +Set-PSFConfig -Module dbachecks -Name skip.database.fkcktrusted -Validation bool -Value $false -Initialize -Description "Skip the check for foreign keys and constraints being trusted" Set-PSFConfig -Module dbachecks -Name skip.logshiptesting -Validation bool -Value $false -Initialize -Description "Skip the logshipping test" diff --git a/source/internal/functions/Get-AllDatabaseInfo.ps1 b/source/internal/functions/Get-AllDatabaseInfo.ps1 index f47de5e3..04748e78 100644 --- a/source/internal/functions/Get-AllDatabaseInfo.ps1 +++ b/source/internal/functions/Get-AllDatabaseInfo.ps1 @@ -161,6 +161,10 @@ function Get-AllDatabaseInfo { $ConfigValues | Add-Member -MemberType NoteProperty -Name 'pageverifyexclude' -Value ($__dbcconfig | Where-Object Name -EQ 'policy.database.contdbsqlauthexclude').Value $ConfigValues | Add-Member -MemberType NoteProperty -Name 'pageverify' -Value ($__dbcconfig | Where-Object Name -EQ 'policy.pageverify').Value } + 'FKCKTrusted' { + $trusted = $true + $ConfigValues | Add-Member -MemberType NoteProperty -Name 'fkcktrustedexclude' -Value ($__dbcconfig | Where-Object Name -EQ 'policy.database.fkcktrustedexclude').Value + } Default { } } @@ -202,6 +206,8 @@ function Get-AllDatabaseInfo { ContainedDbAutoClose = @(if ($containedDbAutoClose) { if (($psItem.ContainmentType -ne "NONE") -and ($null -ne $psItem.ContainmentType) -and $psitem.AutoClose) { $true } else { $false } } ) ContainedDbSqlAuthUsers = @(if ($containedDbSqlAuthUsers) { if ($psItem.ContainmentType -ne "NONE" -and ($null -ne $psItem.ContainmentType)) { ($psitem.Users | Where-Object { $_.LoginType -eq "SqlLogin" -and $_.HasDbAccess -eq $true } | Measure-Object ).Count } } ) PageVerify = @(if ($pageverify) { $psitem.PageVerify }) + ForeignKeys = @(if ($trusted) {$psitem.Tables.ForeignKeys | Where-Object {-not $_.NotForReplication} | Select-Object Name, Parent, @{l='Database';e={$_.Parent.Parent.Name}}, IsChecked } ) + Constraints = @(if ($trusted) {$psitem.Tables.Checks | Where-Object {(-not $_.NotForReplication) -and $_.IsEnabled} | Select-Object Name, Parent, @{l='Database';e={$_.Parent.Parent.Name}}, IsChecked } ) } } }