ManageApplocker.ps1
#Requires -RunAsAdministrator <#PSScriptInfo .VERSION 22.2.19.1 .GUID da1892c0-98ec-41e3-aaf5-f6cc767626e5 .AUTHOR christopher.strobel@outlook.de .COMPANYNAME .COPYRIGHT .TAGS Applocker .LICENSEURI .PROJECTURI .ICONURI .EXTERNALMODULEDEPENDENCIES .REQUIREDSCRIPTS .EXTERNALSCRIPTDEPENDENCIES .RELEASENOTES .PRIVATEDATA #> <# .SYNOPSIS Wrapper script to manage AppLocker policy's/ruleset's in Local/Domain/Intune environments .DESCRIPTION Script to easily Manage Applocker in Intune, Domain, local .PARAMETER Local Select operationmode for Local AppLocker configuration .PARAMETER Domain Select operationmode for AppLocker configuration via Group Policy (make sure to prestage GPO with 'Applocker' string in name) .PARAMETER Intune Select operationmode for AppLocker configuration via custom OMA-URI in Intune (no prestage needed) .PARAMETER File Select operationmode for AppLocker configuration via xml file .PARAMETER BuildBridgeScript Build an Powershell script, which apply AppLocker ruleset based on hosted xml file on fileshare or url .PARAMETER XmlSource Define the source location for the AppLocker xml file. This location will be hardcoded in created bridge script and validated if the script runs. .PARAMETER ScriptPath Define the filepath for the generated bridge script. .PARAMETER ReportFromForwarded Create Out-Grid view of forwarded event's for better search experience .PARAMETER ReportFromForwardedWithStatistic Create Out-Grid view of forwarded event's for better search experience and statistic's .PARAMETER CreateDefaultPolicy Create the default AppLocker ruleset, which would also been created in msc "wizard" (in audit mode, so don't panic) .PARAMETER ApplyToLocal Apply ruleset from selected operationmode to local AppLocker ruleset for better editing/overview (Tip: I like to use an clean Windows Sandbox/VM) .PARAMETER Merge Merge selected rules from eventlog with existing ruleset from selected operationmode .PARAMETER IntunePolicyName Define name of Intune configuration profile (creates new if not exists) .PARAMETER Ruletype Select ruletype publish/hash/path for new rule .PARAMETER PulishLocalPolicy Replace existing ruleset with ruleset from local AppLocker configuration .PARAMETER SwitchEnforcementMode Switch enforcementmode of ruleset between notconfigured, auditonly or enabled .PARAMETER ReturnXML Return an xml object of current ruleset .PARAMETER CleanupLocalPolicy Cleanup local AppLocker ruleset from device .PARAMETER CleanupLocalMDMPolicy Cleanup wmi instance's created by AppLocker bridge script on local device .PARAMETER BackupPolicy Backup currrent ruleset as xml file .EXAMPLE .\ManageApplocker.ps1 -Local -CreateDefaultPolicy Create default AppLocker ruleset in local policy store, which can be edit via secpol.msc Also supported with -File -Domain -Intune .EXAMPLE .\ManageApplocker.ps1 -Intune -ApplyToLocal Apply ruleset from Intune configuration profile to local AppLocker policy for better editing Also supported with -File -Domain .EXAMPLE .\ManageApplocker.ps1 -Intune -Merge -IntunePolicyName "Custom configuration profile" List rules from forwarded eventlog and merge selected rules with existing rules in intune configuration profile Also supported with -File -Domain -Local .EXAMPLE .\ManageApplocker.ps1 -Intune -Merge -IntunePolicyName "Custom configuration profile" Add selected rules to your existing rules in intune configuration profile Also supported with -File -Domain -Local .EXAMPLE .\ManageApplocker.ps1 -Intune -PulishLocalPolicy Upload your local Applocker policy to Intune Also supported with -File -Domain .EXAMPLE .\ManageApplocker.ps1 -BuildBridgeScript -XmlSource "https://yourdomain.com/ruleset.xml" Create an Powershell script, which loads the ruleset from "https://yourdomain.com/ruleset.xml" and apply this via mdm bridge. Also supported with unc or local path like "\\yourserver\yourshare\share\ruleset.xml" or "c:\temp\ruleset.xml" .EXAMPLE .\ManageApplocker.ps1 -CleanupLocalPolicy Remove the local AppLocker policy from system .EXAMPLE .\ManageApplocker.ps1 -CleanupLocalMDMPolicy Remove AppLocker policy's, which assigned via mdm bridge #> [CmdletBinding()] param ( [Parameter(ParameterSetName = "ReportFromForwarded")] [Switch]$ReportFromForwarded, [Parameter(ParameterSetName = "ReportFromForwardedWithStatistic")] [Switch]$ReportFromForwardedWithStatistic, [Parameter(ParameterSetName = "Local-Create")] [Parameter(ParameterSetName = "Local-Apply")] [Parameter(ParameterSetName = "Local-Merge")] [Parameter(ParameterSetName = "Local-Switch")] [Parameter(ParameterSetName = "Local-Return")] [Switch]$Local, [Parameter(ParameterSetName = "Domain-Create")] [Parameter(ParameterSetName = "Domain-Apply")] [Parameter(ParameterSetName = "Domain-Merge")] [Parameter(ParameterSetName = "Domain-Switch")] [Parameter(ParameterSetName = "Domain-Return")] [Parameter(ParameterSetName = "Domain-Publish")] [Switch]$Domain, [Parameter(ParameterSetName = "Intune-Create")] [Parameter(ParameterSetName = "Intune-Apply")] [Parameter(ParameterSetName = "Intune-Merge")] [Parameter(ParameterSetName = "Intune-Switch")] [Parameter(ParameterSetName = "Intune-Return")] [Parameter(ParameterSetName = "Intune-Publish")] [Switch]$Intune, [Parameter(ParameterSetName = "Intune-Create")] [Parameter(ParameterSetName = "Intune-Merge")] [Parameter(ParameterSetName = "Intune-Publish")] [string]$IntunePolicyName, [Parameter(ParameterSetName = "File-Create")] [Parameter(ParameterSetName = "File-Apply")] [Parameter(ParameterSetName = "File-Merge")] [Parameter(ParameterSetName = "File-Switch")] [Parameter(ParameterSetName = "File-Return")] [Parameter(ParameterSetName = "File-Publish")] [Switch]$File, [Parameter(ParameterSetName = "File-Create")] [Parameter(ParameterSetName = "File-Apply")] [Parameter(ParameterSetName = "File-Merge")] [Parameter(ParameterSetName = "File-Switch")] [Parameter(ParameterSetName = "File-Return")] [Parameter(ParameterSetName = "File-Publish")] [System.IO.FileInfo]$Path = $(Join-Path -Path $PWD -ChildPath AppLockerRules.xml), [Parameter(ParameterSetName = "BuildBridgeScript")] [Switch]$BuildBridgeScript, [Parameter(Mandatory, ParameterSetName = "BuildBridgeScript")] [string]$XmlSource, [Parameter(ParameterSetName = "BuildBridgeScript")] [System.IO.FileInfo]$ScriptPath = $(Join-Path -Path $PWD -ChildPath maAppLBridgeScript.ps1), [Parameter(ParameterSetName = "Local-Create")] [Parameter(ParameterSetName = "Domain-Create")] [Parameter(ParameterSetName = "Intune-Create")] [Parameter(ParameterSetName = "File-Create")] [Switch]$CreateDefaultPolicy, [Parameter(ParameterSetName = "Domain-Apply")] [Parameter(ParameterSetName = "Intune-Apply")] [Parameter(ParameterSetName = "File-Apply")] [Switch]$ApplyToLocal, [Parameter(ParameterSetName = "Local-Merge")] [Parameter(ParameterSetName = "Domain-Merge")] [Parameter(ParameterSetName = "Intune-Merge")] [Parameter(ParameterSetName = "File-Merge")] [Switch]$Merge, [Parameter(ParameterSetName = "Local-Merge")] [Parameter(ParameterSetName = "Domain-Merge")] [Parameter(ParameterSetName = "Intune-Merge")] [Parameter(ParameterSetName = "File-Merge")] [ValidateSet("Publisher", "Path", "Hash")] [string]$Ruletype, [Parameter(ParameterSetName = "Local-Merge")] [Parameter(ParameterSetName = "Domain-Merge")] [Parameter(ParameterSetName = "Intune-Merge")] [Parameter(ParameterSetName = "File-Merge")] [string]$User = "Jeder", [Parameter(ParameterSetName = "Domain-Publish")] [Parameter(ParameterSetName = "Intune-Publish")] [Parameter(ParameterSetName = "File-Publish")] [switch]$PulishLocalPolicy, [Parameter(ParameterSetName = "Local-Switch")] [Parameter(ParameterSetName = "Domain-Switch")] [Parameter(ParameterSetName = "Intune-Switch")] [Parameter(ParameterSetName = "File-Switch")] [Switch]$SwitchEnforcementMode, [Parameter(ParameterSetName = "Local-Return")] [Parameter(ParameterSetName = "Domain-Return")] [Parameter(ParameterSetName = "Intune-Return")] [Parameter(ParameterSetName = "File-Return")] [Switch]$ReturnXML, [Parameter(ParameterSetName = "CleanupPolicy")] [Switch]$CleanupLocalPolicy, [Parameter(ParameterSetName = "CleanupLocalMDMPolicy")] [Switch]$CleanupLocalMDMPolicy, [Parameter(ParameterSetName = "BackupPolicy")] [ValidateSet("Domain", "Local", "Intune", "File")] [String]$BackupPolicy ) # init $ErrorActionPreference = 'Stop' $host.PrivateData.VerboseForegroundColor = 'Cyan' $DcName = $($env:LOGONSERVER -replace '\\', '' ) # default rules from wizard [xml]$defaultAppLockerRulesXML = '<AppLockerPolicy Version="1"><RuleCollection Type="Appx" EnforcementMode="AuditOnly"><FilePublisherRule Id="a9e18c21-ff8f-43cf-b9fc-db40eed693ba" Name="(Standardregel) Alle signierten App-Pakete" Description="Erm?glicht Mitgliedern der Gruppe "Jeder" das Ausf?hren von signierten App-Paketen." UserOrGroupSid="S-1-1-0" Action="Allow"><Conditions><FilePublisherCondition PublisherName="*" ProductName="*" BinaryName="*"><BinaryVersionRange LowSection="0.0.0.0" HighSection="*" /></FilePublisherCondition></Conditions></FilePublisherRule></RuleCollection><RuleCollection Type="Dll" EnforcementMode="NotConfigured" /><RuleCollection Type="Exe" EnforcementMode="AuditOnly"><FilePathRule Id="921cc481-6e17-4653-8f75-050b80acca20" Name="(Standardregel) Alle Dateien im Ordner "Programme"" Description="Erm?glicht Mitgliedern der Gruppe "Jeder" das Ausf?hren von Anwendungen, die sich im Ordner "Programme" befinden" UserOrGroupSid="S-1-1-0" Action="Allow"><Conditions><FilePathCondition Path="%PROGRAMFILES%\*" /></Conditions></FilePathRule><FilePathRule Id="a61c8b2c-a319-4cd0-9690-d2177cad7b51" Name="(Standardregel) Alle Dateien im Ordner "Windows"" Description="Erm?glicht Mitgliedern der Gruppe "Jeder" das Ausf?hren von Anwendungen, die sich im Ordner "Windows" befinden" UserOrGroupSid="S-1-1-0" Action="Allow"><Conditions><FilePathCondition Path="%WINDIR%\*" /></Conditions></FilePathRule><FilePathRule Id="fd686d83-a829-4351-8ff4-27c7de5755d2" Name="(Standardregel) Alle Dateien" Description="Erm?glicht Mitgliedern der lokalen Administratorgruppe das Ausf?hren aller Anwendungen" UserOrGroupSid="S-1-5-32-544" Action="Allow"><Conditions><FilePathCondition Path="*" /></Conditions></FilePathRule></RuleCollection><RuleCollection Type="Msi" EnforcementMode="AuditOnly"><FilePublisherRule Id="b7af7102-efde-4369-8a89-7a6a392d1473" Name="(Standardregel) Alle digital signierten Windows Installer-Dateien" Description="Erm?glicht Mitgliedern der Gruppe "Jeder" das Ausf?hren von digital signierten Windows Installer-Dateien" UserOrGroupSid="S-1-1-0" Action="Allow"><Conditions><FilePublisherCondition PublisherName="*" ProductName="*" BinaryName="*"><BinaryVersionRange LowSection="0.0.0.0" HighSection="*" /></FilePublisherCondition></Conditions></FilePublisherRule><FilePathRule Id="5b290184-345a-4453-b184-45305f6d9a54" Name="(Standardregel) Alle Windows Installer-Dateien unter "%systemdrive%\Windows\Installer"" Description="Erm?glicht Mitgliedern der Gruppe "Jeder" das Ausf?hren aller Windows Installer-Dateien, die sich unter "%systemdrive%\Windows\Installer" befinden." UserOrGroupSid="S-1-1-0" Action="Allow"><Conditions><FilePathCondition Path="%WINDIR%\Installer\*" /></Conditions></FilePathRule><FilePathRule Id="64ad46ff-0d71-4fa0-a30b-3f3d30c5433d" Name="(Standardregel) Alle Windows Installer-Dateien" Description="Erm?glicht Mitgliedern der lokalen Administratorgruppe das Ausf?hren aller Windows Installer-Dateien" UserOrGroupSid="S-1-5-32-544" Action="Allow"><Conditions><FilePathCondition Path="*.*" /></Conditions></FilePathRule></RuleCollection><RuleCollection Type="Script" EnforcementMode="AuditOnly"><FilePathRule Id="06dce67b-934c-454f-a263-2515c8796a5d" Name="(Standardregel) Alle Skripts im Ordner "Programme"" Description="Erm?glicht Mitgliedern der Gruppe "Jeder" das Ausf?hren von Skripts, die sich im Ordner "Programme" befinden" UserOrGroupSid="S-1-1-0" Action="Allow"><Conditions><FilePathCondition Path="%PROGRAMFILES%\*" /></Conditions></FilePathRule><FilePathRule Id="9428c672-5fc3-47f4-808a-a0011f36dd2c" Name="(Standardregel) Alle Skripts im Ordner "Windows"" Description="Erm?glicht Mitgliedern der Gruppe "Jeder" das Ausf?hren von Skripts, die sich im Ordner "Windows" befinden" UserOrGroupSid="S-1-1-0" Action="Allow"><Conditions><FilePathCondition Path="%WINDIR%\*" /></Conditions></FilePathRule><FilePathRule Id="ed97d0cb-15ff-430f-b82c-8d7832957725" Name="(Standardregel) Alle Skripts" Description="Erm?glicht Mitgliedern der lokalen Administratorgruppe das Ausf?hren aller Skripts" UserOrGroupSid="S-1-5-32-544" Action="Allow"><Conditions><FilePathCondition Path="*" /></Conditions></FilePathRule></RuleCollection></AppLockerPolicy>' #region internal function's function Get-maApplockerGPO { try { if ([string]::IsNullOrEmpty($(Get-PSSession -ComputerName $DcName))) { Write-Verbose -Message "Create target GPOs" $dcSession = New-PSSession -ComputerName $DcName Import-PSSession -Session $dcSession -Module GroupPolicy | Out-Null } Write-Verbose -Message "List target GPOs" $GPO = get-gpo -all | Where-Object displayname -Like "*Applocker*" | Select-Object displayname, path | Out-GridView -PassThru -Title "Select target GPO to apply rules" if ([string]::IsNullOrEmpty($GPO)) { Write-Warning "Sry, you have to select one target GPO, if no one exists create one with 'AppLocker' in name"; break } return $GPO } catch { $_.Exception.Message } finally { Write-Verbose -Message "Cleanup PSSessions..." Get-PSSession | Remove-PSSession } } function Get-maLDAPPath { if ([string]::IsNullOrEmpty($DcName)) { Write-Warning "No logonserer found in `$env:LOGONSERVER variable, are you realy on an ad device with ad user?" break } "LDAP://" + "$DcName" + "." + "$ENV:USERDNSDOMAIN" + "/" + "$((Get-maApplockerGPO).Path)" } function Convertto-maBase64 { param ( [Parameter(Mandatory = $true, ValueFromPipeline = $true)] $Object ) $bytes = [System.Text.Encoding]::UTF8.GetBytes($Object) [Convert]::ToBase64String($bytes) } function ConvertFrom-maBase64 { param ( [Parameter(Mandatory = $true, ValueFromPipeline = $true)] $Base64String ) $bytes = [convert]::FromBase64String($Base64String) [System.Text.Encoding]::UTF8.GetString($bytes) } function Select-maRuletype { if (!$Ruletype) { $Ruletype = "Publisher", "Path", "Hash" | Out-GridView -Title "Please select needed rule type" -OutputMode Single if ([string]::IsNullOrEmpty($Ruletype)) { Write-Warning "Sry, you have to select one rule type"; break } } return $Ruletype } function Select-maEnforcementMode { $selectedMode = "NotConfigured", "AuditOnly", "Enabled" | Out-GridView -Title "Select your enforcementmode, witch you want to set" -OutputMode Single if (!$selectedMode) { Write-Warning "Sry, you have to select an enforcementmode" break } return $selectedMode } function Select-maAppLockerRules { $fwRules = Get-AppLockerFileInformation -EventLog -LogPath ForwardedEvents | Out-GridView -PassThru if ([string]::IsNullOrEmpty($fwRules)) { Write-Warning "Sry, you have to select some rules" break } return $fwRules } function Get-maIntunePolicy { param ( $PolicyName ) # check for intune module $intuneModule = Get-Module -Name Microsoft.Graph.Intune -ListAvailable if ([string]::IsNullOrEmpty($intuneModule)) { Install-Module -Name Microsoft.Graph.Intune -Force -Confirm:$false } Connect-MSGraph -ErrorAction Stop | Out-Null if ([string]::IsNullOrEmpty($PolicyName)) { Write-Verbose "No Policyname parsed, list available profiles with 'applocker' in name..." $config = Get-DeviceManagement_DeviceConfigurations | Where-Object displayname -Like "*applocker*" | Select-Object displayname, description, omaSettings | Out-GridView -Title "Select intune configuration policy" -OutputMode Single } else { Write-Verbose "Query profile with with $PolicyName from Intune" $config = Get-DeviceManagement_DeviceConfigurations -Filter "displayName eq '$PolicyName'" } if ([string]::IsNullOrEmpty($config)) { Write-Warning "Sry, no Intune-Configuration with name $PolicyName found..." break } return $Config } function Get-maIntunePolicyXML { param ( $PolicyObject ) # create new AppLocker xml $intuneXML = New-Object Xml $applockerNode = $intuneXML.CreateElement('AppLockerPolicy') $intuneXML.AppendChild($applockerNode) | Out-Null $applockerNode.SetAttribute('Version', "1") $PolicyObject.omaSettings | ForEach-Object { [xml]$xmlToAdd = ConvertFrom-maBase64 -Base64String $_.value $rulesetNode = $intuneXML.ImportNode($xmlToAdd.DocumentElement, $true) $intuneXML.AppLockerPolicy.AppendChild($rulesetNode) | Out-Null } return $intuneXML } function Publish-maIntunePolicy { [CmdletBinding()] param ( [Parameter(Mandatory, ValueFromPipeline)] [xml]$AppLockerXML, [Parameter(Mandatory, ValueFromPipeline)] [string]$PolicyName ) begin { # check for intune module $intuneModule = Get-Module -Name Microsoft.Graph.Intune -ListAvailable if ([string]::IsNullOrEmpty($intuneModule)) { Install-Module -Name Microsoft.Graph.Intune -Force -Confirm:$false } # connect to graph Connect-MSGraph -ErrorAction Stop | Out-Null # check if configuration already exists $checkConfig = get-DeviceManagement_DeviceConfigurations -Filter "displayname eq '$PolicyName'" if ($checkConfig) { Write-Warning "Deviceconfiguration with name $IntunePolicyName already exists, will be updated " } } process { $ErrorActionPreference = 'stop' try { $omaSettings = @() $AppLockerXML.AppLockerPolicy.RuleCollection | Where-Object EnforcementMode -NE "NotConfigured" | ForEach-Object { Write-Verbose "Create ruleset for $($_.Type)" Write-Verbose "Processing XML for $($_.Type) : `n$($_.OuterXml)" switch ($_.Type) { Appx { $omaPath = "StoreApps"; break } Dll { $omaPath = "DLL"; break } Exe { $omaPath = "EXE"; break } Msi { $omaPath = "MSI"; break } Script { $omaPath = "SCRIPT"; break } } $omaName = "Policy for $omaPath" $omaUri = "./Vendor/MSFT/AppLocker/ApplicationLaunchRestrictions/$omaPath`Group/$omaPath/Policy" $encOmaXml = $_.OuterXml | Convertto-maBase64 $omaSetting = New-OmaSettingObject -displayName "Applocker - $omaPath" ` -description $omaName ` -omaUri $omaUri ` -omaSettingStringXml ` -value $encOmaXml $omaSettings += $omaSetting Write-Host -ForegroundColor Green "Create ruleset for $($_.Type) done" } # create/update intune device configuration $configParams = @{ windows10CustomConfiguration = $true displayName = $PolicyName description = "Applying AppLocker policy via mdm, using event forwarding for better management" omaSettings = $omaSettings } if ($checkConfig) { Update-DeviceManagement_DeviceConfigurations -deviceConfigurationId $checkConfig.id @configParams } else { New-DeviceManagement_DeviceConfigurations @configParams } } catch { $_.Exception.Message } } } function Merge-maAppLockerXML { [CmdletBinding()] param ( [xml[]]$XMLs ) begin { Write-Verbose "Create new AppLocker xml for output" # create new AppLocker xml $finalXml = New-Object Xml $applockerNode = $finalXml.CreateElement('AppLockerPolicy') $finalXml.AppendChild($applockerNode) | Out-Null $applockerNode.SetAttribute('Version', "1") "Appx", "Dll", "Exe", "Msi", "Script" | ForEach-Object { $node = $finalXml.CreateElement('RuleCollection') $finalXml.AppLockerPolicy.AppendChild($node) | Out-Null $node.SetAttribute('Type', $_) $node.SetAttribute('EnforcementMode', 'NotConfigured') } Write-Verbose $finalXml.OuterXml } process { foreach ($xml in $XMLs) { # validate AppLocker xml if (!$xml.AppLockerPolicy) { Write-Warning "Sry this is not an AppLocker XML"; return } # loop through rulecollection foreach ($collection in $xml.AppLockerPolicy.RuleCollection) { # set enforcementmode $parentNode = $finalXml.AppLockerPolicy.RuleCollection.Where( { $_.Type -eq $collection.Type }) if (($parentNode.EnforcementMode -eq 'NotConfigured') -or ($parentNode.EnforcementMode -eq 'AuditOnly')) { $parentNode.SetAttribute('EnforcementMode', $($collection.EnforcementMode)) } # loop through elements foreach ($element in $collection.ChildNodes) { if ($parentNode.ChildNodes.id -contains $element.Id) { Write-Verbose "Element already present" } else { $node = $finalXml.ImportNode($element, $true) $parentNode.AppendChild($node) | Out-Null Write-Verbose "Element added" } } } } Write-Verbose $finalXml.OuterXml $finalXml } } #rework for Microsoft.Graph.DeviceManagement module function Get-mgIntuneOmaSetPlainValue { param ( $DeviceConfigurationId, $SecretReferenceValueId ) # build url $baseUrl = "https://graph.microsoft.com/beta/deviceManagement/deviceConfigurations/" $configUrl = $baseUrl + $DeviceConfigurationId $plainUrl = $configUrl + "/getOmaSettingPlainTextValue(secretReferenceValueId='$SecretReferenceValueId')" $result = Invoke-mgGraphRequest -Uri $plainUrl return $result.value } function Get-mgIntunePolicy { param ( $PolicyName ) # check for intune module $graphModule = Get-InstalledModule -Name Microsoft.Graph.DeviceManagement -ErrorAction SilentlyContinue if ([string]::IsNullOrEmpty($graphModule)) { Install-Module -Name Microsoft.Graph.DeviceManagement -Force -Confirm:$false } # connect to microsoft graph Connect-MgGraph -Scopes DeviceManagementConfiguration.ReadWrite.All -ErrorAction Stop | Out-Null if ([string]::IsNullOrEmpty($PolicyName)) { Write-Verbose "No Policyname parsed, list available profiles with 'applocker' in name..." $configID = Get-MgDeviceManagementDeviceConfiguration -Filter "contains(displayName,'Applocker')" | Select-Object displayname, description, Id | Out-GridView -Title "Select intune configuration policy" -OutputMode Single | Select-Object -ExpandProperty id } else { Write-Verbose "Query profile with with $PolicyName from Intune" $configID = Get-MgDeviceManagementDeviceConfiguration -Filter "displayName eq '$PolicyName'" | Select-Object -ExpandProperty id } if ([string]::IsNullOrEmpty($configID)) { Write-Warning "Sry, no Intune-Configuration with name $PolicyName found..." break } ## have to use Invoke-mgGraphRequest to get full item with secretReferenceValueId property $baseUrl = "https://graph.microsoft.com/beta/deviceManagement/deviceConfigurations/" $configUrl = $baseUrl + $configID $config = Invoke-mgGraphRequest -Uri $configUrl return $Config } function Get-mgIntunePolicyXML { param ( $PolicyObject ) # create new AppLocker xml $intuneXML = New-Object Xml $applockerNode = $intuneXML.CreateElement('AppLockerPolicy') $intuneXML.AppendChild($applockerNode) | Out-Null $applockerNode.SetAttribute('Version', "1") $PolicyObject.omaSettings | ForEach-Object { $refID = $_.secretReferenceValueId [xml]$xmlToAdd = Get-mgIntuneOmaSetPlainValue $PolicyObject.id $refID $rulesetNode = $intuneXML.ImportNode($xmlToAdd.DocumentElement, $true) $intuneXML.AppLockerPolicy.AppendChild($rulesetNode) | Out-Null } return $intuneXML } #endregion # Backup if ($PSBoundParameters.Keys.Contains("BackupPolicy")) { $LogDate = (Get-Date).ToString("dd.MM.yyyy-HH.mm") $Filename = $env:COMPUTERNAME + "_" + $LogDate + ".xml" if ($PSBoundParameters.BackupPolicy -eq "Intune") { Write-Verbose -Message "Backup Intune policyruleset" $intunePolicy = Get-maIntunePolicy -PolicyName $IntunePolicyName $intunePolicyXML = Get-maIntunePolicyXML -PolicyObject $intunePolicy $intunePolicyXML.Save($(Join-Path -Path $PWD -ChildPath "intune_$Filename")) } elseif ($PSBoundParameters.BackupPolicy -eq "Domain") { Write-Verbose -Message "Backup domain policyruleset" $LDAPPath = Get-maLDAPPath [xml]$domainPolicyXML = Get-AppLockerPolicy -Ldap $LDAPPath -Domain -Xml $domainPolicyXML.Save($(Join-Path -Path $PWD -ChildPath "domain_$Filename")) } else { Write-Verbose -Message "Backup local policyruleset" [xml]$localPolicyXML = Get-AppLockerPolicy -Local -Xml $localPolicyXML.Save($(Join-Path -Path $PWD -ChildPath "local_$Filename")) } } # Report if ($ReportFromForwarded.IsPresent) { Write-Verbose -Message "Create Report from forwarded eventlog and pipe to ogw" Get-AppLockerFileInformation -EventLog -LogPath ForwardedEvents | Out-GridView } if ($ReportFromForwardedWithStatistic.IsPresent) { Write-Verbose -Message "Create Report with statistics from forwarded eventlog and pipe to ogw" Get-AppLockerFileInformation -EventLog -LogPath ForwardedEvents -Statistics | Out-GridView } # Create if ($CreateDefaultPolicy.IsPresent) { if ($Intune.IsPresent) { try { if ([string]::IsNullOrEmpty($IntunePolicyName)) { $IntunePolicyName = 'Configure - AppLocker policy via mdm' Write-Verbose -Message "No Intune profilename entered, default value: $IntunePolicyName" } Write-Verbose -Message "Create default AppLocker policy in Intune" Publish-maIntunePolicy -PolicyName $IntunePolicyName -AppLockerXML $defaultAppLockerRulesXML } catch { $_.Exception.Message } } elseif ($Domain.IsPresent) { try { Write-Verbose -Message "Create default AppLocker policy on group policy for domain" $tempXmlFile = Join-Path -Path $env:TEMP -ChildPath defaultrules.xml $LDAPPath = Get-maLDAPPath $defaultAppLockerRulesXML.Save($tempXmlFile) Set-AppLockerPolicy -XmlPolicy $tempXmlFile -Ldap $LDAPPath Remove-Item -Path $tempXmlFile -Force } catch { $_.Exception.Message } } elseif ($File.IsPresent) { try { Write-Verbose -Message "Create default AppLocker policy xml file on $Path" $defaultAppLockerRulesXML.Save($Path) } catch { $_.Exception.Message } } else { Write-Verbose -Message "Create default AppLocker policy on local device" $tempXmlFile = Join-Path -Path $env:TEMP -ChildPath defaultrules.xml $defaultAppLockerRulesXML.Save($tempXmlFile) Set-AppLockerPolicy -XmlPolicy $tempXmlFile Remove-Item -Path $tempXmlFile -Force secpol.msc } } # Merge if ($Merge.IsPresent) { if ($Intune.IsPresent) { try { $intunePolicy = Get-maIntunePolicy -PolicyName $IntunePolicyName $intunePolicyXML = Get-maIntunePolicyXML -PolicyObject $intunePolicy Write-Verbose "Receive AppLockerInformation from eventlog" $newRules = Select-maAppLockerRules $mergeXML = $newRules | New-AppLockerPolicy -RuleType $(Select-maRuletype) -IgnoreMissingFileInformation -Optimize -Xml $finalXML = Merge-maAppLockerXML -XMLs $intunePolicyXML, $mergeXML Write-Verbose -Message "Merged selected rules with existing rules in Intune `n$($finalXML.OuterXml)" Publish-maIntunePolicy -AppLockerXML $finalXML -PolicyName $IntunePolicyName } catch { $_.Exception.Message } } elseif ($Domain.IsPresent) { try { $LDAPPath = Get-maLDAPPath Write-Verbose -Message "Merge selected rules with existing rules and apply to local policy" $newRules = Select-maAppLockerRules $newRules | New-AppLockerPolicy -RuleType $(Select-maRuletype) -User $User -IgnoreMissingFileInformation -Optimize | Set-AppLockerPolicy -Ldap $LDAPPath -Merge } catch { $_.Exception.Message } } elseif ($File.IsPresent) { try { [xml]$filePolicyXML = Get-Content -Path $Path Write-Verbose -Message "Merge selected rules with existing rules in target file" $newRules = Select-maAppLockerRules $mergeXML = $newRules | New-AppLockerPolicy -RuleType $(Select-maRuletype) -IgnoreMissingFileInformation -Optimize -Xml $finalXML = Merge-maAppLockerXML -XMLs $filePolicyXML, $mergeXML Write-Verbose -Message "Merged selected rules with existing rules on target file" $finalXML.Save($Path) } catch { $_.Exception.Message } } else { Write-Verbose -Message "Merge selected rules with existing rules and apply to local policy" $newRules = Select-maAppLockerRules $newRules | New-AppLockerPolicy -RuleType $(Select-maRuletype) -User $User -IgnoreMissingFileInformation -Optimize | Set-AppLockerPolicy -Merge } } # Apply if ($ApplyToLocal.IsPresent) { if ($Intune.IsPresent) { try { Write-Verbose -Message "Apply Intune policy to local policy" $intunePolicy = Get-mgIntunePolicy -PolicyName $IntunePolicyName $intunePolicyXML = Get-mgIntunePolicyXML -PolicyObject $intunePolicy # apply intune to local $intunePolicyXML.OuterXml | Out-File -FilePath $env:TEMP\applockerFile.xml -Force Set-AppLockerPolicy -XmlPolicy $env:TEMP\applockerFile.xml Remove-Item -Path $env:TEMP\applockerFile.xml -Force secpol.msc } catch { $_.Exception.Message } } elseif ($Domain.IsPresent) { try { Write-Verbose -Message "Apply domain policy to local policy" $LDAPPath = Get-maLDAPPath # apply intune to local Get-AppLockerPolicy -Domain -Ldap $LDAPPath | Set-AppLockerPolicy secpol.msc } catch { $_.Exception.Message } } # else file mode (already filtered by parameterset) else { try { Write-Verbose -Message "Apply ruleset from AppLocker file localy" Set-AppLockerPolicy -XmlPolicy $Path secpol.msc } catch { $_.Exception.Message } } } # Publish if ($PulishLocalPolicy.IsPresent) { if ($Intune.IsPresent) { try { $intunePolicy = Get-maIntunePolicy -PolicyName $IntunePolicyName Write-Verbose -Message "Get local policy rules" [xml]$localPolicyXML = Get-AppLockerPolicy -Local -Xml Write-Verbose -Message "Upload local policy rules to Intune" Publish-maIntunePolicy -AppLockerXML $localPolicyXML -PolicyName $intunePolicy.displayName } catch { $_.Exception.Message } } elseif ($Domain.IsPresent) { try { $LDAPPath = Get-maLDAPPath Write-Verbose -Message "Get local policy rules" $localPolicy = Get-AppLockerPolicy -Local Write-Verbose -Message "Upload local policy to domain" $localPolicy | Set-AppLockerPolicy -Domain -Ldap $LDAPPath } catch { $_.Exception.Message } } # else file mode (already filtered by parameterset) else { try { Write-Verbose -Message "Get local ruleset" [xml]$localPolicyXML = Get-AppLockerPolicy -Local -Xml Write-Verbose -Message "Override target file $($Path.Fullname) with new one" $localPolicyXML.Save($Path) } catch { $_.Exception.Message } } } # Switch if ($SwitchEnforcementMode.IsPresent) { if ($Intune.IsPresent) { Write-Verbose "Query device configuration profiles" $editPolicy = Get-maIntunePolicy $editXML = Get-maIntunePolicyXML -PolicyObject $editPolicy # select/edit enforcementmode $enforcementMode = Select-maEnforcementMode $editXML.AppLockerPolicy.RuleCollection | Out-GridView -Title "Select ruleset you want to edit" -PassThru | ForEach-Object { $_.EnforcementMode = "$enforcementMode" } # upload new configuration Publish-maIntunePolicy -AppLockerXML $editXML -PolicyName $editPolicy.displayName } elseif ($Domain.IsPresent) { try { Write-Verbose -Message "Query group policy's" $LDAPPath = Get-maLDAPPath [xml]$editXML = Get-AppLockerPolicy -Ldap $LDAPPath -Xml # select/edit enforcementmode $enforcementMode = Select-maEnforcementMode $editXML.AppLockerPolicy.RuleCollection | Out-GridView -Title "Select ruleset you want to edit" -PassThru | ForEach-Object { $_.EnforcementMode = "$enforcementMode" } # save file temporarily $tempXmlFile = Join-Path -Path $env:TEMP -ChildPath defaultrules.xml $editXML.Save($tempXmlFile) # Set domain policy Set-AppLockerPolicy -Ldap $LDAPPath -XmlPolicy $tempXmlFile Remove-Item -Path $tempXmlFile -Force } catch { $_.Exception.Message } } elseif ($File.IsPresent) { try { Write-Verbose -Message "Query group policy's" [xml]$editXML = Get-Content -Path $Path # select/edit enforcementmode $enforcementMode = Select-maEnforcementMode $editXML.AppLockerPolicy.RuleCollection | Out-GridView -Title "Select ruleset you want to edit" -PassThru | ForEach-Object { $_.EnforcementMode = "$enforcementMode" } Write-Verbose -Message "Save changes if done" $editXML.Save($Path) } catch { $_.Exception.Message } } else { try { Write-Verbose -Message "Merge selected rules with existing rules and apply to local policy" [xml]$editXML = Get-AppLockerPolicy -Local -Xml # select/edit enforcementmode $enforcementMode = "NotConfigured", "AuditOnly", "Enabled" | Out-GridView -Title "Select your enforcementmode, witch you want to set" -OutputMode Single if (!$enforcementmode) { Write-Warning "Sry, you have to select an enforcementmode"; break } $editXML.AppLockerPolicy.RuleCollection | Out-GridView -Title "Select ruleset you want to edit" -PassThru | ForEach-Object { $_.EnforcementMode = "$enforcementMode" } # save file temporarily $tempXmlFile = Join-Path -Path $env:TEMP -ChildPath editrules.xml $editXML.Save($tempXmlFile) # Set domain policy Set-AppLockerPolicy -XmlPolicy $tempXmlFile Remove-Item -Path $tempXmlFile -Force } catch { $_.Exception.Message } } } # Return if ($ReturnXML.IsPresent) { if ($Intune.IsPresent) { try { Write-Verbose -Message "Return Intune XML AppLocker policy in Intune" $intunePolicy = Get-maIntunePolicy -PolicyName $IntunePolicyName $intunePolicyXML = Get-maIntunePolicyXML -PolicyObject $intunePolicy return $intunePolicyXML } catch { $_.Exception.Message } } elseif ($Domain.IsPresent) { try { Write-Verbose -Message "Return domain XML AppLocker policy" $LDAPPath = Get-maLDAPPath [xml]$domainPolicyXML = Get-AppLockerPolicy -Ldap $LDAPPath -Domain -Xml return $domainPolicyXML } catch { $_.Exception.Message } } # else local mode (already filtered by parameterset) else { Write-Verbose -Message "Return local XML AppLocker policy" [xml]$localPolicyXML = Get-AppLockerPolicy -Local -Xml return $localPolicyXML } } # Cleanup if ($CleanupLocalPolicy.IsPresent) { try { Set-AppLockerPolicy -PolicyObject ([Microsoft.Security.ApplicationId.PolicyManagement.PolicyModel.AppLockerPolicy]::new()) Write-Verbose "Cleaning local AppLocker policy successfully" } catch { } } if ($CleanupLocalMDMPolicy.IsPresent) { try { Write-Verbose "Cleaning local MDM AppLocker policy" $namespaceName = "root\cimv2\mdm\dmmap" $GroupName = "AppLockerMDM" $parentID = "./Vendor/MSFT/AppLocker/ApplicationLaunchRestrictions/$GroupName" @( "MDM_AppLocker_ApplicationLaunchRestrictions01_StoreApps03" "MDM_AppLocker_DLL03" "MDM_AppLocker_ApplicationLaunchRestrictions01_EXE03" "MDM_AppLocker_MSI03" "MDM_AppLocker_Script03" ) | ForEach-Object { Write-Verbose "Checking for instance in $_" if ($curInstance = Get-CimInstance -Namespace $namespaceName -ClassName $_) { Write-Verbose "Cleanup MDM policy for class $($_)" Remove-CimInstance -InputObject $curInstance } } Write-Verbose "All AppLocker MDM policy's removed from local device, removing files from AppLocker folder" Remove-Item -Path $(Join-Path -Path $env:windir -ChildPath "system32\AppLocker\*") -Recurse -Force Write-Warning "Cleanup done, don't forget to reboot the device" } catch { $_.Exception.Message } } # Build bridge script if ($BuildBridgeScript.IsPresent) { # create script for wmi-bridge based deployment's from fileshare/url $scriptBlock = { [CmdletBinding()] # init $Source = $XmlSource $namespaceName = "root\cimv2\mdm\dmmap" $GroupName = "AppLockerMDM" $parentID = "./Vendor/MSFT/AppLocker/ApplicationLaunchRestrictions/$GroupName" $taskName = "runScriptAsSystem" $unsAsSystem = $env:USERNAME -match $env:COMPUTERNAME # using wmi bridge required system permissions if (!$unsAsSystem) { # enable manual invokation $action = New-ScheduledTaskAction -Execute "Powershell.exe" -Argument "-NoProfile -ExecutionPolicy bypass -WindowStyle Hidden -File $($MyInvocation.MyCommand.Source)" $task = Register-ScheduledTask -User SYSTEM -Action $action -TaskName $taskName -Force Start-ScheduledTask -InputObject $task } else { try { $ErrorActionPreference = 'stop' Add-Type -AssemblyName System.Web # start logging Start-Transcript -Path $(Join-Path -Path C:\ -ChildPath "$($MyInvocation.MyCommand.Name).log") # validate source if ($Source -match '://.*\.xml') { Write-Verbose "Loading xml content from url $Source" [xml]$policyXML = (New-Object System.Net.WebClient).DownloadString($Source) } elseif ($Source -match '\\\\.*\.xml|:\\.*\.xml') { Write-Verbose "Loading xml content from smbshare $Source" [xml]$policyXML = Get-Content -Path $Source } else { Write-Warning "Could not validate your source, make sure that your source ends with .xml, only url's and smbshare's are supported" break } $policyXML.AppLockerPolicy.RuleCollection | Where-Object EnforcementMode -NE "NotConfigured" | ForEach-Object { Write-Verbose "Create ruleset for $($_.Type)" Write-Verbose "Processing XML for $($_.Type) : `n$($_.OuterXml)" switch ($_.Type) { Appx { $className = "MDM_AppLocker_ApplicationLaunchRestrictions01_StoreApps03"; break } Dll { $className = "MDM_AppLocker_DLL03"; break } Exe { $className = "MDM_AppLocker_ApplicationLaunchRestrictions01_EXE03"; break } Msi { $className = "MDM_AppLocker_MSI03"; break } Script { $className = "MDM_AppLocker_Script03"; break } } # Check for existing mdm policy's if ($curInstance = Get-CimInstance -Namespace $namespaceName -ClassName $className) { Write-Verbose "MDM policy for $($_.Type) already exists, deleting before reapply" Remove-CimInstance -InputObject $curInstance } $instanceID = $className.Split('_|03', [System.StringSplitOptions]::RemoveEmptyEntries)[-1] $encodeObj = [System.Net.WebUtility]::HtmlEncode($_.OuterXml) New-CimInstance -Namespace $namespaceName ` -ClassName $className ` -Property @{ ParentID = $parentID InstanceID = $instanceID Policy = $encodeObj } } } catch { $_.Exception.Message } finally { # cleanup scheduled task Get-ScheduledTask -TaskName $taskName | Unregister-ScheduledTask -Confirm:$false Stop-Transcript } } } # export scriptblock as standalone script $scriptBlock.ToString().Replace( '$XmlSource', "`"$XmlSource`"" ) | Out-File $ScriptPath } |