Skip to content
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

SqlServerLogin: Set default database #1485

Merged
merged 10 commits into from
Apr 11, 2020
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ For older change log history see the [historic changelog](HISTORIC_CHANGELOG.md)

## [Unreleased]

### Added

- SqlServerLogin
- Added `DefaultDatabase` parameter ([issue #1474](https://github.com/dsccommunity/SqlServerDsc/issues/1474).)

### Changed

- SqlServerDsc
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1414,6 +1414,8 @@ No description.
policy. Only applies to SQL Logins. Default is $true.
* **`[Boolean]` Disabled** _(Write)_: Specifies if the login is disabled. Default
is $false.
* **`[String]` DefaultDatabase** _(Write)_: Default database name. If not specified,
default database is not changed.

#### Examples

Expand Down
53 changes: 45 additions & 8 deletions source/DSCResources/MSFT_SqlServerLogin/MSFT_SqlServerLogin.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -62,12 +62,13 @@ function Get-TargetResource
)

$returnValue = @{
Ensure = $ensure
Name = $Name
LoginType = $login.LoginType
ServerName = $ServerName
InstanceName = $InstanceName
Disabled = $login.IsDisabled
Ensure = $ensure
Name = $Name
LoginType = $login.LoginType
ServerName = $ServerName
InstanceName = $InstanceName
Disabled = $login.IsDisabled
DefaultDatabase = $login.DefaultDatabase
}

if ($login.LoginType -eq 'SqlLogin')
Expand Down Expand Up @@ -113,6 +114,9 @@ function Get-TargetResource

.PARAMETER Disabled
Specifies if the login is disabled. Default is $false.

.PARAMETER DefaultDatabase
Specifies the default database for the login.
#>
function Set-TargetResource
{
Expand Down Expand Up @@ -167,7 +171,11 @@ function Set-TargetResource

[Parameter()]
[System.Boolean]
$Disabled
$Disabled,

[Parameter()]
[System.String]
$DefaultDatabase
)

$serverObject = Connect-SQL -ServerName $ServerName -InstanceName $InstanceName
Expand Down Expand Up @@ -232,6 +240,12 @@ function Set-TargetResource
$login.Enable()
}
}

if ( $PSBoundParameters.ContainsKey('DefaultDatabase') -and ($login.DefaultDatabase -ne $DefaultDatabase) )
{
$login.DefaultDatabase = $DefaultDatabase
Update-SQLServerLogin -Login $login
}
}
else
{
Expand Down Expand Up @@ -295,6 +309,13 @@ function Set-TargetResource

$login.Disable()
}

# set the default database if specified
if ( $PSBoundParameters.ContainsKey('DefaultDatabase') )
{
$login.DefaultDatabase = $DefaultDatabase
Update-SQLServerLogin -Login $login
}
}
}

Expand Down Expand Up @@ -345,6 +366,9 @@ function Set-TargetResource

.PARAMETER Disabled
Specifies if the login is disabled. Default is $false.

.PARAMETER DefaultDatabase
Specifies the default database for the login.
#>
function Test-TargetResource
{
Expand Down Expand Up @@ -399,7 +423,11 @@ function Test-TargetResource

[Parameter()]
[System.Boolean]
$Disabled
$Disabled,

[Parameter()]
[System.String]
$DefaultDatabase
)

Write-Verbose -Message (
Expand Down Expand Up @@ -455,6 +483,15 @@ function Test-TargetResource
$testPassed = $false
}

if ( $PSBoundParameters.ContainsKey('DefaultDatabase') -and ($loginInfo.DefaultDatabase -ne $DefaultDatabase) )
{
Write-Verbose -Message (
$script:localizedData.WrongDefaultDatabase -f $Name, $loginInfo.DefaultDatabase, $DefaultDatabase
)

$testPassed = $false
}

if ( $LoginType -eq 'SqlLogin' )
{
if ( $LoginPasswordExpirationEnabled -ne $loginInfo.LoginPasswordExpirationEnabled )
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@ class MSFT_SqlServerLogin : OMI_BaseResource
[Write, Description("Specifies if the login password is required to expire in accordance to the operating system security policy. Only applies to SQL Logins. Default is $true.")] Boolean LoginPasswordExpirationEnabled;
[Write, Description("Specifies if the login password is required to conform to the password policy specified in the system security policy. Only applies to SQL Logins. Default is $true.")] Boolean LoginPasswordPolicyEnforced;
[Write, Description("Specifies if the login is disabled. Default is $false.")] Boolean Disabled;
[Write, Description("Default database name.")] String DefaultDatabase;
};
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ ConvertFrom-StringData @'
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.
WrongDefaultDatabase = The login '{0}' has the default database '{1}', but expected it to have the default database '{2}'.
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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ try
$resourceCurrentState.Ensure | Should -Be 'Present'
$resourceCurrentState.Name | Should -Be $ConfigurationData.AllNodes.DscUser2Name
$resourceCurrentState.LoginType | Should -Be $ConfigurationData.AllNodes.DscUser2Type
$resourceCurrentState.DefaultDatabase | Should -Be $ConfigurationData.AllNodes.DefaultDbName
$resourceCurrentState.Disabled | Should -Be $false
}

