Skip to content

Commit

Permalink
SqlServiceAccount: Updated Get-ServiceObject to find SSIS service (ds…
Browse files Browse the repository at this point in the history
…ccommunity#1246)

- Changes to SqlServiceAccount
  - Fixed Get-ServiceObject when searching for Integration Services service.
    Unlike the rest of SQL Server services, the Integration Services service
    cannot be instanced, however you can have multiple versions installed.
    Get-Service object would return the correct service name that you
    are looking for, but it appends the version number at the end. Added
    parameter VersionNumber so the search would return the correct
    service name.
  - Added code to allow for using Managed Service Accounts.
- Changes to SqlServerLogin
  - Fixed issue in Test-TargetResource to valid password on disabled accounts (issue dsccommunity#915).
  • Loading branch information
Shawn Sesna authored and johlju committed Jan 14, 2019
1 parent c78a95c commit e8e14af
Show file tree
Hide file tree
Showing 11 changed files with 465 additions and 44 deletions.
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,19 @@

## Unreleased

- Changes to SqlServiceAccount
- Fixed Get-ServiceObject when searching for Integration Services service.
Unlike the rest of SQL Server services, the Integration Services service
cannot be instanced, however you can have multiple versions installed.
Get-Service object would return the correct service name that you
are looking for, but it appends the version number at the end. Added
parameter VersionNumber so the search would return the correct
service name.
- Added code to allow for using Managed Service Accounts.
- Changes to SqlServerLogin
- Fixed issue in Test-TargetResource to valid password on disabled accounts.
([issue #915](https://github.com/PowerShell/SqlServerDsc/issues/915)).

## 12.2.0.0

- Changes to SqlServerDsc
Expand Down
38 changes: 36 additions & 2 deletions DSCResources/MSFT_SqlServerLogin/MSFT_SqlServerLogin.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -420,8 +420,42 @@ function Test-TargetResource
}
catch
{
New-VerboseMessage -Message "Password validation failed for the login '$Name'."
$testPassed = $false
# Check to see if the parameter of $Disabled is true
if ($Disabled)
{
<#
An exception occurred and $Disabled is true, we neeed
to check the error codes for expected error numbers.
Recursively search the Exception variable and inner
Exceptions for the specific numbers.
18470 - Username and password are correct, but
account is disabled.
18456 - Login failed for user.
#>
if ((Find-ExceptionByNumber -ExceptionToSearch $_.Exception -ErrorNumber 18470))
{
New-VerboseMessage -Message "Password valid, but '$Name' is disabled."
}
elseif ((Find-ExceptionByNumber -ExceptionToSearch $_.Exception -ErrorNumber 18456))
{
New-VerboseMessage -Message $_.Exception.message

# The password was not correct, password validation failed
$testPassed = $false
}
else
{
New-VerboseMessage -Message "Unknown error: $($_.Exception.message)"

# Something else went wrong, rethrow error
throw
}
}
else
{
New-VerboseMessage -Message "Password validation failed for the login '$Name'."
$testPassed = $false
}
}
}
}
Expand Down
66 changes: 57 additions & 9 deletions DSCResources/MSFT_SqlServiceAccount/MSFT_SqlServiceAccount.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,13 @@ $script:localizedData = Get-LocalizedData -ResourceName 'MSFT_SqlServiceAccount'
** Not used in this function **
Credential of the service account that should be used.
.PARAMETER VersionNumber
** Only used when specifying IntegrationServices **
Version number of IntegrationServices.
.EXAMPLE
Get-TargetResource -ServerName $env:COMPUTERNAME -InstanceName MSSQLSERVER -ServiceType DatabaseEngine -ServiceAccount $account
Get-TargetResource -ServerName $env:COMPUTERNAME -InstanceName MSSQLSERVER -ServiceType IntegrationServices -ServiceAccount $account -VersionNumber 130
#>
function Get-TargetResource
{
Expand All @@ -48,11 +53,15 @@ function Get-TargetResource

[Parameter(Mandatory = $true)]
[System.Management.Automation.PSCredential]
$ServiceAccount
$ServiceAccount,

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

# Get the SMO Service object instance
$serviceObject = Get-ServiceObject -ServerName $ServerName -InstanceName $InstanceName -ServiceType $ServiceType
$serviceObject = Get-ServiceObject -ServerName $ServerName -InstanceName $InstanceName -ServiceType $ServiceType -VersionNumber $VersionNumber

# If no service was found, throw an exception
if (-not $serviceObject)
Expand Down Expand Up @@ -98,8 +107,12 @@ function Get-TargetResource
.PARAMETER Force
Forces the service account to be updated.
.PARAMETER VersionNumber
Version number of IntegrationServices
.EXAMPLE
Test-TargetResource -ServerName $env:COMPUTERNAME -InstanceName MSSQLSERVER -ServiceType DatabaseEngine -ServiceAccount $account
Test-TargetResource -ServerName $env:COMPUTERNAME -InstanceName MSSQLSERVER -SerticeType IntegrationServices -ServiceAccount $account -VersionNumber 130
#>
function Test-TargetResource
Expand Down Expand Up @@ -131,7 +144,11 @@ function Test-TargetResource

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

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

if ($Force)
Expand All @@ -141,7 +158,7 @@ function Test-TargetResource
}

# Get the current state
$currentState = Get-TargetResource -ServerName $ServerName -InstanceName $InstanceName -ServiceType $ServiceType -ServiceAccount $ServiceAccount
$currentState = Get-TargetResource -ServerName $ServerName -InstanceName $InstanceName -ServiceType $ServiceType -ServiceAccount $ServiceAccount -VersionNumber $VersionNumber
New-VerboseMessage -Message ($script:localizedData.CurrentServiceAccount -f $currentState.ServiceAccountName, $ServerName, $InstanceName)

return ($currentState.ServiceAccountName -ieq $ServiceAccount.UserName)
Expand Down Expand Up @@ -171,6 +188,9 @@ function Test-TargetResource
.PARAMETER Force
Forces the service account to be updated.
.PARAMETER VersionNumber
Version number of IntegrationServices
.EXAMPLE
Set-TargetResource -ServerName $env:COMPUTERNAME -InstanceName MSSQLSERVER -ServiceType DatabaseEngine -ServiceAccount $account
#>
Expand Down Expand Up @@ -202,11 +222,15 @@ function Set-TargetResource

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

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

# Get the Service object
$serviceObject = Get-ServiceObject -ServerName $ServerName -InstanceName $InstanceName -ServiceType $ServiceType
$serviceObject = Get-ServiceObject -ServerName $ServerName -InstanceName $InstanceName -ServiceType $ServiceType -VersionNumber $VersionNumber

# If no service was found, throw an exception
if (-not $serviceObject)
Expand All @@ -218,7 +242,8 @@ function Set-TargetResource
try
{
New-VerboseMessage -Message ($script:localizedData.UpdatingServiceAccount -f $ServiceAccount.UserName, $serviceObject.Name)
$serviceObject.SetServiceAccount($ServiceAccount.UserName, $ServiceAccount.GetNetworkCredential().Password)
$account = Get-ServiceAccount -ServiceAccount $ServiceAccount
$serviceObject.SetServiceAccount($account.UserName, $account.Password)
}
catch
{
Expand Down Expand Up @@ -246,9 +271,13 @@ function Set-TargetResource
.PARAMETER ServiceType
Type of service to be managed. Must be one of the following:
DatabaseEngine, SQLServerAgent, Search, IntegrationServices, AnalysisServices, ReportingServices, SQLServerBrowser, NotificationServices.
.PARAMETER VersionNumber
Version number of IntegrationServices.
.EXAMPLE
Get-ServiceObject -ServerName $env:COMPUTERNAME -InstanceName MSSQLSERVER -ServiceType DatabaseEngine
Get-ServiceObject -ServerName $env:COMPUTERNAME -InstanceName MSSQLSERVER -ServiceType IntegrationServices -VersionNumber 130
#>
function Get-ServiceObject
{
Expand All @@ -266,9 +295,20 @@ function Get-ServiceObject
[Parameter(Mandatory = $true)]
[ValidateSet('DatabaseEngine', 'SQLServerAgent', 'Search', 'IntegrationServices', 'AnalysisServices', 'ReportingServices', 'SQLServerBrowser', 'NotificationServices')]
[System.String]
$ServiceType
$ServiceType,

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

# Check to see if Integration services was specified, but no version specified
if (($ServiceType -eq 'IntegrationServices') -and ([String]::IsNullOrEmpty($VersionNumber)))
{
$errorMessage = $script:localizedData.MissingParameter -f $ServiceType
New-InvalidArgumentException -Message $errorMessage -ArgumentName 'VersionNumber'
}

# Load the SMO libraries
Import-SQLPSModule

Expand All @@ -281,9 +321,16 @@ function Get-ServiceObject
# Get the service name for the specified instance and type
$serviceNameFilter = Get-SqlServiceName -InstanceName $InstanceName -ServiceType $ServiceType

# Check the service type and append version number if IntegrationServices
if ($ServiceType -eq 'IntegrationServices')
{
# Append version number
$serviceNameFilter = '{0}{1}' -f $serviceNameFilter, $VersionNumber
}

# Get the Service object for the specified instance/type
$serviceObject = $managedComputer.Services | Where-Object -FilterScript {
$_.Name -eq $serviceNameFilter
$_.Name -eq "$serviceNameFilter"
}

return $serviceObject
Expand Down Expand Up @@ -440,3 +487,4 @@ function Get-SqlServiceName
# Build the name of the service and return it
return ($returnValue -f $serviceNamingScheme, $InstanceName)
}

Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ class MSFT_SqlServiceAccount : OMI_BaseResource
[Write, Description("Determines whether the service is automatically restarted when a change to the configuration was needed.")] Boolean RestartService;
[Write, Description("Forces the service account to be updated. Useful for password changes.")] Boolean Force;
[Read, Description("Returns the service account username for the service.")] String ServiceAccountName;
[Write, Description("The version number for the service, mandatory with IntegrationServices ServiceType")] String VersionNumber;
};
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ ConvertFrom-StringData @'
SetServiceAccountFailed = Unable to set the service account for {0} on {1}. Message {2}
UnknownServiceType = Unknown or unsupported service type '{0}' specified!
NotInstanceAware = Service type '{0}' is not instance aware.
MissingParameter = Missing parameter detected for '{0}'!
'@
43 changes: 12 additions & 31 deletions DSCResources/MSFT_SqlSetup/MSFT_SqlSetup.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -2250,42 +2250,23 @@ function Get-ServiceAccountParameters
$ServiceType
)

