checks/Instance.Tests.ps1
$filename = $MyInvocation.MyCommand.Name.Replace(".Tests.ps1", "") Describe "SQL Engine Service" -Tags SqlEngineServiceAccount, ServiceAccount, $filename { @(Get-Instance).ForEach{ Context "Testing SQL Engine Service on $psitem" { @(Get-DbaSqlService -ComputerName $psitem -Type Engine).ForEach{ It "SQL Engine service account Should Be running on $($psitem.InstanceName)" { $psitem.State | Should -Be "Running" -Because 'If the service is not running, the SQL Server will not be accessible' } It "SQL Engine service account should have a start mode of Automatic on $($psitem.InstanceName)" { $psitem.StartMode | Should -Be "Automatic" -Because 'If the server restarts, the SQL Server will not be accessibl' } } } } } Describe "SQL Browser Service" -Tags SqlBrowserServiceAccount, ServiceAccount, $filename { @(Get-ComputerName).ForEach{ Context "Testing SQL Browser Service on $psitem" { if (@(Get-DbaSqlService -ComputerName $psitem -Type Engine).Count -eq 1) { It "SQL browser service on $psitem Should Be Stopped as only one instance is installed" { (Get-DbaSqlService -ComputerName $psitem -Type Browser).State | Should -Be "Stopped" -Because 'Unless there are multple instances you dont need the browser service' } } else { It "SQL browser service on $psitem Should Be Running as multiple instances are installed" { (Get-DbaSqlService -ComputerName $psitem -Type Browser).State| Should -Be "Running" -Because 'You need the browser service with multiple instances' } } if (@(Get-DbaSqlService -ComputerName $psitem -Type Engine).Count -eq 1) { It "SQL browser service startmode Should Be Disabled on $psitem as only one instance is installed" { (Get-DbaSqlService -ComputerName $psitem -Type Browser).StartMode | Should -Be "Disabled" -Because 'Unless there are multple instances you dont need the browser service' } } else { It "SQL browser service startmode Should Be Automatic on $psitem as multiple instances are installed" { (Get-DbaSqlService -ComputerName $psitem -Type Browser).StartMode | Should -Be "Automatic" } } } } } Describe "TempDB Configuration" -Tags TempDbConfiguration, $filename { @(Get-Instance).ForEach{ Context "Testing TempDB Configuration on $psitem" { $TempDBTest = Test-DbaTempDbConfiguration -SqlServer $psitem It "should have TF1118 enabled on $($TempDBTest[0].SqlInstance)" -Skip:(Get-DbcConfigValue -Name skip.TempDb1118) { $TempDBTest[0].CurrentSetting | Should -Be $TempDBTest[0].Recommended -Because 'TF 1118 should be enabled' } It "should have $($TempDBTest[1].Recommended) TempDB Files on $($TempDBTest[1].SqlInstance)" -Skip:(Get-DbcConfigValue -Name skip.tempdbfileCount) { $TempDBTest[1].CurrentSetting | Should -Be $TempDBTest[1].Recommended -Because 'This is the recommended number of tempdb files for your server' } It "should not have TempDB Files autogrowth set to percent on $($TempDBTest[2].SqlInstance)" -Skip:(Get-DbcConfigValue -Name skip.TempDbFileGrowthPercent) { $TempDBTest[2].CurrentSetting | Should -Be $TempDBTest[2].Recommended -Because 'Auto growth type should not be percent' } It "should not have TempDB Files on the C Drive on $($TempDBTest[3].SqlInstance)" -Skip:(Get-DbcConfigValue -Name skip.TempDbFilesonC) { $TempDBTest[3].CurrentSetting | Should -Be $TempDBTest[3].Recommended -Because 'You dot want the tempdb files on the same drive as the operating system' } It "should not have TempDB Files with MaxSize Set on $($TempDBTest[4].SqlInstance)" -Skip:(Get-DbcConfigValue -Name skip.TempDbFileMaxSize) { $TempDBTest[4].CurrentSetting | Should -Be $TempDBTest[4].Recommended -Because 'Tempdb files should be able to grow' } } } } Describe "Ad Hoc Workload Optimization" -Tags AdHocWorkload, $filename { @(Get-Instance).ForEach{ Context "Testing Ad Hoc Workload Optimization on $psitem" { It "$psitem Should Be Optimised for Ad Hoc workloads" { @(Test-DbaOptimizeForAdHoc -SqlInstance $psitem).ForEach{ $psitem.CurrentOptimizeAdHoc | Should -Be $psitem.RecommendedOptimizeAdHoc } } } } } Describe "Backup Path Access" -Tags BackupPathAccess, Storage, DISA, $filename { @(Get-Instance).ForEach{ Context "Testing Backup Path Access on $psitem" { if (-not (Get-DbcConfigValue policy.storage.backuppath)) { $backuppath = (Get-DbaDefaultPath -SqlInstance $psitem).Backup } else { $backuppath = Get-DbcConfigValue policy.storage.backuppath } It "can access backup path ($backuppath) on $psitem" { Test-DbaSqlPath -SqlInstance $psitem -Path $backuppath | Should -BeTrue -Because 'The SQL Service account needs to have access to the backup path to backup your databases' } } } } Describe "Dedicated Administrator Connection" -Tags DAC, $filename { $dac = Get-DbcConfigValue policy.dacallowed @(Get-Instance).ForEach{ Context "Testing Dedicated Administrator Connection on $psitem" { It "DAC is set to $dac on $psitem" { (Get-DbaSpConfigure -SqlInstance $psitem -ConfigName 'RemoteDACConnectionsEnabled').ConfiguredValue -eq 1 | Should -Be $dac -Because 'This is the setting that you have chosen for DAC connections' } } } } Describe "Network Latency" -Tags NetworkLatency, Connectivity, $filename { $max = Get-DbcConfigValue policy.network.latencymaxms @(Get-Instance).ForEach{ Context "Testing Network Latency on $psitem" { @(Test-DbaNetworkLatency -SqlInstance $psitem).ForEach{ It "network latency Should Be less than $max ms on $($psitem.SqlInstance)" { $psitem.Average.TotalMilliseconds | Should -BeLessThan $max -Because 'You dont want to be waiting on the network' } } } } } Describe "Linked Servers" -Tags LinkedServerConnection, Connectivity, $filename { @(Get-Instance).ForEach{ Context "Testing Linked Servers on $psitem" { @(Test-DbaLinkedServerConnection -SqlInstance $psitem).ForEach{ It "Linked Server $($psitem.LinkedServerName) on on $($psitem.SqlInstance) has connectivity" { $psitem.Connectivity | Should -BeTrue -Because 'You need to be able to connect to your linked servers' } } } } } Describe "Max Memory" -Tags MaxMemory, $filename { @(Get-Instance).ForEach{ Context "Testing Max Memory on $psitem" { It "Max Memory setting Should Be correct on $psitem" { @(Test-DbaMaxMemory -SqlInstance $psitem).ForEach{ $psitem.SqlMaxMB | Should -BeLessThan ($psitem.RecommendedMB + 379) -Because 'You do not want to exhaust server memory' } } } } } Describe "Orphaned Files" -Tags OrphanedFile, $filename { @(Get-Instance).ForEach{ Context "Checking for orphaned database files on $psitem" { It "$psitem doesn't have orphan files" { (Find-DbaOrphanedFile -SqlInstance $psitem).Count | Should -Be 0 -Because 'You dont want any orphaned files - Use Find-DbaOrphanedFiles to locate them' } } } } Describe "SQL + Windows names match" -Tags ServerNameMatch, $filename { @(Get-Instance).ForEach{ Context "Testing instance name matches Windows name for $psitem" { It "$psitem doesn't require rename" { (Test-DbaServerName -SqlInstance $psitem).RenameRequired | Should -BeFalse -Because 'SQL and Windows should agree on the server name' } } } } Describe "SQL Memory Dumps" -Tags MemoryDump, $filename { $maxdumps = Get-DbcConfigValue -Name policy.dump.maxcount @(Get-Instance).ForEach{ Context "Checking that dumps on $psitem do not exceed $maxdumps for $psitem" { $count = (Get-DbaDump -SqlInstance $psitem).Count It "dump count of $count is less than or equal to the $maxdumps dumps on $psitem" { $Count | Should -BeLessOrEqual $maxdumps -Because 'Memory dumps often suggest issues with the SQL Server instance' } } } } Describe "Supported Build" -Tags SupportedBuild, DISA, $filename { $BuildWarning = Get-DbcConfigValue -Name policy.build.warningwindow @(Get-Instance).ForEach{ Context "Checking that build is still supportedby Microsoft for $psitem" { $results = Get-DbaSqlBuildReference -SqlInstance $psitem It "$($results.Build) on $psitem is still supported" { $results.SupportedUntil | Should -BeGreaterThan (Get-Date) -Because 'This build is now unsupported by Microsoft' } It "$($results.Build) on $psitem is supported for more than $BuildWarning Months" { $results.SupportedUntil | Should -BeGreaterThan (Get-Date).AddMonths($BuildWarning) -Because 'This build will soon be unsupported by Microsoft' } } } } Describe "SA Login Renamed" -Tags SaRenamed, DISA, $filename { @(Get-Instance).ForEach{ Context "Checking that sa login has been renamed on $psitem" { $results = Get-DbaLogin -SqlInstance $psitem -Login sa It "sa login does not exist on $psitem" { $results | Should -Be $null -Because 'Renaming the sa account is a requirement' } } } } Describe "Default Backup Compression" -Tags DefaultBackupCompression, $filename { $defaultbackupcompression = Get-DbcConfigValue policy.backup.defaultbackupcompression @(Get-Instance).ForEach{ Context "Testing Default Backup Compression on $psitem" { It "Default Backup Compression is set to $defaultbackupcompression on $psitem" { (Get-DbaSpConfigure -SqlInstance $psitem -ConfigName 'DefaultBackupCompression').ConfiguredValue -eq 1 | Should -Be $defaultbackupcompression -Because 'The default backup compression should be set correctly' } } } } Describe "Stopped XE Sessions" -Tags XESessionStopped, ExtendedEvent, $filename { $xesession = Get-DbcConfigValue policy.xevent.requiredstoppedsession @(Get-Instance).ForEach{ Context "Checking sessions on $psitem" { @(Get-DbaXESession -SqlInstance $psitem).ForEach{ if ($psitem.Name -in $xesession) { It "session $($psitem.Name) should not be running on $($psitem.InstanceName)" { $psitem.Status | Should -Be "Stopped" -Because 'This session should be stopped' } } } } } } Describe "Running XE Sessions" -Tags XESessionRunning, ExtendedEvent, $filename { $xesession = Get-DbcConfigValue policy.xevent.requiredrunningsession @(Get-Instance).ForEach{ Context "Checking running sessions on $psitem" { @(Get-DbaXESession -SqlInstance $psitem).ForEach{ if ($psitem.Name -in $xesession) { It "session $($psitem.Name) Should Be running on $($psitem.InstanceName)" { $psitem.Status | Should -Be "Running" -Because 'This session should be running' } } } } } } Describe "XE Sessions Running Allowed" -Tags XESessionRunningAllowed, ExtendedEvent, $filename { $xesession = Get-DbcConfigValue policy.xevent.validrunningsession @(Get-Instance).ForEach{ Context "Checking sessions on $psitem" { @(Get-DbaXESession -SqlInstance $psitem).ForEach{ if ($psitem.Name -notin $xesession) { It "session $($psitem.Name) should not be running on $($psitem.InstanceName)" { $psitem.Status | Should -Be "Stopped" -Because 'These sessions should not be running' } } } } } } Describe "OLE Automation" -Tags OLEAutomation, $filename { $OLEAutomation = Get-DbcConfigValue policy.oleautomation @(Get-Instance).ForEach{ Context "Testing OLE Automation on $psitem" { It "OLE Automation is set to $OLEAutomation on $psitem" { (Get-DbaSpConfigure -SqlInstance $psitem -ConfigName 'OleAutomationProceduresEnabled').ConfiguredValue -eq 1 | Should -Be $OLEAutomation -Because 'OLE Automation can introduce additional security risks' } } } } Describe "sp_whoisactive is Installed" -Tags WhoIsActiveInstalled, $filename { $db = Get-DbcConfigValue policy.whoisactive.database @(Get-Instance).ForEach{ Context "Testing WhoIsActive exists on $psitem" { It "WhoIsActive should exists on $db on $psitem" { (Get-DbaSqlModule -SqlInstance $psitem -Database $db -Type StoredProcedure | Where-Object name -eq "sp_WhoIsActive") | Should -Not -Be $Null -Because 'The sp_WhoIsActive stored procedure should be installed' } } } } Describe "Model Database Growth" -Tags ModelDbGrowth, $filename { $modeldbgrowthtest = Get-DbcConfigValue skip.instance.modeldbgrowth if (-not $modeldbgrowthtest) { @(Get-Instance).ForEach{ Context "Testing model database growth setting is not default on $psitem" { @(Get-DbaDatabaseFile -SqlInstance $psitem -Database Model).ForEach{ It "Model database growth settings should not be percent for file $($psitem.LogicalName) on $($psitem.SqlInstance)" { $psitem.GrowthType | Should -Not -Be 'Percent' -Because 'New databases use the model database as a template and percent growth can cause performance problems' } It "Model database growth settings should not be 1Mb for file $($psitem.LogicalName) on $($psitem.SqlInstance)" { $psitem.Growth | Should -Not -Be 1024 -Because 'New databases use the model database as a template and growing for each Mb will have a performance impact' } } } } } } Describe "Error Log Entries" -Tags ErrorLog, $filename { $logWindow = Get-DbcConfigValue policy.errorlog.warningwindow @(Get-SqlInstance).ForEach{ Context "Checking error log on $psitem" { It "Error log should be free of error severities 17-24 on $psitem" { (Get-DbaSqlLog -SqlInstance $psitem -After (Get-Date).AddDays(-$logWindow)).Text | Should -Not -Match "Severity: 1[7-9]" -Because "these severities indicate serious problems" (Get-DbaSqlLog -SqlInstance $psitem -After (Get-Date).AddDays(-$logWindow)).Text | Should -Not -Match "Severity: 2[0-4]" -Because "these severities indicate serious problems" } } } } # SIG # Begin signature block # MIINEAYJKoZIhvcNAQcCoIINATCCDP0CAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB # gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR # AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUs9XP/Ddpka5F+GpJ5E8Dvtll # ElKgggpSMIIFGjCCBAKgAwIBAgIQAsF1KHTVwoQxhSrYoGRpyjANBgkqhkiG9w0B # AQsFADByMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYD # VQQLExB3d3cuZGlnaWNlcnQuY29tMTEwLwYDVQQDEyhEaWdpQ2VydCBTSEEyIEFz # c3VyZWQgSUQgQ29kZSBTaWduaW5nIENBMB4XDTE3MDUwOTAwMDAwMFoXDTIwMDUx # MzEyMDAwMFowVzELMAkGA1UEBhMCVVMxETAPBgNVBAgTCFZpcmdpbmlhMQ8wDQYD # VQQHEwZWaWVubmExETAPBgNVBAoTCGRiYXRvb2xzMREwDwYDVQQDEwhkYmF0b29s # czCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAI8ng7JxnekL0AO4qQgt # Kr6p3q3SNOPh+SUZH+SyY8EA2I3wR7BMoT7rnZNolTwGjUXn7bRC6vISWg16N202 # 1RBWdTGW2rVPBVLF4HA46jle4hcpEVquXdj3yGYa99ko1w2FOWzLjKvtLqj4tzOh # K7wa/Gbmv0Si/FU6oOmctzYMI0QXtEG7lR1HsJT5kywwmgcjyuiN28iBIhT6man0 # Ib6xKDv40PblKq5c9AFVldXUGVeBJbLhcEAA1nSPSLGdc7j4J2SulGISYY7ocuX3 # tkv01te72Mv2KkqqpfkLEAQjXgtM0hlgwuc8/A4if+I0YtboCMkVQuwBpbR9/6ys # Z+sCAwEAAaOCAcUwggHBMB8GA1UdIwQYMBaAFFrEuXsqCqOl6nEDwGD5LfZldQ5Y # MB0GA1UdDgQWBBRcxSkFqeA3vvHU0aq2mVpFRSOdmjAOBgNVHQ8BAf8EBAMCB4Aw # EwYDVR0lBAwwCgYIKwYBBQUHAwMwdwYDVR0fBHAwbjA1oDOgMYYvaHR0cDovL2Ny # bDMuZGlnaWNlcnQuY29tL3NoYTItYXNzdXJlZC1jcy1nMS5jcmwwNaAzoDGGL2h0 # dHA6Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9zaGEyLWFzc3VyZWQtY3MtZzEuY3JsMEwG # A1UdIARFMEMwNwYJYIZIAYb9bAMBMCowKAYIKwYBBQUHAgEWHGh0dHBzOi8vd3d3 # LmRpZ2ljZXJ0LmNvbS9DUFMwCAYGZ4EMAQQBMIGEBggrBgEFBQcBAQR4MHYwJAYI # KwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBOBggrBgEFBQcwAoZC # aHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0U0hBMkFzc3VyZWRJ # RENvZGVTaWduaW5nQ0EuY3J0MAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQELBQAD # ggEBANuBGTbzCRhgG0Th09J0m/qDqohWMx6ZOFKhMoKl8f/l6IwyDrkG48JBkWOA # QYXNAzvp3Ro7aGCNJKRAOcIjNKYef/PFRfFQvMe07nQIj78G8x0q44ZpOVCp9uVj # sLmIvsmF1dcYhOWs9BOG/Zp9augJUtlYpo4JW+iuZHCqjhKzIc74rEEiZd0hSm8M # asshvBUSB9e8do/7RhaKezvlciDaFBQvg5s0fICsEhULBRhoyVOiUKUcemprPiTD # xh3buBLuN0bBayjWmOMlkG1Z6i8DUvWlPGz9jiBT3ONBqxXfghXLL6n8PhfppBhn # daPQO8+SqF5rqrlyBPmRRaTz2GQwggUwMIIEGKADAgECAhAECRgbX9W7ZnVTQ7Vv # lVAIMA0GCSqGSIb3DQEBCwUAMGUxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdp # Q2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xJDAiBgNVBAMTG0Rp # Z2lDZXJ0IEFzc3VyZWQgSUQgUm9vdCBDQTAeFw0xMzEwMjIxMjAwMDBaFw0yODEw # MjIxMjAwMDBaMHIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMx # GTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xMTAvBgNVBAMTKERpZ2lDZXJ0IFNI # QTIgQXNzdXJlZCBJRCBDb2RlIFNpZ25pbmcgQ0EwggEiMA0GCSqGSIb3DQEBAQUA # A4IBDwAwggEKAoIBAQD407Mcfw4Rr2d3B9MLMUkZz9D7RZmxOttE9X/lqJ3bMtdx # 6nadBS63j/qSQ8Cl+YnUNxnXtqrwnIal2CWsDnkoOn7p0WfTxvspJ8fTeyOU5JEj # lpB3gvmhhCNmElQzUHSxKCa7JGnCwlLyFGeKiUXULaGj6YgsIJWuHEqHCN8M9eJN # YBi+qsSyrnAxZjNxPqxwoqvOf+l8y5Kh5TsxHM/q8grkV7tKtel05iv+bMt+dDk2 # DZDv5LVOpKnqagqrhPOsZ061xPeM0SAlI+sIZD5SlsHyDxL0xY4PwaLoLFH3c7y9 # hbFig3NBggfkOItqcyDQD2RzPJ6fpjOp/RnfJZPRAgMBAAGjggHNMIIByTASBgNV # HRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIBhjATBgNVHSUEDDAKBggrBgEF # BQcDAzB5BggrBgEFBQcBAQRtMGswJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRp # Z2ljZXJ0LmNvbTBDBggrBgEFBQcwAoY3aHR0cDovL2NhY2VydHMuZGlnaWNlcnQu # Y29tL0RpZ2lDZXJ0QXNzdXJlZElEUm9vdENBLmNydDCBgQYDVR0fBHoweDA6oDig # NoY0aHR0cDovL2NybDQuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0QXNzdXJlZElEUm9v # dENBLmNybDA6oDigNoY0aHR0cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0 # QXNzdXJlZElEUm9vdENBLmNybDBPBgNVHSAESDBGMDgGCmCGSAGG/WwAAgQwKjAo # BggrBgEFBQcCARYcaHR0cHM6Ly93d3cuZGlnaWNlcnQuY29tL0NQUzAKBghghkgB # hv1sAzAdBgNVHQ4EFgQUWsS5eyoKo6XqcQPAYPkt9mV1DlgwHwYDVR0jBBgwFoAU # Reuir/SSy4IxLVGLp6chnfNtyA8wDQYJKoZIhvcNAQELBQADggEBAD7sDVoks/Mi # 0RXILHwlKXaoHV0cLToaxO8wYdd+C2D9wz0PxK+L/e8q3yBVN7Dh9tGSdQ9RtG6l # jlriXiSBThCk7j9xjmMOE0ut119EefM2FAaK95xGTlz/kLEbBw6RFfu6r7VRwo0k # riTGxycqoSkoGjpxKAI8LpGjwCUR4pwUR6F6aGivm6dcIFzZcbEMj7uo+MUSaJ/P # QMtARKUT8OZkDCUIQjKyNookAv4vcn4c10lFluhZHen6dGRrsutmQ9qzsIzV6Q3d # 9gEgzpkxYz0IGhizgZtPxpMQBvwHgfqL2vmCSfdibqFT+hKUGIUukpHqaGxEMrJm # oecYpJpkUe8xggIoMIICJAIBATCBhjByMQswCQYDVQQGEwJVUzEVMBMGA1UEChMM # RGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMTEwLwYDVQQD # EyhEaWdpQ2VydCBTSEEyIEFzc3VyZWQgSUQgQ29kZSBTaWduaW5nIENBAhACwXUo # dNXChDGFKtigZGnKMAkGBSsOAwIaBQCgeDAYBgorBgEEAYI3AgEMMQowCKACgACh # AoAAMBkGCSqGSIb3DQEJAzEMBgorBgEEAYI3AgEEMBwGCisGAQQBgjcCAQsxDjAM # BgorBgEEAYI3AgEVMCMGCSqGSIb3DQEJBDEWBBRqEPhFXpfhgmukL6Z/7TVPIGWP # fDANBgkqhkiG9w0BAQEFAASCAQBsnMhGNTl+GfKuud+pkF6arq/7A3CTn/8Nj0Lw # tN1E+0KdSX0M3sN1yCEeC0tfbvUBG8gXNr4UR8qz6phMuqSpOOf2UC0ztK7kd16o # WFrJwaCB6o2hECLHxwmp5OhP6t+k6/KcpHb5DPcC73N/4oJ5LG13tpjpqrvjCR4C # ZIiskgoqG8p6MoyahjHAP7Atm3qFgFYRtjUNkjcOmpEfUBjDkKqelHiFZx6oevwA # xhpna9RC7CIcUEEUGOqwp0cs35DxTzxyau8unF96el5Os+iEvsWhDIRrmCBtTlAC # HPEqgNpzPxMHnJouYlz4b4y3lZZv26lxF//9vf9GeebqL1Tg # SIG # End signature block |