Skip to content

Commit

Permalink
Changes to SqlServerLogin
Browse files Browse the repository at this point in the history
- Added en-US localization (issue dsccommunity#615).
- Added unit tests to improved code coverage.
  • Loading branch information
johlju committed Apr 25, 2019
1 parent fb32a5f commit 556142b
Show file tree
Hide file tree
Showing 7 changed files with 297 additions and 87 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@
coverage.
- Changes to SqlServerMaxDop
- Added en-US localization ([issue #616](https://github.com/PowerShell/SqlServerDsc/issues/616)).
- Changes to SqlServerLogin
- Added en-US localization ([issue #615](https://github.com/PowerShell/SqlServerDsc/issues/615)).
- Added unit tests to improved code coverage.

## 12.4.0.0

Expand Down
187 changes: 143 additions & 44 deletions DSCResources/MSFT_SqlServerLogin/MSFT_SqlServerLogin.psm1

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Localized resources for SqlSetup

ConvertFrom-StringData @'
GetLogin = Getting the login '{0}' from the instance '{1}\\{2}'.
LoginCurrentState = The login '{0}' is {1} at the instance '{2}\\{3}'.
SetPasswordExpirationEnabled = Setting password expiration enabled to '{0}' for the login '{1}' on the instance '{2}\\{3}'.
SetPasswordPolicyEnforced = Setting password policy enforced to '{0}' for the login '{1}' on the instance '{2}\\{3}'.
SetPassword = Setting the password for the login '{0}' on the instance '{1}\\{2}'.
SetDisabled = Disabling the the login '{0}' on the instance '{1}\\{2}'.
SetEnabled = Enabling the the login '{0}' on the instance '{1}\\{2}'.
LoginTypeNotImplemented = The login type '{0}' is not implemented in this resource.
LoginCredentialNotFound = To create the SQL login '{0}', the login credentials must also be provided.
CreateLogin = Creating the login '{0}', with the login type '{1}', on the instance '{2}\\{3}'.
IncorrectLoginMode = The instance '{0}\\{1}' is currently in '{2}' authentication mode. To create a SQL Login, it must be set to 'Mixed' authentication mode.
DropLogin = Removing the login '{0}' from the instance '{1}\\{2}'.
TestingConfiguration = Determines if the login '{0}' at the instance '{1}\\{2}' has the correct state.
WrongEnsureState = The login '{0}' is {1}, but expected it to be {2}.
WrongLoginType = The login '{0}' has the login type '{1}', but expected it to have the login type '{2}'.
ExpectedDisabled = Expected the login '{0}' to be disabled, but it is enabled.
ExpectedEnabled = Expected the login '{0}' to be enabled, but it is disabled.
ExpectedLoginPasswordExpirationDisabled = The login '{0}' has the password expiration enabled, but expected it to be disabled.
ExpectedLoginPasswordExpirationEnabled = The login '{0}' has the password expiration disabled, but expected it to be enabled.
ExpectedLoginPasswordPolicyEnforcedDisabled = The login '{0}' has the password policy enforced enabled, but expected it to be disabled.
ExpectedLoginPasswordPolicyEnforcedEnabled = The login '{0}' has the password policy enforced disabled, but expected it to be enabled.
PasswordValidButLoginDisabled = The password for the login '{0}' is valid, but the login is disabled.
PasswordValidationFailed = The password was not correct, password validation failed for the login '{0}'.
PasswordValidationFailedMessage = The returned error message was: {0}
PasswordValidationError = Password validation failed with an error.
AlterLoginFailed = Altering the login '{0}' failed.
CreateLoginFailedOnPassword = Creation of the login '{0}' failed due to a problem with the password.
CreateLoginFailed = Creation of the login '{0}' failed.
DropLoginFailed = Removal of the login '{0}' failed.
SetPasswordValidationFailed = Setting the password failed for the login '{0}' because of password validation error.
SetPasswordFailed = Setting the password failed for the login '{0}'.
'@
13 changes: 0 additions & 13 deletions Modules/DscResource.Common/en-US/DscResource.Common.strings.psd1
Original file line number Diff line number Diff line change
Expand Up @@ -103,19 +103,6 @@ ConvertFrom-StringData @'
AlterAlwaysOnServiceFailed = Failed to ensure Always On is {0} on the instance '{1}'.
UnexpectedAlwaysOnStatus = The status of property Server.IsHadrEnabled was neither $true or $false. Status is '{0}'.
# Login
PasswordValidationFailed = Creation of the login '{0}' failed due to the following error: {1}
LoginCreationFailedFailedOperation = Creation of the login '{0}' failed due to a failed operation.
LoginCreationFailedSqlNotSpecified = Creation of the SQL login '{0}' failed due to an unspecified error.
LoginCreationFailedWindowsNotSpecified = Creation of the Windows login '{0}' failed due to an unspecified error.
LoginTypeNotImplemented = The login type '{0}' is not implemented in this resource.
IncorrectLoginMode = The instance '{0}\{1}' is currently in '{2}' authentication mode. To create a SQL Login, it must be set to 'Mixed' authentication mode.
LoginCredentialNotFound = The credential for the SQL Login '{0}' was not found.
PasswordChangeFailed = Setting the password failed for the SQL Login '{0}'.
AlterLoginFailed = Altering the login '{0}' failed.
CreateLoginFailed = Creating the login '{0}' failed.
DropLoginFailed = Dropping the login '{0}' failed.
# AlwaysOnAvailabilityGroup
CreateAvailabilityGroupReplicaFailed = Creating the Availability Group Replica '{0}' failed on the instance '{1}'.
CreateAvailabilityGroupFailed = Creating the availability group '{0}'.
Expand Down
13 changes: 0 additions & 13 deletions Modules/DscResource.Common/sv-SE/DscResource.Common.strings.psd1
Original file line number Diff line number Diff line change
Expand Up @@ -96,19 +96,6 @@ ConvertFrom-StringData @'
AlterAlwaysOnServiceFailed = Failed to ensure Always On is {0} on the instance '{1}'.
UnexpectedAlwaysOnStatus = The status of property Server.IsHadrEnabled was neither $true or $false. Status is '{0}'.
# Login
PasswordValidationFailed = Creation of the login '{0}' failed due to the following error: {1}
LoginCreationFailedFailedOperation = Creation of the login '{0}' failed due to a failed operation.
LoginCreationFailedSqlNotSpecified = Creation of the SQL login '{0}' failed due to an unspecified error.
LoginCreationFailedWindowsNotSpecified = Creation of the Windows login '{0}' failed due to an unspecified error.
LoginTypeNotImplemented = The login type '{0}' is not implemented in this resource.
IncorrectLoginMode = The instance '{0}\{1}' is currently in '{2}' authentication mode. To create a SQL Login, it must be set to 'Mixed' authentication mode.
LoginCredentialNotFound = The credential for the SQL Login '{0}' was not found.
PasswordChangeFailed = Setting the password failed for the SQL Login '{0}'.
AlterLoginFailed = Altering the login '{0}' failed.
CreateLoginFailed = Creating the login '{0}' failed.
DropLoginFailed = Dropping the login '{0}' failed.
# AlwaysOnAvailabilityGroup
ClusterPermissionsMissing = The cluster does not have permissions to manage the Availability Group on '{0}\\{1}'. Grant 'Connect SQL', 'Alter Any Availability Group', and 'View Server State' to either 'NT SERVICE\\ClusSvc' or 'NT AUTHORITY\\SYSTEM'.
CreateAvailabilityGroupReplicaFailed = Creating the Availability Group Replica '{0}' failed on the instance '{1}'.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,62 @@ function New-InvalidResultException
throw $errorRecordToThrow
}

<#
.SYNOPSIS
Creates and throws an not implemented exception.
.PARAMETER Message
The message explaining why this error is being thrown.
.PARAMETER ErrorRecord
The error record containing the exception that is causing this terminating error.
'
.NOTES
The error categories can be found here:
https://docs.microsoft.com/en-us/dotnet/api/system.management.automation.errorcategory
#>
function New-NotImplementedException
{
[CmdletBinding()]
param
(
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[System.String]
$Message,

[Parameter()]
[ValidateNotNull()]
[System.Management.Automation.ErrorRecord]
$ErrorRecord
)

if ($null -eq $ErrorRecord)
{
$invalidOperationException = New-Object -TypeName 'NotImplementedException' `
-ArgumentList @($Message)
}
else
{
$invalidOperationException = New-Object -TypeName 'NotImplementedException' `
-ArgumentList @($Message, $ErrorRecord.Exception)
}

$newObjectParameters = @{
TypeName = 'System.Management.Automation.ErrorRecord'
ArgumentList = @(
$invalidOperationException.ToString(),
'MachineStateIncorrect',
'NotImplemented',
$null
)
}

$errorRecordToThrow = New-Object @newObjectParameters

throw $errorRecordToThrow
}

Export-ModuleMember -Function @(
'New-InvalidArgumentException',
'New-InvalidOperationException',
Expand Down
77 changes: 60 additions & 17 deletions Tests/Unit/MSFT_SqlServerLogin.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -487,7 +487,7 @@ try
$result | Should -Be $false
}

It 'Should throw exception when unkown error occurred and account is disabled' {
It 'Should throw exception when unknown error occurred and account is disabled' {
$mockTestTargetResourceParameters = $getTargetResource_KnownSqlLogin.Clone()
$mockTestTargetResourceParameters.Add('Ensure', 'Present')
$mockTestTargetResourceParameters.Add('Disabled', $true)
Expand All @@ -512,10 +512,11 @@ try
}

# Call the test target
{ Test-TargetResource @mockTestTargetResourceParameters } | Should -Throw
$errorMessage = $script:localizedData.PasswordValidationError
{ Test-TargetResource @mockTestTargetResourceParameters } | Should -Throw $errorMessage

Assert-MockCalled -CommandName Get-TargetResource -Scope It -Times 1 -Exactly
Assert-MockCAlled -CommandName Connect-SQL -Scope It -Times 1 -Exactly
Assert-MockCalled -CommandName Connect-SQL -Scope It -Times 1 -Exactly
}
}

Expand Down Expand Up @@ -692,6 +693,23 @@ try

Assert-MockCalled -CommandName Connect-SQL -Scope It -Times 1 -Exactly
}

It 'Should be return $false when a login has the wrong login type' {
$mockTestTargetResourceParameters = $instanceParameters.Clone()
$mockTestTargetResourceParameters.Add( 'Ensure', 'Present' )
<#
Use WindowsLogin format here to be able to test the
specific property LoginType.
#>
$mockTestTargetResourceParameters.Add( 'Name', 'Windows\UserDisabled' )
$mockTestTargetResourceParameters.Add( 'LoginType', 'SqlLogin' )
$mockTestTargetResourceParameters.Add( 'Disabled', $true )

$result = Test-TargetResource @mockTestTargetResourceParameters
$result | Should -Be $false

Assert-MockCalled -CommandName Connect-SQL -Scope It -Times 1 -Exactly
}
}
}

