tasks/SqlTasks.ps1
Function Invoke-SetSqlMixedModeTask { <# .SYNOPSIS Enables a SQL Server Authentication. .DESCRIPTION The Invoke-SetSqlMixedModeTask is registered as SetSqlMixedMode task. .EXAMPLE Json task configuration for Sitecore Install Framework: "SetDbMixedMode": { "Type": "SetSqlMixedMode", "Params": { "SQLServerName": "[parameter('SqlServerName')]", "UserName": "[parameter('SqlUser')]", "Password": "[parameter('SqlPassword')]" } } #> [CmdletBinding(SupportsShouldProcess=$true)] param( [Parameter(Mandatory=$true)] [string]$SQLServerName, [string]$UserName, [string]$Password ) #region "Get MSSQL server instance" $sqlServerSmo = Get-SqlServerSmo -SQLServerName $SQLServerName if( $sqlServerSmo -eq $null ) { Write-Error "Cannot find MSSQL server $SQLServerName" return; } #endregion if( -not ([string]::IsNullOrEmpty($UserName))) { Write-Verbose "Connect with MSSQL Authentication: ($UserName)" $sqlServerSmo.ConnectionContext.LoginSecure = $false $sqlServerSmo.ConnectionContext.Login = $UserName $sqlServerSmo.ConnectionContext.Password = $Password } else { Write-Verbose "Connect with Windows Authentication" $sqlServerSmo.ConnectionContext.LoginSecure = $true } [string]$nm = $sqlServerSmo.Name [string]$mode = $sqlServerSmo.Settings.LoginMode Write-Verbose "Instance Name: $nm, login mode $mode" if($pscmdlet.ShouldProcess($SQLServerName, "Set server login mode ($mode) to mixed")) { if( $mode -ne "Mixed" ) { #Change to Mixed Mode $sqlServerSmo.Settings.LoginMode = [Microsoft.SqlServer.Management.SMO.ServerLoginMode]::Mixed # Make the changes $sqlServerSmo.Alter() } } if($pscmdlet.ShouldProcess($SQLServerName, "Restart")) { $service = Get-Service mssqlserver -ErrorAction SilentlyContinue if( $service -ne $null ) { Restart-Service -Force "MSSQLSERVER" } $service = Get-Service SQLEXPRESS -ErrorAction SilentlyContinue if( $service -ne $null ) { Restart-Service -Force "SQLEXPRESS" } } } <# .SYNOPSIS Creates a login account on the instance of SQL Server .DESCRIPTION The Invoke-CreateDbUserTask is registered as CreateDbUser task. .EXAMPLE Json task configuration for Sitecore Install Framework: "CreateDatabaseUser": { "Type": "CreateDbUser", "Params": { "SQLServerName": "[parameter('SqlServerName')]", "UserName": "[parameter('SqlUser')]", "Password": "[parameter('SqlPassword')]" } } #> function Invoke-CreateSqlUserTask { [CmdletBinding(SupportsShouldProcess=$true)] param( [Parameter(Mandatory=$true)] [string]$SQLServerName, [Parameter(Mandatory=$true)] [string]$UserName, [Parameter(Mandatory=$true)] [string]$Password ) Write-Information -Message "Create user $UserName on server $SQLServerName" -Tag 'MSSQL' $sqlServerSmo = Get-SqlServerSmo -SQLServerName $SQLServerName if( $sqlServerSmo -eq $null ) { Write-Error "Cannot find MSSQL server $SQLServerName" return; } if( $UserName -eq "sa" ) { Write-Warning "Skipping 'sa' user creation" return; } if($pscmdlet.ShouldProcess($SQLServerName, "Create user $UserName with sysadmin role")) { $login = $sqlServerSmo.Logins[$UserName] if($login -eq $null) { $login = new-object Microsoft.SqlServer.Management.Smo.Login($sqlServerSmo.Name, $UserName) $login.LoginType = 'SqlLogin' $login.PasswordPolicyEnforced = $false $login.PasswordExpirationEnabled = $false $login.Create($Password) $login.AddToRole('sysadmin') } else { $login.AddToRole('sysadmin') Write-Warning "User exist: $UserName ..." } } } function Invoke-DeleteSqlUserTask { [CmdletBinding(SupportsShouldProcess=$true)] param( [Parameter(Mandatory=$true)] [string]$SQLServerName, [Parameter(Mandatory=$true)] [string]$UserName ) Write-Information -Message "Delete user $UserName on server $SQLServerName" -Tag 'MSSQL' $sqlServerSmo = Get-SqlServerSmo -SQLServerName $SQLServerName if( $sqlServerSmo -eq $null ) { Write-Error "Cannot find MSSQL server $SQLServerName" return; } if($pscmdlet.ShouldProcess($SQLServerName, "Delete user $UserName")) { $login = $sqlServerSmo.Logins[$UserName] if($login -eq $null) { Write-Warning "User $UserName not exist" } else { $login.DropIfExists() } } } <# .SYNOPSIS Add a roles to the database user .DESCRIPTION The Invoke-SqlSetDatabaseRolesTask function adds a roles to the specified database or databases. The Invoke-SqlSetDatabaseRolesTask is registered as SetDatabaseRoles task. .EXAMPLE Json task configuration for Sitecore Install Framework: "AddRolesForDatabases": { "Type": "SetDatabaseRoles", "Params": { "SQLServerName": "[parameter('SqlServerName')]", "Databases": [ "[variable('Sql.Database.Analytics')]", "[variable('Sql.Database.Master')]", "[variable('Sql.Database.Web')]" ], "Login": "[parameter('SqlUser')]", "Roles": [ "db_datareader", "db_datawriter", "public" ] } } #> function Invoke-SetSqlDatabaseRolesTask { [CmdletBinding(SupportsShouldProcess=$true)] param( [Parameter(Mandatory=$true)] [string]$SQLServerName, [Parameter(Mandatory=$true)] [string[]]$Databases, [Parameter(Mandatory=$true)] [string]$Login, [Parameter(Mandatory=$true)] [string[]]$Roles ) #region "Get MSSQL server instance" $sqlServerSmo = Get-SqlServerSmo -SQLServerName $SQLServerName if( $sqlServerSmo -eq $null ) { Write-Error "Cannot find MSSQL server $SQLServerName" return; } #endregion if ($Login -eq "sa") { Write-Warning "The login '$Login' is the built-in sysadmin for SQL. Skip setting roles for this user." return } foreach( $db in $Databases ) { $database = $sqlServerSmo.Databases[$db] $dbUser = $database.Users | Where-Object {$_.Login -eq "$Login"} if ($dbUser -eq $null) { Write-Information -Message "Adding user $Login in $($database.Name)" -Tag 'MSSQL' $dbUser = New-Object -TypeName Microsoft.SqlServer.Management.Smo.User($database, $Login) $dbUser.Login = $Login $dbUser.Create() } # Assign database roles user foreach ($roleName in $roles) { Write-Information -Message "Adding $roleName role for $($dbUser.Name) on $db" -Tag 'MSSQL' $dbrole = $database.Roles[$roleName] $dbrole.AddMember($dbUser.Name) $dbrole.Alter | Out-Null } } } function Invoke-AttachSqlDatabaseTask { <# .SYNOPSIS Attach a database to the MSSQL server. .DESCRIPTION The Invoke-AttachSqlDatabaseTask attach 'DBDataFilePath' to 'SQLServerName' as 'DBName'. The Invoke-AttachSqlDatabaseTask is registered as AttachDB task. .EXAMPLE Json task configuration for Sitecore Install Framework: "AttachCoreDatabase": { "Type": "AttachDB", "Params": { "SQLServerName": "[parameter('SqlServerName')]", "DBName": "[variable('Sql.Database.Core')]", "DBDataFilePath": "[variable('Sql.MDF.Core')]", "DBLogFilePath": "[variable('Sql.LDF.Core')]" } } #> [CmdletBinding(SupportsShouldProcess=$true)] param( [Parameter(Mandatory=$true)] [string]$SQLServerName, [Parameter(Mandatory=$true)] [string]$DBName, [Parameter(Mandatory=$true)] [string]$DBDataFilePath, [Parameter(Mandatory=$true)] [string]$DBLogFilePath ) #region "Get MSSQL server instance" $sqlServerSmo = Get-SqlServerSmo -SQLServerName $SQLServerName if( $sqlServerSmo -eq $null ) { Write-Error "Cannot find MSSQL server $SQLServerName" return; } #endregion if($pscmdlet.ShouldProcess($SQLServerName, "Attach $DBDataFilePath as database $DBName")) { if ($sqlServerSmo.databases[$DBName] -eq $null) { Write-Information -Message "Attaching $DBDataFilePath to $SQLServerName as $DBName" -Tag 'MSSQL' Write-Information -Message "Attaching $DBLogFilePath to $SQLServerName as $DBName" -Tag 'MSSQL' $files = New-Object System.Collections.Specialized.StringCollection $files.Add($DBDataFilePath) | Out-Null; $files.Add($DBLogFilePath) | Out-Null; # Try attaching try { $sqlServerSmo.AttachDatabase($DBName, $files) } catch { Write-Error $_.Exception } } else { $message = "Database $DBName already exists on " + $sqlServerSmo.Name Write-Warning $message } } } function Invoke-SetSqlDatabasePermisionsTask { [CmdletBinding(SupportsShouldProcess=$true)] param( [Parameter(Mandatory=$true)] [string]$SQLServerName, [Parameter(Mandatory=$true)] [string[]]$Databases, [Parameter(Mandatory=$true)] [string]$UserName ) #region "Get MSSQL server instance" $sqlServerSmo = Get-SqlServerSmo -SQLServerName $SQLServerName if( $sqlServerSmo -eq $null ) { Write-Error "Cannot find MSSQL server $SQLServerName" return; } #endregion foreach( $db in $Databases ) { $database = $sqlServerSmo.Databases[$db] if ($UserName -eq "sa") { Write-Warning "The login '$UserName' is the built-in sysadmin for SQL. Skip setting roles for this user." return } $dbUser = $database.Users | Where-Object {$_.Login -eq "$UserName"} if ($dbUser -eq $null) { Write-Warning "Could not find a user '$UserName' for the login . Cannot grant permissions." return } $permset = New-Object Microsoft.SqlServer.Management.Smo.DatabasePermissionSet $permset.Execute = $true $database.Grant($permset, $UserName) $database.Alter(); $message = "Granted Execute permission to $UserName on $db" Write-Information -Message $message -Tag 'MSSQL' } } function Invoke-DeleteSqlDatabaseTask { <# .SYNOPSIS Removes a SQL databases on server .DESCRIPTION The Invoke-DeleteSqlDatabaseTask function removes a databases on MSSQL server. The Invoke-DeleteSqlDatabaseTask is registered as SqlDeleteDatabase task. .EXAMPLE Json task configuration for Sitecore Install Framework "DeleteDatabases": { "Type": "DeleteSqlDatabase", "Params": { "SQLServerName": "[parameter('SqlServerName')]", "Databases": [ "[variable('Sql.Database.Analytics')]", "[variable('Sql.Database.Master')]", "[variable('Sql.Database.Web')]" ], } } #> [CmdletBinding(SupportsShouldProcess=$true)] param( [Parameter(Mandatory=$true)] [string]$SQLServerName, [Parameter(Mandatory=$true)] [string[]]$Databases ) #region "Get MSSQL server instance" $sqlServerSmo = Get-SqlServerSmo -SQLServerName $SQLServerName if( $sqlServerSmo -eq $null ) { Write-Error "Cannot find MSSQL server $SQLServerName" return; } #endregion foreach( $database in $Databases ) { if($pscmdlet.ShouldProcess($SQLServerName, "Remove $database")) { if ($sqlServerSmo.databases[$database] -ne $null) { Write-Information -Message "Remove $database" -Tag 'MSSQL' Invoke-SQLcmd -ServerInstance $SQLServerName -Query ("EXEC msdb.dbo.sp_delete_database_backuphistory @database_name = N'" + $database + "'") Invoke-SQLcmd -ServerInstance $SQLServerName -Query ("DROP DATABASE [" + $database + "]") } else { $message = "Database $database not exists on $SQLServerName" Write-Warning $message } } } } $sql = @" declare @ApplicationName nvarchar(256) = 'sitecore' declare @UserName nvarchar(256) = 'sitecore\admin' declare @Password nvarchar(128) = 'passwordplaceholder' declare @HashAlgorithm nvarchar(10) = 'SHA2_512' declare @PasswordFormat int = 1 -- Hashed declare @CurrentTimeUtc datetime = SYSUTCDATETIME() declare @Salt varbinary(16) = 0x declare @HashedPassword varbinary(512) declare @EncodedHash nvarchar(128) declare @EncodedSalt nvarchar(128) -- Generate random salt while len(@Salt) < 16 begin set @Salt = (@Salt + cast(cast(floor(rand() * 256) as tinyint) as binary(1))) end -- Hash password set @HashedPassword = HASHBYTES(@HashAlgorithm, @Salt + cast(@Password as varbinary(128))); -- Convert hash and salt to BASE64 select @EncodedHash = cast(N'' as xml).value( 'xs:base64Binary(xs:hexBinary(sql:column("bin")))' , 'varchar(max)' ) from (select @HashedPassword as [bin] ) T select @EncodedSalt = cast(N'' as xml).value( 'xs:base64Binary(xs:hexBinary(sql:column("bin")))' , 'VARCHAR(MAX)' ) from (select @Salt as [bin] ) T execute [dbo].[aspnet_Membership_SetPassword] @ApplicationName ,@UserName ,@EncodedHash ,@EncodedSalt ,@CurrentTimeUtc ,@PasswordFormat "@ function Invoke-SetSitecoreAdminPasswordTask { [CmdletBinding(SupportsShouldProcess=$true)] param( [Parameter(Mandatory=$true)] [string]$SqlServer, [Parameter(Mandatory=$true)] [string]$SqlDb, [Parameter(Mandatory=$true)] [string]$SqlAdminUser, [Parameter(Mandatory=$true)] [string]$SqlAdminPassword, [Parameter(Mandatory=$true)] [string]$SitecoreAdminPassword ) if($pscmdlet.ShouldProcess($SqlServer, "Reset Sitecore admin password at database $SqlDb")) { Write-Information -Message "Reset Sitecore admin password at database $SqlDb" -Tag 'MSSQL' $query = $sql -replace 'passwordplaceholder',$SitecoreAdminPassword Invoke-SQLcmd -ServerInstance $SqlServer -Query $Query -Database $SqlDb -Username $SqlAdminUser -Password $SqlAdminPassword } } Export-ModuleMember Invoke-SetSqlMixedModeTask Export-ModuleMember Invoke-AttachSqlDatabaseTask Export-ModuleMember Invoke-DeleteSqlDatabaseTask Export-ModuleMember Invoke-SetSqlDatabaseRolesTask Export-ModuleMember Invoke-SetSqlDatabasePermisionsTask Export-ModuleMember Invoke-CreateSqlUserTask Export-ModuleMember Invoke-DeleteSqlUserTask Export-ModuleMember Invoke-SetSitecoreAdminPasswordTask Register-SitecoreInstallExtension -Command Invoke-SetSitecoreAdminPasswordTask -As SetSitecoreAdminPassword -Type Task |