From b6c7475673e627db7c1c5ed012515525ec8b99d3 Mon Sep 17 00:00:00 2001 From: djpbessems Date: Mon, 22 Feb 2021 16:11:09 +0100 Subject: [PATCH] Eliminate .csv's; Draft dynamic pw provisioning --- .../scripts/01.Organizational units.csv | 16 ------- .../scripts/01.Organizational units.ps1 | 31 ++++++++++-- .../scripts/01.Organizational units.yml | 33 +++++++++++++ scripts/ADDS/payload/scripts/02.Groups.csv | 6 --- scripts/ADDS/payload/scripts/02.Groups.ps1 | 47 ++++++++++++++++--- scripts/ADDS/payload/scripts/02.Groups.yml | 28 +++++++++++ scripts/ADDS/payload/scripts/03.Users.csv | 5 -- scripts/ADDS/payload/scripts/03.Users.ps1 | 37 ++++++++++++--- scripts/ADDS/payload/scripts/03.Users.yml | 20 ++++++++ 9 files changed, 179 insertions(+), 44 deletions(-) delete mode 100644 scripts/ADDS/payload/scripts/01.Organizational units.csv create mode 100644 scripts/ADDS/payload/scripts/01.Organizational units.yml delete mode 100644 scripts/ADDS/payload/scripts/02.Groups.csv create mode 100644 scripts/ADDS/payload/scripts/02.Groups.yml delete mode 100644 scripts/ADDS/payload/scripts/03.Users.csv create mode 100644 scripts/ADDS/payload/scripts/03.Users.yml diff --git a/scripts/ADDS/payload/scripts/01.Organizational units.csv b/scripts/ADDS/payload/scripts/01.Organizational units.csv deleted file mode 100644 index 8f152e7..0000000 --- a/scripts/ADDS/payload/scripts/01.Organizational units.csv +++ /dev/null @@ -1,16 +0,0 @@ -"DistinguishedName","Description" -"OU=Computer accounts","" -"OU=Clients,OU=Computer accounts","" -"OU=Desktops,OU=Clients,OU=Computer accounts","" -"OU=Laptops,OU=Clients,OU=Computer accounts","" -"OU=Servers,OU=Computer accounts","" -"OU=Groups","" -"OU=Resources,OU=Groups","" -"OU=Roles,OU=Groups","" -"OU=User accounts","" -"OU=Privileged,OU=User accounts","" -"OU=Administrators,OU=Privileged,OU=User accounts","" -"OU=Service accounts,OU=Privileged,OU=User accounts","" -"OU=Non-privileged,OU=User accounts","" -"OU=Employees,OU=Non-privileged,OU=User accounts","" -"OU=Contractors,OU=Non-privileged,OU=User accounts","" diff --git a/scripts/ADDS/payload/scripts/01.Organizational units.ps1 b/scripts/ADDS/payload/scripts/01.Organizational units.ps1 index 08693a1..3cffae8 100644 --- a/scripts/ADDS/payload/scripts/01.Organizational units.ps1 +++ b/scripts/ADDS/payload/scripts/01.Organizational units.ps1 @@ -7,11 +7,34 @@ Param( # Only executed on primary or standalone Domain Controller If (@('primary','standalone') -contains $Parameter['deployment.type']) { $GetContentSplat = @{ - Path = "$($PSScriptRoot)\$($MyInvocation.MyCommand)".Replace('.ps1', ".csv") + Path = "$($PSScriptRoot)\$($MyInvocation.MyCommand)".Replace('.ps1', ".yml") + Raw = $True } - $CSVImport = (Get-Content @GetContentSplat) | ConvertFrom-Csv + $RawContent = Get-Content @GetContentSplat + $ConvertFromYamlSplat = @{ + Yaml = $RawContent + AllDocuments = $True + } + $YamlDocuments = ConvertFrom-Yaml @ConvertFromYamlSplat - ForEach ($OU in $CSVImport) { + # 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) + } + # Perform conversion to Yaml again, now with parsed file contents + $ConvertFromYamlSplat = @{ + Yaml = $RawContent + AllDocuments = $True + } + $YamlDocuments = ConvertFrom-Yaml @ConvertFromYamlSplat + $Entries = $YamlDocuments[0..($YamlDocuments.Count - 2)] + } + Else { + $Entries = $YamlDocuments + } + + ForEach ($OU in $Entries.OrganizationalUnits) { $OUName, $OUPath = $OU.DistinguishedName -split ',', 2 If ($OUPath.Length -ne 0) { $OUPath += ',' @@ -19,7 +42,7 @@ If (@('primary','standalone') -contains $Parameter['deployment.type']) { $NewADOrganizationalUnitSplat = @{ Name = $OUName.Substring(3) - Path = $OUPath + 'DC=' + $Parameter['addsconfig.domainname'].Replace('.', ',DC=') + Path = $OUPath + (Get-ADRootDSE).rootDomainNamingContext Description = $OU.Description ProtectedFromAccidentalDeletion = $False ErrorAction = 'SilentlyContinue' diff --git a/scripts/ADDS/payload/scripts/01.Organizational units.yml b/scripts/ADDS/payload/scripts/01.Organizational units.yml new file mode 100644 index 0000000..28b415c --- /dev/null +++ b/scripts/ADDS/payload/scripts/01.Organizational units.yml @@ -0,0 +1,33 @@ +OrganizationalUnits: +- DistinguishedName: OU=Computer accounts + Description: '' +- DistinguishedName: OU=Clients,OU=Computer accounts + Description: '' +- DistinguishedName: OU=Desktops,OU=Clients,OU=Computer accounts + Description: '' +- DistinguishedName: OU=Laptops,OU=Clients,OU=Computer accounts + Description: '' +- DistinguishedName: OU=Servers,OU=Computer accounts + Description: '' + +- DistinguishedName: OU=Groups + Description: '' +- DistinguishedName: OU=Resources,OU=Groups + Description: '' +- DistinguishedName: OU=Roles,OU=Groups + Description: '' + +- DistinguishedName: OU=User accounts + Description: '' +- DistinguishedName: OU=Privileged,OU=User accounts + Description: '' +- DistinguishedName: OU=Administrators,OU=Privileged,OU=User accounts + Description: '' +- DistinguishedName: OU=Service accounts,OU=Privileged,OU=User accounts + Description: '' +- DistinguishedName: OU=Non-privileged,OU=User accounts + Description: '' +- DistinguishedName: OU=Employees,OU=Non-privileged,OU=User accounts + Description: '' +- DistinguishedName: OU=Contractors,OU=Non-privileged,OU=User accounts + Description: '' diff --git a/scripts/ADDS/payload/scripts/02.Groups.csv b/scripts/ADDS/payload/scripts/02.Groups.csv deleted file mode 100644 index f657c84..0000000 --- a/scripts/ADDS/payload/scripts/02.Groups.csv +++ /dev/null @@ -1,6 +0,0 @@ -"DistinguishedName","Description" -"CN=RemoteDesktop - Management servers,OU=Resources,OU=Groups","" -"CN=ContentLibraryAdmin - vSphere servers,OU=Resources,OU=Groups","" -"CN=DatastoreAdmin - vSphere servers,OU=Resources,OU=Groups","" -"CN=Hypervisor administrators,OU=Roles,OU=Groups","" -"CN=Firewall administrators,OU=Roles,OU=Groups","" diff --git a/scripts/ADDS/payload/scripts/02.Groups.ps1 b/scripts/ADDS/payload/scripts/02.Groups.ps1 index 603511a..66ade84 100644 --- a/scripts/ADDS/payload/scripts/02.Groups.ps1 +++ b/scripts/ADDS/payload/scripts/02.Groups.ps1 @@ -7,19 +7,54 @@ Param( # Only executed on primary or standalone Domain Controller If (@('primary','standalone') -contains $Parameter['deployment.type']) { $GetContentSplat = @{ - Path = "$($PSScriptRoot)\$($MyInvocation.MyCommand)".Replace('.ps1', ".csv") + Path = "$($PSScriptRoot)\$($MyInvocation.MyCommand)".Replace('.ps1', ".yml") + Raw = $True } - $CSVImport = (Get-Content @GetContentSplat) | ConvertFrom-Csv + $RawContent = Get-Content @GetContentSplat + $ConvertFromYamlSplat = @{ + Yaml = $RawContent + AllDocuments = $True + } + $YamlDocuments = ConvertFrom-Yaml @ConvertFromYamlSplat - ForEach ($Group in $CSVImport) { + # 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) + } + # Perform conversion to Yaml again, now with parsed file contents + $ConvertFromYamlSplat = @{ + Yaml = $RawContent + AllDocuments = $True + } + $YamlDocuments = ConvertFrom-Yaml @ConvertFromYamlSplat + $Entries = $YamlDocuments[0..($YamlDocuments.Count - 2)] + } + Else { + $Entries = $YamlDocuments + } + + ForEach ($Group in $Entries.SecurityGroups) { $NewADGroupSplat = @{ Name = ($Group.DistinguishedName -split ',', 2)[0].Substring(3) - Path = ($Group.DistinguishedName -split ',', 2)[1] + ',DC=' + $Parameter['addsconfig.domainname'].Replace('.', ',DC=') + Path = ($Group.DistinguishedName -split ',', 2)[1] + (',{0}' -f (Get-ADRootDSE).rootDomainNamingContext) Description = $Group.Description GroupCategory = 'Security' - GroupScope = 'Global' + GroupScope = $Group.Scope + PassThru = $True ErrorAction = 'SilentlyContinue' } - New-ADGroup @NewADGroupSplat + $NewADGroup = New-ADGroup @NewADGroupSplat + + If ([boolean]$Group.MemberOf) { + ForEach ($ParentGroup in $Group.MemberOf) { + $AddADGroupMemberSplat = @{ + Identity = $ParentGroup + (',{0}' -f (Get-ADRootDSE).rootDomainNamingContext) + Members = $NewADGroup.DistinguishedName + ErrorAction = 'SilentlyContinue' + } + Add-ADGroupMember @AddADGroupMemberSplat + } + } } } \ No newline at end of file diff --git a/scripts/ADDS/payload/scripts/02.Groups.yml b/scripts/ADDS/payload/scripts/02.Groups.yml new file mode 100644 index 0000000..b12ae65 --- /dev/null +++ b/scripts/ADDS/payload/scripts/02.Groups.yml @@ -0,0 +1,28 @@ +SecurityGroups: + # Role groups +- DistinguishedName: CN=Hypervisor administrators,OU=Roles,OU=Groups + Description: '' + Scope: 'Global' + MemberOf: [] +- DistinguishedName: CN=Firewall administrators,OU=Roles,OU=Groups + Description: '' + Scope: 'Global' + MemberOf: [] + +# Resource groups +- DistinguishedName: CN=RemoteDesktop - Management servers,OU=Resources,OU=Groups + Description: '' + Scope: 'DomainLocal' + MemberOf: + - CN=Hypervisor administrators,OU=Roles,OU=Groups + - CN=Firewall administrators,OU=Roles,OU=Groups +- DistinguishedName: CN=ContentLibraryAdmin - vSphere servers,OU=Resources,OU=Groups + Description: '' + Scope: 'DomainLocal' + MemberOf: + - CN=Hypervisor administrators,OU=Roles,OU=Groups +- DistinguishedName: CN=DatastoreAdmin - vSphere servers,OU=Resources,OU=Groups + Description: '' + Scope: 'DomainLocal' + MemberOf: + - CN=Hypervisor administrators,OU=Roles,OU=Groups diff --git a/scripts/ADDS/payload/scripts/03.Users.csv b/scripts/ADDS/payload/scripts/03.Users.csv deleted file mode 100644 index 86eeca4..0000000 --- a/scripts/ADDS/payload/scripts/03.Users.csv +++ /dev/null @@ -1,5 +0,0 @@ -"DistinguishedName","Password","MemberOf" -"CN=Jane Doe,OU=Employees,OU=Non-privileged,OU=User accounts","Complex42!","" -"CN=John Doe,OU=Contractors,OU=Non-privileged,OU=User accounts","Complex42!","" -"CN=admJaneD,OU=Administrators,OU=Privileged,OU=User accounts","Complex42!","" -"CN=zzLDAP,OU=Service accounts,OU=Privileged,OU=User accounts","Complex42!","" diff --git a/scripts/ADDS/payload/scripts/03.Users.ps1 b/scripts/ADDS/payload/scripts/03.Users.ps1 index a711477..a5167c2 100644 --- a/scripts/ADDS/payload/scripts/03.Users.ps1 +++ b/scripts/ADDS/payload/scripts/03.Users.ps1 @@ -7,25 +7,48 @@ Param( # Only executed on primary or standalone Domain Controller If (@('primary','standalone') -contains $Parameter['deployment.type']) { $GetContentSplat = @{ - Path = "$($PSScriptRoot)\$($MyInvocation.MyCommand)".Replace('.ps1', ".csv") + Path = "$($PSScriptRoot)\$($MyInvocation.MyCommand)".Replace('.ps1', ".yml") + Raw = $True } - $CSVImport = (Get-Content @GetContentSplat) | ConvertFrom-Csv + $RawContent = Get-Content @GetContentSplat + $ConvertFromYamlSplat = @{ + Yaml = $RawContent + AllDocuments = $True + } + $YamlDocuments = ConvertFrom-Yaml @ConvertFromYamlSplat - ForEach ($User in $CSVImport) { + # 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) + } + # Perform conversion to Yaml again, now with parsed file contents + $ConvertFromYamlSplat = @{ + Yaml = $RawContent + AllDocuments = $True + } + $YamlDocuments = ConvertFrom-Yaml @ConvertFromYamlSplat + $Entries = $YamlDocuments[0..($YamlDocuments.Count - 2)] + } + Else { + $Entries = $YamlDocuments + } + + ForEach ($User in $Entries.Users) { # Create new user $NewADUserSplat = @{ Name = ($User.DistinguishedName -split ',', 2)[0].Substring(3) - Path = ($User.DistinguishedName -split ',', 2)[1] + ',DC=' + $Parameter['addsconfig.domainname'].Replace('.', ',DC=') + Path = ($User.DistinguishedName -split ',', 2)[1] + (',{0}' -f (Get-ADRootDSE).rootDomainNamingContext) AccountPassword = ConvertTo-SecureString $User.Password -AsPlainText -Force PassThru = $True ErrorAction = 'SilentlyContinue' } $NewADUser = New-ADUser @NewADUserSplat # Add user to group(s) - If ($User.MemberOf -ne '') { - ForEach ($Group in $User.MemberOf.Split('|')) { + If ([boolean]$User.MemberOf) { + ForEach ($Group in $User.MemberOf) { $AddADGroupMemberSplat = @{ - Identity = $Group + ',DC=' + $Parameter['addsconfig.domainname'].Replace('.', ',DC=') + Identity = $Group + (',{0}' -f (Get-ADRootDSE).rootDomainNamingContext) Members = $NewADUser.DistinguishedName ErrorAction = 'SilentlyContinue' } diff --git a/scripts/ADDS/payload/scripts/03.Users.yml b/scripts/ADDS/payload/scripts/03.Users.yml new file mode 100644 index 0000000..5b1227b --- /dev/null +++ b/scripts/ADDS/payload/scripts/03.Users.yml @@ -0,0 +1,20 @@ +Users: +- DistinguishedName: CN=Jane Doe,OU=Employees,OU=Non-privileged,OU=User accounts + Password: Complex42! + # Password: "{{ password.janedoe }}" + MemberOf: [] +- DistinguishedName: CN=John Doe,OU=Contractors,OU=Non-privileged,OU=User accounts + Password: Complex42! + MemberOf: [] +- DistinguishedName: CN=admJaneD,OU=Administrators,OU=Privileged,OU=User accounts + Password: Complex42! + MemberOf: [] +- DistinguishedName: CN=zzLDAP,OU=Service accounts,OU=Privileged,OU=User accounts + Password: Complex42! + MemberOf: [] + +# --- +# Variables: +# - Name: password.janedoe +# Expression: | +# (Invoke-WebRequest -Uri 'vault' -Body '' | ConvertFrom-Json).Password \ No newline at end of file