Expand Down Expand Up @@ -945,7 +963,8 @@ try
$setTargetResource_CertificateAbsent_EnsurePresent = $setTargetResource_CertificateAbsent.Clone()
$setTargetResource_CertificateAbsent_EnsurePresent.Add( 'Ensure', 'Present' )

{ Set-TargetResource @setTargetResource_CertificateAbsent_EnsurePresent } | Should -Throw 'LoginTypeNotImplemented'
$errorMessage = $script:localizedData.LoginTypeNotImplemented -f $setTargetResource_CertificateAbsent_EnsurePresent.LoginType
{ Set-TargetResource @setTargetResource_CertificateAbsent_EnsurePresent } | Should -Throw $errorMessage

Assert-MockCalled -CommandName Connect-SQL -Scope It -Times 1 -Exactly
Assert-MockCalled -CommandName Update-SQLServerLogin -Scope It -Times 0 -Exactly
Expand All @@ -960,7 +979,8 @@ try
$setTargetResource_SqlLoginAbsent_EnsurePresent_NoCred = $setTargetResource_SqlLoginAbsent.Clone()
$setTargetResource_SqlLoginAbsent_EnsurePresent_NoCred.Add( 'Ensure', 'Present' )

{ Set-TargetResource @setTargetResource_SqlLoginAbsent_EnsurePresent_NoCred } | Should -Throw 'LoginCredentialNotFound'
$errorMessage = $script:localizedData.LoginCredentialNotFound -f $setTargetResource_SqlLoginAbsent_EnsurePresent_NoCred.Name
{ Set-TargetResource @setTargetResource_SqlLoginAbsent_EnsurePresent_NoCred } | Should -Throw $errorMessage

