15 Commits

Author SHA1 Message Date
a57c64a04a Fix plugin version constraint
All checks were successful
continuous-integration/drone/push Build is passing
2021-06-04 22:39:07 +02:00
d3802bba75 Remove redundant feedback 2021-06-04 22:35:56 +02:00
ae98042e4e Housekeeping;Add debugging information
All checks were successful
continuous-integration/drone/push Build is passing
2021-06-04 22:31:53 +02:00
f36f452a59 Remove redundant variable;Fix path
All checks were successful
continuous-integration/drone/push Build is passing
2021-06-04 22:17:55 +02:00
b0615f11d1 Migrate to HCL;Add packer init step;Add variable definitions
Some checks failed
continuous-integration/drone/push Build is failing
2021-06-04 22:16:06 +02:00
483013270d Allow multiple OU's for Delegation of Control
All checks were successful
continuous-integration/drone/push Build is passing
2021-05-03 14:18:58 +02:00
aa2c05df3f Fix yamllint errors #2
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-09 11:25:36 +02:00
280d3e2258 Fix yamllint errors;change yamllint config
Some checks failed
continuous-integration/drone/push Build is failing
2021-04-09 11:24:46 +02:00
632caa89ef Switch yamllint configuration to 'relaxed'
Some checks failed
continuous-integration/drone/push Build is failing
2021-04-09 11:03:40 +02:00
c04081bac1 Add image pull policy
Some checks failed
continuous-integration/drone/push Build is failing
2021-04-09 10:59:46 +02:00
ae1a263129 Add yaml linting step
Some checks failed
continuous-integration/drone/push Build is failing
2021-04-09 10:56:48 +02:00
f8a8cb80c8 Separate firewall configuration between linked OUs
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-08 17:13:24 +02:00
ed69de5d27 Add errorhandling;Fix OU
All checks were successful
continuous-integration/drone/push Build is passing
2021-03-27 08:56:26 +01:00
9dfb51db18 Update hypervisor FQDN
All checks were successful
continuous-integration/drone/push Build is passing
2021-03-24 15:25:16 +01:00
b02dcfa717 Fix switch regex match;Add GPO link debugging 2021-03-24 11:19:27 +01:00
22 changed files with 502 additions and 281 deletions

View File

@ -3,24 +3,35 @@ type: kubernetes
name: 'Packer Build'
steps:
- name: Active Directory Domain Services
- name: Debugging information
image: bv11-cr01.bessems.eu/library/packer-extended
commands:
- yamllint --version
- packer --version
- pwsh --version
- ovftool --version
- name: Active Directory Domain Services
image: bv11-cr01.bessems.eu/library/packer-extended
pull: always
commands:
- |
yamllint -d "{extends: relaxed, rules: {line-length: disable}}" scripts
- |
packer init -upgrade \
./packer
- |
packer validate \
-var-file=packer/variables.vsphere.json \
-var vm_name=$DRONE_BUILD_NUMBER-${DRONE_COMMIT_SHA:0:10} \
-var vsphere_password=$${VSPHERE_PASSWORD} \
-var winrm_password=$${WINRM_PASSWORD} \
packer/adds.json
./packer
- |
packer build \
-on-error=cleanup \
-var-file=packer/variables.vsphere.json \
-on-error=cleanup -timestamp-ui \
-var vm_name=$DRONE_BUILD_NUMBER-${DRONE_COMMIT_SHA:0:10} \
-var vsphere_password=$${VSPHERE_PASSWORD} \
-var winrm_password=$${WINRM_PASSWORD} \
packer/adds.json
./packer
environment:
VSPHERE_PASSWORD:
from_secret: vsphere_password

View File

