Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
ea52565
`Get-SqlDscLogin`: function to retrieve SQL Server logins
johlju Aug 14, 2025
e382411
Force import of SqlServerDsc module in test setup
johlju Aug 14, 2025
66a4d34
Remove unnecessary stub cmdlet loading and cleanup from Get-SqlDscLog…
johlju Aug 15, 2025
15d6926
Fix connection
johlju Aug 15, 2025
b713731
Rename error message for missing login in Get-SqlDscLogin to improve …
johlju Aug 15, 2025
ccd0a7f
Remove reference to passing **LoginObject** in Get-SqlDscLogin docume…
johlju Aug 15, 2025
8f3d576
Remove unnecessary suppression of PSUseOutputTypeCorrectly warning in…
johlju Aug 15, 2025
da84289
Fix array access syntax in Get-SqlDscLogin integration tests for type…
johlju Aug 15, 2025
a21c6d2
Fix expected error message format in Get-SqlDscLogin integration test…
johlju Aug 15, 2025
452005a
Fix array count comparison in Get-SqlDscLogin integration tests to en…
johlju Aug 15, 2025
12614f0
Refactor Get-SqlDscLogin integration tests to use script-scoped varia…
johlju Aug 15, 2025
4519969
Update documentation for Get-SqlDscLogin to clarify output types and …
johlju Aug 16, 2025
45a8000
Fix comments for clarity and consistency in Get-SqlDscLogin integrati…
johlju Aug 16, 2025
33dc0e2
Fix comments for clarity and correct grammatical errors in Get-SqlDsc…
johlju Aug 16, 2025
72d1c69
Change error category from 'InvalidOperation' to 'ObjectNotFound' in …
johlju Aug 16, 2025
1c03af1
Add tests for parameter metadata in Get-SqlDscLogin function
johlju Aug 16, 2025
22e3e7a
Update source/Public/Get-SqlDscLogin.ps1
johlju Aug 16, 2025
7606c11
Update source/Public/Get-SqlDscLogin.ps1
johlju Aug 16, 2025
3b68e4d
Update source/Public/Get-SqlDscLogin.ps1
johlju Aug 16, 2025
7c31fd9
Update source/Public/Get-SqlDscLogin.ps1
johlju Aug 16, 2025
7bad8de
Add verbose logging for login retrieval in Get-SqlDscLogin function
johlju Aug 16, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
exists as a login, throwing a terminating error if it doesn't exist.
- Supports pipeline input and provides detailed error messages with localization.
- Uses `Test-SqlDscIsLogin` command for login validation following module patterns.
- `Get-SqlDscLogin`
- Added new public command to get a SQL Server login from a Database Engine instance.
- Returns a `Microsoft.SqlServer.Management.Smo.Login` object that represents
the login.
- Supports getting a specific login by name or all logins if no name is specified.
- Includes a `-Refresh` parameter to refresh the server's login collection
before retrieval.

### Changed

Expand Down
1 change: 1 addition & 0 deletions azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,7 @@ stages:
'tests/Integration/Commands/Connect-SqlDscDatabaseEngine.Integration.Tests.ps1'
# Group 2
'tests/Integration/Commands/Assert-SqlDscLogin.Integration.Tests.ps1'
'tests/Integration/Commands/Get-SqlDscLogin.Integration.Tests.ps1'
# Group 9
'tests/Integration/Commands/Uninstall-SqlDscServer.Integration.Tests.ps1'
)
Expand Down
101 changes: 101 additions & 0 deletions source/Public/Get-SqlDscLogin.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
<#
.SYNOPSIS
Gets SQL Server logins.

.DESCRIPTION
Retrieves login objects from a SQL Server Database Engine instance. Specify -Name
to return a specific login, or omit -Name to return all logins. Use -Refresh to
refresh the login collection before retrieval.

.PARAMETER ServerObject
Specifies the current server connection object.
.PARAMETER Name
Specifies the name of the server login to get.

.PARAMETER Refresh
Specifies that the **ServerObject** logins should be refreshed before
trying to get the login object. This is helpful when logins might have
been modified outside of the **ServerObject**, for example through T-SQL.
On instances with a large number of logins, consider ensuring the
**ServerObject** is recent enough.

.EXAMPLE
$serverObject = Connect-SqlDscDatabaseEngine -InstanceName 'MyInstance'
$serverObject | Get-SqlDscLogin -Name 'MyLogin'

Get the login named **MyLogin**.

.OUTPUTS
`[Microsoft.SqlServer.Management.Smo.Login]`

Returns a single Login object when the Name parameter is specified and a
match is found.

.OUTPUTS
`[Microsoft.SqlServer.Management.Smo.Login[]]`

