Skip to content

Commit 1d7e6df

Browse files
committed
chore: added pre-written infrastrcture deployment function
1 parent 9cd32e7 commit 1d7e6df

2 files changed

Lines changed: 193 additions & 6 deletions

File tree

Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
function Deploy-AGInfrastructure {
2+
<#
3+
TODO: Create 'PAW' as a Custom Role that includes RSAT.
4+
TODO: Accept Roles as Parameter.
5+
#>
6+
7+
[CmdletBinding()]
8+
param (
9+
[PsfValidatePattern('^\w{1,11}$', ErrorMessage = 'Lab name must be no longer than 11 characters and only contain letters and numbers.')]
10+
$Name = 'Locksmith',
11+
[PsfValidatePattern('\.', ErrorMessage = 'Domain must contain at least one dot.')]
12+
$Domain = 'adcs.goat',
13+
$ExternalSwitch = 'External Switch',
14+
$Sources = (Get-LabSourcesLocation),
15+
$LabsRoot = "$((Get-PSFConfig -Module AutomatedLab -Name LabAppDataRoot).Value)\Labs", # Not currently needed, but I like it.,
16+
[switch]$Confirm
17+
)
18+
19+
<#
20+
#requires -Modules Hyper-V, AutomatedLab -Version 7 -RunAsAdministrator
21+
#>
22+
23+
Write-Verbose -Message @"
24+
25+
----------------------------------------------------
26+
| Initial Configuration |
27+
----------------------------------------------------
28+
29+
Name = $Name
30+
Domain = $Domain
31+
ExternalSwitch = $ExternalSwitch
32+
Sources = $Sources
33+
LabRoot = $LabsRoot
34+
"@
35+
36+
# Confirm lab name is unique on this host.
37+
while ((Get-Lab -List) -contains $Name) {
38+
Write-Host
39+
Write-Warning -Message "A lab named `"$Name`" already exists on this host."
40+
Write-Host "Please select a new lab name: " -NoNewline
41+
$Name = Read-Host
42+
}
43+
44+
# Import existing labs and add their domains to an array.
45+
Write-Host "`nImporting existing labs to confirm the new root domain name `"$Domain`" is unique."
46+
$ExistingDomains = Get-Lab -List | ForEach-Object {
47+
Import-Lab -Name $_
48+
Get-LabVM | Select-Object DomainName
49+
}
50+
51+
$ExistingDomains = $ExistingDomains | Sort-Object -Property DomainName -Unique
52+
if ($ExistingDomains) { Write-Verbose "Existing Domains: $($ExistingDomains.DomainName)" }
53+
54+
# Confirm root domain name is unique on this host.
55+
while ($ExistingDomains.DomainName -contains $Domain) {
56+
Write-Host
57+
Write-Warning -Message "A lab using the domain `"$Domain`" already exists on this host."
58+
Write-Host "Please select a new root domain name: " -NoNewline
59+
$Domain = Read-Host
60+
}
61+
62+
# Create a Hyper-V External Switch if none exists.
63+
while (-not (Get-VMSwitch | Where-Object Name -EQ $ExternalSwitch)) {
64+
#region Select NetAdapter for Use in Lab
65+
$netIPAddressCollection = Get-NetIPAddress | Where-Object {
66+
$_.IPAddress -notmatch '^169.254|^127.0.0' -and
67+
$_.InterfaceAlias -notmatch 'VMware' -and
68+
$_.AddressFamily -eq 'IPv4' -and
69+
$_.PrefixLength -eq 24 -and
70+
$_.PrefixOrigin -eq 'Dhcp'
71+
}
72+
73+
Write-Host @"
74+
This script is designed to use a single network adapter with the following configuration:
75+
76+
- has an IPv4 address
77+
- does not have an IP address in a link-local block
78+
- is configured for DHCP
79+
- has a subnet mask of /24
80+
81+
Only network adapters meeting this configuration are shown below.
82+
83+
Select the network adapter you'd like to use in your lab.
84+
"@
85+
86+
# Enumerate network adapters on the host.
87+
$i = 0
88+
$netIPAddressCollection | ForEach-Object {
89+
$i++
90+
Write-Host " ${i}: $($_.InterfaceAlias) ($($_.IPAddress))"
91+
}
92+
[int]$adapterIndex = Read-Host -Prompt "Please enter a number `[1-$i`]"
93+
94+
$adapterIndex = $adapterIndex - 1
95+
96+
$NetAdapterName = $netIPAddressCollection[$($adapterIndex)].InterfaceAlias
97+
#endregion Select NetAdapter for Use in Lab
98+
99+
# Create a new External Switch named $ExternalSwitch aka 'vEthernet ($ExternalSwitch)'
100+
try {
101+
New-VMSwitch -Name $ExternalSwitch -NetAdapterName $NetAdapterName -ErrorAction Stop
102+
Start-Sleep -Seconds 5
103+
} catch {
104+
throw $_
105+
}
106+
}
107+
108+
# Get IP Address of External Switch
109+
[string]$NetAdapterIP = (Get-NetIPConfiguration -InterfaceAlias "vEthernet ($ExternalSwitch)").IPv4Address
110+
111+
# Create required addresses
112+
if ($NetAdapterIP -match '(?:\d{1,3}\.){3}') {
113+
$BaseAddress = $matches[0]
114+
$NetworkAddress = $BaseAddress + '0'
115+
$Gateway = $BaseAddress + '1'
116+
}
117+
118+
# Get IP Address of other machines in subnet
119+
$ExistingIPs = Get-VM |
120+
Where-Object State -EQ Running |
121+
Select-Object -ExpandProperty NetworkAdapters |
122+
Select-Object -ExpandProperty IPAddresses |
123+
ForEach-Object {
124+
if ($_ -match '(?:\d{1,3}\.){3}') { $_ }
125+
}
126+
127+
# Pick IP Addresses for new VMs
128+
$NewIPs = @{}
129+
$Roles = @('DC', 'CA', 'PAW')
130+
$RoleIndex = 0
131+
132+
for ($i = 3; $i -lt 255 -and $RoleIndex -lt $Roles.Count; $i++) {
133+
$CandidateIP = "$BaseAddress$i"
134+
if ($ExistingIPs -notcontains $CandidateIP) {
135+
$NewIPs[$Roles[$RoleIndex]] = $CandidateIP
136+
$RoleIndex++
137+
}
138+
}
139+
140+
# Create IPs for each role.
141+
$Roles | ForEach-Object {
142+
New-Variable -Name "${_}IP" -Value $NewIPs[$_]
143+
}
144+
145+
if (-not $Confirm) {
146+
Write-PSFHostColor @"
147+
----------------------------------------------------
148+
| Lab Configuration |
149+
----------------------------------------------------
150+
Name: <c='em'>$Name</c>
151+
Root Domain: <c='em'>$Domain</c>
152+
Network Address: <c='em'>$NetworkAddress</c>
153+
Gateway: <c='em'>$Gateway</c>
154+
Domain Controller IP: <c='em'>$DCIP</c>
155+
Certification Authority IP: <c='em'>$CAIP</c>
156+
Privileged Access Workstation IP: <c='em'>$PAWIP</c>
157+
"@
158+
159+
$Answer = Get-PSFUserChoice -Caption 'Continue with deployment?' -Options Yes, No
160+
161+
if ($Answer -eq 1) { exit }
162+
}
163+
164+
# Define the lab + hypervisor
165+
New-LabDefinition -Name $Name -DefaultVirtualizationEngine HyperV
166+
167+
# Use existing External Switch created or discovered above
168+
Add-LabVirtualNetworkDefinition -Name $ExternalSwitch -AddressSpace "$NetAdapterIP/24"
169+
170+
# Set default parameters for all machines in the lab
171+
$PSDefaultParameterValues = @{
172+
'Add-LabMachineDefinition:Network' = $ExternalSwitch
173+
'Add-LabMachineDefinition:ToolsPath' = "$Sources\Tools"
174+
'Add-LabMachineDefinition:MinMemory' = 512MB
175+
'Add-LabMachineDefinition:Memory' = 1GB
176+
'Add-LabMachineDefinition:MaxMemory' = 4GB
177+
'Add-LabMachineDefinition:Processors' = 2
178+
'Add-LabMachineDefinition:DomainName' = $Domain
179+
'Add-LabMachineDefinition:Gateway' = $Gateway
180+
'Add-LabMachineDefinition:DnsServer1' = $DCIP
181+
'Add-LabMachineDefinition:OperatingSystem' = 'Windows Server 2022 Datacenter (Desktop Experience)'
182+
}
183+
184+
Add-LabMachineDefinition -Name "$Name-DC" -Roles RootDC -IpAddress $DCIP
185+
Add-LabMachineDefinition -Name "$Name-CA" -Roles CaRoot -IpAddress $CAIP
186+
Add-LabMachineDefinition -Name "$Name-PAW" -IpAddress $PAWIP
187+
188+
Install-Lab
189+
190+
Install-LabWindowsFeature -FeatureName RSAT -ComputerName "$Name-PAW" -IncludeAllSubFeature
191+
192+
Show-LabDeploymentSummary
193+
}

requirements.psd1

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,4 @@
2323
'PSScriptAnalyzer' = @{
2424
Version = '1.19.1'
2525
}
26-
'AutomatedLab' = @{
27-
Version = '5.59.0'
28-
}
29-
'PSCertutil' = @{
30-
Version = '0.0.1'
31-
}
3226
}

0 commit comments

Comments
 (0)