From 07abe730f859a8f19282204327e478aaf7b90731 Mon Sep 17 00:00:00 2001 From: Tracy Boggiano Date: Sat, 28 Dec 2019 15:59:55 -0500 Subject: [PATCH 01/61] CIS test for Hide Instance setting for server --- checks/Instance.Tests.ps1 | 18 ++++++++ internal/assertions/Instance.Assertions.ps1 | 44 +++++++++++++++++-- .../configurations/DbcCheckDescriptions.json | 4 ++ internal/configurations/configuration.ps1 | 1 + 4 files changed, 63 insertions(+), 4 deletions(-) diff --git a/checks/Instance.Tests.ps1 b/checks/Instance.Tests.ps1 index fa3c3fe4..df403f06 100644 --- a/checks/Instance.Tests.ps1 +++ b/checks/Instance.Tests.ps1 @@ -943,6 +943,24 @@ $Tags = Get-CheckInformation -Check $Check -Group Instance -AllChecks $AllChecks } } } + + Describe "Hide Instance" -Tags HideInstance, Security, CIS, Medium, $filename { + $skip = Get-DbcConfigValue skip.instance.hideinstance + if ($NotContactable -contains $psitem) { + Context "Testing Hide Instance on $psitem" { + It "Can't Connect to $Psitem" -Skip:$skip { + $false | Should -BeTrue -Because "The instance should be available to be connected to!" + } + } + } + else { + Context "Testing Hide Instance on $psitem" { + It "The Hide Instance on SQL Server instance $psitem" -Skip:$skip { + Assert-HideInstance -AllInstanceInfo $AllInstanceInfo + } + } + } + } } Describe "SQL Browser Service" -Tags SqlBrowserServiceAccount, ServiceAccount, High, $filename { diff --git a/internal/assertions/Instance.Assertions.ps1 b/internal/assertions/Instance.Assertions.ps1 index 9972a5ce..2b985736 100644 --- a/internal/assertions/Instance.Assertions.ps1 +++ b/internal/assertions/Instance.Assertions.ps1 @@ -305,7 +305,6 @@ function Get-AllInstanceInfo { $results = Invoke-DbaQuery -SqlInstance $Instance -Query $query $SaDisabled = [pscustomobject] @{ Disabled = $results.is_disabled - } } catch { @@ -369,8 +368,7 @@ function Get-AllInstanceInfo { catch { $There = $false $EngineService = [pscustomobject] @{ - State = 'We Could not Connect to $Instance $ComputerName , $InstanceName from catch' - StartType = 'We Could not Connect to $Instance $ComputerName , $InstanceName from catch' + Result = 'We Could not Connect to $Instance' } } } @@ -378,7 +376,39 @@ function Get-AllInstanceInfo { $There = $false $EngineService = [pscustomobject] @{ State = 'We Could not Connect to $Instance' - StartType = 'We Could not Connect to $Instance' + } + } + } + 'HideInstance' { + if ($There) { + try { + $query = " + DECLARE @getValue INT; + + EXEC master.sys.xp_instance_regread + @rootkey = N'HKEY_LOCAL_MACHINE', + @key = N'SOFTWARE\Microsoft\Microsoft SQL Server\MSSQLServer\SuperSocketNetLib', + @value_name = N'HideInstance', + @value = @getValue OUTPUT; + + SELECT @getValue as Value; + " + $results = Invoke-DbaQuery -SqlInstance $Instance -Query $query + $HideInstance = [pscustomobject] @{ + Value = $results.Value + } + } + catch { + $There = $false + $HideInstance = [pscustomobject] @{ + Value = StartType = 'We Could not Connect to $Instance' + } + } + } + else { + $There = $false + $HideInstance = [pscustomobject] @{ + Value = 'We Could not Connect to $Instance' } } } @@ -396,6 +426,7 @@ function Get-AllInstanceInfo { SaExist = $SaExist SaDisabled = $SaDisabled EngineService = $EngineService + HideInstance = $HideInstance } } @@ -587,6 +618,11 @@ function Assert-SaExist { $AllInstanceInfo.SaExist.Exist | Should -Be $false -Because "We expected no login to exist with the name sa" } +function Assert-HideInstance { + Param($AllInstanceInfo) + $AllInstanceInfo.HideInstance.Value | Should -Be 1 -Because "We expected the hide instance proptety to be set to YES (1)" +} + # SIG # Begin signature block # MIINEAYJKoZIhvcNAQcCoIINATCCDP0CAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB # gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR diff --git a/internal/configurations/DbcCheckDescriptions.json b/internal/configurations/DbcCheckDescriptions.json index 44194c7a..bb2cb03c 100644 --- a/internal/configurations/DbcCheckDescriptions.json +++ b/internal/configurations/DbcCheckDescriptions.json @@ -450,5 +450,9 @@ { "UniqueTag": "ContainedDBAutoClose", "Description": "Tests that each contained database has AUTO CLOSE disabled." + }, + { + "UniqueTag": "HideInstance", + "Description": "Tests that each hide instance is set to YES for the instance." } ] diff --git a/internal/configurations/configuration.ps1 b/internal/configurations/configuration.ps1 index 9e921638..304df9f9 100644 --- a/internal/configurations/configuration.ps1 +++ b/internal/configurations/configuration.ps1 @@ -241,6 +241,7 @@ Set-PSFConfig -Module dbachecks -Name skip.instance.latestbuild -Validation bool Set-PSFConfig -Module dbachecks -Name skip.security.sadisabled -Validation bool -Value $true -Initialize -Description "Skip the check for if the sa login is disabled" Set-PSFConfig -Module dbachecks -Name skip.security.saexist -Validation bool -Value $true -Initialize -Description "Skip teh check for a login named sa does not exist" Set-PSFConfig -Module dbachecks -Name skip.security.containedbautoclose -Validation bool -Value $true -Initialize -Description "Skips the scan for contained databases should have auto close enabled" +Set-PSFConfig -Module dbachecks -Name skip.security.hideinstance -Validation bool -Value $true -Initialize -Description "Skips the scan for if hide instance is set to YES on the instance" #agent Set-PSFConfig -Module dbachecks -Name agent.dbaoperatorname -Value $null -Initialize -Description "Name of the DBA Operator in SQL Agent" From bde9684e64429a8d275af0e1ac9f51a83eb1912f Mon Sep 17 00:00:00 2001 From: Tracy Boggiano Date: Sat, 28 Dec 2019 16:02:57 -0500 Subject: [PATCH 02/61] fix typo --- checks/Instance.Tests.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/checks/Instance.Tests.ps1 b/checks/Instance.Tests.ps1 index df403f06..8899ebd6 100644 --- a/checks/Instance.Tests.ps1 +++ b/checks/Instance.Tests.ps1 @@ -945,7 +945,7 @@ $Tags = Get-CheckInformation -Check $Check -Group Instance -AllChecks $AllChecks } Describe "Hide Instance" -Tags HideInstance, Security, CIS, Medium, $filename { - $skip = Get-DbcConfigValue skip.instance.hideinstance + $skip = Get-DbcConfigValue skip.security.hideinstance if ($NotContactable -contains $psitem) { Context "Testing Hide Instance on $psitem" { It "Can't Connect to $Psitem" -Skip:$skip { From bbfb6efd567f0943e8b2be2fb6205fe26aa782ca Mon Sep 17 00:00:00 2001 From: Tracy Boggiano Date: Sat, 28 Dec 2019 16:06:06 -0500 Subject: [PATCH 03/61] fix mistakes --- internal/assertions/Instance.Assertions.ps1 | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/internal/assertions/Instance.Assertions.ps1 b/internal/assertions/Instance.Assertions.ps1 index 2b985736..5686d2f3 100644 --- a/internal/assertions/Instance.Assertions.ps1 +++ b/internal/assertions/Instance.Assertions.ps1 @@ -368,7 +368,8 @@ function Get-AllInstanceInfo { catch { $There = $false $EngineService = [pscustomobject] @{ - Result = 'We Could not Connect to $Instance' + State = 'We Could not Connect to $Instance $ComputerName , $InstanceName from catch' + StartType = 'We Could not Connect to $Instance $ComputerName , $InstanceName from catch' } } } @@ -376,6 +377,7 @@ function Get-AllInstanceInfo { $There = $false $EngineService = [pscustomobject] @{ State = 'We Could not Connect to $Instance' + StartType = 'We Could not Connect to $Instance' } } } From 35815553ae930a9e0c3e9e02a0c730e3218c46a0 Mon Sep 17 00:00:00 2001 From: Tracy Boggiano Date: Mon, 30 Dec 2019 09:52:00 -0500 Subject: [PATCH 04/61] change titles --- checks/Instance.Tests.ps1 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/checks/Instance.Tests.ps1 b/checks/Instance.Tests.ps1 index 8899ebd6..c9fe7735 100644 --- a/checks/Instance.Tests.ps1 +++ b/checks/Instance.Tests.ps1 @@ -947,15 +947,15 @@ $Tags = Get-CheckInformation -Check $Check -Group Instance -AllChecks $AllChecks Describe "Hide Instance" -Tags HideInstance, Security, CIS, Medium, $filename { $skip = Get-DbcConfigValue skip.security.hideinstance if ($NotContactable -contains $psitem) { - Context "Testing Hide Instance on $psitem" { + Context "Checking the Hide an Instance of SQL Server Database Engine property on $psitem" { It "Can't Connect to $Psitem" -Skip:$skip { $false | Should -BeTrue -Because "The instance should be available to be connected to!" } } } else { - Context "Testing Hide Instance on $psitem" { - It "The Hide Instance on SQL Server instance $psitem" -Skip:$skip { + Context "Checking the Hide an Instance of SQL Server Database Engine property on $psitem" { + It "The Hide an Instance of SQL Server Database Engine property on SQL Server instance $psitem" -Skip:$skip { Assert-HideInstance -AllInstanceInfo $AllInstanceInfo } } From 7c14818b38c7b45553647ae52d3d65ae9cba960e Mon Sep 17 00:00:00 2001 From: Tracy Boggiano Date: Tue, 31 Dec 2019 09:53:02 -0500 Subject: [PATCH 05/61] save changes --- checks/Database.Tests.ps1 | 42 +++++++++++++++++++ internal/assertions/Database.Assertions.ps1 | 32 ++++++++++++++ .../configurations/DbcCheckDescriptions.json | 8 ++++ internal/configurations/configuration.ps1 | 2 + 4 files changed, 84 insertions(+) diff --git a/checks/Database.Tests.ps1 b/checks/Database.Tests.ps1 index 1580e4c4..f1021a8c 100644 --- a/checks/Database.Tests.ps1 +++ b/checks/Database.Tests.ps1 @@ -957,6 +957,48 @@ $ExcludedDatabases += $ExcludeDatabase } } } + + Describe "AsymmetricKeySize" -Tags AssymetricKeySize, CIS, $filename { + $skip = Get-DbcConfigValue skip.security.assymetrickeysize + $ExcludedDatabases += "master", "tempdb", "msdb" + if ($NotContactable -contains $psitem) { + Context "Testing Asymmetric Key Size is 2048 or higher on $psitem" { + It "Can't Connect to $Psitem" { + $true | Should -BeFalse -Because "The instance should be available to be connected to!" + } + } + } + else { + Context "Testing Asymmetric Key Size is 2048 or higher on $psitem" { + @($InstanceSMO.Databases.Where{($(if ($Database) {$PsItem.Name -in $Database}else {$ExcludedDatabases -notcontains $PsItem.Name}))}).ForEach{ + It "$($psitem.Name) on $($psitem.Parent.Name) asymmetric keys sizes of at least 2048" -Skip:$skip { + $psitem.AutoClose | Should -BeTrue -Because "Asymmetric Key Size should be 2048 or higher for CIS compliance" + } + } + } + } + } + + Describe "SymmetricKeyEncryptionLevel" -Tags SymmetricKeyEncryptionLevel, CIS, $filename { + $skip = Get-DbcConfigValue skip.security.symmetrickeyencryptionlevel + $ExcludedDatabases += "master", "tempdb", "msdb" + if ($NotContactable -contains $psitem) { + Context "Testing Symmetric Key Encruption Level at least AES_128 or higher on $psitem" { + It "Can't Connect to $Psitem" { + $true | Should -BeFalse -Because "The instance should be available to be connected to!" + } + } + } + else { + Context "Testing Symmetric Key Encruption Level at least AES_128 or higher on $psitem" { + @($InstanceSMO.Databases.Where{($(if ($Database) {$PsItem.Name -in $Database}else {$ExcludedDatabases -notcontains $PsItem.Name}))}).ForEach{ + It "$($psitem.Name) on $($psitem.Parent.Name) should have symmetric key encyption levels of at least AES_128" -Skip:$skip { + $psitem.AutoClose | Should -BeTrue -Because "Symmetric Key Encruption Level at least AES_128 or higher for CIS compliance" + } + } + } + } + } } Set-PSFConfig -Module dbachecks -Name global.notcontactable -Value $NotContactable diff --git a/internal/assertions/Database.Assertions.ps1 b/internal/assertions/Database.Assertions.ps1 index fd1b3686..9671f647 100644 --- a/internal/assertions/Database.Assertions.ps1 +++ b/internal/assertions/Database.Assertions.ps1 @@ -69,6 +69,38 @@ function Assert-DatabaseExists { $Actual = Get-Database -Instance $instance -Requiredinfo Name $Actual | Should -Contain $expecteddb -Because "We expect $expecteddb to be on $Instance" } + +function Assert-AsymmetricKeySize { + Param ( + [string]$Instance, + [string]$Database + ) + $query = " + SELECT name, + key_length + FROM sys.asymmetric_keys + WHERE key_length < 2048; + " + + $Actual = Get-Database -Instance $instance -Requiredinfo Name + $Actual | Should -Contain $expecteddb -Because "We expect $expecteddb to be on $Instance" +} + +function Assert-SymmetricKeyEncryptionLevel { + Param ( + [string]$Instance, + [string]$Database + ) + $query = " + SELECT name, + algorithm_desc + FROM sys.symmetric_keys + WHERE algorithm_desc NOT IN ('AES_128','AES_192','AES_256'); + " + Get-DbaDbEncryption (Get-DbaDbEncryption -SqlInstance . -Database master | Where-Object Encryption -eq "Asymmetric Key") | Where-Object EncryptionAlgrothim + $Actual = Get-Database -Instance $instance -Requiredinfo Name + $Actual | Should -Contain $expecteddb -Because "We expect $expecteddb to be on $Instance" +} # SIG # Begin signature block # MIINEAYJKoZIhvcNAQcCoIINATCCDP0CAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB # gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR diff --git a/internal/configurations/DbcCheckDescriptions.json b/internal/configurations/DbcCheckDescriptions.json index 44194c7a..f3de62dd 100644 --- a/internal/configurations/DbcCheckDescriptions.json +++ b/internal/configurations/DbcCheckDescriptions.json @@ -450,5 +450,13 @@ { "UniqueTag": "ContainedDBAutoClose", "Description": "Tests that each contained database has AUTO CLOSE disabled." + }, + { + "UniqueTag": "SymmetricKeyEncryptionLevel", + "Description": "Tests that Symmetric Key Encryption Level is at least AES_128 in non-system databases." + }, + { + "UniqueTag": "AsymmetricKeySize", + "Description": "Tests that Asymmetric Key Sizes are at least 2048 in non-system databases." } ] diff --git a/internal/configurations/configuration.ps1 b/internal/configurations/configuration.ps1 index 9e921638..e51f2b98 100644 --- a/internal/configurations/configuration.ps1 +++ b/internal/configurations/configuration.ps1 @@ -241,6 +241,8 @@ Set-PSFConfig -Module dbachecks -Name skip.instance.latestbuild -Validation bool Set-PSFConfig -Module dbachecks -Name skip.security.sadisabled -Validation bool -Value $true -Initialize -Description "Skip the check for if the sa login is disabled" Set-PSFConfig -Module dbachecks -Name skip.security.saexist -Validation bool -Value $true -Initialize -Description "Skip teh check for a login named sa does not exist" Set-PSFConfig -Module dbachecks -Name skip.security.containedbautoclose -Validation bool -Value $true -Initialize -Description "Skips the scan for contained databases should have auto close enabled" +Set-PSFConfig -Module dbachecks -Name skip.security.symmetrickeyencryptionlevel -Validation bool -Value $true -Initialize -Description "Skips the test for if the Symmetric Encryption is at least AES_128 or higher in non-system databases" +Set-PSFConfig -Module dbachecks -Name skip.security.asymmetrickeysize -Validation bool -Value $true -Initialize -Description "Skips the test for the size of the Assymetric Key sizes being above 2048 in non-system databases" #agent Set-PSFConfig -Module dbachecks -Name agent.dbaoperatorname -Value $null -Initialize -Description "Name of the DBA Operator in SQL Agent" From 2c261f2a02acc7175d30719ce29fde4bfa18d48e Mon Sep 17 00:00:00 2001 From: Tracy Boggiano Date: Tue, 31 Dec 2019 11:04:54 -0500 Subject: [PATCH 06/61] CIS test for symmetric and asymmetric keys on databases --- checks/Database.Tests.ps1 | 12 ++++++------ internal/assertions/Database.Assertions.ps1 | 20 ++------------------ 2 files changed, 8 insertions(+), 24 deletions(-) diff --git a/checks/Database.Tests.ps1 b/checks/Database.Tests.ps1 index f1021a8c..6a29b67a 100644 --- a/checks/Database.Tests.ps1 +++ b/checks/Database.Tests.ps1 @@ -971,8 +971,8 @@ $ExcludedDatabases += $ExcludeDatabase else { Context "Testing Asymmetric Key Size is 2048 or higher on $psitem" { @($InstanceSMO.Databases.Where{($(if ($Database) {$PsItem.Name -in $Database}else {$ExcludedDatabases -notcontains $PsItem.Name}))}).ForEach{ - It "$($psitem.Name) on $($psitem.Parent.Name) asymmetric keys sizes of at least 2048" -Skip:$skip { - $psitem.AutoClose | Should -BeTrue -Because "Asymmetric Key Size should be 2048 or higher for CIS compliance" + It "$($psitem.Name) on $($psitem.Parent.Name) Asymmetric Key Size should be at least 2048" -Skip:$skip { + Assert-AsymmetricKeySize -Instance $instance -Database $psitem } } } @@ -983,8 +983,8 @@ $ExcludedDatabases += $ExcludeDatabase $skip = Get-DbcConfigValue skip.security.symmetrickeyencryptionlevel $ExcludedDatabases += "master", "tempdb", "msdb" if ($NotContactable -contains $psitem) { - Context "Testing Symmetric Key Encruption Level at least AES_128 or higher on $psitem" { - It "Can't Connect to $Psitem" { + Context "Testing Symmetric Key Encruption Level at least AES_128 or higher on $psitem" -Skip:$skip { + It "Can't Connect to $Psitem" -Skip:$skip { $true | Should -BeFalse -Because "The instance should be available to be connected to!" } } @@ -992,8 +992,8 @@ $ExcludedDatabases += $ExcludeDatabase else { Context "Testing Symmetric Key Encruption Level at least AES_128 or higher on $psitem" { @($InstanceSMO.Databases.Where{($(if ($Database) {$PsItem.Name -in $Database}else {$ExcludedDatabases -notcontains $PsItem.Name}))}).ForEach{ - It "$($psitem.Name) on $($psitem.Parent.Name) should have symmetric key encyption levels of at least AES_128" -Skip:$skip { - $psitem.AutoClose | Should -BeTrue -Because "Symmetric Key Encruption Level at least AES_128 or higher for CIS compliance" + It "$($psitem.Name) on $($psitem.Parent.Name) Symmetric Key Encryption Level should have AES_128 or higher" -Skip:$skip { + Assert-SymmetricKeyEncryptionLevel -Instance $instance -Database $psitem } } } diff --git a/internal/assertions/Database.Assertions.ps1 b/internal/assertions/Database.Assertions.ps1 index 9671f647..77c12d36 100644 --- a/internal/assertions/Database.Assertions.ps1 +++ b/internal/assertions/Database.Assertions.ps1 @@ -75,15 +75,7 @@ function Assert-AsymmetricKeySize { [string]$Instance, [string]$Database ) - $query = " - SELECT name, - key_length - FROM sys.asymmetric_keys - WHERE key_length < 2048; - " - - $Actual = Get-Database -Instance $instance -Requiredinfo Name - $Actual | Should -Contain $expecteddb -Because "We expect $expecteddb to be on $Instance" + @(Get-DbaDbEncryption -SqlInstance $Instance -Database $Database | Where-Object {$_.Encryption -eq "Symmetric Key" -and $_.KeyLength -LT 2048}).Count | Should -Be 0 -Because "Symmetric keys should have a key length greater than or equal to 2048" } function Assert-SymmetricKeyEncryptionLevel { @@ -91,15 +83,7 @@ function Assert-SymmetricKeyEncryptionLevel { [string]$Instance, [string]$Database ) - $query = " - SELECT name, - algorithm_desc - FROM sys.symmetric_keys - WHERE algorithm_desc NOT IN ('AES_128','AES_192','AES_256'); - " - Get-DbaDbEncryption (Get-DbaDbEncryption -SqlInstance . -Database master | Where-Object Encryption -eq "Asymmetric Key") | Where-Object EncryptionAlgrothim - $Actual = Get-Database -Instance $instance -Requiredinfo Name - $Actual | Should -Contain $expecteddb -Because "We expect $expecteddb to be on $Instance" + @(Get-DbaDbEncryption -SqlInstance $Instance -Database $Database | Where-Object {$_.Encryption -eq "Asymmetric Key" -and $_.EncryptionAlgrothim -notin "AES_128","AES_192","AES_256"}).Count | Should -Be 0 -Because "Asymmetric keys should have an encryption algrothim of at least AES_128" } # SIG # Begin signature block # MIINEAYJKoZIhvcNAQcCoIINATCCDP0CAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB From c2d6477379586d120d943d35372ad1d9646a3624 Mon Sep 17 00:00:00 2001 From: Tracy Boggiano Date: Tue, 31 Dec 2019 11:08:52 -0500 Subject: [PATCH 07/61] fix spelling errors --- checks/Database.Tests.ps1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/checks/Database.Tests.ps1 b/checks/Database.Tests.ps1 index 6a29b67a..914b1c5d 100644 --- a/checks/Database.Tests.ps1 +++ b/checks/Database.Tests.ps1 @@ -958,8 +958,8 @@ $ExcludedDatabases += $ExcludeDatabase } } - Describe "AsymmetricKeySize" -Tags AssymetricKeySize, CIS, $filename { - $skip = Get-DbcConfigValue skip.security.assymetrickeysize + Describe "AsymmetricKeySize" -Tags AsymmetricKeySize, CIS, $filename { + $skip = Get-DbcConfigValue skip.security.asymmetrickeysize $ExcludedDatabases += "master", "tempdb", "msdb" if ($NotContactable -contains $psitem) { Context "Testing Asymmetric Key Size is 2048 or higher on $psitem" { From 2c5b76249e33ce723b0dae5a8be3b730c10b486d Mon Sep 17 00:00:00 2001 From: Tracy Boggiano Date: Tue, 31 Dec 2019 14:38:13 -0500 Subject: [PATCH 08/61] CIS Test for SQL Agent proxies publix permissions --- checks/Instance.Tests.ps1 | 18 +++++++++ internal/assertions/Instance.Assertions.ps1 | 37 +++++++++++++++++++ .../configurations/DbcCheckDescriptions.json | 4 ++ internal/configurations/configuration.ps1 | 1 + 4 files changed, 60 insertions(+) diff --git a/checks/Instance.Tests.ps1 b/checks/Instance.Tests.ps1 index fa3c3fe4..3e06dc9e 100644 --- a/checks/Instance.Tests.ps1 +++ b/checks/Instance.Tests.ps1 @@ -943,6 +943,24 @@ $Tags = Get-CheckInformation -Check $Check -Group Instance -AllChecks $AllChecks } } } + + Describe "SqlAgentProxiesNoPublicRole" -Tags SqlAgentProxiesNoPublicRole, Security, CIS, Medium, $filename { + $skip = Get-DbcConfigValue skip.security.sqlagentproxiesnopublicrole + if ($NotContactable -contains $psitem) { + Context "Testing to see if the public role has access to the SQL Agent proxies on $psitem" { + It "Can't Connect to $Psitem" -Skip:$skip { + $false | Should -BeTrue -Because "The instance should be available to be connected to!" + } + } + } + else { + Context "Testing to see if the public role has access to the SQL Agent proxies on $psitem" { + It "The public role should not have access to the SQL Agent Proxies on $psitem" -Skip:$skip { + Assert-SqlAgentProxiesNoPublicRole -AllInstanceInfo $AllInstanceInfo + } + } + } + } } Describe "SQL Browser Service" -Tags SqlBrowserServiceAccount, ServiceAccount, High, $filename { diff --git a/internal/assertions/Instance.Assertions.ps1 b/internal/assertions/Instance.Assertions.ps1 index 9972a5ce..349e541d 100644 --- a/internal/assertions/Instance.Assertions.ps1 +++ b/internal/assertions/Instance.Assertions.ps1 @@ -382,6 +382,37 @@ function Get-AllInstanceInfo { } } } + + 'SqlAgentProxiesNoPublicRole' { + if ($There) { + try { + $query = " + SELECT count(*) [Count] + FROM dbo.sysproxylogin spl + JOIN sys.database_principals dp ON dp.sid = spl.sid + JOIN dbo.sysproxies sp ON sp.proxy_id = spl.proxy_id + WHERE principal_id = USER_ID('public'); + " + $results = Invoke-DbaQuery -SqlInstance $Instance -Database "msdb" -Query $query + + $SqlAgentProxiesNoPublicRole = [pscustomobject] @{ + Count = $results.Count + } + } + catch { + $There = $false + $SqlAgentProxiesNoPublicRole = [pscustomobject] @{ + Count = 'We Could not Connect to $Instance' + } + } + } + else { + $There = $false + $SqlAgentProxiesNoPublicRole = [pscustomobject] @{ + Count = 'We Could not Connect to $Instance' + } + } + } Default {} } [PSCustomObject]@{ @@ -396,6 +427,7 @@ function Get-AllInstanceInfo { SaExist = $SaExist SaDisabled = $SaDisabled EngineService = $EngineService + SqlAgentProxiesNoPublicRole = $SqlAgentProxiesNoPublicRole } } @@ -587,6 +619,11 @@ function Assert-SaExist { $AllInstanceInfo.SaExist.Exist | Should -Be $false -Because "We expected no login to exist with the name sa" } +function Assert-SqlAgentProxiesNoPublicRole { + Param($AllInstanceInfo) + $AllInstanceInfo.SqlAgentProxiesNoPublicRole.Count | Should -Be 0 -Because "We expected the public role to not have access to any SQL Agent proxies" +} + # SIG # Begin signature block # MIINEAYJKoZIhvcNAQcCoIINATCCDP0CAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB # gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR diff --git a/internal/configurations/DbcCheckDescriptions.json b/internal/configurations/DbcCheckDescriptions.json index 44194c7a..654b559e 100644 --- a/internal/configurations/DbcCheckDescriptions.json +++ b/internal/configurations/DbcCheckDescriptions.json @@ -450,5 +450,9 @@ { "UniqueTag": "ContainedDBAutoClose", "Description": "Tests that each contained database has AUTO CLOSE disabled." + }, + { + "UniqueTag": "SqlAgentProxiesNoPublicRole", + "Description": "Tests that the public role does not have access to SQL Agent Proxies." } ] diff --git a/internal/configurations/configuration.ps1 b/internal/configurations/configuration.ps1 index 9e921638..6fbf7b78 100644 --- a/internal/configurations/configuration.ps1 +++ b/internal/configurations/configuration.ps1 @@ -241,6 +241,7 @@ Set-PSFConfig -Module dbachecks -Name skip.instance.latestbuild -Validation bool Set-PSFConfig -Module dbachecks -Name skip.security.sadisabled -Validation bool -Value $true -Initialize -Description "Skip the check for if the sa login is disabled" Set-PSFConfig -Module dbachecks -Name skip.security.saexist -Validation bool -Value $true -Initialize -Description "Skip teh check for a login named sa does not exist" Set-PSFConfig -Module dbachecks -Name skip.security.containedbautoclose -Validation bool -Value $true -Initialize -Description "Skips the scan for contained databases should have auto close enabled" +Set-PSFConfig -Module dbachecks -Name skip.security.sqlagentproxiesnopublicrole -Validation bool -Value $true -Initialize -Description "Skips the scan for if the public role has access to SQL Agent proxies" #agent Set-PSFConfig -Module dbachecks -Name agent.dbaoperatorname -Value $null -Initialize -Description "Name of the DBA Operator in SQL Agent" From fbf1cc4a87dd756c1579e5aa82c8d6e87aeb55e9 Mon Sep 17 00:00:00 2001 From: Tracy Boggiano Date: Thu, 2 Jan 2020 08:30:31 -0500 Subject: [PATCH 09/61] save work --- checks/Database.Tests.ps1 | 20 +++++++++++++++++++ internal/assertions/Database.Assertions.ps1 | 15 ++++++++++++++ .../configurations/DbcCheckDescriptions.json | 6 +++++- internal/configurations/configuration.ps1 | 1 + 4 files changed, 41 insertions(+), 1 deletion(-) diff --git a/checks/Database.Tests.ps1 b/checks/Database.Tests.ps1 index 1580e4c4..216de6e5 100644 --- a/checks/Database.Tests.ps1 +++ b/checks/Database.Tests.ps1 @@ -957,6 +957,26 @@ $ExcludedDatabases += $ExcludeDatabase } } } + + Describe "CLR Assemblies SAFE_ACCESS" -Tags CLRAssembliesSafe, CIS, $filename { + $skip = Get-DbcConfigValue skip.security.clrassembliessafe + if ($NotContactable -contains $psitem) { + Context "Testing that all user-defined CLR assemblies are set to SAFE_ACCESS on $psitem" { + It "Can't Connect to $Psitem" { + $true | Should -BeFalse -Because "The instance should be available to be connected to!" + } + } + } + else { + Context "Testing that all user-defined CLR assemblies are set to SAFE_ACCESS on $psitem" { + @($InstanceSMO.Databases.Where{($(if ($Database) {$PsItem.Name -in $Database}else {$ExcludedDatabases -notcontains $PsItem.Name}))}).ForEach{ + It "$($psitem.Name) on $($psitem.Parent.Name) user-defined CLR assemblies are set to SAFE_ACCESS" { + Assert-CLRAssembliesSafe -Instance $instance -Database $psitem + } + } + } + } + } } Set-PSFConfig -Module dbachecks -Name global.notcontactable -Value $NotContactable diff --git a/internal/assertions/Database.Assertions.ps1 b/internal/assertions/Database.Assertions.ps1 index fd1b3686..f4f2f8be 100644 --- a/internal/assertions/Database.Assertions.ps1 +++ b/internal/assertions/Database.Assertions.ps1 @@ -69,6 +69,21 @@ function Assert-DatabaseExists { $Actual = Get-Database -Instance $instance -Requiredinfo Name $Actual | Should -Contain $expecteddb -Because "We expect $expecteddb to be on $Instance" } + +function Assert-CLRAssembliesSafe { + Param ( + [string]$Instance, + [string]$Database + ) + $query = " + SELECT name + FROM sys.assemblies + WHERE is_user_defined = 1 + AND permission_set_desc <> 'SAFE_ACCESS'; + " + @(Invoke-DbaQuery -SqlInstance $Instance -Database $Database -Query $query).Count | Should -Be 0 -Because "We expected all user-defined CLR assemblies to have SAFE_ACCESS" +} + # SIG # Begin signature block # MIINEAYJKoZIhvcNAQcCoIINATCCDP0CAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB # gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR diff --git a/internal/configurations/DbcCheckDescriptions.json b/internal/configurations/DbcCheckDescriptions.json index 44194c7a..1b4cc794 100644 --- a/internal/configurations/DbcCheckDescriptions.json +++ b/internal/configurations/DbcCheckDescriptions.json @@ -450,5 +450,9 @@ { "UniqueTag": "ContainedDBAutoClose", "Description": "Tests that each contained database has AUTO CLOSE disabled." + }, + { + "UniqueTag": "CLRAssembliesSafe", + "Description": "Tests that CLR assembly permissions are set to SAFE_ACCESS." } - ] + ] \ No newline at end of file diff --git a/internal/configurations/configuration.ps1 b/internal/configurations/configuration.ps1 index 9e921638..498bff57 100644 --- a/internal/configurations/configuration.ps1 +++ b/internal/configurations/configuration.ps1 @@ -241,6 +241,7 @@ Set-PSFConfig -Module dbachecks -Name skip.instance.latestbuild -Validation bool Set-PSFConfig -Module dbachecks -Name skip.security.sadisabled -Validation bool -Value $true -Initialize -Description "Skip the check for if the sa login is disabled" Set-PSFConfig -Module dbachecks -Name skip.security.saexist -Validation bool -Value $true -Initialize -Description "Skip teh check for a login named sa does not exist" Set-PSFConfig -Module dbachecks -Name skip.security.containedbautoclose -Validation bool -Value $true -Initialize -Description "Skips the scan for contained databases should have auto close enabled" +Set-PSFConfig -Module dbachecks -Name skip.security.clrassembliessafe -Validation bool -Value $true -Initialize -Description "Skips the scan for if CLR Assemblies are set to SAFE_ACCESS" #agent Set-PSFConfig -Module dbachecks -Name agent.dbaoperatorname -Value $null -Initialize -Description "Name of the DBA Operator in SQL Agent" From f4ba24c12084a2bedb48617fb21bc3725118f319 Mon Sep 17 00:00:00 2001 From: Tracy Boggiano Date: Thu, 2 Jan 2020 08:37:58 -0500 Subject: [PATCH 10/61] CLR SAFE_ACCESS --- checks/Database.Tests.ps1 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/checks/Database.Tests.ps1 b/checks/Database.Tests.ps1 index 216de6e5..78f15957 100644 --- a/checks/Database.Tests.ps1 +++ b/checks/Database.Tests.ps1 @@ -969,9 +969,10 @@ $ExcludedDatabases += $ExcludeDatabase } else { Context "Testing that all user-defined CLR assemblies are set to SAFE_ACCESS on $psitem" { + $instance = $psitem @($InstanceSMO.Databases.Where{($(if ($Database) {$PsItem.Name -in $Database}else {$ExcludedDatabases -notcontains $PsItem.Name}))}).ForEach{ It "$($psitem.Name) on $($psitem.Parent.Name) user-defined CLR assemblies are set to SAFE_ACCESS" { - Assert-CLRAssembliesSafe -Instance $instance -Database $psitem + Assert-CLRAssembliesSafe -Instance $instance -Database $psitem.Name } } } From 2dc058a6219ddd6e5c5f2d08fdd722df0cc11e20 Mon Sep 17 00:00:00 2001 From: Tracy Boggiano Date: Fri, 3 Jan 2020 13:44:50 -0500 Subject: [PATCH 11/61] CIS tests for if service accounts are local admins --- checks/Instance.Tests.ps1 | 54 +++++++++ internal/assertions/Instance.Assertions.ps1 | 105 ++++++++++++++++++ .../configurations/DbcCheckDescriptions.json | 12 ++ internal/configurations/configuration.ps1 | 3 + 4 files changed, 174 insertions(+) diff --git a/checks/Instance.Tests.ps1 b/checks/Instance.Tests.ps1 index fa3c3fe4..4d09feaa 100644 --- a/checks/Instance.Tests.ps1 +++ b/checks/Instance.Tests.ps1 @@ -943,6 +943,60 @@ $Tags = Get-CheckInformation -Check $Check -Group Instance -AllChecks $AllChecks } } } + + Describe "SQL Engine Service Admin" -Tags EngineServiceAdmin, Security, CIS, Medium, $filename { + $skip = Get-DbcConfigValue skip.security.EngineServiceAdmin + if ($NotContactable -contains $psitem) { + Context "Testing whether SQL Engine account is a local adminstrator on $psitem" { + It "Can't Connect to $Psitem" -Skip:$skip { + $false | Should -BeTrue -Because "The instance should be available to be connected to!" + } + } + } + else { + Context "Testing whether SQL Engine account is a local adminstrator on $psitem" { + It "The SQL Engine service account should not be a local administrator on $psitem" -Skip:$skip { + Assert-EngineServiceAdmin -AllInstanceInfo $AllInstanceInfo + } + } + } + } + + Describe "SQL Agent Service Admin" -Tags AgentServiceAdmin, Security, CIS, Medium, $filename { + $skip = Get-DbcConfigValue skip.security.AgentServiceAdmin + if ($NotContactable -contains $psitem) { + Context "Testing whether SQL Agent account is a local adminstrator on $psitem" { + It "Can't Connect to $Psitem" -Skip:$skip { + $false | Should -BeTrue -Because "The instance should be available to be connected to!" + } + } + } + else { + Context "Testing whether SQL Agent account is a local adminstrator on $psitem" { + It "The SQL Agent service account should not be a local administrator on $psitem" -Skip:$skip { + Assert-AgentServiceAdmin -AllInstanceInfo $AllInstanceInfo + } + } + } + } + + Describe "SQL Full Text Service Admin" -Tags FullTextServiceAdmin, Security, CIS, Medium, $filename { + $skip = Get-DbcConfigValue skip.security.FullTextServiceAdmin + if ($NotContactable -contains $psitem) { + Context "Testing whether SQL Full Text account is a local adminstrator on $psitem" { + It "Can't Connect to $Psitem" -Skip:$skip { + $false | Should -BeTrue -Because "The instance should be available to be connected to!" + } + } + } + else { + Context "Testing whether SQL Full Text account is a local adminstrator on $psitem" { + It "The SQL Full Text service account should not be a local administrator on $psitem" -Skip:$skip { + Assert-FullTextServiceAdmin -AllInstanceInfo $AllInstanceInfo + } + } + } + } } Describe "SQL Browser Service" -Tags SqlBrowserServiceAccount, ServiceAccount, High, $filename { diff --git a/internal/assertions/Instance.Assertions.ps1 b/internal/assertions/Instance.Assertions.ps1 index 9972a5ce..437d89cc 100644 --- a/internal/assertions/Instance.Assertions.ps1 +++ b/internal/assertions/Instance.Assertions.ps1 @@ -382,6 +382,93 @@ function Get-AllInstanceInfo { } } } + + 'EngineServiceAdmin' { + if ($There) { + try { + $ComputerName , $InstanceName = $Instance.Name.Split('\') + if ($null -eq $InstanceName) { + $InstanceName = 'MSSQLSERVER' + } + $SqlEngineService = Get-DbaService -ComputerName $ComputerName -InstanceName $instanceName -Type Engine -ErrorAction SilentlyContinue + $LocalAdmins = Invoke-Command -ComputerName $ComputerName -ScriptBlock { Get-LocalGroupMember -Group "Administrators" } -ErrorAction SilentlyContinue + + $EngineServiceAdmin = [pscustomobject] @{ + Exist = $localAdmins.Name.Contains($SqlEngineService.StartName) + } + } + catch { + $There = $false + $EngineServiceAdmin = [pscustomobject] @{ + Exist = 'We Could not Connect to $Instance $ComputerName , $InstanceName from catch' + } + } + } + else { + $There = $false + $EngineServiceAdmin = [pscustomobject] @{ + Exist = 'We Could not Connect to $Instance' + } + } + } + + 'AgentServiceAdmin' { + if ($There) { + try { + $ComputerName , $InstanceName = $Instance.Name.Split('\') + if ($null -eq $InstanceName) { + $InstanceName = 'MSSQLSERVER' + } + $SqlAgentService = Get-DbaService -ComputerName $ComputerName -InstanceName $instanceName -Type Agent -ErrorAction SilentlyContinue + $LocalAdmins = Invoke-Command -ComputerName $ComputerName -ScriptBlock { Get-LocalGroupMember -Group "Administrators" } -ErrorAction SilentlyContinue + + $AgentServiceAdmin = [pscustomobject] @{ + Exist = $localAdmins.Name.Contains($SqlAgentService.StartName) + } + } + catch { + $There = $false + $AgentServiceAdmin = [pscustomobject] @{ + Exist = 'We Could not Connect to $Instance $ComputerName , $InstanceName from catch' + } + } + } + else { + $There = $false + $AgentServiceAdmin = [pscustomobject] @{ + Exist = 'We Could not Connect to $Instance' + } + } + } + + 'FullTextServiceAdmin' { + if ($There) { + try { + $ComputerName , $InstanceName = $Instance.Name.Split('\') + if ($null -eq $InstanceName) { + $InstanceName = 'MSSQLSERVER' + } + $SqlFullTextService = Get-DbaService -ComputerName $ComputerName -InstanceName $instanceName -Type FullText -ErrorAction SilentlyContinue + $LocalAdmins = Invoke-Command -ComputerName $ComputerName -ScriptBlock { Get-LocalGroupMember -Group "Administrators" } -ErrorAction SilentlyContinue + + $FullTextServiceAdmin = [pscustomobject] @{ + Exist = $localAdmins.Name.Contains($SqlFullTextService.StartName) + } + } + catch { + $There = $false + $FullTextServiceAdmin = [pscustomobject] @{ + Exist = 'We Could not Connect to $Instance $ComputerName , $InstanceName from catch' + } + } + } + else { + $There = $false + $FullTextServiceAdmin = [pscustomobject] @{ + Exist = 'We Could not Connect to $Instance' + } + } + } Default {} } [PSCustomObject]@{ @@ -396,6 +483,9 @@ function Get-AllInstanceInfo { SaExist = $SaExist SaDisabled = $SaDisabled EngineService = $EngineService + EngineServiceAdmin = $EngineServiceAdmin + AgentServiceAdmin = $AgentServiceAdmin + FullTextServiceAdmin = $FullTextServiceAdmin } } @@ -587,6 +677,21 @@ function Assert-SaExist { $AllInstanceInfo.SaExist.Exist | Should -Be $false -Because "We expected no login to exist with the name sa" } +function Assert-AgentServiceAdmin { + Param($AllInstanceInfo) + $AllInstanceInfo.AgentServiceAdmin.Exist | Should -Be $false -Because "We expected the service account for the SQL Agent to not be a local administrator" +} + +function Assert-EngineServiceAdmin { + Param($AllInstanceInfo) + $AllInstanceInfo.EngineServiceAdmin.Exist | Should -Be $false -Because "We expected the service account for the SQL Engine to not be a local administrator" +} + +function Assert-FullTextServiceAdmin { + Param($AllInstanceInfo) + $AllInstanceInfo.FullTextServiceAdmin.Exist | Should -Be $false -Because "We expected the service account for the SQL Full Text to not be a local administrator" +} + # SIG # Begin signature block # MIINEAYJKoZIhvcNAQcCoIINATCCDP0CAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB # gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR diff --git a/internal/configurations/DbcCheckDescriptions.json b/internal/configurations/DbcCheckDescriptions.json index 44194c7a..56fe195c 100644 --- a/internal/configurations/DbcCheckDescriptions.json +++ b/internal/configurations/DbcCheckDescriptions.json @@ -450,5 +450,17 @@ { "UniqueTag": "ContainedDBAutoClose", "Description": "Tests that each contained database has AUTO CLOSE disabled." + }, + { + "UniqueTag": "EngineServiceAdmin", + "Description": "Tests that the SQL Engine service account is not a local administrator." + }, + { + "UniqueTag": "AgentServiceAdmin", + "Description": "Tests that the SQL Agent service account is not a local administrator." + }, + { + "UniqueTag": "FullTextServiceAdmin", + "Description": "Tests that the SQL Full Text service account is not a local administrator." } ] diff --git a/internal/configurations/configuration.ps1 b/internal/configurations/configuration.ps1 index 9e921638..77a6e4b7 100644 --- a/internal/configurations/configuration.ps1 +++ b/internal/configurations/configuration.ps1 @@ -241,6 +241,9 @@ Set-PSFConfig -Module dbachecks -Name skip.instance.latestbuild -Validation bool Set-PSFConfig -Module dbachecks -Name skip.security.sadisabled -Validation bool -Value $true -Initialize -Description "Skip the check for if the sa login is disabled" Set-PSFConfig -Module dbachecks -Name skip.security.saexist -Validation bool -Value $true -Initialize -Description "Skip teh check for a login named sa does not exist" Set-PSFConfig -Module dbachecks -Name skip.security.containedbautoclose -Validation bool -Value $true -Initialize -Description "Skips the scan for contained databases should have auto close enabled" +Set-PSFConfig -Module dbachecks -Name skip.security.engineserviceadmin -Validation bool -Value $true -Initialize -Description "Skips the scan for contained databases should have auto close enabled" +Set-PSFConfig -Module dbachecks -Name skip.security.agentserviceadmin -Validation bool -Value $true -Initialize -Description "Skips the scan for contained databases should have auto close enabled" +Set-PSFConfig -Module dbachecks -Name skip.security.fulltextserviceadmin -Validation bool -Value $true -Initialize -Description "Skips the scan for contained databases should have auto close enabled" #agent Set-PSFConfig -Module dbachecks -Name agent.dbaoperatorname -Value $null -Initialize -Description "Name of the DBA Operator in SQL Agent" From e3bb67cda935458445295008a8c429e54782b747 Mon Sep 17 00:00:00 2001 From: Rob Sewell Date: Thu, 9 Jan 2020 13:59:19 +0000 Subject: [PATCH 12/61] sily rogue v --- internal/configurations/DbcCheckDescriptions.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/configurations/DbcCheckDescriptions.json b/internal/configurations/DbcCheckDescriptions.json index 1d5f1d6f..5b8b1a0d 100644 --- a/internal/configurations/DbcCheckDescriptions.json +++ b/internal/configurations/DbcCheckDescriptions.json @@ -169,7 +169,7 @@ }, { "UniqueTag": "ClusterHealth", - "Description": "Runs a suite of tests against an Availability Group on a Windows cluster to ensure that everything is as it should be. Tests cluster resources are online, cluster nodes are up, at least one IP Address for the AG listener is available, that each replica and listener are pingable (listener ping check can be skipped), can be connected to via T-SQL, have the correct domain name and TCP port, that each replica is synchronised/ing, is connected, is not in an unknown state, each database is synchronised/ing, failover ready and joined to the domain and that the Always On Health Extended Event sessions are running and set to auto-start" + "Description": "Runs a suite of tests against an Availability Group on a Windows cluster to ensure that everything is as it should be. Tests cluster resources are online, cluster nodes are up, at least one IP Address for the AG listener is available, that each replica and listener are pingable (listener ping check can be skipped), can be connected to via T-SQL, have the correct domain name and TCP port, that each replica is synchronized/ing, is connected, is not in an unknown state, each database is synchronized/ing, failover ready and joined to the domain and that the Always On Health Extended Event sessions are running and set to auto-start" }, { "UniqueTag": "SqlEngineServiceAccount", @@ -457,7 +457,7 @@ }, { "UniqueTag": "AsymmetricKeySize", - "Description": "Tests that Asymmetric Key Sizes are at least 2048 in non-system databases."v + "Description": "Tests that Asymmetric Key Sizes are at least 2048 in non-system databases." }, { "UniqueTag": "LoginAuditFailed", From 11e1771453cd7eb9ce98452bdcca5edefe69c608 Mon Sep 17 00:00:00 2001 From: Rob Sewell Date: Thu, 9 Jan 2020 15:31:33 +0000 Subject: [PATCH 13/61] need to work with Ubuntu as well --- PSScriptAnalyzerSettings.psd1 | 1 + internal/assertions/Instance.Assertions.ps1 | 102 ++++++++++++-------- 2 files changed, 63 insertions(+), 40 deletions(-) diff --git a/PSScriptAnalyzerSettings.psd1 b/PSScriptAnalyzerSettings.psd1 index 0350b9ea..cdbc5dc4 100644 --- a/PSScriptAnalyzerSettings.psd1 +++ b/PSScriptAnalyzerSettings.psd1 @@ -25,6 +25,7 @@ 'InModuleScope' #Because Pester! 'Mock' #Because Pester! 'Assert-MockCalled' #Because Pester! + 'Get-LocalGroupMember' # Because we handle it ) } PSUseCompatibleSyntax = @{ diff --git a/internal/assertions/Instance.Assertions.ps1 b/internal/assertions/Instance.Assertions.ps1 index 6bc19efd..e06afbbd 100644 --- a/internal/assertions/Instance.Assertions.ps1 +++ b/internal/assertions/Instance.Assertions.ps1 @@ -513,22 +513,29 @@ function Get-AllInstanceInfo { } 'EngineServiceAdmin' { if ($There) { - try { - $ComputerName , $InstanceName = $Instance.Name.Split('\') - if ($null -eq $InstanceName) { - $InstanceName = 'MSSQLSERVER' - } - $SqlEngineService = Get-DbaService -ComputerName $ComputerName -InstanceName $instanceName -Type Engine -ErrorAction SilentlyContinue - $LocalAdmins = Invoke-Command -ComputerName $ComputerName -ScriptBlock { Get-LocalGroupMember -Group "Administrators" } -ErrorAction SilentlyContinue - + if ($IsLinux) { $EngineServiceAdmin = [pscustomobject] @{ - Exist = $localAdmins.Name.Contains($SqlEngineService.StartName) + Exist = 'We Cant Check running on Linux' } } - catch { - $There = $false - $EngineServiceAdmin = [pscustomobject] @{ - Exist = 'We Could not Connect to $Instance $ComputerName , $InstanceName from catch' + else { + try { + $ComputerName , $InstanceName = $Instance.Name.Split('\') + if ($null -eq $InstanceName) { + $InstanceName = 'MSSQLSERVER' + } + $SqlEngineService = Get-DbaService -ComputerName $ComputerName -InstanceName $instanceName -Type Engine -ErrorAction SilentlyContinue + $LocalAdmins = Invoke-Command -ComputerName $ComputerName -ScriptBlock { Get-LocalGroupMember -Group "Administrators" } -ErrorAction SilentlyContinue + + $EngineServiceAdmin = [pscustomobject] @{ + Exist = $localAdmins.Name.Contains($SqlEngineService.StartName) + } + } + catch { + $There = $false + $EngineServiceAdmin = [pscustomobject] @{ + Exist = 'We Could not Connect to $Instance $ComputerName , $InstanceName from catch' + } } } } @@ -538,26 +545,33 @@ function Get-AllInstanceInfo { Exist = 'We Could not Connect to $Instance' } } - } + } 'AgentServiceAdmin' { if ($There) { - try { - $ComputerName , $InstanceName = $Instance.Name.Split('\') - if ($null -eq $InstanceName) { - $InstanceName = 'MSSQLSERVER' - } - $SqlAgentService = Get-DbaService -ComputerName $ComputerName -InstanceName $instanceName -Type Agent -ErrorAction SilentlyContinue - $LocalAdmins = Invoke-Command -ComputerName $ComputerName -ScriptBlock { Get-LocalGroupMember -Group "Administrators" } -ErrorAction SilentlyContinue - + if ($IsLinux) { $AgentServiceAdmin = [pscustomobject] @{ - Exist = $localAdmins.Name.Contains($SqlAgentService.StartName) + Exist = 'We Cant Check running on Linux' } } - catch { - $There = $false - $AgentServiceAdmin = [pscustomobject] @{ - Exist = 'We Could not Connect to $Instance $ComputerName , $InstanceName from catch' + else { + try { + $ComputerName , $InstanceName = $Instance.Name.Split('\') + if ($null -eq $InstanceName) { + $InstanceName = 'MSSQLSERVER' + } + $SqlAgentService = Get-DbaService -ComputerName $ComputerName -InstanceName $instanceName -Type Agent -ErrorAction SilentlyContinue + $LocalAdmins = Invoke-Command -ComputerName $ComputerName -ScriptBlock { Get-LocalGroupMember -Group "Administrators" } -ErrorAction SilentlyContinue + + $AgentServiceAdmin = [pscustomobject] @{ + Exist = $localAdmins.Name.Contains($SqlAgentService.StartName) + } + } + catch { + $There = $false + $AgentServiceAdmin = [pscustomobject] @{ + Exist = 'We Could not Connect to $Instance $ComputerName , $InstanceName from catch' + } } } } @@ -571,24 +585,32 @@ function Get-AllInstanceInfo { 'FullTextServiceAdmin' { if ($There) { - try { - $ComputerName , $InstanceName = $Instance.Name.Split('\') - if ($null -eq $InstanceName) { - $InstanceName = 'MSSQLSERVER' - } - $SqlFullTextService = Get-DbaService -ComputerName $ComputerName -InstanceName $instanceName -Type FullText -ErrorAction SilentlyContinue - $LocalAdmins = Invoke-Command -ComputerName $ComputerName -ScriptBlock { Get-LocalGroupMember -Group "Administrators" } -ErrorAction SilentlyContinue - + if ($IsLinux) { $FullTextServiceAdmin = [pscustomobject] @{ - Exist = $localAdmins.Name.Contains($SqlFullTextService.StartName) + Exist = 'We Cant Check running on Linux' } } - catch { - $There = $false - $FullTextServiceAdmin = [pscustomobject] @{ - Exist = 'We Could not Connect to $Instance $ComputerName , $InstanceName from catch' + else { + try { + $ComputerName , $InstanceName = $Instance.Name.Split('\') + if ($null -eq $InstanceName) { + $InstanceName = 'MSSQLSERVER' + } + $SqlFullTextService = Get-DbaService -ComputerName $ComputerName -InstanceName $instanceName -Type FullText -ErrorAction SilentlyContinue + $LocalAdmins = Invoke-Command -ComputerName $ComputerName -ScriptBlock { Get-LocalGroupMember -Group "Administrators" } -ErrorAction SilentlyContinue + + $FullTextServiceAdmin = [pscustomobject] @{ + Exist = $localAdmins.Name.Contains($SqlFullTextService.StartName) + } + } + catch { + $There = $false + $FullTextServiceAdmin = [pscustomobject] @{ + Exist = 'We Could not Connect to $Instance $ComputerName , $InstanceName from catch' + } } } + } else { $There = $false From b5b562ff0488dbd6576e5dffe451ed2d18022748 Mon Sep 17 00:00:00 2001 From: Rob Sewell Date: Thu, 9 Jan 2020 16:06:40 +0000 Subject: [PATCH 14/61] whitspace --- checks/Instance.Tests.ps1 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/checks/Instance.Tests.ps1 b/checks/Instance.Tests.ps1 index 75b8406f..9965c242 100644 --- a/checks/Instance.Tests.ps1 +++ b/checks/Instance.Tests.ps1 @@ -1027,7 +1027,7 @@ $Tags = Get-CheckInformation -Check $Check -Group Instance -AllChecks $AllChecks else { Context "Testing whether SQL Engine account is a local adminstrator on $psitem" { It "The SQL Engine service account should not be a local administrator on $psitem" -Skip:$skip { - Assert-EngineServiceAdmin -AllInstanceInfo $AllInstanceInfo + Assert-EngineServiceAdmin -AllInstanceInfo $AllInstanceInfo } } } @@ -1045,7 +1045,7 @@ $Tags = Get-CheckInformation -Check $Check -Group Instance -AllChecks $AllChecks else { Context "Testing whether SQL Agent account is a local adminstrator on $psitem" { It "The SQL Agent service account should not be a local administrator on $psitem" -Skip:$skip { - Assert-AgentServiceAdmin -AllInstanceInfo $AllInstanceInfo + Assert-AgentServiceAdmin -AllInstanceInfo $AllInstanceInfo } } } @@ -1063,7 +1063,7 @@ $Tags = Get-CheckInformation -Check $Check -Group Instance -AllChecks $AllChecks else { Context "Testing whether SQL Full Text account is a local adminstrator on $psitem" { It "The SQL Full Text service account should not be a local administrator on $psitem" -Skip:$skip { - Assert-FullTextServiceAdmin -AllInstanceInfo $AllInstanceInfo + Assert-FullTextServiceAdmin -AllInstanceInfo $AllInstanceInfo } } } From 27d61e2047b94adf0b6270548a6988ef646566a3 Mon Sep 17 00:00:00 2001 From: Tracy Boggiano Date: Mon, 13 Jan 2020 13:41:52 -0500 Subject: [PATCH 15/61] Fix descriptions --- internal/configurations/configuration.ps1 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/internal/configurations/configuration.ps1 b/internal/configurations/configuration.ps1 index 5e6c359c..fdb7be71 100644 --- a/internal/configurations/configuration.ps1 +++ b/internal/configurations/configuration.ps1 @@ -239,9 +239,9 @@ Set-PSFConfig -Module dbachecks -Name skip.instance.latestbuild -Validation bool Set-PSFConfig -Module dbachecks -Name skip.security.sadisabled -Validation bool -Value $true -Initialize -Description "Skip the check for if the sa login is disabled" Set-PSFConfig -Module dbachecks -Name skip.security.saexist -Validation bool -Value $true -Initialize -Description "Skip the check for a login named sa does not exist" Set-PSFConfig -Module dbachecks -Name skip.security.containedbautoclose -Validation bool -Value $true -Initialize -Description "Skips the scan for contained databases should have auto close enabled" -Set-PSFConfig -Module dbachecks -Name skip.security.engineserviceadmin -Validation bool -Value $true -Initialize -Description "Skips the scan for contained databases should have auto close enabled" -Set-PSFConfig -Module dbachecks -Name skip.security.agentserviceadmin -Validation bool -Value $true -Initialize -Description "Skips the scan for contained databases should have auto close enabled" -Set-PSFConfig -Module dbachecks -Name skip.security.fulltextserviceadmin -Validation bool -Value $true -Initialize -Description "Skips the scan for contained databases should have auto close enabled" +Set-PSFConfig -Module dbachecks -Name skip.security.engineserviceadmin -Validation bool -Value $true -Initialize -Description "Skips the scan for the SQL Server Engine account is a local administrator" +Set-PSFConfig -Module dbachecks -Name skip.security.agentserviceadmin -Validation bool -Value $true -Initialize -Description "Skips the scan for the SQL Server Agent account is a local administrator" +Set-PSFConfig -Module dbachecks -Name skip.security.fulltextserviceadmin -Validation bool -Value $true -Initialize -Description "Skips the scan for the SQL Server Full Text account is a local administrator" Set-PSFConfig -Module dbachecks -Name skip.security.loginauditlevelfailed -Validation bool -Value $true -Initialize -Description "Skips the scan for if server login level records failed logins" Set-PSFConfig -Module dbachecks -Name skip.security.loginauditlevelsuccessful -Validation bool -Value $true -Initialize -Description "Skips the scan for if server login level records successful and failed logins" Set-PSFConfig -Module dbachecks -Name skip.security.localwindowsgroup -Validation bool -Value $true -Initialize -Description "Skips the scan for if local windows groups have SQL Logins" From 49f8f3556b04d9b02a57cdc4e3e543f0e8c82eab Mon Sep 17 00:00:00 2001 From: Tracy Boggiano Date: Mon, 13 Jan 2020 14:18:04 -0500 Subject: [PATCH 16/61] use new Get-Dba-HideInstance dbatools command to make it easy as pie --- checks/Instance.Tests.ps1 | 2 +- internal/assertions/Instance.Assertions.ps1 | 22 ++++++--------------- 2 files changed, 7 insertions(+), 17 deletions(-) diff --git a/checks/Instance.Tests.ps1 b/checks/Instance.Tests.ps1 index c9fe7735..a2e8df81 100644 --- a/checks/Instance.Tests.ps1 +++ b/checks/Instance.Tests.ps1 @@ -955,7 +955,7 @@ $Tags = Get-CheckInformation -Check $Check -Group Instance -AllChecks $AllChecks } else { Context "Checking the Hide an Instance of SQL Server Database Engine property on $psitem" { - It "The Hide an Instance of SQL Server Database Engine property on SQL Server instance $psitem" -Skip:$skip { + It "The Hide an Instance of SQL Server Database Engine property on SQL Server instance $psitem" { Assert-HideInstance -AllInstanceInfo $AllInstanceInfo } } diff --git a/internal/assertions/Instance.Assertions.ps1 b/internal/assertions/Instance.Assertions.ps1 index 5686d2f3..edff0ad9 100644 --- a/internal/assertions/Instance.Assertions.ps1 +++ b/internal/assertions/Instance.Assertions.ps1 @@ -384,33 +384,23 @@ function Get-AllInstanceInfo { 'HideInstance' { if ($There) { try { - $query = " - DECLARE @getValue INT; - - EXEC master.sys.xp_instance_regread - @rootkey = N'HKEY_LOCAL_MACHINE', - @key = N'SOFTWARE\Microsoft\Microsoft SQL Server\MSSQLServer\SuperSocketNetLib', - @value_name = N'HideInstance', - @value = @getValue OUTPUT; - - SELECT @getValue as Value; - " - $results = Invoke-DbaQuery -SqlInstance $Instance -Query $query + $results = Get-DbaHideInstance -SqlInstance $Instance + $HideInstance = [pscustomobject] @{ - Value = $results.Value + HideInstance = $results.HideInstance } } catch { $There = $false $HideInstance = [pscustomobject] @{ - Value = StartType = 'We Could not Connect to $Instance' + HideInstance = StartType = 'We Could not Connect to $Instance' } } } else { $There = $false $HideInstance = [pscustomobject] @{ - Value = 'We Could not Connect to $Instance' + HideInstance = 'We Could not Connect to $Instance' } } } @@ -622,7 +612,7 @@ function Assert-SaExist { function Assert-HideInstance { Param($AllInstanceInfo) - $AllInstanceInfo.HideInstance.Value | Should -Be 1 -Because "We expected the hide instance proptety to be set to YES (1)" + $AllInstanceInfo.HideInstance.HideInstance | Should -Be $true -Because "We expected the hide instance proptety to be set to $true" } # SIG # Begin signature block From e310d84b3efa78d7250b47994be15eb1d70c6fab Mon Sep 17 00:00:00 2001 From: Tracy Boggiano Date: Mon, 13 Jan 2020 14:40:13 -0500 Subject: [PATCH 17/61] put skip back in --- checks/Instance.Tests.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/checks/Instance.Tests.ps1 b/checks/Instance.Tests.ps1 index bbd421ed..cd0f3f2c 100644 --- a/checks/Instance.Tests.ps1 +++ b/checks/Instance.Tests.ps1 @@ -1026,7 +1026,7 @@ $Tags = Get-CheckInformation -Check $Check -Group Instance -AllChecks $AllChecks } else { Context "Checking the Hide an Instance of SQL Server Database Engine property on $psitem" { - It "The Hide an Instance of SQL Server Database Engine property on SQL Server instance $psitem" { + It "The Hide an Instance of SQL Server Database Engine property on SQL Server instance $psitem" -Skip:$skip { Assert-HideInstance -AllInstanceInfo $AllInstanceInfo } } From 1161cb431303975d0154751fff67fd0d38bc4fe6 Mon Sep 17 00:00:00 2001 From: Tracy Boggiano Date: Mon, 13 Jan 2020 14:48:38 -0500 Subject: [PATCH 18/61] trailing whitespaces --- checks/Instance.Tests.ps1 | 2 +- internal/assertions/Instance.Assertions.ps1 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/checks/Instance.Tests.ps1 b/checks/Instance.Tests.ps1 index cd0f3f2c..205f0ac2 100644 --- a/checks/Instance.Tests.ps1 +++ b/checks/Instance.Tests.ps1 @@ -1027,7 +1027,7 @@ $Tags = Get-CheckInformation -Check $Check -Group Instance -AllChecks $AllChecks else { Context "Checking the Hide an Instance of SQL Server Database Engine property on $psitem" { It "The Hide an Instance of SQL Server Database Engine property on SQL Server instance $psitem" -Skip:$skip { - Assert-HideInstance -AllInstanceInfo $AllInstanceInfo + Assert-HideInstance -AllInstanceInfo $AllInstanceInfo } } } diff --git a/internal/assertions/Instance.Assertions.ps1 b/internal/assertions/Instance.Assertions.ps1 index 385b3e48..c1ecb090 100644 --- a/internal/assertions/Instance.Assertions.ps1 +++ b/internal/assertions/Instance.Assertions.ps1 @@ -515,7 +515,7 @@ function Get-AllInstanceInfo { 'HideInstance' { if ($There) { try { - $results = Get-DbaHideInstance -SqlInstance $Instance + $results = Get-DbaHideInstance -SqlInstance $Instance $HideInstance = [pscustomobject] @{ HideInstance = $results.HideInstance From 1801f3e11e1c8986beaa8fa246d56374a29a27de Mon Sep 17 00:00:00 2001 From: Tracy Boggiano Date: Mon, 13 Jan 2020 14:58:51 -0500 Subject: [PATCH 19/61] trailing whitespaces --- internal/assertions/Instance.Assertions.ps1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/assertions/Instance.Assertions.ps1 b/internal/assertions/Instance.Assertions.ps1 index c1ecb090..f5cd95c3 100644 --- a/internal/assertions/Instance.Assertions.ps1 +++ b/internal/assertions/Instance.Assertions.ps1 @@ -361,7 +361,7 @@ function Get-AllInstanceInfo { catch { $There = $false $EngineService = [pscustomobject] @{ - State = 'We Could not Connect to $Instance $ComputerName , $InstanceName from catch' + State = 'We Could not Connect to $Instance $ComputerName , $InstanceName from catch' StartType = 'We Could not Connect to $Instance $ComputerName , $InstanceName from catch' } } @@ -516,7 +516,7 @@ function Get-AllInstanceInfo { if ($There) { try { $results = Get-DbaHideInstance -SqlInstance $Instance - + $HideInstance = [pscustomobject] @{ HideInstance = $results.HideInstance } From 6e9b9994d6e97bb8a96c2d4dc576a939698b768d Mon Sep 17 00:00:00 2001 From: Tracy Boggiano Date: Tue, 14 Jan 2020 10:35:52 -0500 Subject: [PATCH 20/61] trailing white space --- checks/Instance.Tests.ps1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/checks/Instance.Tests.ps1 b/checks/Instance.Tests.ps1 index 0cd15dbd..69eea219 100644 --- a/checks/Instance.Tests.ps1 +++ b/checks/Instance.Tests.ps1 @@ -1026,8 +1026,8 @@ $Tags = Get-CheckInformation -Check $Check -Group Instance -AllChecks $AllChecks } else { Context "Testing to see if the public role has access to the SQL Agent proxies on $psitem" { - It "The public role should not have access to the SQL Agent Proxies on $psitem" { - Assert-SqlAgentProxiesNoPublicRole -AllInstanceInfo $AllInstanceInfo + It "The public role should not have access to the SQL Agent Proxies on $psitem" -Skip:$skip { + Assert-SqlAgentProxiesNoPublicRole -AllInstanceInfo $AllInstanceInfo } } } From 10bd8dcf76fb49733f6c34de2bdd86402845f9fa Mon Sep 17 00:00:00 2001 From: Tracy Boggiano Date: Wed, 29 Jan 2020 08:14:08 -0500 Subject: [PATCH 21/61] check policy --- checks/Instance.Tests.ps1 | 18 ++++++ internal/assertions/Instance.Assertions.ps1 | 61 ++++++++++++------- .../configurations/DbcCheckDescriptions.json | 6 +- internal/configurations/configuration.ps1 | 2 + workspace.code-workspace | 6 ++ 5 files changed, 69 insertions(+), 24 deletions(-) diff --git a/checks/Instance.Tests.ps1 b/checks/Instance.Tests.ps1 index 4aa57898..ea10c5af 100644 --- a/checks/Instance.Tests.ps1 +++ b/checks/Instance.Tests.ps1 @@ -1014,6 +1014,24 @@ $Tags = Get-CheckInformation -Check $Check -Group Instance -AllChecks $AllChecks } } } + + Describe "Login Check Policy" -Tags LoginCheckPolicy, Security, CIS, Medium, $filename { + $skip = Get-DbcConfigValue skip.security.LoginCheckPolicy + if ($NotContactable -contains $psitem) { + Context "Testing if the CHECK_POLICY is enabled on all logins on $psitem" { + It "Can't Connect to $Psitem" -Skip:$skip { + $false | Should -BeTrue -Because "The instance should be available to be connected to!" + } + } + } + else { + Context "Testing if the CHECK_POLICY is enabled on all logins on $psitem" { + It "All logins should have the CHECK_POLICY option set to ON on $psitem" { + Assert-LoginCheckPolicy -AllInstanceInfo $AllInstanceInfo + } + } + } + } } Describe "SQL Browser Service" -Tags SqlBrowserServiceAccount, ServiceAccount, High, $filename { diff --git a/internal/assertions/Instance.Assertions.ps1 b/internal/assertions/Instance.Assertions.ps1 index 75fe36a5..80a7bd95 100644 --- a/internal/assertions/Instance.Assertions.ps1 +++ b/internal/assertions/Instance.Assertions.ps1 @@ -319,16 +319,8 @@ function Get-AllInstanceInfo { 'SaExist' { if ($There) { try { - $results = Get-DbaLogin -SqlInstance $Instance -Login sa - if ($null -eq $results.Name) { - $Exist = $false - } - else { - $Exist = $true - } - $SaExist = [pscustomobject] @{ - Exist = $Exist + Exist = @(Get-DbaLogin -SqlInstance $Instance -Login sa).Count } } catch { @@ -389,7 +381,7 @@ function Get-AllInstanceInfo { AND NOT (state_desc = 'GRANT' and [permission_name] = 'CONNECT' and class_desc = 'ENDPOINT' and major_id = 5); " $results = Invoke-DbaQuery -SqlInstance $Instance -Query $query - Write-Output $results.RowCount + $PublicRolePermission = [pscustomobject] @{ Count = $results.RowCount } @@ -411,16 +403,8 @@ function Get-AllInstanceInfo { 'BuiltInAdmin' { if ($There) { try { - $results = Get-DbaLogin -SqlInstance $Instance -Login "BUILTIN\Administrators" - if ($null -eq $results.Name) { - $Exist = $false - } - else { - $Exist = $true - } - $BuiltInAdmin = [pscustomobject] @{ - Exist = $Exist + Exist = @(Get-DbaLogin -SqlInstance $Instance -Login "BUILTIN\Administrators").Count } } catch { @@ -511,6 +495,30 @@ function Get-AllInstanceInfo { } } } + + 'LoginCheckPolicy' { + if ($There) { + try { + $LoginCheckPolicy = [pscustomobject] @{ + Count = @(Get-DbaLogin -SQLInstance $instance -ExcludeSystemLogin| Where-Object { $_.PasswordPolicyEnforced -eq "OFF" -and $_.LoginType -eq "SqlLogin" }).Count + } + } + catch { + $There = $false + $LoginCheckPolicy = [pscustomobject] @{ + Count = 'We Could not Connect to $Instance' + } + } + } + else { + $There = $false + $LoginCheckPolicy = [pscustomobject] @{ + Count = 'We Could not Connect to $Instance' + } + } + } + + Default { } } [PSCustomObject]@{ @@ -530,6 +538,7 @@ function Get-AllInstanceInfo { LocalWindowsGroup = $LocalWindowsGroup BuiltInAdmin = $BuiltInAdmin PublicRolePermission = $PublicRolePermission + LoginCheckPolicy = $LoginCheckPolicy } } @@ -656,7 +665,7 @@ function Assert-TraceFlag { function Assert-NotTraceFlag { Param( [string]$SQLInstance, - [int[]]$NotExpectedTraceFlag + [int[]]$NotExpectedTraceFlagA ) if ($null -eq $NotExpectedTraceFlag) { @@ -722,7 +731,7 @@ function Assert-SaDisabled { function Assert-SaExist { Param($AllInstanceInfo) - $AllInstanceInfo.SaExist.Exist | Should -Be $false -Because "We expected no login to exist with the name sa" + $AllInstanceInfo.SaExist.Exist | Should -Be 0 -Because "We expected no login to exist with the name sa" } function Assert-LocalWindowsGroup { @@ -735,7 +744,7 @@ function Assert-PublicRolePermission { } function Assert-BuiltInAdmin { Param($AllInstanceInfo) - $AllInstanceInfo.BuiltInAdmin.Exist | Should -Be $false -Because "We expected no login to exist with the name BUILTIN\Administrators" + $AllInstanceInfo.BuiltInAdmin.Exist | Should -Be 0 -Because "We expected no login to exist with the name BUILTIN\Administrators" } function Assert-LoginAuditSuccessful { @@ -745,8 +754,14 @@ function Assert-LoginAuditSuccessful { function Assert-LoginAuditFailed { Param($AllInstanceInfo) - $AllInstanceInfo.LoginAuditFailed.AuditLevel | Should -BeIn @("Failure", "All") -Because "We expected expected the audit level to be set to capture failed logins" + $AllInstanceInfo.LoginAuditFailed.AuditLevel | Should -BeIn @("Failure", "All") -Because "We expected the audit level to be set to capture failed logins" } + +function Assert-LoginCheckPolicy { + Param($AllInstanceInfo) + $AllInstanceInfo.LoginCheckPolicy.Count | Should -Be 0 -Because "We expected the CHECK_POLICY for the all logins to be enabled" +} + # SIG # Begin signature block # MIINEAYJKoZIhvcNAQcCoIINATCCDP0CAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB # gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR diff --git a/internal/configurations/DbcCheckDescriptions.json b/internal/configurations/DbcCheckDescriptions.json index d5a0ee64..be7db4d2 100644 --- a/internal/configurations/DbcCheckDescriptions.json +++ b/internal/configurations/DbcCheckDescriptions.json @@ -474,5 +474,9 @@ { "UniqueTag": "BuiltInAdmin", "Description": "Tests to see if the BUILTIN\\Administrator login exist." + }, + { + "UniqueTag": "LoginCheckPolicy", + "Description": "Tests to see if CHECK_POLICY property is set for all logins." } - ] + ] \ No newline at end of file diff --git a/internal/configurations/configuration.ps1 b/internal/configurations/configuration.ps1 index 328377f7..e36135e5 100644 --- a/internal/configurations/configuration.ps1 +++ b/internal/configurations/configuration.ps1 @@ -245,6 +245,8 @@ Set-PSFConfig -Module dbachecks -Name skip.security.localwindowsgroup -Validatio Set-PSFConfig -Module dbachecks -Name skip.security.publicrolepermission -Validation bool -Value $true -Initialize -Description "Skips the scan for if the public server role has permissions" Set-PSFConfig -Module dbachecks -Name skip.security.builtinadmin -Validation bool -Value $true -Initialize -Description "Skips the scan for BUILTIN\Administrators login" Set-PSFConfig -Module dbachecks -Name skip.security.guestuserconnect -Validation bool -Value $true -Initialize -Description "Skips the scan for guest user have CONNECT permission" +Set-PSFConfig -Module dbachecks -Name skip.security.LoginCheckPolicy -Validation bool -Value $true -Initialize -Description "Skips the scan for CHECK_POLICY on for all logins" + #agent Set-PSFConfig -Module dbachecks -Name agent.dbaoperatorname -Value $null -Initialize -Description "Name of the DBA Operator in SQL Agent" Set-PSFConfig -Module dbachecks -Name agent.dbaoperatoremail -Value $null -Initialize -Description "Email address of the DBA Operator in SQL Agent" diff --git a/workspace.code-workspace b/workspace.code-workspace index 531fad7e..3815edbd 100644 --- a/workspace.code-workspace +++ b/workspace.code-workspace @@ -2,6 +2,12 @@ "folders": [ { "path": "." + }, + { + "path": "C:\\Github\\dbadisa" + }, + { + "path": "C:\\Github\\dbatools" } ], "settings": { From e28e9256a1e84d56e6c357e9dfbf8bf93464a18a Mon Sep 17 00:00:00 2001 From: Tracy Boggiano Date: Wed, 29 Jan 2020 08:44:24 -0500 Subject: [PATCH 22/61] do not check disabled accounts --- checks/Instance.Tests.ps1 | 2 +- internal/assertions/Instance.Assertions.ps1 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/checks/Instance.Tests.ps1 b/checks/Instance.Tests.ps1 index ea10c5af..efe2cbc0 100644 --- a/checks/Instance.Tests.ps1 +++ b/checks/Instance.Tests.ps1 @@ -1026,7 +1026,7 @@ $Tags = Get-CheckInformation -Check $Check -Group Instance -AllChecks $AllChecks } else { Context "Testing if the CHECK_POLICY is enabled on all logins on $psitem" { - It "All logins should have the CHECK_POLICY option set to ON on $psitem" { + It "All logins should have the CHECK_POLICY option set to ON on $psitem" -Skip:$skip { Assert-LoginCheckPolicy -AllInstanceInfo $AllInstanceInfo } } diff --git a/internal/assertions/Instance.Assertions.ps1 b/internal/assertions/Instance.Assertions.ps1 index 80a7bd95..973446d1 100644 --- a/internal/assertions/Instance.Assertions.ps1 +++ b/internal/assertions/Instance.Assertions.ps1 @@ -500,7 +500,7 @@ function Get-AllInstanceInfo { if ($There) { try { $LoginCheckPolicy = [pscustomobject] @{ - Count = @(Get-DbaLogin -SQLInstance $instance -ExcludeSystemLogin| Where-Object { $_.PasswordPolicyEnforced -eq "OFF" -and $_.LoginType -eq "SqlLogin" }).Count + Count = @(Get-DbaLogin -SQLInstance $instance -ExcludeSystemLogin| Where-Object { $_.PasswordPolicyEnforced -eq "OFF" -and $_.LoginType -eq "SqlLogin" -and $_.IsDisabled -eq $false}).Count } } catch { From cf14b613f94400bd3a3a17b5df9c075e57577ac6 Mon Sep 17 00:00:00 2001 From: Tracy Boggiano Date: Wed, 29 Jan 2020 09:01:29 -0500 Subject: [PATCH 23/61] change to false --- checks/Instance.Tests.ps1 | 18 ++++++++++++ internal/assertions/Instance.Assertions.ps1 | 29 ++++++++++++++++++- .../configurations/DbcCheckDescriptions.json | 4 +++ internal/configurations/configuration.ps1 | 1 + 4 files changed, 51 insertions(+), 1 deletion(-) diff --git a/checks/Instance.Tests.ps1 b/checks/Instance.Tests.ps1 index efe2cbc0..05e6d488 100644 --- a/checks/Instance.Tests.ps1 +++ b/checks/Instance.Tests.ps1 @@ -1032,6 +1032,24 @@ $Tags = Get-CheckInformation -Check $Check -Group Instance -AllChecks $AllChecks } } } + + Describe "Login Password Expiration" -Tags LoginPasswordExpiration, Security, CIS, Medium, $filename { + $skip = Get-DbcConfigValue skip.security.LoginPasswordExpiration + if ($NotContactable -contains $psitem) { + Context "Testing if the login password expiratin is enabeld for sql logins in the sysadmin role $psitem" { + It "Can't Connect to $Psitem" -Skip:$skip { + $false | Should -BeTrue -Because "The instance should be available to be connected to!" + } + } + } + else { + Context "Testing if the login password expiratin is enabeld for sql logins in the sysadmin role on $psitem" { + It "All sql logins should have the password expiration option set to ON in the sysadmin role on $psitem" -Skip:$skip { + Assert-LoginPasswordExpiration -AllInstanceInfo $AllInstanceInfo + } + } + } + } } Describe "SQL Browser Service" -Tags SqlBrowserServiceAccount, ServiceAccount, High, $filename { diff --git a/internal/assertions/Instance.Assertions.ps1 b/internal/assertions/Instance.Assertions.ps1 index 973446d1..11bf5ce9 100644 --- a/internal/assertions/Instance.Assertions.ps1 +++ b/internal/assertions/Instance.Assertions.ps1 @@ -518,7 +518,28 @@ function Get-AllInstanceInfo { } } - + 'LoginPasswordExpiration' { + if ($There) { + try { + $LoginPasswordExpiration = [pscustomobject] @{ + Count = @(Get-DbaLogin -SQLInstance $instance -ExcludeSystemLogin| Where-Object { $_.PasswordPolicyEnforced -eq $false -and $_.LoginType -eq "SqlLogin" -and $_.IsDisabled -eq $false}).Count + } + } + catch { + $There = $false + $LoginPasswordExpiration = [pscustomobject] @{ + Count = 'We Could not Connect to $Instance' + } + } + } + else { + $There = $false + $LoginPasswordExpiration = [pscustomobject] @{ + Count = 'We Could not Connect to $Instance' + } + } + } + Default { } } [PSCustomObject]@{ @@ -539,6 +560,7 @@ function Get-AllInstanceInfo { BuiltInAdmin = $BuiltInAdmin PublicRolePermission = $PublicRolePermission LoginCheckPolicy = $LoginCheckPolicy + LoginPasswordExpiration = $LoginPasswordExpiration } } @@ -762,6 +784,11 @@ function Assert-LoginCheckPolicy { $AllInstanceInfo.LoginCheckPolicy.Count | Should -Be 0 -Because "We expected the CHECK_POLICY for the all logins to be enabled" } +function Assert-LoginPasswordExpiration { + Param($AllInstanceInfo) + $AllInstanceInfo.LoginPasswordExpiration.Count | Should -Be 0 -Because "We expected the password expiration policy to set on all sql logins in the sysadmin role" +} + # SIG # Begin signature block # MIINEAYJKoZIhvcNAQcCoIINATCCDP0CAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB # gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR diff --git a/internal/configurations/DbcCheckDescriptions.json b/internal/configurations/DbcCheckDescriptions.json index be7db4d2..e9270c51 100644 --- a/internal/configurations/DbcCheckDescriptions.json +++ b/internal/configurations/DbcCheckDescriptions.json @@ -478,5 +478,9 @@ { "UniqueTag": "LoginCheckPolicy", "Description": "Tests to see if CHECK_POLICY property is set for all logins." + }, + { + "UniqueTag": "LoginPasswordExpiration", + "Description": "Tests to see if password expiration policy is set for sql logins in sysadmin role." } ] \ No newline at end of file diff --git a/internal/configurations/configuration.ps1 b/internal/configurations/configuration.ps1 index e36135e5..39f01eb6 100644 --- a/internal/configurations/configuration.ps1 +++ b/internal/configurations/configuration.ps1 @@ -246,6 +246,7 @@ Set-PSFConfig -Module dbachecks -Name skip.security.publicrolepermission -Valida Set-PSFConfig -Module dbachecks -Name skip.security.builtinadmin -Validation bool -Value $true -Initialize -Description "Skips the scan for BUILTIN\Administrators login" Set-PSFConfig -Module dbachecks -Name skip.security.guestuserconnect -Validation bool -Value $true -Initialize -Description "Skips the scan for guest user have CONNECT permission" Set-PSFConfig -Module dbachecks -Name skip.security.LoginCheckPolicy -Validation bool -Value $true -Initialize -Description "Skips the scan for CHECK_POLICY on for all logins" +Set-PSFConfig -Module dbachecks -Name skip.security.LoginPasswordExpiration -Validation bool -Value $true -Initialize -Description "Skips the scan for password expiration on for all logins in sysadmin role" #agent Set-PSFConfig -Module dbachecks -Name agent.dbaoperatorname -Value $null -Initialize -Description "Name of the DBA Operator in SQL Agent" From 2bb7e69298cde7223e86938ab0101f8c78dded72 Mon Sep 17 00:00:00 2001 From: Tracy Boggiano Date: Wed, 29 Jan 2020 09:58:24 -0500 Subject: [PATCH 24/61] login tests --- checks/Instance.Tests.ps1 | 22 +++++++- internal/assertions/Instance.Assertions.ps1 | 59 ++++++++++++++++++++- 2 files changed, 77 insertions(+), 4 deletions(-) diff --git a/checks/Instance.Tests.ps1 b/checks/Instance.Tests.ps1 index 05e6d488..01d299e8 100644 --- a/checks/Instance.Tests.ps1 +++ b/checks/Instance.Tests.ps1 @@ -1036,20 +1036,38 @@ $Tags = Get-CheckInformation -Check $Check -Group Instance -AllChecks $AllChecks Describe "Login Password Expiration" -Tags LoginPasswordExpiration, Security, CIS, Medium, $filename { $skip = Get-DbcConfigValue skip.security.LoginPasswordExpiration if ($NotContactable -contains $psitem) { - Context "Testing if the login password expiratin is enabeld for sql logins in the sysadmin role $psitem" { + Context "Testing if the login password expiration is enabled for sql logins in the sysadmin role $psitem" { It "Can't Connect to $Psitem" -Skip:$skip { $false | Should -BeTrue -Because "The instance should be available to be connected to!" } } } else { - Context "Testing if the login password expiratin is enabeld for sql logins in the sysadmin role on $psitem" { + Context "Testing if the login password expiration is enabled for sql logins in the sysadmin role on $psitem" { It "All sql logins should have the password expiration option set to ON in the sysadmin role on $psitem" -Skip:$skip { Assert-LoginPasswordExpiration -AllInstanceInfo $AllInstanceInfo } } } } + + Describe "Login Must Change" -Tags LoginMustChange, Security, CIS, Medium, $filename { + $skip = Get-DbcConfigValue skip.security.LoginMustChange + if ($NotContactable -contains $psitem) { + Context "Testing if the new SQL logins that have not logged have to change their password when they log in on $psitem" { + It "Can't Connect to $Psitem" -Skip:$skip { + $false | Should -BeTrue -Because "The instance should be available to be connected to!" + } + } + } + else { + Context "Testing if the new SQL logins that have not logged have to change their password when they log in on $psitem" { + It "All new sql logins should have the have to change their password when they log in for the first time on $psitem" { + Assert-LoginMustChange -AllInstanceInfo $AllInstanceInfo + } + } + } + } } Describe "SQL Browser Service" -Tags SqlBrowserServiceAccount, ServiceAccount, High, $filename { diff --git a/internal/assertions/Instance.Assertions.ps1 b/internal/assertions/Instance.Assertions.ps1 index 11bf5ce9..fa1d16c8 100644 --- a/internal/assertions/Instance.Assertions.ps1 +++ b/internal/assertions/Instance.Assertions.ps1 @@ -500,7 +500,7 @@ function Get-AllInstanceInfo { if ($There) { try { $LoginCheckPolicy = [pscustomobject] @{ - Count = @(Get-DbaLogin -SQLInstance $instance -ExcludeSystemLogin| Where-Object { $_.PasswordPolicyEnforced -eq "OFF" -and $_.LoginType -eq "SqlLogin" -and $_.IsDisabled -eq $false}).Count + Count = @(Get-DbaLogin -SQLInstance $instance -Type SQL | Where-Object { $_.PasswordPolicyEnforced -eq $false -and $_.IsDisabled -eq $false}).Count } } catch { @@ -521,8 +521,10 @@ function Get-AllInstanceInfo { 'LoginPasswordExpiration' { if ($There) { try { + $role = GetDbaServerRole -SQLInstance $instance -ServerRole "sysadmin" + $LoginPasswordExpiration = [pscustomobject] @{ - Count = @(Get-DbaLogin -SQLInstance $instance -ExcludeSystemLogin| Where-Object { $_.PasswordPolicyEnforced -eq $false -and $_.LoginType -eq "SqlLogin" -and $_.IsDisabled -eq $false}).Count + Count = @(Get-DbaLogin -SQLInstance $instance -Login @($role.Login) -Type SQL | Where-Object { $_.PasswordExpirationEnabled -eq $false -and $_.IsDisabled -eq $false}).Count } } catch { @@ -540,6 +542,52 @@ function Get-AllInstanceInfo { } } + 'LoginPasswordExpiration' { + if ($There) { + try { + $role = GetDbaServerRole -SQLInstance $instance -ServerRole "sysadmin" + + $LoginMustChange = [pscustomobject] @{ + Count = @(Get-DbaLogin -SQLInstance $instance -Login @($role.Login) -Type SQL | Where-Object { $_.IsMustChange -eq $false -and $_.IsDisabled -eq $false -and $null -eq $_LastLogin }).Count + } + } + catch { + $There = $false + $LoginMustChange = [pscustomobject] @{ + Count = 'We Could not Connect to $Instance' + } + } + } + else { + $There = $false + $LoginMustChange = [pscustomobject] @{ + Count = 'We Could not Connect to $Instance' + } + } + } + + 'LoginMustChange' { + if ($There) { + try { + $LoginMustChange = [pscustomobject] @{ + Count = @(Get-DbaLogin -SQLInstance . -Type SQL | Where-Object { $_.MustChangePassword -eq $false -and $_.IsDisabled -eq $false -and $_.LastLogin -eq $null }).Count + } + } + catch { + $There = $false + $LoginMustChange = [pscustomobject] @{ + Count = 'We Could not Connect to $Instance' + } + } + } + else { + $There = $false + $LoginMustChange = [pscustomobject] @{ + Count = 'We Could not Connect to $Instance' + } + } + } + Default { } } [PSCustomObject]@{ @@ -561,6 +609,7 @@ function Get-AllInstanceInfo { PublicRolePermission = $PublicRolePermission LoginCheckPolicy = $LoginCheckPolicy LoginPasswordExpiration = $LoginPasswordExpiration + LoginMustChange = $LoginMustChange } } @@ -789,6 +838,12 @@ function Assert-LoginPasswordExpiration { $AllInstanceInfo.LoginPasswordExpiration.Count | Should -Be 0 -Because "We expected the password expiration policy to set on all sql logins in the sysadmin role" } +function Assert-LoginMustChange { + Param($AllInstanceInfo) + $AllInstanceInfo.LoginMustChange.Count | Should -Be 0 -Because "We expected the all the new sql logins to have change the password on first login" +} + + # SIG # Begin signature block # MIINEAYJKoZIhvcNAQcCoIINATCCDP0CAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB # gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR From 52d7c5daed48732acef18bc688db6c4edebaf010 Mon Sep 17 00:00:00 2001 From: Tracy Boggiano Date: Wed, 29 Jan 2020 10:00:50 -0500 Subject: [PATCH 25/61] move null --- internal/assertions/Instance.Assertions.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/assertions/Instance.Assertions.ps1 b/internal/assertions/Instance.Assertions.ps1 index fa1d16c8..fa528565 100644 --- a/internal/assertions/Instance.Assertions.ps1 +++ b/internal/assertions/Instance.Assertions.ps1 @@ -570,7 +570,7 @@ function Get-AllInstanceInfo { if ($There) { try { $LoginMustChange = [pscustomobject] @{ - Count = @(Get-DbaLogin -SQLInstance . -Type SQL | Where-Object { $_.MustChangePassword -eq $false -and $_.IsDisabled -eq $false -and $_.LastLogin -eq $null }).Count + Count = @(Get-DbaLogin -SQLInstance . -Type SQL | Where-Object { $_.MustChangePassword -eq $false -and $_.IsDisabled -eq $false -and $null -eq $_.LastLogin }).Count } } catch { From 61c5280360e6cd8a7d7dec8f2656a9da64b7447f Mon Sep 17 00:00:00 2001 From: Tracy Boggiano Date: Wed, 29 Jan 2020 10:05:31 -0500 Subject: [PATCH 26/61] fix pester test missing description --- checks/Instance.Tests.ps1 | 2 +- internal/configurations/DbcCheckDescriptions.json | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/checks/Instance.Tests.ps1 b/checks/Instance.Tests.ps1 index 01d299e8..fc091932 100644 --- a/checks/Instance.Tests.ps1 +++ b/checks/Instance.Tests.ps1 @@ -1061,7 +1061,7 @@ $Tags = Get-CheckInformation -Check $Check -Group Instance -AllChecks $AllChecks } } else { - Context "Testing if the new SQL logins that have not logged have to change their password when they log in on $psitem" { + Context "Testing if the new SQL logins that have not logged have to change their password when they log in on $psitem" -Skip:$skip { It "All new sql logins should have the have to change their password when they log in for the first time on $psitem" { Assert-LoginMustChange -AllInstanceInfo $AllInstanceInfo } diff --git a/internal/configurations/DbcCheckDescriptions.json b/internal/configurations/DbcCheckDescriptions.json index e9270c51..145345f3 100644 --- a/internal/configurations/DbcCheckDescriptions.json +++ b/internal/configurations/DbcCheckDescriptions.json @@ -482,5 +482,9 @@ { "UniqueTag": "LoginPasswordExpiration", "Description": "Tests to see if password expiration policy is set for sql logins in sysadmin role." + }, + { + "UniqueTag": "LoginMustChange", + "Description": "Tests to see if password must change is enabled for new logins." } ] \ No newline at end of file From 82c2d9ed8a84a5d2528449c0d307b7aae392bf9e Mon Sep 17 00:00:00 2001 From: Tracy Boggiano Date: Wed, 29 Jan 2020 10:19:04 -0500 Subject: [PATCH 27/61] fix pester tests --- internal/assertions/Instance.Assertions.ps1 | 4 +--- internal/configurations/configuration.ps1 | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/internal/assertions/Instance.Assertions.ps1 b/internal/assertions/Instance.Assertions.ps1 index fa528565..214f9da4 100644 --- a/internal/assertions/Instance.Assertions.ps1 +++ b/internal/assertions/Instance.Assertions.ps1 @@ -540,8 +540,7 @@ function Get-AllInstanceInfo { Count = 'We Could not Connect to $Instance' } } - } - + } 'LoginPasswordExpiration' { if ($There) { try { @@ -565,7 +564,6 @@ function Get-AllInstanceInfo { } } } - 'LoginMustChange' { if ($There) { try { diff --git a/internal/configurations/configuration.ps1 b/internal/configurations/configuration.ps1 index 39f01eb6..79845dad 100644 --- a/internal/configurations/configuration.ps1 +++ b/internal/configurations/configuration.ps1 @@ -247,7 +247,7 @@ Set-PSFConfig -Module dbachecks -Name skip.security.builtinadmin -Validation boo Set-PSFConfig -Module dbachecks -Name skip.security.guestuserconnect -Validation bool -Value $true -Initialize -Description "Skips the scan for guest user have CONNECT permission" Set-PSFConfig -Module dbachecks -Name skip.security.LoginCheckPolicy -Validation bool -Value $true -Initialize -Description "Skips the scan for CHECK_POLICY on for all logins" Set-PSFConfig -Module dbachecks -Name skip.security.LoginPasswordExpiration -Validation bool -Value $true -Initialize -Description "Skips the scan for password expiration on for all logins in sysadmin role" - +Set-PSFConfig -Module dbachecks -Name skip.security.LoginMustChange -Validation bool -Value $true -Initialize -Description "Skips the scan for new logins must have password change turned on" #agent Set-PSFConfig -Module dbachecks -Name agent.dbaoperatorname -Value $null -Initialize -Description "Name of the DBA Operator in SQL Agent" Set-PSFConfig -Module dbachecks -Name agent.dbaoperatoremail -Value $null -Initialize -Description "Email address of the DBA Operator in SQL Agent" From f6b271bf5e22a1d88822767a27ea7ce5879697e1 Mon Sep 17 00:00:00 2001 From: Tracy Boggiano Date: Wed, 29 Jan 2020 10:27:51 -0500 Subject: [PATCH 28/61] fix errors --- internal/assertions/Instance.Assertions.ps1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/assertions/Instance.Assertions.ps1 b/internal/assertions/Instance.Assertions.ps1 index 214f9da4..52a503bd 100644 --- a/internal/assertions/Instance.Assertions.ps1 +++ b/internal/assertions/Instance.Assertions.ps1 @@ -540,7 +540,7 @@ function Get-AllInstanceInfo { Count = 'We Could not Connect to $Instance' } } - } + } 'LoginPasswordExpiration' { if ($There) { try { @@ -734,7 +734,7 @@ function Assert-TraceFlag { function Assert-NotTraceFlag { Param( [string]$SQLInstance, - [int[]]$NotExpectedTraceFlagA + [int[]]$NotExpectedTraceFlag ) if ($null -eq $NotExpectedTraceFlag) { From bca03fdee33ca2e90fd894b3cfe62eac05c46965 Mon Sep 17 00:00:00 2001 From: Tracy Boggiano Date: Wed, 29 Jan 2020 12:21:15 -0500 Subject: [PATCH 29/61] fix saexist --- internal/configurations/configuration.ps1 | 2 +- tests/checks/InstanceChecks.Tests.ps1 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/configurations/configuration.ps1 b/internal/configurations/configuration.ps1 index 79845dad..8ea57ae9 100644 --- a/internal/configurations/configuration.ps1 +++ b/internal/configurations/configuration.ps1 @@ -237,7 +237,7 @@ Set-PSFConfig -Module dbachecks -Name skip.instance.remoteaccessdisabled -Valida Set-PSFConfig -Module dbachecks -Name skip.instance.scanforstartupproceduresdisabled -Validation bool -Value $false -Initialize -Description "Skip the scan for startup procedures disabled check" Set-PSFConfig -Module dbachecks -Name skip.instance.latestbuild -Validation bool -Value $false -Initialize -Description "Skip the scan the latest build of SQL Server check" Set-PSFConfig -Module dbachecks -Name skip.security.sadisabled -Validation bool -Value $true -Initialize -Description "Skip the check for if the sa login is disabled" -Set-PSFConfig -Module dbachecks -Name skip.security.saexist -Validation bool -Value $true -Initialize -Description "Skip the check for a login named sa does not exist" +Set-PSFConfig -Module dbachecks -Name skip.security.saexist -Validation bool -Value -Initialize -Description "Skip the check for a login named sa does not exist" Set-PSFConfig -Module dbachecks -Name skip.security.containedbautoclose -Validation bool -Value $true -Initialize -Description "Skips the scan for contained databases should have auto close enabled" Set-PSFConfig -Module dbachecks -Name skip.security.loginauditlevelfailed -Validation bool -Value $true -Initialize -Description "Skips the scan for if server login level records failed logins" Set-PSFConfig -Module dbachecks -Name skip.security.loginauditlevelsuccessful -Validation bool -Value $true -Initialize -Description "Skips the scan for if server login level records successful and failed logins" diff --git a/tests/checks/InstanceChecks.Tests.ps1 b/tests/checks/InstanceChecks.Tests.ps1 index c22969bd..9d4e4606 100644 --- a/tests/checks/InstanceChecks.Tests.ps1 +++ b/tests/checks/InstanceChecks.Tests.ps1 @@ -1102,7 +1102,7 @@ InModuleScope dbachecks { Exist = $true } }} - {Assert-SaExist -AllInstanceInfo (Get-AllInstanceInfo)} | Should -Throw -ExpectedMessage "Expected `$false, because We expected no login to exist with the name sa, but got `$true." + {Assert-SaExist -AllInstanceInfo (Get-AllInstanceInfo)} | Should -Throw -ExpectedMessage "Expected 0, because We expected no login to exist with the name sa, but got 1." } } } From 1d6a364f5c4feb515a52f2d224df32f4ecbd0d1d Mon Sep 17 00:00:00 2001 From: Tracy Boggiano Date: Wed, 29 Jan 2020 12:31:55 -0500 Subject: [PATCH 30/61] saexist --- checks/Instance.Tests.ps1 | 2 +- tests/checks/InstanceChecks.Tests.ps1 | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/checks/Instance.Tests.ps1 b/checks/Instance.Tests.ps1 index fc091932..e25d66b2 100644 --- a/checks/Instance.Tests.ps1 +++ b/checks/Instance.Tests.ps1 @@ -1061,7 +1061,7 @@ $Tags = Get-CheckInformation -Check $Check -Group Instance -AllChecks $AllChecks } } else { - Context "Testing if the new SQL logins that have not logged have to change their password when they log in on $psitem" -Skip:$skip { + Context "Testing if the new SQL logins that have not logged have to change their password when they log in on $psitem" -Skip:$skip{ It "All new sql logins should have the have to change their password when they log in for the first time on $psitem" { Assert-LoginMustChange -AllInstanceInfo $AllInstanceInfo } diff --git a/tests/checks/InstanceChecks.Tests.ps1 b/tests/checks/InstanceChecks.Tests.ps1 index 9d4e4606..95ffa223 100644 --- a/tests/checks/InstanceChecks.Tests.ps1 +++ b/tests/checks/InstanceChecks.Tests.ps1 @@ -1088,7 +1088,7 @@ InModuleScope dbachecks { # Mock for success Mock Get-AllInstanceInfo {[PSCustomObject]@{ SaExist = [PSCustomObject]@{ - Exist = $false + Exist = 0 } } } @@ -1099,7 +1099,7 @@ InModuleScope dbachecks { # Mock for failing test Mock Get-AllInstanceInfo {[PSCustomObject]@{ SaExist = [PSCustomObject]@{ - Exist = $true + Exist = 1 } }} {Assert-SaExist -AllInstanceInfo (Get-AllInstanceInfo)} | Should -Throw -ExpectedMessage "Expected 0, because We expected no login to exist with the name sa, but got 1." From 9baa0ca5bc0388074a6a312974eada0404ff525d Mon Sep 17 00:00:00 2001 From: Tracy Boggiano Date: Wed, 29 Jan 2020 12:39:23 -0500 Subject: [PATCH 31/61] fix stupid mistake --- internal/configurations/configuration.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/configurations/configuration.ps1 b/internal/configurations/configuration.ps1 index 8ea57ae9..79845dad 100644 --- a/internal/configurations/configuration.ps1 +++ b/internal/configurations/configuration.ps1 @@ -237,7 +237,7 @@ Set-PSFConfig -Module dbachecks -Name skip.instance.remoteaccessdisabled -Valida Set-PSFConfig -Module dbachecks -Name skip.instance.scanforstartupproceduresdisabled -Validation bool -Value $false -Initialize -Description "Skip the scan for startup procedures disabled check" Set-PSFConfig -Module dbachecks -Name skip.instance.latestbuild -Validation bool -Value $false -Initialize -Description "Skip the scan the latest build of SQL Server check" Set-PSFConfig -Module dbachecks -Name skip.security.sadisabled -Validation bool -Value $true -Initialize -Description "Skip the check for if the sa login is disabled" -Set-PSFConfig -Module dbachecks -Name skip.security.saexist -Validation bool -Value -Initialize -Description "Skip the check for a login named sa does not exist" +Set-PSFConfig -Module dbachecks -Name skip.security.saexist -Validation bool -Value $true -Initialize -Description "Skip the check for a login named sa does not exist" Set-PSFConfig -Module dbachecks -Name skip.security.containedbautoclose -Validation bool -Value $true -Initialize -Description "Skips the scan for contained databases should have auto close enabled" Set-PSFConfig -Module dbachecks -Name skip.security.loginauditlevelfailed -Validation bool -Value $true -Initialize -Description "Skips the scan for if server login level records failed logins" Set-PSFConfig -Module dbachecks -Name skip.security.loginauditlevelsuccessful -Validation bool -Value $true -Initialize -Description "Skips the scan for if server login level records successful and failed logins" From 92d99e8ee3e59a538f8a46dc7ae17103e256cb90 Mon Sep 17 00:00:00 2001 From: Rob Sewell Date: Sat, 14 Mar 2020 20:05:01 +0000 Subject: [PATCH 32/61] dont need the starttype --- internal/assertions/Instance.Assertions.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/assertions/Instance.Assertions.ps1 b/internal/assertions/Instance.Assertions.ps1 index f5cd95c3..fbefa584 100644 --- a/internal/assertions/Instance.Assertions.ps1 +++ b/internal/assertions/Instance.Assertions.ps1 @@ -524,7 +524,7 @@ function Get-AllInstanceInfo { catch { $There = $false $HideInstance = [pscustomobject] @{ - HideInstance = StartType = 'We Could not Connect to $Instance' + HideInstance = 'We Could not Connect to $Instance' } } } From 7b353f4224c302f6cea1e11b10cab45cf08c61e7 Mon Sep 17 00:00:00 2001 From: Rob Sewell Date: Sat, 14 Mar 2020 20:11:19 +0000 Subject: [PATCH 33/61] release notes --- RELEASE.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/RELEASE.md b/RELEASE.md index feacacb1..9299b1ce 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -1,3 +1,9 @@ +## Date 8th January 2020 +Thank you Tracey tboggiano + New CIS Check Hide Instance #728 + +##Latest + ## Date 8th January 2020 Thank you Tracey tboggiano New CIS Check Guest Account connect permissions #725 @@ -10,8 +16,6 @@ Thank you Rob Added Tag parameter to Get-DbcCheck Updated tests to work with PowerShell 7 -##Latest - ## Date 22nd December Thank you Tracey tboggiano Two New CIS Checks Contained databases should be auto-closed #721 From 8b5edea65c57592bc4a425783925ce2f6fecfa93 Mon Sep 17 00:00:00 2001 From: Rob Sewell Date: Sat, 14 Mar 2020 20:37:45 +0000 Subject: [PATCH 34/61] release notes --- RELEASE.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/RELEASE.md b/RELEASE.md index 9299b1ce..d5952163 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -1,6 +1,7 @@ -## Date 8th January 2020 +## Date 14th March 2020 Thank you Tracey tboggiano New CIS Check Hide Instance #728 + New CIS Check Symmetric Key #732 ##Latest From 04023fc9341f1f9220a896f3f9d3b673c9454226 Mon Sep 17 00:00:00 2001 From: Rob Sewell Date: Sat, 14 Mar 2020 21:09:39 +0000 Subject: [PATCH 35/61] release notes --- RELEASE.md | 1 + 1 file changed, 1 insertion(+) diff --git a/RELEASE.md b/RELEASE.md index d5952163..db4cced8 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -2,6 +2,7 @@ Thank you Tracey tboggiano New CIS Check Hide Instance #728 New CIS Check Symmetric Key #732 + New CIS Check Agent Proxy not have access to public Role #732 ##Latest From abbf6d132ac8bdf94cf5dca3e1bd4f736ddd0876 Mon Sep 17 00:00:00 2001 From: Rob Sewell Date: Sat, 14 Mar 2020 21:27:56 +0000 Subject: [PATCH 36/61] damn those white spaces --- internal/assertions/Instance.Assertions.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/assertions/Instance.Assertions.ps1 b/internal/assertions/Instance.Assertions.ps1 index d65e1e38..f7f0927a 100644 --- a/internal/assertions/Instance.Assertions.ps1 +++ b/internal/assertions/Instance.Assertions.ps1 @@ -536,7 +536,7 @@ function Get-AllInstanceInfo { CredentialIdentity = $null } } - } + } else { $There = $false $SqlAgentProxiesWithPublicRole = [pscustomobject] @{ From 67d5449fecfb707c19965d19eb9cdaf1afff0556 Mon Sep 17 00:00:00 2001 From: Rob Sewell Date: Sat, 14 Mar 2020 21:34:46 +0000 Subject: [PATCH 37/61] release notes --- dbachecks.psd1 | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/dbachecks.psd1 b/dbachecks.psd1 index 68e305f0..44420829 100644 --- a/dbachecks.psd1 +++ b/dbachecks.psd1 @@ -134,17 +134,11 @@ # Release notes for this particular version of the module ReleaseNotes = " -## Date 8th January 2020 +## Date 14th March 2020 Thank you Tracey tboggiano - New CIS Check Guest Account connect permissions #725 - New CIS Check BuiltIn Admins login #726 - New CIS Check public role permissions #729 - New CIS Check local windows groups do not have logins #731 - Update sa login check #730 - -Thank you Rob - Added Tag parameter to Get-DbcCheck - Updated tests to work with PowerShell 7 + New CIS Check Hide Instance #728 + New CIS Check Symmetric Key #732 + New CIS Check Agent Proxy not have access to public Role #732 ##Latest From 5d492de11515f19ff16f4737b2935b3244b4cdee Mon Sep 17 00:00:00 2001 From: SQLDBAWithABeard Date: Sat, 14 Mar 2020 21:48:41 +0000 Subject: [PATCH 38/61] Updated Version Number to 1.2.25 ***NO_CI*** --- dbachecks.psd1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dbachecks.psd1 b/dbachecks.psd1 index 44420829..f7107e20 100644 --- a/dbachecks.psd1 +++ b/dbachecks.psd1 @@ -11,7 +11,7 @@ RootModule = 'dbachecks.psm1' # Version number of this module. - ModuleVersion = '1.2.24' + ModuleVersion = '1.2.25' # ID used to uniquely identify this module GUID = '578c5d98-50c8-43a8-bdbb-d7159028d7ac' From 8b925dcbf480c1dac17d027e40d90e0c059e3bd2 Mon Sep 17 00:00:00 2001 From: SQLDBAWithABeard Date: Sat, 14 Mar 2020 21:52:15 +0000 Subject: [PATCH 39/61] Updated Version Number and docs from master ***NO_CI*** --- docs/RELEASE.md | 10 +++- docs/functions/Invoke-DbcCheck.md | 86 +++++++++++++++++++++++++++---- 2 files changed, 84 insertions(+), 12 deletions(-) diff --git a/docs/RELEASE.md b/docs/RELEASE.md index feacacb1..db4cced8 100644 --- a/docs/RELEASE.md +++ b/docs/RELEASE.md @@ -1,3 +1,11 @@ +## Date 14th March 2020 +Thank you Tracey tboggiano + New CIS Check Hide Instance #728 + New CIS Check Symmetric Key #732 + New CIS Check Agent Proxy not have access to public Role #732 + +##Latest + ## Date 8th January 2020 Thank you Tracey tboggiano New CIS Check Guest Account connect permissions #725 @@ -10,8 +18,6 @@ Thank you Rob Added Tag parameter to Get-DbcCheck Updated tests to work with PowerShell 7 -##Latest - ## Date 22nd December Thank you Tracey tboggiano Two New CIS Checks Contained databases should be auto-closed #721 diff --git a/docs/functions/Invoke-DbcCheck.md b/docs/functions/Invoke-DbcCheck.md index 5db153fb..7f528eae 100644 --- a/docs/functions/Invoke-DbcCheck.md +++ b/docs/functions/Invoke-DbcCheck.md @@ -102,14 +102,17 @@ Invoke-DbcCheck [-Script ] [-TestName ] [-EnableExit] [[-Che [-ConfigSkipInstanceOleautomationproceduresdisabled ] [-ConfigSkipInstanceRemoteaccessdisabled ] [-ConfigSkipInstanceScanforstartupproceduresdisabled ] [-ConfigSkipLogfilecounttest ] - [-ConfigSkipLogshiptesting ] [-ConfigSkipSecurityBuiltinadmin ] - [-ConfigSkipSecurityContainedbautoclose ] [-ConfigSkipSecurityGuestuserconnect ] + [-ConfigSkipLogshiptesting ] [-ConfigSkipSecurityAsymmetrickeysize ] + [-ConfigSkipSecurityBuiltinadmin ] [-ConfigSkipSecurityContainedbautoclose ] + [-ConfigSkipSecurityGuestuserconnect ] [-ConfigSkipSecurityHideinstance ] [-ConfigSkipSecurityLocalwindowsgroup ] [-ConfigSkipSecurityLoginauditlevelfailed ] [-ConfigSkipSecurityLoginauditlevelsuccessful ] [-ConfigSkipSecurityPublicrolepermission ] [-ConfigSkipSecuritySadisabled ] [-ConfigSkipSecuritySaexist ] - [-ConfigSkipTempdb1118 ] [-ConfigSkipTempdbfilecount ] - [-ConfigSkipTempdbfilegrowthpercent ] [-ConfigSkipTempdbfilesizemax ] - [-ConfigSkipTempdbfilesonc ] [-ConfigTestingIntegrationInstance ] [] + [-ConfigSkipSecuritySqlagentproxiesnopublicrole ] + [-ConfigSkipSecuritySymmetrickeyencryptionlevel ] [-ConfigSkipTempdb1118 ] + [-ConfigSkipTempdbfilecount ] [-ConfigSkipTempdbfilegrowthpercent ] + [-ConfigSkipTempdbfilesizemax ] [-ConfigSkipTempdbfilesonc ] + [-ConfigTestingIntegrationInstance ] [] ``` ### NewOutputSet @@ -209,14 +212,17 @@ Invoke-DbcCheck [-Script ] [-TestName ] [-EnableExit] [[-Che [-ConfigSkipInstanceOleautomationproceduresdisabled ] [-ConfigSkipInstanceRemoteaccessdisabled ] [-ConfigSkipInstanceScanforstartupproceduresdisabled ] [-ConfigSkipLogfilecounttest ] - [-ConfigSkipLogshiptesting ] [-ConfigSkipSecurityBuiltinadmin ] - [-ConfigSkipSecurityContainedbautoclose ] [-ConfigSkipSecurityGuestuserconnect ] + [-ConfigSkipLogshiptesting ] [-ConfigSkipSecurityAsymmetrickeysize ] + [-ConfigSkipSecurityBuiltinadmin ] [-ConfigSkipSecurityContainedbautoclose ] + [-ConfigSkipSecurityGuestuserconnect ] [-ConfigSkipSecurityHideinstance ] [-ConfigSkipSecurityLocalwindowsgroup ] [-ConfigSkipSecurityLoginauditlevelfailed ] [-ConfigSkipSecurityLoginauditlevelsuccessful ] [-ConfigSkipSecurityPublicrolepermission ] [-ConfigSkipSecuritySadisabled ] [-ConfigSkipSecuritySaexist ] - [-ConfigSkipTempdb1118 ] [-ConfigSkipTempdbfilecount ] - [-ConfigSkipTempdbfilegrowthpercent ] [-ConfigSkipTempdbfilesizemax ] - [-ConfigSkipTempdbfilesonc ] [-ConfigTestingIntegrationInstance ] [] + [-ConfigSkipSecuritySqlagentproxiesnopublicrole ] + [-ConfigSkipSecuritySymmetrickeyencryptionlevel ] [-ConfigSkipTempdb1118 ] + [-ConfigSkipTempdbfilecount ] [-ConfigSkipTempdbfilegrowthpercent ] + [-ConfigSkipTempdbfilesizemax ] [-ConfigSkipTempdbfilesonc ] + [-ConfigTestingIntegrationInstance ] [] ``` ## DESCRIPTION @@ -3382,6 +3388,21 @@ Accept pipeline input: False Accept wildcard characters: False ``` +### -ConfigSkipSecurityAsymmetrickeysize +{{ Fill ConfigSkipSecurityAsymmetrickeysize Description }} + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + ### -ConfigSkipSecurityBuiltinadmin {{ Fill ConfigSkipSecurityBuiltinadmin Description }} @@ -3427,6 +3448,21 @@ Accept pipeline input: False Accept wildcard characters: False ``` +### -ConfigSkipSecurityHideinstance +{{ Fill ConfigSkipSecurityHideinstance Description }} + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + ### -ConfigSkipSecurityLocalwindowsgroup {{ Fill ConfigSkipSecurityLocalwindowsgroup Description }} @@ -3517,6 +3553,36 @@ Accept pipeline input: False Accept wildcard characters: False ``` +### -ConfigSkipSecuritySqlagentproxiesnopublicrole +{{ Fill ConfigSkipSecuritySqlagentproxiesnopublicrole Description }} + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ConfigSkipSecuritySymmetrickeyencryptionlevel +{{ Fill ConfigSkipSecuritySymmetrickeyencryptionlevel Description }} + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + ### -ConfigSkipTempdb1118 {{ Fill ConfigSkipTempdb1118 Description }} From d3ff6141e4ec5c92add7f2ab7e323deb0bba7ac3 Mon Sep 17 00:00:00 2001 From: Rob Date: Wed, 18 Mar 2020 22:49:41 +0000 Subject: [PATCH 40/61] HADR doesnt run on Core because FailoverCluster Module wont load --- checks/HADR.Tests.ps1 | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/checks/HADR.Tests.ps1 b/checks/HADR.Tests.ps1 index afa96645..92e0ee6e 100644 --- a/checks/HADR.Tests.ps1 +++ b/checks/HADR.Tests.ps1 @@ -44,7 +44,12 @@ function Get-ClusterObject { # needs the failover cluster module if (-not (Get-Module FailoverClusters)) { try { - Import-Module FailoverClusters -ErrorAction Stop + if($IsCoreCLR){ + Stop-PSFFunction -Message "FailoverClusters module cannot be loaded in PowerShell Core unfortunately" -ErrorRecord $psitem + return + }else{ + Import-Module FailoverClusters -ErrorAction Stop + } } catch { Stop-PSFFunction -Message "FailoverClusters module could not load - Please install the Failover Cluster module using Windows Features " -ErrorRecord $psitem @@ -125,7 +130,18 @@ foreach ($clustervm in $clusters) { Context "Cluster Connectivity for Availability Group $($AG.Name) on $clustername" { @($AG.AvailabilityGroupListeners).ForEach{ - $results = Test-DbaConnection -sqlinstance $_.Name + try{ + $results = Test-DbaConnection -sqlinstance $_.Name + } + Catch{ + $results = [PSCustomObject]@{ + IsPingable = $false + ConnectSuccess = $false + DomainName = $false + TCPPort = $false + } + } + It "Listener $($results.SqlInstance) should be pingable" -skip:$skiplistener { $results.IsPingable | Should -BeTrue -Because 'The listeners should be pingable' } @@ -206,7 +222,7 @@ foreach ($clustervm in $clusters) { $psitem.IsFailoverReady | Should -BeFalse -Because 'The database on the asynchronous secondary replica should be ready to failover' } It "Database $($psitem.DatabaseName) should be joined on the secondary replica $($psitem.Replica)" { - $psitem.IsJoined | Should -BeTrue -Because 'The database on the asynchronous secondary replica should be joined to the availaility group' + $psitem.IsJoined | Should -BeTrue -Because 'The database on the asynchronous secondary replica should be joined to the availability group' } It "Database $($psitem.DatabaseName) should not be suspended on the secondary replica $($psitem.Replica)" { $psitem.IsSuspended | Should -Be $False -Because 'The database on the asynchronous secondary replica should not be suspended' From 01e5eb5b01d8b430c6891b8a7a1b2bacc8808a60 Mon Sep 17 00:00:00 2001 From: Rob Date: Wed, 18 Mar 2020 23:17:19 +0000 Subject: [PATCH 41/61] removed trailing whitespace --- checks/HADR.Tests.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/checks/HADR.Tests.ps1 b/checks/HADR.Tests.ps1 index 92e0ee6e..28f36599 100644 --- a/checks/HADR.Tests.ps1 +++ b/checks/HADR.Tests.ps1 @@ -141,7 +141,7 @@ foreach ($clustervm in $clusters) { TCPPort = $false } } - + It "Listener $($results.SqlInstance) should be pingable" -skip:$skiplistener { $results.IsPingable | Should -BeTrue -Because 'The listeners should be pingable' } From cf5fd0ce772000c50dc3bdc77f1cc619598a55cc Mon Sep 17 00:00:00 2001 From: Rob Date: Wed, 18 Mar 2020 23:18:41 +0000 Subject: [PATCH 42/61] release notes --- RELEASE.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/RELEASE.md b/RELEASE.md index db4cced8..b3948f83 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -1,11 +1,15 @@ +## Date 18th March 2020 +Thank you Tracey tboggiano + New CIS user-defined CLRs to be set to SAFE_ACCESS#734 + +##Latest + ## Date 14th March 2020 Thank you Tracey tboggiano New CIS Check Hide Instance #728 New CIS Check Symmetric Key #732 New CIS Check Agent Proxy not have access to public Role #732 -##Latest - ## Date 8th January 2020 Thank you Tracey tboggiano New CIS Check Guest Account connect permissions #725 From e55fa3e676dfaad9b010a8d00ca082e944795722 Mon Sep 17 00:00:00 2001 From: Rob Date: Wed, 18 Mar 2020 23:30:06 +0000 Subject: [PATCH 43/61] added psscriptanal;yser file --- PSScriptAnalyzerSettings.psd1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PSScriptAnalyzerSettings.psd1 b/PSScriptAnalyzerSettings.psd1 index 0350b9ea..dc9a0181 100644 --- a/PSScriptAnalyzerSettings.psd1 +++ b/PSScriptAnalyzerSettings.psd1 @@ -16,7 +16,7 @@ # You can specify commands to not check like this, which also will ignore its parameters: IgnoreCommands = @( 'It', # Because Pester! - 'Should', # Because Pester! + #'Should', # Because Pester! 'Context', # Because Pester! 'BeforeAll', # Because Pester! 'AfterAll', # Because Pester! From be56646b952384b93a51bcd9d0bf810679eca068 Mon Sep 17 00:00:00 2001 From: Rob Date: Wed, 18 Mar 2020 23:56:32 +0000 Subject: [PATCH 44/61] release notes --- RELEASE.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/RELEASE.md b/RELEASE.md index b3948f83..3faadc55 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -1,6 +1,7 @@ ## Date 18th March 2020 Thank you Tracey tboggiano - New CIS user-defined CLRs to be set to SAFE_ACCESS#734 + New CIS user-defined CLRs to be set to SAFE_ACCESS #734 + CIS tests for if service accounts are local admins #736 ##Latest From e4ab980ff6dce2c321a10087795f5cfb7e254b50 Mon Sep 17 00:00:00 2001 From: Rob Date: Thu, 19 Mar 2020 00:17:39 +0000 Subject: [PATCH 45/61] hmm --- PSScriptAnalyzerSettings.psd1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PSScriptAnalyzerSettings.psd1 b/PSScriptAnalyzerSettings.psd1 index 5e2e808a..cdbc5dc4 100644 --- a/PSScriptAnalyzerSettings.psd1 +++ b/PSScriptAnalyzerSettings.psd1 @@ -16,7 +16,7 @@ # You can specify commands to not check like this, which also will ignore its parameters: IgnoreCommands = @( 'It', # Because Pester! - #'Should', # Because Pester! + 'Should', # Because Pester! 'Context', # Because Pester! 'BeforeAll', # Because Pester! 'AfterAll', # Because Pester! From 19b9edfd0e1f322bb546439fbe5dcd576d0bccb8 Mon Sep 17 00:00:00 2001 From: Rob Date: Thu, 19 Mar 2020 00:21:26 +0000 Subject: [PATCH 46/61] wont work on core --- checks/Instance.Tests.ps1 | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/checks/Instance.Tests.ps1 b/checks/Instance.Tests.ps1 index f93e203d..77333e6a 100644 --- a/checks/Instance.Tests.ps1 +++ b/checks/Instance.Tests.ps1 @@ -1059,6 +1059,9 @@ $Tags = Get-CheckInformation -Check $Check -Group Instance -AllChecks $AllChecks } } else { + if($IsCoreCLR){ + $Skip = $true + } Context "Testing whether SQL Engine account is a local administrator on $psitem" { It "The SQL Engine service account should not be a local administrator on $psitem" -Skip:$skip { Assert-EngineServiceAdmin -AllInstanceInfo $AllInstanceInfo @@ -1077,6 +1080,9 @@ $Tags = Get-CheckInformation -Check $Check -Group Instance -AllChecks $AllChecks } } else { + if($IsCoreCLR){ + $Skip = $true + } Context "Testing whether SQL Agent account is a local administrator on $psitem" { It "The SQL Agent service account should not be a local administrator on $psitem" -Skip:$skip { Assert-AgentServiceAdmin -AllInstanceInfo $AllInstanceInfo @@ -1095,6 +1101,9 @@ $Tags = Get-CheckInformation -Check $Check -Group Instance -AllChecks $AllChecks } } else { + if($IsCoreCLR){ + $Skip = $true + } Context "Testing whether SQL Full Text account is a local administrator on $psitem" { It "The SQL Full Text service account should not be a local administrator on $psitem" -Skip:$skip { Assert-FullTextServiceAdmin -AllInstanceInfo $AllInstanceInfo From d5f57389bb1a74c5fe818f974d458542653830f1 Mon Sep 17 00:00:00 2001 From: Rob Date: Fri, 20 Mar 2020 13:27:37 +0000 Subject: [PATCH 47/61] need to handle the service not being available --- internal/assertions/Instance.Assertions.ps1 | 41 +++++++++++++++++++-- 1 file changed, 38 insertions(+), 3 deletions(-) diff --git a/internal/assertions/Instance.Assertions.ps1 b/internal/assertions/Instance.Assertions.ps1 index 65ae31db..45e654ea 100644 --- a/internal/assertions/Instance.Assertions.ps1 +++ b/internal/assertions/Instance.Assertions.ps1 @@ -590,6 +590,18 @@ function Get-AllInstanceInfo { Exist = $localAdmins.Name.Contains($SqlEngineService.StartName) } } + catch [System.Exception] { + if ($_.Exception.Message -like '*No services found in relevant namespaces*') { + $FullTextServiceAdmin = [pscustomobject] @{ + Exist = $false + } + } + else { + $FullTextServiceAdmin = [pscustomobject] @{ + Exist = 'Some sort of failure' + } + } + } catch { $There = $false $EngineServiceAdmin = [pscustomobject] @{ @@ -626,6 +638,18 @@ function Get-AllInstanceInfo { Exist = $localAdmins.Name.Contains($SqlAgentService.StartName) } } + catch [System.Exception] { + if ($_.Exception.Message -like '*No services found in relevant namespaces*') { + $FullTextServiceAdmin = [pscustomobject] @{ + Exist = $false + } + } + else { + $FullTextServiceAdmin = [pscustomobject] @{ + Exist = 'Some sort of failure' + } + } + } catch { $There = $false $AgentServiceAdmin = [pscustomobject] @{ @@ -655,17 +679,28 @@ function Get-AllInstanceInfo { if ($null -eq $InstanceName) { $InstanceName = 'MSSQLSERVER' } - $SqlFullTextService = Get-DbaService -ComputerName $ComputerName -InstanceName $instanceName -Type FullText -ErrorAction SilentlyContinue + $SqlFullTextService = Get-DbaService -ComputerName $ComputerName -InstanceName $instanceName -Type FullText -ErrorAction SilentlyContinue -WarningAction SilentlyContinue -WarningVariable WarVar $LocalAdmins = Invoke-Command -ComputerName $ComputerName -ScriptBlock { Get-LocalGroupMember -Group "Administrators" } -ErrorAction SilentlyContinue - $FullTextServiceAdmin = [pscustomobject] @{ Exist = $localAdmins.Name.Contains($SqlFullTextService.StartName) } } + catch [System.Exception] { + if ($_.Exception.Message -like '*No services found in relevant namespaces*') { + $FullTextServiceAdmin = [pscustomobject] @{ + Exist = $false + } + } + else { + $FullTextServiceAdmin = [pscustomobject] @{ + Exist = 'Some sort of failure' + } + } + } catch { $There = $false $FullTextServiceAdmin = [pscustomobject] @{ - Exist = 'We Could not Connect to $Instance $ComputerName , $InstanceName from catch' + Exist = "We Could not Connect to $Instance $ComputerName , $InstanceName from catch" } } } From 346a7934e184cfdd3bc99d5b4112be88ac08999b Mon Sep 17 00:00:00 2001 From: Rob Date: Fri, 20 Mar 2020 14:40:22 +0000 Subject: [PATCH 48/61] mkaes more sense --- RELEASE.md | 3 +++ internal/configurations/configuration.ps1 | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/RELEASE.md b/RELEASE.md index 3faadc55..2955dd9a 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -3,6 +3,9 @@ Thank you Tracey tboggiano New CIS user-defined CLRs to be set to SAFE_ACCESS #734 CIS tests for if service accounts are local admins #736 +Thank you Rob + Getting service accounts tests to pass if no service + ##Latest ## Date 14th March 2020 diff --git a/internal/configurations/configuration.ps1 b/internal/configurations/configuration.ps1 index dfb6ef73..804ab327 100644 --- a/internal/configurations/configuration.ps1 +++ b/internal/configurations/configuration.ps1 @@ -263,7 +263,7 @@ Set-PSFConfig -Module dbachecks -Name agent.databasemailprofile -Value $null -In Set-PSFConfig -Module dbachecks -Name agent.validjobowner.name -Value "sa" -Initialize -Description "Agent job owner account should be this user" Set-PSFConfig -Module dbachecks -Name agent.alert.messageid -Value @('823', '824', '825') -Initialize -Description "Agent alert messageid to validate; https://www.brentozar.com/blitz/configure-sql-server-alerts/" Set-PSFConfig -Module dbachecks -Name agent.alert.Severity -Value @('16', '17', '18', '19', '20', '21', '22', '23', '24', '25') -Initialize -Description "Agent alert severity to validate; https://www.brentozar.com/blitz/configure-sql-server-alerts/" -Set-PSFConfig -Module dbachecks -Name agent.alert.Job -Value $false -Initialize -Description "Agent alert job notification. Ex job to write to eventlog for SCOM monitoring" +Set-PSFConfig -Module dbachecks -Name agent.alert.Job -Value $false -Initialize -Description "Should we check for an agent job for the Agent Alert checks?" Set-PSFConfig -Module dbachecks -Name agent.alert.Notification -Value $true -Initialize -Description "Agent alert notification" Set-PSFConfig -Module dbachecks -Name agent.history.maximumhistoryrows -Value 1000 -Initialize -Description "Maximum job history log size (in rows). The value -1 means disabled" Set-PSFConfig -Module dbachecks -Name agent.history.maximumjobhistoryrows -Value 100 -Initialize -Description "Maximum job history row per job. When the property is disabled the value is 0." From da9750ee9fd7a1058886703f886c0b5d1a51b7b8 Mon Sep 17 00:00:00 2001 From: Rob Date: Fri, 20 Mar 2020 14:41:36 +0000 Subject: [PATCH 49/61] consistency in config names is sgood even for case --- internal/configurations/configuration.ps1 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/internal/configurations/configuration.ps1 b/internal/configurations/configuration.ps1 index 804ab327..9d097d60 100644 --- a/internal/configurations/configuration.ps1 +++ b/internal/configurations/configuration.ps1 @@ -262,9 +262,9 @@ Set-PSFConfig -Module dbachecks -Name agent.failsafeoperator -Value $null -Initi Set-PSFConfig -Module dbachecks -Name agent.databasemailprofile -Value $null -Initialize -Description "Name of the Database Mail Profile in SQL Agent" Set-PSFConfig -Module dbachecks -Name agent.validjobowner.name -Value "sa" -Initialize -Description "Agent job owner account should be this user" Set-PSFConfig -Module dbachecks -Name agent.alert.messageid -Value @('823', '824', '825') -Initialize -Description "Agent alert messageid to validate; https://www.brentozar.com/blitz/configure-sql-server-alerts/" -Set-PSFConfig -Module dbachecks -Name agent.alert.Severity -Value @('16', '17', '18', '19', '20', '21', '22', '23', '24', '25') -Initialize -Description "Agent alert severity to validate; https://www.brentozar.com/blitz/configure-sql-server-alerts/" -Set-PSFConfig -Module dbachecks -Name agent.alert.Job -Value $false -Initialize -Description "Should we check for an agent job for the Agent Alert checks?" -Set-PSFConfig -Module dbachecks -Name agent.alert.Notification -Value $true -Initialize -Description "Agent alert notification" +Set-PSFConfig -Module dbachecks -Name agent.alert.severity -Value @('16', '17', '18', '19', '20', '21', '22', '23', '24', '25') -Initialize -Description "Agent alert severity to validate; https://www.brentozar.com/blitz/configure-sql-server-alerts/" +Set-PSFConfig -Module dbachecks -Name agent.alert.job -Value $false -Initialize -Description "Should we check for an agent job for the Agent Alert checks?" +Set-PSFConfig -Module dbachecks -Name agent.alert.notification -Value $true -Initialize -Description "Agent alert notification" Set-PSFConfig -Module dbachecks -Name agent.history.maximumhistoryrows -Value 1000 -Initialize -Description "Maximum job history log size (in rows). The value -1 means disabled" Set-PSFConfig -Module dbachecks -Name agent.history.maximumjobhistoryrows -Value 100 -Initialize -Description "Maximum job history row per job. When the property is disabled the value is 0." Set-PSFConfig -Module dbachecks -Name agent.failedjob.excludecancelled -Value $false -Initialize -Description "Exclude agent jobs with a status of cancelled" From 1e89d367198183827c7081cdeabb10b58d424886 Mon Sep 17 00:00:00 2001 From: Rob Date: Fri, 20 Mar 2020 14:42:40 +0000 Subject: [PATCH 50/61] better reading this way --- internal/configurations/configuration.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/configurations/configuration.ps1 b/internal/configurations/configuration.ps1 index 9d097d60..e6457dc9 100644 --- a/internal/configurations/configuration.ps1 +++ b/internal/configurations/configuration.ps1 @@ -264,7 +264,7 @@ Set-PSFConfig -Module dbachecks -Name agent.validjobowner.name -Value "sa" -Init Set-PSFConfig -Module dbachecks -Name agent.alert.messageid -Value @('823', '824', '825') -Initialize -Description "Agent alert messageid to validate; https://www.brentozar.com/blitz/configure-sql-server-alerts/" Set-PSFConfig -Module dbachecks -Name agent.alert.severity -Value @('16', '17', '18', '19', '20', '21', '22', '23', '24', '25') -Initialize -Description "Agent alert severity to validate; https://www.brentozar.com/blitz/configure-sql-server-alerts/" Set-PSFConfig -Module dbachecks -Name agent.alert.job -Value $false -Initialize -Description "Should we check for an agent job for the Agent Alert checks?" -Set-PSFConfig -Module dbachecks -Name agent.alert.notification -Value $true -Initialize -Description "Agent alert notification" +Set-PSFConfig -Module dbachecks -Name agent.alert.notification -Value $true -Initialize -Description "Should we check for a notification for the Agent Alert checks?" Set-PSFConfig -Module dbachecks -Name agent.history.maximumhistoryrows -Value 1000 -Initialize -Description "Maximum job history log size (in rows). The value -1 means disabled" Set-PSFConfig -Module dbachecks -Name agent.history.maximumjobhistoryrows -Value 100 -Initialize -Description "Maximum job history row per job. When the property is disabled the value is 0." Set-PSFConfig -Module dbachecks -Name agent.failedjob.excludecancelled -Value $false -Initialize -Description "Exclude agent jobs with a status of cancelled" From a70f80fca7e96a42f2d5f6152b9a66ef684e8926 Mon Sep 17 00:00:00 2001 From: Rob Date: Fri, 20 Mar 2020 17:17:35 +0000 Subject: [PATCH 51/61] running jobs, long running jobs improvements --- checks/Agent.Tests.ps1 | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/checks/Agent.Tests.ps1 b/checks/Agent.Tests.ps1 index 215497da..81f7203e 100644 --- a/checks/Agent.Tests.ps1 +++ b/checks/Agent.Tests.ps1 @@ -133,7 +133,7 @@ Set-PSFConfig -Module dbachecks -Name global.notcontactable -Value $NotContactab Context "Testing database mail profile is set on $psitem" { $databasemailprofile = Get-DbcConfigValue agent.databasemailprofile It "database mail profile on $psitem is $databasemailprofile" { - (Connect-DbaInstance -SqlInstance $psitem).JobServer.DatabaseMailProfile | Should -Be $databasemailprofile -Because 'The database mail profile is required to send emails' + (Get-DbaDbMailProfile -SqlInstance $InstanceSMO).Name | Should -Be $databasemailprofile -Because 'The database mail profile is required to send emails' } } } @@ -328,9 +328,16 @@ Set-PSFConfig -Module dbachecks -Name global.notcontactable -Value $NotContactab } else { Context "Testing long running jobs on $psitem" { - foreach ($runningjob in $runningjobs | Where-Object { $_.AvgSec -ne 0 }) { - It "Running job $($runningjob.JobName) duration should not be more than $runningjobpercentage % extra of the average run time on $psitem" -Skip:$skip { - Assert-LongRunningJobs -runningjob $runningjob -runningjobpercentage $runningjobpercentage + if ($runningjobs) { + foreach ($runningjob in $runningjobs | Where-Object { $_.AvgSec -ne 0 }) { + It "Running job $($runningjob.JobName) duration should not be more than $runningjobpercentage % extra of the average run time on $psitem" -Skip:$skip { + Assert-LongRunningJobs -runningjob $runningjob -runningjobpercentage $runningjobpercentage + } + } + } + else { + It "There are no running jobs currently on $psitem" -Skip:$skip { + $True | SHould -BeTrue } } } @@ -385,8 +392,6 @@ Set-PSFConfig -Module dbachecks -Name global.notcontactable -Value $NotContactab DROP Table #dbachecksLastRunTime DROP Table #dbachecksAverageRunTime" $lastagentjobruns = Invoke-DbaQuery -SqlInstance $PSItem -Database msdb -Query $query - } - else { Context "Testing last job run time on $psitem" { foreach ($lastagentjobrun in $lastagentjobruns | Where-Object { $_.AvgSec -ne 0 }) { It "Job $($lastagentjobrun.JobName) last run duration should be not be greater than $runningjobpercentage % extra of the average run time on $psitem" -Skip:$skip { @@ -395,6 +400,13 @@ Set-PSFConfig -Module dbachecks -Name global.notcontactable -Value $NotContactab } } } + else { + Context "Testing last job run time on $psitem" { + It "Job average run time on $psitem" -Skip { + Assert-LastJobRun -lastagentjobrun $lastagentjobrun -runningjobpercentage $runningjobpercentage + } + } + } } } } From 36c3d52fcfb9a91dc19b78abd1f0365f55a89c96 Mon Sep 17 00:00:00 2001 From: Rob Date: Fri, 20 Mar 2020 17:18:21 +0000 Subject: [PATCH 52/61] release notes --- RELEASE.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/RELEASE.md b/RELEASE.md index 2955dd9a..6577eb71 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -5,6 +5,8 @@ Thank you Tracey tboggiano Thank you Rob Getting service accounts tests to pass if no service + Made long running jobs check work as expected + Improved Database Mail check ##Latest From 53482d4503b1240a041452ce70067268c1d2eeb2 Mon Sep 17 00:00:00 2001 From: Rob Date: Sat, 21 Mar 2020 14:24:47 +0000 Subject: [PATCH 53/61] skip alerts checks if we want to --- checks/Agent.Tests.ps1 | 9 +++++---- internal/configurations/configuration.ps1 | 2 ++ 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/checks/Agent.Tests.ps1 b/checks/Agent.Tests.ps1 index 81f7203e..5dd19bc0 100644 --- a/checks/Agent.Tests.ps1 +++ b/checks/Agent.Tests.ps1 @@ -200,6 +200,7 @@ Set-PSFConfig -Module dbachecks -Name global.notcontactable -Value $NotContactab $messageid = Get-DbcConfigValue agent.alert.messageid $AgentAlertJob = Get-DbcConfigValue agent.alert.Job $AgentAlertNotification = Get-DbcConfigValue agent.alert.Notification + $skip = Get-DbcConfigValue skip.agent.alert if ($NotContactable -contains $psitem) { Context "Testing Agent Alerts Severity exists on $psitem" { It "Can't Connect to $Psitem" { @@ -216,19 +217,19 @@ Set-PSFConfig -Module dbachecks -Name global.notcontactable -Value $NotContactab $alerts = Get-DbaAgentAlert -SqlInstance $psitem Context "Testing Agent Alerts Severity exists on $psitem" { ForEach ($sev in $severity) { - It "$psitem should have Severity $sev Alert" { + It "$psitem should have Severity $sev Alert" -Skip:$skip{ ($alerts.Where{ $psitem.Severity -eq $sev }) | Should -be $true -Because "Recommended Agent Alerts to exists http://blog.extreme-advice.com/2013/01/29/list-of-errors-and-severity-level-in-sql-server-with-catalog-view-sysmessages/" } - It "$psitem should have Severity $sev Alert enabled" { + It "$psitem should have Severity $sev Alert enabled" -Skip:$skip{ ($alerts.Where{ $psitem.Severity -eq $sev }) | Should -be $true -Because "Configured alerts should be enabled" } if ($AgentAlertJob) { - It "$psitem should have Jobname for Severity $sev Alert" { + It "$psitem should have Jobname for Severity $sev Alert" -Skip:$skip{ ($alerts.Where{ $psitem.Severity -eq $sev }).jobname -ne $null | Should -be $true -Because "Should notify by SQL Agent Job" } } if ($AgentAlertNotification) { - It "$psitem should have notification for Severity $sev Alert" { + It "$psitem should have notification for Severity $sev Alert" -Skip:$skip{ ($alerts.Where{ $psitem.Severity -eq $sev }).HasNotification -in 1, 2, 3, 4, 5, 6, 7 | Should -be $true -Because "Should notify by Agent notifications" } } diff --git a/internal/configurations/configuration.ps1 b/internal/configurations/configuration.ps1 index e6457dc9..0b7ab5fb 100644 --- a/internal/configurations/configuration.ps1 +++ b/internal/configurations/configuration.ps1 @@ -254,6 +254,8 @@ Set-PSFConfig -Module dbachecks -Name skip.security.localwindowsgroup -Validatio Set-PSFConfig -Module dbachecks -Name skip.security.publicrolepermission -Validation bool -Value $true -Initialize -Description "Skips the scan for if the public server role has permissions" Set-PSFConfig -Module dbachecks -Name skip.security.builtinadmin -Validation bool -Value $true -Initialize -Description "Skips the scan for BUILTIN\Administrators login" Set-PSFConfig -Module dbachecks -Name skip.security.guestuserconnect -Validation bool -Value $true -Initialize -Description "Skips the scan for guest user have CONNECT permission" +Set-PSFConfig -Module dbachecks -Name skip.agent.alert -Validation bool -Value $false -Initialize -Description "Skips the agent alerts checks" + #agent Set-PSFConfig -Module dbachecks -Name agent.dbaoperatorname -Value $null -Initialize -Description "Name of the DBA Operator in SQL Agent" From 57c620ce0d2e3fb3521473c895e27004faf59913 Mon Sep 17 00:00:00 2001 From: Rob Date: Sat, 21 Mar 2020 14:27:03 +0000 Subject: [PATCH 54/61] also these checks --- checks/Agent.Tests.ps1 | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/checks/Agent.Tests.ps1 b/checks/Agent.Tests.ps1 index 5dd19bc0..5748c392 100644 --- a/checks/Agent.Tests.ps1 +++ b/checks/Agent.Tests.ps1 @@ -237,19 +237,19 @@ Set-PSFConfig -Module dbachecks -Name global.notcontactable -Value $NotContactab } Context "Testing Agent Alerts MessageID exists on $psitem" { ForEach ($mid in $messageid) { - It "$psitem should have Message_ID $mid Alert" { + It "$psitem should have Message_ID $mid Alert" -Skip:$skip{ ($alerts.Where{ $psitem.messageid -eq $mid }) | Should -be $true -Because "Recommended Agent Alerts to exists http://blog.extreme-advice.com/2013/01/29/list-of-errors-and-severity-level-in-sql-server-with-catalog-view-sysmessages/" } - It "$psitem should have Message_ID $mid Alert enabled" { + It "$psitem should have Message_ID $mid Alert enabled" -Skip:$skip{ ($alerts.Where{ $psitem.messageid -eq $mid }) | Should -be $true -Because "Configured alerts should be enabled" } if ($AgentAlertJob) { - It "$psitem should have Job name for Message_ID $mid Alert" { + It "$psitem should have Job name for Message_ID $mid Alert" -Skip:$skip { ($alerts.Where{ $psitem.messageid -eq $mid }).jobname -ne $null | Should -be $true -Because "Should notify by SQL Agent Job" } } if ($AgentAlertNotification) { - It "$psitem should have notification for Message_ID $mid Alert" { + It "$psitem should have notification for Message_ID $mid Alert" -Skip:$skip { ($alerts.Where{ $psitem.messageid -eq $mid }).HasNotification -in 1, 2, 3, 4, 5, 6, 7 | Should -be $true -Because "Should notify by Agent notifications" } } From 20cf545f4b7354bd3e45503b39902d72dcba0554 Mon Sep 17 00:00:00 2001 From: Rob Date: Sat, 21 Mar 2020 14:41:31 +0000 Subject: [PATCH 55/61] we have added a context block --- tests/Unit.Tests.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Unit.Tests.ps1 b/tests/Unit.Tests.ps1 index cf291239..682d726a 100644 --- a/tests/Unit.Tests.ps1 +++ b/tests/Unit.Tests.ps1 @@ -129,7 +129,7 @@ Describe "Checking that each dbachecks Pester test is correctly formatted for Po } } It "$CheckName should have the right number of Context blocks as the AST doesnt parse how I like and I cant be bothered to fix it right now"{ - $Contexts.Count | Should -Be 23 -Because "There should be 23 context blocks in the Agent checks file" + $Contexts.Count | Should -Be 24 -Because "There should be 24 context blocks in the Agent checks file" } } } From ac1b6e296c9a378ce4cfc5e1efc249caa1a092f8 Mon Sep 17 00:00:00 2001 From: Rob Date: Sat, 21 Mar 2020 15:07:49 +0000 Subject: [PATCH 56/61] sometimes the module is loaded already and it still doesnt work --- checks/HADR.Tests.ps1 | 47 +++++++++++++++++++++++++------------------ 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/checks/HADR.Tests.ps1 b/checks/HADR.Tests.ps1 index 28f36599..cf356a4f 100644 --- a/checks/HADR.Tests.ps1 +++ b/checks/HADR.Tests.ps1 @@ -7,7 +7,7 @@ function Get-ClusterObject { [string]$ClusterVM ) - [pscustomobject]$return = @{} + [pscustomobject]$return = @{ } # Don't think you can use the cluster name here it won't run remotely try { $ErrorActionPreference = 'Stop' @@ -26,7 +26,7 @@ function Get-ClusterObject { $return.Groups = 'FailedToConnect' $return.AGs = 'FailedToConnect' } - $return.AvailabilityGroups = @{} + $return.AvailabilityGroups = @{ } #Add all the AGs foreach ($Ag in $return.AGs) { try { @@ -44,10 +44,11 @@ function Get-ClusterObject { # needs the failover cluster module if (-not (Get-Module FailoverClusters)) { try { - if($IsCoreCLR){ + if ($IsCoreCLR) { Stop-PSFFunction -Message "FailoverClusters module cannot be loaded in PowerShell Core unfortunately" -ErrorRecord $psitem - return - }else{ + return + } + else { Import-Module FailoverClusters -ErrorAction Stop } } @@ -56,6 +57,12 @@ if (-not (Get-Module FailoverClusters)) { return } } +else { + if ($IsCoreCLR) { + Stop-PSFFunction -Message "FailoverClusters module cannot be loaded in PowerShell Core unfortunately" -ErrorRecord $psitem + return + } +} # Grab some values $clusters = Get-DbcConfigValue app.cluster @@ -70,11 +77,11 @@ if ($clusters.Count -eq 0) { } foreach ($clustervm in $clusters) { - try{ - # pick the name here for the output - we cant use it as we are accessing remotely - $clustername = (Get-Cluster -Name $clustervm -ErrorAction Stop).Name + try { + # pick the name here for the output - we cant use it as we are accessing remotely + $clustername = (Get-Cluster -Name $clustervm -ErrorAction Stop).Name } - catch{ + catch { # so that we dont get the error and Get-ClusterObject fills it as FailedtoConnect $clustername = $clustervm } @@ -97,9 +104,9 @@ foreach ($clustervm in $clusters) { } } # Get the resources where IP Address is owned by AG and group by AG - @($return.Resources.Where{$_.ResourceType -eq 'IP Address' -and $_.OwnerGroup -in $return.AGs} | Group-Object -Property OwnerGroup).ForEach{ + @($return.Resources.Where{ $_.ResourceType -eq 'IP Address' -and $_.OwnerGroup -in $return.AGs } | Group-Object -Property OwnerGroup).ForEach{ It "One of the IP Addresses for Availability Group $($Psitem.Name) Should be online" { - $psitem.Group.Where{$_.State -eq 'Online'}.Count | Should -Be 1 -Because "There should be one IP Address online for Availability Group $($PSItem.Name)" + $psitem.Group.Where{ $_.State -eq 'Online' }.Count | Should -Be 1 -Because "There should be one IP Address online for Availability Group $($PSItem.Name)" } } } @@ -130,15 +137,15 @@ foreach ($clustervm in $clusters) { Context "Cluster Connectivity for Availability Group $($AG.Name) on $clustername" { @($AG.AvailabilityGroupListeners).ForEach{ - try{ + try { $results = Test-DbaConnection -sqlinstance $_.Name } - Catch{ + Catch { $results = [PSCustomObject]@{ - IsPingable = $false - ConnectSuccess = $false - DomainName = $false - TCPPort = $false + IsPingable = $false + ConnectSuccess = $false + DomainName = $false + TCPPort = $false } } @@ -197,7 +204,7 @@ foreach ($clustervm in $clusters) { } Context "Database availability group status for $($AG.Name) on $clustername" { - @($ag.AvailabilityReplicas.Where{$_.AvailabilityMode -eq 'SynchronousCommit' }).ForEach{ + @($ag.AvailabilityReplicas.Where{ $_.AvailabilityMode -eq 'SynchronousCommit' }).ForEach{ @(Get-DbaAgDatabase -SqlInstance $psitem.Name -AvailabilityGroup $Ag.Name).ForEach{ It "Database $($psitem.DatabaseName) should be synchronised on the replica $($psitem.Replica)" { $psitem.SynchronizationState | Should -Be 'Synchronized' -Because 'The database on the synchronous replica should be synchronised' @@ -213,7 +220,7 @@ foreach ($clustervm in $clusters) { } } } - @($ag.AvailabilityReplicas.Where{$_.AvailabilityMode -eq 'AsynchronousCommit' }).ForEach{ + @($ag.AvailabilityReplicas.Where{ $_.AvailabilityMode -eq 'AsynchronousCommit' }).ForEach{ @(Get-DbaAgDatabase -SqlInstance $PSItem.Name -AvailabilityGroup $Ag.Name).ForEach{ It "Database $($psitem.DatabaseName) should be synchronising on the secondary as it is Async" { $psitem.SynchronizationState | Should -Be 'Synchronizing' -Because 'The database on the asynchronous secondary replica should be synchronising' @@ -240,7 +247,7 @@ foreach ($clustervm in $clusters) { $Xevents = 'FailedToConnect' } It "Replica $($psitem.Name) should have an extended event session called AlwaysOn_health" { - $Xevents.Name | Should -Contain 'AlwaysOn_health' -Because 'The extended events session should exist' + $Xevents.Name | Should -Contain 'AlwaysOn_health' -Because 'The extended events session should exist' } It "Replica $($psitem.Name) Always On Health extended event session should be running" { $Xevents.Where{ $_.Name -eq 'AlwaysOn_health' }.Status | Should -Be 'Running' -Because 'The extended event session will enable you to troubleshoot errors' From ef4272e93a73c23da31eea2770885a9c48fcf7ff Mon Sep 17 00:00:00 2001 From: Rob Date: Sat, 21 Mar 2020 15:21:04 +0000 Subject: [PATCH 57/61] this check doesnt run on core --- checks/Server.Tests.ps1 | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/checks/Server.Tests.ps1 b/checks/Server.Tests.ps1 index bdd952ce..de5d60b9 100644 --- a/checks/Server.Tests.ps1 +++ b/checks/Server.Tests.ps1 @@ -63,18 +63,27 @@ Return } Describe "Disk Allocation Unit" -Tags DiskAllocationUnit, Medium, $filename { - Context "Testing disk allocation unit on $psitem" { - $computerName = $psitem - $excludedisks = Get-DbcConfigValue policy.server.excludeDiskAllocationUnit - @($AllServerInfo.DiskAllocation).Where{$psitem.IsSqlDisk -eq $true}.ForEach{ - if($Psitem.Name -in $excludedisks){ - $exclude = $true + if($IsCoreCLR){ + Context "Testing disk allocation unit on $psitem" { + It "Can't run this check on Core on $psitem" -Skip { + $true | Should -BeTrue } - else { - $exclude = $false - } - It "$($Psitem.Name) Should be set to 64kb on $computerName" -Skip:$exclude { - Assert-DiskAllocationUnit -DiskAllocationObject $Psitem + } + } + else { + Context "Testing disk allocation unit on $psitem" { + $computerName = $psitem + $excludedisks = Get-DbcConfigValue policy.server.excludeDiskAllocationUnit + @($AllServerInfo.DiskAllocation).Where{$psitem.IsSqlDisk -eq $true}.ForEach{ + if($Psitem.Name -in $excludedisks){ + $exclude = $true + } + else { + $exclude = $false + } + It "$($Psitem.Name) Should be set to 64kb on $computerName" -Skip:$exclude { + Assert-DiskAllocationUnit -DiskAllocationObject $Psitem + } } } } From 331d24554301ae7af7b26c56589cdc16545a848a Mon Sep 17 00:00:00 2001 From: Rob Date: Sat, 21 Mar 2020 15:22:46 +0000 Subject: [PATCH 58/61] release notes --- RELEASE.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/RELEASE.md b/RELEASE.md index 6577eb71..6fb47efb 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -7,6 +7,10 @@ Thank you Rob Getting service accounts tests to pass if no service Made long running jobs check work as expected Improved Database Mail check + Made sure disk allocations dont run on Core + +Thank you mikedavem + Fixed bug in disk allocation check exclusions ##Latest From 0ddee2bbbf4c54a7ab0bd78bd51c86f261b3fbef Mon Sep 17 00:00:00 2001 From: Rob Date: Sat, 21 Mar 2020 15:36:40 +0000 Subject: [PATCH 59/61] fixed whitespace to pass the pester --- checks/Server.Tests.ps1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/checks/Server.Tests.ps1 b/checks/Server.Tests.ps1 index de5d60b9..79113053 100644 --- a/checks/Server.Tests.ps1 +++ b/checks/Server.Tests.ps1 @@ -64,12 +64,12 @@ Return Describe "Disk Allocation Unit" -Tags DiskAllocationUnit, Medium, $filename { if($IsCoreCLR){ - Context "Testing disk allocation unit on $psitem" { + Context "Testing disk allocation unit on $psitem" { It "Can't run this check on Core on $psitem" -Skip { $true | Should -BeTrue } } - } + } else { Context "Testing disk allocation unit on $psitem" { $computerName = $psitem From d7af3bb8f35ff0a2c967b80105961f53082aeae1 Mon Sep 17 00:00:00 2001 From: Rob Date: Sat, 21 Mar 2020 16:19:59 +0000 Subject: [PATCH 60/61] move the skip --- checks/Instance.Tests.ps1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/checks/Instance.Tests.ps1 b/checks/Instance.Tests.ps1 index bebac21d..c9565387 100644 --- a/checks/Instance.Tests.ps1 +++ b/checks/Instance.Tests.ps1 @@ -1157,8 +1157,8 @@ $Tags = Get-CheckInformation -Check $Check -Group Instance -AllChecks $AllChecks } } else { - Context "Testing if the new SQL logins that have not logged have to change their password when they log in on $psitem" -Skip:$skip { - It "All new sql logins should have the have to change their password when they log in for the first time on $psitem" { + Context "Testing if the new SQL logins that have not logged have to change their password when they log in on $psitem"{ + It "All new sql logins should have the have to change their password when they log in for the first time on $psitem" -Skip:$skip { Assert-LoginMustChange -AllInstanceInfo $AllInstanceInfo } } From ae9b1eb2926fff89d5399f4efe9d4aca8edb56b2 Mon Sep 17 00:00:00 2001 From: Rob Date: Sat, 21 Mar 2020 16:20:10 +0000 Subject: [PATCH 61/61] use the right command name --- internal/assertions/Instance.Assertions.ps1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/assertions/Instance.Assertions.ps1 b/internal/assertions/Instance.Assertions.ps1 index 6a3b6a2c..c60f2c3c 100644 --- a/internal/assertions/Instance.Assertions.ps1 +++ b/internal/assertions/Instance.Assertions.ps1 @@ -723,7 +723,7 @@ function Get-AllInstanceInfo { 'LoginPasswordExpiration' { if ($There) { try { - $role = GetDbaServerRole -SQLInstance $instance -ServerRole "sysadmin" + $role = Get-DbaServerRole -SQLInstance $instance -ServerRole "sysadmin" $LoginPasswordExpiration = [pscustomobject] @{ Count = @(Get-DbaLogin -SQLInstance $instance -Login @($role.Login) -Type SQL | Where-Object { $_.PasswordExpirationEnabled -eq $false -and $_.IsDisabled -eq $false}).Count @@ -746,7 +746,7 @@ function Get-AllInstanceInfo { 'LoginMustChange' { if ($There) { try { - $role = GetDbaServerRole -SQLInstance $instance -ServerRole "sysadmin" + $role = Get-DbaServerRole -SQLInstance $instance -ServerRole "sysadmin" $LoginMustChange = [pscustomobject] @{ Count = @(Get-DbaLogin -SQLInstance $instance -Login @($role.Login) -Type SQL | Where-Object { $_.IsMustChange -eq $false -and $_.IsDisabled -eq $false -and $null -eq $_LastLogin }).Count