This commit is contained in:
Brian Wilhite 2021-06-01 16:59:42 -04:00
Родитель 60ee0cacc0
Коммит f4e4ae0d4e
11 изменённых файлов: 1307 добавлений и 170 удалений

1
.gitignore поставляемый
Просмотреть файл

@ -1 +1,2 @@
**/.DS_Store
.vscode/

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

@ -29,22 +29,83 @@
"constraints": {
"required": true,
"regex": "^[a-z0-9A-Z-]{3,15}$",
"validationMessage": "Virtual machine Name must be between 3 and 15 characters long and contain letters, numbers and hyphens only."
"validationMessage": "Virtual machine name must be between 3 and 15 characters long and contain letters, numbers and hyphens only."
}
},
{
"name": "vmAvailabilitySet",
"type": "Microsoft.Solutions.ResourceSelector",
"label": "Availability set",
"resourceType": "Microsoft.Compute/availabilitySets",
"toolTip": "Select existing Availability set to be configured for Virtual machine. Availability set must be present in the same resource group.",
"options": {
"filter": {
"subscription": "onBasic",
"location": "onBasic"
}
"name": "availabilityOptions",
"type": "Microsoft.Common.DropDown",
"label": "Availability options",
"toolTip": "Azure offers a range of options for managing availability and resiliency for your applications. Architect your solution to use replicated VMs in Availability Sets to protect your apps and data from datacenter outages and maintenance events.",
"defaultValue": "No infrastructure redundancy required",
"constraints": {
"allowedValues": [
{
"value": "default",
"label": "No infrastructure redundancy required"
},
{
"value": "availabilitySet",
"label": "Availability set"
}
],
"required": true
},
"visible": false
"visible": true
},
{
"name": "availabilitySetName",
"type": "Microsoft.Common.TextBox",
"label": "Availability set name",
"toolTip": "Name of the Availability set.",
"constraints": {
"required": "[equals(steps('instance').availabilityOptions, 'availabilitySet')]",
"regex": "^[a-z0-9A-Z-]{3,15}$",
"validationMessage": "Availability set name must be between 3 and 15 characters long and contain letters, numbers and hyphens only."
},
"visible": "[equals(steps('instance').availabilityOptions, 'availabilitySet')]"
},
{
"name": "instanceCount",
"type": "Microsoft.Common.Slider",
"min": 1,
"max": 5,
"label": "Instance count",
"defaultValue": 2,
"showStepMarkers": false,
"toolTip": "Number of virtual machines in the availability set.",
"constraints": {
"required": false
},
"visible": "[equals(steps('instance').availabilityOptions, 'availabilitySet')]"
},
{
"name": "faultDomains",
"type": "Microsoft.Common.Slider",
"min": 1,
"max": 3,
"label": "Fault domains",
"defaultValue": 2,
"showStepMarkers": false,
"toolTip": "Virtual machines in the same fault domain share a common power source and physical network switch.",
"constraints": {
"required": false
},
"visible": "[equals(steps('instance').availabilityOptions, 'availabilitySet')]"
},
{
"name": "updateDomains",
"type": "Microsoft.Common.Slider",
"min": 1,
"max": 5,
"label": "Update domains",
"defaultValue": 3,
"showStepMarkers": true,
"toolTip": "Virtual machines in the same update domain will be restarted together during planned maintenance. Azure never restarts more than one update domain at a time.",
"constraints": {
"required": false
},
"visible": "[equals(steps('instance').availabilityOptions, 'availabilitySet')]"
},
{
"name": "osVersion",
@ -78,6 +139,10 @@
"value": "CentOS74",
"label": "CentOS 7.4"
},
{
"value": "RHEL79",
"label": "Red Hat Enterprise Linux 7.9"
},
{
"value": "RHEL78",
"label": "Red Hat Enterprise Linux 7.8"
@ -427,7 +492,11 @@
"outputs": {
"location": "[location()]",
"vmName": "[steps('instance').vmName]",
"availabilitySetResourceId": "[steps('instance').vmAvailabilitySet.id]",
"availabilityOptions": "[steps('instance').availabilityOptions]",
"availabilitySetName": "[steps('instance').availabilitySetName]",
"instanceCount": "[steps('instance').instanceCount]",
"faultDomains": "[steps('instance').faultDomains]",
"updateDomains": "[steps('instance').updateDomains]",
"osVersion": "[steps('instance').osVersion]",
"vmSize": "[steps('instance').vmSize]",
"adminUsername": "[steps('instance').adminUsername]",

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

@ -4,7 +4,7 @@
"parameters": {
"vmName": {
"type": "string",
"defaultValue": "simple-vm",
"defaultValue": "stig-vm",
"metadata": {
"description": "Name of the virtual machine."
}
@ -155,11 +155,49 @@
"description": "(Optional) Application Security Group resource id."
}
},
"availabilitySetResourceId": {
"availabilityOptions": {
"type": "string",
"defaultValue": "",
"defaultValue": "default",
"allowedValues": [
"default",
"availabilitySet"
],
"metadata": {
"description": "(Optional) Availability Set resource id."
"description": "(Optional) Availability options."
}
},
"availabilitySetName": {
"type": "string",
"defaultValue": "stig-vm-as",
"metadata": {
"description": "(Optional) Availability set name."
}
},
"instanceCount": {
"type": "int",
"defaultValue": 2,
"minValue": 1,
"maxValue": 5,
"metadata": {
"description": "(Optional) Instance count."
}
},
"faultDomains": {
"type": "int",
"defaultValue": 2,
"minValue": 1,
"maxValue": 3,
"metadata": {
"description": "(Optional) Fault domains."
}
},
"updateDomains": {
"type": "int",
"defaultValue": 3,
"minValue": 1,
"maxValue": 5,
"metadata": {
"description": "(Optional) Update domains."
}
},
"logsRetentionInDays": {
@ -187,6 +225,10 @@
}
},
"variables": {
"instanceCount": "[if(equals(parameters('availabilityOptions'), 'availabilitySet'), parameters('instanceCount'), 1)]",
"availabilitySet": {
"id": "[resourceId('Microsoft.Compute/availabilitySets', parameters('availabilitySetName'))]"
},
"nicName": "[concat(parameters('vmName'), '-nic')]",
"vnetId": {
"new": "[resourceId('Microsoft.Network/virtualNetworks',parameters('vmVirtualNetwork'))]",
@ -388,11 +430,29 @@
]
}
},
{
"type": "Microsoft.Compute/availabilitySets",
"apiVersion": "2020-06-01",
"name": "[parameters('availabilitySetName')]",
"location": "[parameters('location')]",
"condition": "[equals(parameters('availabilityOptions'), 'availabilitySet')]",
"sku": {
"name": "Aligned"
},
"properties": {
"PlatformUpdateDomainCount": "[parameters('updateDomains')]",
"PlatformFaultDomainCount": "[parameters('faultDomains')]"
}
},
{
"type": "Microsoft.Network/networkInterfaces",
"apiVersion": "2020-06-01",
"name": "[variables('nicName')]",
"name": "[concat(variables('nicName'), if(equals(variables('instanceCount'), 1), '', copyIndex()))]",
"location": "[parameters('location')]",
"copy": {
"name": "nicLoop",
"count": "[variables('instanceCount')]"
},
"dependsOn": [
"[resourceId('Microsoft.Network/virtualNetworks', parameters('vmVirtualNetwork'))]"
],
@ -415,11 +475,15 @@
{
"type": "Microsoft.Network/networkInterfaces/providers/diagnosticSettings",
"apiVersion": "2017-05-01-preview",
"name": "[concat(variables('nicName'), '/Microsoft.Insights/service')]",
"name": "[concat(variables('nicName'), if(equals(variables('instanceCount'), 1), '', copyIndex()), '/Microsoft.Insights/service')]",
"location": "[parameters('location')]",
"condition": "[or(not(equals(parameters('diagnosticStorageResourceId'), '')), not(equals(parameters('logAnalyticsWorkspaceId'), '')))]",
"copy": {
"name": "nicDiagnosticLoop",
"count": "[variables('instanceCount')]"
},
"dependsOn": [
"[variables('nicName')]"
"nicloop"
],
"properties": {
"storageAccountId": "[if(equals(parameters('diagnosticStorageResourceId'), ''), json('null'), parameters('diagnosticStorageResourceId'))]",
@ -439,10 +503,14 @@
{
"type": "Microsoft.Compute/virtualMachines",
"apiVersion": "2020-06-01",
"name": "[parameters('vmName')]",
"name": "[concat(parameters('vmName'), if(equals(variables('instanceCount'), 1), '', copyIndex()))]",
"location": "[parameters('location')]",
"copy": {
"name": "virtualMachineLoop",
"count": "[variables('instanceCount')]"
},
"dependsOn": [
"[resourceId('Microsoft.Network/networkInterfaces', variables('nicName'))]"
"nicLoop"
],
"properties": {
"hardwareProfile": {
@ -461,7 +529,7 @@
"networkProfile": {
"networkInterfaces": [
{
"id": "[resourceId('Microsoft.Network/networkInterfaces', variables('nicName'))]"
"id": "[resourceId('Microsoft.Network/networkInterfaces', concat(variables('nicName'), if(equals(variables('instanceCount'), 1), '', copyIndex())))]"
}
]
},
@ -472,7 +540,7 @@
"linuxConfiguration": "[if(equals(parameters('authenticationType'), 'password'), json('null'), variables('linuxConfiguration'))]",
"customData": "[if(equals(parameters('customData'), ''), json('null'), base64(parameters('customData')))]"
},
"availabilitySet": "[if(equals(parameters('availabilitySetResourceId'), ''), json('null'), parameters('availabilitySetResourceId'))]",
"availabilitySet": "[if(equals(parameters('availabilityOptions'), 'availabilitySet'), variables('availabilitySet'), json('null'))]",
"diagnosticsProfile": {
"bootDiagnostics": {
"enabled": "[if(equals(parameters('diagnosticStorageResourceId'), ''), false(), true())]",
@ -486,10 +554,14 @@
{
"apiVersion": "2020-06-01",
"type": "Microsoft.Compute/virtualMachines/extensions",
"name": "[concat(parameters('vmName'),'/setup-linux-dsc')]",
"name": "[concat(parameters('vmName'), if(equals(variables('instanceCount'), 1), '', copyIndex()), '/setup-linux-dsc')]",
"location": "[parameters('location')]",
"copy": {
"name": "dscLoop",
"count": "[variables('instanceCount')]"
},
"dependsOn": [
"[resourceId('Microsoft.Compute/virtualMachines', parameters('vmName'))]"
"monitoringAgentLoop"
],
"properties": {
"publisher": "Microsoft.OSTCExtensions",
@ -505,10 +577,14 @@
{
"type": "Microsoft.Compute/virtualMachines/extensions",
"apiVersion": "2019-07-01",
"name": "[concat(parameters('vmName'), '/setup-linux-dsc-stig')]",
"name": "[concat(parameters('vmName'), if(equals(variables('instanceCount'), 1), '', copyIndex()), '/setup-linux-dsc-stig')]",
"location": "[parameters('location')]",
"copy": {
"name": "cseLoop",
"count": "[variables('instanceCount')]"
},
"dependsOn": [
"[resourceId('Microsoft.Compute/virtualMachines/extensions/', parameters('vmName'), 'setup-linux-dsc')]"
"dscLoop"
],
"properties": {
"publisher": "Microsoft.Azure.Extensions",
@ -531,11 +607,15 @@
{
"type": "Microsoft.Compute/virtualMachines/providers/diagnosticSettings",
"apiVersion": "2017-05-01-preview",
"name": "[concat(parameters('vmName'), '/Microsoft.Insights/service')]",
"name": "[concat(parameters('vmName'), if(equals(variables('instanceCount'), 1), '', copyIndex()), '/Microsoft.Insights/service')]",
"location": "[parameters('location')]",
"condition": "[or(not(equals(parameters('diagnosticStorageResourceId'), '')), not(equals(parameters('logAnalyticsWorkspaceId'), '')))]",
"copy": {
"name": "virtualMachineDiagnosticLoop",
"count": "[variables('instanceCount')]"
},
"dependsOn": [
"[parameters('vmName')]"
"virtualMachineLoop"
],
"properties": {
"storageAccountId": "[if(equals(parameters('diagnosticStorageResourceId'), ''), json('null'), parameters('diagnosticStorageResourceId'))]",
@ -554,12 +634,16 @@
},
{
"type": "Microsoft.Compute/virtualMachines/extensions",
"name": "[concat(parameters('vmName'), '/Microsoft.EnterpriseCloud.Monitoring')]",
"name": "[concat(parameters('vmName'), if(equals(variables('instanceCount'), 1), '', copyIndex()), '/Microsoft.EnterpriseCloud.Monitoring')]",
"apiVersion": "2015-06-15",
"location": "[parameters('location')]",
"condition": "[not(equals(parameters('logAnalyticsWorkspaceId'), ''))]",
"copy": {
"name": "monitoringAgentLoop",
"count": "[variables('instanceCount')]"
},
"dependsOn": [
"[resourceId('Microsoft.Compute/virtualMachines', parameters('vmName'))]"
"virtualMachineDiagnosticLoop"
],
"properties": {
"publisher": "Microsoft.EnterpriseCloud.Monitoring",

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

@ -6,11 +6,10 @@ if [ -f ./azAutomationComplete ]; then
exit 0
fi
# rhel 7.2/7.3 ssl cert issue remediation
# https://docs.microsoft.com/en-us/azure/virtual-machines/workloads/redhat/redhat-rhui
version=$(. /etc/os-release && echo $VERSION_ID)
if [ ${version} == '7.2' ] || [ ${version} == '7.3' ]; then
echo "Executing yum update to disable all repos and enable all microsoft repos (7.2/7.3 fix)..."
id=$(. /etc/os-release && echo $ID)
if [ ${id} == 'rhel' ]; then
echo "Executing yum update to disable all repos and enable all microsoft repos..."
yum update -y --disablerepo='*' --enablerepo='*microsoft*' > ./yumupdateresults.log
fi

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

@ -0,0 +1,86 @@
@{
# Datafile structure is single key/value pair, where the "value" is an array of hashtables decribing each VM deployment.
AllNodes =
@(
@{
# Windows Deployment Example w/AvailabilitySet
ResourceGroupName = 'deploymentRG' # 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
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-'
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
InstanceCount = 2 # Number of VMs to deploy per Availability Set (valid range 1-5), i.e.: 2
FaultDomains = 2 # Fault domains (valid range 1-3), i.e.: 2
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'
},
@{
# Windows Deployment Example w/o AvailabilitySet
ResourceGroupName = 'deploymentRG' # 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
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-'
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
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
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
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 = '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-'
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
InstanceCount = 2 # Number of VMs to deploy per Availability Set (valid range 1-5), i.e.: 2
FaultDomains = 2 # Fault domains (valid range 1-3), i.e.: 2
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'
},
@{
# Linux Deployment Example w/o AvailabilitySet
ResourceGroupName = 'deploymentRG' # 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
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
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 = '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-'
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
}
)
}

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

@ -0,0 +1,99 @@
<#
.SYNOPSIS
Kick start script that copies artifact data to a storeage account, then deploys Virtual Machines based on the specified data file.
.DESCRIPTION
Kick start script that copies artifact data to a storeage account, then deploys Virtual Machines based on the specified data file.
.PARAMETER ResourceGroupName
Specifies the name of the deployment resource group.
.PARAMETER StorageAccountName
Specifies the name of the Storage Account where the artifacts will be copied.
.PARAMETER ContainerName
Specifies the name of the container where the artifacts will be copied.
.PARAMETER Environment
Environment containing the Azure account.
.PARAMETER DataFilePath
ATO Scale deployment data file (.psd1)
.EXAMPLE
$kickStartParams = @{
ResourceGroupName = 'deploymentRG'
StorageAccountName = 'deploymentSA'
ContainerName = 'deploymentContainer'
Environment = 'AzureUSGovernment'
DataFilePath = 'C:\data\deploymentData.psd1'
}
.\kick-start-scaled-deployment.ps1 @kickStartParams
This example leverage the .\publish-to-blob.ps1 script to copy deployment artifacts to a storage account, then invoke
.\scale-deployment.ps1 to deploy Virtual Machines defined in the data file (psd1).
#>
[CmdletBinding()]
param
(
[Parameter(Mandatory = $true)]
[string]
$ResourceGroupName,
[Parameter(Mandatory = $true)]
[string]
$StorageAccountName,
[Parameter(Mandatory = $false)]
[string]
$ContainerName = 'artifacts',
[Parameter(Mandatory = $true)]
[string]
$Environment,
[Parameter(Mandatory = $true)]
[ValidateScript({Test-Path -Path $_})]
[string]
$DataFilePath
)
# prompt for AdminPassword, twice, confirm they are equal before proceeding
$passTryCount = 0
do
{
$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)
{
throw "Deployment Admin Password confirmation does not match, Check the password and try again."
}
$passTryCount++
}
until ($passwordEntryDecrypt -eq $passConfEntryDecrypt)
# connect to AzAccount
if ($null -eq $(Get-AzContext))
{
try
{
Connect-AzAccount -Environment $Environment -ErrorAction Stop | Out-Null
}
catch
{
throw "Unable to connect to AzAccount; $_"
}
}
# 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')
$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

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

@ -0,0 +1,124 @@
<#
.SYNOPSIS
This script publishes templates and associated scripts into your Azure Storage account, and generates Azure Portal link for deployment.
.DESCRIPTION
This script publishes templates and associated scripts into your Azure Storage account, and generates Azure Portal link for deployment.
.PARAMETER ResourceGroupName
Specifies the name of the deployment resource group.
.PARAMETER StorageAccountName
Specifies the name of the Storage Account where the artifacts will be copied.
.PARAMETER ContainerName
Specifies the name of the container where the artifacts will be copied.
.PARAMETER Environment
Environment containing the Azure account.
.PARAMETER MetadataPassthru
Used to pass Uri data through the pipeline.
.EXAMPLE
$deploymentUri = .\publish-to-blob.ps1 -ResourceGroupName deploymentRG -StorageAccountName deploymentSA -ContainerName artifacts -MetadataPassthru
This example will copy deployment artifacts to the specified storage account / container, then output via Write-Host Uri details.
This example also stores the artifact location details as a hashtable in the deploymentUri variable.
#>
Param(
[Parameter(Mandatory = $true)]
[string]
$ResourceGroupName,
[Parameter(Mandatory = $true)]
[string]
$StorageAccountName,
[Parameter(Mandatory = $false)]
[string]
$ContainerName = 'artifacts',
[Parameter(Mandatory = $false)]
[string]
$Environment = ((Get-AzContext).Environment.Name),
[Parameter(Mandatory = $false)]
[switch]
$MetadataPassthru
)
# create storage account context for use throughout the script
$context = (Get-AzStorageAccount -ResourceGroupName $ResourceGroupName -Name $StorageAccountName).Context
# detect specified container name, create it if it does not exist
if (-not(Get-AzStorageContainer -Context $context -Prefix $ContainerName))
{
Write-Verbose -Message "Specified container does not exist, creating $ContainerName"
New-AzStorageContainer -Context $context -Name $ContainerName -Permission Off | Out-Null
}
# detect artifact folders and copy both to the specified blob storage container
$projectRootFolder = Join-Path -Path $PSScriptRoot -ChildPath '..\'
$winArtifactFolder = Join-Path -Path $projectRootFolder -ChildPath '.\windows'
$linArtifactFolder = Join-Path -Path $projectRootFolder -ChildPath '.\linux*'
$artifactFolderNames = Get-ChildItem -Path $winArtifactFolder, $linArtifactFolder
$artifactFiles = Get-ChildItem -Path $artifactFolderNames.FullName -File -Recurse
$copiedBlobContent = $artifactFiles | Set-AzStorageBlobContent -Context $context -Container $ContainerName -Force
# create container SAS token
$sasToken = New-AzStorageContainerSASToken -Context $context -Name $ContainerName -Permission r
# isolating mainTemplate/createUiDefinition blob objects
$mainTemplateWinBlob = $copiedBlobContent | Where-Object -FilterScript {$_.ICloudBlob.Uri.AbsoluteUri -like "*/windows/*mainTemplate.json"}
$createUIDefiWinBlob = $copiedBlobContent | Where-Object -FilterScript {$_.ICloudBlob.Uri.AbsoluteUri -like "*/windows/*createUiDefinition.json"}
$mainTemplateLinBlob = $copiedBlobContent | Where-Object -FilterScript {$_.ICloudBlob.Uri.AbsoluteUri -like "*/linux*/*mainTemplate.json"}
$createUIiDefLinBlob = $copiedBlobContent | Where-Object -FilterScript {$_.ICloudBlob.Uri.AbsoluteUri -like "*/linux*/*createUiDefinition.json"}
# store mainTemplate/createUiDefinition json file Uris from blob objects
$mainTemplateWinUri = $mainTemplateWinBlob.ICloudBlob.Uri.AbsoluteUri
$createUIDefiWinUri = $createUIDefiWinBlob.ICloudBlob.Uri.AbsoluteUri
$artifactsLocWinUrl = $mainTemplateWinBlob.ICloudBlob.Parent.Uri.AbsoluteUri
$mainTemplateLinUri = $mainTemplateLinBlob.ICloudBlob.Uri.AbsoluteUri
$createUIiDefLinUrl = $createUIiDefLinBlob.ICloudBlob.Uri.AbsoluteUri
$artifactsLocLinUrl = $mainTemplateLinBlob.ICloudBlob.Parent.Uri.AbsoluteUri
# creating switch for Context Environment to support additional environments
switch ($Environment)
{
'AzureUSGovernment' {$azureRootDomain = 'us'; break}
'AzureGermanCloud' {$azureRootDomain = 'de'; break}
'AzureCloud' {$azureRootDomain = 'com'; break}
default {$azureRootDomain = 'com'}
}
# create portal template links and return a formatted Uri Write-Host output
$azPortalUrl = 'https://portal.azure.{0}/#create/Microsoft.Template/uri/' -f $azureRootDomain
$windowsUri = '{0}{1}/createUIDefinitionUri/{2}' -f $azPortalUrl, [uri]::EscapeDataString($mainTemplateWinUri + $sasToken), [uri]::EscapeDataString($createUIDefiWinUri + $sasToken)
$linuxUri = '{0}{1}/createUIDefinitionUri/{2}' -f $azPortalUrl, [uri]::EscapeDataString($mainTemplateLinUri + $sasToken), [uri]::EscapeDataString($createUIiDefLinUrl + $sasToken)
Write-Host -Object "`nWindows Portal Uri:" -ForegroundColor Green
Write-Host -Object $windowsUri -ForegroundColor Blue
Write-Host -Object 'Windows ArtifactsLocation Uri:' -ForegroundColor Green
Write-Host -Object $artifactsLocWinUrl -ForegroundColor Blue
Write-Host -Object 'Windows TemplateUri:' -ForegroundColor Green
Write-Host -Object $mainTemplateWinUri -ForegroundColor Blue
Write-Host -Object "`nLinux Portal Uri:" -ForegroundColor Green
Write-Host -Object $linuxUri -ForegroundColor Blue
Write-Host -Object 'Linux ArtifactsLocation Uri:' -ForegroundColor Green
Write-Host -Object $artifactsLocLinUrl -ForegroundColor Blue
Write-Host -Object 'Linux TemplateUri:' -ForegroundColor Green
Write-Host -Object $mainTemplateLinUri -ForegroundColor Blue
# metadatapassthru is used in conjunction with scale-deployment.ps1
if ($MetadataPassthru -eq $true)
{
return @{
WindowsTemplateUri = $mainTemplateWinUri
WindowsArtifactsLocation = $artifactsLocWinUrl
LinuxTemplateUri = $mainTemplateLinUri
LinuxArtifactsLocation = $artifactsLocLinUrl
ArtifactsLocationSasToken = $sasToken | ConvertTo-SecureString -AsPlainText -Force
}
}

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

@ -0,0 +1,495 @@
<#
.SYNOPSIS
This script enables scaled STIG VM deployment using ATO Tool Kit artifacts.
.DESCRIPTION
This script enables scaled STIG VM deployment using ATO Tool Kit artifacts.
.PARAMETER VmName
Name of the virtual machine.
.PARAMETER VmNamePrefix
Prefix to be used with VmName.
.PARAMETER VmNameSuffixDelimiter
Delimiter between VmName and VmNameSuffixStartingNumber.
.PARAMETER VmNameSuffixStartingNumber
The starting number for the first VM in the deployment.
.PARAMETER Count
Number of unque VMs or VM Availability Sets to deploy.
.PARAMETER OsVersion
Linux or Windows OS Version.
.PARAMETER ResourceGroupName
Specifies the name of the deployment resource group.
.PARAMETER TemplateUri
Specifies the URI of a custom template file.
.PARAMETER Location
Location for all resources.
.PARAMETER AdminUserName
Username for the Virtual Machine.
.PARAMETER VirtualNetworkNewOrExisting
Is the Virtual Network new or existing for the Virtual Machine.
.PARAMETER VmVirtualNetwork
Virtual Network for the Virtual Machine.
.PARAMETER VirtualNetworkResourceGroupName
Name of the resource group for the existing virtual network.
.PARAMETER AddressPrefix
Address prefix of the virtual network.
.PARAMETER SubnetPrefix
Subnet prefix of the virtual network.
.PARAMETER SubnetName
Subnet name for the Virtual Machine.
.PARAMETER AuthenticationType
Type of authentication to use on the Virtual Machine, used with Linux deployments, non-applicable for Windows.
.PARAMETER ArtifactsLocation
SAS Token to access the storage location containing artifacts.
.PARAMETER DiagnosticStorageResourceId
Diagnostic Storage account resource id.
.PARAMETER LogAnalyticsWorkspaceId
Log Analytics workspace resource id.
.PARAMETER OsDiskEncryptionSetResourceId
OS Disk Encryption Set resource id.
.PARAMETER ApplicationSecurityGroupResourceId
Application Security Group resource id.
.PARAMETER OsDiskStorageType
Azure managed disks types to support your workload or scenario.
.PARAMETER CustomData
Pass a script, configuration file, or other data into the virtual machine while it is being provisioned. The data will be saved on the VM in a known location.
.PARAMETER AvailabilityOptions
Determines if an AvailabilitySet is deployed ('availabilitySet' AvailabilitySet is created), ('default' no AvailabilitySet)
.PARAMETER AvailabilitySetNameSuffix
AvailabilitySetName Suffix to be used with scaled deployment.
.PARAMETER InstanceCount
Number of VMs to deploy per Availability Set.
.PARAMETER FaultDomains
Azure fault domains
.PARAMETER UpdateDomains
Azure update domains.
.PARAMETER LogsRetentionInDays
Log retention in days.
.PARAMETER EnableHybridBenefitServerLicense
Enable Azure Hybrid Benefit to use your on-premises Windows Server licenses and reduce cost.
.PARAMETER AutoInstallDependencies
Boolean value to indicate an online or offline environment.
.PARAMETER ArtifactsLocationSasToken
SAS Token to access the storage location containing artifacts.
.PARAMETER AdminPasswordOrKey
SSH Key or password for the Linux Virtual Machine, password only for Windows deployments.
.PARAMETER TimeInSecondsBetweenJobs
Time between New-AzResourceGroupDeployment jobs to ensure sufficient time for pid deployment to succeed.
.PARAMETER LinuxTemplateUri
Specifies the URI of the Linux template file.
.PARAMETER WindowsTemplateUri
Specifies the URI of the Windows template file.
.PARAMETER LinuxArtifactsLocation
Specifies the URI of the Linux artifacts location.
.PARAMETER WindowsArtifactsLocation
Specifies the URI of the Windows artifacts location.
.PARAMETER DataFilePath
ATO Scale deployment data file (.psd1)
.EXAMPLE
$artifactLocationParams = .\publish-to-blob.ps1 -ResourceGroupName deploymentRG -StorageAccountName deploymentSA -ContainerName artifacts -MetadataPassthru
$dataFilePath = 'C:\data\vmDeploymentData.psd1
$securePassword = Read-Host -Prompt 'adminUserName password' -AsSecureString
.\scale-deployment.ps1 @artifactLocationParams -DataFilePath $dataFilePath -AdminPasswordOrKey $securePassword
This example uses the publish-to-blob.ps1 script to copy deployment artifact files to a storage account, then deploy the solution based on data
from the data file.
#>
[CmdletBinding(DefaultParameterSetName = 'Default')]
Param
(
[Parameter(Mandatory = $true, ParameterSetName = 'Default')]
[ValidateScript({$_ -notmatch '[^\w-]'})]
[string]
$VmName,
[Parameter(Mandatory = $false, ParameterSetName = 'Default')]
[ValidateScript({$_ -notmatch '[^\w-]'})]
[string]
$VmNamePrefix = $null,
[Parameter(Mandatory = $false, ParameterSetName = 'Default')]
[ValidateScript({$_ -notmatch '[^\w-]'})]
[string]
$VmNameSuffixDelimiter = '-',
[Parameter(Mandatory = $false, ParameterSetName = 'Default')]
[int]
$VmNameSuffixStartingNumber = 1,
[Parameter(Mandatory = $false, ParameterSetName = 'Default')]
[int]
$Count,
[Parameter(Mandatory = $true, ParameterSetName = 'Default')]
[ValidateSet(
"CentOS79",
"CentOS78",
"CentOS77",
"CentOS76",
"CentOS75",
"CentOS74",
"RHEL79",
"RHEL78",
"RHEL77",
"RHEL75",
"RHEL74",
"RHEL73",
"RHEL72",
"Ubuntu1804",
"Ubuntu1804-DataScience",
"2019-Datacenter",
"2016-Datacenter",
"19h2-ent",
IgnoreCase = $false
)]
[string]
$OsVersion,
[Parameter(Mandatory = $true, ParameterSetName = 'Default')]
[string]
$ResourceGroupName,
[Parameter(Mandatory = $true, ParameterSetName = 'Default')]
[ValidateScript({[uri]::IsWellFormedUriString($_, 1)})]
[string]
$TemplateUri,
[Parameter(Mandatory = $false, ParameterSetName = 'Default')]
[string]
$Location,
[Parameter(Mandatory = $true, ParameterSetName = 'Default')]
[string]
$AdminUserName,
[Parameter(Mandatory = $false, ParameterSetName = 'Default')]
[string]
$VirtualNetworkNewOrExisting,
[Parameter(Mandatory = $false, ParameterSetName = 'Default')]
[string]
$VmVirtualNetwork,
[Parameter(Mandatory = $false, ParameterSetName = 'Default')]
[string]
$VirtualNetworkResourceGroupName,
[Parameter(Mandatory = $false, ParameterSetName = 'Default')]
[string]
$AddressPrefix,
[Parameter(Mandatory = $false, ParameterSetName = 'Default')]
[string]
$SubnetPrefix,
[Parameter(Mandatory = $false, ParameterSetName = 'Default')]
[string]
$SubnetName,
[Parameter(Mandatory = $false, ParameterSetName = 'Default')]
[string]
$AuthenticationType,
[Parameter(Mandatory = $true, ParameterSetName = 'Default')]
[ValidateScript({[uri]::IsWellFormedUriString($_, 1)})]
[string]
$ArtifactsLocation,
[Parameter(Mandatory = $false, ParameterSetName = 'Default')]
[string]
$DiagnosticStorageResourceId,
[Parameter(Mandatory = $false, ParameterSetName = 'Default')]
[string]
$LogAnalyticsWorkspaceId,
[Parameter(Mandatory = $false, ParameterSetName = 'Default')]
[string]
$OsDiskEncryptionSetResourceId,
[Parameter(Mandatory = $false, ParameterSetName = 'Default')]
[string]
$ApplicationSecurityGroupResourceId,
[Parameter(Mandatory = $false, ParameterSetName = 'Default')]
[ValidateSet(
"Premium_LRS",
"Standard_LRS",
"StandardSSD_LRS",
IgnoreCase = $false
)]
[string]
$OsDiskStorageType,
[Parameter(Mandatory = $false, ParameterSetName = 'Default')]
[string]
$CustomData,
[Parameter(Mandatory = $false, ParameterSetName = 'Default')]
[string]
$AvailabilityOptions,
[Parameter(Mandatory = $false, ParameterSetName = 'Default')]
[string]
$AvailabilitySetNameSuffix,
[Parameter(Mandatory = $false, ParameterSetName = 'Default')]
[ValidateRange(1, 5)]
[int]
$InstanceCount,
[Parameter(Mandatory = $false, ParameterSetName = 'Default')]
[ValidateRange(1, 3)]
[int]
$FaultDomains,
[Parameter(Mandatory = $false, ParameterSetName = 'Default')]
[ValidateRange(1, 5)]
[int]
$UpdateDomains,
[Parameter(Mandatory = $false, ParameterSetName = 'Default')]
[ValidateRange(0, 365)]
[int]
$LogsRetentionInDays,
[Parameter(Mandatory = $false, ParameterSetName = 'Default')]
[switch]
$EnableHybridBenefitServerLicense,
[Parameter(Mandatory = $false, ParameterSetName = 'Default')]
[switch]
$AutoInstallDependencies,
[Parameter(Mandatory = $false, ParameterSetName = 'Default')]
[Parameter(Mandatory = $false, ParameterSetName = 'DataFilePath')]
[SecureString]
$ArtifactsLocationSasToken,
[Parameter(Mandatory = $true, ParameterSetName = 'Default')]
[Parameter(Mandatory = $true, ParameterSetName = 'DataFilePath')]
[SecureString]
$AdminPasswordOrKey,
[Parameter(Mandatory = $false, ParameterSetName = 'Default')]
[Parameter(Mandatory = $false, ParameterSetName = 'DataFilePath')]
[ValidateRange(10, 120)]
[int]
$TimeInSecondsBetweenJobs = 10,
[Parameter(Mandatory = $false, ParameterSetName = 'DataFilePath')]
[ValidateScript({[uri]::IsWellFormedUriString($_, 1)})]
[string]
$LinuxTemplateUri,
[Parameter(Mandatory = $false, ParameterSetName = 'DataFilePath')]
[ValidateScript({[uri]::IsWellFormedUriString($_, 1)})]
[string]
$WindowsTemplateUri,
[Parameter(Mandatory = $false, ParameterSetName = 'DataFilePath')]
[ValidateScript({[uri]::IsWellFormedUriString($_, 1)})]
[string]
$LinuxArtifactsLocation,
[Parameter(Mandatory = $false, ParameterSetName = 'DataFilePath')]
[ValidateScript({[uri]::IsWellFormedUriString($_, 1)})]
[string]
$WindowsArtifactsLocation,
[Parameter(Mandatory = $false, ParameterSetName = 'DataFilePath')]
[ValidateScript({Test-Path -Path $_})]
[string]
$DataFilePath
)
if ($PSCmdlet.ParameterSetName -eq 'Default')
{
# removing non-template params from $PSBoundParams, in order to splat New-AzResourceGroupDeployment
$newAzResourceGroupDeploymentParams = $PSBoundParameters
[void] $newAzResourceGroupDeploymentParams.Remove('VmName')
[void] $newAzResourceGroupDeploymentParams.Remove('VmNamePrefix')
[void] $newAzResourceGroupDeploymentParams.Remove('VmNameSuffixDelimiter')
[void] $newAzResourceGroupDeploymentParams.Remove('VmNameSuffixStartingNumber')
[void] $newAzResourceGroupDeploymentParams.Remove('Count')
[void] $newAzResourceGroupDeploymentParams.Remove('TimeInSecondsBetweenJobs')
[array] $psBoundKeys = $PSBoundParameters.Keys
# adding AsJob for parallel execution
$newAzResourceGroupDeploymentParams['AsJob'] = $true
# updating params from friendly user defined, to template params; under-score usage
switch ($psBoundKeys)
{
'ArtifactsLocation'
{
$newAzResourceGroupDeploymentParams['_artifactsLocation'] = $ArtifactsLocation
[void] $newAzResourceGroupDeploymentParams.Remove('ArtifactsLocation')
}
'ArtifactsLocationSasToken'
{
$newAzResourceGroupDeploymentParams['_artifactsLocationSasToken'] = $ArtifactsLocationSasToken
# the QueryString param is used in conjunction with TemplateUri when decrypted SAS token is used
$decryptedSasToken = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto(
[System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($ArtifactsLocationSasToken)
)
$newAzResourceGroupDeploymentParams['QueryString'] = $decryptedSasToken
[void] $newAzResourceGroupDeploymentParams.Remove('ArtifactsLocationSasToken')
}
}
# creating VM names based on user input
$vmNames = [System.Collections.Specialized.OrderedDictionary]::new()
for ($i = $VmNameSuffixStartingNumber; $i -le $Count; $i++)
{
$assembledVmName = '{0}{1}{2}{3}' -f $VmNamePrefix, $VmName, $VmNameSuffixDelimiter, $i
if ($AvailabilityOptions -eq 'availabilitySet')
{
$assembledAvName = '{0}{1}{2}{3}{4}' -f $VmNamePrefix, $VmName, $VmNameSuffixDelimiter, $i, $AvailabilitySetNameSuffix
}
else
{
$assembledAvName = $null
}
$vmNames[$assembledVmName] = $assembledAvName
}
# assembled VmName validation, if invalid, we're going to fail
if ($($vmNames.Keys)[-1].Length -gt 64 -and $OsVersion -notmatch '^\d+h\d+-e(nt|vd)$|^\d+-Datacenter$')
{
throw "Linux VM Name: $($($vmNames.Keys)[-1]) exceeds 64 characters, unable to continue."
}
if ($($vmNames.Keys)[-1].Length -gt 15 -and $OsVersion -match '^\d+h\d+-e(nt|vd)$|^\d+-Datacenter$')
{
throw "Windows VM Name: $($($vmNames.Keys)[-1]) exceeds 15 characters, unable to continue."
}
foreach ($vmName in $vmNames.Keys)
{
$newAzResourceGroupDeploymentParams['Name'] = $vmName
$newAzResourceGroupDeploymentParams['VmName'] = $vmName
if ($newAzResourceGroupDeploymentParams.ContainsKey('AvailabilitySetNameSuffix'))
{
# the hashtable "value" of the vmName "key" is the AvailabilitySetName
$newAzResourceGroupDeploymentParams['AvailabilitySetName'] = $vmNames[$vmName]
[void] $newAzResourceGroupDeploymentParams.Remove('AvailabilitySetNameSuffix')
}
# handling OsVersion mainTemplate parameter deltas
if ($OsVersion -match '^\d+h\d+-e(nt|vd)$|^\d+-Datacenter$')
{
$newAzResourceGroupDeploymentParams['adminPassword'] = $newAzResourceGroupDeploymentParams['AdminPasswordOrKey']
[void] $newAzResourceGroupDeploymentParams.Remove('AdminPasswordOrKey')
[void] $newAzResourceGroupDeploymentParams.Remove('AuthenticationType')
[void] $newAzResourceGroupDeploymentParams.Remove('CustomData')
}
else
{
[void] $newAzResourceGroupDeploymentParams.Remove('AutoInstallDependencies')
[void] $newAzResourceGroupDeploymentParams.Remove('EnableHybridBenefitServerLicense')
}
$jobInfo = New-AzResourceGroupDeployment @newAzResourceGroupDeploymentParams
Write-Verbose -Message "JobId: $($jobInfo.Id); Name: $($jobInfo.Name); For more details use: Get-Job -Id $($jobInfo.Id)"
# sleep statement is required to provide sufficient time for pid deployment to succeed.
Start-Sleep -Seconds $TimeInSecondsBetweenJobs
}
}
else
{
# import PowerShell data file, structure should mimic .psd1 documented here:
$dataFileStructureLink = '_placeHolder_for_ato_markdown_link_'
$deploymentDataFileImport = Import-PowerShellDataFile -Path $DataFilePath
# if the hashtable keys are more than one, fail, since the structure is incorrect.
if ($deploymentDataFileImport.Keys.Count -gt 1)
{
throw "Deployment Data File structure syntax issue, see the following link for more details: $dataFileStructureLink"
}
# removing DataFilePath based params from $PSBoundParams so that the default param set is used when the scale-deployment script is invoked
[void] $PSBoundParameters.Remove('DataFilePath')
[void] $PSBoundParameters.Remove('LinuxTemplateUri')
[void] $PSBoundParameters.Remove('LinuxArtifactsLocation')
[void] $PSBoundParameters.Remove('WindowsTemplateUri')
[void] $PSBoundParameters.Remove('WindowsArtifactsLocation')
# looping through all deployment hashtables from data file
$scriptPath = Join-Path -Path $PSScriptRoot -ChildPath 'scale-deployment.ps1'
foreach ($newAzResourceGroupDeploymentParams in $deploymentDataFileImport[$deploymentDataFileImport.Keys -as [string]])
{
# if TemplateUri is not used in the data file, use Windows or Linux locations based on OsVersion
if (-not $newAzResourceGroupDeploymentParams.ContainsKey('TemplateUri'))
{
# if the passed OsVersion is windows, use the WindowsTemplateUri param, else use linux
if ($newAzResourceGroupDeploymentParams['OsVersion'] -match '^\d+h\d+-e(nt|vd)$|^\d+-Datacenter$')
{
$newAzResourceGroupDeploymentParams['TemplateUri'] = $WindowsTemplateUri
}
else
{
$newAzResourceGroupDeploymentParams['TemplateUri'] = $LinuxTemplateUri
}
}
# if ArtifactsLocation is not used in the data file, use Windows or Linux locations based on OsVersion
if (-not $newAzResourceGroupDeploymentParams.ContainsKey('ArtifactsLocation'))
{
# if the passed OsVersion is windows, use the WindowArtifactsLocation param, else use linux
if ($newAzResourceGroupDeploymentParams['OsVersion'] -match '^\d+h\d+-e(nt|vd)$|^\d+-Datacenter$')
{
$newAzResourceGroupDeploymentParams['ArtifactsLocation'] = $WindowsArtifactsLocation
}
else
{
$newAzResourceGroupDeploymentParams['ArtifactsLocation'] = $LinuxArtifactsLocation
}
}
# call the deployment script with data file hash table and params passed during script invocation.
& $scriptPath @newAzResourceGroupDeploymentParams @PSBoundParameters
}
}

Двоичный файл не отображается.

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

@ -29,22 +29,83 @@
"constraints": {
"required": true,
"regex": "^[a-z0-9A-Z-]{3,15}$",
"validationMessage": "Virtual machine Name must be between 3 and 15 characters long and contain letters, numbers and hyphens only."
"validationMessage": "Virtual machine name must be between 3 and 15 characters long and contain letters, numbers and hyphens only."
}
},
{
"name": "vmAvailabilitySet",
"type": "Microsoft.Solutions.ResourceSelector",
"label": "Availability set",
"resourceType": "Microsoft.Compute/availabilitySets",
"toolTip": "Select existing Availability set to be configured for Virtual machine. Availability set must be present in the same resource group.",
"options": {
"filter": {
"subscription": "onBasic",
"location": "onBasic"
}
"name": "availabilityOptions",
"type": "Microsoft.Common.DropDown",
"label": "Availability options",
"toolTip": "Azure offers a range of options for managing availability and resiliency for your applications. Architect your solution to use replicated VMs in Availability Sets to protect your apps and data from datacenter outages and maintenance events.",
"defaultValue": "No infrastructure redundancy required",
"constraints": {
"allowedValues": [
{
"value": "default",
"label": "No infrastructure redundancy required"
},
{
"value": "availabilitySet",
"label": "Availability set"
}
],
"required": true
},
"visible": false
"visible": true
},
{
"name": "availabilitySetName",
"type": "Microsoft.Common.TextBox",
"label": "Availability set name",
"toolTip": "Name of the Availability set.",
"constraints": {
"required": "[equals(steps('instance').availabilityOptions, 'availabilitySet')]",
"regex": "^[a-z0-9A-Z-]{3,15}$",
"validationMessage": "Availability set name must be between 3 and 15 characters long and contain letters, numbers and hyphens only."
},
"visible": "[equals(steps('instance').availabilityOptions, 'availabilitySet')]"
},
{
"name": "instanceCount",
"type": "Microsoft.Common.Slider",
"min": 1,
"max": 5,
"label": "Instance count",
"defaultValue": 2,
"showStepMarkers": false,
"toolTip": "Number of virtual machines in the availability set.",
"constraints": {
"required": false
},
"visible": "[equals(steps('instance').availabilityOptions, 'availabilitySet')]"
},
{
"name": "faultDomains",
"type": "Microsoft.Common.Slider",
"min": 1,
"max": 3,
"label": "Fault domains",
"defaultValue": 2,
"showStepMarkers": false,
"toolTip": "Virtual machines in the same fault domain share a common power source and physical network switch.",
"constraints": {
"required": false
},
"visible": "[equals(steps('instance').availabilityOptions, 'availabilitySet')]"
},
{
"name": "updateDomains",
"type": "Microsoft.Common.Slider",
"min": 1,
"max": 5,
"label": "Update domains",
"defaultValue": 3,
"showStepMarkers": true,
"toolTip": "Virtual machines in the same update domain will be restarted together during planned maintenance. Azure never restarts more than one update domain at a time.",
"constraints": {
"required": false
},
"visible": "[equals(steps('instance').availabilityOptions, 'availabilitySet')]"
},
{
"name": "osVersion",
@ -61,6 +122,10 @@
{
"value": "2016-Datacenter",
"label": "2016-Datacenter"
},
{
"value": "19h2-ent",
"label": "Windows-10"
}
],
"required": true
@ -124,6 +189,7 @@
{
"name": "textBlock2",
"type": "Microsoft.Common.TextBlock",
"visible": "[or(equals(steps('instance').osVersion, '2019-Datacenter'), equals(steps('instance').osVersion, '2016-Datacenter'))]",
"options": {
"text": "Licensing"
}
@ -135,6 +201,7 @@
"constraints": {
"required": false
},
"visible": "[or(equals(steps('instance').osVersion, '2019-Datacenter'), equals(steps('instance').osVersion, '2016-Datacenter'))]",
"toolTip": "If you own Windows licenses with active Software Assurance (SA) or have an active Windows Server subscription, use Azure Hybrid Benefit to save compute cost."
}
]
@ -338,7 +405,11 @@
"outputs": {
"location": "[location()]",
"vmName": "[steps('instance').vmName]",
"availabilitySetResourceId": "[steps('instance').vmAvailabilitySet.id]",
"availabilityOptions": "[steps('instance').availabilityOptions]",
"availabilitySetName": "[steps('instance').availabilitySetName]",
"instanceCount": "[steps('instance').instanceCount]",
"faultDomains": "[steps('instance').faultDomains]",
"updateDomains": "[steps('instance').updateDomains]",
"osVersion": "[steps('instance').osVersion]",
"vmSize": "[steps('instance').vmSize]",
"adminUsername": "[steps('instance').adminUsername]",

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

@ -4,7 +4,7 @@
"parameters": {
"vmName": {
"type": "string",
"defaultValue": "simple-vm",
"defaultValue": "stig-vm",
"metadata": {
"description": "Name of the virtual machine."
}
@ -41,7 +41,8 @@
"defaultValue": "2019-Datacenter",
"allowedValues": [
"2019-Datacenter",
"2016-Datacenter"
"2016-Datacenter",
"19h2-ent"
],
"metadata": {
"description": "The Windows version for the VM. This will pick a fully patched image of this given Windows version."
@ -132,11 +133,49 @@
"description": "(Optional) Application Security Group resource id."
}
},
"availabilitySetResourceId": {
"availabilityOptions": {
"type": "string",
"defaultValue": "",
"defaultValue": "default",
"allowedValues": [
"default",
"availabilitySet"
],
"metadata": {
"description": "(Optional) Availability Set resource id."
"description": "(Optional) Availability options."
}
},
"availabilitySetName": {
"type": "string",
"defaultValue": "stig-vm-as",
"metadata": {
"description": "(Optional) Availability set name."
}
},
"instanceCount": {
"type": "int",
"defaultValue": 2,
"minValue": 1,
"maxValue": 5,
"metadata": {
"description": "(Optional) Instance count."
}
},
"faultDomains": {
"type": "int",
"defaultValue": 2,
"minValue": 1,
"maxValue": 3,
"metadata": {
"description": "(Optional) Fault domains."
}
},
"updateDomains": {
"type": "int",
"defaultValue": 3,
"minValue": 1,
"maxValue": 5,
"metadata": {
"description": "(Optional) Update domains."
}
},
"logsRetentionInDays": {
@ -171,6 +210,10 @@
}
},
"variables": {
"instanceCount": "[if(equals(parameters('availabilityOptions'), 'availabilitySet'), parameters('instanceCount'), 1)]",
"availabilitySet": {
"id": "[resourceId('Microsoft.Compute/availabilitySets', parameters('availabilitySetName'))]"
},
"nicName": "[concat(parameters('vmName'), '-nic')]",
"vnetId": {
"new": "[resourceId('Microsoft.Network/virtualNetworks',parameters('vmVirtualNetwork'))]",
@ -196,7 +239,33 @@
"wadperfcounters2": "<PerformanceCounterConfiguration counterSpecifier=\"\\PhysicalDisk(_Total)\\% Disk Read Time\" sampleRate=\"PT15S\" unit=\"Percent\"><annotation displayName=\"Disk active read time\" locale=\"en-us\"/></PerformanceCounterConfiguration><PerformanceCounterConfiguration counterSpecifier=\"\\PhysicalDisk(_Total)\\% Disk Write Time\" sampleRate=\"PT15S\" unit=\"Percent\"><annotation displayName=\"Disk active write time\" locale=\"en-us\"/></PerformanceCounterConfiguration><PerformanceCounterConfiguration counterSpecifier=\"\\PhysicalDisk(_Total)\\Disk Transfers/sec\" sampleRate=\"PT15S\" unit=\"CountPerSecond\"><annotation displayName=\"Disk operations\" locale=\"en-us\"/></PerformanceCounterConfiguration><PerformanceCounterConfiguration counterSpecifier=\"\\PhysicalDisk(_Total)\\Disk Reads/sec\" sampleRate=\"PT15S\" unit=\"CountPerSecond\"><annotation displayName=\"Disk read operations\" locale=\"en-us\"/></PerformanceCounterConfiguration><PerformanceCounterConfiguration counterSpecifier=\"\\PhysicalDisk(_Total)\\Disk Writes/sec\" sampleRate=\"PT15S\" unit=\"CountPerSecond\"><annotation displayName=\"Disk write operations\" locale=\"en-us\"/></PerformanceCounterConfiguration><PerformanceCounterConfiguration counterSpecifier=\"\\PhysicalDisk(_Total)\\Disk Bytes/sec\" sampleRate=\"PT15S\" unit=\"BytesPerSecond\"><annotation displayName=\"Disk speed\" locale=\"en-us\"/></PerformanceCounterConfiguration><PerformanceCounterConfiguration counterSpecifier=\"\\PhysicalDisk(_Total)\\Disk Read Bytes/sec\" sampleRate=\"PT15S\" unit=\"BytesPerSecond\"><annotation displayName=\"Disk read speed\" locale=\"en-us\"/></PerformanceCounterConfiguration><PerformanceCounterConfiguration counterSpecifier=\"\\PhysicalDisk(_Total)\\Disk Write Bytes/sec\" sampleRate=\"PT15S\" unit=\"BytesPerSecond\"><annotation displayName=\"Disk write speed\" locale=\"en-us\"/></PerformanceCounterConfiguration><PerformanceCounterConfiguration counterSpecifier=\"\\LogicalDisk(_Total)\\% Free Space\" sampleRate=\"PT15S\" unit=\"Percent\"><annotation displayName=\"Disk free space (percentage)\" locale=\"en-us\"/></PerformanceCounterConfiguration></PerformanceCounters>",
"wadcfgxstart": "[concat(variables('wadlogs'), variables('wadperfcounters1'), variables('wadperfcounters2'), '<Metrics resourceId=\"')]",
"wadmetricsresourceid": "[resourceId('Microsoft.Compute/virtualMachines', parameters('vmName'))]",
"wadcfgxend": "\"><MetricAggregation scheduledTransferPeriod=\"PT1H\"/><MetricAggregation scheduledTransferPeriod=\"PT1M\"/></Metrics></DiagnosticMonitorConfiguration></WadCfg>"
"wadcfgxend": "\"><MetricAggregation scheduledTransferPeriod=\"PT1H\"/><MetricAggregation scheduledTransferPeriod=\"PT1M\"/></Metrics></DiagnosticMonitorConfiguration></WadCfg>",
"images": {
"2019-Datacenter": {
"reference": {
"publisher": "MicrosoftWindowsServer",
"offer": "WindowsServer",
"sku": "2019-Datacenter",
"version": "latest"
}
},
"2016-Datacenter": {
"reference": {
"publisher": "MicrosoftWindowsServer",
"offer": "WindowsServer",
"sku": "2016-Datacenter",
"version": "latest"
}
},
"19h2-ent": {
"reference": {
"publisher": "MicrosoftWindowsDesktop",
"offer": "Windows-10",
"sku": "19h2-ent",
"version": "latest"
}
}
}
},
"resources": [
{
@ -235,11 +304,29 @@
]
}
},
{
"type": "Microsoft.Compute/availabilitySets",
"apiVersion": "2020-06-01",
"name": "[parameters('availabilitySetName')]",
"location": "[parameters('location')]",
"condition": "[equals(parameters('availabilityOptions'), 'availabilitySet')]",
"sku": {
"name": "Aligned"
},
"properties": {
"PlatformUpdateDomainCount": "[parameters('updateDomains')]",
"PlatformFaultDomainCount": "[parameters('faultDomains')]"
}
},
{
"type": "Microsoft.Network/networkInterfaces",
"apiVersion": "2020-06-01",
"name": "[variables('nicName')]",
"name": "[concat(variables('nicName'), if(equals(variables('instanceCount'), 1), '', copyIndex()))]",
"location": "[parameters('location')]",
"copy": {
"name": "nicLoop",
"count": "[variables('instanceCount')]"
},
"dependsOn": [
"[resourceId('Microsoft.Network/virtualNetworks', parameters('vmVirtualNetwork'))]"
],
@ -262,11 +349,15 @@
{
"type": "Microsoft.Network/networkInterfaces/providers/diagnosticSettings",
"apiVersion": "2017-05-01-preview",
"name": "[concat(variables('nicName'), '/Microsoft.Insights/service')]",
"name": "[concat(variables('nicName'), if(equals(variables('instanceCount'), 1), '', copyIndex()), '/Microsoft.Insights/service')]",
"location": "[parameters('location')]",
"condition": "[or(not(equals(parameters('diagnosticStorageResourceId'), '')), not(equals(parameters('logAnalyticsWorkspaceId'), '')))]",
"copy": {
"name": "nicDiagnosticLoop",
"count": "[variables('instanceCount')]"
},
"dependsOn": [
"[variables('nicName')]"
"nicLoop"
],
"properties": {
"storageAccountId": "[if(equals(parameters('diagnosticStorageResourceId'), ''), json('null'), parameters('diagnosticStorageResourceId'))]",
@ -286,10 +377,14 @@
{
"type": "Microsoft.Compute/virtualMachines",
"apiVersion": "2020-06-01",
"name": "[parameters('vmName')]",
"name": "[concat(parameters('vmName'), if(equals(variables('instanceCount'), 1), '', copyIndex()))]",
"location": "[parameters('location')]",
"copy": {
"name": "virtualMachineLoop",
"count": "[variables('instanceCount')]"
},
"dependsOn": [
"[resourceId('Microsoft.Network/networkInterfaces', variables('nicName'))]"
"nicLoop"
],
"properties": {
"hardwareProfile": {
@ -301,12 +396,7 @@
"adminPassword": "[parameters('adminPassword')]"
},
"storageProfile": {
"imageReference": {
"publisher": "MicrosoftWindowsServer",
"offer": "WindowsServer",
"sku": "[parameters('osVersion')]",
"version": "latest"
},
"imageReference": "[variables('images')[parameters('osVersion')].reference]",
"osDisk": {
"createOption": "FromImage",
"managedDisk": {
@ -318,11 +408,11 @@
"networkProfile": {
"networkInterfaces": [
{
"id": "[resourceId('Microsoft.Network/networkInterfaces', variables('nicName'))]"
"id": "[resourceId('Microsoft.Network/networkInterfaces', concat(variables('nicName'), if(equals(variables('instanceCount'), 1), '', copyIndex())))]"
}
]
},
"availabilitySet": "[if(equals(parameters('availabilitySetResourceId'), ''), json('null'), parameters('availabilitySetResourceId'))]",
"availabilitySet": "[if(equals(parameters('availabilityOptions'), 'availabilitySet'), variables('availabilitySet'), json('null'))]",
"diagnosticsProfile": {
"bootDiagnostics": {
"enabled": "[if(equals(parameters('diagnosticStorageResourceId'), ''), false(), true())]",
@ -332,116 +422,20 @@
"licenseType": "[if(equals(parameters('enableHybridBenefitServerLicense'), true()), 'Windows_Server', json('null'))]"
},
"resources": [
{
"name": "[concat(parameters('vmName'), '/Microsoft.Insights.VMDiagnosticsSettings')]",
"type": "Microsoft.Compute/virtualMachines/extensions",
"location": "[parameters('location')]",
"apiVersion": "2020-06-01",
"condition": "[not(equals(parameters('diagnosticStorageResourceId'), ''))]",
"dependsOn": [
"[resourceId('Microsoft.Compute/virtualMachines', parameters('vmName'))]"
],
"tags": {
"displayName": "AzureDiagnostics"
},
"properties": {
"publisher": "Microsoft.Azure.Diagnostics",
"type": "IaaSDiagnostics",
"typeHandlerVersion": "1.5",
"autoUpgradeMinorVersion": true,
"settings": {
"xmlCfg": "[base64(concat(variables('wadcfgxstart'), variables('wadmetricsresourceid'), variables('wadcfgxend')))]",
"storageAccount": "[variables('storageAccountName')]"
},
"protectedSettings": {
"storageAccountName": "[variables('storageAccountName')]",
"storageAccountKey": "[if(equals(parameters('diagnosticStorageResourceId'), ''), '', listkeys(variables('storageAccountResourceid'), '2019-06-01').keys[0].value)]",
"storageAccountEndPoint": "[concat('https://', environment().suffixes.storage)]"
}
}
},
{
"type": "extensions",
"apiVersion": "2020-12-01",
"name": "install-powershell-modules",
"location": "[parameters('location')]",
"condition": "[not(equals(parameters('_artifactsLocation'), ''))]",
"dependsOn": [
"[resourceId('Microsoft.Compute/virtualMachines', parameters('vmName'))]"
],
"properties": {
"publisher": "Microsoft.Compute",
"type": "CustomScriptExtension",
"typeHandlerVersion": "1.10",
"autoUpgradeMinorVersion": true,
"settings": {
"fileUris": [
"[concat(parameters('_artifactsLocation'), variables('requiredModulesFile'), variables('artifactsLocationSasToken'))]",
"[concat(parameters('_artifactsLocation'), variables('installPSModulesFile'), variables('artifactsLocationSasToken'))]",
"[concat(parameters('_artifactsLocation'), variables('generateStigChecklist'), variables('artifactsLocationSasToken'))]"
],
"timestamp": 123456788,
"commandToExecute": "[concat('PowerShell -ExecutionPolicy Unrestricted -File ', variables('installPSModulesFile'), ' -autoInstallDependencies ', parameters('autoInstallDependencies'))]"
}
}
},
{
"type": "extensions",
"apiVersion": "2020-12-01",
"name": "[concat('setup-win-dsc-stig')]",
"location": "[parameters('location')]",
"condition": "[not(equals(parameters('_artifactsLocation'), ''))]",
"dependsOn": [
"[resourceId('Microsoft.Compute/virtualMachines', parameters('vmName'))]",
"[resourceId('Microsoft.Compute/virtualMachines/extensions', parameters('vmName'), 'install-powershell-modules')]"
],
"properties": {
"publisher": "Microsoft.Powershell",
"type": "DSC",
"typeHandlerVersion": "2.77",
"autoUpgradeMinorVersion": true,
"settings": {
"wmfVersion": "latest",
"configuration": {
"url": "[concat(parameters('_artifactsLocation'), 'WindowsServer.ps1.zip', variables('artifactsLocationSasToken'))]",
"script": "WindowsServer.ps1",
"function": "WindowsServer"
}
}
}
},
{
"type": "extensions",
"name": "Microsoft.EnterpriseCloud.Monitoring",
"apiVersion": "2015-06-15",
"location": "[parameters('location')]",
"condition": "[not(equals(parameters('logAnalyticsWorkspaceId'), ''))]",
"dependsOn": [
"[resourceId('Microsoft.Compute/virtualMachines', parameters('vmName'))]"
],
"properties": {
"publisher": "Microsoft.EnterpriseCloud.Monitoring",
"type": "MicrosoftMonitoringAgent",
"typeHandlerVersion": "1.0",
"autoUpgradeMinorVersion": true,
"settings": {
"workspaceId": "[if(equals(parameters('logAnalyticsWorkspaceId'), ''), json('null'), reference(parameters('logAnalyticsWorkspaceId'), '2015-03-20').customerId)]"
},
"protectedSettings": {
"workspaceKey": "[if(equals(parameters('logAnalyticsWorkspaceId'), ''), json('null'), listkeys(parameters('logAnalyticsWorkspaceId'), '2015-03-20').primarySharedKey)]"
}
}
}
]
},
{
"type": "Microsoft.Compute/virtualMachines/providers/diagnosticSettings",
"apiVersion": "2017-05-01-preview",
"name": "[concat(parameters('vmName'), '/Microsoft.Insights/service')]",
"name": "[concat(parameters('vmName'), if(equals(variables('instanceCount'), 1), '', copyIndex()), '/Microsoft.Insights/service')]",
"location": "[parameters('location')]",
"condition": "[or(not(equals(parameters('diagnosticStorageResourceId'), '')), not(equals(parameters('logAnalyticsWorkspaceId'), '')))]",
"copy": {
"name": "virtualMachineDiagnosticLoop",
"count": "[variables('instanceCount')]"
},
"dependsOn": [
"[parameters('vmName')]"
"virtualMachineLoop"
],
"properties": {
"storageAccountId": "[if(equals(parameters('diagnosticStorageResourceId'), ''), json('null'), parameters('diagnosticStorageResourceId'))]",
@ -458,6 +452,121 @@
]
}
},
{
"type": "Microsoft.Compute/virtualMachines/extensions",
"apiVersion": "2015-06-15",
"name": "[concat(parameters('vmName'), if(equals(variables('instanceCount'), 1), '', copyIndex()), '/Microsoft.EnterpriseCloud.Monitoring')]",
"location": "[parameters('location')]",
"condition": "[not(equals(parameters('logAnalyticsWorkspaceId'), ''))]",
"copy": {
"name": "monitoringAgentLoop",
"count": "[variables('instanceCount')]"
},
"dependsOn": [
"virtualMachineDiagnosticLoop"
],
"properties": {
"publisher": "Microsoft.EnterpriseCloud.Monitoring",
"type": "MicrosoftMonitoringAgent",
"typeHandlerVersion": "1.0",
"autoUpgradeMinorVersion": true,
"settings": {
"workspaceId": "[if(equals(parameters('logAnalyticsWorkspaceId'), ''), json('null'), reference(parameters('logAnalyticsWorkspaceId'), '2015-03-20').customerId)]"
},
"protectedSettings": {
"workspaceKey": "[if(equals(parameters('logAnalyticsWorkspaceId'), ''), json('null'), listkeys(parameters('logAnalyticsWorkspaceId'), '2015-03-20').primarySharedKey)]"
}
}
},
{
"type": "Microsoft.Compute/virtualMachines/extensions",
"apiVersion": "2020-06-01",
"name": "[concat(parameters('vmName'), if(equals(variables('instanceCount'), 1), '', copyIndex()), '/Microsoft.Insights.VMDiagnosticsSettings')]",
"location": "[parameters('location')]",
"condition": "[not(equals(parameters('diagnosticStorageResourceId'), ''))]",
"copy": {
"name": "iaasDiagnosticLoop",
"count": "[variables('instanceCount')]"
},
"dependsOn": [
"monitoringAgentLoop"
],
"properties": {
"publisher": "Microsoft.Azure.Diagnostics",
"type": "IaaSDiagnostics",
"typeHandlerVersion": "1.5",
"autoUpgradeMinorVersion": true,
"settings": {
"xmlCfg": "[base64(concat(variables('wadcfgxstart'), variables('wadmetricsresourceid'), variables('wadcfgxend')))]",
"storageAccount": "[variables('storageAccountName')]"
},
"protectedSettings": {
"storageAccountName": "[variables('storageAccountName')]",
"storageAccountKey": "[if(equals(parameters('diagnosticStorageResourceId'), ''), '', listkeys(variables('storageAccountResourceid'), '2019-06-01').keys[0].value)]",
"storageAccountEndPoint": "[concat('https://', environment().suffixes.storage)]"
}
}
},
{
"type": "Microsoft.Compute/virtualMachines/extensions",
"apiVersion": "2020-12-01",
"name": "[concat(parameters('vmName'), if(equals(variables('instanceCount'), 1), '', copyIndex()), '/install-powershell-modules')]",
"location": "[parameters('location')]",
"condition": "[not(equals(parameters('_artifactsLocation'), ''))]",
"copy": {
"name": "cseLoop",
"count": "[variables('instanceCount')]"
},
"dependsOn": [
"iaasDiagnosticLoop"
],
"properties": {
"publisher": "Microsoft.Compute",
"type": "CustomScriptExtension",
"typeHandlerVersion": "1.10",
"autoUpgradeMinorVersion": true,
"protectedSettings": {
"fileUris": [
"[concat(parameters('_artifactsLocation'), variables('requiredModulesFile'), variables('artifactsLocationSasToken'))]",
"[concat(parameters('_artifactsLocation'), variables('installPSModulesFile'), variables('artifactsLocationSasToken'))]",
"[concat(parameters('_artifactsLocation'), variables('generateStigChecklist'), variables('artifactsLocationSasToken'))]"
],
"ignoreRelativePathForFileDownloads": true
},
"settings": {
"timestamp": 123456788,
"commandToExecute": "[concat('PowerShell -ExecutionPolicy Unrestricted -File ', variables('installPSModulesFile'), ' -autoInstallDependencies ', parameters('autoInstallDependencies'))]"
}
}
},
{
"type": "Microsoft.Compute/virtualMachines/extensions",
"apiVersion": "2020-12-01",
"name": "[concat(parameters('vmName'), if(equals(variables('instanceCount'), 1), '', copyIndex()), '/setup-win-dsc-stig')]",
"location": "[parameters('location')]",
"condition": "[not(equals(parameters('_artifactsLocation'), ''))]",
"copy": {
"name": "dscLoop",
"count": "[variables('instanceCount')]"
},
"dependsOn": [
"cseLoop"
],
"properties": {
"publisher": "Microsoft.Powershell",
"type": "DSC",
"typeHandlerVersion": "2.77",
"autoUpgradeMinorVersion": true,
"settings": {
"wmfVersion": "latest",
"configuration": {
"url": "[concat(parameters('_artifactsLocation'), 'Windows.ps1.zip', variables('artifactsLocationSasToken'))]",
"script": "Windows.ps1",
"function": "Windows"
}
}
}
},
{
"apiVersion": "2020-06-01",
"name": "pid-93aca1dd-7b6a-4db4-a130-45f5b7c82c5c",