@ -1,91 +0,0 @@
{
"builders": [
{
"type": "vsphere-clone",
"name": "adds",
"vcenter_server": "{{user `vcenter_server`}}",
"username": "{{user `vsphere_username`}}",
"password": "{{user `vsphere_password`}}",
"insecure_connection": "true",
"vm_name": "adds-{{user `vm_name`}}",
"datastore": "{{user `vsphere_datastore`}}",
"folder": "{{user `vsphere_folder`}}",
"datacenter": "{{user `vsphere_datacenter`}}",
"host": "{{user `vsphere_host`}}",
"boot_order": "disk,cdrom",
"communicator": "winrm",
"winrm_username": "administrator",
"winrm_password": "{{user `winrm_password`}}",
"winrm_timeout": "10m",
"cpus": 2,
"RAM": 8192,
"template": "Windows-Server-2019-LTSC",
"floppy_files": [
"packer/preseed/ADDS/Sysprep_Unattend.xml"
],
"boot_command": "",
"boot_wait": "2m30s",
"shutdown_command": "C:\\Windows\\System32\\Sysprep\\sysprep.exe /generalize /oobe /unattend:A:\\Sysprep_Unattend.xml",
"shutdown_timeout": "1h",
"export": {
"images": false
}
}
],
"provisioners": [
{
"type": "powershell",
"inline": [
"New-Item -Path 'C:\\Payload\\Scripts' -ItemType 'Directory' -Force:$True -Confirm:$False"
]
},
{
"type": "file",
"source": "scripts/ADDS/payload/",
"destination": "C:\\Payload\\"
},
{
"type": "powershell",
"scripts": [
"scripts/ADDS/Install-Prerequisites.ps1",
"scripts/ADDS/Register-ScheduledTask.ps1"
]
}
],
"post-processors": [[
{
"type": "shell-local",
"inline": [
"pwsh -command \"& scripts/Update-OvfConfiguration.ps1 \\",
" -OVFFile './output-adds/adds-{{user `vm_name`}}.ovf' \\",
" -Parameter @{'appliance.name'='ADDS';'appliance.version'='{{user `vm_name`}}'}\"",
"pwsh -file scripts/Update-Manifest.ps1 \\",
" -ManifestFileName './output-adds/adds-{{user `vm_name`}}.mf'",
"ovftool --acceptAllEulas --allowExtraConfig --overwrite \\",
" './output-adds/adds-{{user `vm_name`}}.ovf' \\",
" /output/ADDS-appliance.ova"
]
}
],
[
{
"type": "shell-local",
"inline": [
"pwsh -file scripts/Remove-Resources.ps1 \\",
" -VMName 'adds-{{user `vm_name`}}' \\",
" -VSphereFQDN '{{user `vcenter_server`}}' \\",
" -VSphereUsername '{{user `vsphere_username`}}' \\",
" -VSpherePassword '{{user `vsphere_password`}}'"
]
}
]]
}

90
packer/adds.pkr.hcl Normal file
View File

@ -0,0 +1,90 @@
packer {
required_plugins {
windows-update = {
version = ">= 0.12.0"
source = "github.com/rgl/windows-update"
}
}
}
source "vsphere-clone" "adds" {
vcenter_server = var.vcenter_server
username = var.vsphere_username
password = var.vsphere_password
insecure_connection = "true"
vm_name = "adds-${var.vm_name}"
datacenter = var.vsphere_datacenter
host = var.vsphere_host
folder = var.vsphere_folder
datastore = var.vsphere_datastore
template = "Windows-Server-2019-LTSC"
boot_order = "disk,cdrom"
boot_command = [""]
boot_wait = "2m30s"
communicator = "winrm"
winrm_password = var.winrm_password
winrm_timeout = "10m"
winrm_username = "administrator"
RAM = 8192
CPUs = 2
floppy_files = [
"packer/preseed/ADDS/Sysprep_Unattend.xml"
]
shutdown_command = "C:\\Windows\\System32\\Sysprep\\sysprep.exe /generalize /oobe /unattend:A:\\Sysprep_Unattend.xml"
shutdown_timeout = "1h"
export {
images = false
}
}
build {
sources = ["source.vsphere-clone.adds"]
provisioner "powershell" {
inline = [
"New-Item -Path 'C:\\Payload\\Scripts' -ItemType 'Directory' -Force:$True -Confirm:$False"
]
}
provisioner "file" {
destination = "C:\\Payload\\"
source = "scripts/ADDS/payload/"
}
provisioner "powershell" {
scripts = [
"scripts/ADDS/Install-Prerequisites.ps1",
"scripts/ADDS/Register-ScheduledTask.ps1"
]
}
post-processor "shell-local" {
inline = [
"pwsh -command \"& scripts/Update-OvfConfiguration.ps1 \\",
" -OVFFile './output-adds/adds-${var.vm_name}.ovf' \\",
" -Parameter @{'appliance.name'='ADDS';'appliance.version'='${var.vm_name}'}\"",
"pwsh -file scripts/Update-Manifest.ps1 \\",
" -ManifestFileName './output-adds/adds-${var.vm_name}.mf'",
"ovftool --acceptAllEulas --allowExtraConfig --overwrite \\",
" './output-adds/adds-${var.vm_name}.ovf' \\",
" /output/ADDS-appliance.ova"
]
}
post-processor "shell-local" {
inline = [
"pwsh -file scripts/Remove-Resources.ps1 \\",
" -VMName 'adds-${var.vm_name}' \\",
" -VSphereFQDN '${var.vcenter_server}' \\",
" -VSphereUsername '${var.vsphere_username}' \\",
" -VSpherePassword '${var.vsphere_password}'"
]
}
}