# Get the service account properties
$accountParameters = Get-ServiceAccount -ServiceAccount $ServiceAccount
$parameters = @{}

switch -Regex ($ServiceAccount.UserName.ToUpper())
{
'^(?:NT ?AUTHORITY\\)?(SYSTEM|LOCALSERVICE|LOCAL SERVICE|NETWORKSERVICE|NETWORK SERVICE)$'
{
$parameters = @{
"$($ServiceType)SVCACCOUNT" = "NT AUTHORITY\$($Matches[1])"
}
}

'^(?:NT SERVICE\\)(.*)$'
{
$parameters = @{
"$($ServiceType)SVCACCOUNT" = "NT SERVICE\$($Matches[1])"
}
}

# Testing if account is a Managed Service Account, which ends with '$'.
'\$$'
{
$parameters = @{
"$($ServiceType)SVCACCOUNT" = $ServiceAccount.UserName
}
}
# Assign the service type the account
$parameters = @{
"$($ServiceType)SVCACCOUNT" = $accountParameters.UserName
}

# Normal local or domain service account.
default
{
$parameters = @{
"$($ServiceType)SVCACCOUNT" = $ServiceAccount.UserName
"$($ServiceType)SVCPASSWORD" = $ServiceAccount.GetNetworkCredential().Password
}
}
# Check to see if password is null
if (![string]::IsNullOrEmpty($accountParameters.Password))
{
# Add the password to the hashtable
$parameters.Add("$($ServiceType)SVCPASSWORD", $accountParameters.Password)
}


return $parameters
}

Expand Down
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1527,6 +1527,9 @@ Manage the service account for SQL Server services.
* **`[Boolean]` Force** (Write): Forces the service account to be updated.
Useful for password changes. This will cause `Set-TargetResource` to be run on
each consecutive run.
* **`[String]` VersionNumber** (Write): The version number of the SQL Server,
mandatory for when IntegrationServices is used as **ServiceType**.
Eg. 130 for SQL 2016.

#### Read-Only Properties from Get-TargetResource

Expand Down
Loading

0 comments on commit e8e14af

Please sign in to comment.