Separate firewall configuration between linked OUs
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
ed69de5d27
commit
f8a8cb80c8
@ -1,3 +1,6 @@
|
||||
Name: 'COMP: Firewall (Clients)'
|
||||
LinkedOUs:
|
||||
- OU=Clients,OU=Computer accounts
|
||||
FirewallRules:
|
||||
- Description: Rule A
|
||||
Action: Block
|
@ -0,0 +1,65 @@
|
||||
Name: 'COMP: Firewall (DomainControllers)'
|
||||
LinkedOUs:
|
||||
- OU=Domain Controllers
|
||||
FirewallRules:
|
||||
- Description: Rule A
|
||||
Action: Block
|
||||
Direction: Inbound
|
||||
Program: ''
|
||||
Port: '21-22,25'
|
||||
Protocol: TCP
|
||||
- Description: Rule B
|
||||
Action: Allow
|
||||
Direction: Inbound
|
||||
Program: D:\MSSQL\sqlsvr.exe
|
||||
Port: ''
|
||||
Protocol: ''
|
||||
FirewallProfiles:
|
||||
- Name: Domain
|
||||
Enabled: 'True'
|
||||
Connections:
|
||||
Inbound: Block
|
||||
Outbound: Allow
|
||||
Settings:
|
||||
DisplayNotification: 'False'
|
||||
ApplyLocalFirewallRules: 'True'
|
||||
ApplyLocalConnectionSecurityRules: 'True'
|
||||
Logging:
|
||||
Name: '%SYSTEMROOT%\System32\Logfiles\Firewall\domainfw.log'
|
||||
SizeLimit: 16384
|
||||
LogDroppedPackets: 'True'
|
||||
LogSuccessfullConnections: 'False'
|
||||
- Name: Private
|
||||
Enabled: 'True'
|
||||
Connections:
|
||||
Inbound: Block
|
||||
Outbound: Allow
|
||||
Settings:
|
||||
DisplayNotification: 'False'
|
||||
ApplyLocalFirewallRules: 'True'
|
||||
ApplyLocalConnectionSecurityRules: 'True'
|
||||
Logging:
|
||||
Name: '%SYSTEMROOT%\System32\Logfiles\Firewall\privatefw.log'
|
||||
SizeLimit: 16384
|
||||
LogDroppedPackets: 'True'
|
||||
LogSuccessfullConnections: 'False'
|
||||
- Name: Public
|
||||
Enabled: 'True'
|
||||
Connections:
|
||||
Inbound: Block
|
||||
Outbound: Allow
|
||||
Settings:
|
||||
DisplayNotification: 'False'
|
||||
ApplyLocalFirewallRules: 'True'
|
||||
ApplyLocalConnectionSecurityRules: 'True'
|
||||
Logging:
|
||||
Name: '%SYSTEMROOT%\System32\Logfiles\Firewall\publicfw.log'
|
||||
SizeLimit: 16384
|
||||
LogDroppedPackets: 'True'
|
||||
LogSuccessfullConnections: 'False'
|
||||
|
||||
# ---
|
||||
# Variables:
|
||||
# - Name: foo
|
||||
# Expression: |
|
||||
# Write-Host 'bar'
|
@ -6,104 +6,135 @@ Param(
|
||||
|
||||
# Only executed on primary or standalone Domain Controller
|
||||
If (@('primary','standalone') -contains $Parameter['deployment.type']) {
|
||||
$GetContentSplat = @{
|
||||
$GetItemSplat = @{
|
||||
Path = "$($PSScriptRoot)\$($MyInvocation.MyCommand)".Replace('.ps1', '.yml')
|
||||
Raw = $true
|
||||
}
|
||||
$RawContent = Get-Content @GetContentSplat
|
||||
$ConvertFromYamlSplat = @{
|
||||
Yaml = $RawContent
|
||||
AllDocuments = $True
|
||||
}
|
||||
$YamlDocuments = ConvertFrom-Yaml @ConvertFromYamlSplat
|
||||
|
||||
# Check if the respective .yml file declared substitutions which need to be parsed
|
||||
If (($YamlDocuments.Count -gt 1) -and $YamlDocuments[-1].Variables) {
|
||||
ForEach ($Pattern in $YamlDocuments[-1].Variables) {
|
||||
$RawContent = $RawContent -replace "\{\{ ($($Pattern.Name)) \}\}", [string](Invoke-Expression -Command $Pattern.Expression)
|
||||
ForEach ($File in (Get-Item @GetItemSplat)) {
|
||||
Try {
|
||||
Write-Host "Loading/parsing file '$($File)' ..."
|
||||
$GetContentSplat = @{
|
||||
Path = $File
|
||||
Raw = $True
|
||||
}
|
||||
$RawContent = Get-Content @GetContentSplat
|
||||
$ConvertFromYamlSplat = @{
|
||||
Yaml = $RawContent
|
||||
AllDocuments = $True
|
||||
}
|
||||
$YamlDocuments = ConvertFrom-Yaml @ConvertFromYamlSplat
|
||||
}
|
||||
# Perform conversion to Yaml again, now with parsed file contents
|
||||
$ConvertFromYamlSplat = @{
|
||||
Yaml = $RawContent
|
||||
AllDocuments = $True
|
||||
Catch {
|
||||
$ParseErrors += "While processing '$($File)': $($_.Exception.Message)"
|
||||
Continue
|
||||
}
|
||||
$YamlDocuments = ConvertFrom-Yaml @ConvertFromYamlSplat
|
||||
$Settings = $YamlDocuments[0..($YamlDocuments.Count - 2)]
|
||||
}
|
||||
Else {
|
||||
$Settings = $YamlDocuments
|
||||
}
|
||||
|
||||
# Check if the respective .yml file declared substitutions which need to be parsed
|
||||
If (($YamlDocuments.Count -gt 1) -and $YamlDocuments[-1].Variables) {
|
||||
Try {
|
||||
ForEach ($Pattern in $YamlDocuments[-1].Variables) {
|
||||
$RawContent = $RawContent -replace "\{\{ ($($Pattern.Name)) \}\}", [string](Invoke-Expression -Command $Pattern.Expression)
|
||||
}
|
||||
# Perform conversion to Yaml again, now with parsed file contents
|
||||
$ConvertFromYamlSplat = @{
|
||||
Yaml = $RawContent
|
||||
AllDocuments = $True
|
||||
}
|
||||
$YamlDocuments = ConvertFrom-Yaml @ConvertFromYamlSplat
|
||||
}
|
||||
Catch {
|
||||
$ParseErrors += "While processing '$($File)' (after substitutions): $($_.Exception.Message)"
|
||||
Continue
|
||||
}
|
||||
|
||||
$NewGPOSplat = @{
|
||||
Name = 'COMP: Firewall (Servers)'
|
||||
}
|
||||
$NewGPO = New-GPO @NewGPOSplat
|
||||
|
||||
$OpenNetGPOSplat = @{
|
||||
PolicyStore = "$($Parameter['addsconfig.domainname'])\$($NewGPO.DisplayName)"
|
||||
}
|
||||
$GPOSession = Open-NetGPO @OpenNetGPOSplat
|
||||
|
||||
ForEach ($Rule in $Settings.FirewallRules) {
|
||||
$NewNetFirewallRuleSplat = @{
|
||||
# Using so-called string formatting with the '-f' operator (looks more complicated than it is) to create consistent policy names:
|
||||
# Examples:
|
||||
# 'DENY: Inbound port 443 (TCP)'
|
||||
# 'ALLOW: Inbound 'D:\MSSQL\bin\sqlservr.exe'
|
||||
DisplayName = ("{0}: {1} {2} {3} {4}" -f
|
||||
$Rule.Action.ToUpper(),
|
||||
$Rule.Direction,
|
||||
("'$($Rule.Program)'", $NULL)[!($Rule.Program)],
|
||||
("Port $($Rule.Port)", $NULL)[!($Rule.Port)],
|
||||
("($($Rule.Protocol))", $NULL)[!($Rule.Protocol)]
|
||||
) -replace '\s+',' '
|
||||
Description = $Rule.Description
|
||||
Action = $Rule.Action
|
||||
Direction = $Rule.Direction
|
||||
Program = ($Rule.Program, 'Any')[!($Rule.Program)]
|
||||
LocalPort = ($Rule.Port.Split(','), 'Any')[!($Rule.Port)]
|
||||
Protocol = ($Rule.Protocol, 'Any')[!($Rule.Protocol)]
|
||||
GPOSession = $GPOSession
|
||||
PolicyStore = $NewGPO.DisplayName
|
||||
Confirm = $False
|
||||
$Settings = $YamlDocuments[0..($YamlDocuments.Count - 2)]
|
||||
}
|
||||
New-NetFirewallRule @NewNetFirewallRuleSplat
|
||||
}
|
||||
|
||||
ForEach ($Profile in $Settings.FirewallProfiles) {
|
||||
$SetNetFirewallProfileSplat = @{
|
||||
Name = $Profile.Name
|
||||
Enabled = $Profile.Enabled
|
||||
DefaultInboundAction = $Profile.Connections.Inbound
|
||||
DefaultOutboundAction = $Profile.Connections.Outbound
|
||||
LogAllowed = $Profile.Logging.LogSuccessfullConnections
|
||||
LogBlocked = $Profile.Logging.LogDroppedPackets
|
||||
LogFileName = $Profile.Logging.Name
|
||||
LogMaxSizeKilobytes = $Profile.Logging.SizeLimit
|
||||
AllowLocalFirewallRules = $Profile.Settings.ApplyLocalFirewallRules
|
||||
AllowLocalIPsecRules = $Profile.Settings.ApplyLocalConnectionSecurityRules
|
||||
NotifyOnListen = $Profile.Settings.DisplayNotification
|
||||
GPOSession = $GPOSession
|
||||
PolicyStore = $NewGPO.DisplayName
|
||||
Confirm = $False
|
||||
Else {
|
||||
$Settings = $YamlDocuments
|
||||
}
|
||||
|
||||
$NewGPOSplat = @{
|
||||
Name = $Settings.Name
|
||||
}
|
||||
$NewGPO = New-GPO @NewGPOSplat
|
||||
|
||||
$OpenNetGPOSplat = @{
|
||||
PolicyStore = "$($Parameter['addsconfig.domainname'])\$($NewGPO.DisplayName)"
|
||||
}
|
||||
$GPOSession = Open-NetGPO @OpenNetGPOSplat
|
||||
|
||||
ForEach ($Rule in $Settings.FirewallRules) {
|
||||
$NewNetFirewallRuleSplat = @{
|
||||
# Using so-called string formatting with the '-f' operator (looks more complicated than it is) to create consistent policy names:
|
||||
# Examples:
|
||||
# 'DENY: Inbound port 443 (TCP)'
|
||||
# 'ALLOW: Inbound 'D:\MSSQL\bin\sqlservr.exe'
|
||||
DisplayName = ("{0}: {1} {2} {3} {4}" -f
|
||||
$Rule.Action.ToUpper(),
|
||||
$Rule.Direction,
|
||||
("'$($Rule.Program)'", $NULL)[!($Rule.Program)],
|
||||
("Port $($Rule.Port)", $NULL)[!($Rule.Port)],
|
||||
("($($Rule.Protocol))", $NULL)[!($Rule.Protocol)]
|
||||
) -replace '\s+',' '
|
||||
Description = $Rule.Description
|
||||
Action = $Rule.Action
|
||||
Direction = $Rule.Direction
|
||||
Program = ($Rule.Program, 'Any')[!($Rule.Program)]
|
||||
LocalPort = ($Rule.Port.Split(','), 'Any')[!($Rule.Port)]
|
||||
Protocol = ($Rule.Protocol, 'Any')[!($Rule.Protocol)]
|
||||
GPOSession = $GPOSession
|
||||
PolicyStore = $NewGPO.DisplayName
|
||||
Confirm = $False
|
||||
}
|
||||
New-NetFirewallRule @NewNetFirewallRuleSplat
|
||||
}
|
||||
|
||||
ForEach ($Profile in $Settings.FirewallProfiles) {
|
||||
$SetNetFirewallProfileSplat = @{
|
||||
Name = $Profile.Name
|
||||
Enabled = $Profile.Enabled
|
||||
DefaultInboundAction = $Profile.Connections.Inbound
|
||||
DefaultOutboundAction = $Profile.Connections.Outbound
|
||||
LogAllowed = $Profile.Logging.LogSuccessfullConnections
|
||||
LogBlocked = $Profile.Logging.LogDroppedPackets
|
||||
LogFileName = $Profile.Logging.Name
|
||||
LogMaxSizeKilobytes = $Profile.Logging.SizeLimit
|
||||
AllowLocalFirewallRules = $Profile.Settings.ApplyLocalFirewallRules
|
||||
AllowLocalIPsecRules = $Profile.Settings.ApplyLocalConnectionSecurityRules
|
||||
NotifyOnListen = $Profile.Settings.DisplayNotification
|
||||
GPOSession = $GPOSession
|
||||
PolicyStore = $NewGPO.DisplayName
|
||||
Confirm = $False
|
||||
}
|
||||
Set-NetFirewallProfile @SetNetFirewallProfileSplat
|
||||
}
|
||||
|
||||
$SaveNetGPOSplat = @{
|
||||
GPOSession = $GPOSession
|
||||
}
|
||||
Save-NetGPO @SaveNetGPOSplat
|
||||
|
||||
ForEach ($OU in $Settings.LinkedOUs) {
|
||||
If (Test-Path "AD:\$($OU + (',{0}' -f (Get-ADRootDSE).rootDomainNamingContext))") {
|
||||
Try {
|
||||
Write-Host "Linking policy '$($NewGPO.DisplayName)' to OU '$($OU)' ..."
|
||||
$NewGPLinkSplat = @{
|
||||
Name = $NewGPO.DisplayName
|
||||
Target = $OU + (',{0}' -f (Get-ADRootDSE).rootDomainNamingContext)
|
||||
}
|
||||
New-GPLink @NewGPLinkSplat | Out-Null
|
||||
}
|
||||
Catch {
|
||||
$ParseErrors += "Could not link GPO '$($NewGPO.DisplayName)' to OU '$($OU)'"
|
||||
Continue
|
||||
}
|
||||
}
|
||||
Else {
|
||||
$ParseErrors += "Path not accessible (referred to by '$($NewGPO.DisplayName)'): 'AD:\$($OU + (',{0}' -f (Get-ADRootDSE).rootDomainNamingContext))'"
|
||||
Continue
|
||||
}
|
||||
}
|
||||
Set-NetFirewallProfile @SetNetFirewallProfileSplat
|
||||
}
|
||||
|
||||
$SaveNetGPOSplat = @{
|
||||
GPOSession = $GPOSession
|
||||
If ($ParseErrors) {
|
||||
Throw "One or more errors occurred:`n$($ParseErrors -join "`n")"
|
||||
}
|
||||
Save-NetGPO @SaveNetGPOSplat
|
||||
|
||||
$NewGPLinkSplat = @{
|
||||
Name = $NewGPO.DisplayName
|
||||
# Should probably be configurable through yml
|
||||
Target = 'OU=Servers,OU=Computer accounts,DC=' + $Parameter['addsconfig.domainname'].Replace('.', ',DC=')
|
||||
}
|
||||
New-GPLink @NewGPLinkSplat
|
||||
$NewGPLinkSplat = @{
|
||||
Name = $NewGPO.DisplayName
|
||||
Target = 'OU=Domain Controllers,DC=' + $Parameter['addsconfig.domainname'].Replace('.', ',DC=')
|
||||
}
|
||||
New-GPLink @NewGPLinkSplat
|
||||
}
|
||||
|
65
scripts/ADDS/payload/scripts/05.Firewall.servers.yml
Normal file
65
scripts/ADDS/payload/scripts/05.Firewall.servers.yml
Normal file
@ -0,0 +1,65 @@
|
||||
Name: 'COMP: Firewall (Servers)'
|
||||
LinkedOUs:
|
||||
- OU=Servers,OU=Computer accounts
|
||||
FirewallRules:
|
||||
- Description: Rule A
|
||||
Action: Block
|
||||
Direction: Inbound
|
||||
Program: ''
|
||||
Port: '21-22,25'
|
||||
Protocol: TCP
|
||||
- Description: Rule B
|
||||
Action: Allow
|
||||
Direction: Inbound
|
||||
Program: D:\MSSQL\sqlsvr.exe
|
||||
Port: ''
|
||||
Protocol: ''
|
||||
FirewallProfiles:
|
||||
- Name: Domain
|
||||
Enabled: 'True'
|
||||
Connections:
|
||||
Inbound: Block
|
||||
Outbound: Allow
|
||||
Settings:
|
||||
DisplayNotification: 'False'
|
||||
ApplyLocalFirewallRules: 'True'
|
||||
ApplyLocalConnectionSecurityRules: 'True'
|
||||
Logging:
|
||||
Name: '%SYSTEMROOT%\System32\Logfiles\Firewall\domainfw.log'
|
||||
SizeLimit: 16384
|
||||
LogDroppedPackets: 'True'
|
||||
LogSuccessfullConnections: 'False'
|
||||
- Name: Private
|
||||
Enabled: 'True'
|
||||
Connections:
|
||||
Inbound: Block
|
||||
Outbound: Allow
|
||||
Settings:
|
||||
DisplayNotification: 'False'
|
||||
ApplyLocalFirewallRules: 'True'
|
||||
ApplyLocalConnectionSecurityRules: 'True'
|
||||
Logging:
|
||||
Name: '%SYSTEMROOT%\System32\Logfiles\Firewall\privatefw.log'
|
||||
SizeLimit: 16384
|
||||
LogDroppedPackets: 'True'
|
||||
LogSuccessfullConnections: 'False'
|
||||
- Name: Public
|
||||
Enabled: 'True'
|
||||
Connections:
|
||||
Inbound: Block
|
||||
Outbound: Allow
|
||||
Settings:
|
||||
DisplayNotification: 'False'
|
||||
ApplyLocalFirewallRules: 'True'
|
||||
ApplyLocalConnectionSecurityRules: 'True'
|
||||
Logging:
|
||||
Name: '%SYSTEMROOT%\System32\Logfiles\Firewall\publicfw.log'
|
||||
SizeLimit: 16384
|
||||
LogDroppedPackets: 'True'
|
||||
LogSuccessfullConnections: 'False'
|
||||
|
||||
# ---
|
||||
# Variables:
|
||||
# - Name: foo
|
||||
# Expression: |
|
||||
# Write-Host 'bar'
|
Loading…
Reference in New Issue
Block a user