Expand Down
16 changes: 16 additions & 0 deletions tests/Integration/MSFT_SqlServerLogin.config.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ else
ServerName = $env:COMPUTERNAME
InstanceName = 'DSCSQLTEST'

DefaultDbName = 'DefaultDb'

DscUser1Name = ('{0}\{1}' -f $env:COMPUTERNAME, 'DscUser1')
DscUser1Type = 'WindowsUser'

Expand Down Expand Up @@ -52,6 +54,7 @@ else
Configuration MSFT_SqlServerLogin_CreateDependencies_Config
{
Import-DscResource -ModuleName 'PSDscResources' -ModuleVersion '2.12.0.0'
Import-DscResource -ModuleName 'SqlServerDsc'

node $AllNodes.NodeName
{
Expand Down Expand Up @@ -99,6 +102,18 @@ Configuration MSFT_SqlServerLogin_CreateDependencies_Config
'[User]CreateDscUser2'
)
}

SqlDatabase 'DefaultDb_Test'
{
Ensure = 'Present'
ServerName = $Node.ServerName
InstanceName = $Node.InstanceName
Name = $Node.DefaultDbName

PsDscRunAsCredential = New-Object `
-TypeName System.Management.Automation.PSCredential `
-ArgumentList @($Node.Admin_UserName, (ConvertTo-SecureString -String $Node.Admin_Password -AsPlainText -Force))
}
}
}

Expand Down Expand Up @@ -143,6 +158,7 @@ Configuration MSFT_SqlServerLogin_AddLoginDscUser2_Config
Ensure = 'Present'
Name = $Node.DscUser2Name
LoginType = $Node.DscUser2Type
DefaultDatabase = $Node.DefaultDbName

ServerName = $Node.ServerName
InstanceName = $Node.InstanceName
Expand Down
86 changes: 67 additions & 19 deletions tests/Unit/MSFT_SqlServerLogin.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -185,24 +185,28 @@ try
$script:mockWasLoginClassMethodEnableCalled = $false
$script:mockWasLoginClassMethodDisabledCalled = $false

