Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Root-CA Build
#region Configuration
$VMName = 'Root-CA'
$DSCConfigSCript = "$PSScriptRoot\RootCA_Config.ps1"
$Start_Deploy_param = @{
VHDSourcePath = 'G:\UpdateOut\Template_Production.vhdx'
InitializeScriptPath = "$PSScriptRoot\VMScripts\FirstRun.ps1"
HelperScriptPath = "$PSScriptRoot\Helpers"
AtStartupScriptPath = "$PSScriptRoot\VMScripts\SSC-Init.ps1"
VMName = $VMName
VMSwitch = 'testlab'
}
$Get_VMCert_param = @{
VMName = $VMName
CertOutPath = "$PSScriptRoot"
VMCertPath = '\PStemp\CertFile\DSCSelfSignedCertificate.cer'
}
$Set_VmLcm_param = @{
InitializeScriptPath = "$PSScriptRoot\VMScripts\DSC-Init.ps1"
LocalhostMofFolder = "$PSScriptRoot\RootCA"
DSCResorcePath = "$PSScriptRoot\Resorces_RootCA"
}
if (-not (Test-Path -Path $PSScriptRoot\$VMName.LocalAdminCred.xml))
{
Get-Credential -Message 'RootCA LocalAdmin account' |
Export-Clixml -Path $PSScriptRoot\$VMName.LocalAdminCred.xml
}
if (-not (Test-Path -Path $PSScriptRoot\$VMName.RemoteUserCred.xml))
{
Get-Credential -Message 'User for remote share with source.wim' |
Export-Clixml -Path $PSScriptRoot\$VMName.RemoteUserCred.xml
}
#endregion
#region Main script
#region Import Supporting functions
Import-Module -Name "$PSScriptRoot\Functions"
#endregion
#region Create VM and get Cert
Start-Deploy @Start_Deploy_param -Verbose
Get-VMCert @Get_VMCert_param -Verbose
#endregion
#region CreateMOF
. "$DSCConfigSCript"
#endregion
#region start DSC
set-VmLcm -VMName $VMName @Set_VmLcm_param -verbose
Start-VM -VMName $VMName
#endregion
#endregion
Remove-Module -Name Functions
#region cleanup
Start-Transcript -Path $PSScriptRoot\DSC-Init.log
Get-ScheduledTask -TaskName AtStartup | Unregister-ScheduledTask -Confirm:$false
Remove-Item -Path c:\unattend.xml
#endregion
#region Start-DSC
Update-xDscEventLogStatus -Channel Analytic -Status Enabled
Update-xDscEventLogStatus -Channel Debug -Status Enabled
Set-DscLocalConfigurationManager -Path "$PSScriptRoot\ServerConfig" -Verbose
Start-DscConfiguration -Path "$PSScriptRoot\ServerConfig" -Force -Wait -Verbose
#endregion
Stop-Transcript
#requires -Version 2 -Modules ScheduledTasks
Start-Transcript -Path $PSScriptRoot\FirstRun.log
#Create AtStartup Task.
$Paramaters = @{
Action = New-ScheduledTaskAction -Execute '%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe' -Argument '-NoProfile -ExecutionPolicy Bypass -File C:\PSTemp\AtStartup.ps1'
Trigger = New-ScheduledTaskTrigger -AtStartup
Settings = New-ScheduledTaskSettingsSet
}
$TaskObject = New-ScheduledTask @Paramaters
Register-ScheduledTask AtStartup -InputObject $TaskObject -User 'nt authority\system' -Verbose
Start-Sleep -Seconds 20
Restart-Computer -Verbose -Force
Stop-Transcript
#requires -Version 1
. $PSScriptRoot\Get-VmCert.ps1
. $PSScriptRoot\Set-VmLcm.ps1
. $PSScriptRoot\Start-Deploy.ps1
function Get-VMCert
{
[CmdletBinding()]
Param
(
$VirtualHardDiskRootPath = (Get-VMHost).VirtualHardDiskPath,
# Path to Virtual Machine definition
$VirtualMachinePath = (Get-VMHost).VirtualMachinePath,
# Name for the VM
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[ValidateScript({
((Get-VM $_ -ErrorAction SilentlyContinue) -or
(Test-Path -Path "$VirtualHardDiskRootPath\$_.vhdx"))
})]
$VMName,
# Path to location to store cert
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[ValidateScript({
Test-Path $_ -PathType Container
})]
$CertOutPath,
# location of vert relitive to C: of VM
$VMCertPath
)
$ParametersToPass = @{}
foreach ($key in ('Whatif', 'Verbose', 'Debug'))
{
if ($PSBoundParameters.ContainsKey($key))
{
$ParametersToPass[$key] = $PSBoundParameters[$key]
}
}
$vhdPath = "$VirtualHardDiskRootPath\$VMName.vhdx"
$MountPath = "$env:temp\$([System.IO.Path]::GetRandomFileName())"
try
{
if (Get-VM $VMName | Where-Object -Property state -EQ -Value 'running')
{
Stop-VM $VMName
while (Get-VM $VMName | Where-Object -Property state -EQ -Value 'running')
{
Write-Verbose -Message "Wating for $VMName to stop"
Start-Sleep -Seconds 30
}
}
Write-Verbose -Message "[$vhdPath] [$MountPath]"
mkdir $MountPath -ErrorAction Stop @ParametersToPass
Mount-WindowsImage -ImagePath "$vhdPath" -Path "$MountPath" -Index 1 -ErrorAction Stop @ParametersToPass
Copy-Item "$MountPath\$VMCertPath" "$CertOutPath\$VMName.crt"
}
catch
{
$msg = "Failed $($_.Exception.Message)"
Write-Error $msg
throw 'Error extracting Certificate'
}
finally
{
Dismount-WindowsImage -Path "$MountPath" -Discard @ParametersToPass
}
}
if (-not ($vmname))
{
$vmname = 'Root-CA'
}
$certpath = "$PSScriptRoot\$vmname.crt"
if (-not(Test-Path $certpath))
{
throw 'Certificate not found'
}
$cert = "$PSScriptRoot\$vmname.crt"
$certPrint = New-Object -TypeName System.Security.Cryptography.X509Certificates.X509Certificate2
$certPrint.Import("$cert")
try
{
$LocalAdmin = Import-Clixml -Path $PSScriptRoot\$vmname.LocalAdminCred.xml
$RemoteUser = Import-Clixml -Path $PSScriptRoot\$vmname.RemoteUserCred.xml
}
catch
{
throw 'error importing passwords from xml'
}
$ConfigData = @{
AllNodes = @(
@{
NodeName = 'localhost'
CertificateFile = "$PSScriptRoot\$vmname.crt"
Thumbprint = "$($certPrint.Thumbprint)"
#PSDscAllowPlainTextPassword = $true;
};
)
}
configuration RootCA
{
Import-DscResource -ModuleName xComputerManagement, xAdcsDeployment, xNetworking,
PSDesiredStateConfiguration
node $AllNodes.NodeName
{
xIPAddress Ethernet
{
InterfaceAlias = 'Ethernet 4'
IPAddress = '10.20.1.51'
AddressFamily = 'IPv4'
SubnetMask = 24
}
User LocalAdmin
{
UserName = 'Administrator'
Disabled = $false
Ensure = 'Present'
Password = $LocalAdmin
PasswordChangeNotAllowed = $false
PasswordNeverExpires = $true
}
xComputer ComputerName
{
Name = 'Root-CA'
WorkGroupName = 'Workgroup'
}
File Source
{
DestinationPath = 'c:\Source.wim'
Credential = $RemoteUser
Ensure = 'Present'
SourcePath = '\\10.20.1.41\DSC\WIM\Source.wim'
Type = 'File'
DependsOn = '[xIPAddress]Ethernet'
}
WindowsFeature ADCS_Cert_Authority
{
Name = 'ADCS-Cert-Authority'
DependsOn = '[File]Source'
Ensure = 'Present'
Source = 'WIM:c:\Source.wim:1'
}
xAdcsCertificationAuthority Root_CA
{
CAType = 'StandaloneRootCA'
Credential = $LocalAdmin
CACommonName = 'Root-CA'
DependsOn = '[WindowsFeature]ADCS_Cert_Authority', '[xComputer]ComputerName'
Ensure = 'Present'
}
Script 'SetRevocationList'
{
GetScript = {
(Get-CACrlDistributionPoint).Uri
}
SetScript = {
$crllist = Get-CACrlDistributionPoint; foreach ($crl in $crllist)
{
Remove-CACrlDistributionPoint $crl.uri -Force
}
Add-CACRLDistributionPoint -Uri C:\Windows\System32\CertSrv\CertEnroll\%3%8.crl -PublishToServer -Force
Add-CACRLDistributionPoint -Uri http://pki.contoso.com/pki/%3%8.crl -AddToCertificateCDP -Force
$aialist = Get-CAAuthorityInformationAccess; foreach ($aia in $aialist)
{
Remove-CAAuthorityInformationAccess $aia.uri -Force
}
certutil.exe -setreg CA\CRLOverlapPeriodUnits 12
certutil.exe -setreg CA\CRLOverlapPeriod 'Hours'
certutil.exe -setreg CA\ValidityPeriodUnits 10
certutil.exe -setreg CA\ValidityPeriod 'Years'
certutil.exe -setreg CA\AuditFilter 127
Restart-Service -Name certsvc
certutil.exe -crl
}
TestScript = {
if ((Get-CACrlDistributionPoint).Uri -contains 'http://pki.contoso.com/pki/<CAName><CRLNameSuffix>.crl')
{
return $true
}
else
{
return $false
}
}
DependsOn = '[xAdcsCertificationAuthority]Root_CA'
}
LocalConfigurationManager
{
CertificateId = $node.Thumbprint
ConfigurationMode = 'ApplyandAutoCorrect'
RebootNodeIfNeeded = $true
}
}
}
RootCA -ConfigurationData $ConfigData -OutputPath "$PSScriptRoot\RootCA"
Start-Transcript -Path $PSScriptRoot\SSC-Init.log
. "$($PSScriptRoot)\New-SelfSignedCertificateEx.ps1"
$cert = Get-ChildItem -Path Cert:\LocalMachine\My | Where-Object -FilterScript {
$_.Subject -eq 'CN=DSC SelfSigned Certificate'
}
if (-not $cert)
{
$pfxfile = Get-ChildItem -Path "$PSScriptRoot\*DSC Test Certificate.pfx" | Select-Object -First 1
if (-not $pfxfile)
{
$pfxfile = Get-ChildItem -Path '.\*DSC Test Certificate.pfx' | Select-Object -First 1
}
if ($pfxfile)
{
$password = ConvertTo-SecureString -String 'password' -Force -AsPlainText
Import-PfxCertificate -FilePath $pfxfile -Exportable -Password $password `
-CertStoreLocation Cert:\Localmachine\My
}
else
{
Write-Verbose -Message 'Creating new Self signed Certificate' -Verbose
New-SelfSignedCertificateEx -Subject 'CN=DSC SelfSigned Certificate' -StoreLocation LocalMachine -StoreName My -EnhancedKeyUsage 'Client Authentication'
}
$cert = Get-ChildItem -Path Cert:\LocalMachine\My | Where-Object -Property Subject -EQ -Value 'CN=DSC SelfSigned Certificate'
}
mkdir -Path $PSScriptRoot\CertFile
$certfile = "$PSScriptRoot\CertFile\DSCSelfSignedCertificate.cer"
Export-Certificate -Cert $cert -FilePath $certfile
Stop-Computer
function Set-VmLcm
{
[CmdletBinding()]
Param
(
$VirtualHardDiskRootPath = (Get-VMHost).VirtualHardDiskPath,
# Path to Virtual Machine definition
$VirtualMachinePath = (Get-VMHost).VirtualMachinePath,
# Name for the VM
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[ValidateScript({
((Get-VM $_ -ErrorAction SilentlyContinue) -or
(Test-Path -Path "$VirtualHardDiskRootPath\$_.vhdx"))
})]
$VMName,
# Path script to use as AtBoot (must also remove AtBoot task)
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[ValidateScript({
Test-Path $_ -PathType Leaf
})]
$InitializeScriptPath,
# Path to folder containing localhost.mof and localhost.meta.mof
$LocalhostMofFolder,
# Path to configuration MOF
$ConfigMofPath,
# Multiling string content of Meta MOF
$MetaMofContent,
# Path to DSC REsorces to copy
[ValidateScript({
Test-Path $_ -PathType Container
})]
$DSCResorcePath
)
$ParametersToPass = @{}
foreach ($key in ('Whatif', 'Verbose', 'Debug'))
{
if ($PSBoundParameters.ContainsKey($key))
{
$ParametersToPass[$key] = $PSBoundParameters[$key]
}
}
$vhdPath = "$VirtualHardDiskRootPath\$VMName.vhdx"
$MountPath = "$env:temp\$([System.IO.Path]::GetRandomFileName())"
try
{
if (Get-VM $VMName | Where-Object -Property state -EQ -Value 'running')
{
Stop-VM $VMName
while (Get-VM $VMName | Where-Object -Property state -EQ -Value 'running')
{
Write-Verbose -Message "Wating for $VMName to stop"
Start-Sleep -Seconds 30
}
}
Write-Verbose -Message "Mounting [$vhdPath] to [$MountPath]"
mkdir $MountPath -ErrorAction Stop @ParametersToPass
Mount-WindowsImage -ImagePath "$vhdPath" -Path "$MountPath" -Index 1 -ErrorAction Stop @ParametersToPass
Copy-Item "$InitializeScriptPath" "$MountPath\PSTemp\AtStartup.ps1" -Force @ParametersToPass
if ($LocalhostMofFolder)
{
Test-Path "$LocalhostMofFolder\localhost.mof" -ErrorAction Stop
mkdir $MountPath\PSTemp\serverConfig -ErrorAction SilentlyContinue
Copy-Item "$LocalhostMofFolder\localhost*" "$MountPath\PSTemp\serverConfig\" @ParametersToPass
}
else
{
if ($ConfigMofPath)
{
Test-Path $ConfigMofPath -ErrorAction stop
Copy-Item "$ConfigMofPath" "$MountPath\Windows\System32\Configuration\Pending.mof" @ParametersToPass
}
if ($MetaMofContent)
{
Set-Content -Path "$MountPath\Windows\System32\Configuration\metaconfig.mof" -Value $MetaMofContent -Encoding unicode @ParametersToPass
}
}
if ($DSCResorcePath)
{
Copy-Item "$DSCResorcePath" "$MountPath\Program Files\WindowsPowerShell\Modules" -Recurse @ParametersToPass
}
}
catch
{
$msg = "Failed $($_.Exception.Message)"
Write-Error $msg
throw 'Error Bootstraping DSC'
}
finally
{
Dismount-WindowsImage -Path "$MountPath" -Save @ParametersToPass
}
}
function Start-Deploy
{
[CmdletBinding()]
Param
(
$VirtualHardDiskRootPath = (Get-VMHost).VirtualHardDiskPath,
# Path to Virtual Machine definition
$VirtualMachinePath = (Get-VMHost).VirtualMachinePath,
# Path to VHD Template (must be syspreped)
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[ValidateScript({
Test-Path $_ -PathType Leaf
})]
$VHDSourcePath,
# Name for the VM
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[ValidateScript({
(-not(Get-VM $_ -ErrorAction SilentlyContinue)) -or
(-not(Test-Path -Path $VirtualHardDiskRootPath\$_))
})]
$VMName,
# Path to script to ctreate scedualed task
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[ValidateScript({
Test-Path $_ -PathType Leaf
})]
$InitializeScriptPath,
# Path to script to run AtStarup
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[ValidateScript({
Test-Path $_ -PathType Leaf
})]
$AtStartupScriptPath,
# Path to helper scripts
[ValidateScript({
Test-Path $_ -PathType Container
})]
$HelperScriptPath,
# VM Switch to connect NIC1 to
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[ValidateScript({
Get-VMSwitch $_
})]
$VMSwitch,
# Path to Unattend.xml
[ValidateScript({
(Test-Path -Path $_)
})]
$Unattend = "$PSScriptRoot\Unattend.xml"
)
$ParametersToPass = @{}
foreach ($key in ('Whatif', 'Verbose', 'Debug'))
{
if ($PSBoundParameters.ContainsKey($key))
{
$ParametersToPass[$key] = $PSBoundParameters[$key]
}
}
#region Prepair VHD
$MountPath = "$env:temp\$([System.IO.Path]::GetRandomFileName())"
$vhdDestination = "$VirtualHardDiskRootPath\$VMName.vhdx"
Try
{
#region Validation
if (Test-Path -Path $vhdDestination)
{
throw "$vhdDestination exists"
}
if (Test-Path -Path $MountPath)
{
throw "$MountPath exists"
}
#endregion
Copy-Item -Path $VHDSourcePath -Destination $VirtualHardDiskRootPath\$VMName.vhdx -ErrorAction Stop @ParametersToPass
mkdir $MountPath -ErrorAction Stop @ParametersToPass
Mount-WindowsImage -ImagePath $vhdDestination -Path $MountPath -ErrorAction Stop @ParametersToPass -Index 1
Copy-Item $Unattend $MountPath\Unattend.xml -ErrorAction Stop @ParametersToPass
mkdir $MountPath\PSTemp -ErrorAction SilentlyContinue @ParametersToPass
Copy-Item $InitializeScriptPath $MountPath\PSTemp\FirstRun.ps1 -ErrorAction Stop @ParametersToPass
if ($HelperScriptPath)
{
Copy-Item $HelperScriptPath\* $MountPath\PSTemp\ -Recurse
}
if ($AtStartupScriptPath)
{
Copy-Item $AtStartupScriptPath $MountPath\PSTemp\AtStartup.ps1 -Recurse
}
}
catch
{
$msg = "Failed $($_.Exception.Message)"
Write-Error $msg
throw 'Error Prepairing VHDX'
}
finally
{
Dismount-WindowsImage -Path $MountPath -Save
}
#endregion
#region Create and Start VM
Try
{
New-VM -Name $VMName -MemoryStartupBytes 1GB -VHDPath $vhdDestination -SwitchName $VMSwitch -Generation 2 -ErrorAction stop @ParametersToPass
Start-VM $VMName -ErrorAction stop @ParametersToPass
while (Get-VM $VMName | Where-Object -Property state -EQ -Value 'running')
{
Write-Verbose -Message "Wating for $VMName to stop"
Start-Sleep -Seconds 30
}
}
catch
{
$msg = "Failed $($_.Exception.Message)"
Write-Error $msg
throw 'Failed creating VM'
}
#endregion
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment