scale deployment logic final commit - v1

This commit is contained in:
Brian Wilhite 2021-06-07 09:59:43 -04:00
Родитель b45295f1b9
Коммит 42fd2d1266
3 изменённых файлов: 79 добавлений и 30 удалений

Просмотреть файл

@ -4,17 +4,17 @@
@(
@{
# Windows Deployment Example w/AvailabilitySet
ResourceGroupName = 'deploymentRG' # Resource Group name
ResourceGroupName = 'atoTesting' # Resource Group name
adminUsername = 'testuser' # Admin user account name for VM
virtualNetworkNewOrExisting = 'Existing' # vNet 'New' or 'Existing'
vmVirtualNetwork = 'stig-vm-vnet' # vNet name, creates new if not does exist
virtualNetworkNewOrExisting = 'new' # vNet 'new' or 'existing'
vmVirtualNetwork = 'ato-vm-vnet' # vNet name, creates new if not does exist
subnetName = 'subnet1' # Subnet name within specified vNet
diagnosticStorageResourceId = '' # Diagnostic Storage Resource Id (Get-AzStorageAccount -ResourceGroupName <ResourceGroupName> -Name <diagStorageAcctName>).Id
logAnalyticsWorkspaceId = '' # Log Analytic Workspace Id (Get-AzOperationalInsightsWorkspace -ResourceGroupName <ResourceGroupName> -Name <WorkspaceName>).ResourceId
osDiskEncryptionSetResourceId = '' # Disk Encryption Set Resource Id (Get-AzDiskEncryptionSet -ResourceGroupName <ResourceGroupName> -Name <DiskEncryptionSetName>).Id
OsVersion = '2019-Datacenter' # OS Version, i.e.: '2019-Datacenter', '2016-Datacenter', '19h2-ent'
VmName = 'win2019' # Virtual Machine Name, this will be the base name used in conjunction with VmNamePrefix, VmNameSuffixDelimiter and VmNameSuffixStartingNumber
VmNamePrefix = 'cl-' # VM Name prefix, i.e.: 'cl-'
VmNamePrefix = 'ato-' # VM Name prefix, i.e.: 'ato-'
VmNameSuffixDelimiter = '-' # Delimiter used in conjunction with VmName and Suffix Starting Number, i.e.: '-'
VmNameSuffixStartingNumber = 1 # VM Name Suffix Starting number, used to create unique VM Name, i.e.: 1
Count = 1 # Number of unque VMs or VM Availability Sets to deploy, i.e.: 2
@ -23,30 +23,31 @@
UpdateDomains = 3 # Update domains (valid range 1-5), i.e.: 3
AvailabilityOptions = 'availabilitySet' # if 'availabilitySet' is specified, AvailabilitySet is created. 'default' no AvailabilitySet is created
AvailabilitySetNameSuffix = '-as' # AvailabilitySetName Suffix to be used with scaled deployment, i.e.: '-as'
TimeInSecondsBetweenJobs = 30 # Specify, in seconds, how long to wait before executing the next deployment. This is useful when creating a new vNet with the first deployment, min/default value is 10
},
@{
# Windows Deployment Example w/o AvailabilitySet
ResourceGroupName = 'deploymentRG' # Resource Group name
ResourceGroupName = 'atoTesting' # Resource Group name
adminUsername = 'testuser' # Admin user account name for VM
virtualNetworkNewOrExisting = 'Existing' # vNet 'New' or 'Existing'
vmVirtualNetwork = 'stig-vm-vnet' # vNet name, creates new if not does exist
virtualNetworkNewOrExisting = 'existing' # vNet 'new' or 'existing'
vmVirtualNetwork = 'ato-vm-vnet' # vNet name, creates new if not does exist
subnetName = 'subnet1' # Subnet name within specified vNet
diagnosticStorageResourceId = '' # Diagnostic Storage Resource Id (Get-AzStorageAccount -ResourceGroupName <ResourceGroupName> -Name <diagStorageAcctName>).Id
logAnalyticsWorkspaceId = '' # Log Analytic Workspace Id (Get-AzOperationalInsightsWorkspace -ResourceGroupName <ResourceGroupName> -Name <WorkspaceName>).ResourceId
osDiskEncryptionSetResourceId = '' # Disk Encryption Set Resource Id (Get-AzDiskEncryptionSet -ResourceGroupName <ResourceGroupName> -Name <DiskEncryptionSetName>).Id
OsVersion = '2016-Datacenter' # OS Version, i.e.: '2019-Datacenter', '2016-Datacenter', '19h2-ent'
VmName = 'win2016' # Virtual Machine Name, this will be the base name used in conjunction with VmNamePrefix, VmNameSuffixDelimiter and VmNameSuffixStartingNumber
VmNamePrefix = 'cl-' # VM Name prefix, i.e.: 'cl-'
VmNamePrefix = 'ato-' # VM Name prefix, i.e.: 'ato-'
VmNameSuffixDelimiter = '-' # Delimiter used in conjunction with VmName and Suffix Starting Number, i.e.: '-'
VmNameSuffixStartingNumber = 1 # VM Name Suffix Starting number, used to create unique VM Name, i.e.: 1
Count = 1 # Number of unque VMs or VM Availability Sets to deploy, i.e.: 2
},
@{
# Linux Deployment Example w/AvailabilitySet
ResourceGroupName = 'deploymentRG' # Resource Group name
ResourceGroupName = 'atoTesting' # Resource Group name
adminUsername = 'testuser' # Admin user account name for VM
virtualNetworkNewOrExisting = 'Existing' # vNet 'New' or 'Existing'
vmVirtualNetwork = 'stig-vm-vnet' # vNet name, creates new if not does exist
virtualNetworkNewOrExisting = 'existing' # vNet 'new' or 'existing'
vmVirtualNetwork = 'ato-vm-vnet' # vNet name, creates new if not does exist
subnetName = 'subnet1' # Subnet name within specified vNet
authenticationType = 'password' # Type of authentication to use on the Virtual Machine (valid values 'sshPublicKey' and 'password')
diagnosticStorageResourceId = '' # Diagnostic Storage Resource Id (Get-AzStorageAccount -ResourceGroupName <ResourceGroupName> -Name <diagStorageAcctName>).Id
@ -54,7 +55,7 @@
osDiskEncryptionSetResourceId = '' # Disk Encryption Set Resource Id (Get-AzDiskEncryptionSet -ResourceGroupName <ResourceGroupName> -Name <DiskEncryptionSetName>).Id
OsVersion = 'RHEL79' # OS Verison, i.e.: 'CentOS79', 'RHEL79', 'Ubuntu1804'
VmName = 'redhat' # Virtual Machine Name, this will be the base name used in conjunction with VmNamePrefix, VmNameSuffixDelimiter and VmNameSuffixStartingNumber
VmNamePrefix = 'cl-' # VM Name prefix, i.e.: 'cl-'
VmNamePrefix = 'ato-' # VM Name prefix, i.e.: 'ato-'
VmNameSuffixDelimiter = '-' # Delimiter used in conjunction with VmName and Suffix Starting Number, i.e.: '-'
VmNameSuffixStartingNumber = 1 # VM Name Suffix Starting number, used to create unique VM Name, i.e.: 1
Count = 1 # Number of unque VMs or VM Availability Sets to deploy, i.e.: 2
@ -66,10 +67,10 @@
},
@{
# Linux Deployment Example w/o AvailabilitySet
ResourceGroupName = 'deploymentRG' # Resource Group name
ResourceGroupName = 'atoTesting' # Resource Group name
adminUsername = 'testuser' # Admin user account name for VM
virtualNetworkNewOrExisting = 'Existing' # vNet 'New' or 'Existing'
vmVirtualNetwork = 'stig-vm-vnet' # vNet name, creates new if not does exist
virtualNetworkNewOrExisting = 'existing' # vNet 'new' or 'existing'
vmVirtualNetwork = 'ato-vm-vnet' # vNet name, creates new if not does exist
subnetName = 'subnet1' # Subnet name within specified vNet
authenticationType = 'password' # Type of authentication to use on the Virtual Machine (valid values 'sshPublicKey' and 'password')
diagnosticStorageResourceId = '' # Diagnostic Storage Resource Id (Get-AzStorageAccount -ResourceGroupName <ResourceGroupName> -Name <diagStorageAcctName>).Id
@ -77,7 +78,7 @@
osDiskEncryptionSetResourceId = '' # Disk Encryption Set Resource Id (Get-AzDiskEncryptionSet -ResourceGroupName <ResourceGroupName> -Name <DiskEncryptionSetName>).Id
OsVersion = 'CentOS79' # OS Verison, i.e.: 'CentOS79', 'RHEL79', 'Ubuntu1804'
VmName = 'centos' # Virtual Machine Name, this will be the base name used in conjunction with VmNamePrefix, VmNameSuffixDelimiter and VmNameSuffixStartingNumber
VmNamePrefix = 'cl-' # VM Name prefix, i.e.: 'cl-'
VmNamePrefix = 'ato-' # VM Name prefix, i.e.: 'ato-'
VmNameSuffixDelimiter = '-' # Delimiter used in conjunction with VmName and Suffix Starting Number, i.e.: '-'
VmNameSuffixStartingNumber = 1 # VM Name Suffix Starting number, used to create unique VM Name, i.e.: 1
Count = 1 # Number of unque VMs or VM Availability Sets to deploy, i.e.: 2

Просмотреть файл

@ -1,3 +1,4 @@
#Requires -Module @{ ModuleName = 'Az.Resources'; ModuleVersion = '3.5.0' }
<#
.SYNOPSIS
Kick start script that copies artifact data to a storeage account, then deploys Virtual Machines based on the specified data file.
@ -57,24 +58,61 @@ param
[Parameter(Mandatory = $true)]
[ValidateScript({Test-Path -Path $_})]
[string]
$DataFilePath
$DataFilePath,
[Parameter(Mandatory = $false)]
[SecureString]
$AdminPasswordOrKey
)
# prompt for AdminPassword, twice, confirm they are equal before proceeding
$passTryCount = 0
do
# if AdminPasswordOrKey is not passed at runtime, prompt the user for password
if ($PSBoundParameters.ContainsKey('AdminPasswordOrKey') -eq $false)
{
$passwordEntry = Read-Host -Prompt 'Deployment Admin Password' -AsSecureString
$passConfEntry = Read-Host -Prompt 'Confirm Deployment Admin Password' -AsSecureString
$passwordEntryDecrypt = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto([System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($passwordEntry))
$passConfEntryDecrypt = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto([System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($passConfEntry))
if ($passTryCount -gt 1 -and $passwordEntryDecrypt -ne $passConfEntryDecrypt)
# explain the password requirements to the user
Write-Host "Deployment Admin Password must be at least 12 characters long, contain upper case, lower case, number and symbol." -ForegroundColor Magenta
# prompt for AdminPassword, check for complexity, confirm they are equal before proceeding
$passTryCount = 0
do
{
throw "Deployment Admin Password confirmation does not match, Check the password and try again."
if ($passTryCount -gt 3)
{
throw "The password validation checks failed, check the password and try again."
}
$passTryCount++
# ensure clean decrypted vars through each iteration
$passwordEntryDecrypt = $null
$passConfEntryDecrypt = $null
$passwordEntry = Read-Host -Prompt 'Initial --> Deployment Admin Password' -AsSecureString
$passwordIntPtr = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($passwordEntry)
$passwordEntryDecrypt = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($passwordIntPtr)
[System.Runtime.InteropServices.Marshal]::ZeroFreeBSTR($passwordIntPtr)
# test decrypted password to ensure complexity
$passwordComplexityMatchPattern = '^(?=.*[A-Z])(?=.*[.!@#$%^&*()-_=+])(?=.*[0-9])(?=.*[a-z]).{12,40}$'
if ($passwordEntryDecrypt -notmatch $passwordComplexityMatchPattern)
{
Write-Warning "The password does not meet complexity requirements stated above, try again..."
continue
}
# prompt again to ensure passwords match
$passConfEntry = Read-Host -Prompt 'Confirm --> Deployment Admin Password' -AsSecureString
$passConfIntPtr = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($passConfEntry)
$passConfEntryDecrypt = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($passConfIntPtr)
[System.Runtime.InteropServices.Marshal]::ZeroFreeBSTR($passConfIntPtr)
if ($passwordEntryDecrypt -ne $passConfEntryDecrypt)
{
Write-Warning "The password confirmation does not match, check the password and try again..."
}
}
$passTryCount++
until ($passwordEntryDecrypt -eq $passConfEntryDecrypt)
$adminPasswordOrKey = $passwordEntry
}
until ($passwordEntryDecrypt -eq $passConfEntryDecrypt)
# connect to AzAccount
if ($null -eq $(Get-AzContext))
@ -92,8 +130,9 @@ if ($null -eq $(Get-AzContext))
# call the publish-to-blob.ps1 script to copy deployment artifacts to the specified ResourceGroup and StorageAccount
$publishToBlobScript = Join-Path -Path $PSScriptRoot -ChildPath '.\publish-to-blob.ps1'
[void] $PSBoundParameters.Remove('DataFilePath')
[void] $PSBoundParameters.Remove('AdminPasswordOrKey')
$artifactLocationParams = & $publishToBlobScript @PSBoundParameters -MetadataPassthru
# call the scale-deployment.ps1 script to deploy all datafile VM resources using the artificats previously copied via the publish-to-blob.ps1 script
$scaleDeployment = Join-Path -Path $PSScriptRoot -ChildPath '.\scale-deployment.ps1'
& $scaleDeployment @artifactLocationParams -DataFilePath $DataFilePath -AdminPasswordOrKey $passwordEntry
& $scaleDeployment @artifactLocationParams -DataFilePath $DataFilePath -AdminPasswordOrKey $AdminPasswordOrKey

Просмотреть файл

@ -1,3 +1,4 @@
#Requires -Module @{ ModuleName = 'Az.Resources'; ModuleVersion = '3.5.0' }
<#
.SYNOPSIS
This script enables scaled STIG VM deployment using ATO Tool Kit artifacts.
@ -207,6 +208,11 @@ Param
$AdminUserName,
[Parameter(Mandatory = $false, ParameterSetName = 'Default')]
[ValidateSet(
"new",
"existing",
IgnoreCase = $false
)]
[string]
$VirtualNetworkNewOrExisting,
@ -441,7 +447,8 @@ if ($PSCmdlet.ParameterSetName -eq 'Default')
}
$jobInfo = New-AzResourceGroupDeployment @newAzResourceGroupDeploymentParams
Write-Verbose -Message "JobId: $($jobInfo.Id); Name: $($jobInfo.Name); For more details use: Get-Job -Id $($jobInfo.Id)"
$jobVerboseMessage = 'JobId: {0}; Name: {1}; For more details use: Get-Job -Id {0}; SecondsBetweenJobs: {2}' -f $jobInfo.Id, $jobInfo.Name, $TimeInSecondsBetweenJobs
Write-Verbose -Message $jobVerboseMessage
# sleep statement is required to provide sufficient time for pid deployment to succeed.
Start-Sleep -Seconds $TimeInSecondsBetweenJobs
}
@ -449,8 +456,10 @@ if ($PSCmdlet.ParameterSetName -eq 'Default')
else
{
# import PowerShell data file, structure should mimic .psd1 documented here:
Write-Verbose -Message "Importing deployment data file: $DataFilePath"
$dataFileStructureLink = '_placeHolder_for_ato_markdown_link_'
$deploymentDataFileImport = Import-PowerShellDataFile -Path $DataFilePath
Write-Verbose -Message "-- Total deployments to be created: $($($deploymentDataFileImport[$deploymentDataFileImport.Keys]).Count)"
# if the hashtable keys are more than one, fail, since the structure is incorrect.
if ($deploymentDataFileImport.Keys.Count -gt 1)