Advertisement
Guest User

Add-CodeDomAuthorizedTypeToOWSTimerConfig.ps1

a guest
Jan 15th, 2019
183
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. <#
  2.  
  3.  This Sample Code is provided for the purpose of illustration only and is not intended to be used in a production environment.  
  4.  THIS SAMPLE CODE AND ANY RELATED INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED,
  5.  INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.  
  6.  We grant you a nonexclusive, royalty-free right to use and modify the sample code and to reproduce and distribute the object
  7.  code form of the Sample Code, provided that you agree:
  8.     (i)   to not use our name, logo, or trademarks to market your software product in which the sample code is embedded;
  9.     (ii)  to include a valid copyright notice on your software product in which the sample code is embedded; and
  10.     (iii) to indemnify, hold harmless, and defend us and our suppliers from and against any claims or lawsuits, including
  11.           attorneys' fees, that arise or result from the use or distribution of the sample code.
  12.  Please note: None of the conditions outlined in the disclaimer above will supercede the terms and conditions contained within
  13.               the Premier Customer Services Description.
  14.  ----------------------------------------------------------
  15.  History
  16.  ----------------------------------------------------------
  17.  10/15/2018 - Added three additional authorized types
  18.  
  19.  09/20/2018 - Updated to automatically restart the timer service if any changes are made to the .config
  20.  
  21.  09/18/2018 - Updated to add the necessary <configSections> section, if it doesn't exist in the existing owstimer.exe.config file.
  22.  
  23.  09/18/2018 - Added an update to allow customers using Nintex to use the new IncludeNintexWorkflow switch to automatically add
  24.               the necessary authorizedType required for Nintex
  25.  
  26.  09/17/2018 - Created script to update owstimer.exe.config file on farm servers.
  27.  
  28.  
  29.    REFERENCE:
  30.  
  31.     https://blogs.msdn.microsoft.com/rodneyviana/2018/09/13/after-installing-net-security-patches-to-address-cve-2018-8421-sharepoint-workflows-stop-working/
  32.  
  33.   SUMMARY:
  34.    
  35.     This script will update each of the specified servers defined at the bottom of the script. If additional servers are added to the
  36.     farm at a later date, this script will need to be run against the new server(s) in order for the updates to be added to the owstimer.exe.config
  37.  
  38. ==============================================================
  39. #>
  40.  
  41. Add-PSSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue | Out-Null
  42.  
  43. function Add-ConfigSections
  44. {
  45.     <#
  46.     .Synopsis
  47.        Adds the necessary configSections if not already present in owstimer.exe.config
  48.  
  49.     .DESCRIPTION
  50.        Adds the necessary configSections if not already present in owstimer.exe.config
  51.  
  52.     .EXAMPLE
  53.        Add-ConfigSections -XmlDocument $xmlDoc
  54.     #>
  55.     [CmdletBinding()]
  56.     param
  57.     (
  58.         [parameter(Mandatory=$true)][System.Xml.XmlDocument]$XmlDocument
  59.     )
  60.  
  61.     begin
  62.     {
  63.         $farmMajorVersion = (Get-SPFarm -Verbose:$false ).BuildVersion.Major
  64.     }
  65.     process
  66.     {
  67.         if( $farmMajorVersion -le 14)
  68.         {
  69.             $sectionGroup = New-Object PSObject -Property @{
  70.                 Path  = "/configuration/configSections"
  71.                 Name  = "/configuration/configSections/sectionGroup[@name='System.Workflow.ComponentModel.WorkflowCompiler'][@type='System.Workflow.ComponentModel.Compiler.WorkflowCompilerConfigurationSectionGroup, System.Workflow.ComponentModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35']"
  72.                 Value = '<sectionGroup name="System.Workflow.ComponentModel.WorkflowCompiler" type="System.Workflow.ComponentModel.Compiler.WorkflowCompilerConfigurationSectionGroup, System.Workflow.ComponentModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />'
  73.             }
  74.  
  75.             $authorizedTypesSection = New-Object PSObject -Property @{
  76.                 Path  = "configuration/configSections/sectionGroup"
  77.                 Name  = "configuration/configSections/sectionGroup/section[@name='authorizedTypes'][@type='System.Workflow.ComponentModel.Compiler.AuthorizedTypesSectionHandler, System.Workflow.ComponentModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35']"
  78.                 Value = '<section name="authorizedTypes" type="System.Workflow.ComponentModel.Compiler.AuthorizedTypesSectionHandler, System.Workflow.ComponentModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />'
  79.             }
  80.  
  81.             $authorizedRuleTypesSection = New-Object PSObject -Property @{
  82.                 Path  = "configuration/configSections/sectionGroup"
  83.                 Name  = "configuration/configSections/sectionGroup/section[@name='authorizedRuleTypes'][@type='System.Workflow.ComponentModel.Compiler.AuthorizedTypesSectionHandler, System.Workflow.ComponentModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35']"
  84.                 Value = '<section name="authorizedRuleTypes" type="System.Workflow.ComponentModel.Compiler.AuthorizedTypesSectionHandler, System.Workflow.ComponentModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />'
  85.             }
  86.         }
  87.         else
  88.         {
  89.             $sectionGroup = New-Object PSObject -Property @{
  90.                 Path  = "/configuration/configSections"
  91.                 Name  = "/configuration/configSections/sectionGroup[@name='System.Workflow.ComponentModel.WorkflowCompiler'][@type='System.Workflow.ComponentModel.Compiler.WorkflowCompilerConfigurationSectionGroup, System.Workflow.ComponentModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35']"
  92.                 Value = '<sectionGroup name="System.Workflow.ComponentModel.WorkflowCompiler" type="System.Workflow.ComponentModel.Compiler.WorkflowCompilerConfigurationSectionGroup, System.Workflow.ComponentModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />'
  93.             }
  94.  
  95.             $authorizedTypesSection = New-Object PSObject -Property @{
  96.                 Path  = "configuration/configSections/sectionGroup"
  97.                 Name  = "configuration/configSections/sectionGroup/section[@name='authorizedTypes'][@type='System.Workflow.ComponentModel.Compiler.AuthorizedTypesSectionHandler, System.Workflow.ComponentModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35']"
  98.                 Value = '<section name="authorizedTypes" type="System.Workflow.ComponentModel.Compiler.AuthorizedTypesSectionHandler, System.Workflow.ComponentModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />'
  99.             }
  100.  
  101.             $authorizedRuleTypesSection = New-Object PSObject -Property @{
  102.                 Path  = "configuration/configSections/sectionGroup"
  103.                 Name  = "configuration/configSections/sectionGroup/section[@name='authorizedRuleTypes'][@type='System.Workflow.ComponentModel.Compiler.AuthorizedTypesSectionHandler, System.Workflow.ComponentModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35']"
  104.                 Value = '<section name="authorizedRuleTypes" type="System.Workflow.ComponentModel.Compiler.AuthorizedTypesSectionHandler, System.Workflow.ComponentModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />'
  105.             }
  106.         }
  107.  
  108.         # ensure /configuration
  109.         if( -not ($XmlDocument | Select-Xml -XPath "configuration").Node )
  110.         {
  111.             Initialize-Path -XmlDocument $XmlDocument -Path "configuration" | Out-Null
  112.         }
  113.  
  114.         # ensure /configuration/configSections.  It must be the first child element of the <configuration> element.
  115.         if( -not ($XmlDocument | Select-Xml -XPath "/configuration/configSections").Node )
  116.         {
  117.             $configNode = ($XmlDocument | Select-Xml -XPath "configuration").Node
  118.             $configNode.InsertBefore( $XmlDocument.CreateElement("configSections"), $configNode.FirstChild) | Out-Null
  119.         }
  120.  
  121.         # ensure /configuration/configSections/sectionGroup
  122.         if( -not ($XmlDocument | Select-Xml -XPath $sectionGroup.Name) )
  123.         {
  124.             $parentNode = ($XmlDocument | Select-Xml -XPath $sectionGroup.Path).Node
  125.             $parentNode.InnerXml += $sectionGroup.Value
  126.         }
  127.  
  128.         # ensure /configuration/configSections/sectionGroup/section[@name='authorizedTypes']
  129.         if( -not ($XmlDocument | Select-Xml -XPath $authorizedTypesSection.Name) )
  130.         {
  131.             $parentNode = ($XmlDocument | Select-Xml -XPath $authorizedTypesSection.Path).Node
  132.             $parentNode.InnerXml += $authorizedTypesSection.Value
  133.         }
  134.  
  135.         # ensure configuration/configSections/sectionGroup/section[@name='authorizedRuleTypes']
  136.         if( -not ($XmlDocument | Select-Xml -XPath $authorizedRuleTypesSection.Name) )
  137.         {
  138.             $parentNode = ($XmlDocument | Select-Xml -XPath $authorizedRuleTypesSection.Path).Node
  139.             $parentNode.InnerXml += $authorizedRuleTypesSection.Value
  140.         }
  141.     }
  142.     end
  143.     {
  144.     }
  145. }
  146.  
  147. function Add-AuthorizedTypes
  148. {
  149.     <#
  150.     .Synopsis
  151.        Adds the necessary authorizedTypes elements if not already present in owstimer.exe.config
  152.  
  153.     .DESCRIPTION
  154.        Adds the necessary elements if not already present in owstimer.exe.config. Includes -IncludeNintexWorkflow
  155.        if the local farm utilizes Nintex workflows.
  156.  
  157.     .EXAMPLE
  158.        Add-AuthorizedTypes -XmlDocument $xmlDoc
  159.  
  160.     .EXAMPLE
  161.        Add-AuthorizedTypes -XmlDocument $xmlDoc -IncludeNintexWorkflow
  162.     #>
  163.     [CmdletBinding()]
  164.     param
  165.     (
  166.         [parameter(Mandatory=$true)][System.Xml.XmlDocument]$XmlDocument,
  167.         [parameter(Mandatory=$false)][switch]$IncludeNintexWorkflow
  168.     )
  169.    
  170.     begin
  171.     {
  172.         $authorizedTypes = @()
  173.         $farmMajorVersion = (Get-SPFarm -Verbose:$false ).BuildVersion.Major
  174.  
  175.         if( $farmMajorVersion -le 14)
  176.         {
  177.             $systemAssemblyVersion = "2.0.0.0"
  178.             $targetParentPath      = "configuration/System.Workflow.ComponentModel.WorkflowCompiler/authorizedTypes"
  179.         }
  180.         else
  181.         {
  182.             $systemAssemblyVersion = "4.0.0.0"
  183.             $targetParentPath      = "configuration/System.Workflow.ComponentModel.WorkflowCompiler/authorizedTypes/targetFx[@version='v4.0']"
  184.         }
  185.  
  186.         if($IncludeNintexWorkflow.IsPresent)
  187.         {
  188.             $authorizedTypes += New-Object PSCustomObject -Property @{
  189.                 Assembly  = "System, Version=$systemAssemblyVersion, Culture=neutral, PublicKeyToken=b77a5c561934e089"
  190.                 Namespace = "System.CodeDom"
  191.                 TypeName  = "CodeTypeReferenceExpression"
  192.             }
  193.         }
  194.        
  195.         $authorizedTypes += New-Object PSCustomObject -Property @{
  196.             Assembly  = "System, Version=$systemAssemblyVersion, Culture=neutral, PublicKeyToken=b77a5c561934e089"
  197.             Namespace = "System.CodeDom"
  198.             TypeName  = "CodeBinaryOperatorExpression"
  199.         }
  200.  
  201.         $authorizedTypes += New-Object PSCustomObject -Property @{
  202.             Assembly  = "System, Version=$systemAssemblyVersion, Culture=neutral, PublicKeyToken=b77a5c561934e089"
  203.             Namespace = "System.CodeDom"
  204.             TypeName  = "CodePrimitiveExpression"
  205.         }
  206.  
  207.         $authorizedTypes += New-Object PSCustomObject -Property @{
  208.             Assembly  = "System, Version=$systemAssemblyVersion, Culture=neutral, PublicKeyToken=b77a5c561934e089"
  209.             Namespace = "System.CodeDom"
  210.             TypeName  = "CodeMethodInvokeExpression"
  211.         }
  212.  
  213.         $authorizedTypes += New-Object PSCustomObject -Property @{
  214.             Assembly  = "System, Version=$systemAssemblyVersion, Culture=neutral, PublicKeyToken=b77a5c561934e089"
  215.             Namespace = "System.CodeDom"
  216.             TypeName  = "CodeMethodReferenceExpression"
  217.         }
  218.  
  219.         $authorizedTypes += New-Object PSCustomObject -Property @{
  220.             Assembly  = "System, Version=$systemAssemblyVersion, Culture=neutral, PublicKeyToken=b77a5c561934e089"
  221.             Namespace = "System.CodeDom"
  222.             TypeName  = "CodeFieldReferenceExpression"
  223.         }
  224.  
  225.         $authorizedTypes += New-Object PSCustomObject -Property @{
  226.             Assembly  = "System, Version=$systemAssemblyVersion, Culture=neutral, PublicKeyToken=b77a5c561934e089"
  227.             Namespace = "System.CodeDom"
  228.             TypeName  = "CodeThisReferenceExpression"
  229.         }
  230.  
  231.         $authorizedTypes += New-Object PSCustomObject -Property @{
  232.             Assembly  = "System, Version=$systemAssemblyVersion, Culture=neutral, PublicKeyToken=b77a5c561934e089"
  233.             Namespace = "System.CodeDom"
  234.             TypeName  = "CodePropertyReferenceExpression"
  235.         }
  236.  
  237.         # added 10/15/2018 to match Nov 2018 CU
  238.         $authorizedTypes += New-Object PSCustomObject -Property @{
  239.             Assembly  = "System.Workflow.Activities, Version=$systemAssemblyVersion, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
  240.             Namespace = "System.Workflow.Activities.Rules"
  241.             TypeName  = "RuleDefinitions"
  242.         }
  243.  
  244.         # added 10/15/2018 to match Nov 2018 CU
  245.         $authorizedTypes += New-Object PSCustomObject -Property @{
  246.             Assembly  = "System.Workflow.Activities, Version=$systemAssemblyVersion, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
  247.             Namespace = "System.Workflow.Activities.Rules"
  248.             TypeName  = "RuleExpressionCondition"
  249.         }
  250.  
  251.         # added 10/15/2018 - TBD if necessary
  252.         #$authorizedTypes += New-Object PSCustomObject -Property @{
  253.         #    Assembly  = "Microsoft.SharePoint.WorkflowActions, Version=$farmMajorVersion.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"
  254.         #    Namespace = "Microsoft.SharePoint.WorkflowActions"
  255.         #    TypeName  = "*"
  256.         #}
  257.     }
  258.     process
  259.     {
  260.         Initialize-Path -XmlDocument $XmlDocument -Path "configuration/System.Workflow.ComponentModel.WorkflowCompiler/authorizedTypes" | Out-Null
  261.  
  262.         if( $farmMajorVersion -gt 14 -and -not $XmlDocument.SelectSingleNode( "/configuration/System.Workflow.ComponentModel.WorkflowCompiler/authorizedTypes/targetFx[@version='v4.0']" ))
  263.         {
  264.             $parent = $XmlDocument.SelectSingleNode( "configuration/System.Workflow.ComponentModel.WorkflowCompiler/authorizedTypes")
  265.             $parent.InnerXml += "<targetFx version=`"v4.0`" />"
  266.         }
  267.  
  268.         foreach( $authorizedType in $authorizedTypes )
  269.         {
  270.             $object = New-Object PSObject -Property @{
  271.                 Path  = $targetParentPath
  272.                 Name  = "authorizedType[@Assembly='$($authorizedType.Assembly)'][@Namespace='$($authorizedType.Namespace)'][@TypeName='$($authorizedType.TypeName)'][@Authorized='True']"
  273.                 Value = "<authorizedType Assembly=`"$($authorizedType.Assembly)`" Namespace=`"$($authorizedType.Namespace)`" TypeName=`"$($authorizedType.TypeName)`" Authorized=`"True`"/>"
  274.             }
  275.  
  276.             $parentNode = $XmlDocument.SelectSingleNode( $object.Path )
  277.  
  278.             if( $parentNode -and -not $parentNode.SelectSingleNode( $object.Name ))
  279.             {
  280.                 Write-Verbose -Message "Adding Authorized Type: $($object.Value)"
  281.                 $parentNode.InnerXml += $object.Value
  282.             }
  283.         }
  284.     }
  285.     end
  286.     {
  287.     }
  288.        
  289. }
  290.  
  291. function Initialize-Path
  292. {
  293.     <#
  294.     .Synopsis
  295.        Ensures the supplied XML node path has been created.
  296.  
  297.     .DESCRIPTION
  298.        Ensures the supplied XML node path has been created in the supplied in the XMLDocument
  299.  
  300.     .EXAMPLE
  301.         Initialize-Path -XmlDocument $xml -Path "configuration/System.Workflow.ComponentModel.WorkflowCompiler/authorizedTypes"
  302.  
  303.     .EXAMPLE
  304.         Initialize-Path -XmlDocument $xml -Path "configuration/System.Workflow.ComponentModel.WorkflowCompiler/authorizedTypes/targetFx"
  305.     #>
  306.     [CmdletBinding()]
  307.     param
  308.     (
  309.         [parameter(Mandatory=$true)][System.Xml.XmlDocument]$XmlDocument,
  310.         [parameter(Mandatory=$true)][string]$Path
  311.     )
  312.  
  313.     begin
  314.     {
  315.         $farmMajorVersion = (Get-SPFarm -Verbose:$false ).BuildVersion.Major
  316.     }
  317.     process
  318.     {
  319.         $currentNode = $XmlDocument
  320.  
  321.         foreach( $nodeName in $Path -split "/" )
  322.         {
  323.             $node = $currentNode.SelectSingleNode( $nodeName )
  324.            
  325.             if( -not $node )
  326.             {
  327.                 $node = $currentNode.AppendChild($XmlDocument.CreateElement($nodeName))
  328.             }
  329.  
  330.             $currentNode = $node
  331.         }
  332.        
  333.         return $currentNode
  334.     }
  335.     end
  336.     {
  337.     }
  338. }
  339.  
  340. function Add-CodeDomAuthorizedTypeToOWSTimerConfig
  341. {
  342.     <#
  343.     .Synopsis
  344.        Adds the necessary updates to the OWSTIMER.EXE.CONFIG file on the supplied computers.
  345.  
  346.     .DESCRIPTION
  347.        Adds the necessary updates to the OWSTIMER.EXE.CONFIG file on the supplied computers.  Any existing OWSTIMER.EXE.CONFIG files
  348.        will be backed to a timestamped file.
  349.  
  350.     .EXAMPLE
  351.         Add-CodeDomAuthorizedTypeToOWSTimerConfig -ComputerName "Computer01", "Computer02"
  352.  
  353.     .EXAMPLE
  354.         Add-CodeDomAuthorizedTypeToOWSTimerConfig -ComputerName "Computer01", "Computer02" -IncludeNintexWorkflow
  355.     #>
  356.     [CmdletBinding()]
  357.     param
  358.     (
  359.         [parameter(Mandatory=$true)][string[]]$ComputerName,
  360.         [parameter(Mandatory=$false)][switch]$IncludeNintexWorkflow
  361.     )
  362.  
  363.     begin
  364.     {
  365.     }
  366.     process
  367.     {
  368.         foreach( $computer in $ComputerName )
  369.         {
  370.             # get the path to owstimer.exe on each $ComputerName, just in case it's not in the expected location
  371.             $timerServiceConfigPath = Get-WmiObject -Query "SELECT * FROM Win32_Service WHERE name = 'SPTimerV4'" -ComputerName $computer | SELECT @{Name="PathName"; Expression={$_.PathName.Trim('"')}}
  372.  
  373.             Write-Verbose -Message "Processing server: $($computer)"
  374.  
  375.             # convert local path to UNC PATH
  376.             $uncPath = "\\$computer\$($timerServiceConfigPath.PathName)" -replace ":", "$"
  377.            
  378.             $fi = New-Object System.IO.FileInfo( $uncPath )
  379.            
  380.             # make sure the path exists
  381.             if( -not $fi.Directory.Exists )
  382.             {
  383.                 Write-Error -Message "Directory not found: $($fi.Directory.FullName)"
  384.                 continue
  385.             }
  386.  
  387.             # add ".config" to the end of the file name
  388.             $uncPath = "$uncPath.CONFIG"
  389.  
  390.             # create a default owstimer.exe.config, if none exists
  391.             if( -not (Test-Path -Path $uncPath -PathType Leaf) )
  392.             {
  393.                 # build a base XML file based on what 2010 would have
  394.                 $defaultXml = New-Object System.Text.StringBuilder
  395.                 $defaultXml.AppendLine("<?xml version=`"1.0`" encoding=`"utf-8`" ?>") | Out-Null
  396.                 $defaultXml.AppendLine("<configuration>")  | Out-Null
  397.                 $defaultXml.AppendLine("<runtime>")        | Out-Null
  398.                 $defaultXml.AppendLine("</runtime>")       | Out-Null
  399.                 $defaultXml.AppendLine("</configuration>") | Out-Null
  400.                
  401.                 $defaultXml.ToString() | Set-Content -Path $uncPath
  402.             }
  403.  
  404.             # make a backup of the file before doing anything
  405.             Get-Content -Path $uncPath | Set-Content -Path "$($uncPath)_backup_$(Get-Date -Format 'yyyy_MM_dd_hh.mm.ss').config"
  406.            
  407.             # get the existing xml from the file
  408.             [xml]$xml = Get-Content -Path $uncPath
  409.             $originalXml = $xml.OuterXml
  410.  
  411.             # ensure the necessary config sections are present
  412.             Add-ConfigSections -XmlDocument $xml
  413.  
  414.             # ensure authorizedTypes are added
  415.             Add-AuthorizedTypes -XmlDocument $xml -IncludeNintexWorkflow:$IncludeNintexWorkflow.IsPresent
  416.  
  417.             if( $originalXml -ne $xml.OuterXml )
  418.             {
  419.                 Write-Verbose -Message "Saving file changes on $computer"
  420.  
  421.                 # save the changes
  422.                 $xml.Save($uncPath)
  423.  
  424.                 # restart the timer service to pick up the changes
  425.                 Get-Service -Name SPTimerV4 -ComputerName $computer | Restart-Service
  426.             }
  427.         }
  428.     }
  429.     end
  430.     {
  431.     }
  432. }
  433.  
  434.  
  435. # get all the servers in the farm
  436. $serverNames = @(Get-SPServer | ? { $_.Role -ne "Invalid" } | Select -ExpandProperty Name)
  437.  
  438. # add the owstimer.exe.config updates to all the servers.  Add the -IncludeNintexWorkflow if you use Nintex workflows on the farm
  439. Add-CodeDomAuthorizedTypeToOWSTimerConfig -ComputerName $serverNames -Verbose
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement