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))) { $sqlServerSmo.ConnectionContext.LoginSecure = $false $sqlServerSmo.ConnectionContext.Login = $UserName $sqlServerSmo.ConnectionContext.Password = $Password } [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-TaskInfo -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")) { $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) } else { Write-Warning "User exist: $UserName ..." } } } function Invoke-DeleteSqlUserTask { [CmdletBinding(SupportsShouldProcess=$true)] param( [Parameter(Mandatory=$true)] [string]$SQLServerName, [Parameter(Mandatory=$true)] [string]$UserName ) Write-TaskInfo -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-TaskInfo -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-TaskInfo -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-TaskInfo -Message "Attaching $DBDataFilePath to $SQLServerName as $DBName" -Tag 'MSSQL' Write-TaskInfo -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-TaskInfo -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-TaskInfo -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-TaskInfo -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 # SIG # Begin signature block # MIIOJAYJKoZIhvcNAQcCoIIOFTCCDhECAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB # gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR # AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUi6baPzHQvRwJsoSQKuk/tX5d # CGugggtbMIIFczCCBFugAwIBAgIQUSxkhQ/4RLIK3tXEKSPpmzANBgkqhkiG9w0B # AQsFADB9MQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3JlYXRlciBNYW5jaGVzdGVy # MRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01PRE8gQ0EgTGltaXRlZDEj # MCEGA1UEAxMaQ09NT0RPIFJTQSBDb2RlIFNpZ25pbmcgQ0EwHhcNMTgwNTI4MDAw # MDAwWhcNMTkwNTI4MjM1OTU5WjCBszELMAkGA1UEBhMCVVMxDjAMBgNVBBEMBTc4 # NzAxMQ4wDAYDVQQIDAVUZXhhczEPMA0GA1UEBwwGQXVzdGluMSQwIgYDVQQJDBsy # MDEgVyA1dGggU3RyZWV0IFN1aXRlIDE1NTAxDjAMBgNVBBIMBTc4NzAxMRcwFQYD # VQQKDA5Tb2Z0U2VydmUsIEluYzELMAkGA1UECwwCSVQxFzAVBgNVBAMMDlNvZnRT # ZXJ2ZSwgSW5jMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtacjDf0a # fiL/JjPhuusvx/wzxS4NdQWRwjDtPCPujWuf+IkB1oY4Nq+fACMlLMzTY7btMpEi # 3po6UqRqxgXyaWp0lIdf/uuHNgAL5xzh4U17ChzaCI6kS5oiD3SLtmhv8iJh31s9 # XVe8PgMg/prKHgnkSfBwwL+q7xDjHZ64QVF7j8w8QPUhIe50kSeQKObCl9PoyIxL # filF95MKvat69wBcidedDr1NuIT6zM1MY7IHdJJpckOjwbqmxDqJnMlMcleSXfb6 # c+MuEocRLU5ZBxFlE/HlDDTS55w2JTADqd9frpNNuW/BVsmIJb5wppYm7b8fYf0o # Ztd6r81xKzIwCQIDAQABo4IBtjCCAbIwHwYDVR0jBBgwFoAUKZFg/4pN+uv5pmq4 # z/nmS71JzhIwHQYDVR0OBBYEFCEuZIvB3XxckO1wWP+/CaYTJ2TIMA4GA1UdDwEB # /wQEAwIHgDAMBgNVHRMBAf8EAjAAMBMGA1UdJQQMMAoGCCsGAQUFBwMDMBEGCWCG # SAGG+EIBAQQEAwIEEDBGBgNVHSAEPzA9MDsGDCsGAQQBsjEBAgEDAjArMCkGCCsG # AQUFBwIBFh1odHRwczovL3NlY3VyZS5jb21vZG8ubmV0L0NQUzBDBgNVHR8EPDA6 # MDigNqA0hjJodHRwOi8vY3JsLmNvbW9kb2NhLmNvbS9DT01PRE9SU0FDb2RlU2ln # bmluZ0NBLmNybDB0BggrBgEFBQcBAQRoMGYwPgYIKwYBBQUHMAKGMmh0dHA6Ly9j # cnQuY29tb2RvY2EuY29tL0NPTU9ET1JTQUNvZGVTaWduaW5nQ0EuY3J0MCQGCCsG # AQUFBzABhhhodHRwOi8vb2NzcC5jb21vZG9jYS5jb20wJwYDVR0RBCAwHoEcc2Ft # dGVhbW1haWxAc29mdHNlcnZlaW5jLmNvbTANBgkqhkiG9w0BAQsFAAOCAQEAEdJL # WqG+vwl4lHQAWoMGAUmMpkBFiSPDy7fU7CSIFkdRnVRMVE2VCG2yJiTChBqreM5u # IvZJvqSkMxxzcAbdR66OPVRunRXRo3I1Oxyb11f/4G39Qaw3LxH6JQOHh9g/w3av # L9NR6S+vOhdK7PR+kkDA4rxHdh/1PQNX/5BjvtjZoW7Q6l3qwDH/XENdsk0i7oKm # GeqoY2bjXWZ7Y2uBn9HlaJJOjn7sTgO94rT6YYpFa+TqFP9KY4/d+61tdz9M6K9Z # yRgXyNbtMIPmSMqF7qh8z9/hfPsGY+2AkvgHnnsUFhPbckLdUN/0LDPRoAtIPTwi # k2Oskgam6avYyryNPjCCBeAwggPIoAMCAQICEC58h8wOk0pS/pT9HLfNNK8wDQYJ # KoZIhvcNAQEMBQAwgYUxCzAJBgNVBAYTAkdCMRswGQYDVQQIExJHcmVhdGVyIE1h # bmNoZXN0ZXIxEDAOBgNVBAcTB1NhbGZvcmQxGjAYBgNVBAoTEUNPTU9ETyBDQSBM # aW1pdGVkMSswKQYDVQQDEyJDT01PRE8gUlNBIENlcnRpZmljYXRpb24gQXV0aG9y # aXR5MB4XDTEzMDUwOTAwMDAwMFoXDTI4MDUwODIzNTk1OVowfTELMAkGA1UEBhMC # R0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9y # ZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxIzAhBgNVBAMTGkNPTU9ETyBS # U0EgQ29kZSBTaWduaW5nIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC # AQEAppiQY3eRNH+K0d3pZzER68we/TEds7liVz+TvFvjnx4kMhEna7xRkafPnp4l # s1+BqBgPHR4gMA77YXuGCbPj/aJonRwsnb9y4+R1oOU1I47Jiu4aDGTH2EKhe7VS # A0s6sI4jS0tj4CKUN3vVeZAKFBhRLOb+wRLwHD9hYQqMotz2wzCqzSgYdUjBeVoI # zbuMVYz31HaQOjNGUHOYXPSFSmsPgN1e1r39qS/AJfX5eNeNXxDCRFU8kDwxRstw # rgepCuOvwQFvkBoj4l8428YIXUezg0HwLgA3FLkSqnmSUs2HD3vYYimkfjC9G7WM # crRI8uPoIfleTGJ5iwIGn3/VCwIDAQABo4IBUTCCAU0wHwYDVR0jBBgwFoAUu69+ # Aj36pvE8hI6t7jiY7NkyMtQwHQYDVR0OBBYEFCmRYP+KTfrr+aZquM/55ku9Sc4S # MA4GA1UdDwEB/wQEAwIBhjASBgNVHRMBAf8ECDAGAQH/AgEAMBMGA1UdJQQMMAoG # CCsGAQUFBwMDMBEGA1UdIAQKMAgwBgYEVR0gADBMBgNVHR8ERTBDMEGgP6A9hjto # dHRwOi8vY3JsLmNvbW9kb2NhLmNvbS9DT01PRE9SU0FDZXJ0aWZpY2F0aW9uQXV0 # aG9yaXR5LmNybDBxBggrBgEFBQcBAQRlMGMwOwYIKwYBBQUHMAKGL2h0dHA6Ly9j # cnQuY29tb2RvY2EuY29tL0NPTU9ET1JTQUFkZFRydXN0Q0EuY3J0MCQGCCsGAQUF # BzABhhhodHRwOi8vb2NzcC5jb21vZG9jYS5jb20wDQYJKoZIhvcNAQEMBQADggIB # AAI/AjnD7vjKO4neDG1NsfFOkk+vwjgsBMzFYxGrCWOvq6LXAj/MbxnDPdYaCJT/ # JdipiKcrEBrgm7EHIhpRHDrU4ekJv+YkdK8eexYxbiPvVFEtUgLidQgFTPG3UeFR # AMaH9mzuEER2V2rx31hrIapJ1Hw3Tr3/tnVUQBg2V2cRzU8C5P7z2vx1F9vst/dl # CSNJH0NXg+p+IHdhyE3yu2VNqPeFRQevemknZZApQIvfezpROYyoH3B5rW1CIKLP # DGwDjEzNcweU51qOOgS6oqF8H8tjOhWn1BUbp1JHMqn0v2RH0aofU04yMHPCb7d4 # gp1c/0a7ayIdiAv4G6o0pvyM9d1/ZYyMMVcx0DbsR6HPy4uo7xwYWMUGd8pLm1Gv # TAhKeo/io1Lijo7MJuSy2OU4wqjtxoGcNWupWGFKCpe0S0K2VZ2+medwbVn4bSoM # fxlgXwyaiGwwrFIJkBYb/yud29AgyonqKH4yjhnfe0gzHtdl+K7J+IMUk3Z9ZNCO # zr41ff9yMU2fnr0ebC+ojwwGUPuMJ7N2yfTm18M04oyHIYZh/r9VdOEhdwMKaGy7 # 5Mmp5s9ZJet87EUOeWZo6CLNuO+YhU2WETwJitB/vCgoE/tqylSNklzNwmWYBp7O # SFvUtTeTRkF8B93P+kPvumdh/31J4LswfVyA4+YWOUunMYICMzCCAi8CAQEwgZEw # fTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G # A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxIzAhBgNV # BAMTGkNPTU9ETyBSU0EgQ29kZSBTaWduaW5nIENBAhBRLGSFD/hEsgre1cQpI+mb # MAkGBSsOAwIaBQCgeDAYBgorBgEEAYI3AgEMMQowCKACgAChAoAAMBkGCSqGSIb3 # DQEJAzEMBgorBgEEAYI3AgEEMBwGCisGAQQBgjcCAQsxDjAMBgorBgEEAYI3AgEV # MCMGCSqGSIb3DQEJBDEWBBRDIjxwNqFYVXsv1XFGEt3rQ7GRNDANBgkqhkiG9w0B # AQEFAASCAQABlWVxyi/psoIdT5Jg09oAP6ionUeP/4X4tmB9aAisZ+KtNg4fmN1F # /33zAgwEzuHlUP+VV7OdXCtOx959oKKa1Hq2/qqN9Q+v8Lu9ok1Pk9wtBi7oHdhm # oZZhbNPWVveyVdEbdnTGi+ly5Wpo0aRbpC3UypyoTV7all569qUIfQy0wgxXLYZP # exetOiWiTfhtktVJB4lmTzLskCXAitZyXefria+YUFb0i3Sbozm2liXNq18So844 # bhV76pikGd/BVG4QANt//SMQU+mNkYgE339abEqWcaI8E6D8NRSafKA0zHzQcfof # 3IvQSRocwCcI94PtrW4XfVdtM6IpX4fH # SIG # End signature block |