-
Notifications
You must be signed in to change notification settings - Fork 228
*-SqlDscServerPermission: Add commands SQL Server permission management
#2157
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
johlju
merged 30 commits into
main
from
copilot/fix-e806ea1d-2077-4c68-a272-f8dea52701f7
Sep 1, 2025
Merged
Changes from 4 commits
Commits
Show all changes
30 commits
Select commit
Hold shift + click to select a range
b41547f
Initial plan
Copilot 683ea11
Add core server permission commands and private functions
Copilot 6e04b2e
Add integration tests and update CHANGELOG for new server permission …
Copilot f4db6ab
Update server permission commands to use State parameter and ServerPe…
Copilot 4299b88
Merge branch 'main' into copilot/fix-e806ea1d-2077-4c68-a272-f8dea527…
johlju 167bac9
Restructure server permission commands based on feedback - rename com…
Copilot 24f4c67
Change Permission parameter to accept string array for easier usage
Copilot a1c5aab
Implement all requested improvements to server permission commands
Copilot 50e8487
Address feedback: update server permission commands to use Login/Serv…
Copilot 345461e
Clean up code
johlju aea4697
Fix blank line EOF
johlju 3dcc4a4
Change error handling to use PSCmdlet.ThrowTerminatingError in server…
Copilot f78e7d6
Merge branch 'main' into copilot/fix-e806ea1d-2077-4c68-a272-f8dea527…
johlju 3ec521e
Remove unused $principalObject variables from server permission commands
Copilot cb5e97a
Refactor SQL DSC Server Permission Tests
johlju 8a3dd4d
Update integration tests
johlju 2c337e3
Merge branch 'main' into copilot/fix-e806ea1d-2077-4c68-a272-f8dea527…
johlju a14e934
Remove integration tests for Get-SqlDscServerPermission
johlju 1edcd8f
Refactor permission handling in integration and unit tests to elimina…
johlju 7278bfe
Update CHANGELOG.md
johlju 5c9a575
Update tests/Integration/Commands/Deny-SqlDscServerPermission.Integra…
johlju 01d832a
Update tests/Integration/Commands/Deny-SqlDscServerPermission.Integra…
johlju eba49be
Remove unit test stub imports from server permission integration tests
Copilot bc3112f
Reorganize server permissions in SqlServerPermission enum for clarity…
johlju 8c1aaa3
Reorganize integration test commands by grouping and adding missing r…
johlju 546e22e
Refactor AfterAll block in Deny-SqlDscServerPermission integration te…
johlju a7ea287
Update Pester guidelines to consolidate requirements and best practic…
johlju 475290e
Refactor integration tests to remove default parameter values and add…
johlju 47586c2
Reorganize integration test commands to improve clarity and add missi…
johlju 360c066
Remove redundant module removal command from AfterAll blocks in integ…
johlju File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
132 changes: 132 additions & 0 deletions
132
source/Private/Invoke-SqlDscServerPermissionOperation.ps1
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,132 @@ | ||
| <# | ||
| .SYNOPSIS | ||
| Invokes a server permission operation on a SQL Server principal. | ||
|
|
||
| .DESCRIPTION | ||
| This private function encapsulates the core logic for granting, denying, | ||
| or revoking server permissions on a SQL Server principal. It validates | ||
| the principal exists and executes the specified permission operation. | ||
|
|
||
| .PARAMETER ServerObject | ||
| Specifies current server connection object. | ||
|
|
||
| .PARAMETER Name | ||
| Specifies the name of the principal for which the permissions are modified. | ||
|
|
||
| .PARAMETER Permission | ||
| Specifies the permissions. | ||
|
|
||
| .PARAMETER State | ||
| Specifies the state of the permission operation (Grant, Deny, Revoke). | ||
|
|
||
| .PARAMETER WithGrant | ||
| Specifies that the principal should also be granted the right to grant | ||
| other principals the same permission. This parameter is only valid when | ||
| parameter State is set to Grant or Revoke. | ||
|
|
||
| .OUTPUTS | ||
| None. | ||
| #> | ||
| function Invoke-SqlDscServerPermissionOperation | ||
| { | ||
| [CmdletBinding()] | ||
| [OutputType()] | ||
| param | ||
| ( | ||
| [Parameter(Mandatory = $true)] | ||
| [Microsoft.SqlServer.Management.Smo.Server] | ||
| $ServerObject, | ||
|
|
||
| [Parameter(Mandatory = $true)] | ||
| [System.String] | ||
| $Name, | ||
|
|
||
| [Parameter(Mandatory = $true)] | ||
| [Microsoft.SqlServer.Management.Smo.ServerPermissionSet] | ||
| $Permission, | ||
|
|
||
| [Parameter(Mandatory = $true)] | ||
| [ValidateSet('Grant', 'Deny', 'Revoke')] | ||
| [System.String] | ||
| $State, | ||
|
|
||
| [Parameter()] | ||
| [System.Management.Automation.SwitchParameter] | ||
| $WithGrant | ||
| ) | ||
|
|
||
| # Validate that the principal exists | ||
| $testSqlDscIsPrincipalParameters = @{ | ||
| ServerObject = $ServerObject | ||
| Name = $Name | ||
| } | ||
|
|
||
| $isLogin = Test-SqlDscIsLogin @testSqlDscIsPrincipalParameters | ||
| $isRole = Test-SqlDscIsRole @testSqlDscIsPrincipalParameters | ||
|
|
||
| if (-not ($isLogin -or $isRole)) | ||
| { | ||
| $missingPrincipalMessage = $script:localizedData.ServerPermission_MissingPrincipal -f $Name, $ServerObject.InstanceName | ||
|
|
||
| $PSCmdlet.ThrowTerminatingError( | ||
| [System.Management.Automation.ErrorRecord]::new( | ||
| $missingPrincipalMessage, | ||
| 'ISDSP0001', # cSpell: disable-line | ||
| [System.Management.Automation.ErrorCategory]::InvalidOperation, | ||
| $Name | ||
| ) | ||
| ) | ||
| } | ||
|
|
||
| # Get the permissions names that are set to $true in the ServerPermissionSet. | ||
| $permissionName = $Permission | | ||
| Get-Member -MemberType 'Property' | | ||
| Select-Object -ExpandProperty 'Name' | | ||
| Where-Object -FilterScript { | ||
| $Permission.$_ | ||
| } | ||
|
|
||
| switch ($State) | ||
| { | ||
| 'Grant' | ||
| { | ||
| Write-Verbose -Message ( | ||
| $script:localizedData.ServerPermission_GrantPermission -f ($permissionName -join ','), $Name | ||
| ) | ||
|
|
||
| if ($WithGrant.IsPresent) | ||
| { | ||
| $ServerObject.Grant($Permission, $Name, $true) | ||
| } | ||
| else | ||
| { | ||
| $ServerObject.Grant($Permission, $Name) | ||
| } | ||
| } | ||
|
|
||
| 'Deny' | ||
| { | ||
| Write-Verbose -Message ( | ||
| $script:localizedData.ServerPermission_DenyPermission -f ($permissionName -join ','), $Name | ||
| ) | ||
|
|
||
| $ServerObject.Deny($Permission, $Name) | ||
| } | ||
|
|
||
| 'Revoke' | ||
| { | ||
| Write-Verbose -Message ( | ||
| $script:localizedData.ServerPermission_RevokePermission -f ($permissionName -join ','), $Name | ||
| ) | ||
|
|
||
| if ($WithGrant.IsPresent) | ||
| { | ||
| $ServerObject.Revoke($Permission, $Name, $false, $true) | ||
| } | ||
| else | ||
| { | ||
| $ServerObject.Revoke($Permission, $Name) | ||
| } | ||
| } | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,152 @@ | ||
| <# | ||
| .SYNOPSIS | ||
| Tests if server permissions for a principal are in the desired state. | ||
|
|
||
| .DESCRIPTION | ||
| This private function tests if server permissions for a principal are | ||
| in the desired state by comparing current permissions with desired permissions. | ||
|
|
||
| .PARAMETER ServerObject | ||
| Specifies current server connection object. | ||
|
|
||
| .PARAMETER Name | ||
| Specifies the name of the principal to test. | ||
|
|
||
| .PARAMETER State | ||
| Specifies the desired state of the permission to be tested. | ||
|
|
||
| .PARAMETER Permission | ||
| Specifies the desired permissions as a ServerPermissionSet object. | ||
|
|
||
| .PARAMETER WithGrant | ||
| Specifies that the principal should have the right to grant other principals | ||
| the same permission. This parameter is only valid when parameter **State** is | ||
| set to 'Grant'. | ||
|
|
||
| .OUTPUTS | ||
| [System.Boolean] | ||
| #> | ||
| function Test-SqlDscServerPermissionState | ||
| { | ||
| [CmdletBinding()] | ||
| [OutputType([System.Boolean])] | ||
| param | ||
| ( | ||
| [Parameter(Mandatory = $true)] | ||
| [Microsoft.SqlServer.Management.Smo.Server] | ||
| $ServerObject, | ||
|
|
||
| [Parameter(Mandatory = $true)] | ||
| [System.String] | ||
| $Name, | ||
|
|
||
| [Parameter(Mandatory = $true)] | ||
| [ValidateSet('Grant', 'GrantWithGrant', 'Deny')] | ||
johlju marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| [System.String] | ||
| $State, | ||
|
|
||
| [Parameter(Mandatory = $true)] | ||
| [Microsoft.SqlServer.Management.Smo.ServerPermissionSet] | ||
| $Permission, | ||
|
|
||
| [Parameter()] | ||
| [System.Management.Automation.SwitchParameter] | ||
| $WithGrant | ||
| ) | ||
|
|
||
| Write-Verbose -Message ( | ||
| $script:localizedData.ServerPermission_TestingDesiredState -f $Name, $ServerObject.InstanceName | ||
| ) | ||
johlju marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| # Handle WithGrant parameter by adjusting the effective state | ||
| $effectiveState = $State | ||
| if ($WithGrant.IsPresent -and $State -eq 'Grant') | ||
| { | ||
| $effectiveState = 'GrantWithGrant' | ||
| } | ||
|
|
||
| # Get current permissions | ||
| $serverPermissionInfo = $ServerObject | | ||
| Get-SqlDscServerPermission -Name $Name -ErrorAction 'SilentlyContinue' | ||
|
|
||
| if (-not $serverPermissionInfo) | ||
| { | ||
| Write-Verbose -Message ( | ||
| $script:localizedData.ServerPermission_PermissionNotInDesiredState -f 'All', $effectiveState, $Name | ||
| ) | ||
johlju marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| return $false | ||
| } | ||
|
|
||
| # Convert current permissions to ServerPermission objects | ||
| $currentPermissions = $serverPermissionInfo | ConvertTo-SqlDscServerPermission | ||
|
|
||
| # Find the current permission for the desired state | ||
| $currentPermissionForState = $currentPermissions | | ||
| Where-Object -FilterScript { | ||
| $_.State -eq $effectiveState | ||
| } | ||
|
|
||
| if (-not $currentPermissionForState) | ||
| { | ||
| $currentPermissionForState = [ServerPermission] @{ | ||
| State = $effectiveState | ||
| Permission = @() | ||
| } | ||
| } | ||
|
|
||
| # Get the list of permission names that should be true in the permission set | ||
| $desiredPermissionNames = @() | ||
| $permissionProperties = $Permission | Get-Member -MemberType Property | Where-Object { $_.Name -ne 'IsEmpty' } | ||
|
|
||
| foreach ($property in $permissionProperties) | ||
| { | ||
| if ($Permission.$($property.Name) -eq $true) | ||
| { | ||
| $desiredPermissionNames += $property.Name | ||
| } | ||
| } | ||
|
|
||
| # Check if all desired permissions are present in current state | ||
| foreach ($desiredPermissionName in $desiredPermissionNames) | ||
| { | ||
| if ($desiredPermissionName -notin $currentPermissionForState.Permission) | ||
| { | ||
| Write-Verbose -Message ( | ||
| $script:localizedData.ServerPermission_PermissionNotInDesiredState -f $desiredPermissionName, $effectiveState, $Name | ||
| ) | ||
johlju marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| return $false | ||
| } | ||
| } | ||
|
|
||
| # Check if current state has permissions not in desired state (unless desired is empty) | ||
| if ($desiredPermissionNames.Count -gt 0) | ||
| { | ||
| foreach ($currentPermissionName in $currentPermissionForState.Permission) | ||
| { | ||
| if ($currentPermissionName -notin $desiredPermissionNames) | ||
| { | ||
| Write-Verbose -Message ( | ||
| $script:localizedData.ServerPermission_PermissionNotInDesiredState -f $currentPermissionName, $effectiveState, $Name | ||
| ) | ||
johlju marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| return $false | ||
| } | ||
| } | ||
| } | ||
| else | ||
| { | ||
| # If no permissions are desired, current should also be empty | ||
| if ($currentPermissionForState.Permission.Count -gt 0) | ||
| { | ||
| Write-Verbose -Message ( | ||
| $script:localizedData.ServerPermission_PermissionNotInDesiredState -f ($currentPermissionForState.Permission -join ', '), $effectiveState, $Name | ||
| ) | ||
johlju marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| return $false | ||
| } | ||
| } | ||
|
|
||
| Write-Verbose -Message ( | ||
| $script:localizedData.ServerPermission_InDesiredState -f $Name | ||
| ) | ||
|
|
||
johlju marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| return $true | ||
| } | ||
johlju marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@copilot We should move the relevant logic into the Deny-, Grant-, Revoke- commands instead, then remove this private function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've removed the private function
Invoke-SqlDscServerPermissionOperationand moved the relevant logic directly into the Grant-, Deny-, and Revoke- commands as requested. This makes the code clearer and removes unnecessary abstraction. Changes are in commit a1c5aab.