Returns an array of Login objects when the Name parameter is not specified
(returns all logins) or when multiple matches are found.
#>
Comment thread
johlju marked this conversation as resolved.
Comment thread
johlju marked this conversation as resolved.
function Get-SqlDscLogin
{
[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.')]
[OutputType([Microsoft.SqlServer.Management.Smo.Login[]])]
[CmdletBinding()]
param
(
[Parameter(Mandatory = $true, ValueFromPipeline = $true)]
[Microsoft.SqlServer.Management.Smo.Server]
$ServerObject,

[Parameter()]
[System.String]
$Name,

[Parameter()]
[System.Management.Automation.SwitchParameter]
$Refresh
)

process
{
if ($Refresh.IsPresent)
{
Write-Verbose -Message ($script:localizedData.Login_Get_RefreshingLogins -f $ServerObject.InstanceName)

# Make sure the logins are up-to-date to get any newly created logins.
$ServerObject.Logins.Refresh()
}

$loginObject = @()

if ($PSBoundParameters.ContainsKey('Name'))
{
Write-Verbose -Message ($script:localizedData.Login_Get_RetrievingByName -f $Name, $ServerObject.InstanceName)

$loginObject = $ServerObject.Logins[$Name]

if (-not $loginObject)
{
$missingLoginMessage = $script:localizedData.Login_Get_Missing -f $Name

$writeErrorParameters = @{
Message = $missingLoginMessage
Category = 'ObjectNotFound'
ErrorId = 'GSDL0001' # cspell: disable-line
TargetObject = $Name
}

Write-Error @writeErrorParameters
}
}
else
{
Write-Verbose -Message ($script:localizedData.Login_Get_ReturningAllLogins -f $ServerObject.InstanceName)

$loginObject = $ServerObject.Logins
}

return [Microsoft.SqlServer.Management.Smo.Login[]] $loginObject
}
}
6 changes: 6 additions & 0 deletions source/en-US/SqlServerDsc.strings.psd1
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,12 @@ ConvertFrom-StringData @'
## Get-SqlDscAudit
Audit_Missing = There is no audit with the name '{0}'.

## Get-SqlDscLogin
Login_Get_Missing = There is no login with the name '{0}'.
Login_Get_RefreshingLogins = Refreshing logins on server '{0}'.
Login_Get_RetrievingByName = Retrieving login by name '{0}' from server '{1}'.
Login_Get_ReturningAllLogins = Returning all logins from server '{0}'.

## Remove-SqlDscAudit
Audit_Remove_ShouldProcessVerboseDescription = Removing the audit '{0}' on the instance '{1}'.
Audit_Remove_ShouldProcessVerboseWarning = Are you sure you want to remove the audit '{0}'?
Expand Down
111 changes: 111 additions & 0 deletions tests/Integration/Commands/Get-SqlDscLogin.Integration.Tests.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
[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:dscModuleName = 'SqlServerDsc'

Import-Module -Name $script:dscModuleName
}

Describe 'Get-SqlDscLogin' -Tag @('Integration_SQL2016', 'Integration_SQL2017', 'Integration_SQL2019', 'Integration_SQL2022') {
BeforeAll {
# Starting the named instance SQL Server service prior to running tests.
Start-Service -Name 'MSSQL$DSCSQLTEST' -Verbose -ErrorAction 'Stop'

$script:mockInstanceName = 'DSCSQLTEST'
$script:mockComputerName = Get-ComputerName

$mockSqlAdministratorUserName = 'SqlAdmin' # Using computer name as NetBIOS name throw exception.
Comment thread
johlju marked this conversation as resolved.
$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 {
# Stop the named instance SQL Server service to save memory on the build worker.
Stop-Service -Name 'MSSQL$DSCSQLTEST' -Verbose -ErrorAction 'Stop'
}


Context 'When getting all SQL Server logins' {
It 'Should return an array of Login objects' {
$result = Get-SqlDscLogin -ServerObject $script:serverObject

<#
Casting to array to ensure we get the count on Windows PowerShell
when there is only one login.
#>
@($result).Count | Should -BeGreaterOrEqual 1
@($result)[0] | Should -BeOfType 'Microsoft.SqlServer.Management.Smo.Login'
}

It 'Should return system logins including sa' {
$result = Get-SqlDscLogin -ServerObject $script:serverObject

$result.Name | Should -Contain 'sa'
}
}

Context 'When getting a specific SQL Server login' {
It 'Should return the specified login when it exists' {
$result = Get-SqlDscLogin -ServerObject $script:serverObject -Name 'sa'

$result | Should -BeOfType 'Microsoft.SqlServer.Management.Smo.Login'
$result.Name | Should -Be 'sa'
$result.LoginType | Should -Be 'SqlLogin'
}

It 'Should throw an error when the login does not exist' {
{ Get-SqlDscLogin -ServerObject $script:serverObject -Name 'NonExistentLogin' -ErrorAction 'Stop' } |
Should -Throw -ExpectedMessage 'There is no login with the name ''NonExistentLogin''.'
}

It 'Should return null when the login does not exist and error action is SilentlyContinue' {
$result = Get-SqlDscLogin -ServerObject $script:serverObject -Name 'NonExistentLogin' -ErrorAction 'SilentlyContinue'

$result | Should -BeNullOrEmpty
}
}

Context 'When using the Refresh parameter' {
It 'Should return the same results with and without Refresh' {
$resultWithoutRefresh = Get-SqlDscLogin -ServerObject $script:serverObject
$resultWithRefresh = Get-SqlDscLogin -ServerObject $script:serverObject -Refresh

@($resultWithoutRefresh).Count | Should -Be @($resultWithRefresh).Count
}
}

Context 'When using pipeline input' {
It 'Should accept ServerObject from pipeline' {
$result = $script:serverObject | Get-SqlDscLogin -Name 'sa'

$result | Should -BeOfType 'Microsoft.SqlServer.Management.Smo.Login'
$result.Name | Should -Be 'sa'
}
}
}
Loading
Loading