14
packer/variables.pkr.hcl Normal file
View File

@ -0,0 +1,14 @@
variable "vcenter_server" {}
variable "vsphere_username" {}
variable "vsphere_password" {}
variable "vsphere_host" {}
variable "vsphere_datacenter" {}
variable "vsphere_templatefolder" {}
variable "vsphere_folder" {}
variable "vsphere_datastore" {}
variable "vsphere_network" {}
variable "vm_name" {}
variable "winrm_password" {}

View File

@ -1,11 +0,0 @@
{
"vcenter_server": "bv11-vc01.bessems.lan",
"vsphere_username": "administrator@vsphere.local",
"vsphere_datacenter": "DeSchakel",
"vsphere_host": "bv11-esx.bessems.eu",
"vsphere_hostip": "192.168.11.200",
"vsphere_datastore": "Datastore02.SSD",
"vsphere_folder": "/Packer",
"vsphere_templatefolder": "/Templates",
"vsphere_network": "LAN"
}

View File

@ -0,0 +1,8 @@
vcenter_server = "bv11-vc.bessems.lan"
vsphere_username = "administrator@vsphere.local"
vsphere_datacenter = "DeSchakel"
vsphere_host = "bv11-esx.bessems.lan"
vsphere_datastore = "Datastore01.SSD"
vsphere_folder = "/Packer"
vsphere_templatefolder = "/Templates"
vsphere_network = "LAN"

View File

@ -7,6 +7,8 @@ OrganizationalUnits:
Description: ''
- DistinguishedName: OU=Laptops,OU=Clients,OU=Computer accounts
Description: ''
- DistinguishedName: OU=Kiosks,OU=Clients,OU=Computer accounts
Description: ''
- DistinguishedName: OU=Servers,OU=Computer accounts
Description: ''

View File

@ -11,7 +11,6 @@ Users:
- DistinguishedName: CN=zzLDAP,OU=Service accounts,OU=Privileged,OU=User accounts
Password: "{{ password.zzldap }}"
MemberOf: []
---
Variables:
- Name: password.janedoe

View File

