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

BREAKING CHANGE: SqlLogin: Parameters no longer enforce default values #1696

Merged
merged 10 commits into from
Mar 28, 2022
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Bumped Stale task to v5 in the GitHub workflow.
- Wiki
- add introduction and links to DSC technology
- SqlLogin
- BREAKING CHANGE: `LoginMustChangePassword`, `LoginPasswordExpirationEnabled` and `LoginPasswordPolicyEnforced`
parameters no longer enforce default values ([issue #1669](https://github.com/dsccommunity/SqlServerDsc/issues/1669)).

### Fixed

Expand Down
59 changes: 33 additions & 26 deletions source/DSCResources/DSC_SqlLogin/DSC_SqlLogin.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -107,13 +107,13 @@ function Get-TargetResource
The credential containing the password for a SQL Login. Only applies if the login type is SqlLogin.

.PARAMETER LoginMustChangePassword
Specifies if the login is required to have its password change on the next login. Only applies to SQL Logins. Does not update pre-existing SQL Logins. Default is $true.
Specifies if the login is required to have its password change on the next login. Only applies to SQL Logins. Does not update pre-existing SQL Logins.

.PARAMETER LoginPasswordExpirationEnabled
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.
Specifies if the login password is required to expire in accordance to the operating system security policy. Only applies to SQL Logins.

.PARAMETER LoginPasswordPolicyEnforced
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.
Specifies if the login password is required to conform to the password policy specified in the system security policy. Only applies to SQL Logins.

.PARAMETER Disabled
Specifies if the login is disabled. Default is $false.
Expand Down Expand Up @@ -163,15 +163,15 @@ function Set-TargetResource

[Parameter()]
[System.Boolean]
$LoginMustChangePassword = $true,
$LoginMustChangePassword,

[Parameter()]
[System.Boolean]
$LoginPasswordExpirationEnabled = $true,
$LoginPasswordExpirationEnabled,

[Parameter()]
[System.Boolean]
$LoginPasswordPolicyEnforced = $true,
$LoginPasswordPolicyEnforced,

[Parameter()]
[System.Boolean]
Expand All @@ -195,25 +195,33 @@ function Set-TargetResource
if ( $login.LoginType -eq 'SqlLogin' )
{
# There is no way to update 'MustChangePassword' on existing login so must explicitly throw exception to avoid this functionality being assumed
if ( $login.MustChangePassword -ne $LoginMustChangePassword )
if ( $PSBoundParameters.ContainsKey('LoginMustChangePassword') -and $login.MustChangePassword -ne $LoginMustChangePassword )
{
$errorMessage = $script:localizedData.MustChangePasswordCannotBeChanged
New-InvalidOperationException -Message $errorMessage
}

# `PasswordPolicyEnforced and `PasswordExpirationEnabled` must be updated together (if one or both are not in the desired state)
if ( $login.PasswordPolicyEnforced -ne $LoginPasswordPolicyEnforced -or
$login.PasswordExpirationEnabled -ne $LoginPasswordExpirationEnabled )
if ( ( $PSBoundParameters.ContainsKey('LoginPasswordPolicyEnforced') -and $login.PasswordPolicyEnforced -ne $LoginPasswordPolicyEnforced ) -or
( $PSBoundParameters.ContainsKey('LoginPasswordExpirationEnabled') -and $login.PasswordExpirationEnabled -ne $LoginPasswordExpirationEnabled ) )
{
Write-Verbose -Message (
$script:localizedData.SetPasswordPolicyEnforced -f $LoginPasswordPolicyEnforced, $Name, $ServerName, $InstanceName
)
Write-Verbose -Message (
$script:localizedData.SetPasswordExpirationEnabled -f $LoginPasswordExpirationEnabled, $Name, $ServerName, $InstanceName
)
if ( $PSBoundParameters.ContainsKey('LoginPasswordPolicyEnforced') )
{
Write-Verbose -Message (
$script:localizedData.SetPasswordPolicyEnforced -f $LoginPasswordPolicyEnforced, $Name, $ServerName, $InstanceName
)

$login.PasswordPolicyEnforced = $LoginPasswordPolicyEnforced
$login.PasswordExpirationEnabled = $LoginPasswordExpirationEnabled
$login.PasswordPolicyEnforced = $LoginPasswordPolicyEnforced
}

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

$login.PasswordExpirationEnabled = $LoginPasswordExpirationEnabled
}

Update-SQLServerLogin -Login $login
}
Expand Down Expand Up @@ -365,13 +373,13 @@ function Set-TargetResource
The credential containing the password for a SQL Login. Only applies if the login type is SqlLogin.

.PARAMETER LoginMustChangePassword
Specifies if the login is required to have its password change on the next login. Only applies to SQL Logins. Default is $true.
Specifies if the login is required to have its password change on the next login. Only applies to SQL Logins.

.PARAMETER LoginPasswordExpirationEnabled
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.
Specifies if the login password is required to expire in accordance to the operating system security policy. Only applies to SQL Logins.

.PARAMETER LoginPasswordPolicyEnforced
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.
Specifies if the login password is required to conform to the password policy specified in the system security policy. Only applies to SQL Logins.

.PARAMETER Disabled
Specifies if the login is disabled. Default is $false.
Expand Down Expand Up @@ -421,15 +429,15 @@ function Test-TargetResource

[Parameter()]
[System.Boolean]
$LoginMustChangePassword = $true,
$LoginMustChangePassword,

[Parameter()]
[System.Boolean]
$LoginPasswordExpirationEnabled = $true,
$LoginPasswordExpirationEnabled,

[Parameter()]
[System.Boolean]
$LoginPasswordPolicyEnforced = $true,
$LoginPasswordPolicyEnforced,

[Parameter()]
[System.Boolean]
Expand Down Expand Up @@ -504,7 +512,7 @@ function Test-TargetResource

if ( $LoginType -eq 'SqlLogin' )
{
if ( $LoginPasswordExpirationEnabled -ne $loginInfo.LoginPasswordExpirationEnabled )
if ( $PSBoundParameters.ContainsKey('LoginPasswordExpirationEnabled') -and $LoginPasswordExpirationEnabled -ne $loginInfo.LoginPasswordExpirationEnabled )
{
if ($LoginPasswordExpirationEnabled)
{
Expand All @@ -522,7 +530,7 @@ function Test-TargetResource
$testPassed = $false
}

if ( $LoginPasswordPolicyEnforced -ne $loginInfo.LoginPasswordPolicyEnforced )
if ( $PSBoundParameters.ContainsKey('LoginPasswordPolicyEnforced') -and $LoginPasswordPolicyEnforced -ne $loginInfo.LoginPasswordPolicyEnforced )
{
if ($LoginPasswordPolicyEnforced)
{
Expand Down Expand Up @@ -831,4 +839,3 @@ function Set-SQLServerLoginPassword
$ErrorActionPreference = $originalErrorActionPreference
}
}

6 changes: 3 additions & 3 deletions source/DSCResources/DSC_SqlLogin/DSC_SqlLogin.schema.mof
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ class DSC_SqlLogin : OMI_BaseResource
Values{"WindowsUser","WindowsGroup","SqlLogin","Certificate","AsymmetricKey","ExternalUser","ExternalGroup"}] String LoginType;
[Write, Description("The hostname of the _SQL Server_ to be configured. Default value is the current computer name.")] String ServerName;
[Write, EmbeddedInstance("MSFT_Credential"), Description("Specifies the password as a `[PSCredential]` object. Only applies to _SQL Logins_.")] String LoginCredential;
[Write, Description("Specifies if the login is required to have its password change on the next login. Only applies to _SQL Logins_. Default value is `$true`. This cannot be updated on a pre-existing _SQL Login_ and any attempt to do this will throw an exception.")] Boolean LoginMustChangePassword;
[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 value 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 value is `$true`.")] Boolean LoginPasswordPolicyEnforced;
[Write, Description("Specifies if the login is required to have its password change on the next login. Only applies to _SQL Logins_. This cannot be updated on a pre-existing _SQL Login_ and any attempt to do this will throw an exception.")] Boolean LoginMustChangePassword;
[Write, Description("Specifies if the login password is required to expire in accordance to the operating system security policy. Only applies to _SQL Logins_.")] 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_.")] Boolean LoginPasswordPolicyEnforced;
[Write, Description("Specifies if the login is disabled. Default value is `$false`.")] Boolean Disabled;
[Write, Description("Specifies the default database name.")] String DefaultDatabase;
};
155 changes: 155 additions & 0 deletions tests/Integration/DSC_SqlLogin.Integration.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -482,6 +482,161 @@ try

Wait-ForIdleLcm -Clear

$configurationName = "$($script:dscResourceName)_UpdateLoginDscUser4_Config_LoginPasswordExpirationEnabled"

Context ('When using configuration {0} (to update back to original password)' -f $configurationName) {
It 'Should re-compile and re-apply the MOF without throwing' {
{
$configurationParameters = @{
OutputPath = $TestDrive
# The variable $ConfigurationData was dot-sourced above.
ConfigurationData = $ConfigurationData
}

& $configurationName @configurationParameters

$startDscConfigurationParameters = @{
Path = $TestDrive
ComputerName = 'localhost'
Wait = $true
Verbose = $true
Force = $true
ErrorAction = 'Stop'
}

Start-DscConfiguration @startDscConfigurationParameters
} | Should -Not -Throw
}

It 'Should be able to call Get-DscConfiguration without throwing' {
{
$script:currentConfiguration = Get-DscConfiguration -Verbose -ErrorAction Stop
} | Should -Not -Throw
}

It 'Should have set the resource and all the parameters should match' {
$resourceCurrentState = $script:currentConfiguration | Where-Object -FilterScript {
$_.ConfigurationName -eq $configurationName `
-and $_.ResourceId -eq $resourceId
}

$resourceCurrentState.Ensure | Should -Be 'Present'
$resourceCurrentState.Name | Should -Be $ConfigurationData.AllNodes.DscUser4Name
$resourceCurrentState.LoginType | Should -Be $ConfigurationData.AllNodes.DscUser4Type
$resourceCurrentState.LoginPasswordExpirationEnabled | Should -BeTrue
$resourceCurrentState.LoginPasswordPolicyEnforced | Should -BeFalse
}

It 'Should return $true when Test-DscConfiguration is run' {
Test-DscConfiguration -Verbose | Should -Be 'True'
}
}

Wait-ForIdleLcm -Clear

# Reset LoginPasswordExpirationEnabled and LoginPasswordExpirationEnabled flags
$configurationName = "$($script:dscResourceName)_UpdateLoginDscUser4_Config"

Context ('When using configuration {0}' -f $configurationName) {
It 'Should compile and apply the MOF without throwing' {
{
$configurationParameters = @{
OutputPath = $TestDrive
# The variable $ConfigurationData was dot-sourced above.
ConfigurationData = $ConfigurationData
}

& $configurationName @configurationParameters

$startDscConfigurationParameters = @{
Path = $TestDrive
ComputerName = 'localhost'
Wait = $true
Verbose = $true
Force = $true
ErrorAction = 'Stop'
}

Start-DscConfiguration @startDscConfigurationParameters
} | Should -Not -Throw
}

It 'Should be able to call Get-DscConfiguration without throwing' {
{
$script:currentConfiguration = Get-DscConfiguration -Verbose -ErrorAction Stop
} | Should -Not -Throw
}

It 'Should have set the resource and all the parameters should match' {
$resourceCurrentState = $script:currentConfiguration | Where-Object -FilterScript {
$_.ConfigurationName -eq $configurationName `
-and $_.ResourceId -eq $resourceId
}

$resourceCurrentState.Ensure | Should -Be 'Present'
$resourceCurrentState.Name | Should -Be $ConfigurationData.AllNodes.DscUser4Name
$resourceCurrentState.LoginType | Should -Be $ConfigurationData.AllNodes.DscUser4Type
$resourceCurrentState.Disabled | Should -Be $false
$resourceCurrentState.LoginMustChangePassword | Should -Be $false # Left the same as this cannot be updated
$resourceCurrentState.LoginPasswordExpirationEnabled | Should -Be $false
$resourceCurrentState.LoginPasswordPolicyEnforced | Should -Be $false
}
}

Wait-ForIdleLcm -Clear

$configurationName = "$($script:dscResourceName)_UpdateLoginDscUser4_Config_LoginPasswordPolicyEnforced"

Context ('When using configuration {0} (to update back to original password)' -f $configurationName) {
It 'Should re-compile and re-apply the MOF without throwing' {
{
$configurationParameters = @{
OutputPath = $TestDrive
# The variable $ConfigurationData was dot-sourced above.
ConfigurationData = $ConfigurationData
}

& $configurationName @configurationParameters

$startDscConfigurationParameters = @{
Path = $TestDrive
ComputerName = 'localhost'
Wait = $true
Verbose = $true
Force = $true
ErrorAction = 'Stop'
}

Start-DscConfiguration @startDscConfigurationParameters
} | Should -Not -Throw
}

It 'Should be able to call Get-DscConfiguration without throwing' {
{
$script:currentConfiguration = Get-DscConfiguration -Verbose -ErrorAction Stop
} | Should -Not -Throw
}

It 'Should have set the resource and all the parameters should match' {
$resourceCurrentState = $script:currentConfiguration | Where-Object -FilterScript {
$_.ConfigurationName -eq $configurationName `
-and $_.ResourceId -eq $resourceId
}

$resourceCurrentState.Ensure | Should -Be 'Present'
$resourceCurrentState.Name | Should -Be $ConfigurationData.AllNodes.DscUser4Name
$resourceCurrentState.LoginType | Should -Be $ConfigurationData.AllNodes.DscUser4Type
$resourceCurrentState.LoginPasswordExpirationEnabled | Should -BeFalse
$resourceCurrentState.LoginPasswordPolicyEnforced | Should -BeTrue
}

It 'Should return $true when Test-DscConfiguration is run' {
Test-DscConfiguration -Verbose | Should -Be 'True'
}
}

Wait-ForIdleLcm -Clear

$configurationName = "$($script:dscResourceName)_AddLoginDscSqlUsers1_Config"

Context ('When using configuration {0}' -f $configurationName) {
Expand Down
54 changes: 54 additions & 0 deletions tests/Integration/DSC_SqlLogin.config.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,60 @@ Configuration DSC_SqlLogin_UpdateLoginDscUser4_Config
}
}

<#
.SYNOPSIS
Updates a SQL login, sets LoginPasswordExpirationEnabled to $true
#>
Configuration DSC_SqlLogin_UpdateLoginDscUser4_Config_LoginPasswordExpirationEnabled
{
Import-DscResource -ModuleName 'SqlServerDsc'

node $AllNodes.NodeName
{
SqlLogin 'Integration_Test'
{
Ensure = 'Present'
Name = $Node.DscUser4Name
LoginType = $Node.DscUser4Type
LoginPasswordExpirationEnabled = $true

ServerName = $Node.ServerName
InstanceName = $Node.InstanceName

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

<#
.SYNOPSIS
Updates a SQL login, sets LoginPasswordPolicyEnforced to $true
#>
Configuration DSC_SqlLogin_UpdateLoginDscUser4_Config_LoginPasswordPolicyEnforced
{
Import-DscResource -ModuleName 'SqlServerDsc'

node $AllNodes.NodeName
{
SqlLogin 'Integration_Test'
{
Ensure = 'Present'
Name = $Node.DscUser4Name
LoginType = $Node.DscUser4Type
LoginPasswordPolicyEnforced = $true

ServerName = $Node.ServerName
InstanceName = $Node.InstanceName

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

<#
.SYNOPSIS
Adds a Windows Group login.
Expand Down
Loading