Assert-MockCalled -CommandName Connect-SQL -Scope It -Times 1 -Exactly
Assert-MockCalled -CommandName Update-SQLServerLogin -Scope It -Times 0 -Exactly
Expand Down Expand Up @@ -1058,7 +1078,12 @@ try
$setTargetResource_SqlLoginAbsent_EnsurePresent.Add( 'Ensure', 'Present' )
$setTargetResource_SqlLoginAbsent_EnsurePresent.Add( 'LoginCredential', $mockSqlLoginCredential )

{ Set-TargetResource @setTargetResource_SqlLoginAbsent_EnsurePresent } | Should -Throw 'IncorrectLoginMode'
$errorMessage = $script:localizedData.IncorrectLoginMode -f
$setTargetResource_SqlLoginAbsent_EnsurePresent.ServerName,
$setTargetResource_SqlLoginAbsent_EnsurePresent.InstanceName,
$mockLoginMode

{ Set-TargetResource @setTargetResource_SqlLoginAbsent_EnsurePresent } | Should -Throw $errorMessage

Assert-MockCalled -CommandName Connect-SQL -Scope It -Times 1 -Exactly
Assert-MockCalled -CommandName Update-SQLServerLogin -Scope It -Times 0 -Exactly
Expand All @@ -1077,7 +1102,7 @@ try
$setTargetResource_SqlLoginAbsent_EnsurePresent.Add( 'Ensure', 'Present' )
$setTargetResource_SqlLoginAbsent_EnsurePresent.Add( 'LoginCredential', $mockSqlLoginCredential )

