Delete commit history (containing proprietary code)
Some checks reported errors
continuous-integration/drone/push Build was killed
Some checks reported errors
continuous-integration/drone/push Build was killed
This commit is contained in:
37
.drone.yml
Normal file
37
.drone.yml
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
kind: pipeline
|
||||||
|
type: kubernetes
|
||||||
|
name: 'Packer Build'
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Active Directory Certificate Services
|
||||||
|
image: bv11-cr01.bessems.eu/library/packer-extended
|
||||||
|
commands:
|
||||||
|
- |
|
||||||
|
packer validate \
|
||||||
|
-var-file=packer/variables.vsphere.json \
|
||||||
|
-var vm_name=${DRONE_COMMIT_SHA:0:10}-$DRONE_BUILD_NUMBER \
|
||||||
|
-var vsphere_password=$${VSPHERE_PASSWORD} \
|
||||||
|
-var winrm_password=$${WINRM_PASSWORD} \
|
||||||
|
packer/adcs.json
|
||||||
|
- |
|
||||||
|
packer build \
|
||||||
|
-on-error=cleanup \
|
||||||
|
-var-file=packer/variables.vsphere.json \
|
||||||
|
-var vm_name=${DRONE_COMMIT_SHA:0:10}-$DRONE_BUILD_NUMBER \
|
||||||
|
-var vsphere_password=$${VSPHERE_PASSWORD} \
|
||||||
|
-var winrm_password=$${WINRM_PASSWORD} \
|
||||||
|
packer/adcs.json
|
||||||
|
environment:
|
||||||
|
VSPHERE_PASSWORD:
|
||||||
|
from_secret: vsphere_password
|
||||||
|
WINRM_PASSWORD:
|
||||||
|
from_secret: winrm_password
|
||||||
|
# PACKER_LOG: 1
|
||||||
|
volumes:
|
||||||
|
- name: output
|
||||||
|
path: /output
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
- name: output
|
||||||
|
claim:
|
||||||
|
name: flexvolsmb-drone-output
|
2
README.md
Normal file
2
README.md
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
# Packer.Images [](https://ci.spamasaurus.com/djpbessems/Packer.Images)
|
||||||
|
|
90
packer/adcs.json
Normal file
90
packer/adcs.json
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
{
|
||||||
|
"builders": [
|
||||||
|
{
|
||||||
|
"type": "vsphere-clone",
|
||||||
|
"name": "adcs",
|
||||||
|
|
||||||
|
"vcenter_server": "{{user `vcenter_server`}}",
|
||||||
|
"username": "{{user `vsphere_username`}}",
|
||||||
|
"password": "{{user `vsphere_password`}}",
|
||||||
|
"insecure_connection": "true",
|
||||||
|
|
||||||
|
"vm_name": "adcs-{{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/ADCS/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/ADCS/payload/",
|
||||||
|
"destination": "C:\\Payload\\"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "powershell",
|
||||||
|
"scripts": [
|
||||||
|
"scripts/ADCS/Install-Prerequisites.ps1",
|
||||||
|
"scripts/ADCS/Register-ScheduledTask.ps1"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"post-processors": [[
|
||||||
|
{
|
||||||
|
"type": "shell-local",
|
||||||
|
"inline": [
|
||||||
|
"pwsh -file scripts/Update-OvfConfiguration.ps1 \\",
|
||||||
|
" -OVFFile './output-adcs/adcs-{{user `vm_name`}}.ovf'",
|
||||||
|
"pwsh -file scripts/Update-Manifest.ps1 \\",
|
||||||
|
" -ManifestFileName './output-adcs/adcs-{{user `vm_name`}}.mf'",
|
||||||
|
"ovftool --acceptAllEulas --allowExtraConfig --overwrite \\",
|
||||||
|
" './output-adcs/adcs-{{user `vm_name`}}.ovf' \\",
|
||||||
|
" /output/ADCS-appliance.ova"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"type": "shell-local",
|
||||||
|
"inline": [
|
||||||
|
"pwsh -file scripts/Remove-Resources.ps1 \\",
|
||||||
|
" -VMName 'adcs-{{user `vm_name`}}' \\",
|
||||||
|
" -VSphereFQDN '{{user `vcenter_server`}}' \\",
|
||||||
|
" -VSphereUsername '{{user `vsphere_username`}}' \\",
|
||||||
|
" -VSpherePassword '{{user `vsphere_password`}}'"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]]
|
||||||
|
}
|
27
packer/preseed/ADCS/Sysprep_Unattend.xml
Normal file
27
packer/preseed/ADCS/Sysprep_Unattend.xml
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<unattend xmlns="urn:schemas-microsoft-com:unattend">
|
||||||
|
<settings pass="generalize">
|
||||||
|
<component name="Microsoft-Windows-Security-SPP" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||||
|
<SkipRearm>1</SkipRearm>
|
||||||
|
</component>
|
||||||
|
<component name="Microsoft-Windows-PnpSysprep" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||||
|
<PersistAllDeviceInstalls>true</PersistAllDeviceInstalls>
|
||||||
|
<DoNotCleanUpNonPresentDevices>true</DoNotCleanUpNonPresentDevices>
|
||||||
|
</component>
|
||||||
|
</settings>
|
||||||
|
<settings pass="oobeSystem">
|
||||||
|
<component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||||
|
<OOBE>
|
||||||
|
<HideEULAPage>true</HideEULAPage>
|
||||||
|
<HideLocalAccountScreen>true</HideLocalAccountScreen>
|
||||||
|
<HideOEMRegistrationScreen>true</HideOEMRegistrationScreen>
|
||||||
|
<HideOnlineAccountScreens>true</HideOnlineAccountScreens>
|
||||||
|
<HideWirelessSetupInOOBE>true</HideWirelessSetupInOOBE>
|
||||||
|
<NetworkLocation>Work</NetworkLocation>
|
||||||
|
<ProtectYourPC>1</ProtectYourPC>
|
||||||
|
<SkipMachineOOBE>true</SkipMachineOOBE>
|
||||||
|
<SkipUserOOBE>true</SkipUserOOBE>
|
||||||
|
</OOBE>
|
||||||
|
</component>
|
||||||
|
</settings>
|
||||||
|
</unattend>
|
11
packer/variables.vsphere.json
Normal file
11
packer/variables.vsphere.json
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"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"
|
||||||
|
}
|
48
scripts/ADCS/Install-Prerequisites.ps1
Normal file
48
scripts/ADCS/Install-Prerequisites.ps1
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
[CmdletBinding()]
|
||||||
|
Param(
|
||||||
|
# No parameters
|
||||||
|
)
|
||||||
|
|
||||||
|
$InstallWindowsFeatureSplat = @{
|
||||||
|
Name = 'Adcs-Cert-Authority'
|
||||||
|
IncludeAllSubFeature = $True
|
||||||
|
IncludeManagementTools = $True
|
||||||
|
Restart = $False
|
||||||
|
Confirm = $False
|
||||||
|
}
|
||||||
|
Install-WindowsFeature @InstallWindowsFeatureSplat
|
||||||
|
|
||||||
|
$InstallPackageProviderSplat = @{
|
||||||
|
Name = 'NuGet'
|
||||||
|
MinimumVersion = '2.8.5.201'
|
||||||
|
Force = $True
|
||||||
|
Confirm = $False
|
||||||
|
}
|
||||||
|
Install-PackageProvider @InstallPackageProviderSplat
|
||||||
|
$SetPSRepositorySplat = @{
|
||||||
|
Name = 'PSGallery'
|
||||||
|
InstallationPolicy = 'Trusted'
|
||||||
|
}
|
||||||
|
Set-PSRepository @SetPSRepositorySplat
|
||||||
|
$InstallModuleSplat = @{
|
||||||
|
Name = 'powershell-yaml'
|
||||||
|
Force = $True
|
||||||
|
Confirm = $False
|
||||||
|
}
|
||||||
|
Install-Module @InstallModuleSplat
|
||||||
|
$SetPSRepositorySplat = @{
|
||||||
|
Name = 'PSGallery'
|
||||||
|
InstallationPolicy = 'Untrusted'
|
||||||
|
}
|
||||||
|
Set-PSRepository @SetPSRepositorySplat
|
||||||
|
|
||||||
|
# Double check whether the required PowerShell modules are available
|
||||||
|
$RequiredModules = @(
|
||||||
|
'powershell-yaml' # Provides cmdlets 'ConvertTo-Yaml' and 'ConvertFrom-Yaml'
|
||||||
|
)
|
||||||
|
ForEach ($Module in $RequiredModules) {
|
||||||
|
If ([boolean](Get-Module -Name $Module -ListAvailable) -ne $True) {
|
||||||
|
Write-Error -Message "Missing PowerShell module '$($Module)'"
|
||||||
|
Exit 1
|
||||||
|
}
|
||||||
|
}
|
7
scripts/ADCS/Register-ScheduledTask.ps1
Normal file
7
scripts/ADCS/Register-ScheduledTask.ps1
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
[CmdletBinding()]
|
||||||
|
Param(
|
||||||
|
# No parameters
|
||||||
|
)
|
||||||
|
|
||||||
|
# Create scheduled task
|
||||||
|
& schtasks.exe /Create /TN 'OVF-Properties' /SC ONSTART /RU SYSTEM /TR "powershell.exe -file C:\Payload\Apply-OVFProperties.ps1"
|
166
scripts/ADCS/payload/Apply-OVFProperties.ps1
Normal file
166
scripts/ADCS/payload/Apply-OVFProperties.ps1
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
#Requires -Modules 'ADDSDeployment'
|
||||||
|
[CmdletBinding()]
|
||||||
|
Param(
|
||||||
|
# No parameters
|
||||||
|
)
|
||||||
|
|
||||||
|
$NewEventLogSplat = @{
|
||||||
|
LogName = 'Application'
|
||||||
|
Source = 'OVF-Properties'
|
||||||
|
ErrorAction = 'SilentlyContinue'
|
||||||
|
}
|
||||||
|
New-EventLog @NewEventLogSplat
|
||||||
|
$WriteEventLogSplat = @{
|
||||||
|
LogName = 'Application'
|
||||||
|
Source = 'OVF-Properties'
|
||||||
|
EntryType = 'Information'
|
||||||
|
EventID = 1
|
||||||
|
Message = 'OVF-Properties sequence initiated'
|
||||||
|
}
|
||||||
|
Write-EventLog @WriteEventLogSplat
|
||||||
|
|
||||||
|
$VMwareToolsExecutable = "C:\Program Files\VMware\VMware Tools\vmtoolsd.exe"
|
||||||
|
|
||||||
|
[xml]$ovfEnv = & $VMwareToolsExecutable --cmd "info-get guestinfo.ovfEnv" | Out-String
|
||||||
|
$ovfProperties = $ovfEnv.ChildNodes.NextSibling.PropertySection.Property
|
||||||
|
|
||||||
|
$ovfPropertyValues = @{}
|
||||||
|
foreach ($ovfProperty in $ovfProperties) {
|
||||||
|
$ovfPropertyValues[$ovfProperty.key] = $ovfProperty.Value
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check for mandatory values
|
||||||
|
If (!($ovfPropertyValues['guestinfo.hostname'] -and
|
||||||
|
$ovfPropertyValues['guestinfo.ipaddress'] -and
|
||||||
|
$ovfPropertyValues['guestinfo.dnsserver'] -and
|
||||||
|
$ovfPropertyValues['guestinfo.prefixlength'] -and
|
||||||
|
$ovfPropertyValues['guestinfo.gateway'])) {
|
||||||
|
# Mandatory values missing, cannot provision.
|
||||||
|
$WriteEventLogSplat = @{
|
||||||
|
LogName = 'Application'
|
||||||
|
Source = 'OVF-Properties'
|
||||||
|
EntryType = 'Error'
|
||||||
|
EventID = 66
|
||||||
|
Message = 'Mandatory values missing, cannot provision.'
|
||||||
|
}
|
||||||
|
Write-EventLog @WriteEventLogSplat
|
||||||
|
& schtasks.exe /Change /TN 'OVF-Properties' /DISABLE
|
||||||
|
Stop-Computer -Force
|
||||||
|
Exit
|
||||||
|
}
|
||||||
|
|
||||||
|
# Set hostname and description
|
||||||
|
If ($Env:ComputerName -ne $ovfPropertyValues['guestinfo.hostname']) {
|
||||||
|
$RenameComputerSplat = @{
|
||||||
|
NewName = $ovfPropertyValues['guestinfo.hostname']
|
||||||
|
Force = $True
|
||||||
|
Confirm = $False
|
||||||
|
}
|
||||||
|
Rename-Computer @RenameComputerSplat
|
||||||
|
$SetCimInstanceSplat = @{
|
||||||
|
InputObject = (Get-CimInstance -ClassName 'Win32_OperatingSystem')
|
||||||
|
Property = @{
|
||||||
|
Description = $ovfPropertyValues['guestinfo.hostname']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Set-CimInstance @SetCimInstanceSplat
|
||||||
|
|
||||||
|
# Restart the computer to apply changes
|
||||||
|
Restart-Computer -Force
|
||||||
|
Exit
|
||||||
|
}
|
||||||
|
|
||||||
|
# Configure network interface
|
||||||
|
If ((Get-WmiObject -Class 'Win32_NetworkAdapterConfiguration').IPAddress -NotContains $ovfPropertyValues['guestinfo.ipaddress']) {
|
||||||
|
$NewNetIPAddressSplat = @{
|
||||||
|
InterfaceAlias = (Get-NetAdapter).Name
|
||||||
|
AddressFamily = 'IPv4'
|
||||||
|
IPAddress = $ovfPropertyValues['guestinfo.ipaddress']
|
||||||
|
PrefixLength = $ovfPropertyValues['guestinfo.prefixlength']
|
||||||
|
DefaultGateway = $ovfPropertyValues['guestinfo.gateway']
|
||||||
|
}
|
||||||
|
New-NetIPAddress @NewNetIPAddressSplat
|
||||||
|
|
||||||
|
# Wait for network connection to become available
|
||||||
|
$Timestamp, $TimeoutMinutes = (Get-Date), 5
|
||||||
|
Do {
|
||||||
|
If ($Timestamp.AddMinutes($TimeoutMinutes) -lt (Get-Date)) {
|
||||||
|
$WriteEventLogSplat = @{
|
||||||
|
LogName = 'Application'
|
||||||
|
Source = 'OVF-Properties'
|
||||||
|
EntryType = 'Warning'
|
||||||
|
EventID = 13
|
||||||
|
Message = "Timeout after $($TimeoutMinutes) minutes waiting for network connection to become available."
|
||||||
|
}
|
||||||
|
Write-EventLog @WriteEventLogSplat
|
||||||
|
Break
|
||||||
|
}
|
||||||
|
|
||||||
|
Start-Sleep -Milliseconds 250
|
||||||
|
|
||||||
|
$GetNetIPAddressSplat = @{
|
||||||
|
InterfaceAlias = (Get-NetAdapter).Name
|
||||||
|
AddressFamily = 'IPv4'
|
||||||
|
ErrorAction = 'SilentlyContinue'
|
||||||
|
}
|
||||||
|
} Until ((Get-NetIPAddress @GetNetIPAddressSplat).AddressState -eq 'Preferred')
|
||||||
|
|
||||||
|
$OldErrorActionPreference, $ErrorActionPreference = $ErrorActionPreference, 'SilentlyContinue'
|
||||||
|
$TestNetConnectionSplat = @{
|
||||||
|
ComputerName = ([IPAddress]$ovfPropertyValues['guestinfo.dnsserver']).IPAddressToString
|
||||||
|
InformationLevel = 'Quiet'
|
||||||
|
}
|
||||||
|
$SetDnsClientServerAddressSplat = @{
|
||||||
|
InterfaceAlias = (Get-NetAdapter).Name
|
||||||
|
ServerAddresses = If (
|
||||||
|
[boolean]($ovfPropertyValues['guestinfo.dnsserver'] -as [IPaddress]) -and (Test-NetConnection @TestNetConnectionSplat)) {
|
||||||
|
($ovfPropertyValues['guestinfo.dnsserver'])
|
||||||
|
} else {
|
||||||
|
('127.0.0.1')
|
||||||
|
}
|
||||||
|
Validate = $False
|
||||||
|
}
|
||||||
|
Set-DnsClientServerAddress @SetDnsClientServerAddressSplat
|
||||||
|
$ErrorActionPreference, $OldErrorActionPreference = $OldErrorActionPreference, $NULL
|
||||||
|
}
|
||||||
|
|
||||||
|
# Foo
|
||||||
|
|
||||||
|
# Iterate through and invoke all payload scripts
|
||||||
|
#! TODO: add registry values to determine which scripts have already been invoked (in case of intermediate reboots)
|
||||||
|
$GetItemSplat = @{
|
||||||
|
Path = "$($PSScriptRoot)\Scripts\*.ps1"
|
||||||
|
}
|
||||||
|
Get-Item @GetItemSplat | ForEach-Object {
|
||||||
|
Try {
|
||||||
|
$WriteEventLogSplat = @{
|
||||||
|
LogName = 'Application'
|
||||||
|
Source = 'OVF-Properties'
|
||||||
|
EntryType = 'Information'
|
||||||
|
EventID = 4
|
||||||
|
Message = "Running script: '$($_.FullName)'"
|
||||||
|
}
|
||||||
|
Write-EventLog @WriteEventLogSplat
|
||||||
|
& $_.FullName -Parameter $ovfPropertyValues
|
||||||
|
}
|
||||||
|
Catch {
|
||||||
|
$WriteEventLogSplat = @{
|
||||||
|
LogName = 'Application'
|
||||||
|
Source = 'OVF-Properties'
|
||||||
|
EntryType = 'Error'
|
||||||
|
EventID = 66
|
||||||
|
Message = $_.Exception.Message
|
||||||
|
}
|
||||||
|
Write-EventLog @WriteEventLogSplat
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$WriteEventLogSplat = @{
|
||||||
|
LogName = 'Application'
|
||||||
|
Source = 'OVF-Properties'
|
||||||
|
EntryType = 'Information'
|
||||||
|
EventID = 42
|
||||||
|
Message = 'OVF-Properties sequence applied and finished'
|
||||||
|
}
|
||||||
|
Write-EventLog @WriteEventLogSplat
|
||||||
|
& schtasks.exe /Change /TN 'OVF-Properties' /DISABLE
|
37
scripts/ADCS/payload/scripts/01.Foo.ps1
Normal file
37
scripts/ADCS/payload/scripts/01.Foo.ps1
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
#Requires -Modules 'NetSecurity'
|
||||||
|
Param(
|
||||||
|
[Parameter(Mandatory)]
|
||||||
|
[hashtable]$Parameter
|
||||||
|
)
|
||||||
|
|
||||||
|
If ($False) {
|
||||||
|
$GetContentSplat = @{
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
# Perform conversion to Yaml again, now with parsed file contents
|
||||||
|
$ConvertFromYamlSplat = @{
|
||||||
|
Yaml = $RawContent
|
||||||
|
AllDocuments = $True
|
||||||
|
}
|
||||||
|
$YamlDocuments = ConvertFrom-Yaml @ConvertFromYamlSplat
|
||||||
|
$Settings = $YamlDocuments[0..($YamlDocuments.Count - 2)]
|
||||||
|
}
|
||||||
|
Else {
|
||||||
|
$Settings = $YamlDocuments
|
||||||
|
}
|
||||||
|
|
||||||
|
#Foo
|
||||||
|
}
|
2
scripts/ADCS/payload/scripts/01.Foo.yml
Normal file
2
scripts/ADCS/payload/scripts/01.Foo.yml
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
Foo:
|
||||||
|
- Bar
|
39
scripts/Remove-Resources.ps1
Normal file
39
scripts/Remove-Resources.ps1
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
[CmdletBinding()]
|
||||||
|
Param(
|
||||||
|
[Parameter(Mandatory)]
|
||||||
|
[string]$VMName,
|
||||||
|
[Parameter(Mandatory)]
|
||||||
|
[string]$VSphereFQDN,
|
||||||
|
[Parameter(Mandatory)]
|
||||||
|
[string]$VSphereUsername,
|
||||||
|
[Parameter(Mandatory)]
|
||||||
|
[string]$VSpherePassword
|
||||||
|
)
|
||||||
|
|
||||||
|
$PowerCliConfigurationSplat = @{
|
||||||
|
Scope = 'User'
|
||||||
|
ParticipateInCEIP = $False
|
||||||
|
Confirm = $False
|
||||||
|
InvalidCertificateAction = 'Ignore'
|
||||||
|
}
|
||||||
|
Set-PowerCLIConfiguration @PowerCliConfigurationSplat
|
||||||
|
|
||||||
|
$ConnectVIServerSplat = @{
|
||||||
|
Server = $VSphereFQDN
|
||||||
|
User = "$VSphereUsername"
|
||||||
|
Password = "$VSpherePassword"
|
||||||
|
WarningAction = 'SilentlyContinue'
|
||||||
|
}
|
||||||
|
Connect-VIServer @ConnectVIServerSplat | Out-Null
|
||||||
|
|
||||||
|
$RemoveVMSplat = @{
|
||||||
|
VM = "$($VMName)*"
|
||||||
|
DeletePermanently = $True
|
||||||
|
Confirm = $False
|
||||||
|
ErrorAction = 'SilentlyContinue'
|
||||||
|
}
|
||||||
|
Remove-VM @RemoveVMSplat
|
||||||
|
|
||||||
|
# Also delete ISO/floppy?
|
||||||
|
|
||||||
|
Disconnect-VIServer * -Confirm:$False
|
55
scripts/Update-Manifest.ps1
Normal file
55
scripts/Update-Manifest.ps1
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
#Requires -Modules 'powershell-yaml'
|
||||||
|
[CmdletBinding()]
|
||||||
|
Param(
|
||||||
|
[Parameter(Mandatory)]
|
||||||
|
[ValidateScript({
|
||||||
|
If (Test-Path($_)) {
|
||||||
|
$True
|
||||||
|
} Else {
|
||||||
|
Throw "'$_' is not a valid filename (within working directory '$PWD'), or access denied; aborting."
|
||||||
|
}
|
||||||
|
})]
|
||||||
|
[string]$ManifestFileName
|
||||||
|
)
|
||||||
|
|
||||||
|
$GetItemSplat = @{
|
||||||
|
Path = $ManifestFileName
|
||||||
|
}
|
||||||
|
$ManifestFile = Get-Item @GetItemSplat
|
||||||
|
|
||||||
|
$SetLocationSplat = @{
|
||||||
|
Path = $ManifestFile.DirectoryName
|
||||||
|
}
|
||||||
|
Set-Location @SetLocationSplat
|
||||||
|
|
||||||
|
$GetContentSplat = @{
|
||||||
|
Path = $ManifestFile.FullName
|
||||||
|
}
|
||||||
|
$Manifest = Get-Content @GetContentSplat
|
||||||
|
|
||||||
|
$UpdatedManifest = ForEach ($Line in $Manifest) {
|
||||||
|
Write-Host "Processing '$($Line)' ..."
|
||||||
|
If ($Line -match '^SHA256\((.+)\)= ([0-9a-fA-F]{64})$') {
|
||||||
|
If (Test-Path $Matches[1]) {
|
||||||
|
$GetFileHashSplat = @{
|
||||||
|
Path = $Matches[1]
|
||||||
|
Algorithm = 'SHA256'
|
||||||
|
}
|
||||||
|
Write-Host "Updating checksum..."
|
||||||
|
"SHA256($($Matches[1]))= $((Get-FileHash @GetFileHashSplat).Hash)"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
If ($UpdatedManifest -ne $Null) {
|
||||||
|
$SetContentSplat = @{
|
||||||
|
Path = $ManifestFile.FullName
|
||||||
|
Value = $UpdatedManifest
|
||||||
|
Force = $True
|
||||||
|
Confirm = $False
|
||||||
|
}
|
||||||
|
Set-Content @SetContentSplat
|
||||||
|
} Else {
|
||||||
|
Write-Host "Failed updating manifest."
|
||||||
|
Exit 1
|
||||||
|
}
|
219
scripts/Update-OvfConfiguration.ps1
Normal file
219
scripts/Update-OvfConfiguration.ps1
Normal file
@ -0,0 +1,219 @@
|
|||||||
|
#Requires -Modules 'powershell-yaml'
|
||||||
|
[CmdletBinding()]
|
||||||
|
Param(
|
||||||
|
[Parameter(Mandatory)]
|
||||||
|
[ValidateScript({
|
||||||
|
If (Test-Path($_)) {
|
||||||
|
$True
|
||||||
|
} Else {
|
||||||
|
Throw "'$_' is not a valid filename (within working directory '$PWD'), or access denied; aborting."
|
||||||
|
}
|
||||||
|
})]
|
||||||
|
[string]$OVFFile
|
||||||
|
)
|
||||||
|
|
||||||
|
$GetContentSplat = @{
|
||||||
|
Path = "$($PSScriptRoot)\$($MyInvocation.MyCommand)".Replace('.ps1', ".yml")
|
||||||
|
Raw = $True
|
||||||
|
}
|
||||||
|
$RawContent = Get-Content @GetContentSplat
|
||||||
|
$ConvertFromYamlSplat = @{
|
||||||
|
Yaml = $RawContent
|
||||||
|
AllDocuments = $True
|
||||||
|
}
|
||||||
|
$OVFConfig = ConvertFrom-Yaml @ConvertFromYamlSplat
|
||||||
|
|
||||||
|
$SourceFile = Get-Item -Path $OVFFile
|
||||||
|
$GetContentSplat = @{
|
||||||
|
Path = $SourceFile.FullName
|
||||||
|
}
|
||||||
|
$XML = [xml](Get-Content @GetContentSplat)
|
||||||
|
$NS = [System.Xml.XmlNamespaceManager]$XML.NameTable
|
||||||
|
[void]$NS.AddNamespace('Any', $XML.DocumentElement.xmlns)
|
||||||
|
|
||||||
|
If ($OVFConfig.DeploymentConfigurations.Count -gt 0) {
|
||||||
|
$XMLSection = $XML.CreateElement('DeploymentOptionSection', $XML.DocumentElement.xmlns)
|
||||||
|
$XMLSectionInfo = $XML.CreateElement('Info', $XML.DocumentElement.xmlns)
|
||||||
|
$XMLSectionInfo.InnerText = 'Deployment Type'
|
||||||
|
[void]$XMLSection.AppendChild($XMLSectionInfo)
|
||||||
|
|
||||||
|
ForEach ($Configuration in $OVFConfig.DeploymentConfigurations) {
|
||||||
|
$XMLConfig = $XML.CreateElement('Configuration', $XML.DocumentElement.xmlns)
|
||||||
|
|
||||||
|
$XMLConfigAttrId = $XML.CreateAttribute('id', $XML.DocumentElement.ovf)
|
||||||
|
$XMLConfigAttrId.Value = $Configuration.Id
|
||||||
|
|
||||||
|
$XMLConfigLabel = $XML.CreateElement('Label', $XML.DocumentElement.xmlns)
|
||||||
|
$XMLConfigLabel.InnerText = $Configuration.Label
|
||||||
|
|
||||||
|
$XMLConfigDescription = $XML.CreateElement('Description', $XML.DocumentElement.xmlns)
|
||||||
|
$XMLConfigDescription.InnerText = $Configuration.Description
|
||||||
|
|
||||||
|
[void]$XMLConfig.Attributes.Append($XMLConfigAttrId)
|
||||||
|
[void]$XMLConfig.AppendChild($XMLConfigLabel)
|
||||||
|
[void]$XMLConfig.AppendChild($XMLConfigDescription)
|
||||||
|
|
||||||
|
[void]$XMLSection.AppendChild($XMLConfig)
|
||||||
|
}
|
||||||
|
[void]$XML.SelectSingleNode('//Any:Envelope', $NS).InsertAfter($XMLSection, $XML.SelectSingleNode('//Any:NetworkSection', $NS))
|
||||||
|
Write-Host "Inserted 'DeploymentOptionSection' with $($Configuration.Count) nodes"
|
||||||
|
}
|
||||||
|
|
||||||
|
$XMLAttrTransport = $XML.CreateAttribute('transport', $XML.DocumentElement.ovf)
|
||||||
|
$XMLAttrTransport.Value = 'com.vmware.guestInfo'
|
||||||
|
[void]$XML.SelectSingleNode('//Any:VirtualHardwareSection', $NS).Attributes.Append($XMLAttrTransport)
|
||||||
|
|
||||||
|
$XMLProductSection = $XML.SelectSingleNode('//Any:ProductSection', $NS)
|
||||||
|
If ($XMLProductSection -eq $Null) {
|
||||||
|
$XMLProductSection = $XML.CreateElement('ProductSection', $XML.DocumentElement.xmlns)
|
||||||
|
[void]$XML.SelectSingleNode('//Any:VirtualSystem', $NS).AppendChild($XMLProductSection)
|
||||||
|
Write-Host "Inserted 'ProductSection'"
|
||||||
|
} Else {
|
||||||
|
ForEach ($Child in $XMLProductSection.SelectNodes('//Any:ProductSection/child::*', $NS)) {
|
||||||
|
[void]$Child.ParentNode.RemoveChild($Child)
|
||||||
|
}
|
||||||
|
Write-Host "Destroyed pre-existing children in 'ProductSection'"
|
||||||
|
}
|
||||||
|
$XMLProductSectionInfo = $XML.CreateElement('Info', $XML.DocumentElement.xmlns)
|
||||||
|
$XMLProductSectionInfo.InnerText = 'Information about the installed software'
|
||||||
|
[void]$XMLProductSection.AppendChild($XMLProductSectionInfo)
|
||||||
|
Write-Host "Inserted new 'Info' into 'ProductSection'"
|
||||||
|
|
||||||
|
ForEach ($Category in $OVFConfig.PropertyCategories) {
|
||||||
|
If ($Category.Name -ne '') {
|
||||||
|
$XMLCategory = $XML.CreateElement('Category', $XML.DocumentElement.xmlns)
|
||||||
|
$XMLCategory.InnerText = $Category.Name
|
||||||
|
[void]$XMLProductSection.AppendChild($XMLCategory)
|
||||||
|
Write-Host "Inserted new 'Category' into 'ProductSection'"
|
||||||
|
}
|
||||||
|
|
||||||
|
ForEach ($Property in $Category.ProductProperties) {
|
||||||
|
$XMLProperty = $XML.CreateElement('Property', $XML.DocumentElement.xmlns)
|
||||||
|
|
||||||
|
$XMLPropertyAttrKey = $XML.CreateAttribute('key', $XML.DocumentElement.ovf)
|
||||||
|
$XMLPropertyAttrKey.Value = $Property.Key
|
||||||
|
$XMLPropertyAttrType = $XML.CreateAttribute('type', $XML.DocumentElement.ovf)
|
||||||
|
Switch -regex ($Property.Type) {
|
||||||
|
'boolean' {
|
||||||
|
$XMLPropertyAttrType.Value = 'boolean'
|
||||||
|
}
|
||||||
|
'int' {
|
||||||
|
$XMLPropertyAttrType.Value = 'uint8'
|
||||||
|
$Qualifiers = @()
|
||||||
|
If ($Property.Type -match 'int\((\d*)\.\.(\d*)\)') {
|
||||||
|
If ($Matches[1]) {
|
||||||
|
$Qualifiers += "MinValue($($Matches[1]))"
|
||||||
|
}
|
||||||
|
If ($Matches[2]) {
|
||||||
|
$Qualifiers += "MaxValue($($Matches[2]))"
|
||||||
|
}
|
||||||
|
$XMLPropertyAttrQualifiers = $XML.CreateAttribute('qualifiers', $XML.DocumentElement.ovf)
|
||||||
|
$XMLPropertyAttrQualifiers.Value = $Qualifiers -join ' '
|
||||||
|
[void]$XMLProperty.Attributes.Append($XMLPropertyAttrQualifiers)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
'ip' {
|
||||||
|
$XMLPropertyAttrType.Value = 'string'
|
||||||
|
$XMLPropertyAttrQualifiers = $XML.CreateAttribute('qualifiers', $XML.DocumentElement.vmw)
|
||||||
|
$XMLPropertyAttrQualifiers.Value = 'Ip'
|
||||||
|
[void]$XMLProperty.Attributes.Append($XMLPropertyAttrQualifiers)
|
||||||
|
}
|
||||||
|
'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 ($Matches[1]) {
|
||||||
|
$Qualifiers += "MinLen($($Matches[1]))"
|
||||||
|
}
|
||||||
|
If ($Matches[2]) {
|
||||||
|
$Qualifiers += "MaxLen($($Matches[2]))"
|
||||||
|
}
|
||||||
|
$XMLPropertyAttrQualifiers = $XML.CreateAttribute('qualifiers', $XML.DocumentElement.ovf)
|
||||||
|
$XMLPropertyAttrQualifiers.Value = $Qualifiers -join ' '
|
||||||
|
[void]$XMLProperty.Attributes.Append($XMLPropertyAttrQualifiers)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
'string' {
|
||||||
|
$XMLPropertyAttrType.Value = 'string'
|
||||||
|
$Qualifiers = @()
|
||||||
|
If ($Property.Type -match 'string\((\d*)\.\.(\d*)\)') {
|
||||||
|
If ($Matches[1]) {
|
||||||
|
$Qualifiers += "MinLen($($Matches[1]))"
|
||||||
|
}
|
||||||
|
If ($Matches[2]) {
|
||||||
|
$Qualifiers += "MaxLen($($Matches[2]))"
|
||||||
|
}
|
||||||
|
$XMLPropertyAttrQualifiers = $XML.CreateAttribute('qualifiers', $XML.DocumentElement.ovf)
|
||||||
|
$XMLPropertyAttrQualifiers.Value = $Qualifiers -join ' '
|
||||||
|
[void]$XMLProperty.Attributes.Append($XMLPropertyAttrQualifiers)
|
||||||
|
} ElseIf ($Property.Type -match 'string\[(.*)\]') {
|
||||||
|
$XMLPropertyAttrQualifiers = $XML.CreateAttribute('qualifiers', $XML.DocumentElement.ovf)
|
||||||
|
$XMLPropertyAttrQualifiers.Value = "ValueMap{$($Matches[1] -replace '","', '", "')}"
|
||||||
|
[void]$XMLProperty.Attributes.Append($XMLPropertyAttrQualifiers)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$XMLPropertyAttrUserConfigurable = $XML.CreateAttribute('userConfigurable', $XML.DocumentElement.ovf)
|
||||||
|
$XMLPropertyAttrUserConfigurable.Value = "$([boolean]$Property.UserConfigurable)".ToLower()
|
||||||
|
$XMLPropertyAttrValue = $XML.CreateAttribute('value', $XML.DocumentElement.ovf)
|
||||||
|
If ($Property.Type -eq 'boolean') {
|
||||||
|
$XMLPropertyAttrValue.Value = "$([boolean]$Property.DefaultValue)".ToLower()
|
||||||
|
} Else {
|
||||||
|
$XMLPropertyAttrValue.Value = $Property.DefaultValue
|
||||||
|
}
|
||||||
|
[void]$XMLProperty.Attributes.Append($XMLPropertyAttrKey)
|
||||||
|
[void]$XMLProperty.Attributes.Append($XMLPropertyAttrType)
|
||||||
|
[void]$XMLProperty.Attributes.Append($XMLPropertyAttrUserConfigurable)
|
||||||
|
[void]$XMLProperty.Attributes.Append($XMLPropertyAttrValue)
|
||||||
|
|
||||||
|
If ($Property.Label) {
|
||||||
|
$XMLPropertyLabel = $XML.CreateElement('Label', $XML.DocumentElement.xmlns)
|
||||||
|
$XMLPropertyLabel.InnerText = $Property.Label
|
||||||
|
[void]$XMLProperty.AppendChild($XMLPropertyLabel)
|
||||||
|
}
|
||||||
|
If ($Property.Description) {
|
||||||
|
$XMLPropertyDescription = $XML.CreateElement('Description', $XML.DocumentElement.xmlns)
|
||||||
|
$XMLPropertyDescription.InnerText = $Property.Description
|
||||||
|
[void]$XMLProperty.AppendChild($XMLPropertyDescription)
|
||||||
|
}
|
||||||
|
|
||||||
|
If (($Property.Configurations.Count -eq 1) -and ($Property.Configurations -eq '*')) {
|
||||||
|
$XMLPropertyAttrConfiguration = $XML.CreateAttribute('configuration', $XML.DocumentElement.ovf)
|
||||||
|
$XMLPropertyAttrConfiguration.Value = $OVFConfig.DeploymentConfigurations.Id -join ' '
|
||||||
|
[void]$XMLProperty.Attributes.Append($XMLPropertyAttrConfiguration)
|
||||||
|
} ElseIf ($Property.Configurations.Count -gt 0) {
|
||||||
|
$XMLPropertyAttrConfiguration = $XML.CreateAttribute('configuration', $XML.DocumentElement.ovf)
|
||||||
|
$XMLPropertyAttrConfiguration.Value = $Property.Configurations -join ' '
|
||||||
|
[void]$XMLProperty.Attributes.Append($XMLPropertyAttrConfiguration)
|
||||||
|
}
|
||||||
|
|
||||||
|
If ($Property.Value.Count -eq 1) {
|
||||||
|
$XMLPropertyAttrValue = $XML.CreateAttribute('value', $XML.DocumentElement.ovf)
|
||||||
|
$XMLPropertyAttrValue.Value = $Property.Value
|
||||||
|
[void]$XMLProperty.Attributes.Append($XMLPropertyAttrValue)
|
||||||
|
} ElseIf ($Property.Value.Count -gt 1) {
|
||||||
|
ForEach ($Value in $Property.Value) {
|
||||||
|
$XMLValue = $XML.CreateElement('Value', $XML.DocumentElement.xmlns)
|
||||||
|
|
||||||
|
$XMLValueAttrValue = $XML.CreateAttribute('value', $XML.DocumentElement.ovf)
|
||||||
|
$XMLValueAttrValue.Value = $Value
|
||||||
|
$XMLValueAttrConfiguration = $XML.CreateAttribute('configuration', $XML.DocumentElement.ovf)
|
||||||
|
$XMLValueAttrConfiguration.Value = $Value
|
||||||
|
|
||||||
|
[void]$XMLValue.Attributes.Append($XMLValueAttrValue)
|
||||||
|
[void]$XMLValue.Attributes.Append($XMLValueAttrConfiguration)
|
||||||
|
|
||||||
|
[void]$XMLProperty.AppendChild($XMLValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[void]$XMLProductSection.AppendChild($XMLProperty)
|
||||||
|
}
|
||||||
|
Write-Host "Inserted $($Category.ProductProperties.Count) new node(s) into 'ProductSection'"
|
||||||
|
}
|
||||||
|
|
||||||
|
$XML.Save($SourceFile.FullName)
|
75
scripts/Update-OvfConfiguration.yml
Normal file
75
scripts/Update-OvfConfiguration.yml
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
DeploymentConfigurations:
|
||||||
|
- Id: standalone-root
|
||||||
|
Label: Root Certificate Authority
|
||||||
|
Description: Root CA with self-signed certificate; should be kept turned off
|
||||||
|
- Id: enterprise-intermediate
|
||||||
|
Label: Subordinate enterprise Certificate Authority
|
||||||
|
Description: Subordinate CA on domain-member server; kept online to service certificate requests/enrollment and host CRL
|
||||||
|
- Id: standalone-intermediate
|
||||||
|
Label: Subordinate standalone Certificate Authority
|
||||||
|
Description: Subordinate CA on standalone server; kept online to service certificate requests and host CRL
|
||||||
|
PropertyCategories:
|
||||||
|
- Name: ''
|
||||||
|
ProductProperties:
|
||||||
|
- Key: deployment.type
|
||||||
|
Type: string
|
||||||
|
Value:
|
||||||
|
- standalone-root
|
||||||
|
- enterprise-intermediate
|
||||||
|
- standalone-intermediate
|
||||||
|
UserConfigurable: false
|
||||||
|
- Name: 1) Operating System
|
||||||
|
ProductProperties:
|
||||||
|
- Key: guestinfo.hostname
|
||||||
|
Type: string(1..15)
|
||||||
|
Label: Hostname*
|
||||||
|
Description: '(max length: 15 characters)'
|
||||||
|
DefaultValue: ''
|
||||||
|
Configurations: '*'
|
||||||
|
UserConfigurable: true
|
||||||
|
- Name: 2) Networking
|
||||||
|
ProductProperties:
|
||||||
|
- Key: guestinfo.ipaddress
|
||||||
|
Type: ip
|
||||||
|
Label: IP Address*
|
||||||
|
Description: ''
|
||||||
|
DefaultValue: ''
|
||||||
|
Configurations: '*'
|
||||||
|
UserConfigurable: true
|
||||||
|
- Key: guestinfo.prefixlength
|
||||||
|
Type: int(8..32)
|
||||||
|
Label: Subnet prefix length*
|
||||||
|
Description: ''
|
||||||
|
DefaultValue: '24'
|
||||||
|
Configurations: '*'
|
||||||
|
UserConfigurable: true
|
||||||
|
- Key: guestinfo.dnsserver
|
||||||
|
Type: ip
|
||||||
|
Label: DNS server*
|
||||||
|
Description: ''
|
||||||
|
DefaultValue: ''
|
||||||
|
Configurations: '*'
|
||||||
|
UserConfigurable: true
|
||||||
|
- Key: guestinfo.gateway
|
||||||
|
Type: ip
|
||||||
|
Label: Gateway*
|
||||||
|
Description: ''
|
||||||
|
DefaultValue: ''
|
||||||
|
Configurations: '*'
|
||||||
|
UserConfigurable: true
|
||||||
|
- Name: 3) Active Directory Certificate Services
|
||||||
|
ProductProperties:
|
||||||
|
- Key: adcsconfig.foo
|
||||||
|
Type: string(1..)
|
||||||
|
Label: Foo*
|
||||||
|
Description: ''
|
||||||
|
DefaultValue: ''
|
||||||
|
Configurations: '*'
|
||||||
|
UserConfigurable: true
|
||||||
|
- Key: adcsconfig.bar
|
||||||
|
Type: string(1..)
|
||||||
|
Label: Bar*
|
||||||
|
Description: ''
|
||||||
|
DefaultValue: ''
|
||||||
|
Configurations: '*'
|
||||||
|
UserConfigurable: true
|
Reference in New Issue
Block a user