diff --git a/Templates/SharePoint-ADFS/.vscode/tasks.json b/Templates/SharePoint-ADFS/.vscode/tasks.json new file mode 100644 index 00000000..a2f0d174 --- /dev/null +++ b/Templates/SharePoint-ADFS/.vscode/tasks.json @@ -0,0 +1,24 @@ +{ + // See https://go.microsoft.com/fwlink/?LinkId=733558 + // for the documentation about the tasks.json format + "version": "2.0.0", + "tasks": [ + { + "label": "generate azuredeploy.json", + "type": "shell", + "command": "az", + "args": [ + "bicep", + "build", + "--file", + "main.bicep", + "--outfile", + "azuredeploy.json" + ], + "group": "build", + "presentation": { + "reveal": "silent" + } + } + ] +} \ No newline at end of file diff --git a/Templates/SharePoint-ADFS/CHANGELOG.md b/Templates/SharePoint-ADFS/CHANGELOG.md index 4474e7bd..8bce4f10 100644 --- a/Templates/SharePoint-ADFS/CHANGELOG.md +++ b/Templates/SharePoint-ADFS/CHANGELOG.md @@ -1,7 +1,33 @@ # Change log for Azure template SharePoint-ADFS +## Unreleased + +### Added + +- Template + - Add parameter `outboundAccessMethod`, to choose how the virtual machines connect to internet. Now, they can connect through either a public IP, or using Azure Firewall as an HTTP proxy + - Add value `Subscription-24H1` to parameter `sharePointVersion`, to install SharePoint Subscription with 24H1 update + - Add value `Subscription-24H2` to parameter `sharePointVersion`, to install SharePoint Subscription with 24H2 update + +### Changed + +- Template + - Convert the template to Bicep + - [BREAKING CHANGE] Rename most of the parameters + - Update the display name of most of the resources to be more consistent and reflect their relationship with each other + - Value `Subscription-Latest` for parameter `sharePointVersion` now installs the September 2024 CU for SharePoint Subscription +- All DSC configurations + - Add a firewall rule to all virtual machines to allow remote event viewer connections + - Updated DSC module `ActiveDirectoryDsc` to 6.4.0 + - Updated DSC module `ComputerManagementDsc` to 9.1.0 + - Updated DSC module `SharePointDSC` to 5.5.0 +- DSC Configuration for DC + - Updated DSC module `AdfsDsc` to 1.4.0 + ## Enhancements & bug-fixes - Published in February 26, 2024 +### Changed + - Template - Value `Subscription-Latest` for parameter `sharePointVersion` now installs the February 2024 CU for SharePoint Subscription - Remove SharePoint 2013 diff --git a/Templates/SharePoint-ADFS/Deploy-AzureResourceGroup.ps1 b/Templates/SharePoint-ADFS/Deploy-AzureResourceGroup.ps1 index 63a99813..4735f164 100644 --- a/Templates/SharePoint-ADFS/Deploy-AzureResourceGroup.ps1 +++ b/Templates/SharePoint-ADFS/Deploy-AzureResourceGroup.ps1 @@ -1,43 +1,41 @@ #Requires -PSEdition Core #Requires -Module Az.Resources -### Define variables -$resourceGroupLocation = 'westeurope' -# $resourceGroupLocation = 'francecentral' -$resourceGroupName = "xydsp1" +### Set variables +$resourceGroupLocation = 'francecentral' +$resourceGroupName = "xxydsp2" # $resourceGroupName = "gf(d)df_-sf.sm" -$templateFileName = 'azuredeploy.json' +$templateFileName = 'main.bicep' $templateParametersFileName = 'azuredeploy.parameters.json' -$scriptRoot = $PSScriptRoot -#$scriptRoot = "C:\Job\Dev\Github\AzureRM-Templates\SharePoint\SharePoint-ADFS" -$TemplateFile = [System.IO.Path]::GetFullPath([System.IO.Path]::Combine($scriptRoot, $templateFileName)) -$templateParametersFile = [System.IO.Path]::GetFullPath([System.IO.Path]::Combine($scriptRoot, $templateParametersFileName)) ### Set passwords # $securePassword = $password| ConvertTo-SecureString -AsPlainText -Force if ($null -eq $securePassword) { $securePassword = Read-Host "Type the password of admin and service accounts" -AsSecureString } $passwords = New-Object -TypeName HashTable $passwords.adminPassword = $securePassword -$passwords.serviceAccountsPassword = $securePassword +$passwords.otherAccountsPassword = $securePassword -### Set parameters -$parameters = New-Object -TypeName HashTable -$parameters.adminPassword = $securePassword -$parameters.serviceAccountsPassword = $securePassword -$paramFileContent = Get-Content $TemplateParametersFile -Raw | ConvertFrom-Json -$paramFileContent.parameters | Get-Member -MemberType *Property | ForEach-Object { - $parameters.($_.name) = $paramFileContent.parameters.($_.name).value; -} +# ### Set parameters +$scriptRoot = $PSScriptRoot +#$scriptRoot = "C:\Job\Dev\Github\AzureRM-Templates\SharePoint\SharePoint-ADFS" +$TemplateFile = [System.IO.Path]::GetFullPath([System.IO.Path]::Combine($scriptRoot, $templateFileName)) +$templateParametersFile = [System.IO.Path]::GetFullPath([System.IO.Path]::Combine($scriptRoot, $templateParametersFileName)) +# $parameters = New-Object -TypeName HashTable +# $parameters.adminPassword = $securePassword +# $parameters.otherAccountsPassword = $securePassword +# $paramFileContent = Get-Content $TemplateParametersFile -Raw | ConvertFrom-Json +# $paramFileContent.parameters | Get-Member -MemberType *Property | ForEach-Object { +# $parameters.($_.name) = $paramFileContent.parameters.($_.name).value; +# } -$resourceDeploymentName = "$resourceGroupName-deployment" Write-Host "Starting deployment of template in resource group '$resourceGroupName' in '$resourceGroupLocation'..." -ForegroundColor Green -### Ensure connection to Azure RM +### Validate connection to Azure $azurecontext = $null $azurecontext = Get-AzContext -ErrorAction SilentlyContinue if ($null -eq $azurecontext -or $null -eq $azurecontext.Account -or $null -eq $azurecontext.Subscription) { - Write-Host "Launching Azure authentication prompt..." -ForegroundColor Green - Connect-AzAccount + Write-Host "Connecting to Azure..." -ForegroundColor Green + Connect-AzAccount -UseDeviceAuthentication $azurecontext = Get-AzContext -ErrorAction SilentlyContinue } if ($null -eq $azurecontext -or $null -eq $azurecontext.Account -or $null -eq $azurecontext.Subscription) { @@ -45,7 +43,7 @@ if ($null -eq $azurecontext -or $null -eq $azurecontext.Account -or $null -eq $a return } -### Create Resource Group if it doesn't exist +### Create the resource group if needed if ($null -eq (Get-AzResourceGroup -ResourceGroupName $resourceGroupName -ErrorAction SilentlyContinue)) { New-AzResourceGroup ` -Name $resourceGroupName ` @@ -63,10 +61,11 @@ $checkTemplate = Test-AzResourceGroupDeployment ` @passwords # -TemplateParameterObject $parameters +$resourceDeploymentName = "$resourceGroupName-deployment" if ($checkTemplate.Count -eq 0) { # Template is valid, deploy it $startTime = $(Get-Date) - Write-Host "Starting template deployment..." -ForegroundColor Green + Write-Host "Starting deployment of template..." -ForegroundColor Green $result = New-AzResourceGroupDeployment ` -Name $resourceDeploymentName ` -ResourceGroupName $resourceGroupName ` diff --git a/Templates/SharePoint-ADFS/README.md b/Templates/SharePoint-ADFS/README.md index 8d6114a7..a2ab68c6 100644 --- a/Templates/SharePoint-ADFS/README.md +++ b/Templates/SharePoint-ADFS/README.md @@ -1,14 +1,15 @@ --- -description: This template creates a SharePoint Subscription / 2019 / 2016 farm with an extensive configuration that would take ages to perform manually, including a federated authentication with ADFS, an OAuth trust, the User Profiles service and a web application with 2 zones that contains multiple path based and host-named site collections. On the SharePoint virtual machines, Chocolatey is used to install the latest version of Notepad++, Visual Studio Code, Azure Data Studio, Fiddler, ULS Viewer and 7-Zip. +description: This template creates a DC, a SQL Server 2022, and from 1 to 5 server(s) hosting a SharePoint Subscription / 2019 / 2016 farm with an extensive configuration, including trusted authentication, user profiles with personal sites, an OAuth trust (using a certificate), a dedicated IIS site for hosting high-trust add-ins, etc... The latest version of key softwares (including Fiddler, vscode, np++, 7zip, ULS Viewer) is installed. SharePoint machines have additional fine-tuning to make them immediately usable (remote administration tools, custom policies for Edge and Chrome, shortcuts, etc...).. page_type: sample products: - azure - azure-resource-manager urlFragment: sharepoint-adfs languages: +- bicep - json --- -# SharePoint Subscription / 2019 / 2016 all configured +# SharePoint Subscription / 2019 / 2016 fully configured ## Deploy the template @@ -20,8 +21,10 @@ languages: ## Features -This templates creates a SharePoint Subscription / 2019 / 2016 farm with an extensive configuration that would take ages to perform manually, including a federated authentication with ADFS, an OAuth trust, the User Profiles service and a web application with 2 zones and multiple path based and host-named site collections. -On the SharePoint virtual machines, [Chocolatey](https://chocolatey.org/) is used to install the latest version of Notepad++, Visual Studio Code, Azure Data Studio, Fiddler, ULS Viewer and 7-Zip. +This template creates a DC, a SQL Server 2022, and from 1 to 5 server(s) hosting a SharePoint Subscription / 2019 / 2016 farm with an extensive configuration, including trusted authentication, user profiles with personal sites, an OAuth trust (using a certificate), a dedicated IIS site for hosting high-trust add-ins, etc... +The latest version of key softwares (including Fiddler, vscode, np++, 7zip, ULS Viewer) is installed. +SharePoint machines have additional fine-tuning to make them immediately usable (remote administration tools, custom policies for Edge and Chrome, shortcuts, etc...). + There are some differences in the configuration, depending on the SharePoint version: ### Common to all SharePoint versions @@ -47,44 +50,45 @@ There are some differences in the configuration, depending on the SharePoint ver - The HTTPS site certificate is positioned by the DSC script. - Federated authentication with ADFS is configured using SAML 1.1. -## Key parameters +## Outbound access to internet + +During the provisionning, virtual machines require an outbound access to internet to be able to download and apply their configuration. +The outbound access method depends on variable `outboundAccessMethod`: +- `PublicIPAddress`: Virtual machines use a [Public IP](https://learn.microsoft.com/en-us/azure/virtual-network/ip-services/virtual-network-public-ip-address), associated to their network card. +- `AzureFirewallProxy`: Virtual machines use [Azure Firewall](https://azure.microsoft.com/en-us/products/azure-firewall/) as an [HTTP proxy](https://learn.microsoft.com/en-us/azure/firewall/explicit-proxy). + +## Remote access + +The remote access to the virtual machines depends on the following parameters: + +- Parameter `rdpTrafficRule` specifies if a rule in the network security groups should allow the inbound RDP traffic: + - `No` (default): No rule is created, RDP traffic is blocked. + - `*` or `Internet`: RDP traffic is allowed from everywhere. + - CIDR notation (e.g. `192.168.99.0/24` or `2001:1234::/64`) or an IP address (e.g. `192.168.99.0` or `2001:1234::`): RDP traffic is allowed from the IP address / pattern specified. +- parameter `enable_azure_bastion`: + - if `true`: Configure service [Azure Bastion](https://azure.microsoft.com/services/azure-bastion/) to allow a secure remote access to virtual machines. + - if `false` (default): Service [Azure Bastion](https://azure.microsoft.com/services/azure-bastion/) is not created. + +IMPORTANT: If you set variable `outboundAccessMethod` to `AzureFirewallProxy`, you have to either enable Azure Bastion, or manually add a public IP address later, to be able to connect to a virtual machine. ### Input parameters - parameter `sharePointVersion` lets you choose which version of SharePoint to install: - - `Subscription-Latest` (default): Same as `Subscription-RTM`, then installs the latest cumulative update available at the time of publishing this version: February 2024 ([kb5002560](https://support.microsoft.com/help/5002560)). + - `Subscription-Latest` (default): Same as `Subscription-RTM`, then installs the latest cumulative update available at the time of publishing this version: September 2024 ([kb5002640](https://support.microsoft.com/help/5002640)). + - `Subscription-24H2`: Same as `Subscription-RTM`, then installs the [Feature Update 24H2](https://learn.microsoft.com/en-us/sharepoint/what-s-new/new-and-improved-features-in-sharepoint-server-subscription-edition-24h2-release) (September 2024 CU / [kb5002640](https://support.microsoft.com/help/5002640)). + - `Subscription-24H1`: Same as `Subscription-RTM`, then installs the [Feature Update 24H1](https://learn.microsoft.com/en-us/sharepoint/what-s-new/new-and-improved-features-in-sharepoint-server-subscription-edition-24h1-release) (March 2024 CU / [KB5002564](https://support.microsoft.com/help/5002564)). - `Subscription-23H2`: Same as `Subscription-RTM`, then installs the [Feature Update 23H2](https://learn.microsoft.com/en-us/SharePoint/what-s-new/new-and-improved-features-in-sharepoint-server-subscription-edition-23h2-release) (September 2023 CU / [KB5002474](https://support.microsoft.com/help/5002474)). - `Subscription-23H1`: Same as `Subscription-RTM`, then installs the [Feature Update 23H1](https://learn.microsoft.com/en-us/sharepoint/what-s-new/new-and-improved-features-in-sharepoint-server-subscription-edition-23h1-release) (March 2023 CU / [KB5002355](https://support.microsoft.com/help/5002355)). - `Subscription-22H2`: Same as `Subscription-RTM`, then installs the [Feature Update 22H2](https://learn.microsoft.com/en-us/sharepoint/what-s-new/new-and-improved-features-in-sharepoint-server-subscription-edition-22h2-release) (September 2022 CU / [KB5002270](https://support.microsoft.com/help/5002270) and [KB5002271](https://support.microsoft.com/help/5002271)). - `Subscription-RTM`: Uses a fresh Windows Server 2022 image, on which SharePoint Subscription RTM is downloaded and installed. - `2019`: Uses an image built and maintained by SharePoint Engineering, with SharePoint 2019 bits already installed. - `2016`: Uses an image built and maintained by SharePoint Engineering, with SharePoint 2016 bits already installed. -- parameters `addPublicIPAddress` and `RDPTrafficAllowed`: See [this section](#remote-access-and-security) for detailed information. -- parameter `numberOfAdditionalFrontEnd` lets you add up to 4 additional SharePoint servers to the farm with the [MinRole Front-end](https://learn.microsoft.com/en-us/sharepoint/install/planning-for-a-minrole-server-deployment-in-sharepoint-server). -- parameter `enableHybridBenefitServerLicenses` allows you to enable Azure Hybrid Benefit to use your on-premises Windows Server licenses and reduce cost, if you are eligible. See [this page](https://docs.microsoft.com/azure/virtual-machines/windows/hybrid-use-benefit-licensing) for more information.. - -### Output parameters - -The template returns multiple variables to record the logins, passwords and the public IP address of virtual machines. - -## Remote access and security - -The template creates 1 virtual network with 3 subnets (+1 if [Azure Bastion](https://azure.microsoft.com/services/azure-bastion/) is enabled), and each subnet is protected by a [Network Security Group](https://docs.microsoft.com/azure/virtual-network/network-security-groups-overview) which denies all incoming traffic by default. -The following parameters configure how to connect to the virtual machines, and the level of network security: - -- parameters `adminPassword` and `serviceAccountsPassword` require a [strong password](https://learn.microsoft.com/azure/virtual-machines/windows/faq#what-are-the-password-requirements-when-creating-a-vm-). -- parameter `addPublicIPAddress`: - - if `"SharePointVMsOnly"` (default): Only SharePoint virtual machines get a public IP address with a DNS name and can be reached from Internet. - - If `"Yes"`: All virtual machines get a public IP address with a DNS name, and can be reached from Internet. - - if `"No"`: No public IP resource is created. - - The DNS name format of virtual machines is `"[resourceGroupName]-[vm_name].[region].cloudapp.azure.com"` and is recorded as output in the state file. -- parameter `RDPTrafficAllowed` specifies if RDP traffic is allowed: - - If `"No"` (default): Firewall denies all incoming RDP traffic. - - If `"*"` or `"Internet"`: Firewall accepts all incoming RDP traffic from Internet (very, very much not recommended). - - If CIDR notation (e.g. `"192.168.99.0/24"` or `"2001:1234::/64"`) or IP address (e.g. `"192.168.99.0"` or `"2001:1234::"`): Firewall accepts incoming RDP traffic from the IP addresses specified. -- parameter `addAzureBastion`: - - if `true`: Configure service [Azure Bastion](https://azure.microsoft.com/services/azure-bastion/) to allow a secure remote access to virtual machines. - - if `false` (default): Service [Azure Bastion](https://azure.microsoft.com/services/azure-bastion/) is not created. +- Variable `frontEndServersCount` lets you add up to 4 additional SharePoint servers to the farm with the [MinRole Front-end](https://learn.microsoft.com/en-us/sharepoint/install/planning-for-a-minrole-server-deployment-in-sharepoint-server). +- Variable `enableHybridBenefitServerLicenses` allows you to enable Azure Hybrid Benefit to use your on-premises Windows Server licenses and reduce cost, if you are eligible. See [this page](https://docs.microsoft.com/azure/virtual-machines/windows/hybrid-use-benefit-licensing) for more information.. + +## Outputs + +The template returns multiple values to record the logins and the public IP address of virtual machines. ## Cost of the resources deployed @@ -95,11 +99,11 @@ Here is the default size and storage type per virtual machine role: - SQL Server: Size [Standard_B2ms](https://docs.microsoft.com/azure/virtual-machines/sizes-b-series-burstable) (2 vCPU / 8 GiB RAM) and OS disk is a 128 GiB [standard SSD E10](https://learn.microsoft.com/azure/virtual-machines/disks-types#standard-ssds). - SharePoint: Size [Standard_B4ms](https://docs.microsoft.com/azure/virtual-machines/sizes-b-series-burstable) (4 vCPU / 16 GiB RAM) and OS disk is either a 32 GiB [standard SSD E4](https://learn.microsoft.com/azure/virtual-machines/disks-types#standard-ssds) (for SharePoint Subscription and 2019), or a 128 GiB [standard SSD E10](https://learn.microsoft.com/azure/virtual-machines/disks-types#standard-ssds) (for SharePoint 2016). -You can visit to estimate the monthly cost of the template in the region/currency of your choice, assuming it is created using the default settings and runs 24*7. +You can visit to estimate the monthly cost of the template in the region/currency of your choice, assuming it is created using the default settings and runs 24*7. ## Known issues -- The password of the directory synchronization connection (set in parameter `serviceAccountsPassword`) needs to be re-entered in the "Edit synchronization connection" page, otherwise SharePoint is somehow unable to decrypt it and the import fails. +- The password for the User Profile directory synchronization connection (value of parameter `otherAccountsPassword`) needs to be re-entered in the "Edit synchronization connection" page, otherwise the import fails (password decryption error). ## More information diff --git a/Templates/SharePoint-ADFS/azuredeploy.json b/Templates/SharePoint-ADFS/azuredeploy.json index ea8ad4c3..389500f2 100644 --- a/Templates/SharePoint-ADFS/azuredeploy.json +++ b/Templates/SharePoint-ADFS/azuredeploy.json @@ -1,8 +1,13 @@ { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "5.0.0.0", + "contentVersion": "1.0.0.0", "metadata": { - "description": "Create a SharePoint Subscription / 2019 / 2016 farm with an extensive configuration that would take ages to perform manually, and install useful softwares like Fiddler, vscode, np++, 7zip, ULS Viewer to get ready to use", + "_generator": { + "name": "bicep", + "version": "0.29.47.4906", + "templateHash": "15949922842727340567" + }, + "description": "Create a DC, a SQL Server 2022, and from 1 to 5 server(s) hosting a SharePoint Subscription / 2019 / 2016 farm with an extensive configuration, including trusted authentication, user profiles with personal sites, an OAuth trust (using a certificate), a dedicated IIS site for hosting high-trust add-ins, etc... The latest version of key softwares (including Fiddler, vscode, np++, 7zip, ULS Viewer) is installed. SharePoint machines have additional fine-tuning to make them immediately usable (remote administration tools, custom policies for Edge and Chrome, shortcuts, etc...).", "author": "Yvand" }, "parameters": { @@ -10,35 +15,38 @@ "type": "string", "defaultValue": "[resourceGroup().location]", "metadata": { - "description": "Location for all resources." + "description": "Location for all the resources." } }, "sharePointVersion": { "type": "string", "defaultValue": "Subscription-Latest", "allowedValues": [ - "2016", - "2019", - "Subscription-RTM", - "Subscription-22H2", - "Subscription-23H1", + "Subscription-Latest", + "Subscription-24H2", + "Subscription-24H1", "Subscription-23H2", - "Subscription-Latest" + "Subscription-23H1", + "Subscription-22H2", + "Subscription-RTM", + "2019", + "2016" ], "metadata": { - "description": "Version of SharePoint farm to create." + "description": "Version of the SharePoint farm to create." } }, - "domainFQDN": { + "domainFqdn": { "type": "string", "defaultValue": "contoso.local", "minLength": 5, "metadata": { - "description": "FQDN of the AD forest to create." + "description": "FQDN of the Active Directory forest." } }, - "numberOfAdditionalFrontEnd": { + "frontEndServersCount": { "type": "int", + "defaultValue": 0, "allowedValues": [ 0, 1, @@ -46,60 +54,65 @@ 3, 4 ], - "defaultValue": 0, "metadata": { - "description": "Number of MinRole Front-end to add to the farm. The MinRole type can be changed later as needed." + "description": "Number of servers with MinRole Front-end to add to the farm." } }, - "addAzureBastion": { - "type": "bool", - "defaultValue": false, + "adminUsername": { + "type": "string", + "minLength": 1, "metadata": { - "description": "Specify if Azure Bastion should be provisioned. See https://azure.microsoft.com/en-us/services/azure-bastion for more information." + "description": "Name of the Active Directory and SharePoint administrator. \"admin\" and \"administrator\" are not allowed." } }, - "addPublicIPAddress": { - "type": "string", - "defaultValue": "SharePointVMsOnly", - "allowedValues": [ - "Yes", - "No", - "SharePointVMsOnly" - ], + "adminPassword": { + "type": "securestring", + "minLength": 8, + "metadata": { + "description": "Password for the admin account. Input must meet password complexity requirements as documented in https://learn.microsoft.com/azure/virtual-machines/windows/faq#what-are-the-password-requirements-when-creating-a-vm-" + } + }, + "otherAccountsPassword": { + "type": "securestring", + "minLength": 8, "metadata": { - "description": "Specify if each VM should have a public IP and be reachable from Internet." + "description": "Password for all the other accounts and the SharePoint passphrase. Input must meet password complexity requirements as documented in https://learn.microsoft.com/azure/virtual-machines/windows/faq#what-are-the-password-requirements-when-creating-a-vm-" } }, - "RDPTrafficAllowed": { + "rdpTrafficRule": { "type": "string", "defaultValue": "No", "minLength": 1, "metadata": { - "description": "Specify if RDP traffic is allowed:
- If 'No' (default): Firewall denies all incoming RDP traffic.
- If '*' or 'Internet': Firewall accepts all incoming RDP traffic from Internet.
- If CIDR notation (e.g. 192.168.99.0/24 or 2001:1234::/64) or IP address (e.g. 192.168.99.0 or 2001:1234::): Firewall accepts incoming RDP traffic from the IP addresses specified." + "description": "Specify if a rule in the network security groups should allow the inbound RDP traffic:\r\n- \"No\" (default): No rule is created, RDP traffic is blocked.\r\n- \"*\" or \"Internet\": RDP traffic is allowed from everywhere.\r\n- CIDR notation (e.g. 192.168.99.0/24 or 2001:1234::/64) or an IP address (e.g. 192.168.99.0 or 2001:1234::): RDP traffic is allowed from the IP address / pattern specified.\r\n" } }, - "adminUserName": { + "outboundAccessMethod": { "type": "string", - "minLength": 1, + "defaultValue": "PublicIPAddress", + "allowedValues": [ + "PublicIPAddress", + "AzureFirewallProxy" + ], "metadata": { - "description": "Name of the AD and SharePoint administrator. 'admin' and 'administrator' are not allowed." + "description": "Select how the virtual machines connect to internet.\r\nIMPORTANT: With AzureFirewallProxy, you need to either enable Azure Bastion, or manually add a public IP address to a virtual machine, to be able to connect to it.\r\n" } }, - "adminPassword": { - "type": "securestring", - "minLength": 8, + "enableAzureBastion": { + "type": "bool", + "defaultValue": false, "metadata": { - "description": "Input must meet password complexity requirements as documented in https://learn.microsoft.com/azure/virtual-machines/windows/faq#what-are-the-password-requirements-when-creating-a-vm-" + "description": "Specify if Azure Bastion should be provisioned. See https://azure.microsoft.com/en-us/services/azure-bastion for more information." } }, - "serviceAccountsPassword": { - "type": "securestring", - "minLength": 8, + "enableHybridBenefitServerLicenses": { + "type": "bool", + "defaultValue": false, "metadata": { - "description": "Password for all service accounts and SharePoint passphrase. Input must meet password complexity requirements as documented in https://learn.microsoft.com/azure/virtual-machines/windows/faq#what-are-the-password-requirements-when-creating-a-vm-" + "description": "Enable the Azure Hybrid Benefit on virtual machines, to use your on-premises Windows Server licenses and reduce cost. See https://docs.microsoft.com/en-us/azure/virtual-machines/windows/hybrid-use-benefit-licensing for more information." } }, - "vmsTimeZone": { + "timeZone": { "type": "string", "defaultValue": "Romance Standard Time", "allowedValues": [ @@ -248,100 +261,82 @@ "description": "Time zone of the virtual machines. Type \"[TimeZoneInfo]::GetSystemTimeZones().Id\" in PowerShell to get the list." } }, - "vmsAutoShutdownTime": { + "autoShutdownTime": { "type": "string", "defaultValue": "1900", "minLength": 4, "maxLength": 4, "metadata": { - "description": "The time at which VMs will be automatically shutdown (24h HHmm format). Set value to '9999' to NOT configure the auto shutdown." - } - }, - "enableAutomaticUpdates": { - "type": "bool", - "defaultValue": true, - "metadata": { - "description": "Enable automatic Windows Updates." - } - }, - "enableHybridBenefitServerLicenses": { - "type": "bool", - "defaultValue": false, - "metadata": { - "description": "Enable Azure Hybrid Benefit to use your on-premises Windows Server licenses and reduce cost. See https://docs.microsoft.com/en-us/azure/virtual-machines/windows/hybrid-use-benefit-licensing for more information." - } - }, - "sharePointDataDiskSize": { - "type": "int", - "defaultValue": 0, - "metadata": { - "description": "Size in Gb of the additional data disk attached to SharePoint VMs. Set to 0 to not create it" + "description": "The time (24h HHmm format) at which the virtual machines will automatically be shutdown and deallocated. Set value to \"9999\" to NOT configure the auto shutdown." } }, - "vmDCSize": { + "vmDcSize": { "type": "string", "defaultValue": "Standard_B2s", "metadata": { - "description": "Size of the DC VM" + "description": "Size of the DC virtual machine." } }, - "vmDCStorageAccountType": { + "vmDcStorage": { "type": "string", "defaultValue": "StandardSSD_LRS", "allowedValues": [ "Standard_LRS", "StandardSSD_LRS", + "StandardSSD_ZRS", "Premium_LRS", + "PremiumV2_LRS", "Premium_ZRS", - "StandardSSD_ZRS", "UltraSSD_LRS" ], "metadata": { - "description": "Type of storage for the managed disks. Visit 'https://docs.microsoft.com/en-us/rest/api/compute/disks/list#diskstorageaccounttypes' for more information" + "description": "Type of storage for the managed disk. Visit https://docs.microsoft.com/en-us/rest/api/compute/disks/list#diskstorageaccounttypes for more information." } }, - "vmSQLSize": { + "vmSqlSize": { "type": "string", "defaultValue": "Standard_B2ms", "metadata": { - "description": "Size of the SQL VM" + "description": "Size of the SQL virtual machine." } }, - "vmSQLStorageAccountType": { + "vmSqlStorage": { "type": "string", "defaultValue": "StandardSSD_LRS", "allowedValues": [ "Standard_LRS", "StandardSSD_LRS", + "StandardSSD_ZRS", "Premium_LRS", + "PremiumV2_LRS", "Premium_ZRS", - "StandardSSD_ZRS", "UltraSSD_LRS" ], "metadata": { - "description": "Type of storage for the managed disks. Visit 'https://docs.microsoft.com/en-us/rest/api/compute/disks/list#diskstorageaccounttypes' for more information" + "description": "Type of storage for the managed disk. Visit https://docs.microsoft.com/en-us/rest/api/compute/disks/list#diskstorageaccounttypes for more information." } }, - "vmSPSize": { + "vmSharePointSize": { "type": "string", "defaultValue": "Standard_B4ms", "metadata": { - "description": "Size of the SharePoint VM" + "description": "Size of the SharePoint virtual machine(s)." } }, - "vmSPStorageAccountType": { + "vmSharePointStorage": { "type": "string", "defaultValue": "StandardSSD_LRS", "allowedValues": [ "Standard_LRS", "StandardSSD_LRS", + "StandardSSD_ZRS", "Premium_LRS", + "PremiumV2_LRS", "Premium_ZRS", - "StandardSSD_ZRS", "UltraSSD_LRS" ], "metadata": { - "description": "Type of storage for the managed disks. Visit 'https://docs.microsoft.com/en-us/rest/api/compute/disks/list#diskstorageaccounttypes' for more information" + "description": "Type of storage for the managed disk. Visit https://docs.microsoft.com/en-us/rest/api/compute/disks/list#diskstorageaccounttypes for more information." } }, "_artifactsLocation": { @@ -410,11 +405,27 @@ } ] }, + { + "Label": "24H1", + "Packages": [ + { + "DownloadUrl": "https://download.microsoft.com/download/b/a/b/bab0c7cc-0454-474b-8538-7927f75e6486/uber-subscription-kb5002564-fullfile-x64-glb.exe" + } + ] + }, + { + "Label": "24H2", + "Packages": [ + { + "DownloadUrl": "https://download.microsoft.com/download/6/6/a/66a0057f-79af-4307-8263-103ee75ef5c6/uber-subscription-kb5002640-fullfile-x64-glb.exe" + } + ] + }, { "Label": "Latest", "Packages": [ { - "DownloadUrl": "https://download.microsoft.com/download/8/7/9/8798c828-1d2c-442d-9a98-e6ce59166690/uber-subscription-kb5002560-fullfile-x64-glb.exe" + "DownloadUrl": "https://download.microsoft.com/download/6/6/a/66a0057f-79af-4307-8263-103ee75ef5c6/uber-subscription-kb5002640-fullfile-x64-glb.exe" } ] } @@ -426,31 +437,18 @@ "dcPrivateIPAddress": "10.1.1.4", "subnetSQLPrefix": "10.1.2.0/24", "subnetSPPrefix": "10.1.3.0/24", - "vNetPrivateName": "[concat(variables('resourceGroupNameFormatted'), '-vnet')]", - "subnetDCName": "Subnet-DC", - "subnetSQLName": "Subnet-SQL", - "subnetSPName": "Subnet-SP", - "nsgSubnetDCName": "NSG-Subnet-DC", - "nsgSubnetSQLName": "NSG-Subnet-SQL", - "nsgSubnetSPName": "NSG-Subnet-SP", - "vmDCPublicIPNicAssociation": { - "id": "[resourceId('Microsoft.Network/publicIPAddresses', variables('vmsResourcesNames').vmDCPublicIPName)]" - }, - "vmSQLPublicIPNicAssociation": { - "id": "[resourceId('Microsoft.Network/publicIPAddresses', variables('vmsResourcesNames').vmSQLPublicIPName)]" - }, - "vmSPPublicIPNicAssociation": { - "id": "[resourceId('Microsoft.Network/publicIPAddresses', variables('vmsResourcesNames').vmSPPublicIPName)]" - }, + "subnetDCName": "vnet-subnet-dc", + "subnetSQLName": "vnet-subnet-sql", + "subnetSPName": "vnet-subnet-sp", "nsgRuleAllowIncomingRdp": [ { - "name": "allow-rdp-rule", + "name": "nsg-rule-allow-rdp", "properties": { "description": "Allow RDP", "protocol": "Tcp", "sourcePortRange": "*", "destinationPortRange": "3389", - "sourceAddressPrefix": "[parameters('RDPTrafficAllowed')]", + "sourceAddressPrefix": "[parameters('rdpTrafficRule')]", "destinationAddressPrefix": "*", "access": "Allow", "priority": 110, @@ -460,6 +458,7 @@ ] }, "vmsSettings": { + "enableAutomaticUpdates": true, "vmDCName": "DC", "vmSQLName": "SQL", "vmSPName": "SP", @@ -468,36 +467,26 @@ "vmSQLImage": "MicrosoftSQLServer:sql2022-ws2022:sqldev-gen2:latest", "vmSharePointImage": "[if(variables('sharePointSettings').isSharePointSubscription, variables('sharePointSettings').sharePointImagesList.Subscription, if(equals(parameters('sharePointVersion'), '2019'), variables('sharePointSettings').sharePointImagesList.sp2019, variables('sharePointSettings').sharePointImagesList.sp2016))]" }, - "vmsResourcesNames": { - "vmDCNicName": "[concat('NIC-', variables('vmsSettings').vmDCName, '-0')]", - "vmDCPublicIPName": "[concat('PublicIP-', variables('vmsSettings').vmDCName)]", - "vmSQLNicName": "[concat('NIC-', variables('vmsSettings').vmSQLName, '-0')]", - "vmSQLPublicIPName": "[concat('PublicIP-', variables('vmsSettings').vmSQLName)]", - "vmSPNicName": "[concat('NIC-', variables('vmsSettings').vmSPName, '-0')]", - "vmSPPublicIPName": "[concat('PublicIP-', variables('vmsSettings').vmSPName)]", - "vmFENicName": "[concat('NIC-', variables('vmsSettings').vmFEName, '-0')]", - "vmFEPublicIPName": "[concat('PublicIP-', variables('vmsSettings').vmFEName)]" - }, "dscSettings": { "forceUpdateTag": "1.0", - "vmDCScriptFileUri": "[uri(parameters('_artifactsLocation'), concat('dsc/ConfigureDCVM.zip', parameters('_artifactsLocationSasToken')))]", + "vmDCScriptFileUri": "[uri(parameters('_artifactsLocation'), format('dsc/ConfigureDCVM.zip{0}', parameters('_artifactsLocationSasToken')))]", "vmDCScript": "ConfigureDCVM.ps1", "vmDCFunction": "ConfigureDCVM", - "vmSQLScriptFileUri": "[uri(parameters('_artifactsLocation'), concat('dsc/ConfigureSQLVM.zip', parameters('_artifactsLocationSasToken')))]", + "vmSQLScriptFileUri": "[uri(parameters('_artifactsLocation'), format('dsc/ConfigureSQLVM.zip{0}', parameters('_artifactsLocationSasToken')))]", "vmSQLScript": "ConfigureSQLVM.ps1", "vmSQLFunction": "ConfigureSQLVM", - "vmSPScriptFileUri": "[uri(parameters('_artifactsLocation'), concat(if(variables('sharePointSettings').isSharePointSubscription, 'dsc/ConfigureSPSE.zip', 'dsc/ConfigureSPLegacy.zip'), parameters('_artifactsLocationSasToken')))]", + "vmSPScriptFileUri": "[uri(parameters('_artifactsLocation'), format('{0}{1}', if(variables('sharePointSettings').isSharePointSubscription, 'dsc/ConfigureSPSE.zip', 'dsc/ConfigureSPLegacy.zip'), parameters('_artifactsLocationSasToken')))]", "vmSPScript": "[if(variables('sharePointSettings').isSharePointSubscription, 'ConfigureSPSE.ps1', 'ConfigureSPLegacy.ps1')]", "vmSPFunction": "ConfigureSPVM", - "vmFEScriptFileUri": "[uri(parameters('_artifactsLocation'), concat(if(variables('sharePointSettings').isSharePointSubscription, 'dsc/ConfigureFESE.zip', 'dsc/ConfigureFELegacy.zip'), parameters('_artifactsLocationSasToken')))]", + "vmFEScriptFileUri": "[uri(parameters('_artifactsLocation'), format('{0}{1}', if(variables('sharePointSettings').isSharePointSubscription, 'dsc/ConfigureFESE.zip', 'dsc/ConfigureFELegacy.zip'), parameters('_artifactsLocationSasToken')))]", "vmFEScript": "[if(variables('sharePointSettings').isSharePointSubscription, 'ConfigureFESE.ps1', 'ConfigureFELegacy.ps1')]", "vmFEFunction": "ConfigureFEVM" }, "deploymentSettings": { "sharePointSitesAuthority": "spsites", "sharePointCentralAdminPort": 5000, - "sharePointBitsSelected": "[if(variables('sharePointSettings').isSharePointSubscription, variables('sharePointSettings').sharePointSubscriptionBits, 'fake')]", - "localAdminUserName": "[concat('l-', uniqueString(subscription().subscriptionId))]", + "sharePointBitsSelected": "[if(variables('sharePointSettings').isSharePointSubscription, variables('sharePointSettings').sharePointSubscriptionBits, '')]", + "localAdminUserName": "[format('l-{0}', uniqueString(subscription().subscriptionId))]", "enableAnalysis": false, "applyBrowserPolicies": true, "sqlAlias": "SQLAlias", @@ -511,54 +500,47 @@ "spAppPoolUserName": "spapppool", "spADDirSyncUserName": "spdirsync" }, - "vmSPDataDisk": [ - { - "lun": 0, - "name": "Disk-SP-Data", - "caching": "ReadWrite", - "createOption": "Empty", - "diskSizeGB": "[parameters('sharePointDataDiskSize')]" - } - ] + "firewall_proxy_settings": { + "vNetAzureFirewallPrefix": "10.1.5.0/24", + "azureFirewallIPAddress": "10.1.5.4", + "http_port": 8080, + "https_port": 8443 + }, + "set_proxy_script": "param([string]$proxyIp, [string]$proxyHttpPort, [string]$proxyHttpsPort, [string]$localDomainFqdn) $proxy = \"http={0}:{1};https={0}:{2}\" -f $proxyIp, $proxyHttpPort, $proxyHttpsPort; $bypasslist = \"*.{0};\" -f $localDomainFqdn; netsh winhttp set proxy proxy-server=$proxy bypass-list=$bypasslist; $proxyEnabled = 1; New-ItemProperty -Path \"HKLM:\\SOFTWARE\\Policies\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\" -Name \"ProxySettingsPerUser\" -PropertyType DWORD -Value 0 -Force; $proxyBytes = [system.Text.Encoding]::ASCII.GetBytes($proxy); $bypassBytes = [system.Text.Encoding]::ASCII.GetBytes($bypasslist); $defaultConnectionSettings = [byte[]]@(@(70, 0, 0, 0, 0, 0, 0, 0, $proxyEnabled, 0, 0, 0, $proxyBytes.Length, 0, 0, 0) + $proxyBytes + @($bypassBytes.Length, 0, 0, 0) + $bypassBytes + @(1..36 | % { 0 })); $registryPaths = @(\"HKLM:\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\", \"HKLM:\\Software\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\"); foreach ($registryPath in $registryPaths) { Set-ItemProperty -Path $registryPath -Name ProxyServer -Value $proxy; Set-ItemProperty -Path $registryPath -Name ProxyEnable -Value $proxyEnabled; Set-ItemProperty -Path $registryPath -Name ProxyOverride -Value $bypasslist; Set-ItemProperty -Path \"$registryPath\\Connections\" -Name DefaultConnectionSettings -Value $defaultConnectionSettings; } Bitsadmin /util /setieproxy localsystem MANUAL_PROXY $proxy $bypasslist;" }, "resources": [ { - "name": "[variables('networkSettings').nsgSubnetDCName]", "type": "Microsoft.Network/networkSecurityGroups", - "apiVersion": "2022-07-01", + "apiVersion": "2023-11-01", + "name": "vnet-subnet-dc-nsg", "location": "[parameters('location')]", "properties": { - "securityRules": "[if(equals(toLower(parameters('RDPTrafficAllowed')), 'no'), json('null'), variables('networkSettings').nsgRuleAllowIncomingRdp)]" + "securityRules": "[if(equals(toLower(parameters('rdpTrafficRule')), 'no'), null(), variables('networkSettings').nsgRuleAllowIncomingRdp)]" } }, { - "name": "[variables('networkSettings').nsgSubnetSQLName]", "type": "Microsoft.Network/networkSecurityGroups", - "apiVersion": "2022-07-01", + "apiVersion": "2023-11-01", + "name": "vnet-subnet-sql-nsg", "location": "[parameters('location')]", "properties": { - "securityRules": "[if(equals(toLower(parameters('RDPTrafficAllowed')), 'no'), json('null'), variables('networkSettings').nsgRuleAllowIncomingRdp)]" + "securityRules": "[if(equals(toLower(parameters('rdpTrafficRule')), 'no'), null(), variables('networkSettings').nsgRuleAllowIncomingRdp)]" } }, { - "name": "[variables('networkSettings').nsgSubnetSPName]", "type": "Microsoft.Network/networkSecurityGroups", - "apiVersion": "2022-07-01", + "apiVersion": "2023-11-01", + "name": "vnet-subnet-sp-nsg", "location": "[parameters('location')]", "properties": { - "securityRules": "[if(equals(toLower(parameters('RDPTrafficAllowed')), 'no'), json('null'), variables('networkSettings').nsgRuleAllowIncomingRdp)]" + "securityRules": "[if(equals(toLower(parameters('rdpTrafficRule')), 'no'), null(), variables('networkSettings').nsgRuleAllowIncomingRdp)]" } }, { - "name": "[variables('networkSettings').vNetPrivateName]", "type": "Microsoft.Network/virtualNetworks", - "apiVersion": "2022-07-01", + "apiVersion": "2023-11-01", + "name": "[format('vnet-{0}', uniqueString(resourceGroup().id))]", "location": "[parameters('location')]", - "dependsOn": [ - "[resourceId('Microsoft.Network/networkSecurityGroups', variables('networkSettings').nsgSubnetDCName)]", - "[resourceId('Microsoft.Network/networkSecurityGroups', variables('networkSettings').nsgSubnetSQLName)]", - "[resourceId('Microsoft.Network/networkSecurityGroups', variables('networkSettings').nsgSubnetSPName)]" - ], "properties": { "addressSpace": { "addressPrefixes": [ @@ -569,59 +551,63 @@ { "name": "[variables('networkSettings').subnetDCName]", "properties": { + "defaultOutboundAccess": false, "addressPrefix": "[variables('networkSettings').subnetDCPrefix]", "networkSecurityGroup": { - "id": "[resourceId('Microsoft.Network/networkSecurityGroups', variables('networkSettings').nsgSubnetDCName)]" + "id": "[resourceId('Microsoft.Network/networkSecurityGroups', 'vnet-subnet-dc-nsg')]" } } }, { "name": "[variables('networkSettings').subnetSQLName]", "properties": { + "defaultOutboundAccess": false, "addressPrefix": "[variables('networkSettings').subnetSQLPrefix]", "networkSecurityGroup": { - "id": "[resourceId('Microsoft.Network/networkSecurityGroups', variables('networkSettings').nsgSubnetSQLName)]" + "id": "[resourceId('Microsoft.Network/networkSecurityGroups', 'vnet-subnet-sql-nsg')]" } } }, { "name": "[variables('networkSettings').subnetSPName]", "properties": { + "defaultOutboundAccess": false, "addressPrefix": "[variables('networkSettings').subnetSPPrefix]", "networkSecurityGroup": { - "id": "[resourceId('Microsoft.Network/networkSecurityGroups', variables('networkSettings').nsgSubnetSPName)]" + "id": "[resourceId('Microsoft.Network/networkSecurityGroups', 'vnet-subnet-sp-nsg')]" } } } ] - } + }, + "dependsOn": [ + "[resourceId('Microsoft.Network/networkSecurityGroups', 'vnet-subnet-dc-nsg')]", + "[resourceId('Microsoft.Network/networkSecurityGroups', 'vnet-subnet-sp-nsg')]", + "[resourceId('Microsoft.Network/networkSecurityGroups', 'vnet-subnet-sql-nsg')]" + ] }, { - "condition": "[equals(parameters('addPublicIPAddress'), 'Yes')]", - "name": "[variables('vmsResourcesNames').vmDCPublicIPName]", + "condition": "[equals(parameters('outboundAccessMethod'), 'PublicIPAddress')]", "type": "Microsoft.Network/publicIPAddresses", - "apiVersion": "2022-07-01", + "apiVersion": "2023-11-01", + "name": "vm-dc-pip", "location": "[parameters('location')]", "sku": { - "name": "Basic", + "name": "Standard", "tier": "Regional" }, "properties": { - "publicIPAllocationMethod": "Dynamic", + "publicIPAllocationMethod": "Static", "dnsSettings": { - "domainNameLabel": "[toLower(concat(variables('resourceGroupNameFormatted'), '-', variables('vmsSettings').vmDCName))]" + "domainNameLabel": "[toLower(format('{0}-{1}', variables('resourceGroupNameFormatted'), variables('vmsSettings').vmDCName))]" } } }, { - "name": "[variables('vmsResourcesNames').vmDCNicName]", "type": "Microsoft.Network/networkInterfaces", - "apiVersion": "2022-07-01", + "apiVersion": "2023-11-01", + "name": "vm-dc-nic", "location": "[parameters('location')]", - "dependsOn": [ - "[resourceId('Microsoft.Network/virtualNetworks', variables('networkSettings').vNetPrivateName)]", - "[resourceId('Microsoft.Network/publicIPAddresses', variables('vmsResourcesNames').vmDCPublicIPName)]" - ], "properties": { "ipConfigurations": [ { @@ -630,36 +616,37 @@ "privateIPAllocationMethod": "Static", "privateIPAddress": "[variables('networkSettings').dcPrivateIPAddress]", "subnet": { - "id": "[resourceId('Microsoft.Network/virtualNetworks/subnets', variables('networkSettings').vNetPrivateName, variables('networkSettings').subnetDCName)]" + "id": "[resourceId('Microsoft.Network/virtualNetworks/subnets', format('vnet-{0}', uniqueString(resourceGroup().id)), variables('networkSettings').subnetDCName)]" }, - "publicIPAddress": "[if(equals(parameters('addPublicIPAddress'), 'Yes'), variables('networkSettings').vmDCPublicIPNicAssociation, json('null'))]" + "publicIPAddress": "[if(equals(parameters('outboundAccessMethod'), 'PublicIPAddress'), createObject('id', resourceId('Microsoft.Network/publicIPAddresses', 'vm-dc-pip')), null())]" } } ] - } + }, + "dependsOn": [ + "[resourceId('Microsoft.Network/virtualNetworks', format('vnet-{0}', uniqueString(resourceGroup().id)))]", + "[resourceId('Microsoft.Network/publicIPAddresses', 'vm-dc-pip')]" + ] }, { - "name": "[variables('vmsSettings').vmDCName]", "type": "Microsoft.Compute/virtualMachines", - "apiVersion": "2022-08-01", + "apiVersion": "2024-07-01", + "name": "vm-dc", "location": "[parameters('location')]", - "dependsOn": [ - "[resourceId('Microsoft.Network/networkInterfaces', variables('vmsResourcesNames').vmDCNicName)]" - ], "properties": { "hardwareProfile": { - "vmSize": "[parameters('vmDCSize')]" + "vmSize": "[parameters('vmDcSize')]" }, "osProfile": { "computerName": "[variables('vmsSettings').vmDCName]", - "adminUsername": "[parameters('adminUserName')]", + "adminUsername": "[parameters('adminUsername')]", "adminPassword": "[parameters('adminPassword')]", "windowsConfiguration": { - "timeZone": "[parameters('vmsTimeZone')]", - "enableAutomaticUpdates": "[parameters('enableAutomaticUpdates')]", + "timeZone": "[parameters('timeZone')]", + "enableAutomaticUpdates": "[variables('vmsSettings').enableAutomaticUpdates]", "provisionVMAgent": true, "patchSettings": { - "patchMode": "[if(parameters('enableAutomaticUpdates'), 'AutomaticByOS', 'Manual')]", + "patchMode": "[if(variables('vmsSettings').enableAutomaticUpdates, 'AutomaticByOS', 'Manual')]", "assessmentMode": "ImageDefault" } } @@ -672,101 +659,153 @@ "version": "[split(variables('vmsSettings').vmDCImage, ':')[3]]" }, "osDisk": { - "name": "[concat('Disk-', variables('vmsSettings').vmDCName, '-OS')]", + "name": "vm-dc-disk-os", "caching": "ReadWrite", "osType": "Windows", "createOption": "FromImage", "diskSizeGB": 32, "managedDisk": { - "storageAccountType": "[parameters('vmDCStorageAccountType')]" + "storageAccountType": "[parameters('vmDcStorage')]" } } }, "networkProfile": { "networkInterfaces": [ { - "id": "[resourceId('Microsoft.Network/networkInterfaces', variables('vmsResourcesNames').vmDCNicName)]" + "id": "[resourceId('Microsoft.Network/networkInterfaces', 'vm-dc-nic')]" } ] }, - "licenseType": "[if(parameters('enableHybridBenefitServerLicenses'), 'Windows_Server', json('null'))]" + "licenseType": "[if(parameters('enableHybridBenefitServerLicenses'), 'Windows_Server', null())]" }, - "resources": [ - { - "name": "ConfigureDCVM", - "type": "extensions", - "location": "[parameters('location')]", - "apiVersion": "2022-08-01", - "dependsOn": [ - "[resourceId('Microsoft.Compute/virtualMachines', variables('vmsSettings').vmDCName)]" - ], - "properties": { - "publisher": "Microsoft.Powershell", - "type": "DSC", - "typeHandlerVersion": "2.9", - "autoUpgradeMinorVersion": true, - "forceUpdateTag": "[variables('dscSettings').forceUpdateTag]", - "settings": { - "wmfVersion": "latest", - "configuration": { - "url": "[variables('dscSettings').vmDCScriptFileUri]", - "script": "[variables('dscSettings').vmDCScript]", - "function": "[variables('dscSettings').vmDCFunction]" - }, - "configurationArguments": { - "domainFQDN": "[parameters('domainFQDN')]", - "PrivateIP": "[variables('networkSettings').dcPrivateIPAddress]", - "SPServerName": "[variables('vmsSettings').vmSPName]", - "SharePointSitesAuthority": "[variables('deploymentSettings').sharePointSitesAuthority]", - "SharePointCentralAdminPort": "[variables('deploymentSettings').sharePointCentralAdminPort]", - "ApplyBrowserPolicies": "[variables('deploymentSettings').applyBrowserPolicies]" - }, - "privacy": { - "dataCollection": "enable" - } + "dependsOn": [ + "[resourceId('Microsoft.Network/networkInterfaces', 'vm-dc-nic')]" + ] + }, + { + "condition": "[equals(parameters('outboundAccessMethod'), 'AzureFirewallProxy')]", + "type": "Microsoft.Compute/virtualMachines/runCommands", + "apiVersion": "2024-07-01", + "name": "[format('{0}/{1}', 'vm-dc', 'runcommand-setproxy')]", + "location": "[parameters('location')]", + "properties": { + "source": { + "script": "[variables('set_proxy_script')]" + }, + "parameters": [ + { + "name": "proxyIp", + "value": "[variables('firewall_proxy_settings').azureFirewallIPAddress]" + }, + { + "name": "proxyHttpPort", + "value": "[string(variables('firewall_proxy_settings').http_port)]" + }, + { + "name": "proxyHttpsPort", + "value": "[variables('firewall_proxy_settings').https_port]" + }, + { + "name": "localDomainFqdn", + "value": "[parameters('domainFqdn')]" + } + ], + "timeoutInSeconds": 90, + "treatFailureAsDeploymentFailure": false + }, + "dependsOn": [ + "[resourceId('Microsoft.Compute/virtualMachines', 'vm-dc')]" + ] + }, + { + "type": "Microsoft.Compute/virtualMachines/extensions", + "apiVersion": "2024-07-01", + "name": "[format('{0}/{1}', 'vm-dc', 'apply-dsc')]", + "location": "[parameters('location')]", + "properties": { + "publisher": "Microsoft.Powershell", + "type": "DSC", + "typeHandlerVersion": "2.9", + "autoUpgradeMinorVersion": true, + "forceUpdateTag": "[variables('dscSettings').forceUpdateTag]", + "settings": { + "wmfVersion": "latest", + "configuration": { + "url": "[variables('dscSettings').vmDCScriptFileUri]", + "script": "[variables('dscSettings').vmDCScript]", + "function": "[variables('dscSettings').vmDCFunction]" + }, + "configurationArguments": { + "domainFQDN": "[parameters('domainFqdn')]", + "PrivateIP": "[variables('networkSettings').dcPrivateIPAddress]", + "SPServerName": "[variables('vmsSettings').vmSPName]", + "SharePointSitesAuthority": "[variables('deploymentSettings').sharePointSitesAuthority]", + "SharePointCentralAdminPort": "[variables('deploymentSettings').sharePointCentralAdminPort]", + "ApplyBrowserPolicies": "[variables('deploymentSettings').applyBrowserPolicies]" + }, + "privacy": { + "dataCollection": "enable" + } + }, + "protectedSettings": { + "configurationArguments": { + "AdminCreds": { + "UserName": "[parameters('adminUsername')]", + "Password": "[parameters('adminPassword')]" }, - "protectedSettings": { - "configurationArguments": { - "AdminCreds": { - "UserName": "[parameters('adminUserName')]", - "Password": "[parameters('adminPassword')]" - }, - "AdfsSvcCreds": { - "UserName": "[variables('deploymentSettings').adfsSvcUserName]", - "Password": "[parameters('serviceAccountsPassword')]" - } - } + "AdfsSvcCreds": { + "UserName": "[variables('deploymentSettings').adfsSvcUserName]", + "Password": "[parameters('otherAccountsPassword')]" } } } + }, + "dependsOn": [ + "[resourceId('Microsoft.Compute/virtualMachines', 'vm-dc')]", + "[resourceId('Microsoft.Compute/virtualMachines/runCommands', 'vm-dc', 'runcommand-setproxy')]" + ] + }, + { + "condition": "[not(equals(parameters('autoShutdownTime'), '9999'))]", + "type": "Microsoft.DevTestLab/schedules", + "apiVersion": "2018-09-15", + "name": "[format('shutdown-computevm-{0}', 'vm-dc')]", + "location": "[parameters('location')]", + "properties": { + "targetResourceId": "[resourceId('Microsoft.Compute/virtualMachines', 'vm-dc')]", + "status": "Enabled", + "taskType": "ComputeVmShutdownTask", + "timeZoneId": "[parameters('timeZone')]", + "dailyRecurrence": { + "time": "[parameters('autoShutdownTime')]" + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Compute/virtualMachines', 'vm-dc')]" ] }, { - "condition": "[equals(parameters('addPublicIPAddress'), 'Yes')]", - "name": "[variables('vmsResourcesNames').vmSQLPublicIPName]", + "condition": "[equals(parameters('outboundAccessMethod'), 'PublicIPAddress')]", "type": "Microsoft.Network/publicIPAddresses", - "apiVersion": "2022-07-01", + "apiVersion": "2023-11-01", + "name": "vm-sql-pip", "location": "[parameters('location')]", "sku": { - "name": "Basic", + "name": "Standard", "tier": "Regional" }, "properties": { - "publicIPAllocationMethod": "Dynamic", + "publicIPAllocationMethod": "Static", "dnsSettings": { - "domainNameLabel": "[toLower(concat(variables('resourceGroupNameFormatted'), '-', variables('vmsSettings').vmSQLName))]" + "domainNameLabel": "[toLower(format('{0}-{1}', variables('resourceGroupNameFormatted'), variables('vmsSettings').vmSQLName))]" } } }, { - "name": "[variables('vmsResourcesNames').vmSQLNicName]", "type": "Microsoft.Network/networkInterfaces", - "apiVersion": "2022-07-01", + "apiVersion": "2023-11-01", + "name": "vm-sql-nic", "location": "[parameters('location')]", - "dependsOn": [ - "[resourceId('Microsoft.Network/virtualNetworks', variables('networkSettings').vNetPrivateName)]", - "[resourceId('Microsoft.Network/publicIPAddresses', variables('vmsResourcesNames').vmSQLPublicIPName)]" - ], "properties": { "ipConfigurations": [ { @@ -774,36 +813,37 @@ "properties": { "privateIPAllocationMethod": "Dynamic", "subnet": { - "id": "[resourceId('Microsoft.Network/virtualNetworks/subnets', variables('networkSettings').vNetPrivateName, variables('networkSettings').subnetSQLName)]" + "id": "[resourceId('Microsoft.Network/virtualNetworks/subnets', format('vnet-{0}', uniqueString(resourceGroup().id)), variables('networkSettings').subnetSQLName)]" }, - "publicIPAddress": "[if(equals(parameters('addPublicIPAddress'), 'Yes'), variables('networkSettings').vmSQLPublicIPNicAssociation, json('null'))]" + "publicIPAddress": "[if(equals(parameters('outboundAccessMethod'), 'PublicIPAddress'), createObject('id', resourceId('Microsoft.Network/publicIPAddresses', 'vm-sql-pip')), null())]" } } ] - } + }, + "dependsOn": [ + "[resourceId('Microsoft.Network/virtualNetworks', format('vnet-{0}', uniqueString(resourceGroup().id)))]", + "[resourceId('Microsoft.Network/publicIPAddresses', 'vm-sql-pip')]" + ] }, { - "name": "[variables('vmsSettings').vmSQLName]", "type": "Microsoft.Compute/virtualMachines", - "apiVersion": "2022-08-01", + "apiVersion": "2024-07-01", + "name": "vm-sql", "location": "[parameters('location')]", - "dependsOn": [ - "[resourceId('Microsoft.Network/networkInterfaces', variables('vmsResourcesNames').vmSQLNicName)]" - ], "properties": { "hardwareProfile": { - "vmSize": "[parameters('vmSQLSize')]" + "vmSize": "[parameters('vmSqlSize')]" }, "osProfile": { "computerName": "[variables('vmsSettings').vmSQLName]", "adminUsername": "[variables('deploymentSettings').localAdminUserName]", "adminPassword": "[parameters('adminPassword')]", "windowsConfiguration": { - "timeZone": "[parameters('vmsTimeZone')]", - "enableAutomaticUpdates": "[parameters('enableAutomaticUpdates')]", + "timeZone": "[parameters('timeZone')]", + "enableAutomaticUpdates": "[variables('vmsSettings').enableAutomaticUpdates]", "provisionVMAgent": true, "patchSettings": { - "patchMode": "[if(parameters('enableAutomaticUpdates'), 'AutomaticByOS', 'Manual')]", + "patchMode": "[if(variables('vmsSettings').enableAutomaticUpdates, 'AutomaticByOS', 'Manual')]", "assessmentMode": "ImageDefault" } } @@ -816,53 +856,153 @@ "version": "[split(variables('vmsSettings').vmSQLImage, ':')[3]]" }, "osDisk": { - "name": "[concat('Disk-', variables('vmsSettings').vmSQLName, '-OS')]", + "name": "vm-sql-disk-os", "caching": "ReadWrite", "osType": "Windows", "createOption": "FromImage", "diskSizeGB": 128, "managedDisk": { - "storageAccountType": "[parameters('vmSQLStorageAccountType')]" + "storageAccountType": "[parameters('vmSqlStorage')]" } } }, "networkProfile": { "networkInterfaces": [ { - "id": "[resourceId('Microsoft.Network/networkInterfaces', variables('vmsResourcesNames').vmSQLNicName)]" + "id": "[resourceId('Microsoft.Network/networkInterfaces', 'vm-sql-nic')]" } ] }, - "licenseType": "[if(parameters('enableHybridBenefitServerLicenses'), 'Windows_Server', json('null'))]" + "licenseType": "[if(parameters('enableHybridBenefitServerLicenses'), 'Windows_Server', null())]" + }, + "dependsOn": [ + "[resourceId('Microsoft.Network/networkInterfaces', 'vm-sql-nic')]" + ] + }, + { + "condition": "[equals(parameters('outboundAccessMethod'), 'AzureFirewallProxy')]", + "type": "Microsoft.Compute/virtualMachines/runCommands", + "apiVersion": "2024-07-01", + "name": "[format('{0}/{1}', 'vm-sql', 'runcommand-setproxy')]", + "location": "[parameters('location')]", + "properties": { + "source": { + "script": "[variables('set_proxy_script')]" + }, + "parameters": [ + { + "name": "proxyIp", + "value": "[variables('firewall_proxy_settings').azureFirewallIPAddress]" + }, + { + "name": "proxyHttpPort", + "value": "[string(variables('firewall_proxy_settings').http_port)]" + }, + { + "name": "proxyHttpsPort", + "value": "[variables('firewall_proxy_settings').https_port]" + }, + { + "name": "localDomainFqdn", + "value": "[parameters('domainFqdn')]" + } + ], + "timeoutInSeconds": 90, + "treatFailureAsDeploymentFailure": false + }, + "dependsOn": [ + "[resourceId('Microsoft.Compute/virtualMachines', 'vm-sql')]" + ] + }, + { + "type": "Microsoft.Compute/virtualMachines/extensions", + "apiVersion": "2024-07-01", + "name": "[format('{0}/{1}', 'vm-sql', 'apply-dsc')]", + "location": "[parameters('location')]", + "properties": { + "publisher": "Microsoft.Powershell", + "type": "DSC", + "typeHandlerVersion": "2.9", + "autoUpgradeMinorVersion": true, + "forceUpdateTag": "[variables('dscSettings').forceUpdateTag]", + "settings": { + "wmfVersion": "latest", + "configuration": { + "url": "[variables('dscSettings').vmSQLScriptFileUri]", + "script": "[variables('dscSettings').vmSQLScript]", + "function": "[variables('dscSettings').vmSQLFunction]" + }, + "configurationArguments": { + "DNSServerIP": "[variables('networkSettings').dcPrivateIPAddress]", + "DomainFQDN": "[parameters('domainFqdn')]" + }, + "privacy": { + "dataCollection": "enable" + } + }, + "protectedSettings": { + "configurationArguments": { + "DomainAdminCreds": { + "UserName": "[parameters('adminUsername')]", + "Password": "[parameters('adminPassword')]" + }, + "SqlSvcCreds": { + "UserName": "[variables('deploymentSettings').sqlSvcUserName]", + "Password": "[parameters('otherAccountsPassword')]" + }, + "SPSetupCreds": { + "UserName": "[variables('deploymentSettings').spSetupUserName]", + "Password": "[parameters('otherAccountsPassword')]" + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Compute/virtualMachines', 'vm-sql')]", + "[resourceId('Microsoft.Compute/virtualMachines/runCommands', 'vm-sql', 'runcommand-setproxy')]" + ] + }, + { + "condition": "[not(equals(parameters('autoShutdownTime'), '9999'))]", + "type": "Microsoft.DevTestLab/schedules", + "apiVersion": "2018-09-15", + "name": "[format('shutdown-computevm-{0}', 'vm-sql')]", + "location": "[parameters('location')]", + "properties": { + "targetResourceId": "[resourceId('Microsoft.Compute/virtualMachines', 'vm-sql')]", + "status": "Enabled", + "taskType": "ComputeVmShutdownTask", + "timeZoneId": "[parameters('timeZone')]", + "dailyRecurrence": { + "time": "[parameters('autoShutdownTime')]" + } }, - "resources": [] + "dependsOn": [ + "[resourceId('Microsoft.Compute/virtualMachines', 'vm-sql')]" + ] }, { - "condition": "[or(equals(parameters('addPublicIPAddress'), 'Yes'), equals(parameters('addPublicIPAddress'), 'SharePointVMsOnly'))]", - "name": "[variables('vmsResourcesNames').vmSPPublicIPName]", + "condition": "[equals(parameters('outboundAccessMethod'), 'PublicIPAddress')]", "type": "Microsoft.Network/publicIPAddresses", - "apiVersion": "2022-07-01", + "apiVersion": "2023-11-01", + "name": "vm-sp-pip", "location": "[parameters('location')]", "sku": { - "name": "Basic", + "name": "Standard", "tier": "Regional" }, "properties": { - "publicIPAllocationMethod": "Dynamic", + "publicIPAllocationMethod": "Static", "dnsSettings": { - "domainNameLabel": "[toLower(concat(variables('resourceGroupNameFormatted'), '-', variables('vmsSettings').vmSPName))]" + "domainNameLabel": "[toLower(format('{0}-{1}', variables('resourceGroupNameFormatted'), variables('vmsSettings').vmSPName))]" } } }, { - "name": "[variables('vmsResourcesNames').vmSPNicName]", "type": "Microsoft.Network/networkInterfaces", - "apiVersion": "2022-07-01", + "apiVersion": "2023-11-01", + "name": "vm-sp-nic", "location": "[parameters('location')]", - "dependsOn": [ - "[resourceId('Microsoft.Network/virtualNetworks', variables('networkSettings').vNetPrivateName)]", - "[resourceId('Microsoft.Network/publicIPAddresses', variables('vmsResourcesNames').vmSPPublicIPName)]" - ], "properties": { "ipConfigurations": [ { @@ -870,36 +1010,37 @@ "properties": { "privateIPAllocationMethod": "Dynamic", "subnet": { - "id": "[resourceId('Microsoft.Network/virtualNetworks/subnets', variables('networkSettings').vNetPrivateName, variables('networkSettings').subnetSPName)]" + "id": "[resourceId('Microsoft.Network/virtualNetworks/subnets', format('vnet-{0}', uniqueString(resourceGroup().id)), variables('networkSettings').subnetSPName)]" }, - "publicIPAddress": "[if(or(equals(parameters('addPublicIPAddress'), 'Yes'), equals(parameters('addPublicIPAddress'), 'SharePointVMsOnly')), variables('networkSettings').vmSPPublicIPNicAssociation, json('null'))]" + "publicIPAddress": "[if(equals(parameters('outboundAccessMethod'), 'PublicIPAddress'), createObject('id', resourceId('Microsoft.Network/publicIPAddresses', 'vm-sp-pip')), null())]" } } ] - } + }, + "dependsOn": [ + "[resourceId('Microsoft.Network/virtualNetworks', format('vnet-{0}', uniqueString(resourceGroup().id)))]", + "[resourceId('Microsoft.Network/publicIPAddresses', 'vm-sp-pip')]" + ] }, { - "name": "[variables('vmsSettings').vmSPName]", "type": "Microsoft.Compute/virtualMachines", - "apiVersion": "2022-08-01", + "apiVersion": "2024-07-01", + "name": "vm-sp", "location": "[parameters('location')]", - "dependsOn": [ - "[resourceId('Microsoft.Network/networkInterfaces', variables('vmsResourcesNames').vmSPNicName)]" - ], "properties": { "hardwareProfile": { - "vmSize": "[parameters('vmSPSize')]" + "vmSize": "[parameters('vmSharePointSize')]" }, "osProfile": { "computerName": "[variables('vmsSettings').vmSPName]", "adminUsername": "[variables('deploymentSettings').localAdminUserName]", "adminPassword": "[parameters('adminPassword')]", "windowsConfiguration": { - "timeZone": "[parameters('vmsTimeZone')]", - "enableAutomaticUpdates": "[parameters('enableAutomaticUpdates')]", + "timeZone": "[parameters('timeZone')]", + "enableAutomaticUpdates": "[variables('vmsSettings').enableAutomaticUpdates]", "provisionVMAgent": true, "patchSettings": { - "patchMode": "[if(parameters('enableAutomaticUpdates'), 'AutomaticByOS', 'Manual')]", + "patchMode": "[if(variables('vmsSettings').enableAutomaticUpdates, 'AutomaticByOS', 'Manual')]", "assessmentMode": "ImageDefault" } } @@ -912,99 +1053,84 @@ "version": "[split(variables('vmsSettings').vmSharePointImage, ':')[3]]" }, "osDisk": { - "name": "[concat('Disk-', variables('vmsSettings').vmSPName, '-OS')]", + "name": "vm-sp-disk-os", "caching": "ReadWrite", "osType": "Windows", "createOption": "FromImage", "managedDisk": { - "storageAccountType": "[parameters('vmSPStorageAccountType')]" + "storageAccountType": "[parameters('vmSharePointStorage')]" } - }, - "dataDisks": "[if(equals(parameters('sharePointDataDiskSize'), 0), json('null'), variables('vmSPDataDisk'))]" + } }, "networkProfile": { "networkInterfaces": [ { - "id": "[resourceId('Microsoft.Network/networkInterfaces', variables('vmsResourcesNames').vmSPNicName)]" + "id": "[resourceId('Microsoft.Network/networkInterfaces', 'vm-sp-nic')]" } ] }, - "licenseType": "[if(parameters('enableHybridBenefitServerLicenses'), 'Windows_Server', json('null'))]" + "licenseType": "[if(parameters('enableHybridBenefitServerLicenses'), 'Windows_Server', null())]" }, - "resources": [] + "dependsOn": [ + "[resourceId('Microsoft.Network/networkInterfaces', 'vm-sp-nic')]" + ] }, { - "name": "[concat(variables('vmsSettings').vmSPName,'/IncreaseMaxEnvelopeSizeQuota')]", + "condition": "[equals(parameters('outboundAccessMethod'), 'AzureFirewallProxy')]", "type": "Microsoft.Compute/virtualMachines/runCommands", + "apiVersion": "2024-07-01", + "name": "[format('{0}/{1}', 'vm-sp', 'runcommand-setproxy')]", "location": "[parameters('location')]", - "apiVersion": "2023-03-01", - "dependsOn": [ - "[resourceId('Microsoft.Compute/virtualMachines', variables('vmsSettings').vmSPName)]" - ], "properties": { "source": { - "script": "Set-Item -Path WSMan:\\localhost\\MaxEnvelopeSizeKb -Value 2048" + "script": "[variables('set_proxy_script')]" }, + "parameters": [ + { + "name": "proxyIp", + "value": "[variables('firewall_proxy_settings').azureFirewallIPAddress]" + }, + { + "name": "proxyHttpPort", + "value": "[string(variables('firewall_proxy_settings').http_port)]" + }, + { + "name": "proxyHttpsPort", + "value": "[variables('firewall_proxy_settings').https_port]" + }, + { + "name": "localDomainFqdn", + "value": "[parameters('domainFqdn')]" + } + ], "timeoutInSeconds": 90, "treatFailureAsDeploymentFailure": false - } + }, + "dependsOn": [ + "[resourceId('Microsoft.Compute/virtualMachines', 'vm-sp')]" + ] }, { - "name": "[concat(variables('vmsSettings').vmSQLName,'/ConfigureSQLVM')]", - "type": "Microsoft.Compute/virtualMachines/extensions", + "type": "Microsoft.Compute/virtualMachines/runCommands", + "apiVersion": "2023-03-01", + "name": "[format('{0}/{1}', 'vm-sp', 'runcommand-increase-dsc-quota')]", "location": "[parameters('location')]", - "apiVersion": "2022-08-01", - "dependsOn": [ - "[resourceId('Microsoft.Compute/virtualMachines', variables('vmsSettings').vmSQLName)]" - ], "properties": { - "publisher": "Microsoft.Powershell", - "type": "DSC", - "typeHandlerVersion": "2.9", - "autoUpgradeMinorVersion": true, - "forceUpdateTag": "[variables('dscSettings').forceUpdateTag]", - "settings": { - "wmfVersion": "latest", - "configuration": { - "url": "[variables('dscSettings').vmSQLScriptFileUri]", - "script": "[variables('dscSettings').vmSQLScript]", - "function": "[variables('dscSettings').vmSQLFunction]" - }, - "configurationArguments": { - "DNSServerIP": "[variables('networkSettings').dcPrivateIPAddress]", - "DomainFQDN": "[parameters('domainFQDN')]" - }, - "privacy": { - "dataCollection": "enable" - } + "source": { + "script": "Set-Item -Path WSMan:\\localhost\\MaxEnvelopeSizeKb -Value 2048" }, - "protectedSettings": { - "configurationArguments": { - "DomainAdminCreds": { - "UserName": "[parameters('adminUserName')]", - "Password": "[parameters('adminPassword')]" - }, - "SqlSvcCreds": { - "UserName": "[variables('deploymentSettings').sqlSvcUserName]", - "Password": "[parameters('serviceAccountsPassword')]" - }, - "SPSetupCreds": { - "UserName": "[variables('deploymentSettings').spSetupUserName]", - "Password": "[parameters('serviceAccountsPassword')]" - } - } - } - } + "timeoutInSeconds": 90, + "treatFailureAsDeploymentFailure": false + }, + "dependsOn": [ + "[resourceId('Microsoft.Compute/virtualMachines', 'vm-sp')]" + ] }, { - "name": "[concat(variables('vmsSettings').vmSPName,'/ConfigureSPVM')]", "type": "Microsoft.Compute/virtualMachines/extensions", + "apiVersion": "2024-07-01", + "name": "[format('{0}/{1}', 'vm-sp', 'apply-dsc')]", "location": "[parameters('location')]", - "apiVersion": "2022-08-01", - "dependsOn": [ - "[resourceId('Microsoft.Compute/virtualMachines', variables('vmsSettings').vmSPName)]", - "[resourceId('Microsoft.Compute/virtualMachines/runCommands', variables('vmsSettings').vmSPName, 'IncreaseMaxEnvelopeSizeQuota')]" - ], "properties": { "publisher": "Microsoft.Powershell", "type": "DSC", @@ -1020,7 +1146,7 @@ }, "configurationArguments": { "DNSServerIP": "[variables('networkSettings').dcPrivateIPAddress]", - "DomainFQDN": "[parameters('domainFQDN')]", + "DomainFQDN": "[parameters('domainFqdn')]", "DCServerName": "[variables('vmsSettings').vmDCName]", "SQLServerName": "[variables('vmsSettings').vmSQLName]", "SQLAlias": "[variables('deploymentSettings').sqlAlias]", @@ -1037,80 +1163,100 @@ "protectedSettings": { "configurationArguments": { "DomainAdminCreds": { - "UserName": "[parameters('adminUserName')]", + "UserName": "[parameters('adminUsername')]", "Password": "[parameters('adminPassword')]" }, "SPSetupCreds": { "UserName": "[variables('deploymentSettings').spSetupUserName]", - "Password": "[parameters('serviceAccountsPassword')]" + "Password": "[parameters('otherAccountsPassword')]" }, "SPFarmCreds": { "UserName": "[variables('deploymentSettings').spFarmUserName]", - "Password": "[parameters('serviceAccountsPassword')]" + "Password": "[parameters('otherAccountsPassword')]" }, "SPSvcCreds": { "UserName": "[variables('deploymentSettings').spSvcUserName]", - "Password": "[parameters('serviceAccountsPassword')]" + "Password": "[parameters('otherAccountsPassword')]" }, "SPAppPoolCreds": { "UserName": "[variables('deploymentSettings').spAppPoolUserName]", - "Password": "[parameters('serviceAccountsPassword')]" + "Password": "[parameters('otherAccountsPassword')]" }, "SPADDirSyncCreds": { "UserName": "[variables('deploymentSettings').spADDirSyncUserName]", - "Password": "[parameters('serviceAccountsPassword')]" + "Password": "[parameters('otherAccountsPassword')]" }, "SPPassphraseCreds": { "UserName": "Passphrase", - "Password": "[parameters('serviceAccountsPassword')]" + "Password": "[parameters('otherAccountsPassword')]" }, "SPSuperUserCreds": { "UserName": "[variables('deploymentSettings').spSuperUserName]", - "Password": "[parameters('serviceAccountsPassword')]" + "Password": "[parameters('otherAccountsPassword')]" }, "SPSuperReaderCreds": { "UserName": "[variables('deploymentSettings').spSuperReaderName]", - "Password": "[parameters('serviceAccountsPassword')]" + "Password": "[parameters('otherAccountsPassword')]" } } } - } + }, + "dependsOn": [ + "[resourceId('Microsoft.Compute/virtualMachines', 'vm-sp')]", + "[resourceId('Microsoft.Compute/virtualMachines/runCommands', 'vm-sp', 'runcommand-increase-dsc-quota')]", + "[resourceId('Microsoft.Compute/virtualMachines/runCommands', 'vm-sp', 'runcommand-setproxy')]" + ] }, { - "condition": "[and(greaterOrEquals(parameters('numberOfAdditionalFrontEnd'), 1), or(equals(parameters('addPublicIPAddress'), 'Yes'), equals(parameters('addPublicIPAddress'), 'SharePointVMsOnly')))]", - "name": "[concat(variables('vmsResourcesNames').vmFEPublicIPName, '-', copyIndex())]", - "type": "Microsoft.Network/publicIPAddresses", - "apiVersion": "2022-07-01", + "condition": "[not(equals(parameters('autoShutdownTime'), '9999'))]", + "type": "Microsoft.DevTestLab/schedules", + "apiVersion": "2018-09-15", + "name": "[format('shutdown-computevm-{0}', 'vm-sp')]", "location": "[parameters('location')]", + "properties": { + "targetResourceId": "[resourceId('Microsoft.Compute/virtualMachines', 'vm-sp')]", + "status": "Enabled", + "taskType": "ComputeVmShutdownTask", + "timeZoneId": "[parameters('timeZone')]", + "dailyRecurrence": { + "time": "[parameters('autoShutdownTime')]" + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Compute/virtualMachines', 'vm-sp')]" + ] + }, + { "copy": { - "name": "frontendPublicIPAddresses", - "count": "[parameters('numberOfAdditionalFrontEnd')]" + "name": "vm_fe_pip", + "count": "[length(range(0, parameters('frontEndServersCount')))]" }, + "condition": "[and(greaterOrEquals(parameters('frontEndServersCount'), 1), equals(parameters('outboundAccessMethod'), 'PublicIPAddress'))]", + "type": "Microsoft.Network/publicIPAddresses", + "apiVersion": "2023-11-01", + "name": "[format('vm-fe{0}-pip', range(0, parameters('frontEndServersCount'))[copyIndex()])]", + "location": "[parameters('location')]", "sku": { "name": "Basic", "tier": "Regional" }, "properties": { - "publicIPAllocationMethod": "Dynamic", + "publicIPAllocationMethod": "Static", "dnsSettings": { - "domainNameLabel": "[concat(toLower(concat(variables('resourceGroupNameFormatted'), '-', variables('vmsSettings').vmFEName)), '-', copyIndex())]" + "domainNameLabel": "[format('{0}-{1}', toLower(format('{0}-{1}', variables('resourceGroupNameFormatted'), variables('vmsSettings').vmFEName)), range(0, parameters('frontEndServersCount'))[copyIndex()])]" } } }, { - "condition": "[greaterOrEquals(parameters('numberOfAdditionalFrontEnd'), 1)]", - "name": "[concat(variables('vmsResourcesNames').vmFENicName, '-', copyIndex())]", - "type": "Microsoft.Network/networkInterfaces", - "apiVersion": "2022-07-01", - "location": "[parameters('location')]", - "dependsOn": [ - "[resourceId('Microsoft.Network/virtualNetworks', variables('networkSettings').vNetPrivateName)]", - "frontendPublicIPAddresses" - ], "copy": { - "name": "frontendNetworkInterfaces", - "count": "[parameters('numberOfAdditionalFrontEnd')]" + "name": "vm_fe_nic", + "count": "[length(range(0, parameters('frontEndServersCount')))]" }, + "condition": "[greaterOrEquals(parameters('frontEndServersCount'), 1)]", + "type": "Microsoft.Network/networkInterfaces", + "apiVersion": "2023-11-01", + "name": "[format('vm-fe{0}-nic', range(0, parameters('frontEndServersCount'))[copyIndex()])]", + "location": "[parameters('location')]", "properties": { "ipConfigurations": [ { @@ -1118,41 +1264,43 @@ "properties": { "privateIPAllocationMethod": "Dynamic", "subnet": { - "id": "[resourceId('Microsoft.Network/virtualNetworks/subnets', variables('networkSettings').vNetPrivateName, variables('networkSettings').subnetSPName)]" + "id": "[resourceId('Microsoft.Network/virtualNetworks/subnets', format('vnet-{0}', uniqueString(resourceGroup().id)), variables('networkSettings').subnetSPName)]" }, - "publicIPAddress": "[if(or(equals(parameters('addPublicIPAddress'), 'Yes'), equals(parameters('addPublicIPAddress'), 'SharePointVMsOnly')), json(concat('{\"id\": \"', resourceId('Microsoft.Network/publicIPAddresses', concat(variables('vmsResourcesNames').vmFEPublicIPName, '-', copyIndex())), '\" }')), json('null'))]" + "publicIPAddress": "[if(equals(parameters('outboundAccessMethod'), 'PublicIPAddress'), json(format('{{\"id\": \"{0}\"}}', resourceId('Microsoft.Network/publicIPAddresses', format('vm-fe{0}-pip', range(0, parameters('frontEndServersCount'))[range(0, parameters('frontEndServersCount'))[copyIndex()]])))), null())]" } } ] - } + }, + "dependsOn": [ + "[resourceId('Microsoft.Network/virtualNetworks', format('vnet-{0}', uniqueString(resourceGroup().id)))]", + "[resourceId('Microsoft.Network/publicIPAddresses', format('vm-fe{0}-pip', range(0, parameters('frontEndServersCount'))[range(0, parameters('frontEndServersCount'))[copyIndex()]]))]", + "[resourceId('Microsoft.Network/publicIPAddresses', format('vm-fe{0}-pip', range(0, parameters('frontEndServersCount'))[range(0, parameters('frontEndServersCount'))[copyIndex()]]))]" + ] }, { - "condition": "[greaterOrEquals(parameters('numberOfAdditionalFrontEnd'), 1)]", - "name": "[concat(variables('vmsSettings').vmFEName, '-', copyIndex())]", - "type": "Microsoft.Compute/virtualMachines", - "apiVersion": "2022-08-01", - "location": "[parameters('location')]", - "dependsOn": [ - "frontendNetworkInterfaces" - ], "copy": { - "name": "frontendVirtualMachines", - "count": "[parameters('numberOfAdditionalFrontEnd')]" + "name": "vm_fe_def", + "count": "[length(range(0, parameters('frontEndServersCount')))]" }, + "condition": "[greaterOrEquals(parameters('frontEndServersCount'), 1)]", + "type": "Microsoft.Compute/virtualMachines", + "apiVersion": "2024-07-01", + "name": "[format('vm-fe{0}', range(0, parameters('frontEndServersCount'))[copyIndex()])]", + "location": "[parameters('location')]", "properties": { "hardwareProfile": { - "vmSize": "[parameters('vmSPSize')]" + "vmSize": "[parameters('vmSharePointSize')]" }, "osProfile": { - "computerName": "[concat(variables('vmsSettings').vmFEName, '-', copyIndex())]", + "computerName": "[format('{0}-{1}', variables('vmsSettings').vmFEName, range(0, parameters('frontEndServersCount'))[copyIndex()])]", "adminUsername": "[variables('deploymentSettings').localAdminUserName]", "adminPassword": "[parameters('adminPassword')]", "windowsConfiguration": { - "timeZone": "[parameters('vmsTimeZone')]", - "enableAutomaticUpdates": "[parameters('enableAutomaticUpdates')]", + "timeZone": "[parameters('timeZone')]", + "enableAutomaticUpdates": "[variables('vmsSettings').enableAutomaticUpdates]", "provisionVMAgent": true, "patchSettings": { - "patchMode": "[if(parameters('enableAutomaticUpdates'), 'AutomaticByOS', 'Manual')]", + "patchMode": "[if(variables('vmsSettings').enableAutomaticUpdates, 'AutomaticByOS', 'Manual')]", "assessmentMode": "ImageDefault" } } @@ -1165,39 +1313,78 @@ "version": "[split(variables('vmsSettings').vmSharePointImage, ':')[3]]" }, "osDisk": { - "name": "[concat('Disk-', variables('vmsSettings').vmFEName, '-', copyIndex(), '-OS')]", + "name": "[format('vm-fe{0}-disk-os', range(0, parameters('frontEndServersCount'))[copyIndex()])]", "caching": "ReadWrite", "osType": "Windows", "createOption": "FromImage", "managedDisk": { - "storageAccountType": "[parameters('vmSPStorageAccountType')]" + "storageAccountType": "[parameters('vmSharePointStorage')]" } } }, "networkProfile": { "networkInterfaces": [ { - "id": "[resourceId('Microsoft.Network/networkInterfaces', concat(variables('vmsResourcesNames').vmFENicName, '-', copyIndex()))]" + "id": "[resourceId('Microsoft.Network/networkInterfaces', format('vm-fe{0}-nic', range(0, parameters('frontEndServersCount'))[range(0, parameters('frontEndServersCount'))[copyIndex()]]))]" } ] }, - "licenseType": "[if(parameters('enableHybridBenefitServerLicenses'), 'Windows_Server', json('null'))]" + "licenseType": "[if(parameters('enableHybridBenefitServerLicenses'), 'Windows_Server', null())]" }, - "resources": [] + "dependsOn": [ + "[resourceId('Microsoft.Network/networkInterfaces', format('vm-fe{0}-nic', range(0, parameters('frontEndServersCount'))[range(0, parameters('frontEndServersCount'))[copyIndex()]]))]", + "[resourceId('Microsoft.Network/networkInterfaces', format('vm-fe{0}-nic', range(0, parameters('frontEndServersCount'))[range(0, parameters('frontEndServersCount'))[copyIndex()]]))]" + ] }, { - "condition": "[greaterOrEquals(parameters('numberOfAdditionalFrontEnd'), 1)]", - "name": "[concat(variables('vmsSettings').vmFEName, '-', copyIndex(),'/ConfigureFEVM')]", - "type": "Microsoft.Compute/virtualMachines/extensions", + "copy": { + "name": "vm_fe_runcommand_setproxy", + "count": "[length(range(0, parameters('frontEndServersCount')))]" + }, + "condition": "[and(greaterOrEquals(parameters('frontEndServersCount'), 1), equals(parameters('outboundAccessMethod'), 'AzureFirewallProxy'))]", + "type": "Microsoft.Compute/virtualMachines/runCommands", + "apiVersion": "2024-07-01", + "name": "[format('{0}/{1}', format('vm-fe{0}', range(0, parameters('frontEndServersCount'))[range(0, parameters('frontEndServersCount'))[copyIndex()]]), 'runcommand-setproxy')]", "location": "[parameters('location')]", - "apiVersion": "2022-08-01", + "properties": { + "source": { + "script": "[variables('set_proxy_script')]" + }, + "parameters": [ + { + "name": "proxyIp", + "value": "[variables('firewall_proxy_settings').azureFirewallIPAddress]" + }, + { + "name": "proxyHttpPort", + "value": "[string(variables('firewall_proxy_settings').http_port)]" + }, + { + "name": "proxyHttpsPort", + "value": "[variables('firewall_proxy_settings').https_port]" + }, + { + "name": "localDomainFqdn", + "value": "[parameters('domainFqdn')]" + } + ], + "timeoutInSeconds": 90, + "treatFailureAsDeploymentFailure": false + }, "dependsOn": [ - "frontendVirtualMachines" - ], + "[resourceId('Microsoft.Compute/virtualMachines', format('vm-fe{0}', range(0, parameters('frontEndServersCount'))[range(0, parameters('frontEndServersCount'))[copyIndex()]]))]" + ] + }, + { "copy": { - "name": "frontendVirtualMachineExtensions", - "count": "[parameters('numberOfAdditionalFrontEnd')]" + "name": "vm_fe_ext_applydsc", + "count": "[length(range(0, parameters('frontEndServersCount')))]" }, + "condition": "[greaterOrEquals(parameters('frontEndServersCount'), 1)]", + "type": "Microsoft.Compute/virtualMachines/extensions", + "apiVersion": "2024-07-01", + "name": "[format('{0}/{1}', format('vm-fe{0}', range(0, parameters('frontEndServersCount'))[range(0, parameters('frontEndServersCount'))[copyIndex()]]), 'apply-dsc')]", + "location": "[parameters('location')]", "properties": { "publisher": "Microsoft.Powershell", "type": "DSC", @@ -1213,7 +1400,7 @@ }, "configurationArguments": { "DNSServerIP": "[variables('networkSettings').dcPrivateIPAddress]", - "DomainFQDN": "[parameters('domainFQDN')]", + "DomainFQDN": "[parameters('domainFqdn')]", "DCServerName": "[variables('vmsSettings').vmDCName]", "SQLServerName": "[variables('vmsSettings').vmSQLName]", "SQLAlias": "[variables('deploymentSettings').sqlAlias]", @@ -1229,126 +1416,58 @@ "protectedSettings": { "configurationArguments": { "DomainAdminCreds": { - "UserName": "[parameters('adminUserName')]", + "UserName": "[parameters('adminUsername')]", "Password": "[parameters('adminPassword')]" }, "SPSetupCreds": { "UserName": "[variables('deploymentSettings').spSetupUserName]", - "Password": "[parameters('serviceAccountsPassword')]" + "Password": "[parameters('otherAccountsPassword')]" }, "SPFarmCreds": { "UserName": "[variables('deploymentSettings').spFarmUserName]", - "Password": "[parameters('serviceAccountsPassword')]" + "Password": "[parameters('otherAccountsPassword')]" }, "SPPassphraseCreds": { "UserName": "Passphrase", - "Password": "[parameters('serviceAccountsPassword')]" + "Password": "[parameters('otherAccountsPassword')]" } } } - } - }, - { - "condition": "[not(equals(parameters('vmsAutoShutdownTime'), '9999'))]", - "type": "Microsoft.DevTestLab/schedules", - "name": "[concat('shutdown-computevm-', variables('vmsSettings').vmDCName)]", - "apiVersion": "2018-09-15", - "location": "[parameters('location')]", - "dependsOn": [ - "[resourceId('Microsoft.Compute/virtualMachines', variables('vmsSettings').vmDCName)]" - ], - "properties": { - "status": "Enabled", - "taskType": "ComputeVmShutdownTask", - "dailyRecurrence": { - "time": "[parameters('vmsAutoShutdownTime')]" - }, - "timeZoneId": "[parameters('vmsTimeZone')]", - "notificationSettings": { - "status": "Disabled", - "timeInMinutes": 30 - }, - "targetResourceId": "[resourceId('Microsoft.Compute/virtualMachines', variables('vmsSettings').vmDCName)]" - } - }, - { - "condition": "[not(equals(parameters('vmsAutoShutdownTime'), '9999'))]", - "type": "Microsoft.DevTestLab/schedules", - "name": "[concat('shutdown-computevm-', variables('vmsSettings').vmSQLName)]", - "apiVersion": "2018-09-15", - "location": "[parameters('location')]", + }, "dependsOn": [ - "[resourceId('Microsoft.Compute/virtualMachines', variables('vmsSettings').vmSQLName)]" - ], - "properties": { - "status": "Enabled", - "taskType": "ComputeVmShutdownTask", - "dailyRecurrence": { - "time": "[parameters('vmsAutoShutdownTime')]" - }, - "timeZoneId": "[parameters('vmsTimeZone')]", - "notificationSettings": { - "status": "Disabled", - "timeInMinutes": 30 - }, - "targetResourceId": "[resourceId('Microsoft.Compute/virtualMachines', variables('vmsSettings').vmSQLName)]" - } + "[resourceId('Microsoft.Compute/virtualMachines', format('vm-fe{0}', range(0, parameters('frontEndServersCount'))[range(0, parameters('frontEndServersCount'))[copyIndex()]]))]", + "[resourceId('Microsoft.Compute/virtualMachines/runCommands', format('vm-fe{0}', range(0, parameters('frontEndServersCount'))[range(0, parameters('frontEndServersCount'))[range(0, parameters('frontEndServersCount'))[copyIndex()]]]), 'runcommand-setproxy')]" + ] }, { - "condition": "[not(equals(parameters('vmsAutoShutdownTime'), '9999'))]", + "copy": { + "name": "vm_fe_autoshutdown", + "count": "[length(range(0, parameters('frontEndServersCount')))]" + }, + "condition": "[and(greaterOrEquals(parameters('frontEndServersCount'), 1), not(equals(parameters('autoShutdownTime'), '9999')))]", "type": "Microsoft.DevTestLab/schedules", - "name": "[concat('shutdown-computevm-', variables('vmsSettings').vmSPName)]", "apiVersion": "2018-09-15", + "name": "[format('shutdown-computevm-{0}', format('vm-fe{0}', range(0, parameters('frontEndServersCount'))[range(0, parameters('frontEndServersCount'))[copyIndex()]]))]", "location": "[parameters('location')]", - "dependsOn": [ - "[resourceId('Microsoft.Compute/virtualMachines', variables('vmsSettings').vmSPName)]" - ], "properties": { + "targetResourceId": "[resourceId('Microsoft.Compute/virtualMachines', format('vm-fe{0}', range(0, parameters('frontEndServersCount'))[range(0, parameters('frontEndServersCount'))[copyIndex()]]))]", "status": "Enabled", "taskType": "ComputeVmShutdownTask", + "timeZoneId": "[parameters('timeZone')]", "dailyRecurrence": { - "time": "[parameters('vmsAutoShutdownTime')]" - }, - "timeZoneId": "[parameters('vmsTimeZone')]", - "notificationSettings": { - "status": "Disabled", - "timeInMinutes": 30 - }, - "targetResourceId": "[resourceId('Microsoft.Compute/virtualMachines', variables('vmsSettings').vmSPName)]" - } - }, - { - "condition": "[and(greaterOrEquals(parameters('numberOfAdditionalFrontEnd'), 1), not(equals(parameters('vmsAutoShutdownTime'), '9999')))]", - "type": "Microsoft.DevTestLab/schedules", - "name": "[concat(concat('shutdown-computevm-', variables('vmsSettings').vmFEName), '-', copyIndex())]", - "apiVersion": "2018-09-15", - "location": "[parameters('location')]", - "dependsOn": [ - "frontendVirtualMachines" - ], - "copy": { - "name": "frontendAutoShutdowns", - "count": "[parameters('numberOfAdditionalFrontEnd')]" + "time": "[parameters('autoShutdownTime')]" + } }, - "properties": { - "status": "Enabled", - "taskType": "ComputeVmShutdownTask", - "dailyRecurrence": { - "time": "[parameters('vmsAutoShutdownTime')]" - }, - "timeZoneId": "[parameters('vmsTimeZone')]", - "notificationSettings": { - "status": "Disabled", - "timeInMinutes": 30 - }, - "targetResourceId": "[resourceId('Microsoft.Compute/virtualMachines', concat(variables('vmsSettings').vmFEName, '-', copyIndex()))]" - } + "dependsOn": [ + "[resourceId('Microsoft.Compute/virtualMachines', format('vm-fe{0}', range(0, parameters('frontEndServersCount'))[range(0, parameters('frontEndServersCount'))[copyIndex()]]))]", + "[resourceId('Microsoft.Compute/virtualMachines', format('vm-fe{0}', range(0, parameters('frontEndServersCount'))[range(0, parameters('frontEndServersCount'))[copyIndex()]]))]" + ] }, { - "condition": "[equals(parameters('addAzureBastion'), true())]", - "name": "NSG-Subnet-AzureBastion", + "condition": "[equals(parameters('enableAzureBastion'), true())]", "type": "Microsoft.Network/networkSecurityGroups", - "apiVersion": "2022-07-01", + "apiVersion": "2023-11-01", + "name": "bastion-subnet-nsg", "location": "[parameters('location')]", "properties": { "securityRules": [ @@ -1498,27 +1617,26 @@ } }, { - "condition": "[equals(parameters('addAzureBastion'), true())]", - "name": "[concat(variables('networkSettings').vNetPrivateName, '/', 'AzureBastionSubnet')]", + "condition": "[equals(parameters('enableAzureBastion'), true())]", "type": "Microsoft.Network/virtualNetworks/subnets", - "apiVersion": "2022-07-01", - "location": "[parameters('location')]", - "dependsOn": [ - "[resourceId('Microsoft.Network/virtualNetworks', variables('networkSettings').vNetPrivateName)]", - "[resourceId('Microsoft.Network/networkSecurityGroups', 'NSG-Subnet-AzureBastion')]" - ], + "apiVersion": "2023-11-01", + "name": "[format('{0}/{1}', format('vnet-{0}', uniqueString(resourceGroup().id)), 'AzureBastionSubnet')]", "properties": { "addressPrefix": "10.1.4.0/24", "networkSecurityGroup": { - "id": "[resourceId('Microsoft.Network/networkSecurityGroups', 'NSG-Subnet-AzureBastion')]" + "id": "[resourceId('Microsoft.Network/networkSecurityGroups', 'bastion-subnet-nsg')]" } - } + }, + "dependsOn": [ + "[resourceId('Microsoft.Network/networkSecurityGroups', 'bastion-subnet-nsg')]", + "[resourceId('Microsoft.Network/virtualNetworks', format('vnet-{0}', uniqueString(resourceGroup().id)))]" + ] }, { - "condition": "[equals(parameters('addAzureBastion'), true())]", - "name": "PublicIP-Bastion", + "condition": "[equals(parameters('enableAzureBastion'), true())]", "type": "Microsoft.Network/publicIPAddresses", - "apiVersion": "2022-07-01", + "apiVersion": "2023-11-01", + "name": "bastion-pip", "location": "[parameters('location')]", "sku": { "name": "Standard", @@ -1527,20 +1645,16 @@ "properties": { "publicIPAllocationMethod": "Static", "dnsSettings": { - "domainNameLabel": "[toLower(replace(concat(variables('resourceGroupNameFormatted'), '-', 'Bastion'), '_', '-'))]" + "domainNameLabel": "[toLower(replace(format('{0}-Bastion', variables('resourceGroupNameFormatted')), '_', '-'))]" } } }, { - "condition": "[equals(parameters('addAzureBastion'), true())]", - "name": "Bastion", + "condition": "[equals(parameters('enableAzureBastion'), true())]", "type": "Microsoft.Network/bastionHosts", + "apiVersion": "2023-11-01", + "name": "bastion", "location": "[parameters('location')]", - "apiVersion": "2022-07-01", - "dependsOn": [ - "[resourceId('Microsoft.Network/publicIPAddresses', 'PublicIP-Bastion')]", - "[resourceId('Microsoft.Network/virtualNetworks/subnets', variables('networkSettings').vNetPrivateName, 'AzureBastionSubnet')]" - ], "properties": { "ipConfigurations": [ { @@ -1548,52 +1662,179 @@ "properties": { "privateIPAllocationMethod": "Dynamic", "publicIPAddress": { - "id": "[resourceId('Microsoft.Network/publicIPAddresses', 'PublicIP-Bastion')]" + "id": "[resourceId('Microsoft.Network/publicIPAddresses', 'bastion-pip')]" }, "subnet": { - "id": "[resourceId('Microsoft.Network/virtualNetworks/subnets', variables('networkSettings').vNetPrivateName, 'AzureBastionSubnet')]" + "id": "[resourceId('Microsoft.Network/virtualNetworks/subnets', format('vnet-{0}', uniqueString(resourceGroup().id)), 'AzureBastionSubnet')]" } } } ] + }, + "dependsOn": [ + "[resourceId('Microsoft.Network/publicIPAddresses', 'bastion-pip')]", + "[resourceId('Microsoft.Network/virtualNetworks/subnets', format('vnet-{0}', uniqueString(resourceGroup().id)), 'AzureBastionSubnet')]" + ] + }, + { + "condition": "[equals(parameters('outboundAccessMethod'), 'AzureFirewallProxy')]", + "type": "Microsoft.Network/virtualNetworks/subnets", + "apiVersion": "2023-11-01", + "name": "[format('{0}/{1}', format('vnet-{0}', uniqueString(resourceGroup().id)), 'AzureFirewallSubnet')]", + "properties": { + "addressPrefix": "[variables('firewall_proxy_settings').vNetAzureFirewallPrefix]", + "defaultOutboundAccess": false + }, + "dependsOn": [ + "[resourceId('Microsoft.Network/virtualNetworks', format('vnet-{0}', uniqueString(resourceGroup().id)))]" + ] + }, + { + "condition": "[equals(parameters('outboundAccessMethod'), 'AzureFirewallProxy')]", + "type": "Microsoft.Network/publicIPAddresses", + "apiVersion": "2023-11-01", + "name": "firewall-pip", + "location": "[parameters('location')]", + "sku": { + "name": "Standard", + "tier": "Regional" + }, + "properties": { + "publicIPAllocationMethod": "Static", + "dnsSettings": { + "domainNameLabel": "[toLower(format('{0}-Firewall', variables('resourceGroupNameFormatted')))]" + } } + }, + { + "condition": "[equals(parameters('outboundAccessMethod'), 'AzureFirewallProxy')]", + "type": "Microsoft.Network/firewallPolicies", + "apiVersion": "2023-11-01", + "name": "firewall-policy-proxy", + "location": "[parameters('location')]", + "properties": { + "sku": { + "tier": "Standard" + }, + "threatIntelMode": "Alert", + "explicitProxy": { + "enableExplicitProxy": true, + "httpPort": "[variables('firewall_proxy_settings').http_port]", + "httpsPort": "[variables('firewall_proxy_settings').https_port]", + "enablePacFile": false + } + } + }, + { + "condition": "[equals(parameters('outboundAccessMethod'), 'AzureFirewallProxy')]", + "type": "Microsoft.Network/firewallPolicies/ruleCollectionGroups", + "apiVersion": "2023-11-01", + "name": "[format('{0}/{1}', 'firewall-policy-proxy', 'rules')]", + "properties": { + "priority": 100, + "ruleCollections": [ + { + "name": "proxy-allow-all-outbound", + "ruleCollectionType": "FirewallPolicyFilterRuleCollection", + "action": { + "type": "Allow" + }, + "priority": 100, + "rules": [ + { + "ruleType": "ApplicationRule", + "sourceAddresses": [ + "*" + ], + "targetFqdns": [ + "*" + ], + "protocols": [ + { + "port": 443, + "protocolType": "Https" + }, + { + "port": 80, + "protocolType": "Http" + } + ] + } + ] + } + ] + }, + "dependsOn": [ + "[resourceId('Microsoft.Network/firewallPolicies', 'firewall-policy-proxy')]" + ] + }, + { + "condition": "[equals(parameters('outboundAccessMethod'), 'AzureFirewallProxy')]", + "type": "Microsoft.Network/azureFirewalls", + "apiVersion": "2023-11-01", + "name": "firewall", + "location": "[parameters('location')]", + "properties": { + "ipConfigurations": [ + { + "name": "IpConf", + "properties": { + "subnet": { + "id": "[resourceId('Microsoft.Network/virtualNetworks/subnets', format('vnet-{0}', uniqueString(resourceGroup().id)), 'AzureFirewallSubnet')]" + }, + "publicIPAddress": { + "id": "[resourceId('Microsoft.Network/publicIPAddresses', 'firewall-pip')]" + } + } + } + ], + "firewallPolicy": { + "id": "[resourceId('Microsoft.Network/firewallPolicies', 'firewall-policy-proxy')]" + }, + "sku": { + "name": "AZFW_VNet", + "tier": "Standard" + }, + "threatIntelMode": "Alert" + }, + "dependsOn": [ + "[resourceId('Microsoft.Network/publicIPAddresses', 'firewall-pip')]", + "[resourceId('Microsoft.Network/firewallPolicies', 'firewall-policy-proxy')]", + "[resourceId('Microsoft.Network/virtualNetworks/subnets', format('vnet-{0}', uniqueString(resourceGroup().id)), 'AzureFirewallSubnet')]" + ] } ], "outputs": { - "publicIPAddressSP": { - "condition": "[or(equals(parameters('addPublicIPAddress'), 'Yes'), equals(parameters('addPublicIPAddress'), 'SharePointVMsOnly'))]", + "publicIPAddressDC": { "type": "string", - "value": "[reference(resourceId('Microsoft.Network/publicIPAddresses', variables('vmsResourcesNames').vmSPPublicIPName)).dnsSettings.fqdn]" - }, - "publicIPAddressFEs": { - "condition": "[and(greaterOrEquals(parameters('numberOfAdditionalFrontEnd'), 1), or(equals(parameters('addPublicIPAddress'), 'Yes'), equals(parameters('addPublicIPAddress'), 'SharePointVMsOnly')))]", - "type": "array", - "copy": { - "count": "[parameters('numberOfAdditionalFrontEnd')]", - "input": "[reference(resourceId('Microsoft.Network/publicIPAddresses', concat(variables('vmsResourcesNames').vmFEPublicIPName, '-', copyIndex()))).dnsSettings.fqdn]" - } + "value": "[if(equals(parameters('outboundAccessMethod'), 'PublicIPAddress'), reference(resourceId('Microsoft.Network/publicIPAddresses', 'vm-dc-pip'), '2023-11-01').dnsSettings.fqdn, '')]" }, "publicIPAddressSQL": { - "condition": "[equals(parameters('addPublicIPAddress'), 'Yes')]", "type": "string", - "value": "[reference(resourceId('Microsoft.Network/publicIPAddresses', variables('vmsResourcesNames').vmSQLPublicIPName)).dnsSettings.fqdn]" + "value": "[if(equals(parameters('outboundAccessMethod'), 'PublicIPAddress'), reference(resourceId('Microsoft.Network/publicIPAddresses', 'vm-sql-pip'), '2023-11-01').dnsSettings.fqdn, '')]" }, - "publicIPAddressDC": { - "condition": "[equals(parameters('addPublicIPAddress'), 'Yes')]", + "publicIPAddressSP": { "type": "string", - "value": "[reference(resourceId('Microsoft.Network/publicIPAddresses', variables('vmsResourcesNames').vmDCPublicIPName)).dnsSettings.fqdn]" + "value": "[if(equals(parameters('outboundAccessMethod'), 'PublicIPAddress'), reference(resourceId('Microsoft.Network/publicIPAddresses', 'vm-sp-pip'), '2023-11-01').dnsSettings.fqdn, '')]" + }, + "vm_fe_public_dns": { + "type": "array", + "copy": { + "count": "[length(range(0, parameters('frontEndServersCount')))]", + "input": "[if(equals(parameters('outboundAccessMethod'), 'PublicIPAddress'), reference(resourceId('Microsoft.Network/publicIPAddresses', format('vm-fe{0}-pip', range(0, parameters('frontEndServersCount'))[range(0, parameters('frontEndServersCount'))[copyIndex()]])), '2023-11-01').dnsSettings.fqdn, null())]" + } }, "domainAdminAccount": { "type": "string", - "value": "[concat(substring(parameters('domainFQDN'), 0, indexOf(parameters('domainFQDN'), '.')), '\\', parameters('adminUserName'))]" + "value": "[format('{0}\\{1}', substring(parameters('domainFqdn'), 0, indexOf(parameters('domainFqdn'), '.')), parameters('adminUsername'))]" }, "domainAdminAccountFormatForBastion": { "type": "string", - "value": "[concat(parameters('adminUserName'), '@', parameters('domainFQDN'))]" + "value": "[format('{0}@{1}', parameters('adminUsername'), parameters('domainFqdn'))]" }, "localAdminAccount": { "type": "string", "value": "[variables('deploymentSettings').localAdminUserName]" } } -} +} \ No newline at end of file diff --git a/Templates/SharePoint-ADFS/azuredeploy.parameters.json b/Templates/SharePoint-ADFS/azuredeploy.parameters.json index 9984f114..ee8b81a6 100644 --- a/Templates/SharePoint-ADFS/azuredeploy.parameters.json +++ b/Templates/SharePoint-ADFS/azuredeploy.parameters.json @@ -2,22 +2,37 @@ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", "contentVersion": "1.0.0.0", "parameters": { - "sharePointVersion": { "value": "Subscription-Latest" }, + "sharePointVersion": { "value": "Subscription-24H2" }, // "sharePointVersion": { "value": "2019" }, - "domainFQDN": { "value": "contoso.local" }, - "adminUserName": { "value": "yvand" }, - "adminPassword": { "value": null }, - "serviceAccountsPassword": { "value": null }, - "vmsTimeZone": { "value": "Romance Standard Time" }, - "vmSPStorageAccountType": { "value": "Premium_LRS" }, - "addPublicIPAddress": { "value": "SharePointVMsOnly" }, - // "addPublicIPAddress": { "value": "No" }, - "RDPTrafficAllowed": { "value": "10.20.30.40" }, - "numberOfAdditionalFrontEnd": { "value": 0 }, + "domainFqdn": { "value": "xcontoso.local" }, + "adminUsername": { "value": "xyvand" }, + "timeZone": { "value": "Romance Standard Time" }, + "vmSharePointStorage": { "value": "Premium_LRS" }, + // "outboundAccessMethod": { "value": "PublicIPAddress" }, + "outboundAccessMethod": { "value": "AzureFirewallProxy" }, + "rdpTrafficRule": { "value": "10.20.30.40" }, + "frontEndServersCount": { "value": 1 }, "enableHybridBenefitServerLicenses": { "value": true }, - "enableAutomaticUpdates": { "value": true }, - "sharePointDataDiskSize": { "value": 0 }, - "addAzureBastion": { "value": false }, - "_artifactsLocation": { "value": "https://github.com/Yvand/AzureRM-Templates/raw/dev/Templates/SharePoint-ADFS/" } + "enableAzureBastion": { "value": true }, + "_artifactsLocation": { "value": "https://github.com/Yvand/AzureRM-Templates/raw/dev/Templates/SharePoint-ADFS/" }, + "_artifactsLocationSasToken": { "value": "" }, + "autoShutdownTime": { + "value": "1900" + }, + "vmDcSize": { + "value": "Standard_B2s" + }, + "vmDcStorage": { + "value": "StandardSSD_LRS" + }, + "vmSqlSize": { + "value": "Standard_B2ms" + }, + "vmSqlStorage": { + "value": "StandardSSD_LRS" + }, + "vmSharePointSize": { + "value": "Standard_B4ms" + } } } diff --git a/Templates/SharePoint-ADFS/dsc/ConfigureDCVM.ps1 b/Templates/SharePoint-ADFS/dsc/ConfigureDCVM.ps1 index 2010d388..c7d2a30c 100644 --- a/Templates/SharePoint-ADFS/dsc/ConfigureDCVM.ps1 +++ b/Templates/SharePoint-ADFS/dsc/ConfigureDCVM.ps1 @@ -12,12 +12,12 @@ [Parameter(Mandatory)] [System.Management.Automation.PSCredential]$AdfsSvcCreds ) - Import-DscResource -ModuleName ActiveDirectoryDsc -ModuleVersion 6.3.0 + Import-DscResource -ModuleName ActiveDirectoryDsc -ModuleVersion 6.4.0 Import-DscResource -ModuleName NetworkingDsc -ModuleVersion 9.0.0 Import-DscResource -ModuleName ActiveDirectoryCSDsc -ModuleVersion 5.0.0 Import-DscResource -ModuleName CertificateDsc -ModuleVersion 5.1.0 Import-DscResource -ModuleName DnsServerDsc -ModuleVersion 3.0.0 - Import-DscResource -ModuleName ComputerManagementDsc -ModuleVersion 9.0.0 # Custom + Import-DscResource -ModuleName ComputerManagementDsc -ModuleVersion 9.1.0 # Custom Import-DscResource -ModuleName AdfsDsc -ModuleVersion 1.4.0 # Init @@ -645,6 +645,18 @@ WindowsFeature AddADLDS { Name = "RSAT-ADLDS"; Ensure = "Present"; } WindowsFeature AddADCSManagementTools { Name = "RSAT-ADCS-Mgmt"; Ensure = "Present"; } + Script EnableFileSharing { + GetScript = { } + TestScript = { return $null -ne (Get-NetFirewallRule -DisplayGroup "File And Printer Sharing" -Enabled True -ErrorAction SilentlyContinue | Where-Object { $_.Profile -eq "Domain" }) } + SetScript = { Set-NetFirewallRule -DisplayGroup "File And Printer Sharing" -Enabled True -Profile Domain } + } + + Script EnableRemoteEventViewerConnection { + GetScript = { } + TestScript = { return $null -ne (Get-NetFirewallRule -DisplayGroup "Remote Event Log Management" -Enabled True -ErrorAction SilentlyContinue | Where-Object { $_.Profile -eq "Domain" }) } + SetScript = { Set-NetFirewallRule -DisplayGroup "Remote Event Log Management" -Enabled True -Profile Any } + } + #****************************************************************** # Set insecure LDAP configurations from default 1 to 2 to avoid elevation of priviledge vulnerability on AD domain controller # Mitigate https://msrc.microsoft.com/update-guide/vulnerability/CVE-2017-8563 using https://support.microsoft.com/en-us/topic/use-the-ldapenforcechannelbinding-registry-entry-to-make-ldap-authentication-over-ssl-tls-more-secure-e9ecfa27-5e57-8519-6ba3-d2c06b21812e diff --git a/Templates/SharePoint-ADFS/dsc/ConfigureDCVM.zip b/Templates/SharePoint-ADFS/dsc/ConfigureDCVM.zip index ab067a94..2ba12e9c 100644 Binary files a/Templates/SharePoint-ADFS/dsc/ConfigureDCVM.zip and b/Templates/SharePoint-ADFS/dsc/ConfigureDCVM.zip differ diff --git a/Templates/SharePoint-ADFS/dsc/ConfigureFELegacy.ps1 b/Templates/SharePoint-ADFS/dsc/ConfigureFELegacy.ps1 index 757c3336..c18ec88c 100644 --- a/Templates/SharePoint-ADFS/dsc/ConfigureFELegacy.ps1 +++ b/Templates/SharePoint-ADFS/dsc/ConfigureFELegacy.ps1 @@ -17,11 +17,11 @@ configuration ConfigureFEVM [Parameter(Mandatory)] [System.Management.Automation.PSCredential]$SPPassphraseCreds ) - Import-DscResource -ModuleName ComputerManagementDsc -ModuleVersion 9.0.0 # Custom + Import-DscResource -ModuleName ComputerManagementDsc -ModuleVersion 9.1.0 # Custom Import-DscResource -ModuleName NetworkingDsc -ModuleVersion 9.0.0 - Import-DscResource -ModuleName ActiveDirectoryDsc -ModuleVersion 6.3.0 + Import-DscResource -ModuleName ActiveDirectoryDsc -ModuleVersion 6.4.0 Import-DscResource -ModuleName WebAdministrationDsc -ModuleVersion 4.1.0 - Import-DscResource -ModuleName SharePointDsc -ModuleVersion 5.4.0 + Import-DscResource -ModuleName SharePointDsc -ModuleVersion 5.5.0 Import-DscResource -ModuleName DnsServerDsc -ModuleVersion 3.0.0 Import-DscResource -ModuleName CertificateDsc -ModuleVersion 5.1.0 Import-DscResource -ModuleName SqlServerDsc -ModuleVersion 16.5.0 @@ -128,21 +128,10 @@ configuration ConfigureFEVM SqlAlias AddSqlAlias { Ensure = "Present"; Name = $SQLAlias; ServerName = $SQLServerName; Protocol = "TCP"; TcpPort= 1433 } - Script EnableFileSharing - { - TestScript = { - # Test if firewall rules for file sharing already exist - $rulesSet = Get-NetFirewallRule -DisplayGroup "File And Printer Sharing" -Enabled True -ErrorAction SilentlyContinue | Where-Object{$_.Profile -eq "Domain"} - if ($null -eq $rulesSet) { - return $false # Run SetScript - } else { - return $true # Rules already set - } - } - SetScript = { - Set-NetFirewallRule -DisplayGroup "File And Printer Sharing" -Enabled True -Profile Domain -Confirm:$false - } - GetScript = { } + Script EnableFileSharing { + GetScript = { } + TestScript = { return $null -ne (Get-NetFirewallRule -DisplayGroup "File And Printer Sharing" -Enabled True -ErrorAction SilentlyContinue | Where-Object { $_.Profile -eq "Domain" }) } + SetScript = { Set-NetFirewallRule -DisplayGroup "File And Printer Sharing" -Enabled True -Profile Domain } } # Create the rules in the firewall required for the distributed cache - https://learn.microsoft.com/en-us/sharepoint/administration/plan-for-feeds-and-the-distributed-cache-service#firewall diff --git a/Templates/SharePoint-ADFS/dsc/ConfigureFELegacy.zip b/Templates/SharePoint-ADFS/dsc/ConfigureFELegacy.zip index e3a3e112..73c2dff4 100644 Binary files a/Templates/SharePoint-ADFS/dsc/ConfigureFELegacy.zip and b/Templates/SharePoint-ADFS/dsc/ConfigureFELegacy.zip differ diff --git a/Templates/SharePoint-ADFS/dsc/ConfigureFESE.ps1 b/Templates/SharePoint-ADFS/dsc/ConfigureFESE.ps1 index 9712b7b2..4170272a 100644 --- a/Templates/SharePoint-ADFS/dsc/ConfigureFESE.ps1 +++ b/Templates/SharePoint-ADFS/dsc/ConfigureFESE.ps1 @@ -17,11 +17,11 @@ configuration ConfigureFEVM [Parameter(Mandatory)] [System.Management.Automation.PSCredential]$SPPassphraseCreds ) - Import-DscResource -ModuleName ComputerManagementDsc -ModuleVersion 9.0.0 # Custom + Import-DscResource -ModuleName ComputerManagementDsc -ModuleVersion 9.1.0 # Custom Import-DscResource -ModuleName NetworkingDsc -ModuleVersion 9.0.0 - Import-DscResource -ModuleName ActiveDirectoryDsc -ModuleVersion 6.3.0 + Import-DscResource -ModuleName ActiveDirectoryDsc -ModuleVersion 6.4.0 Import-DscResource -ModuleName WebAdministrationDsc -ModuleVersion 4.1.0 - Import-DscResource -ModuleName SharePointDsc -ModuleVersion 5.4.0 + Import-DscResource -ModuleName SharePointDsc -ModuleVersion 5.5.0 Import-DscResource -ModuleName DnsServerDsc -ModuleVersion 3.0.0 Import-DscResource -ModuleName CertificateDsc -ModuleVersion 5.1.0 Import-DscResource -ModuleName SqlServerDsc -ModuleVersion 16.5.0 @@ -175,7 +175,13 @@ configuration ConfigureFEVM Script EnableFileSharing { GetScript = { } TestScript = { return $null -ne (Get-NetFirewallRule -DisplayGroup "File And Printer Sharing" -Enabled True -ErrorAction SilentlyContinue | Where-Object { $_.Profile -eq "Domain" }) } - SetScript = { Set-NetFirewallRule -DisplayGroup "File And Printer Sharing" -Enabled True -Profile Domain -Confirm:$false } + SetScript = { Set-NetFirewallRule -DisplayGroup "File And Printer Sharing" -Enabled True -Profile Domain } + } + + Script EnableRemoteEventViewerConnection { + GetScript = { } + TestScript = { return $null -ne (Get-NetFirewallRule -DisplayGroup "Remote Event Log Management" -Enabled True -ErrorAction SilentlyContinue | Where-Object { $_.Profile -eq "Domain" }) } + SetScript = { Set-NetFirewallRule -DisplayGroup "Remote Event Log Management" -Enabled True -Profile Domain } } # Create the rules in the firewall required for the distributed cache - https://learn.microsoft.com/en-us/sharepoint/administration/plan-for-feeds-and-the-distributed-cache-service#firewall @@ -194,18 +200,19 @@ configuration ConfigureFEVM } } SetScript = { - $icmpRuleName = "File and Printer Sharing (Echo Request - ICMPv4-In)" - $icmpFirewallRule = Get-NetFirewallRule -DisplayName $icmpRuleName -ErrorAction SilentlyContinue - if ($null -eq $icmpFirewallRule) { - New-NetFirewallRule -Name Allow_Ping -DisplayName $icmpRuleName ` - -Description "Allow ICMPv4 ping" ` - -Protocol ICMPv4 ` - -IcmpType 8 ` - -Enabled True ` - -Profile Any ` - -Action Allow - } - Enable-NetFirewallRule -DisplayName $icmpRuleName + # $icmpRuleName = "File and Printer Sharing (Echo Request - ICMPv4-In)" + # $icmpFirewallRule = Get-NetFirewallRule -DisplayName $icmpRuleName -ErrorAction SilentlyContinue + # if ($null -eq $icmpFirewallRule) { + # New-NetFirewallRule -Name Allow_Ping -DisplayName $icmpRuleName ` + # -Description "Allow ICMPv4 ping" ` + # -Protocol ICMPv4 ` + # -IcmpType 8 ` + # -Enabled True ` + # -Profile Any ` + # -Action Allow + # } + # Enable-NetFirewallRule -DisplayName $icmpRuleName + Enable-NetFirewallRule -displayName "File and Printer Sharing (Echo Request - ICMPv4-In)" $spRuleName = "SharePoint Distributed Cache" $firewallRule = Get-NetFirewallRule -DisplayName $spRuleName -ErrorAction SilentlyContinue diff --git a/Templates/SharePoint-ADFS/dsc/ConfigureFESE.zip b/Templates/SharePoint-ADFS/dsc/ConfigureFESE.zip index bc9d51b1..0c9f6cda 100644 Binary files a/Templates/SharePoint-ADFS/dsc/ConfigureFESE.zip and b/Templates/SharePoint-ADFS/dsc/ConfigureFESE.zip differ diff --git a/Templates/SharePoint-ADFS/dsc/ConfigureSPLegacy.ps1 b/Templates/SharePoint-ADFS/dsc/ConfigureSPLegacy.ps1 index 38696ea3..940a1e5c 100644 --- a/Templates/SharePoint-ADFS/dsc/ConfigureSPLegacy.ps1 +++ b/Templates/SharePoint-ADFS/dsc/ConfigureSPLegacy.ps1 @@ -23,12 +23,12 @@ configuration ConfigureSPVM [Parameter(Mandatory)] [System.Management.Automation.PSCredential]$SPSuperReaderCreds ) - Import-DscResource -ModuleName ComputerManagementDsc -ModuleVersion 9.0.0 # Custom + Import-DscResource -ModuleName ComputerManagementDsc -ModuleVersion 9.1.0 # Custom Import-DscResource -ModuleName NetworkingDsc -ModuleVersion 9.0.0 - Import-DscResource -ModuleName ActiveDirectoryDsc -ModuleVersion 6.3.0 + Import-DscResource -ModuleName ActiveDirectoryDsc -ModuleVersion 6.4.0 Import-DscResource -ModuleName xCredSSP -ModuleVersion 1.4.0 Import-DscResource -ModuleName WebAdministrationDsc -ModuleVersion 4.1.0 - Import-DscResource -ModuleName SharePointDsc -ModuleVersion 5.4.0 + Import-DscResource -ModuleName SharePointDsc -ModuleVersion 5.5.0 Import-DscResource -ModuleName DnsServerDsc -ModuleVersion 3.0.0 Import-DscResource -ModuleName CertificateDsc -ModuleVersion 5.1.0 Import-DscResource -ModuleName SqlServerDsc -ModuleVersion 16.5.0 @@ -150,21 +150,10 @@ configuration ConfigureSPVM SqlAlias AddSqlAlias { Ensure = "Present"; Name = $SQLAlias; ServerName = $SQLServerName; Protocol = "TCP"; TcpPort= 1433 } - Script EnableFileSharing - { - TestScript = { - # Test if firewall rules for file sharing already exist - $rulesSet = Get-NetFirewallRule -DisplayGroup "File And Printer Sharing" -Enabled True -ErrorAction SilentlyContinue | Where-Object{$_.Profile -eq "Domain"} - if ($null -eq $rulesSet) { - return $false # Run SetScript - } else { - return $true # Rules already set - } - } - SetScript = { - Set-NetFirewallRule -DisplayGroup "File And Printer Sharing" -Enabled True -Profile Domain -Confirm:$false - } - GetScript = { } + Script EnableFileSharing { + GetScript = { } + TestScript = { return $null -ne (Get-NetFirewallRule -DisplayGroup "File And Printer Sharing" -Enabled True -ErrorAction SilentlyContinue | Where-Object { $_.Profile -eq "Domain" }) } + SetScript = { Set-NetFirewallRule -DisplayGroup "File And Printer Sharing" -Enabled True -Profile Domain } } # Create the rules in the firewall required for the distributed cache - https://learn.microsoft.com/en-us/sharepoint/administration/plan-for-feeds-and-the-distributed-cache-service#firewall diff --git a/Templates/SharePoint-ADFS/dsc/ConfigureSPLegacy.zip b/Templates/SharePoint-ADFS/dsc/ConfigureSPLegacy.zip index fa90de82..0da35c84 100644 Binary files a/Templates/SharePoint-ADFS/dsc/ConfigureSPLegacy.zip and b/Templates/SharePoint-ADFS/dsc/ConfigureSPLegacy.zip differ diff --git a/Templates/SharePoint-ADFS/dsc/ConfigureSPSE.ps1 b/Templates/SharePoint-ADFS/dsc/ConfigureSPSE.ps1 index 66517310..8f707da2 100644 --- a/Templates/SharePoint-ADFS/dsc/ConfigureSPSE.ps1 +++ b/Templates/SharePoint-ADFS/dsc/ConfigureSPSE.ps1 @@ -23,12 +23,12 @@ configuration ConfigureSPVM [Parameter(Mandatory)] [System.Management.Automation.PSCredential]$SPSuperReaderCreds ) - Import-DscResource -ModuleName ComputerManagementDsc -ModuleVersion 9.0.0 # Custom + Import-DscResource -ModuleName ComputerManagementDsc -ModuleVersion 9.1.0 # Custom Import-DscResource -ModuleName NetworkingDsc -ModuleVersion 9.0.0 - Import-DscResource -ModuleName ActiveDirectoryDsc -ModuleVersion 6.3.0 + Import-DscResource -ModuleName ActiveDirectoryDsc -ModuleVersion 6.4.0 Import-DscResource -ModuleName xCredSSP -ModuleVersion 1.4.0 Import-DscResource -ModuleName WebAdministrationDsc -ModuleVersion 4.1.0 - Import-DscResource -ModuleName SharePointDsc -ModuleVersion 5.4.0 + Import-DscResource -ModuleName SharePointDsc -ModuleVersion 5.5.0 Import-DscResource -ModuleName DnsServerDsc -ModuleVersion 3.0.0 Import-DscResource -ModuleName CertificateDsc -ModuleVersion 5.1.0 Import-DscResource -ModuleName SqlServerDsc -ModuleVersion 16.5.0 @@ -201,7 +201,13 @@ configuration ConfigureSPVM Script EnableFileSharing { GetScript = { } TestScript = { return $null -ne (Get-NetFirewallRule -DisplayGroup "File And Printer Sharing" -Enabled True -ErrorAction SilentlyContinue | Where-Object { $_.Profile -eq "Domain" }) } - SetScript = { Set-NetFirewallRule -DisplayGroup "File And Printer Sharing" -Enabled True -Profile Domain -Confirm:$false } + SetScript = { Set-NetFirewallRule -DisplayGroup "File And Printer Sharing" -Enabled True -Profile Domain } + } + + Script EnableRemoteEventViewerConnection { + GetScript = { } + TestScript = { return $null -ne (Get-NetFirewallRule -DisplayGroup "Remote Event Log Management" -Enabled True -ErrorAction SilentlyContinue | Where-Object { $_.Profile -eq "Domain" }) } + SetScript = { Set-NetFirewallRule -DisplayGroup "Remote Event Log Management" -Enabled True -Profile Domain } } # Create the rules in the firewall required for the distributed cache - https://learn.microsoft.com/en-us/sharepoint/administration/plan-for-feeds-and-the-distributed-cache-service#firewall @@ -220,18 +226,19 @@ configuration ConfigureSPVM } } SetScript = { - $icmpRuleName = "File and Printer Sharing (Echo Request - ICMPv4-In)" - $icmpFirewallRule = Get-NetFirewallRule -DisplayName $icmpRuleName -ErrorAction SilentlyContinue - if ($null -eq $icmpFirewallRule) { - New-NetFirewallRule -Name Allow_Ping -DisplayName $icmpRuleName ` - -Description "Allow ICMPv4 ping" ` - -Protocol ICMPv4 ` - -IcmpType 8 ` - -Enabled True ` - -Profile Any ` - -Action Allow - } - Enable-NetFirewallRule -DisplayName $icmpRuleName + # $icmpRuleName = "File and Printer Sharing (Echo Request - ICMPv4-In)" + # $icmpFirewallRule = Get-NetFirewallRule -DisplayName $icmpRuleName -ErrorAction SilentlyContinue + # if ($null -eq $icmpFirewallRule) { + # New-NetFirewallRule -Name Allow_Ping -DisplayName $icmpRuleName ` + # -Description "Allow ICMPv4 ping" ` + # -Protocol ICMPv4 ` + # -IcmpType 8 ` + # -Enabled True ` + # -Profile Any ` + # -Action Allow + # } + # Enable-NetFirewallRule -DisplayName $icmpRuleName + Enable-NetFirewallRule -displayName "File and Printer Sharing (Echo Request - ICMPv4-In)" $spRuleName = "SharePoint Distributed Cache" $firewallRule = Get-NetFirewallRule -DisplayName $spRuleName -ErrorAction SilentlyContinue diff --git a/Templates/SharePoint-ADFS/dsc/ConfigureSPSE.zip b/Templates/SharePoint-ADFS/dsc/ConfigureSPSE.zip index 817db1eb..264b718d 100644 Binary files a/Templates/SharePoint-ADFS/dsc/ConfigureSPSE.zip and b/Templates/SharePoint-ADFS/dsc/ConfigureSPSE.zip differ diff --git a/Templates/SharePoint-ADFS/dsc/ConfigureSQLVM.ps1 b/Templates/SharePoint-ADFS/dsc/ConfigureSQLVM.ps1 index ef29e8cf..144c2f46 100644 --- a/Templates/SharePoint-ADFS/dsc/ConfigureSQLVM.ps1 +++ b/Templates/SharePoint-ADFS/dsc/ConfigureSQLVM.ps1 @@ -9,9 +9,9 @@ configuration ConfigureSQLVM [Parameter(Mandatory)] [System.Management.Automation.PSCredential]$SPSetupCreds ) - Import-DscResource -ModuleName ComputerManagementDsc -ModuleVersion 9.0.0 # Custom + Import-DscResource -ModuleName ComputerManagementDsc -ModuleVersion 9.1.0 # Custom Import-DscResource -ModuleName NetworkingDsc -ModuleVersion 9.0.0 - Import-DscResource -ModuleName ActiveDirectoryDsc -ModuleVersion 6.3.0 + Import-DscResource -ModuleName ActiveDirectoryDsc -ModuleVersion 6.4.0 Import-DscResource -ModuleName SqlServerDsc -ModuleVersion 16.5.0 WaitForSqlSetup @@ -41,11 +41,16 @@ configuration ConfigureSQLVM DnsServerAddress SetDNS { Address = $DNSServerIP; InterfaceAlias = $InterfaceAlias; AddressFamily = 'IPv4' } - Script EnableFileSharing - { - GetScript = { } - TestScript = { return $null -ne (Get-NetFirewallRule -DisplayGroup "File And Printer Sharing" -Enabled True -ErrorAction SilentlyContinue | Where-Object{$_.Profile -eq "Domain"}) } - SetScript = { Set-NetFirewallRule -DisplayGroup "File And Printer Sharing" -Enabled True -Profile Domain -Confirm:$false } + Script EnableFileSharing { + GetScript = { } + TestScript = { return $null -ne (Get-NetFirewallRule -DisplayGroup "File And Printer Sharing" -Enabled True -ErrorAction SilentlyContinue | Where-Object { $_.Profile -eq "Domain" }) } + SetScript = { Set-NetFirewallRule -DisplayGroup "File And Printer Sharing" -Enabled True -Profile Domain } + } + + Script EnableRemoteEventViewerConnection { + GetScript = { } + TestScript = { return $null -ne (Get-NetFirewallRule -DisplayGroup "Remote Event Log Management" -Enabled True -ErrorAction SilentlyContinue | Where-Object { $_.Profile -eq "Domain" }) } + SetScript = { Set-NetFirewallRule -DisplayGroup "Remote Event Log Management" -Enabled True -Profile Domain } } #********************************************************** diff --git a/Templates/SharePoint-ADFS/dsc/ConfigureSQLVM.zip b/Templates/SharePoint-ADFS/dsc/ConfigureSQLVM.zip index 0d432ee5..6672ffa8 100644 Binary files a/Templates/SharePoint-ADFS/dsc/ConfigureSQLVM.zip and b/Templates/SharePoint-ADFS/dsc/ConfigureSQLVM.zip differ diff --git a/Templates/SharePoint-ADFS/main.bicep b/Templates/SharePoint-ADFS/main.bicep new file mode 100644 index 00000000..10842786 --- /dev/null +++ b/Templates/SharePoint-ADFS/main.bicep @@ -0,0 +1,1645 @@ +metadata description = 'Create a DC, a SQL Server 2022, and from 1 to 5 server(s) hosting a SharePoint Subscription / 2019 / 2016 farm with an extensive configuration, including trusted authentication, user profiles with personal sites, an OAuth trust (using a certificate), a dedicated IIS site for hosting high-trust add-ins, etc... The latest version of key softwares (including Fiddler, vscode, np++, 7zip, ULS Viewer) is installed. SharePoint machines have additional fine-tuning to make them immediately usable (remote administration tools, custom policies for Edge and Chrome, shortcuts, etc...).' +metadata author = 'Yvand' + +@description('Location for all the resources.') +param location string = resourceGroup().location + +@description('Version of the SharePoint farm to create.') +@allowed([ + 'Subscription-Latest' + 'Subscription-24H2' + 'Subscription-24H1' + 'Subscription-23H2' + 'Subscription-23H1' + 'Subscription-22H2' + 'Subscription-RTM' + '2019' + '2016' +]) +param sharePointVersion string = 'Subscription-Latest' + +@description('FQDN of the Active Directory forest.') +@minLength(5) +param domainFqdn string = 'contoso.local' + +@description('Number of servers with MinRole Front-end to add to the farm.') +@allowed([ + 0 + 1 + 2 + 3 + 4 +]) +param frontEndServersCount int = 0 + +@description('Name of the Active Directory and SharePoint administrator. "admin" and "administrator" are not allowed.') +@minLength(1) +param adminUsername string + +@description('Password for the admin account. Input must meet password complexity requirements as documented in https://learn.microsoft.com/azure/virtual-machines/windows/faq#what-are-the-password-requirements-when-creating-a-vm-') +@minLength(8) +@secure() +param adminPassword string + +@description('Password for all the other accounts and the SharePoint passphrase. Input must meet password complexity requirements as documented in https://learn.microsoft.com/azure/virtual-machines/windows/faq#what-are-the-password-requirements-when-creating-a-vm-') +@minLength(8) +@secure() +param otherAccountsPassword string + +@description(''' +Specify if a rule in the network security groups should allow the inbound RDP traffic: +- "No" (default): No rule is created, RDP traffic is blocked. +- "*" or "Internet": RDP traffic is allowed from everywhere. +- CIDR notation (e.g. 192.168.99.0/24 or 2001:1234::/64) or an IP address (e.g. 192.168.99.0 or 2001:1234::): RDP traffic is allowed from the IP address / pattern specified. +''') +@minLength(1) +param rdpTrafficRule string = 'No' + +@description(''' +Select how the virtual machines connect to internet. +IMPORTANT: With AzureFirewallProxy, you need to either enable Azure Bastion, or manually add a public IP address to a virtual machine, to be able to connect to it. +''') +@allowed([ + 'PublicIPAddress' + 'AzureFirewallProxy' +]) +param outboundAccessMethod string = 'PublicIPAddress' + +@description('Specify if Azure Bastion should be provisioned. See https://azure.microsoft.com/en-us/services/azure-bastion for more information.') +param enableAzureBastion bool = false + +@description('Enable the Azure Hybrid Benefit on virtual machines, to use your on-premises Windows Server licenses and reduce cost. See https://docs.microsoft.com/en-us/azure/virtual-machines/windows/hybrid-use-benefit-licensing for more information.') +param enableHybridBenefitServerLicenses bool = false + +@description('Time zone of the virtual machines. Type "[TimeZoneInfo]::GetSystemTimeZones().Id" in PowerShell to get the list.') +@minLength(2) +@allowed([ + 'Dateline Standard Time' + 'UTC-11' + 'Aleutian Standard Time' + 'Hawaiian Standard Time' + 'Marquesas Standard Time' + 'Alaskan Standard Time' + 'UTC-09' + 'Pacific Standard Time (Mexico)' + 'UTC-08' + 'Pacific Standard Time' + 'US Mountain Standard Time' + 'Mountain Standard Time (Mexico)' + 'Mountain Standard Time' + 'Central America Standard Time' + 'Central Standard Time' + 'Easter Island Standard Time' + 'Central Standard Time (Mexico)' + 'Canada Central Standard Time' + 'SA Pacific Standard Time' + 'Eastern Standard Time (Mexico)' + 'Eastern Standard Time' + 'Haiti Standard Time' + 'Cuba Standard Time' + 'US Eastern Standard Time' + 'Turks And Caicos Standard Time' + 'Paraguay Standard Time' + 'Atlantic Standard Time' + 'Venezuela Standard Time' + 'Central Brazilian Standard Time' + 'SA Western Standard Time' + 'Pacific SA Standard Time' + 'Newfoundland Standard Time' + 'Tocantins Standard Time' + 'E. South America Standard Time' + 'SA Eastern Standard Time' + 'Argentina Standard Time' + 'Greenland Standard Time' + 'Montevideo Standard Time' + 'Magallanes Standard Time' + 'Saint Pierre Standard Time' + 'Bahia Standard Time' + 'UTC-02' + 'Mid-Atlantic Standard Time' + 'Azores Standard Time' + 'Cape Verde Standard Time' + 'UTC' + 'GMT Standard Time' + 'Greenwich Standard Time' + 'Sao Tome Standard Time' + 'Morocco Standard Time' + 'W. Europe Standard Time' + 'Central Europe Standard Time' + 'Romance Standard Time' + 'Central European Standard Time' + 'W. Central Africa Standard Time' + 'Jordan Standard Time' + 'GTB Standard Time' + 'Middle East Standard Time' + 'Egypt Standard Time' + 'E. Europe Standard Time' + 'Syria Standard Time' + 'West Bank Standard Time' + 'South Africa Standard Time' + 'FLE Standard Time' + 'Israel Standard Time' + 'Kaliningrad Standard Time' + 'Sudan Standard Time' + 'Libya Standard Time' + 'Namibia Standard Time' + 'Arabic Standard Time' + 'Turkey Standard Time' + 'Arab Standard Time' + 'Belarus Standard Time' + 'Russian Standard Time' + 'E. Africa Standard Time' + 'Iran Standard Time' + 'Arabian Standard Time' + 'Astrakhan Standard Time' + 'Azerbaijan Standard Time' + 'Russia Time Zone 3' + 'Mauritius Standard Time' + 'Saratov Standard Time' + 'Georgian Standard Time' + 'Volgograd Standard Time' + 'Caucasus Standard Time' + 'Afghanistan Standard Time' + 'West Asia Standard Time' + 'Ekaterinburg Standard Time' + 'Pakistan Standard Time' + 'Qyzylorda Standard Time' + 'India Standard Time' + 'Sri Lanka Standard Time' + 'Nepal Standard Time' + 'Central Asia Standard Time' + 'Bangladesh Standard Time' + 'Omsk Standard Time' + 'Myanmar Standard Time' + 'SE Asia Standard Time' + 'Altai Standard Time' + 'W. Mongolia Standard Time' + 'North Asia Standard Time' + 'N. Central Asia Standard Time' + 'Tomsk Standard Time' + 'China Standard Time' + 'North Asia East Standard Time' + 'Singapore Standard Time' + 'W. Australia Standard Time' + 'Taipei Standard Time' + 'Ulaanbaatar Standard Time' + 'Aus Central W. Standard Time' + 'Transbaikal Standard Time' + 'Tokyo Standard Time' + 'North Korea Standard Time' + 'Korea Standard Time' + 'Yakutsk Standard Time' + 'Cen. Australia Standard Time' + 'AUS Central Standard Time' + 'E. Australia Standard Time' + 'AUS Eastern Standard Time' + 'West Pacific Standard Time' + 'Tasmania Standard Time' + 'Vladivostok Standard Time' + 'Lord Howe Standard Time' + 'Bougainville Standard Time' + 'Russia Time Zone 10' + 'Magadan Standard Time' + 'Norfolk Standard Time' + 'Sakhalin Standard Time' + 'Central Pacific Standard Time' + 'Russia Time Zone 11' + 'New Zealand Standard Time' + 'UTC+12' + 'Fiji Standard Time' + 'Kamchatka Standard Time' + 'Chatham Islands Standard Time' + 'UTC+13' + 'Tonga Standard Time' + 'Samoa Standard Time' + 'Line Islands Standard Time' +]) +param timeZone string = 'Romance Standard Time' + +@description('The time (24h HHmm format) at which the virtual machines will automatically be shutdown and deallocated. Set value to "9999" to NOT configure the auto shutdown.') +@minLength(4) +@maxLength(4) +param autoShutdownTime string = '1900' + +@description('Size of the DC virtual machine.') +param vmDcSize string = 'Standard_B2s' + +@description('Type of storage for the managed disk. Visit https://docs.microsoft.com/en-us/rest/api/compute/disks/list#diskstorageaccounttypes for more information.') +@allowed([ + 'Standard_LRS' + 'StandardSSD_LRS' + 'StandardSSD_ZRS' + 'Premium_LRS' + 'PremiumV2_LRS' + 'Premium_ZRS' + 'UltraSSD_LRS' +]) +param vmDcStorage string = 'StandardSSD_LRS' + +@description('Size of the SQL virtual machine.') +param vmSqlSize string = 'Standard_B2ms' + +@description('Type of storage for the managed disk. Visit https://docs.microsoft.com/en-us/rest/api/compute/disks/list#diskstorageaccounttypes for more information.') +@allowed([ + 'Standard_LRS' + 'StandardSSD_LRS' + 'StandardSSD_ZRS' + 'Premium_LRS' + 'PremiumV2_LRS' + 'Premium_ZRS' + 'UltraSSD_LRS' +]) +param vmSqlStorage string = 'StandardSSD_LRS' + +@description('Size of the SharePoint virtual machine(s).') +param vmSharePointSize string = 'Standard_B4ms' + +@description('Type of storage for the managed disk. Visit https://docs.microsoft.com/en-us/rest/api/compute/disks/list#diskstorageaccounttypes for more information.') +@allowed([ + 'Standard_LRS' + 'StandardSSD_LRS' + 'StandardSSD_ZRS' + 'Premium_LRS' + 'PremiumV2_LRS' + 'Premium_ZRS' + 'UltraSSD_LRS' +]) +param vmSharePointStorage string = 'StandardSSD_LRS' + +@description('The base URI where artifacts required by this template are located. When the template is deployed using the accompanying scripts, a private location in the subscription will be used and this value will be automatically generated.') +param _artifactsLocation string = deployment().properties.templateLink.uri + +@description('The sasToken required to access _artifactsLocation. When the template is deployed using the accompanying scripts, a sasToken will be automatically generated.') +@secure() +param _artifactsLocationSasToken string = '' + +// Local variables +var resourceGroupNameFormatted = replace( + replace(replace(replace(resourceGroup().name, '.', '-'), '(', '-'), ')', '-'), + '_', + '-' +) +var sharePointSettings = { + isSharePointSubscription: (startsWith(sharePointVersion, 'subscription') ? true : false) + sharePointImagesList: { + Subscription: 'MicrosoftWindowsServer:WindowsServer:2022-datacenter-azure-edition-smalldisk:latest' + sp2019: 'MicrosoftSharePoint:MicrosoftSharePointServer:sp2019gen2smalldisk:latest' + sp2016: 'MicrosoftSharePoint:MicrosoftSharePointServer:sp2016:latest' + } + sharePointSubscriptionBits: [ + { + Label: 'RTM' + Packages: [ + { + DownloadUrl: 'https://download.microsoft.com/download/3/f/5/3f5f8a7e-462b-41ff-a5b2-04bdf5821ceb/OfficeServer.iso' + ChecksumType: 'SHA256' + Checksum: 'C576B847C573234B68FC602A0318F5794D7A61D8149EB6AE537AF04470B7FC05' + } + ] + } + { + Label: '22H2' + Packages: [ + { + DownloadUrl: 'https://download.microsoft.com/download/8/d/f/8dfcb515-6e49-42e5-b20f-5ebdfd19d8e7/wssloc-subscription-kb5002270-fullfile-x64-glb.exe' + ChecksumType: 'SHA256' + Checksum: '7E496530EB873146650A9E0653DE835CB2CAD9AF8D154CBD7387BB0F2297C9FC' + } + { + DownloadUrl: 'https://download.microsoft.com/download/3/f/5/3f5b1ee0-3336-45d7-b2f4-1e6af977d574/sts-subscription-kb5002271-fullfile-x64-glb.exe' + ChecksumType: 'SHA256' + Checksum: '247011443AC573D4F03B1622065A7350B8B3DAE04D6A5A6DC64C8270A3BE7636' + } + ] + } + { + Label: '23H1' + Packages: [ + { + DownloadUrl: 'https://download.microsoft.com/download/c/6/a/c6a17105-3d86-42ad-888d-49b22383bfa1/uber-subscription-kb5002355-fullfile-x64-glb.exe' + } + ] + } + { + Label: '23H2' + Packages: [ + { + DownloadUrl: 'https://download.microsoft.com/download/f/5/5/f5559e3f-8b24-419f-b238-b09cf986e927/uber-subscription-kb5002474-fullfile-x64-glb.exe' + } + ] + } + { + Label: '24H1' + Packages: [ + { + DownloadUrl: 'https://download.microsoft.com/download/b/a/b/bab0c7cc-0454-474b-8538-7927f75e6486/uber-subscription-kb5002564-fullfile-x64-glb.exe' + } + ] + } + { + Label: '24H2' + Packages: [ + { + DownloadUrl: 'https://download.microsoft.com/download/6/6/a/66a0057f-79af-4307-8263-103ee75ef5c6/uber-subscription-kb5002640-fullfile-x64-glb.exe' + } + ] + } + { + Label: 'Latest' + Packages: [ + { + DownloadUrl: 'https://download.microsoft.com/download/6/6/a/66a0057f-79af-4307-8263-103ee75ef5c6/uber-subscription-kb5002640-fullfile-x64-glb.exe' + } + ] + } + ] +} + +var networkSettings = { + vNetPrivatePrefix: '10.1.0.0/16' + subnetDCPrefix: '10.1.1.0/24' + dcPrivateIPAddress: '10.1.1.4' + subnetSQLPrefix: '10.1.2.0/24' + subnetSPPrefix: '10.1.3.0/24' + subnetDCName: 'vnet-subnet-dc' + subnetSQLName: 'vnet-subnet-sql' + subnetSPName: 'vnet-subnet-sp' + nsgRuleAllowIncomingRdp: [ + { + name: 'nsg-rule-allow-rdp' + properties: { + description: 'Allow RDP' + protocol: 'Tcp' + sourcePortRange: '*' + destinationPortRange: '3389' + sourceAddressPrefix: rdpTrafficRule + destinationAddressPrefix: '*' + access: 'Allow' + priority: 110 + direction: 'Inbound' + } + } + ] +} +var vmsSettings = { + enableAutomaticUpdates: true + vmDCName: 'DC' + vmSQLName: 'SQL' + vmSPName: 'SP' + vmFEName: 'FE' + vmDCImage: 'MicrosoftWindowsServer:WindowsServer:2022-datacenter-azure-edition-smalldisk:latest' + vmSQLImage: 'MicrosoftSQLServer:sql2022-ws2022:sqldev-gen2:latest' + vmSharePointImage: (sharePointSettings.isSharePointSubscription + ? sharePointSettings.sharePointImagesList.Subscription + : ((sharePointVersion == '2019') + ? sharePointSettings.sharePointImagesList.sp2019 + : sharePointSettings.sharePointImagesList.sp2016)) +} + +var dscSettings = { + forceUpdateTag: '1.0' + vmDCScriptFileUri: uri(_artifactsLocation, 'dsc/ConfigureDCVM.zip${_artifactsLocationSasToken}') + vmDCScript: 'ConfigureDCVM.ps1' + vmDCFunction: 'ConfigureDCVM' + vmSQLScriptFileUri: uri(_artifactsLocation, 'dsc/ConfigureSQLVM.zip${_artifactsLocationSasToken}') + vmSQLScript: 'ConfigureSQLVM.ps1' + vmSQLFunction: 'ConfigureSQLVM' + vmSPScriptFileUri: uri( + _artifactsLocation, + '${(sharePointSettings.isSharePointSubscription ? 'dsc/ConfigureSPSE.zip' : 'dsc/ConfigureSPLegacy.zip')}${_artifactsLocationSasToken}' + ) + vmSPScript: (sharePointSettings.isSharePointSubscription ? 'ConfigureSPSE.ps1' : 'ConfigureSPLegacy.ps1') + vmSPFunction: 'ConfigureSPVM' + vmFEScriptFileUri: uri( + _artifactsLocation, + '${(sharePointSettings.isSharePointSubscription ? 'dsc/ConfigureFESE.zip' : 'dsc/ConfigureFELegacy.zip')}${_artifactsLocationSasToken}' + ) + vmFEScript: (sharePointSettings.isSharePointSubscription ? 'ConfigureFESE.ps1' : 'ConfigureFELegacy.ps1') + vmFEFunction: 'ConfigureFEVM' +} + +var deploymentSettings = { + sharePointSitesAuthority: 'spsites' + sharePointCentralAdminPort: 5000 + sharePointBitsSelected: (sharePointSettings.isSharePointSubscription + ? sharePointSettings.sharePointSubscriptionBits + : '') + localAdminUserName: 'l-${uniqueString(subscription().subscriptionId)}' + enableAnalysis: false + applyBrowserPolicies: true + sqlAlias: 'SQLAlias' + spSuperUserName: 'spSuperUser' + spSuperReaderName: 'spSuperReader' + adfsSvcUserName: 'adfssvc' + sqlSvcUserName: 'sqlsvc' + spSetupUserName: 'spsetup' + spFarmUserName: 'spfarm' + spSvcUserName: 'spsvc' + spAppPoolUserName: 'spapppool' + spADDirSyncUserName: 'spdirsync' +} + +var firewall_proxy_settings = { + vNetAzureFirewallPrefix: '10.1.5.0/24' + azureFirewallIPAddress: '10.1.5.4' + http_port: 8080 + https_port: 8443 +} + +// Single-line PowerShell script that runs on the VMs to update their proxy settings, if Azure Firewall is enabled +var set_proxy_script = 'param([string]$proxyIp, [string]$proxyHttpPort, [string]$proxyHttpsPort, [string]$localDomainFqdn) $proxy = "http={0}:{1};https={0}:{2}" -f $proxyIp, $proxyHttpPort, $proxyHttpsPort; $bypasslist = "*.{0};" -f $localDomainFqdn; netsh winhttp set proxy proxy-server=$proxy bypass-list=$bypasslist; $proxyEnabled = 1; New-ItemProperty -Path "HKLM:\\SOFTWARE\\Policies\\Microsoft\\Windows\\CurrentVersion\\Internet Settings" -Name "ProxySettingsPerUser" -PropertyType DWORD -Value 0 -Force; $proxyBytes = [system.Text.Encoding]::ASCII.GetBytes($proxy); $bypassBytes = [system.Text.Encoding]::ASCII.GetBytes($bypasslist); $defaultConnectionSettings = [byte[]]@(@(70, 0, 0, 0, 0, 0, 0, 0, $proxyEnabled, 0, 0, 0, $proxyBytes.Length, 0, 0, 0) + $proxyBytes + @($bypassBytes.Length, 0, 0, 0) + $bypassBytes + @(1..36 | % { 0 })); $registryPaths = @("HKLM:\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", "HKLM:\\Software\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"); foreach ($registryPath in $registryPaths) { Set-ItemProperty -Path $registryPath -Name ProxyServer -Value $proxy; Set-ItemProperty -Path $registryPath -Name ProxyEnable -Value $proxyEnabled; Set-ItemProperty -Path $registryPath -Name ProxyOverride -Value $bypasslist; Set-ItemProperty -Path "$registryPath\\Connections" -Name DefaultConnectionSettings -Value $defaultConnectionSettings; } Bitsadmin /util /setieproxy localsystem MANUAL_PROXY $proxy $bypasslist;' + +// Start creating resources +// Network security groups for each subnet +resource nsg_subnet_dc 'Microsoft.Network/networkSecurityGroups@2023-11-01' = { + name: 'vnet-subnet-dc-nsg' + location: location + properties: { + securityRules: ((toLower(rdpTrafficRule) == 'no') ? null : networkSettings.nsgRuleAllowIncomingRdp) + } +} + +resource nsg_subnet_sql 'Microsoft.Network/networkSecurityGroups@2023-11-01' = { + name: 'vnet-subnet-sql-nsg' + location: location + properties: { + securityRules: ((toLower(rdpTrafficRule) == 'no') ? null : networkSettings.nsgRuleAllowIncomingRdp) + } +} + +resource nsg_subnet_sp 'Microsoft.Network/networkSecurityGroups@2023-11-01' = { + name: 'vnet-subnet-sp-nsg' + location: location + properties: { + securityRules: ((toLower(rdpTrafficRule) == 'no') ? null : networkSettings.nsgRuleAllowIncomingRdp) + } +} + +// Create the virtual network, 3 subnets, and associate each subnet with its Network Security Group +resource virtual_network 'Microsoft.Network/virtualNetworks@2023-11-01' = { + name: 'vnet-${uniqueString(resourceGroup().id)}' + location: location + properties: { + addressSpace: { + addressPrefixes: [ + networkSettings.vNetPrivatePrefix + ] + } + subnets: [ + { + name: networkSettings.subnetDCName + properties: { + defaultOutboundAccess: false + addressPrefix: networkSettings.subnetDCPrefix + networkSecurityGroup: { + id: nsg_subnet_dc.id + } + } + } + { + name: networkSettings.subnetSQLName + properties: { + defaultOutboundAccess: false + addressPrefix: networkSettings.subnetSQLPrefix + networkSecurityGroup: { + id: nsg_subnet_sql.id + } + } + } + { + name: networkSettings.subnetSPName + properties: { + defaultOutboundAccess: false + addressPrefix: networkSettings.subnetSPPrefix + networkSecurityGroup: { + id: nsg_subnet_sp.id + } + } + } + ] + } +} + +// Create resources for VM DC +resource vm_dc_pip 'Microsoft.Network/publicIPAddresses@2023-11-01' = if (outboundAccessMethod == 'PublicIPAddress') { + name: 'vm-dc-pip' + location: location + sku: { + name: 'Standard' + tier: 'Regional' + } + properties: { + publicIPAllocationMethod: 'Static' + dnsSettings: { + domainNameLabel: toLower('${resourceGroupNameFormatted}-${vmsSettings.vmDCName}') + } + } +} + +resource vm_dc_nic 'Microsoft.Network/networkInterfaces@2023-11-01' = { + name: 'vm-dc-nic' + location: location + properties: { + ipConfigurations: [ + { + name: 'ipconfig1' + properties: { + privateIPAllocationMethod: 'Static' + privateIPAddress: networkSettings.dcPrivateIPAddress + subnet: { + id: resourceId( + 'Microsoft.Network/virtualNetworks/subnets', + virtual_network.name, + networkSettings.subnetDCName + ) + } + publicIPAddress: ((outboundAccessMethod == 'PublicIPAddress') ? { id: vm_dc_pip.id } : null) + } + } + ] + } +} + +resource vm_dc_def 'Microsoft.Compute/virtualMachines@2024-07-01' = { + name: 'vm-dc' + location: location + properties: { + hardwareProfile: { + vmSize: vmDcSize + } + osProfile: { + computerName: vmsSettings.vmDCName + adminUsername: adminUsername + adminPassword: adminPassword + windowsConfiguration: { + timeZone: timeZone + enableAutomaticUpdates: vmsSettings.enableAutomaticUpdates + provisionVMAgent: true + patchSettings: { + patchMode: (vmsSettings.enableAutomaticUpdates ? 'AutomaticByOS' : 'Manual') + assessmentMode: 'ImageDefault' + } + } + } + storageProfile: { + imageReference: { + publisher: split(vmsSettings.vmDCImage, ':')[0] + offer: split(vmsSettings.vmDCImage, ':')[1] + sku: split(vmsSettings.vmDCImage, ':')[2] + version: split(vmsSettings.vmDCImage, ':')[3] + } + osDisk: { + name: 'vm-dc-disk-os' + caching: 'ReadWrite' + osType: 'Windows' + createOption: 'FromImage' + diskSizeGB: 32 + managedDisk: { + storageAccountType: vmDcStorage + } + } + } + networkProfile: { + networkInterfaces: [ + { + id: vm_dc_nic.id + } + ] + } + licenseType: (enableHybridBenefitServerLicenses ? 'Windows_Server' : null) + } +} + +resource vm_dc_runcommand_setproxy 'Microsoft.Compute/virtualMachines/runCommands@2024-07-01' = if (outboundAccessMethod == 'AzureFirewallProxy') { + parent: vm_dc_def + name: 'runcommand-setproxy' + location: location + properties: { + source: { + script: set_proxy_script + } + parameters: [ + { + name: 'proxyIp' + value: firewall_proxy_settings.azureFirewallIPAddress + } + { + name: 'proxyHttpPort' + value: string(firewall_proxy_settings.http_port) + } + { + name: 'proxyHttpsPort' + value: firewall_proxy_settings.https_port + } + { + name: 'localDomainFqdn' + value: domainFqdn + } + ] + timeoutInSeconds: 90 + treatFailureAsDeploymentFailure: false + } +} + +resource vm_dc_ext_applydsc 'Microsoft.Compute/virtualMachines/extensions@2024-07-01' = { + parent: vm_dc_def + name: 'apply-dsc' + location: location + dependsOn: [ + vm_dc_runcommand_setproxy + ] + properties: { + publisher: 'Microsoft.Powershell' + type: 'DSC' + typeHandlerVersion: '2.9' + autoUpgradeMinorVersion: true + forceUpdateTag: dscSettings.forceUpdateTag + settings: { + wmfVersion: 'latest' + configuration: { + url: dscSettings.vmDCScriptFileUri + script: dscSettings.vmDCScript + function: dscSettings.vmDCFunction + } + configurationArguments: { + domainFQDN: domainFqdn + PrivateIP: networkSettings.dcPrivateIPAddress + SPServerName: vmsSettings.vmSPName + SharePointSitesAuthority: deploymentSettings.sharePointSitesAuthority + SharePointCentralAdminPort: deploymentSettings.sharePointCentralAdminPort + ApplyBrowserPolicies: deploymentSettings.applyBrowserPolicies + } + privacy: { + dataCollection: 'enable' + } + } + protectedSettings: { + configurationArguments: { + AdminCreds: { + UserName: adminUsername + Password: adminPassword + } + AdfsSvcCreds: { + UserName: deploymentSettings.adfsSvcUserName + Password: otherAccountsPassword + } + } + } + } +} + +resource vm_dc_autoshutdown 'Microsoft.DevTestLab/schedules@2018-09-15' = if (autoShutdownTime != '9999') { + name: 'shutdown-computevm-${vm_dc_def.name}' + location: location + properties: { + targetResourceId: vm_dc_def.id + status: 'Enabled' + taskType: 'ComputeVmShutdownTask' + timeZoneId: timeZone + dailyRecurrence: { + time: autoShutdownTime + } + } +} + +// Create resources for VM SQL +resource vm_sql_pip 'Microsoft.Network/publicIPAddresses@2023-11-01' = if (outboundAccessMethod == 'PublicIPAddress') { + name: 'vm-sql-pip' + location: location + sku: { + name: 'Standard' + tier: 'Regional' + } + properties: { + publicIPAllocationMethod: 'Static' + dnsSettings: { + domainNameLabel: toLower('${resourceGroupNameFormatted}-${vmsSettings.vmSQLName}') + } + } +} + +resource vm_sql_nic 'Microsoft.Network/networkInterfaces@2023-11-01' = { + name: 'vm-sql-nic' + location: location + properties: { + ipConfigurations: [ + { + name: 'ipconfig1' + properties: { + privateIPAllocationMethod: 'Dynamic' + subnet: { + id: resourceId( + 'Microsoft.Network/virtualNetworks/subnets', + virtual_network.name, + networkSettings.subnetSQLName + ) + } + publicIPAddress: ((outboundAccessMethod == 'PublicIPAddress') ? { id: vm_sql_pip.id } : null) + } + } + ] + } +} + +resource vm_sql_def 'Microsoft.Compute/virtualMachines@2024-07-01' = { + name: 'vm-sql' + location: location + properties: { + hardwareProfile: { + vmSize: vmSqlSize + } + osProfile: { + computerName: vmsSettings.vmSQLName + adminUsername: deploymentSettings.localAdminUserName + adminPassword: adminPassword + windowsConfiguration: { + timeZone: timeZone + enableAutomaticUpdates: vmsSettings.enableAutomaticUpdates + provisionVMAgent: true + patchSettings: { + patchMode: (vmsSettings.enableAutomaticUpdates ? 'AutomaticByOS' : 'Manual') + assessmentMode: 'ImageDefault' + } + } + } + storageProfile: { + imageReference: { + publisher: split(vmsSettings.vmSQLImage, ':')[0] + offer: split(vmsSettings.vmSQLImage, ':')[1] + sku: split(vmsSettings.vmSQLImage, ':')[2] + version: split(vmsSettings.vmSQLImage, ':')[3] + } + osDisk: { + name: 'vm-sql-disk-os' + caching: 'ReadWrite' + osType: 'Windows' + createOption: 'FromImage' + diskSizeGB: 128 + managedDisk: { + storageAccountType: vmSqlStorage + } + } + } + networkProfile: { + networkInterfaces: [ + { + id: vm_sql_nic.id + } + ] + } + licenseType: (enableHybridBenefitServerLicenses ? 'Windows_Server' : null) + } +} + +resource vm_sql_runcommand_setproxy 'Microsoft.Compute/virtualMachines/runCommands@2024-07-01' = if (outboundAccessMethod == 'AzureFirewallProxy') { + parent: vm_sql_def + name: 'runcommand-setproxy' + location: location + properties: { + source: { + script: set_proxy_script + } + parameters: [ + { + name: 'proxyIp' + value: firewall_proxy_settings.azureFirewallIPAddress + } + { + name: 'proxyHttpPort' + value: string(firewall_proxy_settings.http_port) + } + { + name: 'proxyHttpsPort' + value: firewall_proxy_settings.https_port + } + { + name: 'localDomainFqdn' + value: domainFqdn + } + ] + timeoutInSeconds: 90 + treatFailureAsDeploymentFailure: false + } +} + +resource vm_sql_ext_applydsc 'Microsoft.Compute/virtualMachines/extensions@2024-07-01' = { + parent: vm_sql_def + name: 'apply-dsc' + location: location + dependsOn: [ + vm_sql_runcommand_setproxy + ] + properties: { + publisher: 'Microsoft.Powershell' + type: 'DSC' + typeHandlerVersion: '2.9' + autoUpgradeMinorVersion: true + forceUpdateTag: dscSettings.forceUpdateTag + settings: { + wmfVersion: 'latest' + configuration: { + url: dscSettings.vmSQLScriptFileUri + script: dscSettings.vmSQLScript + function: dscSettings.vmSQLFunction + } + configurationArguments: { + DNSServerIP: networkSettings.dcPrivateIPAddress + DomainFQDN: domainFqdn + } + privacy: { + dataCollection: 'enable' + } + } + protectedSettings: { + configurationArguments: { + DomainAdminCreds: { + UserName: adminUsername + Password: adminPassword + } + SqlSvcCreds: { + UserName: deploymentSettings.sqlSvcUserName + Password: otherAccountsPassword + } + SPSetupCreds: { + UserName: deploymentSettings.spSetupUserName + Password: otherAccountsPassword + } + } + } + } +} + +resource vm_sql_autoshutdown 'Microsoft.DevTestLab/schedules@2018-09-15' = if (autoShutdownTime != '9999') { + name: 'shutdown-computevm-${vm_sql_def.name}' + location: location + properties: { + targetResourceId: vm_sql_def.id + status: 'Enabled' + taskType: 'ComputeVmShutdownTask' + timeZoneId: timeZone + dailyRecurrence: { + time: autoShutdownTime + } + } +} + +// Create resources for VM SP +resource vm_sp_pip 'Microsoft.Network/publicIPAddresses@2023-11-01' = if (outboundAccessMethod == 'PublicIPAddress') { + name: 'vm-sp-pip' + location: location + sku: { + name: 'Standard' + tier: 'Regional' + } + properties: { + publicIPAllocationMethod: 'Static' + dnsSettings: { + domainNameLabel: toLower('${resourceGroupNameFormatted}-${vmsSettings.vmSPName}') + } + } +} + +resource vm_sp_nic 'Microsoft.Network/networkInterfaces@2023-11-01' = { + name: 'vm-sp-nic' + location: location + properties: { + ipConfigurations: [ + { + name: 'ipconfig1' + properties: { + privateIPAllocationMethod: 'Dynamic' + subnet: { + id: resourceId( + 'Microsoft.Network/virtualNetworks/subnets', + virtual_network.name, + networkSettings.subnetSPName + ) + } + publicIPAddress: ((outboundAccessMethod == 'PublicIPAddress') ? { id: vm_sp_pip.id } : null) + } + } + ] + } +} + +resource vm_sp_def 'Microsoft.Compute/virtualMachines@2024-07-01' = { + name: 'vm-sp' + location: location + properties: { + hardwareProfile: { + vmSize: vmSharePointSize + } + osProfile: { + computerName: vmsSettings.vmSPName + adminUsername: deploymentSettings.localAdminUserName + adminPassword: adminPassword + windowsConfiguration: { + timeZone: timeZone + enableAutomaticUpdates: vmsSettings.enableAutomaticUpdates + provisionVMAgent: true + patchSettings: { + patchMode: (vmsSettings.enableAutomaticUpdates ? 'AutomaticByOS' : 'Manual') + assessmentMode: 'ImageDefault' + } + } + } + storageProfile: { + imageReference: { + publisher: split(vmsSettings.vmSharePointImage, ':')[0] + offer: split(vmsSettings.vmSharePointImage, ':')[1] + sku: split(vmsSettings.vmSharePointImage, ':')[2] + version: split(vmsSettings.vmSharePointImage, ':')[3] + } + osDisk: { + name: 'vm-sp-disk-os' + caching: 'ReadWrite' + osType: 'Windows' + createOption: 'FromImage' + managedDisk: { + storageAccountType: vmSharePointStorage + } + } + } + networkProfile: { + networkInterfaces: [ + { + id: vm_sp_nic.id + } + ] + } + licenseType: (enableHybridBenefitServerLicenses ? 'Windows_Server' : null) + } +} + +resource vm_sp_runcommand_setproxy 'Microsoft.Compute/virtualMachines/runCommands@2024-07-01' = if (outboundAccessMethod == 'AzureFirewallProxy') { + parent: vm_sp_def + name: 'runcommand-setproxy' + location: location + properties: { + source: { + script: set_proxy_script + } + parameters: [ + { + name: 'proxyIp' + value: firewall_proxy_settings.azureFirewallIPAddress + } + { + name: 'proxyHttpPort' + value: string(firewall_proxy_settings.http_port) + } + { + name: 'proxyHttpsPort' + value: firewall_proxy_settings.https_port + } + { + name: 'localDomainFqdn' + value: domainFqdn + } + ] + timeoutInSeconds: 90 + treatFailureAsDeploymentFailure: false + } +} + +resource vm_sp_runcommand_increase_dsc_quota 'Microsoft.Compute/virtualMachines/runCommands@2023-03-01' = { + parent: vm_sp_def + name: 'runcommand-increase-dsc-quota' + location: location + properties: { + source: { + script: 'Set-Item -Path WSMan:\\localhost\\MaxEnvelopeSizeKb -Value 2048' + } + timeoutInSeconds: 90 + treatFailureAsDeploymentFailure: false + } +} + +resource vm_sp_ext_applydsc 'Microsoft.Compute/virtualMachines/extensions@2024-07-01' = { + parent: vm_sp_def + name: 'apply-dsc' + location: location + dependsOn: [ + vm_sp_runcommand_setproxy + vm_sp_runcommand_increase_dsc_quota + ] + properties: { + publisher: 'Microsoft.Powershell' + type: 'DSC' + typeHandlerVersion: '2.9' + autoUpgradeMinorVersion: true + forceUpdateTag: dscSettings.forceUpdateTag + settings: { + wmfVersion: 'latest' + configuration: { + url: dscSettings.vmSPScriptFileUri + script: dscSettings.vmSPScript + function: dscSettings.vmSPFunction + } + configurationArguments: { + DNSServerIP: networkSettings.dcPrivateIPAddress + DomainFQDN: domainFqdn + DCServerName: vmsSettings.vmDCName + SQLServerName: vmsSettings.vmSQLName + SQLAlias: deploymentSettings.sqlAlias + SharePointVersion: sharePointVersion + SharePointSitesAuthority: deploymentSettings.sharePointSitesAuthority + SharePointCentralAdminPort: deploymentSettings.sharePointCentralAdminPort + EnableAnalysis: deploymentSettings.enableAnalysis + SharePointBits: deploymentSettings.sharePointBitsSelected + } + privacy: { + dataCollection: 'enable' + } + } + protectedSettings: { + configurationArguments: { + DomainAdminCreds: { + UserName: adminUsername + Password: adminPassword + } + SPSetupCreds: { + UserName: deploymentSettings.spSetupUserName + Password: otherAccountsPassword + } + SPFarmCreds: { + UserName: deploymentSettings.spFarmUserName + Password: otherAccountsPassword + } + SPSvcCreds: { + UserName: deploymentSettings.spSvcUserName + Password: otherAccountsPassword + } + SPAppPoolCreds: { + UserName: deploymentSettings.spAppPoolUserName + Password: otherAccountsPassword + } + SPADDirSyncCreds: { + UserName: deploymentSettings.spADDirSyncUserName + Password: otherAccountsPassword + } + SPPassphraseCreds: { + UserName: 'Passphrase' + Password: otherAccountsPassword + } + SPSuperUserCreds: { + UserName: deploymentSettings.spSuperUserName + Password: otherAccountsPassword + } + SPSuperReaderCreds: { + UserName: deploymentSettings.spSuperReaderName + Password: otherAccountsPassword + } + } + } + } +} + +resource vm_sp_autoshutdown 'Microsoft.DevTestLab/schedules@2018-09-15' = if (autoShutdownTime != '9999') { + name: 'shutdown-computevm-${vm_sp_def.name}' + location: location + properties: { + targetResourceId: vm_sp_def.id + status: 'Enabled' + taskType: 'ComputeVmShutdownTask' + timeZoneId: timeZone + dailyRecurrence: { + time: autoShutdownTime + } + } +} + +// Create resources for VMs FEs +resource vm_fe_pip 'Microsoft.Network/publicIPAddresses@2023-11-01' = [ + for i in range(0, frontEndServersCount): if (frontEndServersCount >= 1 && outboundAccessMethod == 'PublicIPAddress') { + name: 'vm-fe${i}-pip' + location: location + sku: { + name: 'Basic' + tier: 'Regional' + } + properties: { + publicIPAllocationMethod: 'Static' + dnsSettings: { + domainNameLabel: '${toLower('${resourceGroupNameFormatted}-${vmsSettings.vmFEName}')}-${i}' + } + } + } +] + +resource vm_fe_nic 'Microsoft.Network/networkInterfaces@2023-11-01' = [ + for i in range(0, frontEndServersCount): if (frontEndServersCount >= 1) { + name: 'vm-fe${i}-nic' + location: location + properties: { + ipConfigurations: [ + { + name: 'ipconfig1' + properties: { + privateIPAllocationMethod: 'Dynamic' + subnet: { + id: resourceId( + 'Microsoft.Network/virtualNetworks/subnets', + virtual_network.name, + networkSettings.subnetSPName + ) + } + publicIPAddress: (outboundAccessMethod == 'PublicIPAddress' ? json('{"id": "${vm_fe_pip[i].id}"}') : null) + } + } + ] + } + dependsOn: [ + vm_fe_pip[i] + ] + } +] + +resource vm_fe_def 'Microsoft.Compute/virtualMachines@2024-07-01' = [ + for i in range(0, frontEndServersCount): if (frontEndServersCount >= 1) { + name: 'vm-fe${i}' + location: location + dependsOn: [ + vm_fe_nic[i] + ] + properties: { + hardwareProfile: { + vmSize: vmSharePointSize + } + osProfile: { + computerName: '${vmsSettings.vmFEName}-${i}' + adminUsername: deploymentSettings.localAdminUserName + adminPassword: adminPassword + windowsConfiguration: { + timeZone: timeZone + enableAutomaticUpdates: vmsSettings.enableAutomaticUpdates + provisionVMAgent: true + patchSettings: { + patchMode: (vmsSettings.enableAutomaticUpdates ? 'AutomaticByOS' : 'Manual') + assessmentMode: 'ImageDefault' + } + } + } + storageProfile: { + imageReference: { + publisher: split(vmsSettings.vmSharePointImage, ':')[0] + offer: split(vmsSettings.vmSharePointImage, ':')[1] + sku: split(vmsSettings.vmSharePointImage, ':')[2] + version: split(vmsSettings.vmSharePointImage, ':')[3] + } + osDisk: { + name: 'vm-fe${i}-disk-os' + caching: 'ReadWrite' + osType: 'Windows' + createOption: 'FromImage' + managedDisk: { + storageAccountType: vmSharePointStorage + } + } + } + networkProfile: { + networkInterfaces: [ + { + id: vm_fe_nic[i].id + } + ] + } + licenseType: (enableHybridBenefitServerLicenses ? 'Windows_Server' : null) + } + } +] + +resource vm_fe_runcommand_setproxy 'Microsoft.Compute/virtualMachines/runCommands@2024-07-01' = [ + for i in range(0, frontEndServersCount): if (frontEndServersCount >= 1 && outboundAccessMethod == 'AzureFirewallProxy') { + parent: vm_fe_def[i] + name: 'runcommand-setproxy' + location: location + properties: { + source: { + script: set_proxy_script + } + parameters: [ + { + name: 'proxyIp' + value: firewall_proxy_settings.azureFirewallIPAddress + } + { + name: 'proxyHttpPort' + value: string(firewall_proxy_settings.http_port) + } + { + name: 'proxyHttpsPort' + value: firewall_proxy_settings.https_port + } + { + name: 'localDomainFqdn' + value: domainFqdn + } + ] + timeoutInSeconds: 90 + treatFailureAsDeploymentFailure: false + } + } +] + +resource vm_fe_ext_applydsc 'Microsoft.Compute/virtualMachines/extensions@2024-07-01' = [ + for i in range(0, frontEndServersCount): if (frontEndServersCount >= 1) { + parent: vm_fe_def[i] + name: 'apply-dsc' + location: location + dependsOn: [ + vm_fe_runcommand_setproxy[i] + ] + properties: { + publisher: 'Microsoft.Powershell' + type: 'DSC' + typeHandlerVersion: '2.9' + autoUpgradeMinorVersion: true + forceUpdateTag: dscSettings.forceUpdateTag + settings: { + wmfVersion: 'latest' + configuration: { + url: dscSettings.vmFEScriptFileUri + script: dscSettings.vmFEScript + function: dscSettings.vmFEFunction + } + configurationArguments: { + DNSServerIP: networkSettings.dcPrivateIPAddress + DomainFQDN: domainFqdn + DCServerName: vmsSettings.vmDCName + SQLServerName: vmsSettings.vmSQLName + SQLAlias: deploymentSettings.sqlAlias + SharePointVersion: sharePointVersion + SharePointSitesAuthority: deploymentSettings.sharePointSitesAuthority + EnableAnalysis: deploymentSettings.enableAnalysis + SharePointBits: deploymentSettings.sharePointBitsSelected + } + privacy: { + dataCollection: 'enable' + } + } + protectedSettings: { + configurationArguments: { + DomainAdminCreds: { + UserName: adminUsername + Password: adminPassword + } + SPSetupCreds: { + UserName: deploymentSettings.spSetupUserName + Password: otherAccountsPassword + } + SPFarmCreds: { + UserName: deploymentSettings.spFarmUserName + Password: otherAccountsPassword + } + SPPassphraseCreds: { + UserName: 'Passphrase' + Password: otherAccountsPassword + } + } + } + } + } +] + +resource vm_fe_autoshutdown 'Microsoft.DevTestLab/schedules@2018-09-15' = [ + for i in range(0, frontEndServersCount): if (frontEndServersCount >= 1 && autoShutdownTime != '9999') { + name: 'shutdown-computevm-${vm_fe_def[i].name}' + location: location + properties: { + targetResourceId: vm_fe_def[i].id + status: 'Enabled' + taskType: 'ComputeVmShutdownTask' + timeZoneId: timeZone + dailyRecurrence: { + time: autoShutdownTime + } + } + } +] + +// Resources for Azure Bastion +resource bastion_subnet_nsg 'Microsoft.Network/networkSecurityGroups@2023-11-01' = if (enableAzureBastion == true) { + name: 'bastion-subnet-nsg' + location: location + properties: { + securityRules: [ + { + name: 'AllowHttpsInBound' + properties: { + protocol: 'Tcp' + sourcePortRange: '*' + sourceAddressPrefix: 'Internet' + destinationPortRange: '443' + destinationAddressPrefix: '*' + access: 'Allow' + priority: 100 + direction: 'Inbound' + } + } + { + name: 'AllowGatewayManagerInBound' + properties: { + protocol: 'Tcp' + sourcePortRange: '*' + sourceAddressPrefix: 'GatewayManager' + destinationPortRange: '443' + destinationAddressPrefix: '*' + access: 'Allow' + priority: 110 + direction: 'Inbound' + } + } + { + name: 'AllowLoadBalancerInBound' + properties: { + protocol: 'Tcp' + sourcePortRange: '*' + sourceAddressPrefix: 'AzureLoadBalancer' + destinationPortRange: '443' + destinationAddressPrefix: '*' + access: 'Allow' + priority: 120 + direction: 'Inbound' + } + } + { + name: 'AllowBastionHostCommunicationInBound' + properties: { + protocol: '*' + sourcePortRange: '*' + sourceAddressPrefix: 'VirtualNetwork' + destinationPortRanges: [ + '8080' + '5701' + ] + destinationAddressPrefix: 'VirtualNetwork' + access: 'Allow' + priority: 130 + direction: 'Inbound' + } + } + { + name: 'DenyAllInBound' + properties: { + protocol: '*' + sourcePortRange: '*' + sourceAddressPrefix: '*' + destinationPortRange: '*' + destinationAddressPrefix: '*' + access: 'Deny' + priority: 1000 + direction: 'Inbound' + } + } + { + name: 'AllowSshRdpOutBound' + properties: { + protocol: 'Tcp' + sourcePortRange: '*' + sourceAddressPrefix: '*' + destinationPortRanges: [ + '22' + '3389' + ] + destinationAddressPrefix: 'VirtualNetwork' + access: 'Allow' + priority: 100 + direction: 'Outbound' + } + } + { + name: 'AllowAzureCloudCommunicationOutBound' + properties: { + protocol: 'Tcp' + sourcePortRange: '*' + sourceAddressPrefix: '*' + destinationPortRange: '443' + destinationAddressPrefix: 'AzureCloud' + access: 'Allow' + priority: 110 + direction: 'Outbound' + } + } + { + name: 'AllowBastionHostCommunicationOutBound' + properties: { + protocol: '*' + sourcePortRange: '*' + sourceAddressPrefix: 'VirtualNetwork' + destinationPortRanges: [ + '8080' + '5701' + ] + destinationAddressPrefix: 'VirtualNetwork' + access: 'Allow' + priority: 120 + direction: 'Outbound' + } + } + { + name: 'AllowGetSessionInformationOutBound' + properties: { + protocol: '*' + sourcePortRange: '*' + sourceAddressPrefix: '*' + destinationAddressPrefix: 'Internet' + destinationPortRanges: [ + '80' + '443' + ] + access: 'Allow' + priority: 130 + direction: 'Outbound' + } + } + { + name: 'DenyAllOutBound' + properties: { + protocol: '*' + sourcePortRange: '*' + destinationPortRange: '*' + sourceAddressPrefix: '*' + destinationAddressPrefix: '*' + access: 'Deny' + priority: 1000 + direction: 'Outbound' + } + } + ] + } +} + +resource bastion_subnet 'Microsoft.Network/virtualNetworks/subnets@2023-11-01' = if (enableAzureBastion == true) { + parent: virtual_network + name: 'AzureBastionSubnet' + properties: { + addressPrefix: '10.1.4.0/24' + networkSecurityGroup: { + id: bastion_subnet_nsg.id + } + } +} + +resource bastion_pip 'Microsoft.Network/publicIPAddresses@2023-11-01' = if (enableAzureBastion == true) { + name: 'bastion-pip' + location: location + sku: { + name: 'Standard' + tier: 'Regional' + } + properties: { + publicIPAllocationMethod: 'Static' + dnsSettings: { + domainNameLabel: toLower(replace('${resourceGroupNameFormatted}-Bastion', '_', '-')) + } + } +} + +resource bastion_def 'Microsoft.Network/bastionHosts@2023-11-01' = if (enableAzureBastion == true) { + name: 'bastion' + location: location + properties: { + ipConfigurations: [ + { + name: 'IpConf' + properties: { + privateIPAllocationMethod: 'Dynamic' + publicIPAddress: { + id: bastion_pip.id + } + subnet: { + id: bastion_subnet.id + } + } + } + ] + } +} + +// Resources for Azure Firewall +resource firewall_subnet 'Microsoft.Network/virtualNetworks/subnets@2023-11-01' = if (outboundAccessMethod == 'AzureFirewallProxy') { + parent: virtual_network + name: 'AzureFirewallSubnet' + properties: { + addressPrefix: firewall_proxy_settings.vNetAzureFirewallPrefix + defaultOutboundAccess: false + } +} + +resource firewall_pip 'Microsoft.Network/publicIPAddresses@2023-11-01' = if (outboundAccessMethod == 'AzureFirewallProxy') { + name: 'firewall-pip' + location: location + sku: { + name: 'Standard' + tier: 'Regional' + } + properties: { + publicIPAllocationMethod: 'Static' + dnsSettings: { + domainNameLabel: toLower('${resourceGroupNameFormatted}-Firewall') + } + } +} + +resource firewall_policy_proxy 'Microsoft.Network/firewallPolicies@2023-11-01' = if (outboundAccessMethod == 'AzureFirewallProxy') { + name: 'firewall-policy-proxy' + location: location + properties: { + sku: { + tier: 'Standard' + } + threatIntelMode: 'Alert' + explicitProxy: { + enableExplicitProxy: true + httpPort: firewall_proxy_settings.http_port + httpsPort: firewall_proxy_settings.https_port + enablePacFile: false + } + } +} + +resource firewall_proxy_rules 'Microsoft.Network/firewallPolicies/ruleCollectionGroups@2023-11-01' = if (outboundAccessMethod == 'AzureFirewallProxy') { + name: 'rules' + parent: firewall_policy_proxy + properties: { + priority: 100 + ruleCollections: [ + { + name: 'proxy-allow-all-outbound' + ruleCollectionType: 'FirewallPolicyFilterRuleCollection' + action: { + type: 'Allow' + } + priority: 100 + rules: [ + { + ruleType: 'ApplicationRule' + sourceAddresses: [ + '*' + ] + targetFqdns: [ + '*' + ] + protocols: [ + { + port: 443 + protocolType: 'Https' + } + { + port: 80 + protocolType: 'Http' + } + ] + } + ] + } + ] + } +} + +resource firewall_def 'Microsoft.Network/azureFirewalls@2023-11-01' = if (outboundAccessMethod == 'AzureFirewallProxy') { + name: 'firewall' + location: location + properties: { + ipConfigurations: [ + { + name: 'IpConf' + properties: { + subnet: { + id: firewall_subnet.id + } + publicIPAddress: { + id: firewall_pip.id + } + } + } + ] + firewallPolicy: { + id: firewall_policy_proxy.id + } + sku: { + name: 'AZFW_VNet' + tier: 'Standard' + } + threatIntelMode: 'Alert' + } +} + +output publicIPAddressDC string = outboundAccessMethod == 'PublicIPAddress' + ? vm_dc_pip.properties.dnsSettings.fqdn + : '' +output publicIPAddressSQL string = outboundAccessMethod == 'PublicIPAddress' + ? vm_sql_pip.properties.dnsSettings.fqdn + : '' +output publicIPAddressSP string = outboundAccessMethod == 'PublicIPAddress' + ? vm_sp_pip.properties.dnsSettings.fqdn + : '' +output vm_fe_public_dns array = [ + for i in range(0, frontEndServersCount): (outboundAccessMethod == 'PublicIPAddress') + ? vm_fe_pip[i].properties.dnsSettings.fqdn + : null +] +output domainAdminAccount string = '${substring(domainFqdn,0,indexOf(domainFqdn,'.'))}\\${adminUsername}' +output domainAdminAccountFormatForBastion string = '${adminUsername}@${domainFqdn}' +output localAdminAccount string = deploymentSettings.localAdminUserName diff --git a/Templates/SharePoint-ADFS/metadata.json b/Templates/SharePoint-ADFS/metadata.json index 390ee902..6fa7fb47 100644 --- a/Templates/SharePoint-ADFS/metadata.json +++ b/Templates/SharePoint-ADFS/metadata.json @@ -1,9 +1,9 @@ { "$schema": "https://aka.ms/azure-quickstart-templates-metadata-schema#", "type": "QuickStart", - "itemDisplayName": "SharePoint Subscription / 2019 / 2016 all configured", - "description": "This template creates a SharePoint Subscription / 2019 / 2016 farm with an extensive configuration that would take ages to perform manually, including a federated authentication with ADFS, an OAuth trust, the User Profiles service and a web application with 2 zones that contains multiple path based and host-named site collections. On the SharePoint virtual machines, Chocolatey is used to install the latest version of Notepad++, Visual Studio Code, Azure Data Studio, Fiddler, ULS Viewer and 7-Zip.", - "summary": "Create a SharePoint Server farm with an extensive configuration that would take ages to perform manually, and install useful softwares like Fiddler, vscode, np++, 7zip and ULS Viewer", + "itemDisplayName": "SharePoint Subscription / 2019 / 2016 fully configured", + "description": "Create a DC, a SQL Server 2022, and from 1 to 5 server(s) hosting a SharePoint Subscription / 2019 / 2016 farm with an extensive configuration, including trusted authentication, user profiles with personal sites, an OAuth trust (using a certificate), a dedicated IIS site for hosting high-trust add-ins, etc... The latest version of key softwares (including Fiddler, vscode, np++, 7zip, ULS Viewer) is installed. SharePoint machines have additional fine-tuning to make them immediately usable (remote administration tools, custom policies for Edge and Chrome, shortcuts, etc...).", + "summary": "Create a SharePoint Server farm with an extensive configuration. Key softwares (inc. Fiddler, vscode, np++, 7zip and ULS Viewer) and fine tuning make the farm immediately useful for most scenarios", "githubUsername": "Yvand", - "dateUpdated": "2024-02-26" + "dateUpdated": "2024-09-11" } \ No newline at end of file