$mockConnectSql = {
$mockConnectSQL = {
$windowsUser = New-Object -TypeName Microsoft.SqlServer.Management.Smo.Login -ArgumentList @('Server', 'Windows\User1')
$windowsUser.LoginType = 'WindowsUser'
$windowsUser = $windowsUser | Add-Member -Name 'Disable' -MemberType ScriptMethod -Value {
$script:mockWasLoginClassMethodDisabledCalled = $true
} -PassThru -Force
$windowsUser.DefaultDatabase = "master"

$windowsGroup = New-Object -TypeName Microsoft.SqlServer.Management.Smo.Login -ArgumentList ('Server', 'Windows\Group1')
$windowsGroup.LoginType = 'windowsGroup'
$windowsGroup.DefaultDatabase = "master"

$sqlLogin = New-Object -TypeName Microsoft.SqlServer.Management.Smo.Login -ArgumentList @('Server', 'SqlLogin1')
$sqlLogin.LoginType = 'SqlLogin'
$sqlLogin.MustChangePassword = $false
$sqlLogin.DefaultDatabase = "master"
$sqlLogin.PasswordPolicyEnforced = $true
$sqlLogin.PasswordExpirationEnabled = $true

$sqlLoginDisabled = New-Object -TypeName Microsoft.SqlServer.Management.Smo.Login -ArgumentList @('Server', 'Windows\UserDisabled')
$sqlLoginDisabled.LoginType = 'WindowsUser'
$sqlLoginDisabled.DefaultDatabase = "master"
$sqlLoginDisabled.IsDisabled = $true
$sqlLoginDisabled = $sqlLoginDisabled | Add-Member -Name 'Enable' -MemberType ScriptMethod -Value {
$script:mockWasLoginClassMethodEnableCalled = $true
Expand All @@ -228,12 +232,14 @@ try
'Windows\User1' = ( New-Object -TypeName Object |
Add-Member -MemberType NoteProperty -Name 'Name' -Value 'Windows\User1' -PassThru |
Add-Member -MemberType NoteProperty -Name 'LoginType' -Value 'WindowsUser' -PassThru |
Add-Member -MemberType NoteProperty -Name 'DefaultDatabase' -Value 'master' -PassThru |
Add-Member -MemberType ScriptMethod -Name Alter -Value {} -PassThru |
Add-Member -MemberType ScriptMethod -Name Drop -Value {} -PassThru -Force
)
'SqlLogin1' = ( New-Object -TypeName Object |
Add-Member -MemberType NoteProperty -Name 'Name' -Value 'SqlLogin1' -PassThru |
Add-Member -MemberType NoteProperty -Name 'LoginType' -Value 'SqlLogin' -PassThru |
Add-Member -MemberType NoteProperty -Name 'DefaultDatabase' -Value 'master' -PassThru |
Add-Member -MemberType NoteProperty -Name 'MustChangePassword' -Value $false -PassThru |
Add-Member -MemberType NoteProperty -Name 'PasswordExpirationEnabled' -Value $true -PassThru |
Add-Member -MemberType NoteProperty -Name 'PasswordPolicyEnforced' -Value $true -PassThru |
Expand All @@ -243,6 +249,7 @@ try
'Windows\Group1' = ( New-Object -TypeName Object |
Add-Member -MemberType NoteProperty -Name 'Name' -Value 'Windows\Group1' -PassThru |
Add-Member -MemberType NoteProperty -Name 'LoginType' -Value 'WindowsGroup' -PassThru |
Add-Member -MemberType NoteProperty -Name 'DefaultDatabase' -Value 'master' -PassThru |
Add-Member -MemberType ScriptMethod -Name Alter -Value {} -PassThru |
Add-Member -MemberType ScriptMethod -Name Drop -Value {} -PassThru -Force
)
Expand Down Expand Up @@ -284,6 +291,7 @@ try

$result.Ensure | Should -Be 'Present'
$result.LoginType | Should -Be 'SqlLogin'
$result.DefaultDatabase | Should -Not -BeNullOrEmpty
$result.LoginMustChangePassword | Should -Not -BeNullOrEmpty
$result.LoginPasswordExpirationEnabled | Should -Not -BeNullOrEmpty
$result.LoginPasswordPolicyEnforced | Should -Not -BeNullOrEmpty
Expand All @@ -296,6 +304,7 @@ try

$result.Ensure | Should -Be 'Present'
$result.LoginType | Should -Be 'WindowsUser'
$result.DefaultDatabase | Should -Not -BeNullOrEmpty
$result.LoginMustChangePassword | Should -BeNullOrEmpty
$result.LoginPasswordExpirationEnabled | Should -BeNullOrEmpty
$result.LoginPasswordPolicyEnforced | Should -BeNullOrEmpty
Expand All @@ -308,6 +317,7 @@ try

$result.Ensure | Should -Be 'Present'
$result.LoginType | Should -Be 'WindowsGroup'
$result.DefaultDatabase | Should -Not -BeNullOrEmpty
$result.LoginMustChangePassword | Should -BeNullOrEmpty
$result.LoginPasswordExpirationEnabled | Should -BeNullOrEmpty
$result.LoginPasswordPolicyEnforced | Should -BeNullOrEmpty
Expand All @@ -322,6 +332,7 @@ try

$result.Ensure | Should -Be 'Present'
$result.LoginType | Should -Be 'WindowsUser'
$result.DefaultDatabase | Should -Not -BeNullOrEmpty
$result.LoginMustChangePassword | Should -BeNullOrEmpty
$result.LoginPasswordExpirationEnabled | Should -BeNullOrEmpty
$result.LoginPasswordPolicyEnforced | Should -BeNullOrEmpty
Expand Down Expand Up @@ -426,12 +437,13 @@ try

# Override Get-TargetResource
Mock -CommandName Get-TargetResource {return New-Object PSObject -Property @{
Ensure = 'Present'
Name = $mockTestTargetResourceParameters.Name
LoginType = $mockTestTargetResourceParameters.LoginType
ServerName = 'Server1'
InstanceName = 'MSSQLERVER'
Disabled = $true
Ensure = 'Present'
Name = $mockTestTargetResourceParameters.Name
LoginType = $mockTestTargetResourceParameters.LoginType
ServerName = 'Server1'
InstanceName = 'MSSQLERVER'
Disabled = $true
DefaultDatabase = 'master'
LoginMustChangePassword = $false
LoginPasswordPolicyEnforced = $true
LoginPasswordExpirationEnabled = $true
Expand Down Expand Up @@ -460,12 +472,13 @@ try

# Override Get-TargetResource
Mock -CommandName Get-TargetResource {return New-Object PSObject -Property @{
Ensure = 'Present'
Name = $mockTestTargetResourceParameters.Name
LoginType = $mockTestTargetResourceParameters.LoginType
ServerName = 'Server1'
InstanceName = 'MSSQLERVER'
Disabled = $true
Ensure = 'Present'
Name = $mockTestTargetResourceParameters.Name
LoginType = $mockTestTargetResourceParameters.LoginType
ServerName = 'Server1'
InstanceName = 'MSSQLERVER'
Disabled = $true
DefaultDatabase = 'master'
LoginMustChangePassword = $false
LoginPasswordPolicyEnforced = $true
LoginPasswordExpirationEnabled = $true
Expand Down Expand Up @@ -494,12 +507,13 @@ try

# Override Get-TargetResource
Mock -CommandName Get-TargetResource {return New-Object PSObject -Property @{
Ensure = 'Present'
Name = $mockTestTargetResourceParameters.Name
LoginType = $mockTestTargetResourceParameters.LoginType
ServerName = 'Server1'
InstanceName = 'MSSQLERVER'
Disabled = $true
Ensure = 'Present'
Name = $mockTestTargetResourceParameters.Name
LoginType = $mockTestTargetResourceParameters.LoginType
ServerName = 'Server1'
InstanceName = 'MSSQLERVER'
Disabled = $true
DefaultDatabase = 'master'
LoginMustChangePassword = $false
LoginPasswordPolicyEnforced = $true
LoginPasswordExpirationEnabled = $true
Expand Down Expand Up @@ -603,6 +617,26 @@ try
Assert-MockCalled -CommandName Connect-SQL -Scope It -Times 1 -Exactly
}

It 'Should return $true when the specified SQL Login is Present and DefaultDatabase is "master"' {
$testTargetResource_SqlLoginPresentWithDefaultDatabaseMaster_EnsurePresent = $testTargetResource_SqlLoginPresentWithDefaultValues.Clone()
$testTargetResource_SqlLoginPresentWithDefaultDatabaseMaster_EnsurePresent.Add( 'Ensure', 'Present' )
$testTargetResource_SqlLoginPresentWithDefaultDatabaseMaster_EnsurePresent.Add( 'DefaultDatabase', 'master' )

( Test-TargetResource @testTargetResource_SqlLoginPresentWithDefaultDatabaseMaster_EnsurePresent ) | Should -Be $true

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

It 'Should return $false when the specified SQL Login is Present and DefaultDatabase is not "master"' {
$testTargetResource_SqlLoginPresentWithDefaultDatabaseNotMaster_EnsurePresent = $testTargetResource_SqlLoginPresentWithDefaultValues.Clone()
$testTargetResource_SqlLoginPresentWithDefaultDatabaseNotMaster_EnsurePresent.Add( 'Ensure', 'Present' )
$testTargetResource_SqlLoginPresentWithDefaultDatabaseNotMaster_EnsurePresent.Add( 'DefaultDatabase', 'notmaster' )

( Test-TargetResource @testTargetResource_SqlLoginPresentWithDefaultDatabaseNotMaster_EnsurePresent ) | Should -Be $false

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

It 'Should return $true when the specified SQL Login is Present and PasswordExpirationEnabled is $true' {
$testTargetResource_SqlLoginPresentWithPasswordExpirationEnabledTrue_EnsurePresent = $testTargetResource_SqlLoginPresentWithDefaultValues.Clone()
$testTargetResource_SqlLoginPresentWithPasswordExpirationEnabledTrue_EnsurePresent.Add( 'Ensure', 'Present' )
Expand Down Expand Up @@ -1029,6 +1063,20 @@ try
Assert-MockCalled -CommandName Set-SQLServerLoginPassword -Scope It -Times 1 -Exactly
}

It 'Should set DefaultDatabase on the specified SQL Login if it does not match the DefaultDatabase parameter' {
Mock -CommandName Connect-SQL -MockWith $mockConnectSQL -Verifiable

$setTargetResource_SqlLoginPresent_EnsurePresent_LoginDefaultDatabase = $setTargetResource_SqlLoginPresent.Clone()
$setTargetResource_SqlLoginPresent_EnsurePresent_LoginDefaultDatabase.Add( 'Ensure', 'Present' )
$setTargetResource_SqlLoginPresent_EnsurePresent_LoginDefaultDatabase.Add( 'LoginCredential', $mockSqlLoginCredential )
$setTargetResource_SqlLoginPresent_EnsurePresent_LoginDefaultDatabase.Add( 'DefaultDatabase', 'notmaster' )

Set-TargetResource @setTargetResource_SqlLoginPresent_EnsurePresent_LoginDefaultDatabase

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

It 'Should set PasswordExpirationEnabled on the specified SQL Login if it does not match the LoginPasswordExpirationEnabled parameter' {
Mock -CommandName Connect-SQL -MockWith $mockConnectSQL -Verifiable

Expand Down
Loading