141 lines
5.9 KiB
PowerShell
141 lines
5.9 KiB
PowerShell
#Requires -Modules 'NetSecurity'
|
|
Param(
|
|
[Parameter(Mandatory)]
|
|
[hashtable]$Parameter
|
|
)
|
|
|
|
# Only executed on primary or standalone Domain Controller
|
|
If (@('primary','standalone') -contains $Parameter['deployment.type']) {
|
|
$GetItemSplat = @{
|
|
Path = "$($PSScriptRoot)\$($MyInvocation.MyCommand)".Replace('.ps1', '.yml')
|
|
}
|
|
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
|
|
}
|
|
Catch {
|
|
$ParseErrors += "While processing '$($File)': $($_.Exception.Message)"
|
|
Continue
|
|
}
|
|
|
|
# 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
|
|
}
|
|
|
|
$Settings = $YamlDocuments[0..($YamlDocuments.Count - 2)]
|
|
}
|
|
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
|
|
}
|
|
}
|
|
}
|
|
If ($ParseErrors) {
|
|
Throw "One or more errors occurred:`n$($ParseErrors -join "`n")"
|
|
}
|
|
}
|