diff --git a/CHANGELOG.md b/CHANGELOG.md index bb961f34dc..58544425fd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,18 +36,26 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fixed environment variable persistence by using $GITHUB_ENV instead of job-level env declaration. - `Grant-SqlDscServerPermission` - - Added new public command to grant server permissions to a principal (Login or ServerRole) on a SQL Server Database Engine instance. + - Added new public command to grant server permissions to a principal + (Login or ServerRole) on a SQL Server Database Engine instance. - `Deny-SqlDscServerPermission` - - Added new public command to deny server permissions to a principal (Login or ServerRole). + - Added new public command to deny server permissions to a principal + (Login or ServerRole). - `Revoke-SqlDscServerPermission` - - Added new public command to revoke server permissions from a principal (Login or ServerRole). + - Added new public command to revoke server permissions from a principal + (Login or ServerRole). - `Test-SqlDscServerPermission` - - Added new public command with Grant/Deny parameter sets (and `-WithGrant`) to test server permissions for a principal. + - Added new public command with Grant/Deny parameter sets (and `-WithGrant`) + to test server permissions for a principal. - `Assert-SqlDscLogin` - Added new public command to validate that a specified SQL Server principal is a login. - `Enable-SqlDscLogin` - Added new public command to enable a SQL Server login. +- `Get-SqlDscServerPermission` + - Enhanced command to support pipeline input for Login and ServerRole + objects while maintaining backward compatibility with the original + parameter set. - `Disable-SqlDscLogin` - Added new public command to disable a SQL Server login. - `Test-SqlDscIsLoginEnabled` @@ -88,6 +96,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added documentation for `SqlIntegrationTest` user and `IntegrationTestSqlLogin` login. - Added run order information for `New-SqlDscLogin` integration test. +- `Get-SqlDscServerPermission` + - Enhanced the command to support server roles in addition to logins by + utilizing `Test-SqlDscIsRole` alongside the existing `Test-SqlDscIsLogin` + check. + - The command now accepts both login principals and server role principals + as the `Name` parameter (issue [#2063](https://github.com/dsccommunity/SqlServerDsc/issues/2063)). - `azure-pipelines.yml` - Remove `windows-2019` images fixes [#2106](https://github.com/dsccommunity/SqlServerDsc/issues/2106). - Move individual tasks to `windows-latest`. diff --git a/RequiredModules.psd1 b/RequiredModules.psd1 index 4bc2c97598..0aa702a685 100644 --- a/RequiredModules.psd1 +++ b/RequiredModules.psd1 @@ -28,7 +28,7 @@ Sampler = 'latest' 'Sampler.GitHubTasks' = 'latest' MarkdownLinkCheck = 'latest' - 'DscResource.Test' = 'latest' + 'DscResource.Test' = '0.17.2' xDscResourceDesigner = 'latest' # Build dependencies needed for using the module diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 14cc5cd786..221d53f4a1 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -317,7 +317,6 @@ stages: 'tests/Integration/Commands/Remove-SqlDscDatabase.Integration.Tests.ps1' 'tests/Integration/Commands/Remove-SqlDscRole.Integration.Tests.ps1' 'tests/Integration/Commands/Remove-SqlDscLogin.Integration.Tests.ps1' - # Group 9 'tests/Integration/Commands/Uninstall-SqlDscServer.Integration.Tests.ps1' ) diff --git a/source/Public/Deny-SqlDscServerPermission.ps1 b/source/Public/Deny-SqlDscServerPermission.ps1 index e680456043..d7dd127beb 100644 --- a/source/Public/Deny-SqlDscServerPermission.ps1 +++ b/source/Public/Deny-SqlDscServerPermission.ps1 @@ -104,25 +104,19 @@ function Deny-SqlDscServerPermission $permissionSet.$permissionName = $true } - # Get the permissions names that are set to $true in the ServerPermissionSet. - $permissionName = $permissionSet | - Get-Member -MemberType 'Property' | - Select-Object -ExpandProperty 'Name' | - Where-Object -FilterScript { - $permissionSet.$_ - } - try { $serverObject.Deny($permissionSet, $principalName) } catch { - $errorMessage = $script:localizedData.ServerPermission_Deny_FailedToDenyPermission -f $principalName, $serverObject.InstanceName + $errorMessage = $script:localizedData.ServerPermission_Deny_FailedToDenyPermission -f $principalName, $serverObject.InstanceName, ($Permission -join ',') + + $exception = [System.InvalidOperationException]::new($errorMessage, $_.Exception) $PSCmdlet.ThrowTerminatingError( [System.Management.Automation.ErrorRecord]::new( - $errorMessage, + $exception, 'DSDSP0001', # cSpell: disable-line [System.Management.Automation.ErrorCategory]::InvalidOperation, $principalName diff --git a/source/Public/Get-SqlDscServerPermission.ps1 b/source/Public/Get-SqlDscServerPermission.ps1 index f61f6ee70c..7807daed27 100644 --- a/source/Public/Get-SqlDscServerPermission.ps1 +++ b/source/Public/Get-SqlDscServerPermission.ps1 @@ -1,16 +1,38 @@ <# .SYNOPSIS - Returns the current permissions for the principal. + Returns the current permissions for a SQL Server login or server role. .DESCRIPTION - Returns the current permissions for the principal. + Returns the current permissions for a SQL Server login or server role. + The command can retrieve permissions for both user-defined and built-in + server principals including SQL Server logins and server roles. + + The command supports two modes of operation: + 1. By name: Specify ServerObject, Name, and optionally PrincipalType + 2. By object: Pass Login or ServerRole objects via pipeline .PARAMETER ServerObject - Specifies current server connection object. + Specifies current server connection object. This parameter is used in the + default parameter set for backward compatibility. .PARAMETER Name - Specifies the name of the principal for which the permissions are - returned. + Specifies the name of the SQL Server login or server role for which + the permissions are returned. This parameter is used in the default + parameter set for backward compatibility. + + .PARAMETER PrincipalType + Specifies the type(s) of principal to check. Valid values are 'Login' + and 'Role'. If not specified, both login and role checks will be performed. + If specified, only the specified type(s) will be checked. This parameter + is used in the default parameter set for backward compatibility. + + .PARAMETER Login + Specifies the Login object for which the permissions are returned. + This parameter accepts pipeline input. + + .PARAMETER ServerRole + Specifies the ServerRole object for which the permissions are returned. + This parameter accepts pipeline input. .OUTPUTS [Microsoft.SqlServer.Management.Smo.ServerPermissionInfo[]] @@ -21,28 +43,85 @@ Get the permissions for the principal 'MyPrincipal'. + .EXAMPLE + $serverInstance = Connect-SqlDscDatabaseEngine + Get-SqlDscServerPermission -ServerObject $serverInstance -Name 'sysadmin' + + Get the permissions for the server role 'sysadmin'. + + .EXAMPLE + $serverInstance = Connect-SqlDscDatabaseEngine + Get-SqlDscServerPermission -ServerObject $serverInstance -Name 'MyLogin' -PrincipalType 'Login' + + Get the permissions for the login 'MyLogin', only checking if it exists as a login. + + .EXAMPLE + $serverInstance = Connect-SqlDscDatabaseEngine + Get-SqlDscServerPermission -ServerObject $serverInstance -Name 'MyRole' -PrincipalType 'Role' + + Get the permissions for the server role 'MyRole', only checking if it exists as a role. + + .EXAMPLE + $serverInstance = Connect-SqlDscDatabaseEngine + $login = $serverInstance | Get-SqlDscLogin -Name 'MyLogin' + + Get-SqlDscServerPermission -Login $login + + Get the permissions for the login 'MyLogin' using a Login object. + + .EXAMPLE + $serverInstance = Connect-SqlDscDatabaseEngine + $role = $serverInstance | Get-SqlDscRole -Name 'MyRole' + + $role | Get-SqlDscServerPermission + + Get the permissions for the server role 'MyRole' using a ServerRole object from the pipeline. + + .EXAMPLE + $serverInstance = Connect-SqlDscDatabaseEngine + + $serverInstance | Get-SqlDscLogin | Get-SqlDscServerPermission + + Get the permissions for all logins from the pipeline. + .NOTES If specifying `-ErrorAction 'SilentlyContinue'` then the command will silently ignore if the principal (parameter **Name**) is not present. In such case the command will return `$null`. If specifying `-ErrorAction 'Stop'` the command will throw an error if the principal is missing. + + The Login or ServerRole object must come from the same SQL Server instance + where the permissions will be retrieved. #> function Get-SqlDscServerPermission { [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseOutputTypeCorrectly', '', Justification = 'Because the rule does not understands that the command returns [System.String[]] when using , (comma) in the return statement')] [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('UseSyntacticallyCorrectExamples', '', Justification = 'Because the rule does not yet support parsing the code when a parameter type is not available. The ScriptAnalyzer rule UseSyntacticallyCorrectExamples will always error in the editor due to https://github.com/indented-automation/Indented.ScriptAnalyzerRules/issues/8.')] [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('AvoidThrowOutsideOfTry', '', Justification = 'Because the code throws based on an prior expression')] - [CmdletBinding()] + [CmdletBinding(DefaultParameterSetName = 'ByName')] [OutputType([Microsoft.SqlServer.Management.Smo.ServerPermissionInfo[]])] param ( - [Parameter(Mandatory = $true, ValueFromPipeline = $true)] + [Parameter(Mandatory = $true, ValueFromPipeline = $true, ParameterSetName = 'ByName')] [Microsoft.SqlServer.Management.Smo.Server] $ServerObject, - [Parameter(Mandatory = $true)] + [Parameter(Mandatory = $true, ParameterSetName = 'ByName')] [System.String] - $Name + $Name, + + [Parameter(ParameterSetName = 'ByName')] + [ValidateSet('Login', 'Role')] + [System.String[]] + $PrincipalType, + + [Parameter(Mandatory = $true, ValueFromPipeline = $true, ParameterSetName = 'Login')] + [Microsoft.SqlServer.Management.Smo.Login] + $Login, + + [Parameter(Mandatory = $true, ValueFromPipeline = $true, ParameterSetName = 'ServerRole')] + [Microsoft.SqlServer.Management.Smo.ServerRole] + $ServerRole ) # cSpell: ignore GSDSP @@ -50,22 +129,71 @@ function Get-SqlDscServerPermission { $getSqlDscServerPermissionResult = $null - $testSqlDscIsLoginParameters = @{ - ServerObject = $ServerObject - Name = $Name + # Determine which parameter set we're using and set up variables accordingly + if ($PSCmdlet.ParameterSetName -eq 'Login') + { + $principalName = $Login.Name + $serverObject = $Login.Parent + $isLogin = $true + $isRole = $false + } + elseif ($PSCmdlet.ParameterSetName -eq 'ServerRole') + { + $principalName = $ServerRole.Name + $serverObject = $ServerRole.Parent + $isLogin = $false + $isRole = $true } + else + { + # ByName parameter set (default for backward compatibility) + $principalName = $Name + $serverObject = $ServerObject - $isLogin = Test-SqlDscIsLogin @testSqlDscIsLoginParameters + $testSqlDscIsPrincipalParameters = @{ + ServerObject = $serverObject + Name = $principalName + } + + # Determine which checks to perform based on PrincipalType parameter + $checkLogin = $true + $checkRole = $true + + if ($PSBoundParameters.ContainsKey('PrincipalType')) + { + $checkLogin = $PrincipalType -contains 'Login' + $checkRole = $PrincipalType -contains 'Role' + } + + # Perform the appropriate checks + $isLogin = if ($checkLogin) + { + Test-SqlDscIsLogin @testSqlDscIsPrincipalParameters + } + else + { + $false + } + + $isRole = if ($checkRole) + { + Test-SqlDscIsRole @testSqlDscIsPrincipalParameters + } + else + { + $false + } + } - if ($isLogin) + if ($isLogin -or $isRole) { - $getSqlDscServerPermissionResult = $ServerObject.EnumServerPermissions($Name) + $getSqlDscServerPermissionResult = $serverObject.EnumServerPermissions($principalName) } else { - $missingPrincipalMessage = $script:localizedData.ServerPermission_MissingPrincipal -f $Name, $ServerObject.InstanceName + $missingPrincipalMessage = $script:localizedData.ServerPermission_MissingPrincipal -f $principalName, $serverObject.InstanceName - Write-Error -Message $missingPrincipalMessage -Category 'InvalidOperation' -ErrorId 'GSDSP0001' -TargetObject $Name + Write-Error -Message $missingPrincipalMessage -Category 'InvalidOperation' -ErrorId 'GSDSP0001' -TargetObject $principalName } return , [Microsoft.SqlServer.Management.Smo.ServerPermissionInfo[]] $getSqlDscServerPermissionResult diff --git a/source/Public/Grant-SqlDscServerPermission.ps1 b/source/Public/Grant-SqlDscServerPermission.ps1 index 2c46e0bb7e..7589eefc7e 100644 --- a/source/Public/Grant-SqlDscServerPermission.ps1 +++ b/source/Public/Grant-SqlDscServerPermission.ps1 @@ -119,14 +119,6 @@ function Grant-SqlDscServerPermission $permissionSet.$permissionName = $true } - # Get the permissions names that are set to $true in the ServerPermissionSet. - $permissionName = $permissionSet | - Get-Member -MemberType 'Property' | - Select-Object -ExpandProperty 'Name' | - Where-Object -FilterScript { - $permissionSet.$_ - } - try { if ($WithGrant.IsPresent) @@ -140,11 +132,13 @@ function Grant-SqlDscServerPermission } catch { - $errorMessage = $script:localizedData.ServerPermission_Grant_FailedToGrantPermission -f $principalName, $serverObject.InstanceName + $errorMessage = $script:localizedData.ServerPermission_Grant_FailedToGrantPermission -f $principalName, $serverObject.InstanceName, ($Permission -join ', ') + + $exception = [System.InvalidOperationException]::new($errorMessage, $_.Exception) $PSCmdlet.ThrowTerminatingError( [System.Management.Automation.ErrorRecord]::new( - $errorMessage, + $exception, 'GSDSP0001', # cSpell: disable-line [System.Management.Automation.ErrorCategory]::InvalidOperation, $principalName diff --git a/source/Public/Revoke-SqlDscServerPermission.ps1 b/source/Public/Revoke-SqlDscServerPermission.ps1 index 2cc0f5286b..6b46907179 100644 --- a/source/Public/Revoke-SqlDscServerPermission.ps1 +++ b/source/Public/Revoke-SqlDscServerPermission.ps1 @@ -117,14 +117,6 @@ function Revoke-SqlDscServerPermission $permissionSet.$permissionName = $true } - # Get the permissions names that are set to $true in the ServerPermissionSet. - $permissionName = $permissionSet | - Get-Member -MemberType 'Property' | - Select-Object -ExpandProperty 'Name' | - Where-Object -FilterScript { - $permissionSet.$_ - } - try { if ($WithGrant.IsPresent) @@ -138,11 +130,13 @@ function Revoke-SqlDscServerPermission } catch { - $errorMessage = $script:localizedData.ServerPermission_Revoke_FailedToRevokePermission -f $principalName, $serverObject.InstanceName + $errorMessage = $script:localizedData.ServerPermission_Revoke_FailedToRevokePermission -f $principalName, $serverObject.InstanceName, ($Permission -join ',') + + $exception = [System.InvalidOperationException]::new($errorMessage, $_.Exception) $PSCmdlet.ThrowTerminatingError( [System.Management.Automation.ErrorRecord]::new( - $errorMessage, + $exception, 'RSDSP0001', # cSpell: disable-line [System.Management.Automation.ErrorCategory]::InvalidOperation, $principalName diff --git a/source/Public/Test-SqlDscIsRole.ps1 b/source/Public/Test-SqlDscIsRole.ps1 index 189e229c8b..d78aa658d2 100644 --- a/source/Public/Test-SqlDscIsRole.ps1 +++ b/source/Public/Test-SqlDscIsRole.ps1 @@ -1,15 +1,15 @@ <# .SYNOPSIS - Returns whether the database principal exists and is a database role. + Returns whether the server principal exists and is a server role. .DESCRIPTION - Returns whether the database principal exist and is a database role. + Returns whether the server principal exist and is a server role. .PARAMETER ServerObject Specifies current server connection object. .PARAMETER Name - Specifies the name of the database principal. + Specifies the name of the server principal. .OUTPUTS [System.Boolean] @@ -18,7 +18,7 @@ $serverInstance = Connect-SqlDscDatabaseEngine Test-SqlDscIsRole -ServerObject $serverInstance -Name 'MyPrincipal' - Returns $true if the principal exist as role, if not $false is returned. + Returns $true if the principal exist as a server role, if not $false is returned. #> function Test-SqlDscIsRole { diff --git a/source/Public/Test-SqlDscServerPermission.ps1 b/source/Public/Test-SqlDscServerPermission.ps1 index 2089dcbf50..557a46c72c 100644 --- a/source/Public/Test-SqlDscServerPermission.ps1 +++ b/source/Public/Test-SqlDscServerPermission.ps1 @@ -173,6 +173,10 @@ function Test-SqlDscServerPermission if (-not $serverPermissionInfo) { + Write-Debug -Message ( + $script:localizedData.ServerPermission_Test_NoPermissionsFound -f $principalName + ) + # If no permissions exist and none are desired, that's the desired state if ($Permission.Count -eq 0) { @@ -187,6 +191,13 @@ function Test-SqlDscServerPermission # Convert current permissions to ServerPermission objects $currentPermissions = $serverPermissionInfo | ConvertTo-SqlDscServerPermission + # Output verbose information about current permissions as compressed JSON + $currentPermissionsJson = $currentPermissions | ConvertTo-Json -Compress + + Write-Debug -Message ( + $script:localizedData.ServerPermission_Test_CurrentPermissions -f $principalName, $currentPermissionsJson + ) + # Handle empty Permission collection - check that no permissions are set if ($Permission.Count -eq 0) { diff --git a/source/en-US/SqlServerDsc.strings.psd1 b/source/en-US/SqlServerDsc.strings.psd1 index b5121d2152..8a24bf0219 100644 --- a/source/en-US/SqlServerDsc.strings.psd1 +++ b/source/en-US/SqlServerDsc.strings.psd1 @@ -42,25 +42,27 @@ ConvertFrom-StringData @' ServerPermission_Grant_ShouldProcessVerboseWarning = Are you sure you want to grant server permissions for the principal '{0}'? # This string shall not end with full stop (.) since it is used as a title of ShouldProcess messages. ServerPermission_Grant_ShouldProcessCaption = Grant server permissions - ServerPermission_Grant_FailedToGrantPermission = Failed to grant server permissions for principal '{0}' on instance '{1}'. + ServerPermission_Grant_FailedToGrantPermission = Failed to grant server permissions '{2}' for principal '{0}' on instance '{1}'. ## Deny-SqlDscServerPermission ServerPermission_Deny_ShouldProcessVerboseDescription = Denying server permissions '{2}' for the principal '{0}' on the instance '{1}'. ServerPermission_Deny_ShouldProcessVerboseWarning = Are you sure you want to deny server permissions for the principal '{0}'? # This string shall not end with full stop (.) since it is used as a title of ShouldProcess messages. ServerPermission_Deny_ShouldProcessCaption = Deny server permissions - ServerPermission_Deny_FailedToDenyPermission = Failed to deny server permissions for principal '{0}' on instance '{1}'. + ServerPermission_Deny_FailedToDenyPermission = Failed to deny server permissions '{2}' for principal '{0}' on instance '{1}'. ## Test-SqlDscServerPermission ServerPermission_TestingDesiredState = Testing desired state for server permissions for principal '{0}' on instance '{1}'. ServerPermission_Test_TestFailed = Failed to test server permissions for principal '{0}': {1} + ServerPermission_Test_CurrentPermissions = Current server permissions for principal '{0}': {1} + ServerPermission_Test_NoPermissionsFound = No server permissions found for principal '{0}'. ## Revoke-SqlDscServerPermission ServerPermission_Revoke_ShouldProcessVerboseDescription = Revoking server permissions '{2}' for the principal '{0}' on the instance '{1}'. ServerPermission_Revoke_ShouldProcessVerboseWarning = Are you sure you want to revoke server permissions for the principal '{0}'? # This string shall not end with full stop (.) since it is used as a title of ShouldProcess messages. ServerPermission_Revoke_ShouldProcessCaption = Revoke server permissions - ServerPermission_Revoke_FailedToRevokePermission = Failed to revoke server permissions for principal '{0}' on instance '{1}'. + ServerPermission_Revoke_FailedToRevokePermission = Failed to revoke server permissions '{2}' for principal '{0}' on instance '{1}'. ## Class DatabasePermission InvalidTypeForCompare = Invalid type in comparison. Expected type [{0}], but the type was [{1}]. (DP0001) diff --git a/tests/Integration/Commands/Assert-SqlDscLogin.Integration.Tests.ps1 b/tests/Integration/Commands/Assert-SqlDscLogin.Integration.Tests.ps1 index b9e13ddf28..3cdbba3c44 100644 --- a/tests/Integration/Commands/Assert-SqlDscLogin.Integration.Tests.ps1 +++ b/tests/Integration/Commands/Assert-SqlDscLogin.Integration.Tests.ps1 @@ -24,12 +24,12 @@ BeforeDiscovery { } BeforeAll { - $script:dscModuleName = 'SqlServerDsc' + $script:moduleName = 'SqlServerDsc' - Import-Module -Name $script:dscModuleName -Force -ErrorAction 'Stop' + Import-Module -Name $script:moduleName -Force -ErrorAction 'Stop' } -Describe 'Assert-SqlDscLogin' -Tag @('Integration_SQL2016', 'Integration_SQL2017', 'Integration_SQL2019', 'Integration_SQL2022') { +Describe 'Assert-SqlDscLogin' -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' @@ -53,6 +53,10 @@ Describe 'Assert-SqlDscLogin' -Tag @('Integration_SQL2016', 'Integration_SQL2017 $script:serverObject = Connect-SqlDscDatabaseEngine -InstanceName $script:instanceName -Credential $script:sqlAdminCredential } + AfterAll { + Disconnect-SqlDscDatabaseEngine -ServerObject $script:serverObject + } + Context 'When a login exists' { It 'Should not throw an error for sa login' { { Assert-SqlDscLogin -ServerObject $script:serverObject -Name 'sa' } | Should -Not -Throw diff --git a/tests/Integration/Commands/Connect-SqlDscDatabaseEngine.Integration.Tests.ps1 b/tests/Integration/Commands/Connect-SqlDscDatabaseEngine.Integration.Tests.ps1 index 46c9b1c359..59fb4d69ff 100644 --- a/tests/Integration/Commands/Connect-SqlDscDatabaseEngine.Integration.Tests.ps1 +++ b/tests/Integration/Commands/Connect-SqlDscDatabaseEngine.Integration.Tests.ps1 @@ -23,8 +23,14 @@ BeforeDiscovery { } } +BeforeAll { + $script:moduleName = 'SqlServerDsc' + + Import-Module -Name $script:moduleName -Force -ErrorAction 'Stop' +} + # cSpell: ignore DSCSQLTEST -Describe 'Connect-SqlDscDatabaseEngine' -Tag @('Integration_SQL2016', 'Integration_SQL2017', 'Integration_SQL2019', 'Integration_SQL2022') { +Describe 'Connect-SqlDscDatabaseEngine' -Tag @('Integration_SQL2017', 'Integration_SQL2019', 'Integration_SQL2022') { BeforeAll { Write-Verbose -Message ('Running integration test as user ''{0}''.' -f $env:UserName) -Verbose diff --git a/tests/Integration/Commands/Deny-SqlDscServerPermission.Integration.Tests.ps1 b/tests/Integration/Commands/Deny-SqlDscServerPermission.Integration.Tests.ps1 index a02e7db3a2..1ce96d96dd 100644 --- a/tests/Integration/Commands/Deny-SqlDscServerPermission.Integration.Tests.ps1 +++ b/tests/Integration/Commands/Deny-SqlDscServerPermission.Integration.Tests.ps1 @@ -29,55 +29,38 @@ BeforeAll { Import-Module -Name $script:moduleName -Force -ErrorAction 'Stop' } -AfterAll { - # Unload the module being tested so that it doesn't impact any other tests. - Get-Module -Name $script:moduleName -All | Remove-Module -Force -} - -Describe 'Deny-SqlDscServerPermission' -Tag 'IntegrationTest' { +Describe 'Deny-SqlDscServerPermission' -Tag @('Integration_SQL2017', 'Integration_SQL2019', 'Integration_SQL2022') { BeforeAll { - # Check if there is a CI database instance to use for testing - $script:sqlServerInstanceName = $env:SqlServerInstanceName + # Starting the named instance SQL Server service prior to running tests. + Start-Service -Name 'MSSQL$DSCSQLTEST' -Verbose -ErrorAction 'Stop' - if (-not $script:sqlServerInstanceName) - { - $script:sqlServerInstanceName = 'DSCSQLTEST' - } + $script:mockInstanceName = 'DSCSQLTEST' - # Get a computer name that will work in the CI environment - $script:computerName = Get-ComputerName + $mockSqlAdministratorUserName = 'SqlAdmin' # Using computer name as NetBIOS name throw exception. + $mockSqlAdministratorPassword = ConvertTo-SecureString -String 'P@ssw0rd1' -AsPlainText -Force - Write-Verbose -Message ('Integration tests will run using computer name ''{0}'' and instance name ''{1}''.' -f $script:computerName, $script:sqlServerInstanceName) -Verbose + $script:mockSqlAdminCredential = [System.Management.Automation.PSCredential]::new($mockSqlAdministratorUserName, $mockSqlAdministratorPassword) - $script:serverObject = Connect-SqlDscDatabaseEngine -ServerName $script:computerName -InstanceName $script:sqlServerInstanceName -Force + $script:serverObject = Connect-SqlDscDatabaseEngine -InstanceName $script:mockInstanceName -Credential $script:mockSqlAdminCredential -ErrorAction 'Stop' # Use persistent test login and role created by earlier integration tests $script:testLoginName = 'IntegrationTestSqlLogin' $script:testRoleName = 'SqlDscIntegrationTestRole_Persistent' - - # Verify the persistent principals exist (should be created by New-SqlDscLogin and New-SqlDscRole integration tests) - $existingLogin = Get-SqlDscLogin -ServerObject $script:serverObject -Name $script:testLoginName -ErrorAction 'SilentlyContinue' - if (-not $existingLogin) - { - throw ('Test login {0} does not exist. Please run New-SqlDscLogin integration tests first to create persistent test principals.' -f $script:testLoginName) - } - - $existingRole = Get-SqlDscRole -ServerObject $script:serverObject -Name $script:testRoleName -ErrorAction 'SilentlyContinue' - if (-not $existingRole) - { - throw ('Test role {0} does not exist. Please run New-SqlDscRole integration tests first to create persistent test principals.' -f $script:testRoleName) - } } AfterAll { 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 denying server permissions to login' { BeforeEach { $loginObject = Get-SqlDscLogin -ServerObject $script:serverObject -Name $script:testLoginName -ErrorAction 'Stop' - Revoke-SqlDscServerPermission -Login $loginObject -Permission ViewServerState -Force -ErrorAction 'SilentlyContinue' - Revoke-SqlDscServerPermission -Login $loginObject -Permission ViewAnyDefinition -Force -ErrorAction 'SilentlyContinue' + + Revoke-SqlDscServerPermission -Login $loginObject -Permission 'ViewServerState' -Force -ErrorAction 'SilentlyContinue' + Revoke-SqlDscServerPermission -Login $loginObject -Permission 'ViewAnyDefinition' -Force -ErrorAction 'SilentlyContinue' } It 'Should deny ViewServerState permission' { @@ -93,7 +76,7 @@ Describe 'Deny-SqlDscServerPermission' -Tag 'IntegrationTest' { $null = Deny-SqlDscServerPermission -Login $loginObject -Permission @('ViewAnyDatabase') -Force -ErrorAction 'Stop' # Then test if it's denied - $result = Test-SqlDscServerPermission -Login $loginObject -Deny -Permission @([SqlServerPermission]::ViewAnyDatabase) -ErrorAction 'Stop' + $result = Test-SqlDscServerPermission -Login $loginObject -Deny -Permission @('ViewAnyDatabase') -ErrorAction 'Stop' $result | Should -BeTrue } @@ -104,7 +87,7 @@ Describe 'Deny-SqlDscServerPermission' -Tag 'IntegrationTest' { $null = $loginObject | Deny-SqlDscServerPermission -Permission @('ViewAnyDefinition') -Force -ErrorAction 'Stop' # Verify the permission was denied - $result = Test-SqlDscServerPermission -Login $loginObject -Deny -Permission @([SqlServerPermission]::ViewAnyDefinition) -ErrorAction 'Stop' + $result = Test-SqlDscServerPermission -Login $loginObject -Deny -Permission @('ViewAnyDefinition') -ErrorAction 'Stop' $result | Should -BeTrue } } @@ -112,6 +95,7 @@ Describe 'Deny-SqlDscServerPermission' -Tag 'IntegrationTest' { Context 'When denying server permissions to role' { BeforeEach { $roleObject = Get-SqlDscRole -ServerObject $script:serverObject -Name $script:testRoleName -ErrorAction 'Stop' + Revoke-SqlDscServerPermission -ServerRole $roleObject -Permission 'ViewServerState' -Force -ErrorAction 'SilentlyContinue' } @@ -121,7 +105,7 @@ Describe 'Deny-SqlDscServerPermission' -Tag 'IntegrationTest' { $null = Deny-SqlDscServerPermission -ServerRole $roleObject -Permission @('ViewServerState') -Force -ErrorAction 'Stop' # Verify the permission was denied - $result = Test-SqlDscServerPermission -ServerRole $roleObject -Deny -Permission @([SqlServerPermission]::ViewServerState) -ErrorAction 'Stop' + $result = Test-SqlDscServerPermission -ServerRole $roleObject -Deny -Permission @('ViewServerState') -ErrorAction 'Stop' $result | Should -BeTrue } @@ -131,7 +115,16 @@ Describe 'Deny-SqlDscServerPermission' -Tag 'IntegrationTest' { $null = Deny-SqlDscServerPermission -Login $loginObject -Permission @('AlterTrace') -Force -ErrorAction 'Stop' # Verify the permission was denied - this denial will remain persistent for other integration tests - $result = Test-SqlDscServerPermission -Login $loginObject -Deny -Permission @([SqlServerPermission]::AlterTrace) -ErrorAction 'Stop' + $result = Test-SqlDscServerPermission -Login $loginObject -Deny -Permission @('AlterTrace') -ErrorAction 'Stop' + $result | Should -BeTrue + } + + It 'Should accept ServerRole from pipeline' { + $roleObject = Get-SqlDscRole -ServerObject $script:serverObject -Name $script:testRoleName -ErrorAction 'Stop' + + $null = $roleObject | Deny-SqlDscServerPermission -Permission @('ViewServerState') -Force -ErrorAction 'Stop' + + $result = Test-SqlDscServerPermission -ServerRole $roleObject -Deny -Permission @('ViewServerState') -ErrorAction 'Stop' $result | Should -BeTrue } } diff --git a/tests/Integration/Commands/Disable-SqlDscLogin.Integration.Tests.ps1 b/tests/Integration/Commands/Disable-SqlDscLogin.Integration.Tests.ps1 index ea9c484616..1c86325aac 100644 --- a/tests/Integration/Commands/Disable-SqlDscLogin.Integration.Tests.ps1 +++ b/tests/Integration/Commands/Disable-SqlDscLogin.Integration.Tests.ps1 @@ -24,12 +24,12 @@ BeforeDiscovery { } BeforeAll { - $script:dscModuleName = 'SqlServerDsc' + $script:moduleName = 'SqlServerDsc' - Import-Module -Name $script:dscModuleName -Force -ErrorAction 'Stop' + Import-Module -Name $script:moduleName -Force -ErrorAction 'Stop' } -Describe 'Disable-SqlDscLogin' -Tag @('Integration_SQL2016', 'Integration_SQL2017', 'Integration_SQL2019', 'Integration_SQL2022') { +Describe 'Disable-SqlDscLogin' -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' diff --git a/tests/Integration/Commands/Enable-SqlDscLogin.Integration.Tests.ps1 b/tests/Integration/Commands/Enable-SqlDscLogin.Integration.Tests.ps1 index d23c3ba1d9..48f0b03748 100644 --- a/tests/Integration/Commands/Enable-SqlDscLogin.Integration.Tests.ps1 +++ b/tests/Integration/Commands/Enable-SqlDscLogin.Integration.Tests.ps1 @@ -24,12 +24,12 @@ BeforeDiscovery { } BeforeAll { - $script:dscModuleName = 'SqlServerDsc' + $script:moduleName = 'SqlServerDsc' - Import-Module -Name $script:dscModuleName -Force -ErrorAction 'Stop' + Import-Module -Name $script:moduleName -Force -ErrorAction 'Stop' } -Describe 'Enable-SqlDscLogin' -Tag @('Integration_SQL2016', 'Integration_SQL2017', 'Integration_SQL2019', 'Integration_SQL2022') { +Describe 'Enable-SqlDscLogin' -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' diff --git a/tests/Integration/Commands/Get-SqlDscAgentAlert.Integration.Tests.ps1 b/tests/Integration/Commands/Get-SqlDscAgentAlert.Integration.Tests.ps1 index 49271e857f..8b34fe4e22 100644 --- a/tests/Integration/Commands/Get-SqlDscAgentAlert.Integration.Tests.ps1 +++ b/tests/Integration/Commands/Get-SqlDscAgentAlert.Integration.Tests.ps1 @@ -24,25 +24,16 @@ BeforeDiscovery { } BeforeAll { - $script:dscModuleName = 'SqlServerDsc' + $script:moduleName = 'SqlServerDsc' - Import-Module -Name $script:dscModuleName -Force -ErrorAction 'Stop' - - $env:SqlServerDscCI = $true - - # Integration tests are run on the DSCSQLTEST instance - $script:sqlServerInstance = 'DSCSQLTEST' -} - -AfterAll { - $env:SqlServerDscCI = $null - - # Unload the module being tested so that it doesn't impact any other tests. - Get-Module -Name $script:dscModuleName -All | Remove-Module -Force + Import-Module -Name $script:moduleName -Force -ErrorAction 'Stop' } -Describe 'Get-SqlDscAgentAlert' -Tag 'Integration_SQL2017', 'Integration_SQL2019', 'Integration_SQL2022' { +Describe 'Get-SqlDscAgentAlert' -Tag @('Integration_SQL2017', 'Integration_SQL2019', 'Integration_SQL2022') { BeforeAll { + # Integration tests are run on the DSCSQLTEST instance + $script:sqlServerInstance = 'DSCSQLTEST' + # Starting the named instance SQL Server service prior to running tests. Start-Service -Name 'MSSQL$DSCSQLTEST' -Verbose -ErrorAction 'Stop' diff --git a/tests/Integration/Commands/Get-SqlDscDatabase.Integration.Tests.ps1 b/tests/Integration/Commands/Get-SqlDscDatabase.Integration.Tests.ps1 index d262663dd3..1e6edaa343 100644 --- a/tests/Integration/Commands/Get-SqlDscDatabase.Integration.Tests.ps1 +++ b/tests/Integration/Commands/Get-SqlDscDatabase.Integration.Tests.ps1 @@ -24,9 +24,9 @@ BeforeDiscovery { } BeforeAll { - $script:dscModuleName = 'SqlServerDsc' + $script:moduleName = 'SqlServerDsc' - Import-Module -Name $script:dscModuleName + Import-Module -Name $script:moduleName -Force -ErrorAction 'Stop' } Describe 'Get-SqlDscDatabase' -Tag @('Integration_SQL2017', 'Integration_SQL2019', 'Integration_SQL2022') { diff --git a/tests/Integration/Commands/Get-SqlDscInstalledInstance.Integration.Tests.ps1 b/tests/Integration/Commands/Get-SqlDscInstalledInstance.Integration.Tests.ps1 index f4ab6c930e..60f934e9bc 100644 --- a/tests/Integration/Commands/Get-SqlDscInstalledInstance.Integration.Tests.ps1 +++ b/tests/Integration/Commands/Get-SqlDscInstalledInstance.Integration.Tests.ps1 @@ -23,6 +23,12 @@ BeforeDiscovery { } } +BeforeAll { + $script:moduleName = 'SqlServerDsc' + + Import-Module -Name $script:moduleName -Force -ErrorAction 'Stop' +} + Describe 'Get-SqlDscInstalledInstance' { Context 'When getting all SQL Server instances' -Tag @('Integration_PowerBI') { It 'Should not throw an exception' { diff --git a/tests/Integration/Commands/Get-SqlDscLogin.Integration.Tests.ps1 b/tests/Integration/Commands/Get-SqlDscLogin.Integration.Tests.ps1 index ca923f720d..d8a4976295 100644 --- a/tests/Integration/Commands/Get-SqlDscLogin.Integration.Tests.ps1 +++ b/tests/Integration/Commands/Get-SqlDscLogin.Integration.Tests.ps1 @@ -24,12 +24,12 @@ BeforeDiscovery { } BeforeAll { - $script:dscModuleName = 'SqlServerDsc' + $script:moduleName = 'SqlServerDsc' - Import-Module -Name $script:dscModuleName + Import-Module -Name $script:moduleName -Force -ErrorAction 'Stop' } -Describe 'Get-SqlDscLogin' -Tag @('Integration_SQL2016', 'Integration_SQL2017', 'Integration_SQL2019', 'Integration_SQL2022') { +Describe 'Get-SqlDscLogin' -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' diff --git a/tests/Integration/Commands/Get-SqlDscRSSetupConfiguration.Integration.Tests.ps1 b/tests/Integration/Commands/Get-SqlDscRSSetupConfiguration.Integration.Tests.ps1 index 836a954934..60679426ab 100644 --- a/tests/Integration/Commands/Get-SqlDscRSSetupConfiguration.Integration.Tests.ps1 +++ b/tests/Integration/Commands/Get-SqlDscRSSetupConfiguration.Integration.Tests.ps1 @@ -23,6 +23,12 @@ BeforeDiscovery { } } +BeforeAll { + $script:moduleName = 'SqlServerDsc' + + Import-Module -Name $script:moduleName -Force -ErrorAction 'Stop' +} + Describe 'Get-SqlDscRSSetupConfiguration' { Context 'When getting the configuration for SQL Server Reporting Services instance' -Tag @('Integration_SQL2017_RS') { It 'Should return the correct configuration for SSRS instance' { diff --git a/tests/Integration/Commands/Get-SqlDscRole.Integration.Tests.ps1 b/tests/Integration/Commands/Get-SqlDscRole.Integration.Tests.ps1 index 1da2e702e0..814a1c11b6 100644 --- a/tests/Integration/Commands/Get-SqlDscRole.Integration.Tests.ps1 +++ b/tests/Integration/Commands/Get-SqlDscRole.Integration.Tests.ps1 @@ -24,12 +24,12 @@ BeforeDiscovery { } BeforeAll { - $script:dscModuleName = 'SqlServerDsc' + $script:moduleName = 'SqlServerDsc' - Import-Module -Name $script:dscModuleName + Import-Module -Name $script:moduleName -Force -ErrorAction 'Stop' } -Describe 'Get-SqlDscRole' -Tag @('Integration_SQL2016', 'Integration_SQL2017', 'Integration_SQL2019', 'Integration_SQL2022') { +Describe 'Get-SqlDscRole' -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' diff --git a/tests/Integration/Commands/Get-SqlDscServerPermission.Integration.Tests.ps1 b/tests/Integration/Commands/Get-SqlDscServerPermission.Integration.Tests.ps1 new file mode 100644 index 0000000000..ae399e81c3 --- /dev/null +++ b/tests/Integration/Commands/Get-SqlDscServerPermission.Integration.Tests.ps1 @@ -0,0 +1,317 @@ +[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '', Justification = 'Suppressing this rule because Script Analyzer does not understand Pester syntax.')] +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 build" first.' + } +} + +BeforeAll { + $script:moduleName = 'SqlServerDsc' + + Import-Module -Name $script:moduleName -Force -ErrorAction 'Stop' +} + +Describe 'Get-SqlDscServerPermission' -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' + + $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 + } + + AfterAll { + 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 connecting to SQL Server instance' { + Context 'When getting permissions for valid SQL logins' { + It 'Should return permissions for sa login' { + $result = Get-SqlDscServerPermission -ServerObject $script:serverObject -Name 'sa' + + $result | Should -Not -BeNullOrEmpty + $result | Should -BeOfType [Microsoft.SqlServer.Management.Smo.ServerPermissionInfo] + } + + It 'Should return permissions for sa login using pipeline' { + $result = $script:serverObject | Get-SqlDscServerPermission -Name 'sa' + + $result | Should -Not -BeNullOrEmpty + $result | Should -BeOfType [Microsoft.SqlServer.Management.Smo.ServerPermissionInfo] + } + } + + Context 'When getting permissions for valid Windows logins' { + It 'Should return permissions for SqlAdmin Windows login' { + $windowsLogin = '{0}\SqlAdmin' -f (Get-ComputerName) + $result = Get-SqlDscServerPermission -ServerObject $script:serverObject -Name $windowsLogin + + $result | Should -Not -BeNullOrEmpty + $result | Should -BeOfType [Microsoft.SqlServer.Management.Smo.ServerPermissionInfo] + } + + It 'Should return permissions for NT AUTHORITY\SYSTEM login' { + $result = Get-SqlDscServerPermission -ServerObject $script:serverObject -Name 'NT AUTHORITY\SYSTEM' + + $result | Should -Not -BeNullOrEmpty + $result | Should -BeOfType [Microsoft.SqlServer.Management.Smo.ServerPermissionInfo] + } + } + + Context 'When getting permissions for valid server roles' { + It 'Should return permissions for public server role' { + $result = Get-SqlDscServerPermission -ServerObject $script:serverObject -Name 'public' + + $result | Should -Not -BeNullOrEmpty + $result | Should -BeOfType [Microsoft.SqlServer.Management.Smo.ServerPermissionInfo] + } + + It 'Should return permissions for SqlDscIntegrationTestRole_Persistent server role' { + $result = Get-SqlDscServerPermission -ServerObject $script:serverObject -Name 'SqlDscIntegrationTestRole_Persistent' + + $result | Should -Not -BeNullOrEmpty + $result | Should -BeOfType [Microsoft.SqlServer.Management.Smo.ServerPermissionInfo] + + # Verify that the CreateEndpoint permission granted by Grant-SqlDscServerPermission test is present + $createEndpointPermission = $result | Where-Object { $_.PermissionType.CreateEndpoint -eq $true } + $createEndpointPermission | Should -Not -BeNullOrEmpty -Because 'CreateEndpoint permission should have been granted by Grant-SqlDscServerPermission integration test' + $createEndpointPermission.PermissionState | Should -Be 'Grant' + } + } + + Context 'When getting permissions for invalid principals' { + It 'Should throw error for non-existent login with ErrorAction Stop' { + { Get-SqlDscServerPermission -ServerObject $script:serverObject -Name 'NonExistentLogin123' -ErrorAction 'Stop' } | + Should -Throw + } + + It 'Should return null for non-existent login with ErrorAction SilentlyContinue' { + $result = Get-SqlDscServerPermission -ServerObject $script:serverObject -Name 'NonExistentLogin123' -ErrorAction 'SilentlyContinue' + + $result | Should -BeNullOrEmpty + } + + It 'Should throw error for non-existent server role with ErrorAction Stop' { + { Get-SqlDscServerPermission -ServerObject $script:serverObject -Name 'NonExistentRole123' -ErrorAction 'Stop' } | + Should -Throw + } + + It 'Should return null for non-existent server role with ErrorAction SilentlyContinue' { + $result = Get-SqlDscServerPermission -ServerObject $script:serverObject -Name 'NonExistentRole123' -ErrorAction 'SilentlyContinue' + + $result | Should -BeNullOrEmpty + } + } + + Context 'When verifying permission properties' { + BeforeAll { + # Get permissions for a known principal that should have permissions + $script:testPermissions = Get-SqlDscServerPermission -ServerObject $script:serverObject -Name 'SqlDscIntegrationTestRole_Persistent' + } + + It 'Should return ServerPermissionInfo objects with PermissionState property' { + $script:testPermissions | Should -Not -BeNullOrEmpty + + foreach ($permission in $script:testPermissions) { + $permission.PermissionState | Should -BeIn @('Grant', 'Deny', 'GrantWithGrant') + } + } + + It 'Should return ServerPermissionInfo objects with PermissionType property' { + $script:testPermissions | Should -Not -BeNullOrEmpty + + foreach ($permission in $script:testPermissions) { + $permission.PermissionType | Should -Not -BeNullOrEmpty + $permission.PermissionType | Should -BeOfType [Microsoft.SqlServer.Management.Smo.ServerPermissionSet] + } + } + } + + Context 'When using PrincipalType parameter' { + It 'Should return permissions for sa login when PrincipalType is Login' { + $result = Get-SqlDscServerPermission -ServerObject $script:serverObject -Name 'sa' -PrincipalType 'Login' + + $result | Should -Not -BeNullOrEmpty + $result | Should -BeOfType [Microsoft.SqlServer.Management.Smo.ServerPermissionInfo] + } + + It 'Should return permissions for SqlDscIntegrationTestRole_Persistent role when PrincipalType is Role' { + $result = Get-SqlDscServerPermission -ServerObject $script:serverObject -Name 'SqlDscIntegrationTestRole_Persistent' -PrincipalType 'Role' + + $result | Should -Not -BeNullOrEmpty + $result | Should -BeOfType [Microsoft.SqlServer.Management.Smo.ServerPermissionInfo] + } + + It 'Should return permissions for sa login when PrincipalType is both Login and Role' { + $result = Get-SqlDscServerPermission -ServerObject $script:serverObject -Name 'sa' -PrincipalType 'Login', 'Role' + + $result | Should -Not -BeNullOrEmpty + $result | Should -BeOfType [Microsoft.SqlServer.Management.Smo.ServerPermissionInfo] + } + + It 'Should throw error when looking for login as role' { + { Get-SqlDscServerPermission -ServerObject $script:serverObject -Name 'sa' -PrincipalType 'Role' -ErrorAction 'Stop' } | + Should -Throw + } + + It 'Should throw error when looking for role as login' { + { Get-SqlDscServerPermission -ServerObject $script:serverObject -Name 'SqlDscIntegrationTestRole_Persistent' -PrincipalType 'Login' -ErrorAction 'Stop' } | + Should -Throw + } + + It 'Should return null when looking for login as role with SilentlyContinue' { + $result = Get-SqlDscServerPermission -ServerObject $script:serverObject -Name 'sa' -PrincipalType 'Role' -ErrorAction 'SilentlyContinue' + + $result | Should -BeNullOrEmpty + } + + It 'Should return null when looking for role as login with SilentlyContinue' { + $result = Get-SqlDscServerPermission -ServerObject $script:serverObject -Name 'SqlDscIntegrationTestRole_Persistent' -PrincipalType 'Login' -ErrorAction 'SilentlyContinue' + + $result | Should -BeNullOrEmpty + } + } + + Context 'When using Login parameter set' { + It 'Should return permissions for sa login using Login object' { + $loginObject = Get-SqlDscLogin -ServerObject $script:serverObject -Name 'sa' + $result = Get-SqlDscServerPermission -Login $loginObject + + $result | Should -Not -BeNullOrEmpty + $result | Should -BeOfType [Microsoft.SqlServer.Management.Smo.ServerPermissionInfo] + } + + It 'Should return permissions for sa login using Login object from pipeline' { + $loginObject = Get-SqlDscLogin -ServerObject $script:serverObject -Name 'sa' + $result = $loginObject | Get-SqlDscServerPermission + + $result | Should -Not -BeNullOrEmpty + $result | Should -BeOfType [Microsoft.SqlServer.Management.Smo.ServerPermissionInfo] + } + + It 'Should return permissions for Windows login using Login object' { + $windowsLogin = '{0}\SqlAdmin' -f (Get-ComputerName) + $loginObject = Get-SqlDscLogin -ServerObject $script:serverObject -Name $windowsLogin + $result = Get-SqlDscServerPermission -Login $loginObject + + $result | Should -Not -BeNullOrEmpty + $result | Should -BeOfType [Microsoft.SqlServer.Management.Smo.ServerPermissionInfo] + } + + It 'Should return permissions for multiple logins using pipeline' { + $loginObjects = @( + Get-SqlDscLogin -ServerObject $script:serverObject -Name 'sa' + Get-SqlDscLogin -ServerObject $script:serverObject -Name 'NT AUTHORITY\SYSTEM' + ) + $result = $loginObjects | Get-SqlDscServerPermission + + $result | Should -Not -BeNullOrEmpty + $result | Should -BeOfType [Microsoft.SqlServer.Management.Smo.ServerPermissionInfo[]] + $result.Count | Should -BeGreaterThan 1 + } + } + + Context 'When using ServerRole parameter set' { + It 'Should return permissions for SqlDscIntegrationTestRole_Persistent role using ServerRole object' { + $roleObject = Get-SqlDscRole -ServerObject $script:serverObject -Name 'SqlDscIntegrationTestRole_Persistent' + $result = Get-SqlDscServerPermission -ServerRole $roleObject + + $result | Should -Not -BeNullOrEmpty + $result | Should -BeOfType [Microsoft.SqlServer.Management.Smo.ServerPermissionInfo] + } + + It 'Should return permissions for SqlDscIntegrationTestRole_Persistent role using ServerRole object from pipeline' { + $roleObject = Get-SqlDscRole -ServerObject $script:serverObject -Name 'SqlDscIntegrationTestRole_Persistent' + $result = $roleObject | Get-SqlDscServerPermission + + $result | Should -Not -BeNullOrEmpty + $result | Should -BeOfType [Microsoft.SqlServer.Management.Smo.ServerPermissionInfo] + } + + It 'Should return permissions for public role using ServerRole object' { + $roleObject = Get-SqlDscRole -ServerObject $script:serverObject -Name 'public' + $result = Get-SqlDscServerPermission -ServerRole $roleObject + + $result | Should -Not -BeNullOrEmpty + $result | Should -BeOfType [Microsoft.SqlServer.Management.Smo.ServerPermissionInfo] + } + + It 'Should return permissions for multiple server roles using pipeline' { + $roleObjects = @( + Get-SqlDscRole -ServerObject $script:serverObject -Name 'SqlDscIntegrationTestRole_Persistent' + Get-SqlDscRole -ServerObject $script:serverObject -Name 'public' + ) + $result = $roleObjects | Get-SqlDscServerPermission + + $result | Should -Not -BeNullOrEmpty + $result | Should -BeOfType [Microsoft.SqlServer.Management.Smo.ServerPermissionInfo[]] + $result.Count | Should -BeGreaterThan 1 + } + } + + Context 'When comparing parameter sets' { + It 'Should return same permissions for sa login using different parameter sets' { + # Get permissions using ByName parameter set + $resultByName = Get-SqlDscServerPermission -ServerObject $script:serverObject -Name 'sa' + + # Get permissions using Login parameter set + $loginObject = Get-SqlDscLogin -ServerObject $script:serverObject -Name 'sa' + $resultByLogin = Get-SqlDscServerPermission -Login $loginObject + + # Compare results + $resultByName.Count | Should -Be $resultByLogin.Count + + # Compare each permission (assuming they are returned in the same order) + for ($i = 0; $i -lt $resultByName.Count; $i++) { + $resultByName[$i].PermissionState | Should -Be $resultByLogin[$i].PermissionState + # Note: Permission type comparison is complex due to object structure + } + } + + It 'Should return same permissions for SqlDscIntegrationTestRole_Persistent role using different parameter sets' { + # Get permissions using ByName parameter set + $resultByName = Get-SqlDscServerPermission -ServerObject $script:serverObject -Name 'SqlDscIntegrationTestRole_Persistent' + + # Get permissions using ServerRole parameter set + $roleObject = Get-SqlDscRole -ServerObject $script:serverObject -Name 'SqlDscIntegrationTestRole_Persistent' + $resultByRole = Get-SqlDscServerPermission -ServerRole $roleObject + + # Compare results + $resultByName.Count | Should -Be $resultByRole.Count + + # Compare each permission (assuming they are returned in the same order) + for ($i = 0; $i -lt $resultByName.Count; $i++) { + $resultByName[$i].PermissionState | Should -Be $resultByRole[$i].PermissionState + # Note: Permission type comparison is complex due to object structure + } + } + } + } +} diff --git a/tests/Integration/Commands/Grant-SqlDscServerPermission.Integration.Tests.ps1 b/tests/Integration/Commands/Grant-SqlDscServerPermission.Integration.Tests.ps1 index af2608c66d..1ac0cedeac 100644 --- a/tests/Integration/Commands/Grant-SqlDscServerPermission.Integration.Tests.ps1 +++ b/tests/Integration/Commands/Grant-SqlDscServerPermission.Integration.Tests.ps1 @@ -29,51 +29,30 @@ BeforeAll { Import-Module -Name $script:moduleName -Force -ErrorAction 'Stop' } -AfterAll { - # Unload the module being tested so that it doesn't impact any other tests. - Get-Module -Name $script:moduleName -All | Remove-Module -Force -} - -Describe 'Grant-SqlDscServerPermission Integration Tests' -Tag 'Integration' { +Describe 'Grant-SqlDscServerPermission' -Tag @('Integration_SQL2017', 'Integration_SQL2019', 'Integration_SQL2022') { BeforeAll { - # Check if there is a CI database instance to use for testing - $script:sqlServerInstanceName = $env:SqlServerInstanceName + # Starting the named instance SQL Server service prior to running tests. + Start-Service -Name 'MSSQL$DSCSQLTEST' -Verbose -ErrorAction 'Stop' - if (-not $script:sqlServerInstanceName) - { - $script:sqlServerInstanceName = 'DSCSQLTEST' - } + $script:mockInstanceName = 'DSCSQLTEST' - # Get a computer name that will work in the CI environment - $script:computerName = Get-ComputerName + $mockSqlAdministratorUserName = 'SqlAdmin' # Using computer name as NetBIOS name throw exception. + $mockSqlAdministratorPassword = ConvertTo-SecureString -String 'P@ssw0rd1' -AsPlainText -Force - Write-Verbose -Message ('Integration tests will run using computer name ''{0}'' and instance name ''{1}''.' -f $script:computerName, $script:sqlServerInstanceName) -Verbose + $script:mockSqlAdminCredential = [System.Management.Automation.PSCredential]::new($mockSqlAdministratorUserName, $mockSqlAdministratorPassword) - $script:serverObject = Connect-SqlDscDatabaseEngine -ServerName $script:computerName -InstanceName $script:sqlServerInstanceName -Force + $script:serverObject = Connect-SqlDscDatabaseEngine -InstanceName $script:mockInstanceName -Credential $script:mockSqlAdminCredential -ErrorAction 'Stop' # Use existing persistent principals created by earlier integration tests $script:testLoginName = 'IntegrationTestSqlLogin' $script:testRoleName = 'SqlDscIntegrationTestRole_Persistent' - - # Verify the persistent principals exist (should be created by New-SqlDscLogin and New-SqlDscRole integration tests) - $existingLogin = Get-SqlDscLogin -ServerObject $script:serverObject -Name $script:testLoginName -ErrorAction 'SilentlyContinue' - if (-not $existingLogin) - { - throw ('Test login {0} does not exist. Please run New-SqlDscLogin integration tests first to create persistent test principals.' -f $script:testLoginName) - } - - $existingRole = Get-SqlDscRole -ServerObject $script:serverObject -Name $script:testRoleName -ErrorAction 'SilentlyContinue' - if (-not $existingRole) - { - throw ('Test role {0} does not exist. Please run New-SqlDscRole integration tests first to create persistent test principals.' -f $script:testRoleName) - } } AfterAll { - # Keep the persistent principals for other tests to use - # Do not remove $script:testLoginName and $script:testRoleName as they are managed by New-SqlDscLogin and New-SqlDscRole tests - 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 granting server permissions to login' { @@ -84,44 +63,67 @@ Describe 'Grant-SqlDscServerPermission Integration Tests' -Tag 'Integration' { Revoke-SqlDscServerPermission -Login $script:loginObject -Permission 'ViewServerState' -Force -ErrorAction 'SilentlyContinue' Revoke-SqlDscServerPermission -Login $script:loginObject -Permission 'ViewAnyDatabase' -Force -ErrorAction 'SilentlyContinue' Revoke-SqlDscServerPermission -Login $script:loginObject -Permission 'ViewAnyDefinition' -Force -ErrorAction 'SilentlyContinue' + Revoke-SqlDscServerPermission -Login $script:loginObject -Permission 'CreateAnyDatabase' -WithGrant -Force -ErrorAction 'SilentlyContinue' } It 'Should grant ViewServerState permission successfully' { $null = Grant-SqlDscServerPermission -Login $script:loginObject -Permission @('ViewServerState') -Force -ErrorAction 'Stop' # Verify the permission was granted - $grantedPermissions = Get-SqlDscServerPermission -ServerObject $script:serverObject -Name $script:testLoginName -ErrorAction 'Stop' - $grantedPermissions | Should -Not -BeNullOrEmpty - $grantedPermissions.PermissionType.ViewServerState | Should -BeTrue + $permission = Get-SqlDscServerPermission -ServerObject $script:serverObject -Name $script:testLoginName -ErrorAction 'Stop' + + $permission | Should -Not -BeNullOrEmpty + $grantedPermissions = $permission | Where-Object { $_.PermissionState -eq 'Grant' } + + $expectedPermission = $grantedPermissions | Where-Object { $_.PermissionType.ViewServerState -eq $true } + $expectedPermission | Should -HaveCount 1 + $expectedPermission.PermissionType.ViewServerState | Should -BeTrue } It 'Should grant multiple permissions successfully' { $null = Grant-SqlDscServerPermission -Login $script:loginObject -Permission @('ViewServerState', 'ViewAnyDatabase') -Force -ErrorAction 'Stop' # Verify the permissions were granted - $grantedPermissions = Get-SqlDscServerPermission -ServerObject $script:serverObject -Name $script:testLoginName -ErrorAction 'Stop' - $grantedPermissions | Should -Not -BeNullOrEmpty - $grantedPermissions.PermissionType.ViewServerState | Should -BeTrue - $grantedPermissions.PermissionType.ViewAnyDatabase | Should -BeTrue + $permission = Get-SqlDscServerPermission -ServerObject $script:serverObject -Name $script:testLoginName -ErrorAction 'Stop' + + $permission | Should -Not -BeNullOrEmpty + $grantedPermissions = $permission | Where-Object { $_.PermissionState -eq 'Grant' } + + $expectedPermission = $grantedPermissions | Where-Object { $_.PermissionType.ViewServerState -eq $true } + $expectedPermission | Should -HaveCount 1 + $expectedPermission.PermissionType.ViewServerState | Should -BeTrue + + $expectedPermission = $grantedPermissions | Where-Object { $_.PermissionType.ViewAnyDatabase -eq $true } + $expectedPermission | Should -HaveCount 1 + $expectedPermission.PermissionType.ViewAnyDatabase | Should -BeTrue } It 'Should grant permissions with WithGrant option' { - $null = Grant-SqlDscServerPermission -Login $script:loginObject -Permission @('ViewServerState') -WithGrant -Force -ErrorAction 'Stop' + $null = Grant-SqlDscServerPermission -Login $script:loginObject -Permission @('CreateAnyDatabase') -WithGrant -Force -ErrorAction 'Stop' # Verify the permission was granted with grant option - $grantedPermissions = Get-SqlDscServerPermission -ServerObject $script:serverObject -Name $script:testLoginName -ErrorAction 'Stop' - $grantedPermissions | Should -Not -BeNullOrEmpty - $grantWithGrantPermission = $grantedPermissions | Where-Object { $_.PermissionState -eq 'GrantWithGrant' } - $grantWithGrantPermission.PermissionType.ViewServerState | Should -BeTrue + $permission = Get-SqlDscServerPermission -ServerObject $script:serverObject -Name $script:testLoginName -ErrorAction 'Stop' + + $permission | Should -Not -BeNullOrEmpty + $grantedPermissions = $permission | Where-Object { $_.PermissionState -eq 'GrantWithGrant' } + + $expectedPermission = $grantedPermissions | Where-Object { $_.PermissionType.CreateAnyDatabase -eq $true } + $expectedPermission | Should -HaveCount 1 + $expectedPermission.PermissionType.CreateAnyDatabase | Should -BeTrue } It 'Should accept Login from pipeline' { $null = $script:loginObject | Grant-SqlDscServerPermission -Permission @('ViewAnyDefinition') -Force -ErrorAction 'Stop' # Verify the permission was granted - $grantedPermissions = Get-SqlDscServerPermission -ServerObject $script:serverObject -Name $script:testLoginName -ErrorAction 'Stop' - $grantedPermissions | Should -Not -BeNullOrEmpty - $grantedPermissions.PermissionType.ViewAnyDefinition | Should -BeTrue + $permission = Get-SqlDscServerPermission -ServerObject $script:serverObject -Name $script:testLoginName -ErrorAction 'Stop' + + $permission | Should -Not -BeNullOrEmpty + $grantedPermissions = $permission | Where-Object { $_.PermissionState -eq 'Grant' } + + $expectedPermission = $grantedPermissions | Where-Object { $_.PermissionType.ViewAnyDefinition -eq $true } + $expectedPermission | Should -HaveCount 1 + $expectedPermission.PermissionType.ViewAnyDefinition | Should -BeTrue } } @@ -139,9 +141,14 @@ Describe 'Grant-SqlDscServerPermission Integration Tests' -Tag 'Integration' { $null = Grant-SqlDscServerPermission -ServerRole $roleObject -Permission @('ViewServerState') -Force -ErrorAction 'Stop' # Verify the permission was granted - $grantedPermissions = Get-SqlDscServerPermission -ServerObject $script:serverObject -Name $script:testRoleName -ErrorAction 'Stop' - $grantedPermissions | Should -Not -BeNullOrEmpty - $grantedPermissions.PermissionType.ViewServerState | Should -BeTrue + $permission = Get-SqlDscServerPermission -ServerObject $script:serverObject -Name $script:testRoleName -ErrorAction 'Stop' + + $permission | Should -Not -BeNullOrEmpty + $grantedPermissions = $permission | Where-Object { $_.PermissionState -eq 'Grant' } + + $expectedPermission = $grantedPermissions | Where-Object { $_.PermissionType.ViewServerState -eq $true } + $expectedPermission | Should -HaveCount 1 + $expectedPermission.PermissionType.ViewServerState | Should -BeTrue } It 'Should grant persistent CreateEndpoint permission to role for other tests' { @@ -150,9 +157,14 @@ Describe 'Grant-SqlDscServerPermission Integration Tests' -Tag 'Integration' { $null = Grant-SqlDscServerPermission -ServerRole $roleObject -Permission @('CreateEndpoint') -Force -ErrorAction 'Stop' # Verify the permission was granted - this permission will remain persistent for other integration tests - $grantedPermissions = Get-SqlDscServerPermission -ServerObject $script:serverObject -Name $script:testRoleName -ErrorAction 'Stop' - $grantedPermissions | Should -Not -BeNullOrEmpty - $grantedPermissions.PermissionType.CreateEndpoint | Should -BeTrue + $permission = Get-SqlDscServerPermission -ServerObject $script:serverObject -Name $script:testRoleName -ErrorAction 'Stop' + + $permission | Should -Not -BeNullOrEmpty + $grantedPermissions = $permission | Where-Object { $_.PermissionState -eq 'Grant' } + + $expectedPermission = $grantedPermissions | Where-Object { $_.PermissionType.CreateEndpoint -eq $true } + $expectedPermission | Should -HaveCount 1 + $expectedPermission.PermissionType.CreateEndpoint | Should -BeTrue } } } diff --git a/tests/Integration/Commands/Install-SqlDscBIReportServer.Integration.Tests.ps1 b/tests/Integration/Commands/Install-SqlDscBIReportServer.Integration.Tests.ps1 index a85e48db45..9dbcd7fc38 100644 --- a/tests/Integration/Commands/Install-SqlDscBIReportServer.Integration.Tests.ps1 +++ b/tests/Integration/Commands/Install-SqlDscBIReportServer.Integration.Tests.ps1 @@ -23,6 +23,12 @@ BeforeDiscovery { } } +BeforeAll { + $script:moduleName = 'SqlServerDsc' + + Import-Module -Name $script:moduleName -Force -ErrorAction 'Stop' +} + Describe 'Install-SqlDscBIReportServer' -Tag @('Integration_PowerBI') { BeforeAll { Write-Verbose -Message ('Running integration test as user ''{0}''.' -f $env:UserName) -Verbose diff --git a/tests/Integration/Commands/Install-SqlDscReportingService.Integration.Tests.ps1 b/tests/Integration/Commands/Install-SqlDscReportingService.Integration.Tests.ps1 index bb3f326e22..f4817a6fef 100644 --- a/tests/Integration/Commands/Install-SqlDscReportingService.Integration.Tests.ps1 +++ b/tests/Integration/Commands/Install-SqlDscReportingService.Integration.Tests.ps1 @@ -23,6 +23,12 @@ BeforeDiscovery { } } +BeforeAll { + $script:moduleName = 'SqlServerDsc' + + Import-Module -Name $script:moduleName -Force -ErrorAction 'Stop' +} + Describe 'Install-SqlDscReportingService' -Tag @('Integration_SQL2017_RS', 'Integration_SQL2019_RS', 'Integration_SQL2022_RS') { BeforeAll { Write-Verbose -Message ('Running integration test as user ''{0}''.' -f $env:UserName) -Verbose diff --git a/tests/Integration/Commands/Install-SqlDscServer.Integration.Tests.ps1 b/tests/Integration/Commands/Install-SqlDscServer.Integration.Tests.ps1 index cc2b4e94d5..983a5e7bbc 100644 --- a/tests/Integration/Commands/Install-SqlDscServer.Integration.Tests.ps1 +++ b/tests/Integration/Commands/Install-SqlDscServer.Integration.Tests.ps1 @@ -23,8 +23,14 @@ BeforeDiscovery { } } +BeforeAll { + $script:moduleName = 'SqlServerDsc' + + Import-Module -Name $script:moduleName -Force -ErrorAction 'Stop' +} + # cSpell: ignore SQLSERVERAGENT, DSCSQLTEST -Describe 'Install-SqlDscServer' -Tag @('Integration_SQL2016', 'Integration_SQL2017', 'Integration_SQL2019', 'Integration_SQL2022') { +Describe 'Install-SqlDscServer' -Tag @('Integration_SQL2017', 'Integration_SQL2019', 'Integration_SQL2022') { BeforeAll { Write-Verbose -Message ('Running integration test as user ''{0}''.' -f $env:UserName) -Verbose diff --git a/tests/Integration/Commands/New-SqlDscAgentAlert.Integration.Tests.ps1 b/tests/Integration/Commands/New-SqlDscAgentAlert.Integration.Tests.ps1 index 14b57256b5..4603860921 100644 --- a/tests/Integration/Commands/New-SqlDscAgentAlert.Integration.Tests.ps1 +++ b/tests/Integration/Commands/New-SqlDscAgentAlert.Integration.Tests.ps1 @@ -24,25 +24,16 @@ BeforeDiscovery { } BeforeAll { - $script:dscModuleName = 'SqlServerDsc' + $script:moduleName = 'SqlServerDsc' - Import-Module -Name $script:dscModuleName -Force -ErrorAction 'Stop' - - $env:SqlServerDscCI = $true - - # Integration tests are run on the DSCSQLTEST instance - $script:sqlServerInstance = 'DSCSQLTEST' -} - -AfterAll { - $env:SqlServerDscCI = $null - - # Unload the module being tested so that it doesn't impact any other tests. - Get-Module -Name $script:dscModuleName -All | Remove-Module -Force + Import-Module -Name $script:moduleName -Force -ErrorAction 'Stop' } -Describe 'New-SqlDscAgentAlert' -Tag 'Integration_SQL2017', 'Integration_SQL2019', 'Integration_SQL2022' { +Describe 'New-SqlDscAgentAlert' -Tag @('Integration_SQL2017', 'Integration_SQL2019', 'Integration_SQL2022') { BeforeAll { + # Integration tests are run on the DSCSQLTEST instance + $script:sqlServerInstance = 'DSCSQLTEST' + # Starting the named instance SQL Server service prior to running tests. Start-Service -Name 'MSSQL$DSCSQLTEST' -Verbose -ErrorAction 'Stop' diff --git a/tests/Integration/Commands/New-SqlDscDatabase.Integration.Tests.ps1 b/tests/Integration/Commands/New-SqlDscDatabase.Integration.Tests.ps1 index 4a57ecec12..7923fb404d 100644 --- a/tests/Integration/Commands/New-SqlDscDatabase.Integration.Tests.ps1 +++ b/tests/Integration/Commands/New-SqlDscDatabase.Integration.Tests.ps1 @@ -24,9 +24,9 @@ BeforeDiscovery { } BeforeAll { - $script:dscModuleName = 'SqlServerDsc' + $script:moduleName = 'SqlServerDsc' - Import-Module -Name $script:dscModuleName -Force -ErrorAction 'Stop' + Import-Module -Name $script:moduleName -Force -ErrorAction 'Stop' } Describe 'New-SqlDscDatabase' -Tag @('Integration_SQL2017', 'Integration_SQL2019', 'Integration_SQL2022') { diff --git a/tests/Integration/Commands/New-SqlDscLogin.Integration.Tests.ps1 b/tests/Integration/Commands/New-SqlDscLogin.Integration.Tests.ps1 index d49eb66207..4516a16b9e 100644 --- a/tests/Integration/Commands/New-SqlDscLogin.Integration.Tests.ps1 +++ b/tests/Integration/Commands/New-SqlDscLogin.Integration.Tests.ps1 @@ -24,12 +24,12 @@ BeforeDiscovery { } BeforeAll { - $script:dscModuleName = 'SqlServerDsc' + $script:moduleName = 'SqlServerDsc' - Import-Module -Name $script:dscModuleName -Force -ErrorAction 'Stop' + Import-Module -Name $script:moduleName -Force -ErrorAction 'Stop' } -Describe 'New-SqlDscLogin' -Tag @('Integration_SQL2016', 'Integration_SQL2017', 'Integration_SQL2019', 'Integration_SQL2022') { +Describe 'New-SqlDscLogin' -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' diff --git a/tests/Integration/Commands/New-SqlDscRole.Integration.Tests.ps1 b/tests/Integration/Commands/New-SqlDscRole.Integration.Tests.ps1 index f330f51eb7..20057e3584 100644 --- a/tests/Integration/Commands/New-SqlDscRole.Integration.Tests.ps1 +++ b/tests/Integration/Commands/New-SqlDscRole.Integration.Tests.ps1 @@ -24,12 +24,12 @@ BeforeDiscovery { } BeforeAll { - $script:dscModuleName = 'SqlServerDsc' + $script:moduleName = 'SqlServerDsc' - Import-Module -Name $script:dscModuleName + Import-Module -Name $script:moduleName -Force -ErrorAction 'Stop' } -Describe 'New-SqlDscRole' -Tag @('Integration_SQL2016', 'Integration_SQL2017', 'Integration_SQL2019', 'Integration_SQL2022') { +Describe 'New-SqlDscRole' -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' diff --git a/tests/Integration/Commands/Prerequisites.Integration.Tests.ps1 b/tests/Integration/Commands/Prerequisites.Integration.Tests.ps1 index 62482c8bba..17e17bc5e6 100644 --- a/tests/Integration/Commands/Prerequisites.Integration.Tests.ps1 +++ b/tests/Integration/Commands/Prerequisites.Integration.Tests.ps1 @@ -23,6 +23,12 @@ BeforeDiscovery { } } +BeforeAll { + $script:moduleName = 'SqlServerDsc' + + Import-Module -Name $script:moduleName -Force -ErrorAction 'Stop' +} + # CSpell: ignore Remoting Describe 'Prerequisites' { Context 'Create required local Windows users' -Tag @('Integration_SQL2016', 'Integration_SQL2017', 'Integration_SQL2019', 'Integration_SQL2022', 'Integration_PowerBI') { diff --git a/tests/Integration/Commands/README.md b/tests/Integration/Commands/README.md index 332426df4b..26710b6fd2 100644 --- a/tests/Integration/Commands/README.md +++ b/tests/Integration/Commands/README.md @@ -51,7 +51,7 @@ Enable-SqlDscLogin | 2 | 1 (Install-SqlDscServer), 0 (Prerequisites) | DSCSQLTES Test-SqlDscIsLoginEnabled | 2 | 1 (Install-SqlDscServer), 0 (Prerequisites) | DSCSQLTEST | - New-SqlDscRole | 2 | 1 (Install-SqlDscServer), 0 (Prerequisites) | DSCSQLTEST | SqlDscIntegrationTestRole_Persistent role Get-SqlDscRole | 2 | 1 (Install-SqlDscServer), 0 (Prerequisites) | DSCSQLTEST | - -Grant-SqlDscServerPermission | 2 | 1 (Install-SqlDscServer), 0 (Prerequisites) | DSCSQLTEST | Grants ConnectSql permissions to existing persistent principals, CreateEndpoint to role +Grant-SqlDscServerPermission | 2 | 1 (Install-SqlDscServer), 0 (Prerequisites) | DSCSQLTEST | Grants CreateEndpoint permission to role Get-SqlDscServerPermission | 2 | 1 (Install-SqlDscServer), 0 (Prerequisites) | DSCSQLTEST | - Test-SqlDscServerPermission | 2 | 1 (Install-SqlDscServer), 0 (Prerequisites) | DSCSQLTEST | - Deny-SqlDscServerPermission | 2 | 1 (Install-SqlDscServer), 0 (Prerequisites) | DSCSQLTEST | Denies AlterTrace permission to login (persistent) @@ -104,8 +104,7 @@ with sa owner that remains on the instance for other tests to use. ### `Grant-SqlDscServerPermission` -Grants `ConnectSql` permission to persistent login `IntegrationTestSqlLogin` -and `CreateEndpoint` permission to the role `SqlDscIntegrationTestRole_Persistent` +Grants `CreateEndpoint` permission to the role `SqlDscIntegrationTestRole_Persistent` ### `Deny-SqlDscServerPermission` @@ -181,14 +180,14 @@ Group | Description Login | Password | Permission | Description --- | --- | --- | --- sa | P@ssw0rd1 | sysadmin | Administrator of all the Database Engine instances. -IntegrationTestSqlLogin | P@ssw0rd123! | ConnectSql (Grant), AlterTrace (Deny) | SQL Server login created by New-SqlDscLogin integration tests. ConnectSql permission granted by Grant-SqlDscServerPermission, AlterTrace permission denied by Deny-SqlDscServerPermission integration tests for server permission testing. +IntegrationTestSqlLogin | P@ssw0rd123! | AlterTrace (Deny) | SQL Server login created by New-SqlDscLogin integration tests. AlterTrace permission denied by Deny-SqlDscServerPermission integration tests for server permission testing. .\SqlIntegrationTestGroup | - | - | Windows group login created by New-SqlDscLogin integration tests for testing purposes. ### SQL Server Roles Role | Owner | Permission | Description --- | --- | --- | --- -SqlDscIntegrationTestRole_Persistent | sa | ConnectSql, CreateEndpoint | Server role created by New-SqlDscRole integration tests. ConnectSql and CreateEndpoint permissions granted by Grant-SqlDscServerPermission integration tests for server permission testing. +SqlDscIntegrationTestRole_Persistent | sa | CreateEndpoint | Server role created by New-SqlDscRole integration tests. CreateEndpoint permission granted by Grant-SqlDscServerPermission integration tests for server permission testing. ### Image media (ISO) diff --git a/tests/Integration/Commands/Remove-SqlDscAgentAlert.Integration.Tests.ps1 b/tests/Integration/Commands/Remove-SqlDscAgentAlert.Integration.Tests.ps1 index 8a1cc43068..b386ac6d3a 100644 --- a/tests/Integration/Commands/Remove-SqlDscAgentAlert.Integration.Tests.ps1 +++ b/tests/Integration/Commands/Remove-SqlDscAgentAlert.Integration.Tests.ps1 @@ -24,25 +24,16 @@ BeforeDiscovery { } BeforeAll { - $script:dscModuleName = 'SqlServerDsc' + $script:moduleName = 'SqlServerDsc' - Import-Module -Name $script:dscModuleName -Force -ErrorAction 'Stop' - - $env:SqlServerDscCI = $true - - # Integration tests are run on the DSCSQLTEST instance - $script:sqlServerInstance = 'DSCSQLTEST' -} - -AfterAll { - $env:SqlServerDscCI = $null - - # Unload the module being tested so that it doesn't impact any other tests. - Get-Module -Name $script:dscModuleName -All | Remove-Module -Force + Import-Module -Name $script:moduleName -Force -ErrorAction 'Stop' } -Describe 'Remove-SqlDscAgentAlert' -Tag 'Integration_SQL2017', 'Integration_SQL2019', 'Integration_SQL2022' { +Describe 'Remove-SqlDscAgentAlert' -Tag @('Integration_SQL2017', 'Integration_SQL2019', 'Integration_SQL2022') { BeforeAll { + # Integration tests are run on the DSCSQLTEST instance + $script:sqlServerInstance = 'DSCSQLTEST' + # Starting the named instance SQL Server service prior to running tests. Start-Service -Name 'MSSQL$DSCSQLTEST' -Verbose -ErrorAction 'Stop' diff --git a/tests/Integration/Commands/Remove-SqlDscDatabase.Integration.Tests.ps1 b/tests/Integration/Commands/Remove-SqlDscDatabase.Integration.Tests.ps1 index b81dff88ed..e1603df260 100644 --- a/tests/Integration/Commands/Remove-SqlDscDatabase.Integration.Tests.ps1 +++ b/tests/Integration/Commands/Remove-SqlDscDatabase.Integration.Tests.ps1 @@ -24,9 +24,9 @@ BeforeDiscovery { } BeforeAll { - $script:dscModuleName = 'SqlServerDsc' + $script:moduleName = 'SqlServerDsc' - Import-Module -Name $script:dscModuleName + Import-Module -Name $script:moduleName -Force -ErrorAction 'Stop' } Describe 'Remove-SqlDscDatabase' -Tag @('Integration_SQL2017', 'Integration_SQL2019', 'Integration_SQL2022') { diff --git a/tests/Integration/Commands/Remove-SqlDscLogin.Integration.Tests.ps1 b/tests/Integration/Commands/Remove-SqlDscLogin.Integration.Tests.ps1 index 5e58878fa7..282e4e10f6 100644 --- a/tests/Integration/Commands/Remove-SqlDscLogin.Integration.Tests.ps1 +++ b/tests/Integration/Commands/Remove-SqlDscLogin.Integration.Tests.ps1 @@ -24,12 +24,12 @@ BeforeDiscovery { } BeforeAll { - $script:dscModuleName = 'SqlServerDsc' + $script:moduleName = 'SqlServerDsc' - Import-Module -Name $script:dscModuleName -Force -ErrorAction 'Stop' + Import-Module -Name $script:moduleName -Force -ErrorAction 'Stop' } -Describe 'Remove-SqlDscLogin' -Tag @('Integration_SQL2016', 'Integration_SQL2017', 'Integration_SQL2019', 'Integration_SQL2022') { +Describe 'Remove-SqlDscLogin' -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' diff --git a/tests/Integration/Commands/Remove-SqlDscRole.Integration.Tests.ps1 b/tests/Integration/Commands/Remove-SqlDscRole.Integration.Tests.ps1 index 0162ddf2f5..b36befeabe 100644 --- a/tests/Integration/Commands/Remove-SqlDscRole.Integration.Tests.ps1 +++ b/tests/Integration/Commands/Remove-SqlDscRole.Integration.Tests.ps1 @@ -24,12 +24,12 @@ BeforeDiscovery { } BeforeAll { - $script:dscModuleName = 'SqlServerDsc' + $script:moduleName = 'SqlServerDsc' - Import-Module -Name $script:dscModuleName + Import-Module -Name $script:moduleName -Force -ErrorAction 'Stop' } -Describe 'Remove-SqlDscRole' -Tag @('Integration_SQL2016', 'Integration_SQL2017', 'Integration_SQL2019', 'Integration_SQL2022') { +Describe 'Remove-SqlDscRole' -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' diff --git a/tests/Integration/Commands/Repair-SqlDscBIReportServer.Integration.Tests.ps1 b/tests/Integration/Commands/Repair-SqlDscBIReportServer.Integration.Tests.ps1 index bf1d7296da..0c0dad4585 100644 --- a/tests/Integration/Commands/Repair-SqlDscBIReportServer.Integration.Tests.ps1 +++ b/tests/Integration/Commands/Repair-SqlDscBIReportServer.Integration.Tests.ps1 @@ -23,6 +23,12 @@ BeforeDiscovery { } } +BeforeAll { + $script:moduleName = 'SqlServerDsc' + + Import-Module -Name $script:moduleName -Force -ErrorAction 'Stop' +} + Describe 'Repair-SqlDscBIReportServer' -Tag @('Integration_PowerBI') { BeforeAll { Write-Verbose -Message ('Running integration test as user ''{0}''.' -f $env:UserName) -Verbose diff --git a/tests/Integration/Commands/Repair-SqlDscReportingService.Integration.Tests.ps1 b/tests/Integration/Commands/Repair-SqlDscReportingService.Integration.Tests.ps1 index d2e46a7381..03222bc8e6 100644 --- a/tests/Integration/Commands/Repair-SqlDscReportingService.Integration.Tests.ps1 +++ b/tests/Integration/Commands/Repair-SqlDscReportingService.Integration.Tests.ps1 @@ -23,6 +23,12 @@ BeforeDiscovery { } } +BeforeAll { + $script:moduleName = 'SqlServerDsc' + + Import-Module -Name $script:moduleName -Force -ErrorAction 'Stop' +} + Describe 'Repair-SqlDscReportingService' -Tag @('Integration_SQL2017', 'Integration_SQL2019', 'Integration_SQL2022') { BeforeAll { Write-Verbose -Message ('Running integration test as user ''{0}''.' -f $env:UserName) -Verbose diff --git a/tests/Integration/Commands/Revoke-SqlDscServerPermission.Integration.Tests.ps1 b/tests/Integration/Commands/Revoke-SqlDscServerPermission.Integration.Tests.ps1 index bd87b802f5..1044deb848 100644 --- a/tests/Integration/Commands/Revoke-SqlDscServerPermission.Integration.Tests.ps1 +++ b/tests/Integration/Commands/Revoke-SqlDscServerPermission.Integration.Tests.ps1 @@ -29,48 +29,30 @@ BeforeAll { Import-Module -Name $script:moduleName -Force -ErrorAction 'Stop' } -AfterAll { - # Unload the module being tested so that it doesn't impact any other tests. - Get-Module -Name $script:moduleName -All | Remove-Module -Force -} - -Describe 'Revoke-SqlDscServerPermission' -Tag 'IntegrationTest' { +Describe 'Revoke-SqlDscServerPermission' -Tag @('Integration_SQL2017', 'Integration_SQL2019', 'Integration_SQL2022') { BeforeAll { - # Check if there is a CI database instance to use for testing - $script:sqlServerInstanceName = $env:SqlServerInstanceName + # Starting the named instance SQL Server service prior to running tests. + Start-Service -Name 'MSSQL$DSCSQLTEST' -Verbose -ErrorAction 'Stop' - if (-not $script:sqlServerInstanceName) - { - $script:sqlServerInstanceName = 'DSCSQLTEST' - } + $script:mockInstanceName = 'DSCSQLTEST' - # Get a computer name that will work in the CI environment - $script:computerName = Get-ComputerName + $mockSqlAdministratorUserName = 'SqlAdmin' # Using computer name as NetBIOS name throw exception. + $mockSqlAdministratorPassword = ConvertTo-SecureString -String 'P@ssw0rd1' -AsPlainText -Force - Write-Verbose -Message ('Integration tests will run using computer name ''{0}'' and instance name ''{1}''.' -f $script:computerName, $script:sqlServerInstanceName) -Verbose + $script:mockSqlAdminCredential = [System.Management.Automation.PSCredential]::new($mockSqlAdministratorUserName, $mockSqlAdministratorPassword) - $script:serverObject = Connect-SqlDscDatabaseEngine -ServerName $script:computerName -InstanceName $script:sqlServerInstanceName -Force + $script:serverObject = Connect-SqlDscDatabaseEngine -InstanceName $script:mockInstanceName -Credential $script:mockSqlAdminCredential # Use persistent test login and role created by earlier integration tests $script:testLoginName = 'IntegrationTestSqlLogin' $script:testRoleName = 'SqlDscIntegrationTestRole_Persistent' - - # Verify the persistent principals exist (should be created by New-SqlDscLogin and New-SqlDscRole integration tests) - $existingLogin = Get-SqlDscLogin -ServerObject $script:serverObject -Name $script:testLoginName -ErrorAction 'SilentlyContinue' - if (-not $existingLogin) - { - throw ('Test login {0} does not exist. Please run New-SqlDscLogin integration tests first to create persistent test principals.' -f $script:testLoginName) - } - - $existingRole = Get-SqlDscRole -ServerObject $script:serverObject -Name $script:testRoleName -ErrorAction 'SilentlyContinue' - if (-not $existingRole) - { - throw ('Test role {0} does not exist. Please run New-SqlDscRole integration tests first to create persistent test principals.' -f $script:testRoleName) - } } AfterAll { 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 revoking server permissions from login' { @@ -96,7 +78,7 @@ Describe 'Revoke-SqlDscServerPermission' -Tag 'IntegrationTest' { $null = Revoke-SqlDscServerPermission -Login $loginObject -Permission @('ViewAnyDatabase') -Force -ErrorAction 'Stop' # Test that it's no longer granted - $result = Test-SqlDscServerPermission -Login $loginObject -Grant -Permission @([SqlServerPermission]::ViewAnyDatabase) -ErrorAction 'Stop' + $result = Test-SqlDscServerPermission -Login $loginObject -Grant -Permission @('ViewAnyDatabase') -ErrorAction 'Stop' $result | Should -BeFalse } @@ -110,7 +92,7 @@ Describe 'Revoke-SqlDscServerPermission' -Tag 'IntegrationTest' { $null = $loginObject | Revoke-SqlDscServerPermission -Permission @('ViewAnyDefinition') -Force -ErrorAction 'Stop' # Verify the permission was revoked - $result = Test-SqlDscServerPermission -Login $loginObject -Grant -Permission @([SqlServerPermission]::ViewAnyDefinition) -ErrorAction 'Stop' + $result = Test-SqlDscServerPermission -Login $loginObject -Grant -Permission @('ViewAnyDefinition') -ErrorAction 'Stop' $result | Should -BeFalse } } @@ -128,7 +110,7 @@ Describe 'Revoke-SqlDscServerPermission' -Tag 'IntegrationTest' { $null = Revoke-SqlDscServerPermission -ServerRole $roleObject -Permission @('ViewServerState') -Force -ErrorAction 'Stop' # Test that it's no longer granted - $result = Test-SqlDscServerPermission -ServerRole $roleObject -Grant -Permission @([SqlServerPermission]::ViewServerState) -ErrorAction 'Stop' + $result = Test-SqlDscServerPermission -ServerRole $roleObject -Grant -Permission @('ViewServerState') -ErrorAction 'Stop' $result | Should -BeFalse } diff --git a/tests/Integration/Commands/Set-SqlDscAgentAlert.Integration.Tests.ps1 b/tests/Integration/Commands/Set-SqlDscAgentAlert.Integration.Tests.ps1 index 9f5ae71f70..2731f95b18 100644 --- a/tests/Integration/Commands/Set-SqlDscAgentAlert.Integration.Tests.ps1 +++ b/tests/Integration/Commands/Set-SqlDscAgentAlert.Integration.Tests.ps1 @@ -24,25 +24,16 @@ BeforeDiscovery { } BeforeAll { - $script:dscModuleName = 'SqlServerDsc' + $script:moduleName = 'SqlServerDsc' - Import-Module -Name $script:dscModuleName -Force -ErrorAction 'Stop' - - $env:SqlServerDscCI = $true - - # Integration tests are run on the DSCSQLTEST instance - $script:sqlServerInstance = 'DSCSQLTEST' -} - -AfterAll { - $env:SqlServerDscCI = $null - - # Unload the module being tested so that it doesn't impact any other tests. - Get-Module -Name $script:dscModuleName -All | Remove-Module -Force + Import-Module -Name $script:moduleName -Force -ErrorAction 'Stop' } -Describe 'Set-SqlDscAgentAlert' -Tag 'Integration_SQL2017', 'Integration_SQL2019', 'Integration_SQL2022' { +Describe 'Set-SqlDscAgentAlert' -Tag @('Integration_SQL2017', 'Integration_SQL2019', 'Integration_SQL2022') { BeforeAll { + # Integration tests are run on the DSCSQLTEST instance + $script:sqlServerInstance = 'DSCSQLTEST' + # Starting the named instance SQL Server service prior to running tests. Start-Service -Name 'MSSQL$DSCSQLTEST' -Verbose -ErrorAction 'Stop' diff --git a/tests/Integration/Commands/Set-SqlDscDatabase.Integration.Tests.ps1 b/tests/Integration/Commands/Set-SqlDscDatabase.Integration.Tests.ps1 index e475d9e9f6..66726e0f9c 100644 --- a/tests/Integration/Commands/Set-SqlDscDatabase.Integration.Tests.ps1 +++ b/tests/Integration/Commands/Set-SqlDscDatabase.Integration.Tests.ps1 @@ -24,9 +24,9 @@ BeforeDiscovery { } BeforeAll { - $script:dscModuleName = 'SqlServerDsc' + $script:moduleName = 'SqlServerDsc' - Import-Module -Name $script:dscModuleName + Import-Module -Name $script:moduleName -Force -ErrorAction 'Stop' } Describe 'Set-SqlDscDatabase' -Tag @('Integration_SQL2017', 'Integration_SQL2019', 'Integration_SQL2022') { diff --git a/tests/Integration/Commands/Test-SqlDscAgentAlert.Integration.Tests.ps1 b/tests/Integration/Commands/Test-SqlDscAgentAlert.Integration.Tests.ps1 index 650ae263ae..e99a97ce3e 100644 --- a/tests/Integration/Commands/Test-SqlDscAgentAlert.Integration.Tests.ps1 +++ b/tests/Integration/Commands/Test-SqlDscAgentAlert.Integration.Tests.ps1 @@ -24,25 +24,16 @@ BeforeDiscovery { } BeforeAll { - $script:dscModuleName = 'SqlServerDsc' + $script:moduleName = 'SqlServerDsc' - Import-Module -Name $script:dscModuleName -Force -ErrorAction 'Stop' - - $env:SqlServerDscCI = $true - - # Integration tests are run on the DSCSQLTEST instance - $script:sqlServerInstance = 'DSCSQLTEST' -} - -AfterAll { - $env:SqlServerDscCI = $null - - # Unload the module being tested so that it doesn't impact any other tests. - Get-Module -Name $script:dscModuleName -All | Remove-Module -Force + Import-Module -Name $script:moduleName -Force -ErrorAction 'Stop' } -Describe 'Test-SqlDscAgentAlert' -Tag 'Integration_SQL2017', 'Integration_SQL2019', 'Integration_SQL2022' { +Describe 'Test-SqlDscAgentAlert' -Tag @('Integration_SQL2017', 'Integration_SQL2019', 'Integration_SQL2022'){ BeforeAll { + # Integration tests are run on the DSCSQLTEST instance + $script:sqlServerInstance = 'DSCSQLTEST' + # Starting the named instance SQL Server service prior to running tests. Start-Service -Name 'MSSQL$DSCSQLTEST' -Verbose -ErrorAction 'Stop' diff --git a/tests/Integration/Commands/Test-SqlDscDatabase.Integration.Tests.ps1 b/tests/Integration/Commands/Test-SqlDscDatabase.Integration.Tests.ps1 index a592d4c992..4d91e79981 100644 --- a/tests/Integration/Commands/Test-SqlDscDatabase.Integration.Tests.ps1 +++ b/tests/Integration/Commands/Test-SqlDscDatabase.Integration.Tests.ps1 @@ -24,12 +24,12 @@ BeforeDiscovery { } BeforeAll { - $script:dscModuleName = 'SqlServerDsc' + $script:moduleName = 'SqlServerDsc' - Import-Module -Name $script:dscModuleName -Force -ErrorAction 'Stop' + Import-Module -Name $script:moduleName -Force -ErrorAction 'Stop' } -Describe 'Test-SqlDscDatabase' -Tag @('Integration_SQL2016', 'Integration_SQL2017', 'Integration_SQL2019', 'Integration_SQL2022') { +Describe 'Test-SqlDscDatabase' -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' diff --git a/tests/Integration/Commands/Test-SqlDscIsLoginEnabled.Integration.Tests.ps1 b/tests/Integration/Commands/Test-SqlDscIsLoginEnabled.Integration.Tests.ps1 index 48c8b3fddb..89e96007c6 100644 --- a/tests/Integration/Commands/Test-SqlDscIsLoginEnabled.Integration.Tests.ps1 +++ b/tests/Integration/Commands/Test-SqlDscIsLoginEnabled.Integration.Tests.ps1 @@ -24,12 +24,12 @@ BeforeDiscovery { } BeforeAll { - $script:dscModuleName = 'SqlServerDsc' + $script:moduleName = 'SqlServerDsc' - Import-Module -Name $script:dscModuleName -Force -ErrorAction 'Stop' + Import-Module -Name $script:moduleName -Force -ErrorAction 'Stop' } -Describe 'Test-SqlDscIsLoginEnabled' -Tag @('Integration_SQL2016', 'Integration_SQL2017', 'Integration_SQL2019', 'Integration_SQL2022') { +Describe 'Test-SqlDscIsLoginEnabled' -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' diff --git a/tests/Integration/Commands/Test-SqlDscRSInstalled.Integration.Tests.ps1 b/tests/Integration/Commands/Test-SqlDscRSInstalled.Integration.Tests.ps1 index c04c1c903b..abfd6335dc 100644 --- a/tests/Integration/Commands/Test-SqlDscRSInstalled.Integration.Tests.ps1 +++ b/tests/Integration/Commands/Test-SqlDscRSInstalled.Integration.Tests.ps1 @@ -23,6 +23,12 @@ BeforeDiscovery { } } +BeforeAll { + $script:moduleName = 'SqlServerDsc' + + Import-Module -Name $script:moduleName -Force -ErrorAction 'Stop' +} + Describe 'Test-SqlDscRSInstalled' { Context 'When testing if a specific Reporting Services instance exists' -Tag @('Integration_SQL2017_RS', 'Integration_SQL2019_RS', 'Integration_SQL2022_RS', 'Integration_PowerBI') { It 'Should return $false for a non-existing instance' { diff --git a/tests/Integration/Commands/Test-SqlDscServerPermission.Integration.Tests.ps1 b/tests/Integration/Commands/Test-SqlDscServerPermission.Integration.Tests.ps1 index a43ce23446..1e337a66b3 100644 --- a/tests/Integration/Commands/Test-SqlDscServerPermission.Integration.Tests.ps1 +++ b/tests/Integration/Commands/Test-SqlDscServerPermission.Integration.Tests.ps1 @@ -29,48 +29,30 @@ BeforeAll { Import-Module -Name $script:moduleName -Force -ErrorAction 'Stop' } -AfterAll { - # Unload the module being tested so that it doesn't impact any other tests. - Get-Module -Name $script:moduleName -All | Remove-Module -Force -} - -Describe 'Test-SqlDscServerPermission Integration Tests' -Tag 'Integration' { +Describe 'Test-SqlDscServerPermission' -Tag @('Integration_SQL2017', 'Integration_SQL2019', 'Integration_SQL2022') { BeforeAll { - # Check if there is a CI database instance to use for testing - $script:sqlServerInstanceName = $env:SqlServerInstanceName + # Starting the named instance SQL Server service prior to running tests. + Start-Service -Name 'MSSQL$DSCSQLTEST' -Verbose -ErrorAction 'Stop' - if (-not $script:sqlServerInstanceName) - { - $script:sqlServerInstanceName = 'DSCSQLTEST' - } + $script:mockInstanceName = 'DSCSQLTEST' - # Get a computer name that will work in the CI environment - $script:computerName = Get-ComputerName + $mockSqlAdministratorUserName = 'SqlAdmin' # Using computer name as NetBIOS name throw exception. + $mockSqlAdministratorPassword = ConvertTo-SecureString -String 'P@ssw0rd1' -AsPlainText -Force - Write-Verbose -Message ('Integration tests will run using computer name ''{0}'' and instance name ''{1}''.' -f $script:computerName, $script:sqlServerInstanceName) -Verbose + $script:mockSqlAdminCredential = [System.Management.Automation.PSCredential]::new($mockSqlAdministratorUserName, $mockSqlAdministratorPassword) - $script:serverObject = Connect-SqlDscDatabaseEngine -ServerName $script:computerName -InstanceName $script:sqlServerInstanceName -Force + $script:serverObject = Connect-SqlDscDatabaseEngine -InstanceName $script:mockInstanceName -Credential $script:mockSqlAdminCredential -ErrorAction 'Stop' # Use persistent test login and role created by earlier integration tests $script:testLoginName = 'IntegrationTestSqlLogin' $script:testRoleName = 'SqlDscIntegrationTestRole_Persistent' - - # Verify the persistent principals exist (should be created by New-SqlDscLogin and New-SqlDscRole integration tests) - $existingLogin = Get-SqlDscLogin -ServerObject $script:serverObject -Name $script:testLoginName -ErrorAction 'SilentlyContinue' - if (-not $existingLogin) - { - throw ('Test login {0} does not exist. Please run New-SqlDscLogin integration tests first to create persistent test principals.' -f $script:testLoginName) - } - - $existingRole = Get-SqlDscRole -ServerObject $script:serverObject -Name $script:testRoleName -ErrorAction 'SilentlyContinue' - if (-not $existingRole) - { - throw ('Test role {0} does not exist. Please run New-SqlDscRole integration tests first to create persistent test principals.' -f $script:testRoleName) - } } AfterAll { 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 testing server permissions for login' { @@ -88,7 +70,7 @@ Describe 'Test-SqlDscServerPermission Integration Tests' -Tag 'Integration' { It 'Should return true when permissions match desired state' { $loginObject = Get-SqlDscLogin -ServerObject $script:serverObject -Name $script:testLoginName -ErrorAction 'Stop' - $result = Test-SqlDscServerPermission -Login $loginObject -Grant -Permission @([SqlServerPermission]::ConnectSql, [SqlServerPermission]::ViewServerState) -ErrorAction 'Stop' + $result = Test-SqlDscServerPermission -Login $loginObject -Grant -Permission @('ConnectSql', 'ViewServerState') -ErrorAction 'Stop' $result | Should -BeTrue } @@ -96,7 +78,7 @@ Describe 'Test-SqlDscServerPermission Integration Tests' -Tag 'Integration' { It 'Should return false when permissions do not match desired state' { $loginObject = Get-SqlDscLogin -ServerObject $script:serverObject -Name $script:testLoginName -ErrorAction 'Stop' - $result = Test-SqlDscServerPermission -Login $loginObject -Grant -Permission @([SqlServerPermission]::AlterAnyDatabase) -ErrorAction 'Stop' + $result = Test-SqlDscServerPermission -Login $loginObject -Grant -Permission @('AlterAnyDatabase') -ErrorAction 'Stop' $result | Should -BeFalse } @@ -104,7 +86,7 @@ Describe 'Test-SqlDscServerPermission Integration Tests' -Tag 'Integration' { It 'Should accept Login object from pipeline' { $loginObject = Get-SqlDscLogin -ServerObject $script:serverObject -Name $script:testLoginName -ErrorAction 'Stop' - $result = $loginObject | Test-SqlDscServerPermission -Grant -Permission @([SqlServerPermission]::ConnectSql, [SqlServerPermission]::ViewServerState) -ErrorAction 'Stop' + $result = $loginObject | Test-SqlDscServerPermission -Grant -Permission @('ConnectSql', 'ViewServerState') -ErrorAction 'Stop' $result | Should -BeTrue } @@ -112,7 +94,7 @@ Describe 'Test-SqlDscServerPermission Integration Tests' -Tag 'Integration' { It 'Should return true when only testing specific grant permission that exists' { $loginObject = Get-SqlDscLogin -ServerObject $script:serverObject -Name $script:testLoginName -ErrorAction 'Stop' - $result = Test-SqlDscServerPermission -Login $loginObject -Grant -Permission @([SqlServerPermission]::ConnectSql) -ErrorAction 'Stop' + $result = Test-SqlDscServerPermission -Login $loginObject -Grant -Permission @('ConnectSql') -ErrorAction 'Stop' $result | Should -BeTrue } @@ -120,33 +102,27 @@ Describe 'Test-SqlDscServerPermission Integration Tests' -Tag 'Integration' { It 'Should return false when testing for permission that does not exist' { $loginObject = Get-SqlDscLogin -ServerObject $script:serverObject -Name $script:testLoginName -ErrorAction 'Stop' - $result = Test-SqlDscServerPermission -Login $loginObject -Grant -Permission @([SqlServerPermission]::AlterAnyCredential) -ErrorAction 'Stop' + $result = Test-SqlDscServerPermission -Login $loginObject -Grant -Permission @('AlterAnyCredential') -ErrorAction 'Stop' $result | Should -BeFalse } + # cSpell:ignore securityadmin It 'Should return true when testing for empty permission collection on principal with no additional permissions' { - # Create a temporary login for this test to ensure it has no additional permissions - $tempLoginName = 'TempTestLogin_' + (Get-Random) - $tempLoginObject = New-SqlDscLogin -ServerObject $script:serverObject -Name $tempLoginName -LoginType SqlLogin -SecureString (ConvertTo-SecureString -String 'TempPassword123!' -AsPlainText -Force) -Force -ErrorAction 'Stop' + # Get the built-in securityadmin server role which should have no explicit permissions + $securityAdminRole = Get-SqlDscRole -ServerObject $script:serverObject -Name 'securityadmin' -ErrorAction 'Stop' - try { - # Test that empty permission collection returns true when no permissions are set - $result = Test-SqlDscServerPermission -Login $tempLoginObject -Grant -Permission @() -ErrorAction 'Stop' + # Test that empty permission collection returns true when no permissions are set + $result = Test-SqlDscServerPermission -ServerRole $securityAdminRole -Grant -Permission @() -ErrorAction 'Stop' - $result | Should -BeTrue - } - finally { - # Clean up temporary login - Remove-SqlDscLogin -Login $tempLoginObject -Force -ErrorAction 'SilentlyContinue' - } + $result | Should -BeTrue } It 'Should return false when using ExactMatch and additional permissions exist' { $loginObject = Get-SqlDscLogin -ServerObject $script:serverObject -Name $script:testLoginName -ErrorAction 'Stop' - # Test with ExactMatch - should fail because ViewServerState is also granted - $result = Test-SqlDscServerPermission -Login $loginObject -Grant -Permission @([SqlServerPermission]::ConnectSql) -ExactMatch -ErrorAction 'Stop' + # Test with ExactMatch - should fail because ViewServerState and ViewAnyDefinition is also granted + $result = Test-SqlDscServerPermission -Login $loginObject -Grant -Permission @('ConnectSql') -ExactMatch -ErrorAction 'Stop' $result | Should -BeFalse } @@ -154,8 +130,8 @@ Describe 'Test-SqlDscServerPermission Integration Tests' -Tag 'Integration' { It 'Should return true when using ExactMatch and permissions exactly match' { $loginObject = Get-SqlDscLogin -ServerObject $script:serverObject -Name $script:testLoginName -ErrorAction 'Stop' - # Test with ExactMatch - should pass because both ConnectSql and ViewServerState are granted - $result = Test-SqlDscServerPermission -Login $loginObject -Grant -Permission @([SqlServerPermission]::ConnectSql, [SqlServerPermission]::ViewServerState) -ExactMatch -ErrorAction 'Stop' + # Test with ExactMatch - should pass because both ConnectSql, ViewAnyDefinition and ViewServerState are granted + $result = Test-SqlDscServerPermission -Login $loginObject -Grant -Permission @('ConnectSql', 'ViewServerState', 'ViewAnyDefinition') -ExactMatch -ErrorAction 'Stop' $result | Should -BeTrue } @@ -165,18 +141,26 @@ Describe 'Test-SqlDscServerPermission Integration Tests' -Tag 'Integration' { BeforeAll { # Set up known permissions for testing $roleObject = Get-SqlDscRole -ServerObject $script:serverObject -Name $script:testRoleName -ErrorAction 'Stop' - $null = Grant-SqlDscServerPermission -ServerRole $roleObject -Permission @('ViewServerState') -Force -ErrorAction 'Stop' + $null = Grant-SqlDscServerPermission -ServerRole $roleObject -Permission @('ConnectSql', 'ViewServerState', 'CreateAnyDatabase') -Force -ErrorAction 'Stop' } AfterAll { $roleObject = Get-SqlDscRole -ServerObject $script:serverObject -Name $script:testRoleName -ErrorAction 'Stop' - $null = Revoke-SqlDscServerPermission -ServerRole $roleObject -Permission @('ViewServerState') -Force -ErrorAction 'SilentlyContinue' + $null = Revoke-SqlDscServerPermission -ServerRole $roleObject -Permission @('ConnectSql', 'ViewServerState', 'CreateAnyDatabase') -Force -ErrorAction 'SilentlyContinue' } It 'Should return true when role permissions match desired state' { $roleObject = Get-SqlDscRole -ServerObject $script:serverObject -Name $script:testRoleName -ErrorAction 'Stop' - $result = Test-SqlDscServerPermission -ServerRole $roleObject -Grant -Permission @([SqlServerPermission]::ConnectSql, [SqlServerPermission]::ViewServerState) -ErrorAction 'Stop' + $result = Test-SqlDscServerPermission -ServerRole $roleObject -Grant -Permission @('ConnectSql', 'ViewServerState') -ErrorAction 'Stop' + + $result | Should -BeTrue + } + + It 'Should return true when role permissions exact match desired state' { + $roleObject = Get-SqlDscRole -ServerObject $script:serverObject -Name $script:testRoleName -ErrorAction 'Stop' + + $result = Test-SqlDscServerPermission -ServerRole $roleObject -Grant -Permission @('ConnectSql', 'ViewServerState', 'CreateEndpoint', 'CreateAnyDatabase') -ExactMatch -ErrorAction 'Stop' $result | Should -BeTrue } @@ -184,28 +168,44 @@ Describe 'Test-SqlDscServerPermission Integration Tests' -Tag 'Integration' { It 'Should return false when role permissions do not match desired state' { $roleObject = Get-SqlDscRole -ServerObject $script:serverObject -Name $script:testRoleName -ErrorAction 'Stop' - $result = Test-SqlDscServerPermission -ServerRole $roleObject -Grant -Permission @([SqlServerPermission]::CreateAnyDatabase) -ErrorAction 'Stop' + $result = Test-SqlDscServerPermission -ServerRole $roleObject -Grant -Permission @('AlterAnyEndpoint') -ErrorAction 'Stop' + + $result | Should -BeFalse + } + + It 'Should return false when role permissions do not exact match desired state' { + $roleObject = Get-SqlDscRole -ServerObject $script:serverObject -Name $script:testRoleName -ErrorAction 'Stop' + + $result = Test-SqlDscServerPermission -ServerRole $roleObject -Grant -Permission @('ViewServerState') -ExactMatch -ErrorAction 'Stop' $result | Should -BeFalse } + + It 'Should accept ServerRole object from pipeline' { + $roleObject = Get-SqlDscRole -ServerObject $script:serverObject -Name $script:testRoleName -ErrorAction 'Stop' + + $result = $roleObject | Test-SqlDscServerPermission -Grant -Permission @('ConnectSql', 'ViewServerState') -ErrorAction 'Stop' + + $result | Should -BeTrue + } } Context 'When testing deny permissions' { BeforeAll { # Set up denied permissions for testing $loginObject = Get-SqlDscLogin -ServerObject $script:serverObject -Name $script:testLoginName -ErrorAction 'Stop' - Deny-SqlDscServerPermission -Login $loginObject -Permission @('ViewAnyDefinition') -Force -ErrorAction 'Stop' + $null = Deny-SqlDscServerPermission -Login $loginObject -Permission @('ViewAnyDefinition') -Force -ErrorAction 'Stop' } AfterAll { $loginObject = Get-SqlDscLogin -ServerObject $script:serverObject -Name $script:testLoginName -ErrorAction 'Stop' - Revoke-SqlDscServerPermission -Login $loginObject -Permission @('ViewAnyDefinition') -Force -ErrorAction 'SilentlyContinue' + $null = Revoke-SqlDscServerPermission -Login $loginObject -Permission @('ViewAnyDefinition') -Force -ErrorAction 'SilentlyContinue' } It 'Should return true when testing for denied permission that exists' { $loginObject = Get-SqlDscLogin -ServerObject $script:serverObject -Name $script:testLoginName -ErrorAction 'Stop' - $result = Test-SqlDscServerPermission -Login $loginObject -Deny -Permission @([SqlServerPermission]::ViewAnyDefinition) -ErrorAction 'Stop' + $result = Test-SqlDscServerPermission -Login $loginObject -Deny -Permission @('ViewAnyDefinition') -ErrorAction 'Stop' $result | Should -BeTrue } @@ -213,7 +213,7 @@ Describe 'Test-SqlDscServerPermission Integration Tests' -Tag 'Integration' { It 'Should return false when testing for denied permission that does not exist' { $loginObject = Get-SqlDscLogin -ServerObject $script:serverObject -Name $script:testLoginName -ErrorAction 'Stop' - $result = Test-SqlDscServerPermission -Login $loginObject -Deny -Permission @([SqlServerPermission]::AlterServerState) -ErrorAction 'Stop' + $result = Test-SqlDscServerPermission -Login $loginObject -Deny -Permission @('AlterServerState') -ErrorAction 'Stop' $result | Should -BeFalse } @@ -234,7 +234,7 @@ Describe 'Test-SqlDscServerPermission Integration Tests' -Tag 'Integration' { It 'Should return true when testing for grant with grant permission that exists' { $loginObject = Get-SqlDscLogin -ServerObject $script:serverObject -Name $script:testLoginName -ErrorAction 'Stop' - $result = Test-SqlDscServerPermission -Login $loginObject -Grant -Permission @([SqlServerPermission]::ViewAnyDatabase) -WithGrant -ErrorAction 'Stop' + $result = Test-SqlDscServerPermission -Login $loginObject -Grant -Permission @('ViewAnyDatabase') -WithGrant -ErrorAction 'Stop' $result | Should -BeTrue } @@ -242,7 +242,7 @@ Describe 'Test-SqlDscServerPermission Integration Tests' -Tag 'Integration' { It 'Should return false when testing for grant with grant permission that does not exist' { $loginObject = Get-SqlDscLogin -ServerObject $script:serverObject -Name $script:testLoginName -ErrorAction 'Stop' - $result = Test-SqlDscServerPermission -Login $loginObject -Grant -Permission @([SqlServerPermission]::CreateEndpoint) -WithGrant -ErrorAction 'Stop' + $result = Test-SqlDscServerPermission -Login $loginObject -Grant -Permission @('CreateEndpoint') -WithGrant -ErrorAction 'Stop' $result | Should -BeFalse } @@ -254,7 +254,7 @@ Describe 'Test-SqlDscServerPermission Integration Tests' -Tag 'Integration' { # We need to use a real server object but with a non-existent login name $mockLogin = [Microsoft.SqlServer.Management.Smo.Login]::new($script:serverObject, 'NonExistentLogin') - $result = Test-SqlDscServerPermission -Login $mockLogin -Grant -Permission @([SqlServerPermission]::ConnectSql) -ErrorAction 'Stop' + $result = Test-SqlDscServerPermission -Login $mockLogin -Grant -Permission @('ConnectSql') -ErrorAction 'Stop' $result | Should -BeFalse } diff --git a/tests/Integration/Commands/Uninstall-SqlDscBIReportServer.Integration.Tests.ps1 b/tests/Integration/Commands/Uninstall-SqlDscBIReportServer.Integration.Tests.ps1 index fa9d6f027a..91493231b5 100644 --- a/tests/Integration/Commands/Uninstall-SqlDscBIReportServer.Integration.Tests.ps1 +++ b/tests/Integration/Commands/Uninstall-SqlDscBIReportServer.Integration.Tests.ps1 @@ -23,6 +23,12 @@ BeforeDiscovery { } } +BeforeAll { + $script:moduleName = 'SqlServerDsc' + + Import-Module -Name $script:moduleName -Force -ErrorAction 'Stop' +} + Describe 'Uninstall-SqlDscBIReportServer' -Tag @('Integration_PowerBI') { BeforeAll { Write-Verbose -Message ('Running integration test as user ''{0}''.' -f $env:UserName) -Verbose diff --git a/tests/Integration/Commands/Uninstall-SqlDscReportingService.Integration.Tests.ps1 b/tests/Integration/Commands/Uninstall-SqlDscReportingService.Integration.Tests.ps1 index c77b4d091b..e3ff239118 100644 --- a/tests/Integration/Commands/Uninstall-SqlDscReportingService.Integration.Tests.ps1 +++ b/tests/Integration/Commands/Uninstall-SqlDscReportingService.Integration.Tests.ps1 @@ -23,6 +23,12 @@ BeforeDiscovery { } } +BeforeAll { + $script:moduleName = 'SqlServerDsc' + + Import-Module -Name $script:moduleName -Force -ErrorAction 'Stop' +} + Describe 'Uninstall-SqlDscReportingService' -Tag @('Integration_SQL2017', 'Integration_SQL2019', 'Integration_SQL2022') { BeforeAll { Write-Verbose -Message ('Running integration test as user ''{0}''.' -f $env:UserName) -Verbose diff --git a/tests/Integration/Commands/Uninstall-SqlDscServer.Integration.Tests.ps1 b/tests/Integration/Commands/Uninstall-SqlDscServer.Integration.Tests.ps1 index ad0c8765ea..6c7c120e9f 100644 --- a/tests/Integration/Commands/Uninstall-SqlDscServer.Integration.Tests.ps1 +++ b/tests/Integration/Commands/Uninstall-SqlDscServer.Integration.Tests.ps1 @@ -23,8 +23,14 @@ BeforeDiscovery { } } +BeforeAll { + $script:moduleName = 'SqlServerDsc' + + Import-Module -Name $script:moduleName -Force -ErrorAction 'Stop' +} + # cSpell: ignore DSCSQLTEST -Describe 'Uninstall-SqlDscServer' -Tag @('Integration_SQL2016', 'Integration_SQL2017', 'Integration_SQL2019', 'Integration_SQL2022') { +Describe 'Uninstall-SqlDscServer' -Tag @('Integration_SQL2017', 'Integration_SQL2019', 'Integration_SQL2022') { BeforeAll { Write-Verbose -Message ('Running integration test as user ''{0}''.' -f $env:UserName) -Verbose diff --git a/tests/Unit/Public/Get-SqlDscServerPermission.Tests.ps1 b/tests/Unit/Public/Get-SqlDscServerPermission.Tests.ps1 index 4f97f27d57..dbdc381abe 100644 --- a/tests/Unit/Public/Get-SqlDscServerPermission.Tests.ps1 +++ b/tests/Unit/Public/Get-SqlDscServerPermission.Tests.ps1 @@ -58,6 +58,10 @@ Describe 'Get-SqlDscServerPermission' -Tag 'Public' { Mock -CommandName Test-SqlDscIsLogin -MockWith { return $false } + + Mock -CommandName Test-SqlDscIsRole -MockWith { + return $false + } } Context 'When specifying to throw on error' { @@ -81,7 +85,7 @@ Describe 'Get-SqlDscServerPermission' -Tag 'Public' { } } - Context 'When the principal exist' { + Context 'When the principal is a login' { BeforeAll { $mockServerObject = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Server' | Add-Member -MemberType 'ScriptMethod' -Name 'EnumServerPermissions' -Value { @@ -114,6 +118,10 @@ Describe 'Get-SqlDscServerPermission' -Tag 'Public' { Mock -CommandName Test-SqlDscIsLogin -MockWith { return $true } + + Mock -CommandName Test-SqlDscIsRole -MockWith { + return $false + } } It 'Should return the correct values' { @@ -146,4 +154,476 @@ Describe 'Get-SqlDscServerPermission' -Tag 'Public' { } } } + + Context 'When the principal is a server role' { + BeforeAll { + $mockServerObject = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Server' | + Add-Member -MemberType 'ScriptMethod' -Name 'EnumServerPermissions' -Value { + param + ( + [Parameter()] + [System.String] + $SqlServerRole + ) + + $mockEnumServerPermissions = [Microsoft.SqlServer.Management.Smo.ServerPermissionInfo[]] @() + + $mockEnumServerPermissions += [Microsoft.SqlServer.Management.Smo.ServerPermissionInfo] @{ + PermissionType = [Microsoft.SqlServer.Management.Smo.ServerPermissionSet] @{ + ViewServerState = $true + } + PermissionState = 'Grant' + } + + $mockEnumServerPermissions += [Microsoft.SqlServer.Management.Smo.ServerPermissionInfo] @{ + PermissionType = [Microsoft.SqlServer.Management.Smo.ServerPermissionSet] @{ + ControlServer = $true + } + PermissionState = 'Grant' + } + + return $mockEnumServerPermissions + } -PassThru -Force + + Mock -CommandName Test-SqlDscIsLogin -MockWith { + return $false + } + + Mock -CommandName Test-SqlDscIsRole -MockWith { + return $true + } + } + + It 'Should return the correct values for a server role' { + $mockResult = Get-SqlDscServerPermission -ServerObject $mockServerObject -Name 'MyCustomRole' -ErrorAction 'Stop' + + $mockResult | Should -HaveCount 2 + + $mockResult[0].PermissionState | Should -Be 'Grant' + $mockResult[0].PermissionType.ViewServerState | Should -BeTrue + $mockResult[0].PermissionType.ControlServer | Should -BeFalse + + $mockResult[1].PermissionState | Should -Be 'Grant' + $mockResult[1].PermissionType.ViewServerState | Should -BeFalse + $mockResult[1].PermissionType.ControlServer | Should -BeTrue + } + + Context 'When passing ServerObject over the pipeline' { + It 'Should return the correct values for a server role' { + $mockResult = $mockServerObject | Get-SqlDscServerPermission -Name 'MyCustomRole' -ErrorAction 'Stop' + + $mockResult | Should -HaveCount 2 + + $mockResult[0].PermissionState | Should -Be 'Grant' + $mockResult[0].PermissionType.ViewServerState | Should -BeTrue + $mockResult[0].PermissionType.ControlServer | Should -BeFalse + + $mockResult[1].PermissionState | Should -Be 'Grant' + $mockResult[1].PermissionType.ViewServerState | Should -BeFalse + $mockResult[1].PermissionType.ControlServer | Should -BeTrue + } + } + } + + Context 'When verifying function calls' { + BeforeAll { + $mockServerObject = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Server' | + Add-Member -MemberType 'ScriptMethod' -Name 'EnumServerPermissions' -Value { + return @() + } -PassThru -Force + } + + Context 'When no PrincipalType is specified' { + BeforeAll { + Mock -CommandName Test-SqlDscIsLogin -MockWith { + return $true + } + + Mock -CommandName Test-SqlDscIsRole -MockWith { + return $false + } + } + + It 'Should call both Test-SqlDscIsLogin and Test-SqlDscIsRole' { + $null = Get-SqlDscServerPermission -ServerObject $mockServerObject -Name 'TestPrincipal' -ErrorAction 'SilentlyContinue' + + Should -Invoke -CommandName Test-SqlDscIsLogin -ParameterFilter { + $ServerObject.Equals($mockServerObject) -and $Name -eq 'TestPrincipal' + } -Exactly -Times 1 + + Should -Invoke -CommandName Test-SqlDscIsRole -ParameterFilter { + $ServerObject.Equals($mockServerObject) -and $Name -eq 'TestPrincipal' + } -Exactly -Times 1 + } + } + + Context 'When no PrincipalType is specified and login is not found' { + BeforeAll { + Mock -CommandName Test-SqlDscIsLogin -MockWith { + return $false + } + + Mock -CommandName Test-SqlDscIsRole -MockWith { + return $true + } + } + + It 'Should call both Test-SqlDscIsLogin and Test-SqlDscIsRole' { + $null = Get-SqlDscServerPermission -ServerObject $mockServerObject -Name 'TestPrincipal' -ErrorAction 'SilentlyContinue' + + Should -Invoke -CommandName Test-SqlDscIsLogin -ParameterFilter { + $ServerObject.Equals($mockServerObject) -and $Name -eq 'TestPrincipal' + } -Exactly -Times 1 + + Should -Invoke -CommandName Test-SqlDscIsRole -ParameterFilter { + $ServerObject.Equals($mockServerObject) -and $Name -eq 'TestPrincipal' + } -Exactly -Times 1 + } + } + + Context 'When PrincipalType is Login' { + BeforeAll { + Mock -CommandName Test-SqlDscIsLogin -MockWith { + return $true + } + + Mock -CommandName Test-SqlDscIsRole -MockWith { + return $false + } + } + + It 'Should only call Test-SqlDscIsLogin' { + $null = Get-SqlDscServerPermission -ServerObject $mockServerObject -Name 'TestPrincipal' -PrincipalType 'Login' -ErrorAction 'SilentlyContinue' + + Should -Invoke -CommandName Test-SqlDscIsLogin -ParameterFilter { + $ServerObject.Equals($mockServerObject) -and $Name -eq 'TestPrincipal' + } -Exactly -Times 1 + + Should -Invoke -CommandName Test-SqlDscIsRole -Exactly -Times 0 + } + } + + Context 'When PrincipalType is Role' { + BeforeAll { + Mock -CommandName Test-SqlDscIsLogin -MockWith { + return $false + } + + Mock -CommandName Test-SqlDscIsRole -MockWith { + return $true + } + } + + It 'Should only call Test-SqlDscIsRole' { + $null = Get-SqlDscServerPermission -ServerObject $mockServerObject -Name 'TestPrincipal' -PrincipalType 'Role' -ErrorAction 'SilentlyContinue' + + Should -Invoke -CommandName Test-SqlDscIsLogin -Exactly -Times 0 + + Should -Invoke -CommandName Test-SqlDscIsRole -ParameterFilter { + $ServerObject.Equals($mockServerObject) -and $Name -eq 'TestPrincipal' + } -Exactly -Times 1 + } + } + + Context 'When PrincipalType is both Login and Role' { + BeforeAll { + Mock -CommandName Test-SqlDscIsLogin -MockWith { + return $true + } + + Mock -CommandName Test-SqlDscIsRole -MockWith { + return $false + } + } + + It 'Should call both Test-SqlDscIsLogin and Test-SqlDscIsRole when both types are specified' { + $null = Get-SqlDscServerPermission -ServerObject $mockServerObject -Name 'TestPrincipal' -PrincipalType 'Login', 'Role' -ErrorAction 'SilentlyContinue' + + Should -Invoke -CommandName Test-SqlDscIsLogin -ParameterFilter { + $ServerObject.Equals($mockServerObject) -and $Name -eq 'TestPrincipal' + } -Exactly -Times 1 + + Should -Invoke -CommandName Test-SqlDscIsRole -ParameterFilter { + $ServerObject.Equals($mockServerObject) -and $Name -eq 'TestPrincipal' + } -Exactly -Times 1 + } + } + } + + Context 'When using PrincipalType parameter' { + Context 'When PrincipalType is Login and principal is a login' { + BeforeAll { + $mockServerObject = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Server' | + Add-Member -MemberType 'ScriptMethod' -Name 'EnumServerPermissions' -Value { + param + ( + [Parameter()] + [System.String] + $SqlServerLogin + ) + + $mockEnumServerPermissions = [Microsoft.SqlServer.Management.Smo.ServerPermissionInfo[]] @() + + $mockEnumServerPermissions += [Microsoft.SqlServer.Management.Smo.ServerPermissionInfo] @{ + PermissionType = [Microsoft.SqlServer.Management.Smo.ServerPermissionSet] @{ + ConnectSql = $true + } + PermissionState = 'Grant' + } + + return $mockEnumServerPermissions + } -PassThru -Force + + Mock -CommandName Test-SqlDscIsLogin -MockWith { + return $true + } + + Mock -CommandName Test-SqlDscIsRole -MockWith { + return $false + } + } + + It 'Should return the correct values when specifying PrincipalType as Login' { + $mockResult = Get-SqlDscServerPermission -ServerObject $mockServerObject -Name 'TestLogin' -PrincipalType 'Login' -ErrorAction 'Stop' + + $mockResult | Should -HaveCount 1 + $mockResult[0].PermissionState | Should -Be 'Grant' + $mockResult[0].PermissionType.ConnectSql | Should -BeTrue + } + } + + Context 'When PrincipalType is Role and principal is a role' { + BeforeAll { + $mockServerObject = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Server' | + Add-Member -MemberType 'ScriptMethod' -Name 'EnumServerPermissions' -Value { + param + ( + [Parameter()] + [System.String] + $SqlServerRole + ) + + $mockEnumServerPermissions = [Microsoft.SqlServer.Management.Smo.ServerPermissionInfo[]] @() + + $mockEnumServerPermissions += [Microsoft.SqlServer.Management.Smo.ServerPermissionInfo] @{ + PermissionType = [Microsoft.SqlServer.Management.Smo.ServerPermissionSet] @{ + ViewServerState = $true + } + PermissionState = 'Grant' + } + + return $mockEnumServerPermissions + } -PassThru -Force + + Mock -CommandName Test-SqlDscIsLogin -MockWith { + return $false + } + + Mock -CommandName Test-SqlDscIsRole -MockWith { + return $true + } + } + + It 'Should return the correct values when specifying PrincipalType as Role' { + $mockResult = Get-SqlDscServerPermission -ServerObject $mockServerObject -Name 'TestRole' -PrincipalType 'Role' -ErrorAction 'Stop' + + $mockResult | Should -HaveCount 1 + $mockResult[0].PermissionState | Should -Be 'Grant' + $mockResult[0].PermissionType.ViewServerState | Should -BeTrue + } + } + + Context 'When PrincipalType is Login but principal is not a login' { + BeforeAll { + $mockServerObject = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Server' + $mockServerObject.InstanceName = 'MockInstance' + + Mock -CommandName Test-SqlDscIsLogin -MockWith { + return $false + } + + Mock -CommandName Test-SqlDscIsRole -MockWith { + return $false + } + + $mockErrorMessage = InModuleScope -ScriptBlock { + $script:localizedData.ServerPermission_MissingPrincipal + } + } + + It 'Should throw an error when principal is not found as login' { + { Get-SqlDscServerPermission -ServerObject $mockServerObject -Name 'NotALogin' -PrincipalType 'Login' -ErrorAction 'Stop' } | + Should -Throw -ExpectedMessage ($mockErrorMessage -f 'NotALogin', 'MockInstance') + } + } + } + + Context 'When using Login parameter set' { + BeforeAll { + $mockServerObject = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Server' | + Add-Member -MemberType 'ScriptMethod' -Name 'EnumServerPermissions' -Value { + param + ( + [Parameter()] + [System.String] + $SqlServerLogin + ) + + $mockEnumServerPermissions = [Microsoft.SqlServer.Management.Smo.ServerPermissionInfo[]] @() + + $mockEnumServerPermissions += [Microsoft.SqlServer.Management.Smo.ServerPermissionInfo] @{ + PermissionType = [Microsoft.SqlServer.Management.Smo.ServerPermissionSet] @{ + ConnectSql = $true + } + PermissionState = 'Grant' + } + + return $mockEnumServerPermissions + } -PassThru -Force + + $mockLoginObject = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Login' -ArgumentList $mockServerObject, 'TestLogin' + } + + It 'Should return the correct values when using Login object' { + $mockResult = Get-SqlDscServerPermission -Login $mockLoginObject -ErrorAction 'Stop' + + $mockResult | Should -HaveCount 1 + $mockResult[0].PermissionState | Should -Be 'Grant' + $mockResult[0].PermissionType.ConnectSql | Should -BeTrue + } + + It 'Should accept Login from pipeline' { + $mockResult = $mockLoginObject | Get-SqlDscServerPermission -ErrorAction 'Stop' + + $mockResult | Should -HaveCount 1 + $mockResult[0].PermissionState | Should -Be 'Grant' + $mockResult[0].PermissionType.ConnectSql | Should -BeTrue + } + } + + Context 'When using ServerRole parameter set' { + BeforeAll { + $mockServerObject = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Server' | + Add-Member -MemberType 'ScriptMethod' -Name 'EnumServerPermissions' -Value { + param + ( + [Parameter()] + [System.String] + $SqlServerRole + ) + + $mockEnumServerPermissions = [Microsoft.SqlServer.Management.Smo.ServerPermissionInfo[]] @() + + $mockEnumServerPermissions += [Microsoft.SqlServer.Management.Smo.ServerPermissionInfo] @{ + PermissionType = [Microsoft.SqlServer.Management.Smo.ServerPermissionSet] @{ + ViewServerState = $true + } + PermissionState = 'Grant' + } + + return $mockEnumServerPermissions + } -PassThru -Force + + $mockServerRoleObject = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.ServerRole' -ArgumentList $mockServerObject, 'TestRole' + } + + It 'Should return the correct values when using ServerRole object' { + $mockResult = Get-SqlDscServerPermission -ServerRole $mockServerRoleObject -ErrorAction 'Stop' + + $mockResult | Should -HaveCount 1 + $mockResult[0].PermissionState | Should -Be 'Grant' + $mockResult[0].PermissionType.ViewServerState | Should -BeTrue + } + + It 'Should accept ServerRole from pipeline' { + $mockResult = $mockServerRoleObject | Get-SqlDscServerPermission -ErrorAction 'Stop' + + $mockResult | Should -HaveCount 1 + $mockResult[0].PermissionState | Should -Be 'Grant' + $mockResult[0].PermissionType.ViewServerState | Should -BeTrue + } + } + + Context 'When validating parameters' { + It 'Should have the correct parameters in parameter set ' -ForEach @( + @{ + MockParameterSetName = 'ByName' + MockExpectedParameters = '-ServerObject -Name [-PrincipalType ] []' + } + @{ + MockParameterSetName = 'Login' + MockExpectedParameters = '-Login []' + } + @{ + MockParameterSetName = 'ServerRole' + MockExpectedParameters = '-ServerRole []' + } + ) { + $result = (Get-Command -Name 'Get-SqlDscServerPermission').ParameterSets | + Where-Object -FilterScript { + $_.Name -eq $mockParameterSetName + } | + Select-Object -Property @( + @{ + Name = 'ParameterSetName' + Expression = { $_.Name } + }, + @{ + Name = 'ParameterListAsString' + Expression = { $_.ToString() } + } + ) + + $result.ParameterSetName | Should -Be $MockParameterSetName + $result.ParameterListAsString | Should -Be $MockExpectedParameters + } + + It 'Should have ServerObject as a mandatory parameter in ByName parameter set' { + $parameterInfo = (Get-Command -Name 'Get-SqlDscServerPermission').Parameters['ServerObject'] + $parameterInfo.Attributes.Mandatory | Should -Contain $true + } + + It 'Should accept ServerObject from pipeline in ByName parameter set' { + $parameterInfo = (Get-Command -Name 'Get-SqlDscServerPermission').Parameters['ServerObject'] + $parameterInfo.Attributes.ValueFromPipeline | Should -Contain $true + } + + It 'Should have Name as a mandatory parameter in ByName parameter set' { + $parameterInfo = (Get-Command -Name 'Get-SqlDscServerPermission').Parameters['Name'] + $parameterInfo.Attributes.Mandatory | Should -Contain $true + } + + It 'Should have PrincipalType as an optional parameter in ByName parameter set' { + $parameterInfo = (Get-Command -Name 'Get-SqlDscServerPermission').Parameters['PrincipalType'] + $parameterInfo.Attributes.Mandatory | Should -Not -Contain $true + } + + It 'Should have PrincipalType with correct ValidateSet values' { + $parameterInfo = (Get-Command -Name 'Get-SqlDscServerPermission').Parameters['PrincipalType'] + $validateSetAttribute = $parameterInfo.Attributes | Where-Object { $_ -is [System.Management.Automation.ValidateSetAttribute] } + $validateSetAttribute.ValidValues | Should -Contain 'Login' + $validateSetAttribute.ValidValues | Should -Contain 'Role' + $validateSetAttribute.ValidValues | Should -HaveCount 2 + } + + It 'Should have Login as a mandatory parameter in Login parameter set' { + $parameterInfo = (Get-Command -Name 'Get-SqlDscServerPermission').Parameters['Login'] + $parameterInfo.Attributes.Mandatory | Should -Contain $true + } + + It 'Should accept Login from pipeline in Login parameter set' { + $parameterInfo = (Get-Command -Name 'Get-SqlDscServerPermission').Parameters['Login'] + $parameterInfo.Attributes.ValueFromPipeline | Should -Contain $true + } + + It 'Should have ServerRole as a mandatory parameter in ServerRole parameter set' { + $parameterInfo = (Get-Command -Name 'Get-SqlDscServerPermission').Parameters['ServerRole'] + $parameterInfo.Attributes.Mandatory | Should -Contain $true + } + + It 'Should accept ServerRole from pipeline in ServerRole parameter set' { + $parameterInfo = (Get-Command -Name 'Get-SqlDscServerPermission').Parameters['ServerRole'] + $parameterInfo.Attributes.ValueFromPipeline | Should -Contain $true + } + } } diff --git a/tests/Unit/Public/Revoke-SqlDscServerPermission.Tests.ps1 b/tests/Unit/Public/Revoke-SqlDscServerPermission.Tests.ps1 index 181ecb2001..2ff90bfc24 100644 --- a/tests/Unit/Public/Revoke-SqlDscServerPermission.Tests.ps1 +++ b/tests/Unit/Public/Revoke-SqlDscServerPermission.Tests.ps1 @@ -104,8 +104,8 @@ Describe 'Revoke-SqlDscServerPermission' -Tag 'Public' { $mockServerObject = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Server' $mockServerObject.InstanceName = 'MockInstance' - $mockLogin = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Login' -ArgumentList $mockServerObject, 'TestUser' - $mockServerRole = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.ServerRole' -ArgumentList $mockServerObject, 'TestRole' + $script:mockLogin = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Login' -ArgumentList $mockServerObject, 'TestUser' + $script:mockServerRole = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.ServerRole' -ArgumentList $mockServerObject, 'TestRole' # Mock the Revoke method on the server object $mockServerObject | Add-Member -MemberType ScriptMethod -Name 'Revoke' -Value { @@ -115,27 +115,15 @@ Describe 'Revoke-SqlDscServerPermission' -Tag 'Public' { } It 'Should revoke permissions from a login' { - InModuleScope -Parameters @{ - mockLogin = $mockLogin - } -ScriptBlock { - $null = Revoke-SqlDscServerPermission -Login $mockLogin -Permission ConnectSql -Force - } + $null = Revoke-SqlDscServerPermission -Login $script:mockLogin -Permission 'ConnectSql' -Force } It 'Should revoke permissions from a server role' { - InModuleScope -Parameters @{ - mockServerRole = $mockServerRole - } -ScriptBlock { - $null = Revoke-SqlDscServerPermission -ServerRole $mockServerRole -Permission ConnectSql -Force - } + $null = Revoke-SqlDscServerPermission -ServerRole $script:mockServerRole -Permission 'ConnectSql' -Force } It 'Should handle WithGrant parameter correctly' { - InModuleScope -Parameters @{ - mockLogin = $mockLogin - } -ScriptBlock { - $null = Revoke-SqlDscServerPermission -Login $mockLogin -Permission ConnectSql -WithGrant -Force - } + $null = Revoke-SqlDscServerPermission -Login $script:mockLogin -Permission 'ConnectSql' -WithGrant -Force } } @@ -144,7 +132,7 @@ Describe 'Revoke-SqlDscServerPermission' -Tag 'Public' { $mockServerObject = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Server' $mockServerObject.InstanceName = 'MockInstance' - $mockLogin = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Login' -ArgumentList $mockServerObject, 'TestUser' + $script:mockLogin = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Login' -ArgumentList $mockServerObject, 'TestUser' # Mock the Revoke method to throw an error $mockServerObject | Add-Member -MemberType ScriptMethod -Name 'Revoke' -Value { @@ -154,12 +142,8 @@ Describe 'Revoke-SqlDscServerPermission' -Tag 'Public' { } It 'Should throw a descriptive error when operation fails' { - InModuleScope -Parameters @{ - mockLogin = $mockLogin - } -ScriptBlock { - { Revoke-SqlDscServerPermission -Login $mockLogin -Permission ConnectSql -Force } | - Should -Throw -ExpectedMessage '*Failed to revoke server permissions*' - } + { Revoke-SqlDscServerPermission -Login $script:mockLogin -Permission 'ConnectSql' -Force } | + Should -Throw -ExpectedMessage '*Failed to revoke server permissions*' } } @@ -168,8 +152,8 @@ Describe 'Revoke-SqlDscServerPermission' -Tag 'Public' { $mockServerObject = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Server' $mockServerObject.InstanceName = 'MockInstance' - $mockLogin = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Login' -ArgumentList $mockServerObject, 'TestUser' - $mockServerRole = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.ServerRole' -ArgumentList $mockServerObject, 'TestRole' + $script:mockLogin = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Login' -ArgumentList $mockServerObject, 'TestUser' + $script:mockServerRole = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.ServerRole' -ArgumentList $mockServerObject, 'TestRole' # Mock the Revoke method on the server object $mockServerObject | Add-Member -MemberType ScriptMethod -Name 'Revoke' -Value { @@ -179,19 +163,11 @@ Describe 'Revoke-SqlDscServerPermission' -Tag 'Public' { } It 'Should accept Login from pipeline' { - InModuleScope -Parameters @{ - mockLogin = $mockLogin - } -ScriptBlock { - $null = $mockLogin | Revoke-SqlDscServerPermission -Permission ConnectSql -Force - } + $null = $script:mockLogin | Revoke-SqlDscServerPermission -Permission 'ConnectSql' -Force } It 'Should accept ServerRole from pipeline' { - InModuleScope -Parameters @{ - mockServerRole = $mockServerRole - } -ScriptBlock { - $null = $mockServerRole | Revoke-SqlDscServerPermission -Permission ConnectSql -Force - } + $null = $script:mockServerRole | Revoke-SqlDscServerPermission -Permission 'ConnectSql' -Force } } }