@ -65,21 +65,29 @@ If (@('primary','standalone') -contains $Parameter['deployment.type']) {
$GUIDMap['null'] = [Guid]::Empty
ForEach ($Entry in $Delegations.DelegationEntries) {
$GetADObjectSplat = @{
Identity = $Entry.OrganizationalUnit + (($Parameter['addsconfig.domainname'] -split '\.' | ForEach-Object {',DC={0}' -f $_}) -join '')
}
$OU = Get-ADObject @GetADObjectSplat
$GetACLSPlat = @{
Path = "$($PSDrive.Name):\$($OU.DistinguishedName)"
}
$ACL = Get-ACL @GetACLSPlat
$GetADObjectSplat = @{
Filter = "sAMAccountName -eq '$($Entry.Principal)'"
Properties = 'objectSID'
}
$Principal = Get-ADObject @GetADObjectSplat
ForEach ($OU in $Entry.OrganizationalUnit) {
$GetADObjectSplat = @{
Identity = ($OU + (',{0}' -f (Get-ADRootDSE).rootDomainNamingContext))
ErrorAction = 'SilentlyContinue'
}
$OU = Get-ADObject @GetADObjectSplat
If ([boolean]$OU) {
$GetACLSPlat = @{
Path = "$($PSDrive.Name):\$($OU.DistinguishedName)"
}
$ACL = Get-ACL @GetACLSPlat
}
Else {
# Respective OU was not found in Active Directory; skipping permission assignment
Continue
}
ForEach ($Rule in $Entry.AccessRules) {
If ($Rule.ObjectType -eq '') {
$Rule.ObjectType = 'null'
@ -112,6 +120,7 @@ If (@('primary','standalone') -contains $Parameter['deployment.type']) {
}
Set-Acl @SetAclSplat
}
}
If ([boolean]($PSDrive.Name -eq 'ADDS') -eq $True) {
$RemovePSDriveSplat = @{

View File

@ -1,6 +1,8 @@
DelegationEntries:
- Principal: admJaneD
OrganizationalUnit: CN=Computers # Entries will be concatenated with ',DC=<example>,DC=<org>' automatically
- Principal: admJaneD # Entries will be concatenated with ',DC=<example>,DC=<org>' automatically
OrganizationalUnit:
- CN=Computers
- OU=Kiosks,OU=Clients,OU=Computer accounts
AccessRules:
- ActiveDirectoryRights: Self # A combination of one or more of the ActiveDirectoryRights enumeration values that specifies the rights of the access rule.
AccessControlType: Allow # One of the AccessControlType enumeration values that specifies the access rule type.
@ -48,7 +50,8 @@ DelegationEntries:
ObjectType: Computer
InheritedObjectType: ''
- Principal: admJaneD
OrganizationalUnit: OU=Clients,OU=Computer accounts
OrganizationalUnit:
- OU=Clients,OU=Computer accounts
AccessRules:
- ActiveDirectoryRights: CreateChild, DeleteChild
AccessControlType: Allow

View File

@ -1,3 +1,6 @@
Name: 'COMP: Firewall (Clients)'
LinkedOUs:
- OU=Clients,OU=Computer accounts
FirewallRules:
- Description: Rule A
Action: Block

View File

@ -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'

View File

@ -6,9 +6,15 @@ 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
}
ForEach ($File in (Get-Item @GetItemSplat)) {
Try {
Write-Host "Loading/parsing file '$($File)' ..."
$GetContentSplat = @{
Path = $File
Raw = $True
}
$RawContent = Get-Content @GetContentSplat
$ConvertFromYamlSplat = @{
@ -16,9 +22,15 @@ If (@('primary','standalone') -contains $Parameter['deployment.type']) {
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)
}
@ -28,6 +40,12 @@ If (@('primary','standalone') -contains $Parameter['deployment.type']) {
AllDocuments = $True
}
$YamlDocuments = ConvertFrom-Yaml @ConvertFromYamlSplat
}
Catch {
$ParseErrors += "While processing '$($File)' (after substitutions): $($_.Exception.Message)"
Continue
}
$Settings = $YamlDocuments[0..($YamlDocuments.Count - 2)]
}
Else {
@ -35,7 +53,7 @@ If (@('primary','standalone') -contains $Parameter['deployment.type']) {
}
$NewGPOSplat = @{
Name = 'COMP: Firewall (Servers)'
Name = $Settings.Name
}
$NewGPO = New-GPO @NewGPOSplat
@ -95,15 +113,28 @@ If (@('primary','standalone') -contains $Parameter['deployment.type']) {
}
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
# Should probably be configurable through yml
Target = 'OU=Servers,OU=Computer accounts,DC=' + $Parameter['addsconfig.domainname'].Replace('.', ',DC=')
Target = $OU + (',{0}' -f (Get-ADRootDSE).rootDomainNamingContext)
}
New-GPLink @NewGPLinkSplat
$NewGPLinkSplat = @{
Name = $NewGPO.DisplayName
Target = 'OU=Domain Controllers,DC=' + $Parameter['addsconfig.domainname'].Replace('.', ',DC=')
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")"
}
New-GPLink @NewGPLinkSplat
}

View 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'

View File

@ -1,7 +1,7 @@
Name: 'COMP: Restrict Internet Communication'
Type: Object
LinkedOUs:
- OU=Servers
- OU=Servers,OU=Computer accounts
WMIFilters: []
RegistryEntries:
- Key: HKLM\Software\Policies\Microsoft\InternetManagement

View File

@ -15,13 +15,15 @@ If (@('primary','standalone') -contains $Parameter['deployment.type']) {
}
$PSSession = New-PSSession @NewPSSessionSplat
$ParseErrors = @()
$GetItemSplat = @{
Path = "$($PSScriptRoot)\$($MyInvocation.MyCommand)".Replace('.ps1', '.*.yml')
}
Get-Item @GetItemSplat | ForEach-Object {
Write-Host "Loading/parsing file '$($_)' ..."
ForEach ($File in (Get-Item @GetItemSplat)) {
Try {
Write-Host "Loading/parsing file '$($File)' ..."
$GetContentSplat = @{
Path = $_
Path = $File
Raw = $True
}
$RawContent = Get-Content @GetContentSplat
@ -30,9 +32,15 @@ If (@('primary','standalone') -contains $Parameter['deployment.type']) {
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)
}
@ -42,6 +50,12 @@ If (@('primary','standalone') -contains $Parameter['deployment.type']) {
AllDocuments = $True
}
$YamlDocuments = ConvertFrom-Yaml @ConvertFromYamlSplat
}
Catch {
$ParseErrors += "While processing '$($File)' (after substitutions): $($_.Exception.Message)"
Continue
}
$GroupPolicies = $YamlDocuments[0..($YamlDocuments.Count - 2)]
}
Else {
@ -160,19 +174,28 @@ If (@('primary','standalone') -contains $Parameter['deployment.type']) {
}
ForEach ($OU in $GroupPolicy.LinkedOUs) {
If (Test-Path "AD:\$($OU + ',DC=' + $Parameter['addsconfig.domainname'].Replace('.', ',DC='))") {
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 + ',DC=' + $Parameter['addsconfig.domainname'].Replace('.', ',DC=')
# ErrorAction = 'SilentlyContinue'
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 {
Throw "Path not accessible: 'AD:\$($OU + ',DC=' + $Parameter['addsconfig.domainname'].Replace('.', ',DC='))'"
$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")"
}
}

View File

@ -128,13 +128,13 @@ ForEach ($Category in $OVFConfig.PropertyCategories) {
$XMLPropertyAttrKey.Value = $Property.Key
$XMLPropertyAttrType = $XML.CreateAttribute('type', $XML.DocumentElement.ovf)
Switch -regex ($Property.Type) {
'boolean' {
'^boolean' {
$XMLPropertyAttrType.Value = 'boolean'
}
'int' {
'^int' {
$XMLPropertyAttrType.Value = 'uint8'
$Qualifiers = @()
If ($Property.Type -match 'int\((\d*)\.\.(\d*)\)') {
If ($Property.Type -match '^int\((\d*)\.\.(\d*)\)') {
If ($Matches[1]) {
$Qualifiers += "MinValue($($Matches[1]))"
}
@ -146,20 +146,20 @@ ForEach ($Category in $OVFConfig.PropertyCategories) {
[void]$XMLProperty.Attributes.Append($XMLPropertyAttrQualifiers)
}
}
'ip' {
'^ip' {
$XMLPropertyAttrType.Value = 'string'
$XMLPropertyAttrQualifiers = $XML.CreateAttribute('qualifiers', $XML.DocumentElement.vmw)
$XMLPropertyAttrQualifiers.Value = 'Ip'
[void]$XMLProperty.Attributes.Append($XMLPropertyAttrQualifiers)
}
'password' {
'^password' {
$XMLPropertyAttrType.Value = 'string'
$XMLPropertyAttrPassword = $XML.CreateAttribute('password', $XML.DocumentElement.ovf)
$XMLPropertyAttrPassword.Value = 'true'
[void]$XMLProperty.Attributes.Append($XMLPropertyAttrPassword)
$Qualifiers = @()
If ($Property.Type -match 'password\((\d*)\.\.(\d*)\)') {
If ($Property.Type -match '^password\((\d*)\.\.(\d*)\)') {
If ($Matches[1]) {
$Qualifiers += "MinLen($($Matches[1]))"
}
@ -171,10 +171,10 @@ ForEach ($Category in $OVFConfig.PropertyCategories) {
[void]$XMLProperty.Attributes.Append($XMLPropertyAttrQualifiers)
}
}
'string' {
'^string' {
$XMLPropertyAttrType.Value = 'string'
$Qualifiers = @()
If ($Property.Type -match 'string\((\d*)\.\.(\d*)\)') {
If ($Property.Type -match '^string\((\d*)\.\.(\d*)\)') {
If ($Matches[1]) {
$Qualifiers += "MinLen($($Matches[1]))"
}
@ -184,7 +184,7 @@ ForEach ($Category in $OVFConfig.PropertyCategories) {
$XMLPropertyAttrQualifiers = $XML.CreateAttribute('qualifiers', $XML.DocumentElement.ovf)
$XMLPropertyAttrQualifiers.Value = $Qualifiers -join ' '
[void]$XMLProperty.Attributes.Append($XMLPropertyAttrQualifiers)
} ElseIf ($Property.Type -match 'string\[(.*)\]') {
} ElseIf ($Property.Type -match '^string\[(.*)\]') {
$XMLPropertyAttrQualifiers = $XML.CreateAttribute('qualifiers', $XML.DocumentElement.ovf)
$XMLPropertyAttrQualifiers.Value = "ValueMap{$($Matches[1] -replace '","', '", "')}"
[void]$XMLProperty.Attributes.Append($XMLPropertyAttrQualifiers)