{ Set-TargetResource @setTargetResource_SqlLoginAbsent_EnsurePresent } | Should -Not -Throw 'IncorrectLoginMode'
{ Set-TargetResource @setTargetResource_SqlLoginAbsent_EnsurePresent } | Should -Not -Throw

Assert-MockCalled -CommandName Connect-SQL -Scope It -Times 1 -Exactly
Assert-MockCalled -CommandName Update-SQLServerLogin -Scope It -Times 0 -Exactly
Expand All @@ -1095,7 +1120,7 @@ try
$setTargetResource_SqlLoginAbsent_EnsurePresent.Add( 'Ensure', 'Present' )
$setTargetResource_SqlLoginAbsent_EnsurePresent.Add( 'LoginCredential', $mockSqlLoginCredential )

{ Set-TargetResource @setTargetResource_SqlLoginAbsent_EnsurePresent } | Should -Not -Throw 'IncorrectLoginMode'
{ Set-TargetResource @setTargetResource_SqlLoginAbsent_EnsurePresent } | Should -Not -Throw

Assert-MockCalled -CommandName Connect-SQL -Scope It -Times 1 -Exactly
Assert-MockCalled -CommandName Update-SQLServerLogin -Scope It -Times 0 -Exactly
Expand All @@ -1121,7 +1146,9 @@ try
$login.LoginType = 'WindowsUser'
$login.MockLoginType = 'SqlLogin'

{ Update-SQLServerLogin -Login $login } | Should -Throw 'AlterLoginFailed'
$errorMessage = $script:localizedData.AlterLoginFailed -f $login.Name

