diff --git a/CHANGELOG.md b/CHANGELOG.md index 66ce015d16..3d5b5a8b0e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added integration tests for `Remove-SqlDscAudit` command to ensure it functions correctly in real environments [issue #2241](https://github.com/dsccommunity/SqlServerDsc/issues/2241). +- Added integration tests for `Enable-SqlDscAudit` command to ensure command + reliability [issue #2223](https://github.com/dsccommunity/SqlServerDsc/issues/2223). - Added integration tests for `Get-SqlDscAudit` command to ensure it functions correctly in real environments [issue #2222](https://github.com/dsccommunity/SqlServerDsc/issues/2222). diff --git a/azure-pipelines.yml b/azure-pipelines.yml index baacdaee67..1da4f3a0e0 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -347,6 +347,7 @@ stages: # Group 8 'tests/Integration/Commands/Remove-SqlDscAgentAlert.Integration.Tests.ps1' 'tests/Integration/Commands/Remove-SqlDscAgentOperator.Integration.Tests.ps1' + 'tests/Integration/Commands/Enable-SqlDscAudit.Integration.Tests.ps1' 'tests/Integration/Commands/Get-SqlDscAudit.Integration.Tests.ps1' 'tests/Integration/Commands/Remove-SqlDscAudit.Integration.Tests.ps1' 'tests/Integration/Commands/Set-SqlDscAudit.Integration.Tests.ps1' diff --git a/tests/Integration/Commands/Disconnect-SqlDscDatabaseEngine.Integration.Tests.ps1 b/tests/Integration/Commands/Disconnect-SqlDscDatabaseEngine.Integration.Tests.ps1 index 88a6cc0683..60e9f3c5d0 100644 --- a/tests/Integration/Commands/Disconnect-SqlDscDatabaseEngine.Integration.Tests.ps1 +++ b/tests/Integration/Commands/Disconnect-SqlDscDatabaseEngine.Integration.Tests.ps1 @@ -36,6 +36,16 @@ Describe 'Disconnect-SqlDscDatabaseEngine' -Tag @('Integration_SQL2017', 'Integr } Context 'When disconnecting from the default instance' { + BeforeAll { + # Starting the default instance SQL Server service prior to running tests. + Start-Service -Name 'MSSQLSERVER' -Verbose -ErrorAction 'Stop' + } + + AfterAll { + # Stop the default instance SQL Server service to save memory on the build worker. + Stop-Service -Name 'MSSQLSERVER' -Verbose -ErrorAction 'Stop' + } + It 'Should have the default instance SQL Server service started' { $getServiceResult = Get-Service -Name 'MSSQLSERVER' -ErrorAction 'Stop' diff --git a/tests/Integration/Commands/Enable-SqlDscAudit.Integration.Tests.ps1 b/tests/Integration/Commands/Enable-SqlDscAudit.Integration.Tests.ps1 new file mode 100644 index 0000000000..32a05a70f8 --- /dev/null +++ b/tests/Integration/Commands/Enable-SqlDscAudit.Integration.Tests.ps1 @@ -0,0 +1,262 @@ +[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '', Justification = 'Suppressing this rule because Script Analyzer does not understand Pester syntax.')] +[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingConvertToSecureStringWithPlainText', '', Justification = 'Using ConvertTo-SecureString with plaintext is allowed in tests.')] +[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingEmptyCatchBlock', '', Justification = 'Empty catch blocks are used intentionally for cleanup in test teardown.')] +param () + +BeforeDiscovery { + try + { + if (-not (Get-Module -Name 'DscResource.Test')) + { + # Assumes dependencies have been resolved, so if this module is not available, run 'noop' task. + if (-not (Get-Module -Name 'DscResource.Test' -ListAvailable)) + { + # Redirect all streams to $null, except the error stream (stream 2) + & "$PSScriptRoot/../../../build.ps1" -Tasks 'noop' 3>&1 4>&1 5>&1 6>&1 > $null + } + + # If the dependencies have not been resolved, this will throw an error. + Import-Module -Name 'DscResource.Test' -Force -ErrorAction 'Stop' + } + } + catch [System.IO.FileNotFoundException] + { + throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -ResolveDependency -Tasks noop" first.' + } +} + +BeforeAll { + $script:moduleName = 'SqlServerDsc' + + Import-Module -Name $script:moduleName -Force -ErrorAction 'Stop' +} + +Describe 'Enable-SqlDscAudit' -Tag @('Integration_SQL2017', 'Integration_SQL2019', 'Integration_SQL2022') { + BeforeAll { + $script:mockInstanceName = 'DSCSQLTEST' + $script:mockComputerName = Get-ComputerName + + $mockSqlAdministratorUserName = 'SqlAdmin' # Using computer name as NetBIOS name throw exception. + $mockSqlAdministratorPassword = ConvertTo-SecureString -String 'P@ssw0rd1' -AsPlainText -Force + + $script:mockSqlAdminCredential = [System.Management.Automation.PSCredential]::new($mockSqlAdministratorUserName, $mockSqlAdministratorPassword) + + $script:serverObject = Connect-SqlDscDatabaseEngine -InstanceName $script:mockInstanceName -Credential $script:mockSqlAdminCredential -ErrorAction Stop + } + + AfterAll { + Disconnect-SqlDscDatabaseEngine -ServerObject $script:serverObject + } + + Context 'When enabling an audit using ServerObject parameter set' { + BeforeEach { + # Create a test audit for each test (disabled by default) + $script:testAuditName = 'SqlDscTestEnableAudit_' + (Get-Random) + $null = New-SqlDscAudit -ServerObject $script:serverObject -Name $script:testAuditName -LogType 'ApplicationLog' -Force -ErrorAction Stop + + # Verify audit is created but disabled + $auditObject = Get-SqlDscAudit -ServerObject $script:serverObject -Name $script:testAuditName -ErrorAction Stop + $auditObject.Enabled | Should -BeFalse + } + + AfterEach { + # Clean up: disable and remove the test audit + try { + $auditObject = Get-SqlDscAudit -ServerObject $script:serverObject -Name $script:testAuditName -ErrorAction 'SilentlyContinue' + if ($auditObject) { + if ($auditObject.Enabled) { + $auditObject.Disable() + } + $null = Remove-SqlDscAudit -ServerObject $script:serverObject -Name $script:testAuditName -Force -ErrorAction 'SilentlyContinue' + } + } + catch { + # Ignore cleanup errors + } + } + + It 'Should enable an audit successfully' { + # Enable the audit + $null = Enable-SqlDscAudit -ServerObject $script:serverObject -Name $script:testAuditName -Force -ErrorAction Stop + + # Verify audit is now enabled + $enabledAudit = Get-SqlDscAudit -ServerObject $script:serverObject -Name $script:testAuditName -ErrorAction Stop + $enabledAudit.Enabled | Should -BeTrue + } + + It 'Should throw error when trying to enable non-existent audit' { + { Enable-SqlDscAudit -ServerObject $script:serverObject -Name 'NonExistentAudit' -Force -ErrorAction Stop } | + Should -Throw + } + + It 'Should support the Refresh parameter' { + # Enable the audit with Refresh parameter + $null = Enable-SqlDscAudit -ServerObject $script:serverObject -Name $script:testAuditName -Refresh -Force -ErrorAction Stop + + # Verify audit is now enabled + $enabledAudit = Get-SqlDscAudit -ServerObject $script:serverObject -Name $script:testAuditName -ErrorAction Stop + $enabledAudit.Enabled | Should -BeTrue + } + + It 'Should not fail when enabling an already enabled audit' { + # Enable the audit first time + $null = Enable-SqlDscAudit -ServerObject $script:serverObject -Name $script:testAuditName -Force -ErrorAction Stop + + # Verify audit is enabled + $enabledAudit = Get-SqlDscAudit -ServerObject $script:serverObject -Name $script:testAuditName -ErrorAction Stop + $enabledAudit.Enabled | Should -BeTrue + + # Enable the audit again - should not fail + { Enable-SqlDscAudit -ServerObject $script:serverObject -Name $script:testAuditName -Force -ErrorAction Stop } | + Should -Not -Throw + + # Verify audit is still enabled + $stillEnabledAudit = Get-SqlDscAudit -ServerObject $script:serverObject -Name $script:testAuditName -ErrorAction Stop + $stillEnabledAudit.Enabled | Should -BeTrue + } + } + + Context 'When enabling an audit using AuditObject parameter set' { + BeforeEach { + # Create a test audit for each test (disabled by default) + $script:testAuditNameForObject = 'SqlDscTestEnableAuditObj_' + (Get-Random) + $null = New-SqlDscAudit -ServerObject $script:serverObject -Name $script:testAuditNameForObject -LogType 'ApplicationLog' -Force -ErrorAction Stop + + # Verify audit is created but disabled + $auditObject = Get-SqlDscAudit -ServerObject $script:serverObject -Name $script:testAuditNameForObject -ErrorAction Stop + $auditObject.Enabled | Should -BeFalse + } + + AfterEach { + # Clean up: disable and remove the test audit + try { + $auditObject = Get-SqlDscAudit -ServerObject $script:serverObject -Name $script:testAuditNameForObject -ErrorAction 'SilentlyContinue' + if ($auditObject) { + if ($auditObject.Enabled) { + $auditObject.Disable() + } + $null = Remove-SqlDscAudit -ServerObject $script:serverObject -Name $script:testAuditNameForObject -Force -ErrorAction 'SilentlyContinue' + } + } + catch { + # Ignore cleanup errors + } + } + + It 'Should enable an audit using audit object' { + $auditObject = Get-SqlDscAudit -ServerObject $script:serverObject -Name $script:testAuditNameForObject -ErrorAction Stop + $auditObject | Should -Not -BeNullOrEmpty + $auditObject.Enabled | Should -BeFalse + + # Enable the audit using audit object + $null = Enable-SqlDscAudit -AuditObject $auditObject -Force -ErrorAction Stop + + # Verify audit is now enabled + $enabledAudit = Get-SqlDscAudit -ServerObject $script:serverObject -Name $script:testAuditNameForObject -ErrorAction Stop + $enabledAudit.Enabled | Should -BeTrue + } + + It 'Should support pipeline input with audit object' { + $auditObject = Get-SqlDscAudit -ServerObject $script:serverObject -Name $script:testAuditNameForObject -ErrorAction Stop + $auditObject | Should -Not -BeNullOrEmpty + $auditObject.Enabled | Should -BeFalse + + # Enable the audit using pipeline + $auditObject | Enable-SqlDscAudit -Force -ErrorAction Stop + + # Verify audit is now enabled + $enabledAudit = Get-SqlDscAudit -ServerObject $script:serverObject -Name $script:testAuditNameForObject -ErrorAction Stop + $enabledAudit.Enabled | Should -BeTrue + } + } + + Context 'When enabling an audit using ServerObject parameter set with pipeline' { + BeforeEach { + # Create a test audit for each test (disabled by default) + $script:testAuditNameForPipeline = 'SqlDscTestEnableAuditPipe_' + (Get-Random) + $null = New-SqlDscAudit -ServerObject $script:serverObject -Name $script:testAuditNameForPipeline -LogType 'ApplicationLog' -Force -ErrorAction Stop + + # Verify audit is created but disabled + $auditObject = Get-SqlDscAudit -ServerObject $script:serverObject -Name $script:testAuditNameForPipeline -ErrorAction Stop + $auditObject.Enabled | Should -BeFalse + } + + AfterEach { + # Clean up: disable and remove the test audit + try { + $auditObject = Get-SqlDscAudit -ServerObject $script:serverObject -Name $script:testAuditNameForPipeline -ErrorAction 'SilentlyContinue' + if ($auditObject) { + if ($auditObject.Enabled) { + $auditObject.Disable() + } + $null = Remove-SqlDscAudit -ServerObject $script:serverObject -Name $script:testAuditNameForPipeline -Force -ErrorAction 'SilentlyContinue' + } + } + catch { + # Ignore cleanup errors + } + } + + It 'Should support pipeline input with server object' { + # Enable the audit using pipeline with server object + $script:serverObject | Enable-SqlDscAudit -Name $script:testAuditNameForPipeline -Force -ErrorAction Stop + + # Verify audit is now enabled + $enabledAudit = Get-SqlDscAudit -ServerObject $script:serverObject -Name $script:testAuditNameForPipeline -ErrorAction Stop + $enabledAudit.Enabled | Should -BeTrue + } + } + + Context 'When enabling multiple audits' { + BeforeAll { + # Create multiple test audits (disabled by default) + $script:testAuditNames = @( + 'SqlDscTestMultiEnable1_' + (Get-Random), + 'SqlDscTestMultiEnable2_' + (Get-Random) + ) + + foreach ($auditName in $script:testAuditNames) + { + $null = New-SqlDscAudit -ServerObject $script:serverObject -Name $auditName -LogType 'ApplicationLog' -Force -ErrorAction Stop + + # Verify audit is created but disabled + $auditObject = Get-SqlDscAudit -ServerObject $script:serverObject -Name $auditName -ErrorAction Stop + $auditObject.Enabled | Should -BeFalse + } + } + + AfterAll { + # Clean up: disable and remove all test audits + foreach ($auditName in $script:testAuditNames) + { + try { + $auditObject = Get-SqlDscAudit -ServerObject $script:serverObject -Name $auditName -ErrorAction 'SilentlyContinue' + if ($auditObject) { + if ($auditObject.Enabled) { + $auditObject.Disable() + } + $null = Remove-SqlDscAudit -ServerObject $script:serverObject -Name $auditName -Force -ErrorAction 'SilentlyContinue' + } + } + catch { + # Ignore cleanup errors + } + } + } + + It 'Should enable multiple audits successfully' { + # Enable the audits + foreach ($auditName in $script:testAuditNames) + { + $null = Enable-SqlDscAudit -ServerObject $script:serverObject -Name $auditName -Force -ErrorAction Stop + } + + # Verify audits are now enabled + foreach ($auditName in $script:testAuditNames) + { + $enabledAudit = Get-SqlDscAudit -ServerObject $script:serverObject -Name $auditName -ErrorAction Stop + $enabledAudit.Enabled | Should -BeTrue + } + } + } +} diff --git a/tests/Integration/Commands/Get-SqlDscAudit.Integration.Tests.ps1 b/tests/Integration/Commands/Get-SqlDscAudit.Integration.Tests.ps1 index 739659414a..011dbd5b4e 100644 --- a/tests/Integration/Commands/Get-SqlDscAudit.Integration.Tests.ps1 +++ b/tests/Integration/Commands/Get-SqlDscAudit.Integration.Tests.ps1 @@ -31,9 +31,6 @@ BeforeAll { Describe 'Get-SqlDscAudit' -Tag @('Integration_SQL2017', 'Integration_SQL2019', 'Integration_SQL2022') { BeforeAll { - # Starting the named instance SQL Server service prior to running tests. - Start-Service -Name 'MSSQL$DSCSQLTEST' -Verbose -ErrorAction 'Stop' - $script:mockInstanceName = 'DSCSQLTEST' $script:mockComputerName = Get-ComputerName @@ -73,9 +70,6 @@ Describe 'Get-SqlDscAudit' -Tag @('Integration_SQL2017', 'Integration_SQL2019', } Disconnect-SqlDscDatabaseEngine -ServerObject $script:serverObject - - # Stop the named instance SQL Server service to save memory on the build worker. - Stop-Service -Name 'MSSQL$DSCSQLTEST' -Verbose -ErrorAction 'Stop' } Context 'When getting all SQL Server audits' { diff --git a/tests/Integration/Commands/README.md b/tests/Integration/Commands/README.md index 00ef883379..d70496255a 100644 --- a/tests/Integration/Commands/README.md +++ b/tests/Integration/Commands/README.md @@ -63,6 +63,7 @@ Set-SqlDscStartupParameter | 2 | 1 (Install-SqlDscServer), 0 (Prerequisites) | D Set-SqlDscTraceFlag | 2 | 1 (Install-SqlDscServer), 0 (Prerequisites) | DSCSQLTEST | - Disable-SqlDscLogin | 2 | 1 (Install-SqlDscServer), 0 (Prerequisites) | DSCSQLTEST | - Enable-SqlDscLogin | 2 | 1 (Install-SqlDscServer), 0 (Prerequisites) | DSCSQLTEST | - +Enable-SqlDscAudit | 2 | 1 (Install-SqlDscServer), 0 (Prerequisites) | DSCSQLTEST | - Test-SqlDscIsLogin | 2 | 1 (Install-SqlDscServer), 0 (Prerequisites) | DSCSQLTEST | - Test-SqlDscIsLoginEnabled | 2 | 1 (Install-SqlDscServer), 0 (Prerequisites) | DSCSQLTEST | - New-SqlDscRole | 2 | 1 (Install-SqlDscServer), 0 (Prerequisites) | DSCSQLTEST | SqlDscIntegrationTestRole_Persistent role