{ Update-SQLServerLogin -Login $login } | Should -Throw $errorMessage
}
}
}
Expand Down Expand Up @@ -1157,7 +1184,9 @@ try
$login.LoginType = 'WindowsUser'
$login.MockLoginType = 'SqlLogin'

{ New-SQLServerLogin -Login $login } | Should -Throw 'LoginCreationFailedWindowsNotSpecified'
$errorMessage = $script:localizedData.CreateLoginFailed -f $login.Name

{ New-SQLServerLogin -Login $login } | Should -Throw $errorMessage
}

It 'Should throw the correct error when password validation fails when creating a SQL Login' {
Expand All @@ -1170,7 +1199,9 @@ try
LoginCreateOptions = 'None'
}

{ New-SQLServerLogin @createLoginParameters } | Should -Throw 'PasswordValidationFailed'
$errorMessage = $script:localizedData.CreateLoginFailedOnPassword -f $login.Name

{ New-SQLServerLogin @createLoginParameters } | Should -Throw $errorMessage
}

It 'Should throw the correct error when creating a SQL Login fails' {
Expand All @@ -1183,7 +1214,9 @@ try
LoginCreateOptions = 'None'
}

{ New-SQLServerLogin @createLoginParameters } | Should -Throw 'LoginCreationFailedFailedOperation'
$errorMessage = $script:localizedData.CreateLoginFailed -f $login.Name

{ New-SQLServerLogin @createLoginParameters } | Should -Throw $errorMessage
}

It 'Should throw the correct error when creating a SQL Login fails with an unhandled exception' {
Expand All @@ -1196,7 +1229,9 @@ try
LoginCreateOptions = 'None'
}

{ New-SQLServerLogin @createLoginParameters } | Should -Throw 'LoginCreationFailedSqlNotSpecified'
$errorMessage = $script:localizedData.CreateLoginFailed -f $login.Name

{ New-SQLServerLogin @createLoginParameters } | Should -Throw $errorMessage
}
}
}
Expand All @@ -1217,7 +1252,9 @@ try
$login.LoginType = 'WindowsUser'
$login.MockLoginType = 'SqlLogin'

{ Remove-SQLServerLogin -Login $login } | Should -Throw 'DropLoginFailed'
$errorMessage = $script:localizedData.DropLoginFailed -f $login.Name

{ Remove-SQLServerLogin -Login $login } | Should -Throw $errorMessage
}
}
}
Expand All @@ -1241,7 +1278,9 @@ try
SecureString = ConvertTo-SecureString -String 'pw' -AsPlainText -Force
}

{ Set-SQLServerLoginPassword @setPasswordParameters } | Should -Throw 'PasswordValidationFailed'
$errorMessage = $script:localizedData.SetPasswordValidationFailed -f $setPasswordParameters.Login.Name

{ Set-SQLServerLoginPassword @setPasswordParameters } | Should -Throw $errorMessage
}

It 'Should throw the correct error when changing the password fails' {
Expand All @@ -1250,7 +1289,9 @@ try
SecureString = ConvertTo-SecureString -String 'reused' -AsPlainText -Force
}

{ Set-SQLServerLoginPassword @setPasswordParameters } | Should -Throw 'PasswordChangeFailed'
$errorMessage = $script:localizedData.SetPasswordFailed -f $setPasswordParameters.Login.Name

{ Set-SQLServerLoginPassword @setPasswordParameters } | Should -Throw $errorMessage
}

It 'Should throw the correct error when changing the password fails' {
Expand All @@ -1259,7 +1300,9 @@ try
SecureString = ConvertTo-SecureString -String 'other' -AsPlainText -Force
}

{ Set-SQLServerLoginPassword @setPasswordParameters } | Should -Throw 'PasswordChangeFailed'
$errorMessage = $script:localizedData.SetPasswordFailed -f $setPasswordParameters.Login.Name

{ Set-SQLServerLoginPassword @setPasswordParameters } | Should -Throw $errorMessage
}
}
}
Expand Down

0 comments on commit 556142b

Please sign in to comment.