├── Azure-Automation-Demo ├── terraform.tfvars ├── variables.tf ├── provider.tf ├── PowerShell │ └── power_off_vm.ps1 ├── readme.md ├── .gitignore └── azuredeploy.tf ├── Azure-Backup-Demo-Resources ├── terraform.tfvars ├── variables.tf ├── readme.md ├── provider.tf ├── VM.tf ├── .gitignore └── FileShare.tf ├── Azure Lab Services ├── terraform.tfvars ├── readme.md ├── variables.tf ├── provider.tf ├── .gitignore ├── keyvault.tf └── lab.tf ├── PowerShell ├── readme.md ├── baselab_DomainSetup.ps1 ├── standard_VMSetup.ps1 ├── webserver_VMSetup.ps1 ├── baselab_LabStructure.ps1 ├── baselab_DCSetup.ps1 └── baselabv2_VMSetup.ps1 ├── Dual-Region-Azure-BaseLab ├── PowerShell │ ├── DC2 │ │ ├── baselab_DC2JoinDomain.ps1 │ │ ├── baselab_DC2Promote.ps1 │ │ └── baselab_DCSetup2.ps1 │ └── DC1 │ │ ├── baselab_DomainSetup.ps1 │ │ ├── baselab_LabStructure.ps1 │ │ └── baselab_DCSetup1.ps1 ├── provider.tf ├── .gitignore ├── terraform.tfvars └── README.md ├── Azure-NetApp-Files-CRR-BaseLab ├── PowerShell │ ├── DC2 │ │ ├── baselab_DC2JoinDomain.ps1 │ │ ├── baselab_DC2Promote.ps1 │ │ └── baselab_DCSetup2.ps1 │ └── DC1 │ │ ├── baselab_DomainSetup.ps1 │ │ ├── baselab_LabStructure.ps1 │ │ └── baselab_DCSetup1.ps1 ├── provider.tf ├── .gitignore ├── terraform.tfvars └── README.md ├── Virtual-WAN-Demo ├── images │ ├── Virtual-WAN.png │ ├── Virtual-WAN - Full-Size.png │ ├── Virtual-WAN-with-Firewall.png │ └── Virtual-WAN-with-Firewall - Full-Size.png ├── provider.tf ├── resourcegroups.tf ├── terraform.tfvars ├── .gitignore ├── keyvault.tf ├── bastion.tf ├── variables.tf ├── README.md ├── vwan.tf ├── firewall.tf └── networks.tf ├── CIDRHost-Demo ├── terraform.tfvars ├── variables.tf ├── provider.tf ├── .gitignore └── readme.md ├── CIDRSubnet-Demo ├── terraform.tfvars ├── variables.tf ├── provider.tf ├── .gitignore ├── azuredeploy.tf └── readme.md ├── GitHub-Actions-Deployment ├── images │ ├── Actions1.png │ ├── Actions2.png │ ├── Actions3.png │ ├── Actions4.png │ ├── Actions5.png │ ├── GitHubSecrets.png │ └── ScriptOutputSample.png └── scripts │ └── AzCLIPreReqSetup ├── Terraform-Cloud-Deployment ├── scripts │ └── ServicePrincipalSetup └── readme.md ├── Automatic-ClientIP-NSG ├── terraform.tfvars ├── variables.tf ├── provider.tf ├── .gitignore ├── azuredeploy.tf └── README.md ├── Useful-Tips └── readme.md ├── Azure-KeyVault-with-Secret ├── terraform.tfvars ├── variables.tf ├── provider.tf ├── .gitignore ├── README.md └── azuredeploy.tf ├── Azure-OpenAI-Demo-1 ├── terraform.tfvars ├── variables.tf ├── provider.tf ├── README.md ├── .gitignore └── azuredeploy.tf ├── Getting Started Blog Post ├── terraform.tfvars ├── azuredeploy.tf ├── provider.tf ├── variables.tf └── .gitignore ├── Chaos-Studio-Test ├── readme.md ├── terraform.tfvars ├── provider.tf ├── outputs.tf ├── .gitignore ├── variables.tf └── trafficmanager.tf ├── Cross-Region-Load-Balancer-Lab ├── readme.md ├── terraform.tfvars ├── provider.tf ├── ResourceGroups.tf ├── variables.tf ├── .gitignore ├── output.tf ├── KeyVault.tf ├── VirtualNetworks.tf ├── CrossRegionLB.tf ├── VirtualMachines.tf └── RegionalLBs.tf ├── Ansible-Quickstart ├── Ansible │ └── AnsibleSetup.sh ├── terraform.tfvars ├── provider.tf ├── README.md ├── variables.tf └── .gitignore ├── Single-Region-Azure-BaseLab-with-Ansible ├── Ansible │ └── AnsibleSetup.sh ├── provider.tf ├── README.md ├── .gitignore ├── terraform.tfvars └── variables.tf ├── AVD-Demo-Lab ├── Terraform-Single-Region-Azure-BaseLab-v2 │ ├── README.md │ ├── provider.tf │ ├── terraform.tfvars │ ├── .gitignore │ └── variables.tf ├── README.md └── .gitignore ├── Cost-Optimization-Example-Lab ├── provider.tf ├── README.md ├── terraform.tfvars ├── .gitignore └── variables.tf ├── Single-Region-Azure-BaseLab-v2 ├── provider.tf ├── terraform.tfvars ├── README.md ├── .gitignore └── variables.tf ├── Azure-Firewall-DemoLab ├── provider.tf ├── .gitignore ├── terraform.tfvars ├── variables.tf └── README.md ├── Web-Server-IIS-DemoLab ├── provider.tf ├── .gitignore ├── terraform.tfvars └── variables.tf ├── Single-Region-Azure-BaseLab ├── provider.tf ├── .gitignore ├── terraform.tfvars ├── variables.tf └── README.md ├── Setup-Scripts ├── TerraformApps.ps1 ├── readme.md └── AllApps.ps1 ├── .github └── workflows │ ├── tfsec.yml │ ├── links.yml │ ├── destroy.yml │ └── apply.yml ├── Core-Environment-DemoLab-v1 ├── variables.tf ├── provider.tf ├── terraform.tfvars ├── readme.md ├── .gitignore ├── bastion.tf ├── rg.tf ├── keyvault.tf ├── firewall.tf ├── subnets.tf └── virtualwan.tf ├── UpdateProviders.PS1 └── .gitignore /Azure-Automation-Demo/terraform.tfvars: -------------------------------------------------------------------------------- 1 | region = "uksouth" 2 | -------------------------------------------------------------------------------- /Azure-Backup-Demo-Resources/terraform.tfvars: -------------------------------------------------------------------------------- 1 | location = "uksouth" -------------------------------------------------------------------------------- /Azure Lab Services/terraform.tfvars: -------------------------------------------------------------------------------- 1 | labname = "lab1" 2 | region = "uksouth" 3 | labusername = "labadmin" -------------------------------------------------------------------------------- /Azure-Automation-Demo/variables.tf: -------------------------------------------------------------------------------- 1 | variable "region" { 2 | type = string 3 | default = "UK South" 4 | } -------------------------------------------------------------------------------- /Azure-Backup-Demo-Resources/variables.tf: -------------------------------------------------------------------------------- 1 | variable "location" { 2 | type = string 3 | default = "uksouth" 4 | } -------------------------------------------------------------------------------- /PowerShell/readme.md: -------------------------------------------------------------------------------- 1 | ### Readme 2 | This repo contains PowerShell scripting used throughout my Terraform environments. -------------------------------------------------------------------------------- /Dual-Region-Azure-BaseLab/PowerShell/DC2/baselab_DC2JoinDomain.ps1: -------------------------------------------------------------------------------- 1 | ipconfig /registerdns 2 | Add-Computer -DomainName ad.lab -Restart 3 | -------------------------------------------------------------------------------- /Azure-NetApp-Files-CRR-BaseLab/PowerShell/DC2/baselab_DC2JoinDomain.ps1: -------------------------------------------------------------------------------- 1 | ipconfig /registerdns 2 | Add-Computer -DomainName ad.lab -Restart 3 | -------------------------------------------------------------------------------- /Virtual-WAN-Demo/images/Virtual-WAN.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jakewalsh90/Terraform-Azure/HEAD/Virtual-WAN-Demo/images/Virtual-WAN.png -------------------------------------------------------------------------------- /CIDRHost-Demo/terraform.tfvars: -------------------------------------------------------------------------------- 1 | environment_tag = "jakewalsh90-cidrhost-demo" 2 | region1 = "uksouth" 3 | region1cidr = "10.10.0.0/19" -------------------------------------------------------------------------------- /CIDRSubnet-Demo/terraform.tfvars: -------------------------------------------------------------------------------- 1 | environment_tag = "jakewalsh90-Subnet-Demo" 2 | region1 = "uksouth" 3 | region1cidr = "10.10.0.0/19" -------------------------------------------------------------------------------- /GitHub-Actions-Deployment/images/Actions1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jakewalsh90/Terraform-Azure/HEAD/GitHub-Actions-Deployment/images/Actions1.png -------------------------------------------------------------------------------- /GitHub-Actions-Deployment/images/Actions2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jakewalsh90/Terraform-Azure/HEAD/GitHub-Actions-Deployment/images/Actions2.png -------------------------------------------------------------------------------- /GitHub-Actions-Deployment/images/Actions3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jakewalsh90/Terraform-Azure/HEAD/GitHub-Actions-Deployment/images/Actions3.png -------------------------------------------------------------------------------- /GitHub-Actions-Deployment/images/Actions4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jakewalsh90/Terraform-Azure/HEAD/GitHub-Actions-Deployment/images/Actions4.png -------------------------------------------------------------------------------- /GitHub-Actions-Deployment/images/Actions5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jakewalsh90/Terraform-Azure/HEAD/GitHub-Actions-Deployment/images/Actions5.png -------------------------------------------------------------------------------- /GitHub-Actions-Deployment/images/GitHubSecrets.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jakewalsh90/Terraform-Azure/HEAD/GitHub-Actions-Deployment/images/GitHubSecrets.png -------------------------------------------------------------------------------- /Virtual-WAN-Demo/images/Virtual-WAN - Full-Size.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jakewalsh90/Terraform-Azure/HEAD/Virtual-WAN-Demo/images/Virtual-WAN - Full-Size.png -------------------------------------------------------------------------------- /GitHub-Actions-Deployment/images/ScriptOutputSample.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jakewalsh90/Terraform-Azure/HEAD/GitHub-Actions-Deployment/images/ScriptOutputSample.png -------------------------------------------------------------------------------- /Virtual-WAN-Demo/images/Virtual-WAN-with-Firewall.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jakewalsh90/Terraform-Azure/HEAD/Virtual-WAN-Demo/images/Virtual-WAN-with-Firewall.png -------------------------------------------------------------------------------- /Terraform-Cloud-Deployment/scripts/ServicePrincipalSetup: -------------------------------------------------------------------------------- 1 | az ad sp create-for-rbac -n tfc-demo-lab-env --role Contributor --scopes /subscriptions/xxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx -------------------------------------------------------------------------------- /Automatic-ClientIP-NSG/terraform.tfvars: -------------------------------------------------------------------------------- 1 | environment_tag = "jakewalsh90-Automatic-ClientIP-NSG" 2 | azure-rg-1 = "jakewalsh90-Automatic-ClientIP-NSG" 3 | loc1 = "uk south" 4 | -------------------------------------------------------------------------------- /Virtual-WAN-Demo/images/Virtual-WAN-with-Firewall - Full-Size.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jakewalsh90/Terraform-Azure/HEAD/Virtual-WAN-Demo/images/Virtual-WAN-with-Firewall - Full-Size.png -------------------------------------------------------------------------------- /Azure Lab Services/readme.md: -------------------------------------------------------------------------------- 1 | This lab relates to a blog post covering Azure Lab Services - you can read the post here: https://jakewalsh.co.uk/azure-lab-services-an-overview-setup-terraform-and-more/ -------------------------------------------------------------------------------- /Useful-Tips/readme.md: -------------------------------------------------------------------------------- 1 | ## Please note: 2 | 3 | This has now been moved to its own Repository - here: [https://github.com/jakewalsh90/Terraform-Tips](https://github.com/jakewalsh90/Terraform-Tips) -------------------------------------------------------------------------------- /Azure-KeyVault-with-Secret/terraform.tfvars: -------------------------------------------------------------------------------- 1 | environment_tag = "jakewalsh90-Automatic-KeyVault-with-Secret" 2 | azure-rg-1 = "jakewalsh90-Automatic-KeyVault-with-Secret" 3 | loc1 = "uk south" -------------------------------------------------------------------------------- /Azure-OpenAI-Demo-1/terraform.tfvars: -------------------------------------------------------------------------------- 1 | # Core Variables 2 | region = "uksouth" 3 | # Optional Variables 4 | privatenetworking = true 5 | region1-cidr = "10.10.0.0/16" 6 | region1-subnet = "10.10.1.0/24" -------------------------------------------------------------------------------- /Getting Started Blog Post/terraform.tfvars: -------------------------------------------------------------------------------- 1 | azure-rg-1 = "rg-demo-lab" 2 | loc1 = "uk south" 3 | region1-vnet1-name = "region1-vnet1-hub1" 4 | region1-vnet1-address-space = "10.10.0.0/16" -------------------------------------------------------------------------------- /Chaos-Studio-Test/readme.md: -------------------------------------------------------------------------------- 1 | # Chaos Studio Test Application 2 | 3 | This code is to support a Blog Post around testing Azure Chaos Studio. You can read the post and Chaos Studio Overview [here](https://jakewalsh.co.uk/exploring-the-azure-chaos-studio-preview/). -------------------------------------------------------------------------------- /Cross-Region-Load-Balancer-Lab/readme.md: -------------------------------------------------------------------------------- 1 | # Cross-Region Load Balancer Lab 2 | 3 | This environment is covered by a Blog Post here: [https://jakewalsh.co.uk/azure-cross-region-global-load-balancer-demo-environment/](https://jakewalsh.co.uk/azure-cross-region-global-load-balancer-demo-environment/) -------------------------------------------------------------------------------- /Azure-Backup-Demo-Resources/readme.md: -------------------------------------------------------------------------------- 1 | This lab creates a number of Resources related to Azure Backup. 2 | 3 | This is to support a blog post available here - [https://jakewalsh.co.uk/exploring-backups-dr-and-continuity-in-an-azure-terraform-world/](https://jakewalsh.co.uk/exploring-backups-dr-and-continuity-in-an-azure-terraform-world/) -------------------------------------------------------------------------------- /Azure-Automation-Demo/provider.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | azurerm = { 4 | source = "hashicorp/azurerm" 5 | version = ">= 4.56.0" 6 | } 7 | } 8 | } 9 | 10 | provider "azurerm" { 11 | # Configuration options 12 | 13 | features { 14 | 15 | } 16 | } 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /Automatic-ClientIP-NSG/variables.tf: -------------------------------------------------------------------------------- 1 | variable "environment_tag" { 2 | type = string 3 | description = "Environment Tag value" 4 | } 5 | variable "azure-rg-1" { 6 | type = string 7 | description = "Resource Group 1" 8 | } 9 | variable "loc1" { 10 | description = "Azure Region 1" 11 | type = string 12 | } -------------------------------------------------------------------------------- /Ansible-Quickstart/Ansible/AnsibleSetup.sh: -------------------------------------------------------------------------------- 1 | sudo apt-get update 2 | sudo apt-get upgrade -y 3 | sudo apt-get install python3-pip -y 4 | sudo pip3 install 'ansible[azure]' 5 | ansible-galaxy collection install azure.azcollection 6 | wget https://raw.githubusercontent.com/ansible-collections/azure/dev/requirements-azure.txt 7 | sudo pip3 install -r requirements-azure.txt -------------------------------------------------------------------------------- /Chaos-Studio-Test/terraform.tfvars: -------------------------------------------------------------------------------- 1 | environment_tag = "jakewalsh90-ChaosStudio-Demo" 2 | labname = "chaos-demo" 3 | region1 = "uksouth" 4 | region1cidr = "10.10.0.0/19" 5 | region1code = "uks" 6 | region2 = "northeurope" 7 | region2cidr = "10.20.0.0/19" 8 | region2code = "neu" 9 | servercounta = 1 10 | servercountb = 1 -------------------------------------------------------------------------------- /Azure-KeyVault-with-Secret/variables.tf: -------------------------------------------------------------------------------- 1 | variable "environment_tag" { 2 | type = string 3 | description = "Environment tag value" 4 | } 5 | variable "azure-rg-1" { 6 | type = string 7 | description = "resource group 1" 8 | } 9 | variable "loc1" { 10 | description = "The location for this Lab environment" 11 | type = string 12 | } -------------------------------------------------------------------------------- /Cross-Region-Load-Balancer-Lab/terraform.tfvars: -------------------------------------------------------------------------------- 1 | regions = { 2 | region1 = { 3 | location = "uksouth" 4 | cidr = "10.10.0.0/21" 5 | } 6 | region2 = { 7 | location = "eastus" 8 | cidr = "10.20.0.0/21" 9 | } 10 | region3 = { 11 | location = "westus" 12 | cidr = "10.30.0.0/21" 13 | } 14 | } 15 | adminuser = "azureadmin" 16 | -------------------------------------------------------------------------------- /Azure Lab Services/variables.tf: -------------------------------------------------------------------------------- 1 | variable "labname" { 2 | type = string 3 | description = "Name for the Lab Environment" 4 | } 5 | variable "region" { 6 | type = string 7 | description = "Region 1 Location for this environment" 8 | } 9 | variable "labusername" { 10 | type = string 11 | description = "Username for the Lab Machine Account" 12 | } -------------------------------------------------------------------------------- /CIDRHost-Demo/variables.tf: -------------------------------------------------------------------------------- 1 | variable "environment_tag" { 2 | type = string 3 | description = "Environment tag value" 4 | } 5 | variable "region1" { 6 | description = "The location 1 for this Lab environment" 7 | type = string 8 | } 9 | variable "region1cidr" { 10 | description = "The CIDR range for the whole of Region 1" 11 | type = string 12 | } -------------------------------------------------------------------------------- /CIDRSubnet-Demo/variables.tf: -------------------------------------------------------------------------------- 1 | variable "environment_tag" { 2 | type = string 3 | description = "Environment tag value" 4 | } 5 | variable "region1" { 6 | description = "The location 1 for this Lab environment" 7 | type = string 8 | } 9 | variable "region1cidr" { 10 | description = "The CIDR range for the whole of Region 1" 11 | type = string 12 | } -------------------------------------------------------------------------------- /Single-Region-Azure-BaseLab-with-Ansible/Ansible/AnsibleSetup.sh: -------------------------------------------------------------------------------- 1 | sudo apt-get update 2 | sudo apt-get upgrade -y 3 | sudo apt-get install python3-pip -y 4 | sudo pip3 install 'ansible[azure]' 5 | ansible-galaxy collection install azure.azcollection 6 | wget https://raw.githubusercontent.com/ansible-collections/azure/dev/requirements-azure.txt 7 | sudo pip3 install -r requirements-azure.txt -------------------------------------------------------------------------------- /Azure-Backup-Demo-Resources/provider.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | azurerm = { 4 | source = "hashicorp/azurerm" 5 | version = "4.56.0" 6 | } 7 | random = { 8 | source = "hashicorp/random" 9 | version = "3.7.2" 10 | } 11 | } 12 | } 13 | 14 | provider "azurerm" { 15 | # Configuration options 16 | features { 17 | 18 | } 19 | } -------------------------------------------------------------------------------- /Dual-Region-Azure-BaseLab/PowerShell/DC2/baselab_DC2Promote.ps1: -------------------------------------------------------------------------------- 1 | ipconfig /registerdns 2 | Install-ADDSDomainController ` 3 | -InstallDns:$true ` 4 | -CreateDnsDelegation:$false ` 5 | -DatabasePath "E:\windows\NTDS" ` 6 | -LogPath "E:\windows\NTDS" ` 7 | -NoRebootOnCompletion:$false ` 8 | -SysvolPath "E:\windows\SYSVOL" ` 9 | -DomainName "ad.lab" ` 10 | -Force:$true ` 11 | -Credential (Get-Credential) 12 | -------------------------------------------------------------------------------- /Azure-NetApp-Files-CRR-BaseLab/PowerShell/DC2/baselab_DC2Promote.ps1: -------------------------------------------------------------------------------- 1 | ipconfig /registerdns 2 | Install-ADDSDomainController ` 3 | -InstallDns:$true ` 4 | -CreateDnsDelegation:$false ` 5 | -DatabasePath "E:\windows\NTDS" ` 6 | -LogPath "E:\windows\NTDS" ` 7 | -NoRebootOnCompletion:$false ` 8 | -SysvolPath "E:\windows\SYSVOL" ` 9 | -DomainName "ad.lab" ` 10 | -Force:$true ` 11 | -Credential (Get-Credential) 12 | -------------------------------------------------------------------------------- /AVD-Demo-Lab/Terraform-Single-Region-Azure-BaseLab-v2/README.md: -------------------------------------------------------------------------------- 1 | # Single Region Base Lab Environment for Azure - Version 2 2 | 3 | For an overview of this environment, please see [here](https://jakewalsh.co.uk/introducing-single-region-azure-baselab-v2/). 4 | 5 | This environment is also available as a Terraform Module - see [here](https://github.com/jakewalsh90/Terraform-Modules-Azure/tree/main/azure-single-region-baselabv2). 6 | -------------------------------------------------------------------------------- /Azure-OpenAI-Demo-1/variables.tf: -------------------------------------------------------------------------------- 1 | # Core Variables 2 | variable "region" { 3 | type = string 4 | default = "uk south" 5 | } 6 | # Optional Variables 7 | variable "privatenetworking" { 8 | type = bool 9 | default = true 10 | 11 | } 12 | variable "region1-cidr" { 13 | type = string 14 | default = "10.10.0.0/16" 15 | } 16 | variable "region1-subnet" { 17 | type = string 18 | default = "10.10.1.0/24" 19 | } -------------------------------------------------------------------------------- /PowerShell/baselab_DomainSetup.ps1: -------------------------------------------------------------------------------- 1 | Import-Module ADDSDeployment 2 | Install-ADDSForest ` 3 | -CreateDnsDelegation:$false ` 4 | -DatabasePath "E:\windows\NTDS" ` 5 | -DomainMode "WinThreshold" ` 6 | -DomainName "ad.lab" ` 7 | -DomainNetbiosName "ad" ` 8 | -ForestMode "WinThreshold" ` 9 | -InstallDns:$true ` 10 | -LogPath "E:\windows\NTDS" ` 11 | -NoRebootOnCompletion:$false ` 12 | -SysvolPath "E:\windows\SYSVOL" ` 13 | -Force:$true 14 | -------------------------------------------------------------------------------- /Cross-Region-Load-Balancer-Lab/provider.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | azurerm = { 4 | source = "hashicorp/azurerm" 5 | version = ">= 4.56.0" 6 | } 7 | random = { 8 | source = "hashicorp/random" 9 | version = "3.5.1" 10 | } 11 | } 12 | } 13 | 14 | provider "azurerm" { 15 | # Configuration options 16 | features { 17 | 18 | } 19 | } 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Getting Started Blog Post/azuredeploy.tf: -------------------------------------------------------------------------------- 1 | # Resource Group 2 | resource "azurerm_resource_group" "rg1" { 3 | name = var.azure-rg-1 4 | location = var.loc1 5 | } 6 | # VNET 7 | resource "azurerm_virtual_network" "region1-vnet1-hub1" { 8 | name = var.region1-vnet1-name 9 | location = var.loc1 10 | resource_group_name = azurerm_resource_group.rg1.name 11 | address_space = [var.region1-vnet1-address-space] 12 | } -------------------------------------------------------------------------------- /Dual-Region-Azure-BaseLab/PowerShell/DC1/baselab_DomainSetup.ps1: -------------------------------------------------------------------------------- 1 | Import-Module ADDSDeployment 2 | Install-ADDSForest ` 3 | -CreateDnsDelegation:$false ` 4 | -DatabasePath "E:\windows\NTDS" ` 5 | -DomainMode "WinThreshold" ` 6 | -DomainName "ad.lab" ` 7 | -DomainNetbiosName "ad" ` 8 | -ForestMode "WinThreshold" ` 9 | -InstallDns:$true ` 10 | -LogPath "E:\windows\NTDS" ` 11 | -NoRebootOnCompletion:$false ` 12 | -SysvolPath "E:\windows\SYSVOL" ` 13 | -Force:$true 14 | -------------------------------------------------------------------------------- /Azure-NetApp-Files-CRR-BaseLab/PowerShell/DC1/baselab_DomainSetup.ps1: -------------------------------------------------------------------------------- 1 | Import-Module ADDSDeployment 2 | Install-ADDSForest ` 3 | -CreateDnsDelegation:$false ` 4 | -DatabasePath "E:\windows\NTDS" ` 5 | -DomainMode "WinThreshold" ` 6 | -DomainName "ad.lab" ` 7 | -DomainNetbiosName "ad" ` 8 | -ForestMode "WinThreshold" ` 9 | -InstallDns:$true ` 10 | -LogPath "E:\windows\NTDS" ` 11 | -NoRebootOnCompletion:$false ` 12 | -SysvolPath "E:\windows\SYSVOL" ` 13 | -Force:$true 14 | -------------------------------------------------------------------------------- /Chaos-Studio-Test/provider.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | azurerm = { 4 | source = "hashicorp/azurerm" 5 | version = ">= 4.56.0" 6 | } 7 | random = { 8 | source = "hashicorp/random" 9 | version = ">= 3.7.2" 10 | } 11 | } 12 | } 13 | provider "azurerm" { 14 | features { 15 | key_vault { 16 | purge_soft_delete_on_destroy = true 17 | } 18 | } 19 | } 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Getting Started Blog Post/provider.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | azurerm = { 4 | # Specify what version of the provider we are going to utilise 5 | source = "hashicorp/azurerm" 6 | version = ">= 4.56.0" 7 | } 8 | random = { 9 | source = "hashicorp/random" 10 | version = "3.4.3" 11 | } 12 | } 13 | } 14 | provider "azurerm" { 15 | features { 16 | } 17 | } 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /Getting Started Blog Post/variables.tf: -------------------------------------------------------------------------------- 1 | variable "azure-rg-1" { 2 | type = string 3 | description = "resource group 1" 4 | } 5 | variable "loc1" { 6 | description = "The location for this Lab environment" 7 | type = string 8 | } 9 | variable "region1-vnet1-name" { 10 | description = "VNET1 Name" 11 | type = string 12 | } 13 | variable "region1-vnet1-address-space" { 14 | description = "VNET address space" 15 | type = string 16 | } -------------------------------------------------------------------------------- /Cost-Optimization-Example-Lab/provider.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | azurerm = { 4 | source = "hashicorp/azurerm" 5 | version = ">= 4.56.0" 6 | } 7 | random = { 8 | source = "hashicorp/random" 9 | version = ">= 3.7.2" 10 | } 11 | } 12 | } 13 | 14 | provider "azurerm" { 15 | features { 16 | key_vault { 17 | purge_soft_delete_on_destroy = true 18 | } 19 | } 20 | } 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /Single-Region-Azure-BaseLab-v2/provider.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | azurerm = { 4 | source = "hashicorp/azurerm" 5 | version = ">= 4.56.0" 6 | } 7 | random = { 8 | source = "hashicorp/random" 9 | version = ">= 3.7.2" 10 | } 11 | } 12 | } 13 | 14 | provider "azurerm" { 15 | features { 16 | key_vault { 17 | purge_soft_delete_on_destroy = true 18 | } 19 | } 20 | } 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /Ansible-Quickstart/terraform.tfvars: -------------------------------------------------------------------------------- 1 | environment_tag = "jakewalsh90-ansiblequickstart" 2 | azure-rg-1 = "jakewalsh90-ansible" 3 | loc1 = "uk south" 4 | region1-vnet1-name = "region1-vnet1-ansible1" 5 | region1-vnet1-address-space = "10.10.0.0/16" 6 | region1-vnet1-snet1-name = "region1-vnet1-snet-ansible1" 7 | region1-vnet1-snet1-range = "10.10.1.0/24" 8 | vmsize = "Standard_D2s_v4" 9 | adminusername = "labadmin" -------------------------------------------------------------------------------- /AVD-Demo-Lab/Terraform-Single-Region-Azure-BaseLab-v2/provider.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | azurerm = { 4 | source = "hashicorp/azurerm" 5 | version = ">= 4.56.0" 6 | } 7 | random = { 8 | source = "hashicorp/random" 9 | version = ">= 3.7.2" 10 | } 11 | } 12 | } 13 | 14 | provider "azurerm" { 15 | features { 16 | key_vault { 17 | purge_soft_delete_on_destroy = true 18 | } 19 | } 20 | } 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /Automatic-ClientIP-NSG/provider.tf: -------------------------------------------------------------------------------- 1 | #Providers 2 | terraform { 3 | required_providers { 4 | azurerm = { 5 | # Specify what version of the provider we are going to utilise 6 | source = "hashicorp/azurerm" 7 | version = ">= 4.56.0" 8 | } 9 | random = { 10 | source = "hashicorp/random" 11 | version = ">= 3.7.2" 12 | } 13 | } 14 | } 15 | provider "azurerm" { 16 | features { 17 | } 18 | } 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Azure-Automation-Demo/PowerShell/power_off_vm.ps1: -------------------------------------------------------------------------------- 1 | param ( 2 | [Parameter(Mandatory=$true)] 3 | [string]$dailyshutdowntime 4 | ) 5 | 6 | Disable-AzContextAutosave -Scope Process 7 | $AzureContext = (Connect-AzAccount -Identity ).context 8 | $AzureContext = Set-AzContext -SubscriptionName $AzureContext.Subscription -DefaultProfile $AzureContext 9 | 10 | $VMs = Get-AzVM | Where-Object {$_.Tags.DailyShutdown -eq "$dailyshutdowntime"} 11 | $VMs | Stop-AzVM -Force 12 | Write-Output "Stopped VMs are $($VMs.Name)" -------------------------------------------------------------------------------- /Azure-OpenAI-Demo-1/provider.tf: -------------------------------------------------------------------------------- 1 | #Providers 2 | terraform { 3 | required_providers { 4 | azurerm = { 5 | # Specify what version of the provider we are going to utilise 6 | source = "hashicorp/azurerm" 7 | version = ">= 4.56.0" 8 | } 9 | random = { 10 | source = "hashicorp/random" 11 | version = ">= 3.7.2" 12 | } 13 | } 14 | } 15 | provider "azurerm" { 16 | features { 17 | key_vault { 18 | purge_soft_delete_on_destroy = true 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /PowerShell/standard_VMSetup.ps1: -------------------------------------------------------------------------------- 1 | # Choco install and Choco Apps 2 | Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1')) 3 | choco install googlechrome -y 4 | choco install putty -y 5 | choco install notepadplusplus -y 6 | choco install sysinternals -y 7 | # Disable Firewall for Testing 8 | Set-NetFirewallProfile -All -Enabled False 9 | -------------------------------------------------------------------------------- /Chaos-Studio-Test/outputs.tf: -------------------------------------------------------------------------------- 1 | output "_1_Access-URL-via-TrafficManager" { 2 | value = "Use this URL to access via Traffic Manager: http://${azurerm_traffic_manager_profile.tm1.fqdn} " 3 | } 4 | output "_2_Access-URL-via-Region1-Firewall" { 5 | value = "Use this URL to access directly to the ${var.region1} Firewall: http://${azurerm_public_ip.region1-fwpip.fqdn} " 6 | } 7 | output "_3_Access-URL-via-Region2-Firewall" { 8 | value = "Use this URL to access directly to the ${var.region2} Firewall: http://${azurerm_public_ip.region2-fwpip.fqdn} " 9 | } -------------------------------------------------------------------------------- /CIDRHost-Demo/provider.tf: -------------------------------------------------------------------------------- 1 | #Providers 2 | terraform { 3 | required_providers { 4 | azurerm = { 5 | # Specify what version of the provider we are going to utilise 6 | source = "hashicorp/azurerm" 7 | version = ">= 4.56.0" 8 | } 9 | random = { 10 | source = "hashicorp/random" 11 | version = ">= 3.7.2" 12 | } 13 | } 14 | } 15 | provider "azurerm" { 16 | features { 17 | key_vault { 18 | purge_soft_delete_on_destroy = true 19 | } 20 | } 21 | } 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /Ansible-Quickstart/provider.tf: -------------------------------------------------------------------------------- 1 | #Providers 2 | terraform { 3 | required_providers { 4 | azurerm = { 5 | # Specify what version of the provider we are going to utilise 6 | source = "hashicorp/azurerm" 7 | version = ">= 4.37.0" 8 | } 9 | random = { 10 | source = "hashicorp/random" 11 | version = ">= 3.7.2" 12 | } 13 | } 14 | } 15 | provider "azurerm" { 16 | features { 17 | key_vault { 18 | purge_soft_delete_on_destroy = true 19 | } 20 | } 21 | } 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /Azure Lab Services/provider.tf: -------------------------------------------------------------------------------- 1 | #Providers 2 | terraform { 3 | required_providers { 4 | azurerm = { 5 | # Specify what version of the provider we are going to utilise 6 | source = "hashicorp/azurerm" 7 | version = ">= 4.56.0" 8 | } 9 | random = { 10 | source = "hashicorp/random" 11 | version = ">= 3.7.2" 12 | } 13 | } 14 | } 15 | provider "azurerm" { 16 | features { 17 | key_vault { 18 | purge_soft_delete_on_destroy = true 19 | } 20 | } 21 | } 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /CIDRSubnet-Demo/provider.tf: -------------------------------------------------------------------------------- 1 | #Providers 2 | terraform { 3 | required_providers { 4 | azurerm = { 5 | # Specify what version of the provider we are going to utilise 6 | source = "hashicorp/azurerm" 7 | version = ">= 4.56.0" 8 | } 9 | random = { 10 | source = "hashicorp/random" 11 | version = ">= 3.7.2" 12 | } 13 | } 14 | } 15 | provider "azurerm" { 16 | features { 17 | key_vault { 18 | purge_soft_delete_on_destroy = true 19 | } 20 | } 21 | } 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /Azure-Firewall-DemoLab/provider.tf: -------------------------------------------------------------------------------- 1 | #Providers 2 | terraform { 3 | required_providers { 4 | azurerm = { 5 | # Specify what version of the provider we are going to utilise 6 | source = "hashicorp/azurerm" 7 | version = ">= 4.56.0" 8 | } 9 | random = { 10 | source = "hashicorp/random" 11 | version = ">= 3.7.2" 12 | } 13 | } 14 | } 15 | provider "azurerm" { 16 | features { 17 | key_vault { 18 | purge_soft_delete_on_destroy = true 19 | } 20 | } 21 | } 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /Web-Server-IIS-DemoLab/provider.tf: -------------------------------------------------------------------------------- 1 | #Providers 2 | terraform { 3 | required_providers { 4 | azurerm = { 5 | # Specify what version of the provider we are going to utilise 6 | source = "hashicorp/azurerm" 7 | version = ">= 4.56.0" 8 | } 9 | random = { 10 | source = "hashicorp/random" 11 | version = ">= 3.7.2" 12 | } 13 | } 14 | } 15 | provider "azurerm" { 16 | features { 17 | key_vault { 18 | purge_soft_delete_on_destroy = true 19 | } 20 | } 21 | } 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /Cross-Region-Load-Balancer-Lab/ResourceGroups.tf: -------------------------------------------------------------------------------- 1 | # Resource Groups 2 | resource "azurerm_resource_group" "rg-sec" { 3 | name = "rg-${var.regions.region1.location}-sec" 4 | location = var.regions.region1.location 5 | } 6 | resource "azurerm_resource_group" "rg-con" { 7 | for_each = var.regions 8 | name = "rg-${each.value.location}-con" 9 | location = each.value.location 10 | } 11 | resource "azurerm_resource_group" "rg-host" { 12 | for_each = var.regions 13 | name = "rg-${each.value.location}-host" 14 | location = each.value.location 15 | } -------------------------------------------------------------------------------- /Dual-Region-Azure-BaseLab/provider.tf: -------------------------------------------------------------------------------- 1 | #Providers 2 | terraform { 3 | required_providers { 4 | azurerm = { 5 | # Specify what version of the provider we are going to utilise 6 | source = "hashicorp/azurerm" 7 | version = ">= 4.56.0" 8 | } 9 | random = { 10 | source = "hashicorp/random" 11 | version = ">= 3.7.2" 12 | } 13 | } 14 | } 15 | provider "azurerm" { 16 | features { 17 | key_vault { 18 | purge_soft_delete_on_destroy = true 19 | } 20 | } 21 | } 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /Azure-NetApp-Files-CRR-BaseLab/provider.tf: -------------------------------------------------------------------------------- 1 | #Providers 2 | terraform { 3 | required_providers { 4 | azurerm = { 5 | # Specify what version of the provider we are going to utilise 6 | source = "hashicorp/azurerm" 7 | version = ">= 4.56.0" 8 | } 9 | random = { 10 | source = "hashicorp/random" 11 | version = ">= 3.7.2" 12 | } 13 | } 14 | } 15 | provider "azurerm" { 16 | features { 17 | key_vault { 18 | purge_soft_delete_on_destroy = true 19 | } 20 | } 21 | } 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /Virtual-WAN-Demo/provider.tf: -------------------------------------------------------------------------------- 1 | #Providers 2 | terraform { 3 | required_providers { 4 | azurerm = { 5 | # Specify what version of the provider we are going to utilise 6 | source = "hashicorp/azurerm" 7 | version = ">= 4.56.0" 8 | } 9 | random = { 10 | source = "hashicorp/random" 11 | version = ">= 3.7.2" 12 | } 13 | } 14 | } 15 | # Features 16 | provider "azurerm" { 17 | features { 18 | key_vault { 19 | purge_soft_delete_on_destroy = true 20 | } 21 | } 22 | } 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /Single-Region-Azure-BaseLab-with-Ansible/provider.tf: -------------------------------------------------------------------------------- 1 | #Providers 2 | terraform { 3 | required_providers { 4 | azurerm = { 5 | # Specify what version of the provider we are going to utilise 6 | source = "hashicorp/azurerm" 7 | version = ">= 4.56.0" 8 | } 9 | random = { 10 | source = "hashicorp/random" 11 | version = ">= 3.7.2" 12 | } 13 | } 14 | } 15 | provider "azurerm" { 16 | features { 17 | key_vault { 18 | purge_soft_delete_on_destroy = true 19 | } 20 | } 21 | } 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /Azure-KeyVault-with-Secret/provider.tf: -------------------------------------------------------------------------------- 1 | #Providers 2 | terraform { 3 | required_providers { 4 | azurerm = { 5 | # Specify what version of the provider we are going to utilise 6 | source = "hashicorp/azurerm" 7 | version = ">= 4.56.0" 8 | } 9 | random = { 10 | source = "hashicorp/random" 11 | version = ">= 3.7.2" 12 | } 13 | } 14 | } 15 | provider "azurerm" { 16 | features { 17 | key_vault { 18 | purge_soft_delete_on_destroy = true 19 | } 20 | } 21 | } 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /Cross-Region-Load-Balancer-Lab/variables.tf: -------------------------------------------------------------------------------- 1 | variable "regions" { 2 | description = "Regional variables" 3 | type = map(any) 4 | default = { 5 | region1 = { 6 | location = "uksouth" 7 | cidr = "10.10.0.0/21" 8 | } 9 | region2 = { 10 | location = "eastus" 11 | cidr = "10.20.0.0/21" 12 | } 13 | region3 = { 14 | location = "westus" 15 | cidr = "10.30.0.0/21" 16 | } 17 | } 18 | } 19 | variable "adminuser" { 20 | description = "Admin username" 21 | type = string 22 | default = "azureadmin" 23 | } -------------------------------------------------------------------------------- /Single-Region-Azure-BaseLab/provider.tf: -------------------------------------------------------------------------------- 1 | #Providers 2 | terraform { 3 | required_providers { 4 | azurerm = { 5 | # Specify what version of the provider we are going to utilise 6 | source = "hashicorp/azurerm" 7 | version = ">= 4.56.0" 8 | } 9 | random = { 10 | source = "hashicorp/random" 11 | version = ">= 3.7.2" 12 | } 13 | } 14 | } 15 | provider "azurerm" { 16 | features { 17 | key_vault { 18 | purge_soft_delete_on_destroy = true 19 | } 20 | } 21 | } 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /PowerShell/webserver_VMSetup.ps1: -------------------------------------------------------------------------------- 1 | # Set Execution Policy to allow script to run 2 | Set-ExecutionPolicy Bypass -Scope Process -Force 3 | # Allow Ping 4 | Set-NetFirewallRule -DisplayName "File and Printer Sharing (Echo Request - ICMPv4-In)" -enabled True 5 | Set-NetFirewallRule -DisplayName "File and Printer Sharing (Echo Request - ICMPv6-In)" -enabled True 6 | # Install IIS 7 | Install-WindowsFeature -Name Web-Server -IncludeAllSubFeature -IncludeManagementTools 8 | # Replace IIS Page with Server Name for Identification Purposes 9 | iex hostname | out-file -filepath c:\inetpub\wwwroot\iisstart.htm -Force 10 | -------------------------------------------------------------------------------- /Setup-Scripts/TerraformApps.ps1: -------------------------------------------------------------------------------- 1 | # Chocolatey setup and installation script for using Terraform 2 | Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1')) 3 | # Chocolatey apps 4 | choco install vscode -y -no-desktopshortcuts 5 | choco install terraform -y -no-desktopshortcuts 6 | choco install azure-cli -y -no-desktopshortcuts 7 | choco install az.powershell -y -no-desktopshortcuts 8 | choco install github-desktop -y -no-desktopshortcuts 9 | -------------------------------------------------------------------------------- /.github/workflows/tfsec.yml: -------------------------------------------------------------------------------- 1 | name: TFSec Analysis 2 | on: [workflow_dispatch] 3 | 4 | jobs: 5 | tfsec: 6 | name: tfsec sarif report 7 | runs-on: ubuntu-latest 8 | 9 | steps: 10 | - name: Clone repo 11 | uses: actions/checkout@master 12 | 13 | - name: tfsec 14 | uses: tfsec/tfsec-sarif-action@master 15 | with: 16 | sarif_file: tfsec.sarif 17 | 18 | - name: Upload SARIF file 19 | uses: github/codeql-action/upload-sarif@v1 20 | with: 21 | # Path to SARIF file relative to the root of the repository 22 | sarif_file: tfsec.sarif 23 | -------------------------------------------------------------------------------- /Core-Environment-DemoLab-v1/variables.tf: -------------------------------------------------------------------------------- 1 | # Service Principal 2 | variable "client_id" {} 3 | variable "client_secret" {} 4 | variable "tenant_id" {} 5 | variable "subscription_id" {} 6 | variable "vpn_app_id" {} 7 | # Admin Account (For Key Vault Access Policy) 8 | variable "admin_id" {} 9 | # Naming 10 | variable "lab_name" { 11 | default = "lab" 12 | } 13 | # Sizing 14 | variable "vmsize" { 15 | default = "Standard_B8ms" 16 | } 17 | # Regional 18 | variable "regions" { 19 | type = map(any) 20 | default = { 21 | region1 = { 22 | region = "uksouth" 23 | code = "uks" 24 | cidr = ["10.10.0.0/16"] 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /Virtual-WAN-Demo/resourcegroups.tf: -------------------------------------------------------------------------------- 1 | # Resource Groups Virtual-WAN - Region 1 2 | resource "azurerm_resource_group" "region1-rg1" { 3 | name = "rg-${var.region1}-Virtual-WAN-Demo" 4 | location = var.region1 5 | tags = { 6 | Environment = var.environment_tag 7 | Function = "Virtual-WAN-DemoLab-ResourceGroups" 8 | } 9 | } 10 | # Resource Groups Virtual-WAN - Region 2 11 | resource "azurerm_resource_group" "region2-rg1" { 12 | name = "rg-${var.region2}-Virtual-WAN-Demo" 13 | location = var.region2 14 | tags = { 15 | Environment = var.environment_tag 16 | Function = "Virtual-WAN-DemoLab-ResourceGroups" 17 | } 18 | } -------------------------------------------------------------------------------- /.github/workflows/links.yml: -------------------------------------------------------------------------------- 1 | name: Links 2 | 3 | on: [workflow_dispatch] 4 | 5 | jobs: 6 | linkChecker: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - uses: actions/checkout@v3 10 | 11 | - name: Link Checker 12 | id: lychee 13 | uses: lycheeverse/lychee-action@v1.5.1 14 | env: 15 | GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} 16 | 17 | - name: Create Issue From File 18 | if: steps.lychee.outputs.exit_code != 0 19 | uses: peter-evans/create-issue-from-file@v4 20 | with: 21 | title: Link Checker Report 22 | content-filepath: ./lychee/out.md 23 | labels: report, automated issue 24 | -------------------------------------------------------------------------------- /Core-Environment-DemoLab-v1/provider.tf: -------------------------------------------------------------------------------- 1 | # Providers 2 | terraform { 3 | required_providers { 4 | azurerm = { 5 | source = "hashicorp/azurerm" 6 | version = ">= 4.56.0" 7 | } 8 | random = { 9 | source = "hashicorp/random" 10 | version = ">= 3.7.2" 11 | } 12 | } 13 | } 14 | # Provider Config 15 | provider "azurerm" { 16 | subscription_id = var.subscription_id 17 | tenant_id = var.tenant_id 18 | client_id = var.client_id 19 | client_secret = var.client_secret 20 | # Configuration options 21 | features { 22 | key_vault { 23 | purge_soft_delete_on_destroy = true 24 | } 25 | } 26 | } 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /Cost-Optimization-Example-Lab/README.md: -------------------------------------------------------------------------------- 1 | # Cost Optimization Example Lab 2 | 3 | This environment is an adjusted version of my Single Region Azure BaseLab V2 - albeit with additional resources added to demonstrate elements that will be picked up by cost management tools such as Azure Advisor and Azure Cost Management. Such resources include Public IPs that are not used, extra Disks and more. 4 | 5 | A blog post that uses this environment is available [here](https://jakewalsh.co.uk/azure-advisor-testing-the-cost-optimization-workbook-public-preview/) 6 | 7 | # Single Region Base Lab Environment for Azure - Version 2 8 | 9 | For an overview of this environment, please see [here](https://jakewalsh.co.uk/introducing-single-region-azure-baselab-v2/). -------------------------------------------------------------------------------- /UpdateProviders.PS1: -------------------------------------------------------------------------------- 1 | # This script allows us to update the provider versions in all Provider files within this Repo. 2 | # Provider Details: 3 | $oldazurerm = ' 4 | source = "hashicorp/azurerm" 5 | version = ">= 4.56.0" 6 | ' 7 | $newazurerm = ' 8 | source = "hashicorp/azurerm" 9 | version = ">= 4.56.0" 10 | ' 11 | $oldrandom = ' 12 | source = "hashicorp/random" 13 | version = ">= 3.5.0" 14 | ' 15 | $newrandom = ' 16 | source = "hashicorp/random" 17 | version = ">= 3.7.2" 18 | ' 19 | Get-ChildItem . -Recurse | Where-Object Name -eq "provider.tf" | foreach-object { 20 | (Get-Content -Raw $_).Replace($oldazurerm, $newazurerm)| Set-Content $_ 21 | (Get-Content -Raw $_).Replace($oldrandom, $newrandom)| Set-Content $_ 22 | } -------------------------------------------------------------------------------- /AVD-Demo-Lab/README.md: -------------------------------------------------------------------------------- 1 | # AVD Demo Environment 2 | 3 | This environment uses Terraform and Packer to provide the foundations for an AVD Environment that can be added to most DevOps toolsets (GitHub Actions, Azure DevOps etc).Current files within this repo are: 4 | 5 | - Terraform-Single-Region-Azure-BaseLab-V2 - This Terraform code creates a basic Azure environment that will provide the foundations required to Demostrate AVD (and other Azure services if required). 6 | - Packer - This code provides Packer files that can be used to create machine images for AVD. Customisation within these images is currently done using PowerShell, with applications installed using Chocolatey. Note: Packer files are now located in their own repository here: https://github.com/jakewalsh90/Packer-Azure 7 | -------------------------------------------------------------------------------- /Core-Environment-DemoLab-v1/terraform.tfvars: -------------------------------------------------------------------------------- 1 | # Core 2 | subscription_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" 3 | tenant_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" 4 | client_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" 5 | client_secret = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" 6 | vpn_app_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" 7 | # Admin Account 8 | admin_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" 9 | # Naming 10 | lab_name = "tfc-lab" 11 | # Sizing 12 | vmsize = "Standard_B8ms" 13 | # Regional Map 14 | regions = { 15 | region1 = { 16 | region = "uksouth" 17 | code = "uks" 18 | cidr = "10.10.0.0/19" 19 | } 20 | # region2 = { 21 | # region = "eastus" 22 | # code = "eus" 23 | # cidr = "10.11.0.0/19" 24 | # } 25 | } -------------------------------------------------------------------------------- /Virtual-WAN-Demo/terraform.tfvars: -------------------------------------------------------------------------------- 1 | # Core Variables 2 | environment_tag = "jakewalsh90-virtual-wan-DemoLab" 3 | region1 = "uksouth" 4 | region2 = "eastus" 5 | virtual-wan-region1-hub1-prefix1 = "10.10.0.0/21" 6 | virtual-wan-region2-hub1-prefix1 = "10.20.0.0/21" 7 | # Networking 8 | region1-vnet1-address-space = "10.10.8.0/21" 9 | region1-vnet1-snet1-range = "10.10.11.0/24" 10 | region1-vnet1-bastion-snet-range = "10.10.12.0/24" 11 | region2-vnet1-address-space = "10.20.8.0/21" 12 | region2-vnet1-snet1-range = "10.20.11.0/24" 13 | region2-vnet1-bastion-snet-range = "10.20.12.0/24" 14 | # VMs 15 | vmsize = "Standard_B4ms" 16 | adminusername = "labadmin" 17 | # Optional - Firewalls 18 | azfw = false -------------------------------------------------------------------------------- /.github/workflows/destroy.yml: -------------------------------------------------------------------------------- 1 | name: Terraform Destroy 2 | 3 | on: [workflow_dispatch] 4 | 5 | defaults: 6 | run: 7 | working-directory: ./your-tf-directory 8 | 9 | jobs: 10 | terraform: 11 | runs-on: ubuntu-latest 12 | 13 | env: 14 | ARM_CLIENT_ID: ${{secrets.ARM_CLIENT_ID}} 15 | ARM_CLIENT_SECRET: ${{secrets.ARM_CLIENT_SECRET}} 16 | ARM_SUBSCRIPTION_ID: ${{secrets.ARM_SUBSCRIPTION_ID}} 17 | ARM_TENANT_ID: ${{secrets.ARM_TENANT_ID}} 18 | 19 | steps: 20 | - uses: actions/checkout@v2 21 | 22 | - name: Setup Terraform 23 | uses: hashicorp/setup-terraform@v1 24 | 25 | - name: Terraform Init 26 | run: terraform init 27 | 28 | - name: Terraform Destroy 29 | run: terraform destroy --auto-approve 30 | -------------------------------------------------------------------------------- /Cost-Optimization-Example-Lab/terraform.tfvars: -------------------------------------------------------------------------------- 1 | ########################### 2 | # Core Features - Variables 3 | ########################### 4 | 5 | # Tags 6 | environment_tag = "jakewalsh90-baselab-v2" 7 | # Regional 8 | region1 = "uksouth" 9 | region1code = "uks" 10 | # Networking 11 | # Note - changing to anything other than /19 will require checking IP ranges/addressing within the Code. 12 | region1cidr = "10.10.0.0/19" 13 | # Identity VMs 14 | # Note - 1 VM is the minimum 15 | vmcount = "3" 16 | vmsize = "Standard_D2s_v4" 17 | adminuser = "labadmin" 18 | 19 | ############################### 20 | # Optional Features - Variables 21 | ############################### 22 | 23 | # Azure Bastion 24 | bastion = true 25 | # AVD Supporting Elements 26 | avd = true 27 | # Virtual Network Gateway 28 | vng = true 29 | # Firewall 30 | azfw = true -------------------------------------------------------------------------------- /Single-Region-Azure-BaseLab-v2/terraform.tfvars: -------------------------------------------------------------------------------- 1 | ########################### 2 | # Core Features - Variables 3 | ########################### 4 | 5 | # Tags 6 | environment_tag = "jakewalsh90-baselab-v2" 7 | # Regional 8 | region1 = "uksouth" 9 | region1code = "uks" 10 | # Networking 11 | # Note - changing to anything other than /19 will require checking IP ranges/addressing within the Code. 12 | region1cidr = "10.10.0.0/19" 13 | # Identity VMs 14 | # Note - 1 VM is the minimum 15 | vmcount = "1" 16 | vmsize = "Standard_D2s_v4" 17 | adminuser = "labadmin" 18 | 19 | ############################### 20 | # Optional Features - Variables 21 | ############################### 22 | 23 | # Azure Bastion 24 | bastion = true 25 | # AVD Supporting Elements 26 | avd = true 27 | # Virtual Network Gateway 28 | vng = true 29 | # Firewall 30 | azfw = true -------------------------------------------------------------------------------- /AVD-Demo-Lab/Terraform-Single-Region-Azure-BaseLab-v2/terraform.tfvars: -------------------------------------------------------------------------------- 1 | ########################### 2 | # Core Features - Variables 3 | ########################### 4 | 5 | # Tags 6 | environment_tag = "jakewalsh90-baselab-v2" 7 | # Regional 8 | region1 = "uksouth" 9 | region1code = "uks" 10 | # Networking 11 | # Note - changing to anything other than /19 will require checking IP ranges/addressing within the Code. 12 | region1cidr = "10.10.0.0/19" 13 | # Identity VMs 14 | # Note - 1 VM is the minimum 15 | vmcount = "1" 16 | vmsize = "Standard_D2s_v4" 17 | adminuser = "labadmin" 18 | 19 | ############################### 20 | # Optional Features - Variables 21 | ############################### 22 | 23 | # Azure Bastion 24 | bastion = true 25 | # AVD Supporting Elements 26 | avd = true 27 | # Virtual Network Gateway 28 | vng = true 29 | # Firewall 30 | azfw = true -------------------------------------------------------------------------------- /Ansible-Quickstart/README.md: -------------------------------------------------------------------------------- 1 | # Ansible Azure Quickstart 2 | 3 | ## Overview 4 | This code creates a Ubuntu Server VM with Ansible installed. Designed to get you up and running quickly with Ansible in Azure. 5 | 6 | *It is not intended for production use!* 7 | 8 | ## What this code creates 9 | 10 | 1. Creates a VNET with a Subnet for the Ansible VM 11 | 2. Creates a KeyVault 12 | 3. Creates a random password value and stores this inside the KeyVault - this Password is used for the Ansible VM 13 | 4. Gets your client IP and uses this to create an NSG for secure SSH access into the VM 14 | 5. Creates an Ubuntu Server VM 15 | 6. Uses a custom script extension to install Ansible & dependencies for Azure on the Ubuntu VM 16 | 17 | See [https://jakewalsh.co.uk/ansible-and-azure-30-minute-quickstart/](https://jakewalsh.co.uk/ansible-and-azure-30-minute-quickstart/) for a guide to setup and usage. -------------------------------------------------------------------------------- /Setup-Scripts/readme.md: -------------------------------------------------------------------------------- 1 | # Setup scripts for using this Repo 2 | 3 | ## Windows 4 | 5 | Using the two PowerShell scripts you can install Chocolatey and then the required apps for this repo. 6 | 7 | - [TerraformApps.ps1](https://github.com/jakewalsh90/Terraform-Azure/blob/main/Setup-Scripts/TerraformApps.ps1) - Installs the Apps needed to work with Terraform. 8 | - [AllApps.ps1](https://github.com/jakewalsh90/Terraform-Azure/blob/main/Setup-Scripts/AllApps.ps1) - Installs all the Apps I use on my Windows machine for working with Terraform, Packer, GitHub, and more. 9 | 10 | ## Mac OSX 11 | 12 | I would recommend using Brew to install the required applications - see here: https://formulae.brew.sh/ 13 | 14 | ## Further Reading 15 | 16 | For official installation guides for Terraform - see here: https://developer.hashicorp.com/terraform/tutorials/azure-get-started/install-cli#install-terraform -------------------------------------------------------------------------------- /Azure-Automation-Demo/readme.md: -------------------------------------------------------------------------------- 1 | # Azure Automation Demo Environment 2 | 3 | This lab creates a simple Azure Automation environment, that shuts down VMs with a specific tag on a scheduled basis. The tag required on any VMs you wish to use with this Lab is "DailyShutdown" and the Tag Value for this Lab is "1800". VMs with this Tag and Value will be shut down every day at 1800. Note the time zone is set to Europe/London - you will also need to adjust the start date as required. 4 | 5 | The following resources are created: 6 | 7 | - A Resource Group. 8 | - Azure Automation Account. 9 | - Azure Automation Runbook. 10 | - PowerShell script to shutdown VMs with a specific tag. 11 | - Azure Automation Schedule. 12 | - Azure Automation Managed Identity (for Azure Automation Runbook, which assigns Contributor permissions to the current Subscription). 13 | - Azure Automation Schedule, and Job Schedule set to run every day at 6pm. -------------------------------------------------------------------------------- /Azure-OpenAI-Demo-1/README.md: -------------------------------------------------------------------------------- 1 | # Azure Open AI Demo 2 | 3 | ** Note: this is work in progress! ** 4 | 5 | ## Overview 6 | This code creates an Azure Cognitive Services Resource - with Azure Open AI Services, to allow rapid deployment and testing. 7 | 8 | This environment deploys the following items: 9 | 10 | 1. A Resource Group in a Region that is based upon a variable. 11 | 2. Two Random IDs (using the Random Provider) to be used for naming. 12 | 3. An Azure OpenAI Resource 13 | 4. Two Models - gpt-35-turbo and text-embedding-ada-002 within the Azure OpenAI Resource. 14 | 5. Private Networking Features - including VNET, Subnet, Custom Subdomain Name (For the OpenAI Resource), and a Service Endpoint. 15 | 16 | Note: Private Networking is selected by changing the variable "privatenetworking" to true within the terraform.tfvars file. 17 | 18 | CIDR Ranges are also adjusted for the VNET and Subnet within the terraform.tfvars. -------------------------------------------------------------------------------- /.github/workflows/apply.yml: -------------------------------------------------------------------------------- 1 | name: Terraform Validate, Plan, Apply 2 | 3 | on: [workflow_dispatch] 4 | 5 | defaults: 6 | run: 7 | working-directory: ./your-tf-directory 8 | 9 | jobs: 10 | terraform: 11 | runs-on: ubuntu-latest 12 | 13 | env: 14 | ARM_CLIENT_ID: ${{secrets.ARM_CLIENT_ID}} 15 | ARM_CLIENT_SECRET: ${{secrets.ARM_CLIENT_SECRET}} 16 | ARM_SUBSCRIPTION_ID: ${{secrets.ARM_SUBSCRIPTION_ID}} 17 | ARM_TENANT_ID: ${{secrets.ARM_TENANT_ID}} 18 | 19 | steps: 20 | - uses: actions/checkout@v2 21 | 22 | - name: Setup Terraform 23 | uses: hashicorp/setup-terraform@v1 24 | 25 | - name: Terraform Init 26 | run: terraform init 27 | 28 | - name: Terraform Validate 29 | run: terraform validate 30 | 31 | - name: Terraform Plan 32 | run: terraform plan 33 | 34 | - name: Terraform Apply 35 | run: terraform apply --auto-approve 36 | -------------------------------------------------------------------------------- /Single-Region-Azure-BaseLab-v2/README.md: -------------------------------------------------------------------------------- 1 | # Single Region Base Lab Environment for Azure - Version 2 2 | 3 | For an overview of this environment, please see [here](https://jakewalsh.co.uk/introducing-single-region-azure-baselab-v2/). 4 | 5 | This environment is also available as a Terraform Module - see [here](https://github.com/jakewalsh90/Terraform-Modules-Azure/tree/main/azure-single-region-baselabv2). 6 | 7 | ## Manual Steps to complete Lab Environment 8 | #### The two powershell scripts should be run to complete the setup process on the created Virtual Machine. The scripts promote the VM to a domain controller and then setup a basic Lab OU structure. 9 | 10 | These will be in C:\baselabSetup of the DC VM after deployment, and should be run in this order: 11 | 12 | 1. baselab_DomainSetup.ps1 - the machine will reboot after this. 13 | 2. baselab_LabStructure.ps1 - this will setup a basic OU structure. 14 | 15 | The lab is now deployed and ready to use. 16 | -------------------------------------------------------------------------------- /Ansible-Quickstart/variables.tf: -------------------------------------------------------------------------------- 1 | variable "environment_tag" { 2 | type = string 3 | description = "Environment tag value" 4 | } 5 | variable "azure-rg-1" { 6 | type = string 7 | description = "resource group 1" 8 | } 9 | variable "loc1" { 10 | description = "The location for this Lab environment" 11 | type = string 12 | } 13 | variable "region1-vnet1-name" { 14 | description = "VNET1 Name" 15 | type = string 16 | } 17 | variable "region1-vnet1-address-space" { 18 | description = "VNET address space" 19 | type = string 20 | } 21 | variable "region1-vnet1-snet1-name" { 22 | description = "subnet name" 23 | type = string 24 | } 25 | variable "region1-vnet1-snet1-range" { 26 | description = "subnet range" 27 | type = string 28 | } 29 | variable "vmsize" { 30 | description = "size of vm" 31 | type = string 32 | } 33 | variable "adminusername" { 34 | description = "administrator username for virtual machines" 35 | type = string 36 | } -------------------------------------------------------------------------------- /Single-Region-Azure-BaseLab-with-Ansible/README.md: -------------------------------------------------------------------------------- 1 | # Single Region Base Lab Environment for Azure - with Ansible VM 2 | 3 | ## Overview 4 | This code creates a simple Lab environment within a Single Azure Region, and also includes an Ubuntu Server VM with Ansible installed. For documentation please see [Single-Region-Azure-BaseLab](..//Single-Region-Azure-BaseLab) - this lab is identical, albeit for the Ansible elements. 5 | 6 | *It is not intended for production use!* 7 | 8 | ## Extra elements 9 | 10 | 1. Creates "anpassword" in the KeyVault - this is the Password to log into the Ansible VM 11 | 2. Creates an Ubuntu Server VM to use for Ansible 12 | 3. Creates a Custom Script Extension which runs AnsibleSetup.sh from the Ansible directory in this repo. 13 | 14 | This lab includes everything from the [Single-Region-Azure-BaseLab](..//Single-Region-Azure-BaseLab), but with the additional Ansible VM above. The Domain Setup scripts still need to be run as per the linked Single-Region-Azure-Baselab documentation. 15 | -------------------------------------------------------------------------------- /Web-Server-IIS-DemoLab/.gitignore: -------------------------------------------------------------------------------- 1 | ### Terraform ### 2 | # Local .terraform directories 3 | **/.terraform/* 4 | 5 | # .tfstate files 6 | *.tfstate 7 | *.tfstate.* 8 | *.terraform.lock.hcl* 9 | 10 | #Other files 11 | *.DS_Store* 12 | 13 | # Crash log files 14 | crash.log 15 | 16 | # Ignore any .tfvars files that are generated automatically for each Terraform run. Most 17 | # .tfvars files are managed as part of configuration and so should be included in 18 | # version control. 19 | # 20 | # example.tfvars 21 | 22 | # Ignore override files as they are usually used to override resources locally and so 23 | # are not checked in 24 | override.tf 25 | override.tf.json 26 | *_override.tf 27 | *_override.tf.json 28 | 29 | # Include override files you do wish to add to version control using negated pattern 30 | # !example_override.tf 31 | 32 | # Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan 33 | # example: *tfplan* 34 | 35 | # End of https://www.toptal.com/developers/gitignore/api/terraform -------------------------------------------------------------------------------- /Azure-Backup-Demo-Resources/VM.tf: -------------------------------------------------------------------------------- 1 | # random string 2 | resource "random_id" "vaultid1" { 3 | byte_length = 5 4 | prefix = "rsv" 5 | } 6 | # Resource Group 7 | resource "azurerm_resource_group" "rg1" { 8 | name = "rg-backup-01" 9 | location = var.location 10 | } 11 | # Recovery Services Vault 12 | resource "azurerm_recovery_services_vault" "rsv1" { 13 | name = random_id.vaultid1.hex 14 | location = var.location 15 | resource_group_name = azurerm_resource_group.rg1.name 16 | sku = "Standard" 17 | 18 | soft_delete_enabled = true 19 | } 20 | # Backup Policy 21 | resource "azurerm_backup_policy_vm" "backup-pol1" { 22 | name = "terraform-example-backup-01" 23 | resource_group_name = azurerm_resource_group.rg1.name 24 | recovery_vault_name = azurerm_recovery_services_vault.rsv1.name 25 | policy_type = "V2" 26 | 27 | backup { 28 | frequency = "Daily" 29 | time = "23:00" 30 | } 31 | retention_daily { 32 | count = 10 33 | } 34 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Local .terraform directories 2 | **/.terraform/* 3 | 4 | # .tfstate files 5 | *.tfstate 6 | *.tfstate.* 7 | *.terraform.lock.hcl* 8 | 9 | # Crash log files 10 | crash.log 11 | crash.*.log 12 | 13 | # Exclude all .tfvars files, which are likely to contain sensitive data, such as 14 | # password, private keys, and other secrets. These should not be part of version 15 | # control as they are data points which are potentially sensitive and subject 16 | # to change depending on the environment. 17 | 18 | # Ignore override files as they are usually used to override resources locally and so 19 | # are not checked in 20 | override.tf 21 | override.tf.json 22 | *_override.tf 23 | *_override.tf.json 24 | 25 | # Include override files you do wish to add to version control using negated pattern 26 | # !example_override.tf 27 | 28 | # Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan 29 | # example: *tfplan* 30 | 31 | # Ignore CLI configuration files 32 | .terraformrc 33 | terraform.rc 34 | 35 | # Other Files 36 | *.DS_Store* -------------------------------------------------------------------------------- /Core-Environment-DemoLab-v1/readme.md: -------------------------------------------------------------------------------- 1 | This lab is an environment that I deploy with Terraform Cloud to quickly get an Azure Environment up and running - allowing me to demonstrate concepts and test ideas. 2 | 3 | These labs can also be used with other deployment methods and tooling, but the guide below is for Terraform Cloud. Follow the notes below to deploy. 4 | 5 | For a guide on setting up a Service Principal see here: https://github.com/jakewalsh90/Terraform-Azure/tree/main/Terraform-Cloud-Deployment 6 | 7 | ## Pre reqs: 8 | 9 | The following elements need to be added to Terraform Cloud as variables: 10 | 11 | ### All Labs 12 | - admin_id - The admin user id to be added to the Key Vault access policies. 13 | - client_id - Service Principal ID 14 | - client_secret - Service Principal Secret 15 | - subscription_id - Subscription ID you want to deploy into 16 | - tenant_id - Tenant ID of the Azure Tenant you want to deploy into 17 | - vpn_app_id - ID of the VPN Enterprise Application, see https://learn.microsoft.com/en-us/azure/vpn-gateway/openvpn-azure-ad-tenant -------------------------------------------------------------------------------- /AVD-Demo-Lab/.gitignore: -------------------------------------------------------------------------------- 1 | # Local .terraform directories 2 | **/.terraform/* 3 | 4 | # .tfstate files 5 | *.tfstate 6 | *.tfstate.* 7 | *.terraform.lock.hcl* 8 | 9 | # Crash log files 10 | crash.log 11 | crash.*.log 12 | 13 | # Exclude all .tfvars files, which are likely to contain sensitive data, such as 14 | # password, private keys, and other secrets. These should not be part of version 15 | # control as they are data points which are potentially sensitive and subject 16 | # to change depending on the environment. 17 | 18 | # Ignore override files as they are usually used to override resources locally and so 19 | # are not checked in 20 | override.tf 21 | override.tf.json 22 | *_override.tf 23 | *_override.tf.json 24 | 25 | # Include override files you do wish to add to version control using negated pattern 26 | # !example_override.tf 27 | 28 | # Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan 29 | # example: *tfplan* 30 | 31 | # Ignore CLI configuration files 32 | .terraformrc 33 | terraform.rc 34 | 35 | # Other Files 36 | *.DS_Store* -------------------------------------------------------------------------------- /PowerShell/baselab_LabStructure.ps1: -------------------------------------------------------------------------------- 1 | #Setup Variables 2 | $DCRoot = "DC=ad,DC=lab" 3 | $LabDCRoot = "OU=Lab,DC=ad,DC=Lab" 4 | #Create Root Lab OU 5 | New-ADOrganizationalUnit -Name "Lab" -Path $DCRoot -ProtectedFromAccidentalDeletion $False -Description "Lab Environment" 6 | #Create Other OUs 7 | New-ADOrganizationalUnit -Name "Users" -Path $LabDCRoot -ProtectedFromAccidentalDeletion $False -Description "Lab Users" 8 | New-ADOrganizationalUnit -Name "Service Accounts" -Path $LabDCRoot -ProtectedFromAccidentalDeletion $False -Description "Lab Service Accounts" 9 | New-ADOrganizationalUnit -Name "Servers" -Path $LabDCRoot -ProtectedFromAccidentalDeletion $False -Description "Lab Servers" 10 | New-ADOrganizationalUnit -Name "AVD" -Path $LabDCRoot -ProtectedFromAccidentalDeletion $False -Description "Lab AVD Session Hosts" 11 | New-ADOrganizationalUnit -Name "Computers" -Path $LabDCRoot -ProtectedFromAccidentalDeletion $False -Description "Lab Computers" 12 | New-ADOrganizationalUnit -Name "ANF" -Path $LabDCRoot -ProtectedFromAccidentalDeletion $False -Description "Lab ANF Objects" 13 | -------------------------------------------------------------------------------- /CIDRHost-Demo/.gitignore: -------------------------------------------------------------------------------- 1 | # Local .terraform directories 2 | **/.terraform/* 3 | 4 | # .tfstate files 5 | *.tfstate 6 | *.tfstate.* 7 | *.terraform.lock.hcl* 8 | 9 | # Crash log files 10 | crash.log 11 | crash.*.log 12 | 13 | # Exclude all .tfvars files, which are likely to contain sensitive data, such as 14 | # password, private keys, and other secrets. These should not be part of version 15 | # control as they are data points which are potentially sensitive and subject 16 | # to change depending on the environment. 17 | 18 | # Ignore override files as they are usually used to override resources locally and so 19 | # are not checked in 20 | override.tf 21 | override.tf.json 22 | *_override.tf 23 | *_override.tf.json 24 | 25 | # Include override files you do wish to add to version control using negated pattern 26 | # !example_override.tf 27 | 28 | # Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan 29 | # example: *tfplan* 30 | 31 | # Ignore CLI configuration files 32 | .terraformrc 33 | terraform.rc 34 | 35 | # Other Files 36 | *.DS_Store* -------------------------------------------------------------------------------- /CIDRSubnet-Demo/.gitignore: -------------------------------------------------------------------------------- 1 | # Local .terraform directories 2 | **/.terraform/* 3 | 4 | # .tfstate files 5 | *.tfstate 6 | *.tfstate.* 7 | *.terraform.lock.hcl* 8 | 9 | # Crash log files 10 | crash.log 11 | crash.*.log 12 | 13 | # Exclude all .tfvars files, which are likely to contain sensitive data, such as 14 | # password, private keys, and other secrets. These should not be part of version 15 | # control as they are data points which are potentially sensitive and subject 16 | # to change depending on the environment. 17 | 18 | # Ignore override files as they are usually used to override resources locally and so 19 | # are not checked in 20 | override.tf 21 | override.tf.json 22 | *_override.tf 23 | *_override.tf.json 24 | 25 | # Include override files you do wish to add to version control using negated pattern 26 | # !example_override.tf 27 | 28 | # Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan 29 | # example: *tfplan* 30 | 31 | # Ignore CLI configuration files 32 | .terraformrc 33 | terraform.rc 34 | 35 | # Other Files 36 | *.DS_Store* -------------------------------------------------------------------------------- /Chaos-Studio-Test/.gitignore: -------------------------------------------------------------------------------- 1 | # Local .terraform directories 2 | **/.terraform/* 3 | 4 | # .tfstate files 5 | *.tfstate 6 | *.tfstate.* 7 | *.terraform.lock.hcl* 8 | 9 | # Crash log files 10 | crash.log 11 | crash.*.log 12 | 13 | # Exclude all .tfvars files, which are likely to contain sensitive data, such as 14 | # password, private keys, and other secrets. These should not be part of version 15 | # control as they are data points which are potentially sensitive and subject 16 | # to change depending on the environment. 17 | 18 | # Ignore override files as they are usually used to override resources locally and so 19 | # are not checked in 20 | override.tf 21 | override.tf.json 22 | *_override.tf 23 | *_override.tf.json 24 | 25 | # Include override files you do wish to add to version control using negated pattern 26 | # !example_override.tf 27 | 28 | # Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan 29 | # example: *tfplan* 30 | 31 | # Ignore CLI configuration files 32 | .terraformrc 33 | terraform.rc 34 | 35 | # Other Files 36 | *.DS_Store* -------------------------------------------------------------------------------- /Virtual-WAN-Demo/.gitignore: -------------------------------------------------------------------------------- 1 | # Local .terraform directories 2 | **/.terraform/* 3 | 4 | # .tfstate files 5 | *.tfstate 6 | *.tfstate.* 7 | *.terraform.lock.hcl* 8 | 9 | # Crash log files 10 | crash.log 11 | crash.*.log 12 | 13 | # Exclude all .tfvars files, which are likely to contain sensitive data, such as 14 | # password, private keys, and other secrets. These should not be part of version 15 | # control as they are data points which are potentially sensitive and subject 16 | # to change depending on the environment. 17 | 18 | # Ignore override files as they are usually used to override resources locally and so 19 | # are not checked in 20 | override.tf 21 | override.tf.json 22 | *_override.tf 23 | *_override.tf.json 24 | 25 | # Include override files you do wish to add to version control using negated pattern 26 | # !example_override.tf 27 | 28 | # Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan 29 | # example: *tfplan* 30 | 31 | # Ignore CLI configuration files 32 | .terraformrc 33 | terraform.rc 34 | 35 | # Other Files 36 | *.DS_Store* -------------------------------------------------------------------------------- /Ansible-Quickstart/.gitignore: -------------------------------------------------------------------------------- 1 | # Local .terraform directories 2 | **/.terraform/* 3 | 4 | # .tfstate files 5 | *.tfstate 6 | *.tfstate.* 7 | *.terraform.lock.hcl* 8 | 9 | # Crash log files 10 | crash.log 11 | crash.*.log 12 | 13 | # Exclude all .tfvars files, which are likely to contain sensitive data, such as 14 | # password, private keys, and other secrets. These should not be part of version 15 | # control as they are data points which are potentially sensitive and subject 16 | # to change depending on the environment. 17 | 18 | # Ignore override files as they are usually used to override resources locally and so 19 | # are not checked in 20 | override.tf 21 | override.tf.json 22 | *_override.tf 23 | *_override.tf.json 24 | 25 | # Include override files you do wish to add to version control using negated pattern 26 | # !example_override.tf 27 | 28 | # Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan 29 | # example: *tfplan* 30 | 31 | # Ignore CLI configuration files 32 | .terraformrc 33 | terraform.rc 34 | 35 | # Other Files 36 | *.DS_Store* -------------------------------------------------------------------------------- /Automatic-ClientIP-NSG/.gitignore: -------------------------------------------------------------------------------- 1 | # Local .terraform directories 2 | **/.terraform/* 3 | 4 | # .tfstate files 5 | *.tfstate 6 | *.tfstate.* 7 | *.terraform.lock.hcl* 8 | 9 | # Crash log files 10 | crash.log 11 | crash.*.log 12 | 13 | # Exclude all .tfvars files, which are likely to contain sensitive data, such as 14 | # password, private keys, and other secrets. These should not be part of version 15 | # control as they are data points which are potentially sensitive and subject 16 | # to change depending on the environment. 17 | 18 | # Ignore override files as they are usually used to override resources locally and so 19 | # are not checked in 20 | override.tf 21 | override.tf.json 22 | *_override.tf 23 | *_override.tf.json 24 | 25 | # Include override files you do wish to add to version control using negated pattern 26 | # !example_override.tf 27 | 28 | # Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan 29 | # example: *tfplan* 30 | 31 | # Ignore CLI configuration files 32 | .terraformrc 33 | terraform.rc 34 | 35 | # Other Files 36 | *.DS_Store* -------------------------------------------------------------------------------- /Azure Lab Services/.gitignore: -------------------------------------------------------------------------------- 1 | # Local .terraform directories 2 | **/.terraform/* 3 | 4 | # .tfstate files 5 | *.tfstate 6 | *.tfstate.* 7 | *.terraform.lock.hcl* 8 | 9 | # Crash log files 10 | crash.log 11 | crash.*.log 12 | 13 | # Exclude all .tfvars files, which are likely to contain sensitive data, such as 14 | # password, private keys, and other secrets. These should not be part of version 15 | # control as they are data points which are potentially sensitive and subject 16 | # to change depending on the environment. 17 | 18 | # Ignore override files as they are usually used to override resources locally and so 19 | # are not checked in 20 | override.tf 21 | override.tf.json 22 | *_override.tf 23 | *_override.tf.json 24 | 25 | # Include override files you do wish to add to version control using negated pattern 26 | # !example_override.tf 27 | 28 | # Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan 29 | # example: *tfplan* 30 | 31 | # Ignore CLI configuration files 32 | .terraformrc 33 | terraform.rc 34 | 35 | # Other Files 36 | *.DS_Store* -------------------------------------------------------------------------------- /Azure-Automation-Demo/.gitignore: -------------------------------------------------------------------------------- 1 | # Local .terraform directories 2 | **/.terraform/* 3 | 4 | # .tfstate files 5 | *.tfstate 6 | *.tfstate.* 7 | *.terraform.lock.hcl* 8 | 9 | # Crash log files 10 | crash.log 11 | crash.*.log 12 | 13 | # Exclude all .tfvars files, which are likely to contain sensitive data, such as 14 | # password, private keys, and other secrets. These should not be part of version 15 | # control as they are data points which are potentially sensitive and subject 16 | # to change depending on the environment. 17 | 18 | # Ignore override files as they are usually used to override resources locally and so 19 | # are not checked in 20 | override.tf 21 | override.tf.json 22 | *_override.tf 23 | *_override.tf.json 24 | 25 | # Include override files you do wish to add to version control using negated pattern 26 | # !example_override.tf 27 | 28 | # Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan 29 | # example: *tfplan* 30 | 31 | # Ignore CLI configuration files 32 | .terraformrc 33 | terraform.rc 34 | 35 | # Other Files 36 | *.DS_Store* -------------------------------------------------------------------------------- /Azure-Firewall-DemoLab/.gitignore: -------------------------------------------------------------------------------- 1 | # Local .terraform directories 2 | **/.terraform/* 3 | 4 | # .tfstate files 5 | *.tfstate 6 | *.tfstate.* 7 | *.terraform.lock.hcl* 8 | 9 | # Crash log files 10 | crash.log 11 | crash.*.log 12 | 13 | # Exclude all .tfvars files, which are likely to contain sensitive data, such as 14 | # password, private keys, and other secrets. These should not be part of version 15 | # control as they are data points which are potentially sensitive and subject 16 | # to change depending on the environment. 17 | 18 | # Ignore override files as they are usually used to override resources locally and so 19 | # are not checked in 20 | override.tf 21 | override.tf.json 22 | *_override.tf 23 | *_override.tf.json 24 | 25 | # Include override files you do wish to add to version control using negated pattern 26 | # !example_override.tf 27 | 28 | # Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan 29 | # example: *tfplan* 30 | 31 | # Ignore CLI configuration files 32 | .terraformrc 33 | terraform.rc 34 | 35 | # Other Files 36 | *.DS_Store* -------------------------------------------------------------------------------- /Azure-OpenAI-Demo-1/.gitignore: -------------------------------------------------------------------------------- 1 | # Local .terraform directories 2 | **/.terraform/* 3 | 4 | # .tfstate files 5 | *.tfstate 6 | *.tfstate.* 7 | *.terraform.lock.hcl* 8 | 9 | # Crash log files 10 | crash.log 11 | crash.*.log 12 | 13 | # Exclude all .tfvars files, which are likely to contain sensitive data, such as 14 | # password, private keys, and other secrets. These should not be part of version 15 | # control as they are data points which are potentially sensitive and subject 16 | # to change depending on the environment. 17 | 18 | # Ignore override files as they are usually used to override resources locally and so 19 | # are not checked in 20 | override.tf 21 | override.tf.json 22 | *_override.tf 23 | *_override.tf.json 24 | 25 | # Include override files you do wish to add to version control using negated pattern 26 | # !example_override.tf 27 | 28 | # Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan 29 | # example: *tfplan* 30 | 31 | # Ignore CLI configuration files 32 | .terraformrc 33 | terraform.rc 34 | 35 | # Other Files 36 | *.DS_Store* -------------------------------------------------------------------------------- /Azure-Backup-Demo-Resources/.gitignore: -------------------------------------------------------------------------------- 1 | # Local .terraform directories 2 | **/.terraform/* 3 | 4 | # .tfstate files 5 | *.tfstate 6 | *.tfstate.* 7 | *.terraform.lock.hcl* 8 | 9 | # Crash log files 10 | crash.log 11 | crash.*.log 12 | 13 | # Exclude all .tfvars files, which are likely to contain sensitive data, such as 14 | # password, private keys, and other secrets. These should not be part of version 15 | # control as they are data points which are potentially sensitive and subject 16 | # to change depending on the environment. 17 | 18 | # Ignore override files as they are usually used to override resources locally and so 19 | # are not checked in 20 | override.tf 21 | override.tf.json 22 | *_override.tf 23 | *_override.tf.json 24 | 25 | # Include override files you do wish to add to version control using negated pattern 26 | # !example_override.tf 27 | 28 | # Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan 29 | # example: *tfplan* 30 | 31 | # Ignore CLI configuration files 32 | .terraformrc 33 | terraform.rc 34 | 35 | # Other Files 36 | *.DS_Store* -------------------------------------------------------------------------------- /Azure-KeyVault-with-Secret/.gitignore: -------------------------------------------------------------------------------- 1 | # Local .terraform directories 2 | **/.terraform/* 3 | 4 | # .tfstate files 5 | *.tfstate 6 | *.tfstate.* 7 | *.terraform.lock.hcl* 8 | 9 | # Crash log files 10 | crash.log 11 | crash.*.log 12 | 13 | # Exclude all .tfvars files, which are likely to contain sensitive data, such as 14 | # password, private keys, and other secrets. These should not be part of version 15 | # control as they are data points which are potentially sensitive and subject 16 | # to change depending on the environment. 17 | 18 | # Ignore override files as they are usually used to override resources locally and so 19 | # are not checked in 20 | override.tf 21 | override.tf.json 22 | *_override.tf 23 | *_override.tf.json 24 | 25 | # Include override files you do wish to add to version control using negated pattern 26 | # !example_override.tf 27 | 28 | # Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan 29 | # example: *tfplan* 30 | 31 | # Ignore CLI configuration files 32 | .terraformrc 33 | terraform.rc 34 | 35 | # Other Files 36 | *.DS_Store* -------------------------------------------------------------------------------- /Core-Environment-DemoLab-v1/.gitignore: -------------------------------------------------------------------------------- 1 | # Local .terraform directories 2 | **/.terraform/* 3 | 4 | # .tfstate files 5 | *.tfstate 6 | *.tfstate.* 7 | *.terraform.lock.hcl* 8 | 9 | # Crash log files 10 | crash.log 11 | crash.*.log 12 | 13 | # Exclude all .tfvars files, which are likely to contain sensitive data, such as 14 | # password, private keys, and other secrets. These should not be part of version 15 | # control as they are data points which are potentially sensitive and subject 16 | # to change depending on the environment. 17 | 18 | # Ignore override files as they are usually used to override resources locally and so 19 | # are not checked in 20 | override.tf 21 | override.tf.json 22 | *_override.tf 23 | *_override.tf.json 24 | 25 | # Include override files you do wish to add to version control using negated pattern 26 | # !example_override.tf 27 | 28 | # Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan 29 | # example: *tfplan* 30 | 31 | # Ignore CLI configuration files 32 | .terraformrc 33 | terraform.rc 34 | 35 | # Other Files 36 | *.DS_Store* -------------------------------------------------------------------------------- /Core-Environment-DemoLab-v1/bastion.tf: -------------------------------------------------------------------------------- 1 | # Bastion 2 | resource "azurerm_public_ip" "bastion-pip" { 3 | for_each = var.regions 4 | name = "pip-${each.value.code}-bst-01" 5 | resource_group_name = azurerm_resource_group.rg-con[each.key].name 6 | location = each.value.region 7 | allocation_method = "Static" 8 | sku = "Standard" 9 | tags = { environment = "management", region = each.value.code, tfcreated = "true" } 10 | } 11 | resource "azurerm_bastion_host" "bastion" { 12 | for_each = var.regions 13 | name = "bst-${each.value.code}-01" 14 | resource_group_name = azurerm_resource_group.rg-con[each.key].name 15 | location = each.value.region 16 | ip_configuration { 17 | name = "bst-${each.value.code}-01" 18 | subnet_id = azurerm_subnet.management1[each.key].id 19 | public_ip_address_id = azurerm_public_ip.bastion-pip[each.key].id 20 | } 21 | tags = { environment = "management", region = each.value.code, tfcreated = "true" } 22 | } -------------------------------------------------------------------------------- /Dual-Region-Azure-BaseLab/.gitignore: -------------------------------------------------------------------------------- 1 | # Local .terraform directories 2 | **/.terraform/* 3 | 4 | # .tfstate files 5 | *.tfstate 6 | *.tfstate.* 7 | *.terraform.lock.hcl* 8 | 9 | # Crash log files 10 | crash.log 11 | crash.*.log 12 | 13 | # Exclude all .tfvars files, which are likely to contain sensitive data, such as 14 | # password, private keys, and other secrets. These should not be part of version 15 | # control as they are data points which are potentially sensitive and subject 16 | # to change depending on the environment. 17 | 18 | # Ignore override files as they are usually used to override resources locally and so 19 | # are not checked in 20 | override.tf 21 | override.tf.json 22 | *_override.tf 23 | *_override.tf.json 24 | 25 | # Include override files you do wish to add to version control using negated pattern 26 | # !example_override.tf 27 | 28 | # Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan 29 | # example: *tfplan* 30 | 31 | # Ignore CLI configuration files 32 | .terraformrc 33 | terraform.rc 34 | 35 | # Other Files 36 | *.DS_Store* -------------------------------------------------------------------------------- /Getting Started Blog Post/.gitignore: -------------------------------------------------------------------------------- 1 | # Local .terraform directories 2 | **/.terraform/* 3 | 4 | # .tfstate files 5 | *.tfstate 6 | *.tfstate.* 7 | *.terraform.lock.hcl* 8 | 9 | # Crash log files 10 | crash.log 11 | crash.*.log 12 | 13 | # Exclude all .tfvars files, which are likely to contain sensitive data, such as 14 | # password, private keys, and other secrets. These should not be part of version 15 | # control as they are data points which are potentially sensitive and subject 16 | # to change depending on the environment. 17 | 18 | # Ignore override files as they are usually used to override resources locally and so 19 | # are not checked in 20 | override.tf 21 | override.tf.json 22 | *_override.tf 23 | *_override.tf.json 24 | 25 | # Include override files you do wish to add to version control using negated pattern 26 | # !example_override.tf 27 | 28 | # Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan 29 | # example: *tfplan* 30 | 31 | # Ignore CLI configuration files 32 | .terraformrc 33 | terraform.rc 34 | 35 | # Other Files 36 | *.DS_Store* -------------------------------------------------------------------------------- /Single-Region-Azure-BaseLab/.gitignore: -------------------------------------------------------------------------------- 1 | # Local .terraform directories 2 | **/.terraform/* 3 | 4 | # .tfstate files 5 | *.tfstate 6 | *.tfstate.* 7 | *.terraform.lock.hcl* 8 | 9 | # Crash log files 10 | crash.log 11 | crash.*.log 12 | 13 | # Exclude all .tfvars files, which are likely to contain sensitive data, such as 14 | # password, private keys, and other secrets. These should not be part of version 15 | # control as they are data points which are potentially sensitive and subject 16 | # to change depending on the environment. 17 | 18 | # Ignore override files as they are usually used to override resources locally and so 19 | # are not checked in 20 | override.tf 21 | override.tf.json 22 | *_override.tf 23 | *_override.tf.json 24 | 25 | # Include override files you do wish to add to version control using negated pattern 26 | # !example_override.tf 27 | 28 | # Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan 29 | # example: *tfplan* 30 | 31 | # Ignore CLI configuration files 32 | .terraformrc 33 | terraform.rc 34 | 35 | # Other Files 36 | *.DS_Store* -------------------------------------------------------------------------------- /Azure-NetApp-Files-CRR-BaseLab/.gitignore: -------------------------------------------------------------------------------- 1 | # Local .terraform directories 2 | **/.terraform/* 3 | 4 | # .tfstate files 5 | *.tfstate 6 | *.tfstate.* 7 | *.terraform.lock.hcl* 8 | 9 | # Crash log files 10 | crash.log 11 | crash.*.log 12 | 13 | # Exclude all .tfvars files, which are likely to contain sensitive data, such as 14 | # password, private keys, and other secrets. These should not be part of version 15 | # control as they are data points which are potentially sensitive and subject 16 | # to change depending on the environment. 17 | 18 | # Ignore override files as they are usually used to override resources locally and so 19 | # are not checked in 20 | override.tf 21 | override.tf.json 22 | *_override.tf 23 | *_override.tf.json 24 | 25 | # Include override files you do wish to add to version control using negated pattern 26 | # !example_override.tf 27 | 28 | # Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan 29 | # example: *tfplan* 30 | 31 | # Ignore CLI configuration files 32 | .terraformrc 33 | terraform.rc 34 | 35 | # Other Files 36 | *.DS_Store* -------------------------------------------------------------------------------- /Cost-Optimization-Example-Lab/.gitignore: -------------------------------------------------------------------------------- 1 | # Local .terraform directories 2 | **/.terraform/* 3 | 4 | # .tfstate files 5 | *.tfstate 6 | *.tfstate.* 7 | *.terraform.lock.hcl* 8 | 9 | # Crash log files 10 | crash.log 11 | crash.*.log 12 | 13 | # Exclude all .tfvars files, which are likely to contain sensitive data, such as 14 | # password, private keys, and other secrets. These should not be part of version 15 | # control as they are data points which are potentially sensitive and subject 16 | # to change depending on the environment. 17 | 18 | # Ignore override files as they are usually used to override resources locally and so 19 | # are not checked in 20 | override.tf 21 | override.tf.json 22 | *_override.tf 23 | *_override.tf.json 24 | 25 | # Include override files you do wish to add to version control using negated pattern 26 | # !example_override.tf 27 | 28 | # Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan 29 | # example: *tfplan* 30 | 31 | # Ignore CLI configuration files 32 | .terraformrc 33 | terraform.rc 34 | 35 | # Other Files 36 | *.DS_Store* -------------------------------------------------------------------------------- /Cross-Region-Load-Balancer-Lab/.gitignore: -------------------------------------------------------------------------------- 1 | # Local .terraform directories 2 | **/.terraform/* 3 | 4 | # .tfstate files 5 | *.tfstate 6 | *.tfstate.* 7 | *.terraform.lock.hcl* 8 | 9 | # Crash log files 10 | crash.log 11 | crash.*.log 12 | 13 | # Exclude all .tfvars files, which are likely to contain sensitive data, such as 14 | # password, private keys, and other secrets. These should not be part of version 15 | # control as they are data points which are potentially sensitive and subject 16 | # to change depending on the environment. 17 | 18 | # Ignore override files as they are usually used to override resources locally and so 19 | # are not checked in 20 | override.tf 21 | override.tf.json 22 | *_override.tf 23 | *_override.tf.json 24 | 25 | # Include override files you do wish to add to version control using negated pattern 26 | # !example_override.tf 27 | 28 | # Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan 29 | # example: *tfplan* 30 | 31 | # Ignore CLI configuration files 32 | .terraformrc 33 | terraform.rc 34 | 35 | # Other Files 36 | *.DS_Store* -------------------------------------------------------------------------------- /Single-Region-Azure-BaseLab-v2/.gitignore: -------------------------------------------------------------------------------- 1 | # Local .terraform directories 2 | **/.terraform/* 3 | 4 | # .tfstate files 5 | *.tfstate 6 | *.tfstate.* 7 | *.terraform.lock.hcl* 8 | 9 | # Crash log files 10 | crash.log 11 | crash.*.log 12 | 13 | # Exclude all .tfvars files, which are likely to contain sensitive data, such as 14 | # password, private keys, and other secrets. These should not be part of version 15 | # control as they are data points which are potentially sensitive and subject 16 | # to change depending on the environment. 17 | 18 | # Ignore override files as they are usually used to override resources locally and so 19 | # are not checked in 20 | override.tf 21 | override.tf.json 22 | *_override.tf 23 | *_override.tf.json 24 | 25 | # Include override files you do wish to add to version control using negated pattern 26 | # !example_override.tf 27 | 28 | # Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan 29 | # example: *tfplan* 30 | 31 | # Ignore CLI configuration files 32 | .terraformrc 33 | terraform.rc 34 | 35 | # Other Files 36 | *.DS_Store* -------------------------------------------------------------------------------- /Dual-Region-Azure-BaseLab/PowerShell/DC1/baselab_LabStructure.ps1: -------------------------------------------------------------------------------- 1 | #Setup Variables 2 | $DCRoot = "DC=ad,DC=lab" 3 | $LabDCRoot = "OU=Lab,DC=ad,DC=Lab" 4 | #Create Root Lab OU 5 | New-ADOrganizationalUnit -Name "Lab" -Path $DCRoot -ProtectedFromAccidentalDeletion $False -Description "Lab Environment" 6 | #Create Other OUs 7 | New-ADOrganizationalUnit -Name "Users" -Path $LabDCRoot -ProtectedFromAccidentalDeletion $False -Description "Lab Users" 8 | New-ADOrganizationalUnit -Name "Service Accounts" -Path $LabDCRoot -ProtectedFromAccidentalDeletion $False -Description "Lab Service Accounts" 9 | New-ADOrganizationalUnit -Name "Servers" -Path $LabDCRoot -ProtectedFromAccidentalDeletion $False -Description "Lab Servers" 10 | New-ADOrganizationalUnit -Name "WVD" -Path $LabDCRoot -ProtectedFromAccidentalDeletion $False -Description "Lab WVD Session Hosts" 11 | New-ADOrganizationalUnit -Name "Computers" -Path $LabDCRoot -ProtectedFromAccidentalDeletion $False -Description "Lab Computers" 12 | New-ADOrganizationalUnit -Name "ANF" -Path $LabDCRoot -ProtectedFromAccidentalDeletion $False -Description "Lab ANF Objects" -------------------------------------------------------------------------------- /Azure-NetApp-Files-CRR-BaseLab/PowerShell/DC1/baselab_LabStructure.ps1: -------------------------------------------------------------------------------- 1 | #Setup Variables 2 | $DCRoot = "DC=ad,DC=lab" 3 | $LabDCRoot = "OU=Lab,DC=ad,DC=Lab" 4 | #Create Root Lab OU 5 | New-ADOrganizationalUnit -Name "Lab" -Path $DCRoot -ProtectedFromAccidentalDeletion $False -Description "Lab Environment" 6 | #Create Other OUs 7 | New-ADOrganizationalUnit -Name "Users" -Path $LabDCRoot -ProtectedFromAccidentalDeletion $False -Description "Lab Users" 8 | New-ADOrganizationalUnit -Name "Service Accounts" -Path $LabDCRoot -ProtectedFromAccidentalDeletion $False -Description "Lab Service Accounts" 9 | New-ADOrganizationalUnit -Name "Servers" -Path $LabDCRoot -ProtectedFromAccidentalDeletion $False -Description "Lab Servers" 10 | New-ADOrganizationalUnit -Name "WVD" -Path $LabDCRoot -ProtectedFromAccidentalDeletion $False -Description "Lab WVD Session Hosts" 11 | New-ADOrganizationalUnit -Name "Computers" -Path $LabDCRoot -ProtectedFromAccidentalDeletion $False -Description "Lab Computers" 12 | New-ADOrganizationalUnit -Name "ANF" -Path $LabDCRoot -ProtectedFromAccidentalDeletion $False -Description "Lab ANF Objects" -------------------------------------------------------------------------------- /Single-Region-Azure-BaseLab-with-Ansible/.gitignore: -------------------------------------------------------------------------------- 1 | # Local .terraform directories 2 | **/.terraform/* 3 | 4 | # .tfstate files 5 | *.tfstate 6 | *.tfstate.* 7 | *.terraform.lock.hcl* 8 | 9 | # Crash log files 10 | crash.log 11 | crash.*.log 12 | 13 | # Exclude all .tfvars files, which are likely to contain sensitive data, such as 14 | # password, private keys, and other secrets. These should not be part of version 15 | # control as they are data points which are potentially sensitive and subject 16 | # to change depending on the environment. 17 | 18 | # Ignore override files as they are usually used to override resources locally and so 19 | # are not checked in 20 | override.tf 21 | override.tf.json 22 | *_override.tf 23 | *_override.tf.json 24 | 25 | # Include override files you do wish to add to version control using negated pattern 26 | # !example_override.tf 27 | 28 | # Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan 29 | # example: *tfplan* 30 | 31 | # Ignore CLI configuration files 32 | .terraformrc 33 | terraform.rc 34 | 35 | # Other Files 36 | *.DS_Store* -------------------------------------------------------------------------------- /Cross-Region-Load-Balancer-Lab/output.tf: -------------------------------------------------------------------------------- 1 | output "_1_Access-URL-via-Cross-Region-Load-Balancer" { 2 | value = "Use this URL to access via the Cross-Region (Global) Load Balancer: http://${azurerm_public_ip.pip-cr-lb.fqdn} " 3 | } 4 | data "azurerm_public_ip" "example" { 5 | for_each = var.regions 6 | name = azurerm_public_ip.pip-lb[each.key].name 7 | resource_group_name = azurerm_public_ip.pip-lb[each.key].resource_group_name 8 | } 9 | output "_2_Region1-Access-URL-via-Regional-Load-Balancer" { 10 | value = "Use this URL to access via the ${var.regions.region1.location} Load Balancer: http://${data.azurerm_public_ip.example["region1"].fqdn}" 11 | } 12 | output "_3_Region2-Access-URL-via-Regional-Load-Balancer" { 13 | value = "Use this URL to access via the ${var.regions.region2.location} Load Balancer: http://${data.azurerm_public_ip.example["region2"].fqdn}" 14 | } 15 | output "_4_Region3-Access-URL-via-Regional-Load-Balancer" { 16 | value = "Use this URL to access via the ${var.regions.region3.location} Load Balancer: http://${data.azurerm_public_ip.example["region3"].fqdn}" 17 | } -------------------------------------------------------------------------------- /AVD-Demo-Lab/Terraform-Single-Region-Azure-BaseLab-v2/.gitignore: -------------------------------------------------------------------------------- 1 | # Local .terraform directories 2 | **/.terraform/* 3 | 4 | # .tfstate files 5 | *.tfstate 6 | *.tfstate.* 7 | *.terraform.lock.hcl* 8 | 9 | # Crash log files 10 | crash.log 11 | crash.*.log 12 | 13 | # Exclude all .tfvars files, which are likely to contain sensitive data, such as 14 | # password, private keys, and other secrets. These should not be part of version 15 | # control as they are data points which are potentially sensitive and subject 16 | # to change depending on the environment. 17 | 18 | # Ignore override files as they are usually used to override resources locally and so 19 | # are not checked in 20 | override.tf 21 | override.tf.json 22 | *_override.tf 23 | *_override.tf.json 24 | 25 | # Include override files you do wish to add to version control using negated pattern 26 | # !example_override.tf 27 | 28 | # Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan 29 | # example: *tfplan* 30 | 31 | # Ignore CLI configuration files 32 | .terraformrc 33 | terraform.rc 34 | 35 | # Other Files 36 | *.DS_Store* -------------------------------------------------------------------------------- /Automatic-ClientIP-NSG/azuredeploy.tf: -------------------------------------------------------------------------------- 1 | #Resource Groups 2 | resource "azurerm_resource_group" "rg1" { 3 | name = var.azure-rg-1 4 | location = var.loc1 5 | tags = { 6 | Environment = var.environment_tag 7 | } 8 | } 9 | #Get Client IP Address for NSG 10 | data "http" "clientip" { 11 | url = "https://ipv4.icanhazip.com/" 12 | } 13 | #Lab NSG 14 | resource "azurerm_network_security_group" "Automatic-ClientIP-NSG" { 15 | name = "Automatic-ClientIP-NSG" 16 | location = var.loc1 17 | resource_group_name = azurerm_resource_group.rg1.name 18 | 19 | security_rule { 20 | name = "RDP-In" 21 | priority = 100 22 | direction = "Inbound" 23 | access = "Allow" 24 | protocol = "*" 25 | source_port_range = "*" 26 | destination_port_range = "3389" 27 | source_address_prefix = "${chomp(data.http.clientip.response_body)}/32" 28 | destination_address_prefix = "*" 29 | } 30 | tags = { 31 | Environment = var.environment_tag 32 | } 33 | } -------------------------------------------------------------------------------- /Setup-Scripts/AllApps.ps1: -------------------------------------------------------------------------------- 1 | # Chocolatey setup and installation script for the apps I use. 2 | Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1')) 3 | # Chocolatey apps 4 | choco install putty -y -no-desktopshortcuts 5 | choco install notepadplusplus -y -no-desktopshortcuts 6 | choco install winscp -y -no-desktopshortcuts 7 | choco install 7zip -y -no-desktopshortcuts 8 | choco install firefox -y -no-desktopshortcuts 9 | choco install vlc -y -no-desktopshortcuts 10 | choco install keepass -y -no-desktopshortcuts 11 | choco install vscode -y -no-desktopshortcuts 12 | choco install packer -y -no-desktopshortcuts 13 | choco install terraform -y -no-desktopshortcuts 14 | choco install azure-cli -y -no-desktopshortcuts 15 | choco install microsoftazurestorageexplorer -y -no-desktopshortcuts 16 | choco install az.powershell -y -no-desktopshortcuts 17 | choco install bicep -y -no-desktopshortcuts 18 | choco install github-desktop -y -no-desktopshortcuts 19 | -------------------------------------------------------------------------------- /Automatic-ClientIP-NSG/README.md: -------------------------------------------------------------------------------- 1 | # Automating NSG rules with an external IP in Terraform 2 | 3 | ## Overview 4 | This code dynamically creates an Azure Network Security Group (NSG) using Terraform. The NSG allows inbound RDP access from the Client IP of the machine running Terraform only. The IP address is gathered from an IP check service automatically. 5 | 6 | ### A full overview is available here: https://jakewalsh.co.uk/automating-nsg-rules-with-an-external-ip-in-terraform/ 7 | 8 | ## Actions 9 | This code creates a data source within Terraform, and then uses this during deployment, so that the NSG rule is created dynamically based on the Client IP. To do this, a data source is used, and a URL from an IP check service - see [azuredeploy.tf](azuredeploy.tf). 10 | 11 | In this example 3 things are carried out: 12 | 13 | 1. Creates a Resource Group to hold Resources 14 | 2. Checks the Client IP with https://ipv4.icanhazip.com/ 15 | 3. Creates an NSG that allows inbound RDP using the IP address from the IP Check Service above. 16 | 17 | The NSG can then be applied to whatever resources you wish - and only your Client IP will be able to access them over RDP. 18 | -------------------------------------------------------------------------------- /Chaos-Studio-Test/variables.tf: -------------------------------------------------------------------------------- 1 | variable "environment_tag" { 2 | type = string 3 | description = "Environment tag value" 4 | } 5 | variable "labname" { 6 | type = string 7 | description = "Lab name" 8 | } 9 | variable "region1" { 10 | description = "The location 1 for this Lab environment" 11 | type = string 12 | } 13 | variable "region1cidr" { 14 | description = "The CIDR range for the whole of Region 1" 15 | type = string 16 | } 17 | variable "region1code" { 18 | description = "Server Naming Code for Region 1" 19 | type = string 20 | } 21 | variable "region2" { 22 | description = "The location 2 for this Lab environment" 23 | type = string 24 | } 25 | variable "region2cidr" { 26 | description = "The CIDR range for the whole of Region 2" 27 | type = string 28 | } 29 | variable "region2code" { 30 | description = "Server Naming Code for Region 2" 31 | type = string 32 | } 33 | variable "servercounta" { 34 | description = "Number of Servers in the Lab A" 35 | type = string 36 | } 37 | variable "servercountb" { 38 | description = "Number of Servers in the Lab B" 39 | type = string 40 | } -------------------------------------------------------------------------------- /Web-Server-IIS-DemoLab/terraform.tfvars: -------------------------------------------------------------------------------- 1 | environment_tag = "jakewalsh90-IIS-DemoLab" 2 | azure-rg-1 = "webdemo-labv1-region1infra" 3 | azure-rg-2 = "webdemo-labv1-security" 4 | loc1 = "uk south" 5 | region1-vnet1-name = "r1-vnet1-hub1" 6 | region1-vnet2-name = "r1-vnet1-spoke1" 7 | region1-vnet1-address-space = "10.10.0.0/16" 8 | region1-vnet2-address-space = "10.11.0.0/16" 9 | region1-vnet1-snet1-name = "r1-vnet1-snet-infra1" 10 | region1-vnet1-snet2-name = "r1-vnet1-snet-infra2" 11 | region1-vnet1-snet3-name = "r1-vnet1-snet-infra3" 12 | region1-vnet2-snet1-name = "r1-vnet2-snet-infra1" 13 | region1-vnet2-snet2-name = "r1-vnet2-snet-infra2" 14 | region1-vnet2-snet3-name = "r1-vnet2-snet-anf1" 15 | region1-vnet1-snet1-range = "10.10.1.0/24" 16 | region1-vnet1-snet2-range = "10.10.2.0/24" 17 | region1-vnet1-snet3-range = "10.10.3.0/24" 18 | region1-vnet2-snet1-range = "10.11.1.0/24" 19 | region1-vnet2-snet2-range = "10.11.2.0/24" 20 | region1-vnet2-snet3-range = "10.11.3.0/24" 21 | vmsize-domaincontroller = "Standard_D2s_v4" 22 | adminusername = "labadmin" -------------------------------------------------------------------------------- /Single-Region-Azure-BaseLab/terraform.tfvars: -------------------------------------------------------------------------------- 1 | environment_tag = "jakewalsh90-baselab-v1" 2 | azure-rg-1 = "baselabv1-region1infra" 3 | azure-rg-2 = "baselabv1-security" 4 | loc1 = "uk south" 5 | region1-vnet1-name = "region1-vnet1-hub1" 6 | region1-vnet2-name = "region1-vnet1-spoke1" 7 | region1-vnet1-address-space = "10.10.0.0/16" 8 | region1-vnet2-address-space = "10.11.0.0/16" 9 | region1-vnet1-snet1-name = "region1-vnet1-snet-infra1" 10 | region1-vnet1-snet2-name = "region1-vnet1-snet-infra2" 11 | region1-vnet1-snet3-name = "region1-vnet1-snet-infra3" 12 | region1-vnet2-snet1-name = "region1-vnet2-snet-infra1" 13 | region1-vnet2-snet2-name = "region1-vnet2-snet-infra2" 14 | region1-vnet2-snet3-name = "region1-vnet2-snet-infra3" 15 | region1-vnet1-snet1-range = "10.10.1.0/24" 16 | region1-vnet1-snet2-range = "10.10.2.0/24" 17 | region1-vnet1-snet3-range = "10.10.3.0/24" 18 | region1-vnet2-snet1-range = "10.11.1.0/24" 19 | region1-vnet2-snet2-range = "10.11.2.0/24" 20 | region1-vnet2-snet3-range = "10.11.3.0/24" 21 | vmsize-domaincontroller = "Standard_D2s_v4" 22 | adminusername = "labadmin" -------------------------------------------------------------------------------- /Single-Region-Azure-BaseLab-with-Ansible/terraform.tfvars: -------------------------------------------------------------------------------- 1 | environment_tag = "jakewalsh90-Single-Region-Azure-BaseLab-with-Ansible" 2 | azure-rg-1 = "baselabv1-region1infra" 3 | azure-rg-2 = "baselabv1-security" 4 | loc1 = "uk south" 5 | region1-vnet1-name = "region1-vnet1-hub1" 6 | region1-vnet2-name = "region1-vnet1-spoke1" 7 | region1-vnet1-address-space = "10.10.0.0/16" 8 | region1-vnet2-address-space = "10.11.0.0/16" 9 | region1-vnet1-snet1-name = "region1-vnet1-snet-infra1" 10 | region1-vnet1-snet2-name = "region1-vnet1-snet-infra2" 11 | region1-vnet1-snet3-name = "region1-vnet1-snet-infra3" 12 | region1-vnet2-snet1-name = "region1-vnet2-snet-infra1" 13 | region1-vnet2-snet2-name = "region1-vnet2-snet-infra2" 14 | region1-vnet2-snet3-name = "region1-vnet2-snet-anf1" 15 | region1-vnet1-snet1-range = "10.10.1.0/24" 16 | region1-vnet1-snet2-range = "10.10.2.0/24" 17 | region1-vnet1-snet3-range = "10.10.3.0/24" 18 | region1-vnet2-snet1-range = "10.11.1.0/24" 19 | region1-vnet2-snet2-range = "10.11.2.0/24" 20 | region1-vnet2-snet3-range = "10.11.3.0/24" 21 | vmsize = "Standard_D2s_v4" 22 | adminusername = "labadmin" -------------------------------------------------------------------------------- /Terraform-Cloud-Deployment/readme.md: -------------------------------------------------------------------------------- 1 | # Prerequisites for Terraform Cloud Deployment 2 | This page explains the required pre-requisites for deploying Terraform using Terraform Cloud. 3 | 4 | ## Creating a Service Principal 5 | 6 | In order to interact with Azure, Terraform will require a Service Principal. I've chosen to create this scoped to the Subscription I deploy my Lab into. You may need to scope this differently depending on the environment that you are working with. Doing this is simple using the Azure CLI: 7 | 8 | https://github.com/jakewalsh90/Terraform-Azure/blob/1f678d1ced4510fda3f3d04387a1e4011e47b844/Terraform-Cloud-Deployment/scripts/ServicePrincipalSetup#L1 9 | 10 | This will provide an output that includes 4 important details - save these as you will need these later on to setup Terraform Cloud: 11 | 12 | - ARM_CLIENT_ID 13 | - ARM_CLIENT_SECRET 14 | - ARM_TENANT_ID 15 | - ARM_SUBSCRIPTION_ID 16 | 17 | ## Setting up a GitHub Repo 18 | 19 | A repository to store Terraform Code is required before you can deploy using Terraform Cloud - this is where our configuration will be stored. Within the following repository there is a demo environment available for download, along with instructions for setup. 20 | 21 | See here: https://github.com/jakewalsh90/Terraform-Azure/tree/main/Core-Environment-DemoLab-v1 -------------------------------------------------------------------------------- /Chaos-Studio-Test/trafficmanager.tf: -------------------------------------------------------------------------------- 1 | # Traffic Manager 2 | resource "azurerm_traffic_manager_profile" "tm1" { 3 | name = "tm-${var.labname}" 4 | resource_group_name = azurerm_resource_group.rg1.name 5 | traffic_routing_method = "Weighted" 6 | 7 | dns_config { 8 | relative_name = "${var.labname}-${random_id.dns-name.hex}" 9 | ttl = 100 10 | } 11 | 12 | monitor_config { 13 | protocol = "HTTP" 14 | port = 80 15 | path = "/" 16 | interval_in_seconds = 30 17 | timeout_in_seconds = 10 18 | tolerated_number_of_failures = 3 19 | } 20 | 21 | tags = { 22 | environment = var.environment_tag 23 | } 24 | } 25 | resource "azurerm_traffic_manager_azure_endpoint" "region1-tme1" { 26 | name = "${var.region1}-endpoint" 27 | profile_id = azurerm_traffic_manager_profile.tm1.id 28 | weight = 100 29 | target_resource_id = azurerm_public_ip.region1-fwpip.id 30 | } 31 | resource "azurerm_traffic_manager_azure_endpoint" "region2-tme1" { 32 | name = "${var.region2}-endpoint" 33 | profile_id = azurerm_traffic_manager_profile.tm1.id 34 | weight = 100 35 | target_resource_id = azurerm_public_ip.region2-fwpip.id 36 | } -------------------------------------------------------------------------------- /Azure-Firewall-DemoLab/terraform.tfvars: -------------------------------------------------------------------------------- 1 | environment_tag = "jakewalsh90-Single-Region-Azure-BaseLab" 2 | azure-rg-1 = "baselabv1-region1infra" 3 | azure-rg-2 = "baselabv1-security" 4 | loc1 = "uk south" 5 | region1-vnet1-name = "region1-vnet1-hub1" 6 | region1-vnet2-name = "region1-vnet1-spoke1" 7 | region1-vnet1-address-space = "10.10.0.0/16" 8 | region1-vnet2-address-space = "10.11.0.0/16" 9 | region1-vnet1-snet1-name = "region1-vnet1-snet-infra1" 10 | region1-vnet1-snet2-name = "region1-vnet1-snet-infra2" 11 | region1-vnet1-snet3-name = "region1-vnet1-snet-infra3" 12 | region1-vnet1-snetfw-name = "AzureFirewallSubnet" 13 | region1-vnet2-snet1-name = "region1-vnet2-snet-infra1" 14 | region1-vnet2-snet2-name = "region1-vnet2-snet-infra2" 15 | region1-vnet2-snet3-name = "region1-vnet2-snet-anf1" 16 | region1-vnet1-snet1-range = "10.10.1.0/24" 17 | region1-vnet1-snet2-range = "10.10.2.0/24" 18 | region1-vnet1-snet3-range = "10.10.3.0/24" 19 | region1-vnet1-snetfw-range = "10.10.254.0/24" 20 | region1-vnet2-snet1-range = "10.11.1.0/24" 21 | region1-vnet2-snet2-range = "10.11.2.0/24" 22 | region1-vnet2-snet3-range = "10.11.3.0/24" 23 | vmsize-domaincontroller = "Standard_D2s_v4" 24 | adminusername = "labadmin" 25 | region1-gateway-address-space = "192.168.1.0/24" -------------------------------------------------------------------------------- /Cross-Region-Load-Balancer-Lab/KeyVault.tf: -------------------------------------------------------------------------------- 1 | # Key Vault 2 | resource "random_id" "kv-name" { 3 | byte_length = 6 4 | prefix = "kv" 5 | } 6 | data "azurerm_client_config" "current" {} 7 | resource "azurerm_key_vault" "kv1" { 8 | name = random_id.kv-name.hex 9 | location = azurerm_resource_group.rg-sec.location 10 | resource_group_name = azurerm_resource_group.rg-sec.name 11 | enabled_for_disk_encryption = true 12 | tenant_id = data.azurerm_client_config.current.tenant_id 13 | soft_delete_retention_days = 7 14 | purge_protection_enabled = false 15 | 16 | sku_name = "standard" 17 | 18 | access_policy { 19 | tenant_id = data.azurerm_client_config.current.tenant_id 20 | object_id = data.azurerm_client_config.current.object_id 21 | 22 | key_permissions = [ 23 | "Get", 24 | ] 25 | 26 | secret_permissions = [ 27 | "Get", "Backup", "Delete", "List", "Purge", "Recover", "Restore", "Set", 28 | ] 29 | 30 | storage_permissions = [ 31 | "Get", 32 | ] 33 | } 34 | } 35 | # Create VM password 36 | resource "random_password" "vmpassword" { 37 | length = 20 38 | special = true 39 | } 40 | # Create Key Vault Secret 41 | resource "azurerm_key_vault_secret" "vmpassword" { 42 | name = "vmpassword" 43 | value = random_password.vmpassword.result 44 | key_vault_id = azurerm_key_vault.kv1.id 45 | expiration_date = timeadd(timestamp(), "8760h") 46 | content_type = "Password" 47 | } -------------------------------------------------------------------------------- /Cost-Optimization-Example-Lab/variables.tf: -------------------------------------------------------------------------------- 1 | ########################## 2 | # Core Feature Variables 3 | ########################## 4 | 5 | variable "environment_tag" { 6 | type = string 7 | description = "Environment tag value" 8 | } 9 | variable "region1" { 10 | type = string 11 | description = "Region 1 Location for this environment" 12 | } 13 | variable "region1code" { 14 | type = string 15 | description = "Region 1 Location code for this environment - used for naming Azure Resources" 16 | } 17 | variable "region1cidr" { 18 | type = string 19 | description = "Region 1 CIDR Range" 20 | } 21 | variable "vmcount" { 22 | type = string 23 | description = "Number of identity VMs to create - default is 2" 24 | } 25 | variable "vmsize" { 26 | type = string 27 | description = "VM size to create" 28 | } 29 | variable "adminuser" { 30 | type = string 31 | description = "admin username for the created VMs" 32 | } 33 | 34 | ############################## 35 | # Optional Feature Variables 36 | ############################## 37 | 38 | variable "bastion" { 39 | type = bool 40 | description = "Sets if Azure Bastion is created" 41 | } 42 | variable "avd" { 43 | type = bool 44 | description = "Sets if Azure Virtual Desktop Supporting Resources are created" 45 | } 46 | variable "vng" { 47 | type = bool 48 | description = "Sets if a Virtual Network Gateway is created or not" 49 | } 50 | variable "azfw" { 51 | type = bool 52 | description = "Sets if Azure Firewall is created or not" 53 | } -------------------------------------------------------------------------------- /Single-Region-Azure-BaseLab-v2/variables.tf: -------------------------------------------------------------------------------- 1 | ########################## 2 | # Core Feature Variables 3 | ########################## 4 | 5 | variable "environment_tag" { 6 | type = string 7 | description = "Environment tag value" 8 | } 9 | variable "region1" { 10 | type = string 11 | description = "Region 1 Location for this environment" 12 | } 13 | variable "region1code" { 14 | type = string 15 | description = "Region 1 Location code for this environment - used for naming Azure Resources" 16 | } 17 | variable "region1cidr" { 18 | type = string 19 | description = "Region 1 CIDR Range" 20 | } 21 | variable "vmcount" { 22 | type = string 23 | description = "Number of identity VMs to create - default is 2" 24 | } 25 | variable "vmsize" { 26 | type = string 27 | description = "VM size to create" 28 | } 29 | variable "adminuser" { 30 | type = string 31 | description = "admin username for the created VMs" 32 | } 33 | 34 | ############################## 35 | # Optional Feature Variables 36 | ############################## 37 | 38 | variable "bastion" { 39 | type = bool 40 | description = "Sets if Azure Bastion is created" 41 | } 42 | variable "avd" { 43 | type = bool 44 | description = "Sets if Azure Virtual Desktop Supporting Resources are created" 45 | } 46 | variable "vng" { 47 | type = bool 48 | description = "Sets if a Virtual Network Gateway is created or not" 49 | } 50 | variable "azfw" { 51 | type = bool 52 | description = "Sets if Azure Firewall is created or not" 53 | } -------------------------------------------------------------------------------- /AVD-Demo-Lab/Terraform-Single-Region-Azure-BaseLab-v2/variables.tf: -------------------------------------------------------------------------------- 1 | ########################## 2 | # Core Feature Variables 3 | ########################## 4 | 5 | variable "environment_tag" { 6 | type = string 7 | description = "Environment tag value" 8 | } 9 | variable "region1" { 10 | type = string 11 | description = "Region 1 Location for this environment" 12 | } 13 | variable "region1code" { 14 | type = string 15 | description = "Region 1 Location code for this environment - used for naming Azure Resources" 16 | } 17 | variable "region1cidr" { 18 | type = string 19 | description = "Region 1 CIDR Range" 20 | } 21 | variable "vmcount" { 22 | type = string 23 | description = "Number of identity VMs to create - default is 2" 24 | } 25 | variable "vmsize" { 26 | type = string 27 | description = "VM size to create" 28 | } 29 | variable "adminuser" { 30 | type = string 31 | description = "admin username for the created VMs" 32 | } 33 | 34 | ############################## 35 | # Optional Feature Variables 36 | ############################## 37 | 38 | variable "bastion" { 39 | type = bool 40 | description = "Sets if Azure Bastion is created" 41 | } 42 | variable "avd" { 43 | type = bool 44 | description = "Sets if Azure Virtual Desktop Supporting Resources are created" 45 | } 46 | variable "vng" { 47 | type = bool 48 | description = "Sets if a Virtual Network Gateway is created or not" 49 | } 50 | variable "azfw" { 51 | type = bool 52 | description = "Sets if Azure Firewall is created or not" 53 | } -------------------------------------------------------------------------------- /Virtual-WAN-Demo/keyvault.tf: -------------------------------------------------------------------------------- 1 | # Create KeyVault ID 2 | resource "random_id" "kvname" { 3 | byte_length = 5 4 | prefix = "keyvault" 5 | } 6 | # Keyvault Creation 7 | data "azurerm_client_config" "current" {} 8 | resource "azurerm_key_vault" "kv1" { 9 | depends_on = [azurerm_resource_group.region1-rg1] 10 | name = random_id.kvname.hex 11 | location = var.region1 12 | resource_group_name = azurerm_resource_group.region1-rg1.name 13 | enabled_for_disk_encryption = true 14 | tenant_id = data.azurerm_client_config.current.tenant_id 15 | soft_delete_retention_days = 7 16 | purge_protection_enabled = false 17 | 18 | sku_name = "standard" 19 | 20 | access_policy { 21 | tenant_id = data.azurerm_client_config.current.tenant_id 22 | object_id = data.azurerm_client_config.current.object_id 23 | 24 | key_permissions = [ 25 | "Get", 26 | ] 27 | 28 | secret_permissions = [ 29 | "Get", "Backup", "Delete", "List", "Purge", "Recover", "Restore", "Set", 30 | ] 31 | 32 | storage_permissions = [ 33 | "Get", 34 | ] 35 | } 36 | tags = { 37 | Environment = var.environment_tag 38 | } 39 | } 40 | # Create KeyVault VM password 41 | resource "random_password" "vmpassword" { 42 | length = 20 43 | special = true 44 | } 45 | # Create Key Vault Secret 46 | resource "azurerm_key_vault_secret" "vmpassword" { 47 | name = "vmpassword" 48 | value = random_password.vmpassword.result 49 | key_vault_id = azurerm_key_vault.kv1.id 50 | depends_on = [azurerm_key_vault.kv1] 51 | } -------------------------------------------------------------------------------- /Azure-KeyVault-with-Secret/README.md: -------------------------------------------------------------------------------- 1 | # Creating an Azure Key Vault with a Secret 2 | 3 | ## Overview 4 | This code creates a randomly named Azure Key Vault (keyvault##########), and then creates a Secret based on a random string, and stores that within the Key Vault. This allows automated creation of unique Key Vaults (as Key Vault names need to be unique) and unique passwords - ideal for environments that need to be created by multiple people - labs for example. 5 | 6 | ### A full overview is available here: https://jakewalsh.co.uk/automating-azure-key-vault-and-secrets-using-terraform/ 7 | 8 | ## Actions 9 | This code creates a Key Vault name using the random_id resource, with the prefix of "keyvault". This is then used to create a Key Vault. The random_password resource is then used to create a unique password. This is saved within the Key Vault and can then be used to setup VMs as required. See [azuredeploy.tf](azuredeploy.tf) 10 | 11 | In this example the following actions are carried out: 12 | 13 | 1. Creates a Resource Group to hold Resources. 14 | 2. Creates a Key Vault name using the random_id resource, prefixed with "keyvault". 15 | 3. Creates a Key Vault using the generated name, and sets permissions for Secrets within. 16 | 4. Creates a Password using the random_password resource. 17 | 5. Stores the generated Password inside the generated Key Vault. 18 | 19 | The Secret can then be used as the administrator password for VMs created in Terraform. The password value can be accessed via the Key Vault. When creating a VM using this code, reference the password as below: 20 | 21 | admin_password = azurerm_key_vault_secret.vmpassword.value 22 | -------------------------------------------------------------------------------- /PowerShell/baselab_DCSetup.ps1: -------------------------------------------------------------------------------- 1 | # Choco install and Choco Apps 2 | Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1')) 3 | choco install googlechrome -y 4 | choco install putty -y 5 | choco install notepadplusplus -y 6 | choco install winscp -y 7 | choco install sysinternals -y 8 | choco install bginfo -y 9 | # Download Scripts to Set the rest of the Domain up when logged in 10 | New-Item -Path "c:\" -Name "BaselabSetup" -ItemType "directory" -Force 11 | Invoke-WebRequest -Uri "https://raw.githubusercontent.com/jakewalsh90/Terraform-Azure/main/PowerShell/baselab_DomainSetup.ps1" -OutFile "C:\BaselabSetup\baselab_DomainSetup.ps1" 12 | Invoke-WebRequest -Uri "https://raw.githubusercontent.com/jakewalsh90/Terraform-Azure/main/PowerShell/baselab_LabStructure.ps1" -OutFile "C:\BaselabSetup\baselab_LabStructure.ps1" 13 | # Setup and Partition Data Disk 14 | Get-Disk | Where partitionstyle -eq 'raw' | Initialize-Disk -PartitionStyle MBR -PassThru | New-Partition -AssignDriveLetter -UseMaximumSize | Format-Volume -FileSystem NTFS -NewFileSystemLabel 'Data' -Confirm:$false 15 | # Allow Ping 16 | Set-NetFirewallRule -DisplayName "File and Printer Sharing (Echo Request - ICMPv4-In)" -enabled True 17 | Set-NetFirewallRule -DisplayName "File and Printer Sharing (Echo Request - ICMPv6-In)" -enabled True 18 | # Install Roles to make Server a Domain Controller 19 | Install-windowsfeature -name AD-Domain-Services -IncludeManagementTools 20 | Install-windowsfeature -name DNS -IncludeManagementTools 21 | -------------------------------------------------------------------------------- /PowerShell/baselabv2_VMSetup.ps1: -------------------------------------------------------------------------------- 1 | # Choco install and Choco Apps 2 | Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1')) 3 | choco install googlechrome -y 4 | choco install putty -y 5 | choco install notepadplusplus -y 6 | choco install winscp -y 7 | choco install sysinternals -y 8 | choco install bginfo -y 9 | # Download Scripts to Set the rest of the Domain up when logged in 10 | New-Item -Path "c:\" -Name "BaselabSetup" -ItemType "directory" -Force 11 | Invoke-WebRequest -Uri "https://raw.githubusercontent.com/jakewalsh90/Terraform-Azure/main/PowerShell/baselab_DomainSetup.ps1" -OutFile "C:\BaselabSetup\baselab_DomainSetup.ps1" 12 | Invoke-WebRequest -Uri "https://raw.githubusercontent.com/jakewalsh90/Terraform-Azure/main/PowerShell/baselab_LabStructure.ps1" -OutFile "C:\BaselabSetup\baselab_LabStructure.ps1" 13 | # Setup and Partition Data Disk 14 | Get-Disk | Where partitionstyle -eq 'raw' | Initialize-Disk -PartitionStyle MBR -PassThru | New-Partition -AssignDriveLetter -UseMaximumSize | Format-Volume -FileSystem NTFS -NewFileSystemLabel 'Data' -Confirm:$false 15 | # Allow Ping 16 | Set-NetFirewallRule -DisplayName "File and Printer Sharing (Echo Request - ICMPv4-In)" -enabled True 17 | Set-NetFirewallRule -DisplayName "File and Printer Sharing (Echo Request - ICMPv6-In)" -enabled True 18 | # Install Roles to make Server a Domain Controller 19 | Install-windowsfeature -name AD-Domain-Services -IncludeManagementTools 20 | Install-windowsfeature -name DNS -IncludeManagementTools 21 | -------------------------------------------------------------------------------- /Azure Lab Services/keyvault.tf: -------------------------------------------------------------------------------- 1 | #Create KeyVault ID 2 | resource "random_id" "kvname" { 3 | byte_length = 5 4 | prefix = "keyvault" 5 | } 6 | #Keyvault Creation 7 | data "azurerm_client_config" "current" {} 8 | resource "azurerm_key_vault" "kv1" { 9 | depends_on = [azurerm_resource_group.rg] 10 | name = random_id.kvname.hex 11 | resource_group_name = azurerm_resource_group.rg.name 12 | location = var.region 13 | enabled_for_disk_encryption = true 14 | tenant_id = data.azurerm_client_config.current.tenant_id 15 | soft_delete_retention_days = 7 16 | purge_protection_enabled = false 17 | 18 | sku_name = "standard" 19 | 20 | access_policy { 21 | tenant_id = data.azurerm_client_config.current.tenant_id 22 | object_id = data.azurerm_client_config.current.object_id 23 | 24 | key_permissions = [ 25 | "Get", 26 | ] 27 | 28 | secret_permissions = [ 29 | "Get", "Backup", "Delete", "List", "Purge", "Recover", "Restore", "Set", 30 | ] 31 | 32 | storage_permissions = [ 33 | "Get", 34 | ] 35 | } 36 | tags = { 37 | Environment = var.labname 38 | Function = "AzureLabServices" 39 | } 40 | } 41 | #Create KeyVault VM password 42 | resource "random_password" "vmpassword" { 43 | length = 20 44 | special = true 45 | } 46 | # Create Key Vault Secret 47 | resource "azurerm_key_vault_secret" "vmpassword" { 48 | name = "vmpassword" 49 | value = random_password.vmpassword.result 50 | key_vault_id = azurerm_key_vault.kv1.id 51 | expiration_date = timeadd(timestamp(), "8760h") 52 | content_type = "Password" 53 | } -------------------------------------------------------------------------------- /Virtual-WAN-Demo/bastion.tf: -------------------------------------------------------------------------------- 1 | # Azure Bastion 2 | # Public IPs 3 | resource "azurerm_public_ip" "region1-bastion-pip" { 4 | name = "${var.region1}-bastion-pip" 5 | location = var.region1 6 | resource_group_name = azurerm_resource_group.region1-rg1.name 7 | allocation_method = "Static" 8 | sku = "Standard" 9 | tags = { 10 | Environment = var.environment_tag 11 | } 12 | } 13 | resource "azurerm_public_ip" "region2-bastion-pip" { 14 | name = "${var.region2}-bastion-pip" 15 | location = var.region2 16 | resource_group_name = azurerm_resource_group.region2-rg1.name 17 | allocation_method = "Static" 18 | sku = "Standard" 19 | tags = { 20 | Environment = var.environment_tag 21 | } 22 | } 23 | # Azure Bastion 24 | resource "azurerm_bastion_host" "region1-bastion" { 25 | name = "${var.region1}-bastion" 26 | location = var.region1 27 | resource_group_name = azurerm_resource_group.region1-rg1.name 28 | ip_configuration { 29 | name = "${var.region1}-bastion-ipconfig" 30 | public_ip_address_id = azurerm_public_ip.region1-bastion-pip.id 31 | subnet_id = azurerm_subnet.region1-bastion-snet.id 32 | } 33 | } 34 | resource "azurerm_bastion_host" "region2-bastion" { 35 | name = "${var.region2}-bastion" 36 | location = var.region2 37 | resource_group_name = azurerm_resource_group.region2-rg1.name 38 | ip_configuration { 39 | name = "${var.region2}-bastion-ipconfig" 40 | public_ip_address_id = azurerm_public_ip.region2-bastion-pip.id 41 | subnet_id = azurerm_subnet.region2-bastion-snet.id 42 | } 43 | } -------------------------------------------------------------------------------- /Dual-Region-Azure-BaseLab/PowerShell/DC1/baselab_DCSetup1.ps1: -------------------------------------------------------------------------------- 1 | # Choco install and Choco Apps 2 | Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1')) 3 | choco install googlechrome -y 4 | choco install putty -y 5 | choco install notepadplusplus -y 6 | choco install winscp -y 7 | choco install sysinternals -y 8 | choco install bginfo -y 9 | # Download Scripts to Set the rest of the Domain up when logged in 10 | New-Item -Path "c:\" -Name "BaselabSetup" -ItemType "directory" -Force 11 | Invoke-WebRequest -Uri "https://raw.githubusercontent.com/jakewalsh90/Terraform-Azure/main/Dual-Region-Azure-BaseLab/PowerShell/DC1/baselab_DomainSetup.ps1" -OutFile "C:\BaselabSetup\baselab_DomainSetup.ps1" 12 | Invoke-WebRequest -Uri "https://raw.githubusercontent.com/jakewalsh90/Terraform-Azure/main/Dual-Region-Azure-BaseLab/PowerShell/DC1/baselab_LabStructure.ps1" -OutFile "C:\BaselabSetup\baselab_LabStructure.ps1" 13 | # Setup and Partition Data Disk 14 | Get-Disk | Where partitionstyle -eq 'raw' | Initialize-Disk -PartitionStyle MBR -PassThru | New-Partition -AssignDriveLetter -UseMaximumSize | Format-Volume -FileSystem NTFS -NewFileSystemLabel 'Data' -Confirm:$false 15 | # Allow Ping 16 | Set-NetFirewallRule -DisplayName "File and Printer Sharing (Echo Request - ICMPv4-In)" -enabled True 17 | Set-NetFirewallRule -DisplayName "File and Printer Sharing (Echo Request - ICMPv6-In)" -enabled True 18 | # Install Roles to make Server a Domain Controller 19 | Install-windowsfeature -name AD-Domain-Services -IncludeManagementTools 20 | Install-windowsfeature -name DNS -IncludeManagementTools 21 | Clear-DnsClientCache 22 | -------------------------------------------------------------------------------- /Dual-Region-Azure-BaseLab/PowerShell/DC2/baselab_DCSetup2.ps1: -------------------------------------------------------------------------------- 1 | # Choco install and Choco Apps 2 | Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1')) 3 | choco install googlechrome -y 4 | choco install putty -y 5 | choco install notepadplusplus -y 6 | choco install winscp -y 7 | choco install sysinternals -y 8 | choco install bginfo -y 9 | # Download Scripts to Set the rest of the Domain up when logged in 10 | New-Item -Path "c:\" -Name "BaselabSetup" -ItemType "directory" -Force 11 | Invoke-WebRequest -Uri "https://raw.githubusercontent.com/jakewalsh90/Terraform-Azure/main/Dual-Region-Azure-BaseLab/PowerShell/DC2/baselab_DC2JoinDomain.ps1" -OutFile "C:\BaselabSetup\baselab_DC2JoinDomain.ps1" 12 | Invoke-WebRequest -Uri "https://raw.githubusercontent.com/jakewalsh90/Terraform-Azure/main/Dual-Region-Azure-BaseLab/PowerShell/DC2/baselab_DC2Promote.ps1" -OutFile "C:\BaselabSetup\baselab_DC2Promote.ps1" 13 | # Setup and Partition Data Disk 14 | Get-Disk | Where partitionstyle -eq 'raw' | Initialize-Disk -PartitionStyle MBR -PassThru | New-Partition -AssignDriveLetter -UseMaximumSize | Format-Volume -FileSystem NTFS -NewFileSystemLabel 'Data' -Confirm:$false 15 | # Allow Ping 16 | Set-NetFirewallRule -DisplayName "File and Printer Sharing (Echo Request - ICMPv4-In)" -enabled True 17 | Set-NetFirewallRule -DisplayName "File and Printer Sharing (Echo Request - ICMPv6-In)" -enabled True 18 | # Install Roles to make Server a Domain Controller 19 | Install-windowsfeature -name AD-Domain-Services -IncludeManagementTools 20 | Install-windowsfeature -name DNS -IncludeManagementTools 21 | Clear-DnsClientCache 22 | -------------------------------------------------------------------------------- /Azure-NetApp-Files-CRR-BaseLab/PowerShell/DC1/baselab_DCSetup1.ps1: -------------------------------------------------------------------------------- 1 | # Choco install and Choco Apps 2 | Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1')) 3 | choco install googlechrome -y 4 | choco install putty -y 5 | choco install notepadplusplus -y 6 | choco install winscp -y 7 | choco install sysinternals -y 8 | choco install bginfo -y 9 | # Download Scripts to Set the rest of the Domain up when logged in 10 | New-Item -Path "c:\" -Name "BaselabSetup" -ItemType "directory" -Force 11 | Invoke-WebRequest -Uri "https://raw.githubusercontent.com/jakewalsh90/Terraform-Azure/main/Azure-NetApp-Files-CRR-BaseLab/PowerShell/DC1/baselab_DomainSetup.ps1" -OutFile "C:\BaselabSetup\baselab_DomainSetup.ps1" 12 | Invoke-WebRequest -Uri "https://raw.githubusercontent.com/jakewalsh90/Terraform-Azure/main/Azure-NetApp-Files-CRR-BaseLab/PowerShell/DC1/baselab_LabStructure.ps1" -OutFile "C:\BaselabSetup\baselab_LabStructure.ps1" 13 | # Setup and Partition Data Disk 14 | Get-Disk | Where partitionstyle -eq 'raw' | Initialize-Disk -PartitionStyle MBR -PassThru | New-Partition -AssignDriveLetter -UseMaximumSize | Format-Volume -FileSystem NTFS -NewFileSystemLabel 'Data' -Confirm:$false 15 | # Allow Ping 16 | Set-NetFirewallRule -DisplayName "File and Printer Sharing (Echo Request - ICMPv4-In)" -enabled True 17 | Set-NetFirewallRule -DisplayName "File and Printer Sharing (Echo Request - ICMPv6-In)" -enabled True 18 | # Install Roles to make Server a Domain Controller 19 | Install-windowsfeature -name AD-Domain-Services -IncludeManagementTools 20 | Install-windowsfeature -name DNS -IncludeManagementTools 21 | Clear-DnsClientCache 22 | -------------------------------------------------------------------------------- /Azure-NetApp-Files-CRR-BaseLab/PowerShell/DC2/baselab_DCSetup2.ps1: -------------------------------------------------------------------------------- 1 | # Choco install and Choco Apps 2 | Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1')) 3 | choco install googlechrome -y 4 | choco install putty -y 5 | choco install notepadplusplus -y 6 | choco install winscp -y 7 | choco install sysinternals -y 8 | choco install bginfo -y 9 | # Download Scripts to Set the rest of the Domain up when logged in 10 | New-Item -Path "c:\" -Name "BaselabSetup" -ItemType "directory" -Force 11 | Invoke-WebRequest -Uri "https://raw.githubusercontent.com/jakewalsh90/Terraform-Azure/main/Azure-NetApp-Files-CRR-BaseLab/PowerShell/DC2/baselab_DC2JoinDomain.ps1" -OutFile "C:\BaselabSetup\baselab_DC2JoinDomain.ps1" 12 | Invoke-WebRequest -Uri "https://raw.githubusercontent.com/jakewalsh90/Terraform-Azure/main/Azure-NetApp-Files-CRR-BaseLab/PowerShell/DC2/baselab_DC2Promote.ps1" -OutFile "C:\BaselabSetup\baselab_DC2Promote.ps1" 13 | # Setup and Partition Data Disk 14 | Get-Disk | Where partitionstyle -eq 'raw' | Initialize-Disk -PartitionStyle MBR -PassThru | New-Partition -AssignDriveLetter -UseMaximumSize | Format-Volume -FileSystem NTFS -NewFileSystemLabel 'Data' -Confirm:$false 15 | # Allow Ping 16 | Set-NetFirewallRule -DisplayName "File and Printer Sharing (Echo Request - ICMPv4-In)" -enabled True 17 | Set-NetFirewallRule -DisplayName "File and Printer Sharing (Echo Request - ICMPv6-In)" -enabled True 18 | # Install Roles to make Server a Domain Controller 19 | Install-windowsfeature -name AD-Domain-Services -IncludeManagementTools 20 | Install-windowsfeature -name DNS -IncludeManagementTools 21 | Clear-DnsClientCache 22 | -------------------------------------------------------------------------------- /Cross-Region-Load-Balancer-Lab/VirtualNetworks.tf: -------------------------------------------------------------------------------- 1 | # Virtual Networks 2 | resource "azurerm_virtual_network" "vnet-con" { 3 | for_each = var.regions 4 | name = "vnet-${each.value.location}-con" 5 | address_space = [each.value.cidr] 6 | location = each.value.location 7 | resource_group_name = azurerm_resource_group.rg-con[each.key].name 8 | } 9 | # Subnets 10 | resource "azurerm_subnet" "subnet-con" { 11 | for_each = var.regions 12 | name = "subnet-${each.value.location}-01" 13 | resource_group_name = azurerm_resource_group.rg-con[each.key].name 14 | virtual_network_name = azurerm_virtual_network.vnet-con[each.key].name 15 | address_prefixes = [cidrsubnet("${each.value.cidr}", 2, 0)] 16 | } 17 | # Network Security Groups 18 | resource "azurerm_network_security_group" "nsg" { 19 | for_each = var.regions 20 | name = "nsg-${each.value.location}-01" 21 | location = each.value.location 22 | resource_group_name = azurerm_resource_group.rg-con[each.key].name 23 | 24 | security_rule { 25 | name = "AllowInternetInbound" 26 | priority = 100 27 | direction = "Inbound" 28 | access = "Allow" 29 | protocol = "Tcp" 30 | source_port_range = "*" 31 | destination_port_range = "*" 32 | source_address_prefix = "*" 33 | destination_address_prefix = "*" 34 | } 35 | 36 | } 37 | # Network Security Group Associations 38 | resource "azurerm_subnet_network_security_group_association" "nsg-assocation" { 39 | for_each = var.regions 40 | subnet_id = azurerm_subnet.subnet-con[each.key].id 41 | network_security_group_id = azurerm_network_security_group.nsg[each.key].id 42 | } -------------------------------------------------------------------------------- /Azure-KeyVault-with-Secret/azuredeploy.tf: -------------------------------------------------------------------------------- 1 | #Resource Groups 2 | resource "azurerm_resource_group" "rg1" { 3 | name = var.azure-rg-1 4 | location = var.loc1 5 | tags = { 6 | Environment = var.environment_tag 7 | } 8 | } 9 | #Create KeyVault ID 10 | resource "random_id" "kvname" { 11 | byte_length = 5 12 | prefix = "keyvault" 13 | } 14 | #Keyvault Creation 15 | data "azurerm_client_config" "current" {} 16 | resource "azurerm_key_vault" "kv1" { 17 | depends_on = [azurerm_resource_group.rg1] 18 | name = random_id.kvname.hex 19 | location = var.loc1 20 | resource_group_name = var.azure-rg-1 21 | enabled_for_disk_encryption = true 22 | tenant_id = data.azurerm_client_config.current.tenant_id 23 | soft_delete_retention_days = 7 24 | purge_protection_enabled = false 25 | 26 | sku_name = "standard" 27 | 28 | access_policy { 29 | tenant_id = data.azurerm_client_config.current.tenant_id 30 | object_id = data.azurerm_client_config.current.object_id 31 | 32 | key_permissions = [ 33 | "Get", 34 | ] 35 | 36 | secret_permissions = [ 37 | "Get", "Backup", "Delete", "List", "Purge", "Recover", "Restore", "Set", 38 | ] 39 | 40 | storage_permissions = [ 41 | "Get", 42 | ] 43 | } 44 | tags = { 45 | Environment = var.environment_tag 46 | } 47 | } 48 | #Create KeyVault VM password 49 | resource "random_password" "vmpassword" { 50 | length = 20 51 | special = true 52 | } 53 | #Create Key Vault Secret 54 | resource "azurerm_key_vault_secret" "vmpassword" { 55 | name = "vmpassword" 56 | value = random_password.vmpassword.result 57 | key_vault_id = azurerm_key_vault.kv1.id 58 | depends_on = [azurerm_key_vault.kv1] 59 | } -------------------------------------------------------------------------------- /Virtual-WAN-Demo/variables.tf: -------------------------------------------------------------------------------- 1 | # Variables 2 | variable "environment_tag" { 3 | type = string 4 | description = "Environment tag value" 5 | } 6 | variable "region1" { 7 | type = string 8 | description = "location 1 for the lab" 9 | } 10 | variable "region2" { 11 | type = string 12 | description = "location 2 for the lab" 13 | } 14 | variable "virtual-wan-region1-hub1-prefix1" { 15 | type = string 16 | description = "Address space for virtual-wan Location 1 Hub 1" 17 | } 18 | variable "virtual-wan-region2-hub1-prefix1" { 19 | type = string 20 | description = "Address space for virtual-wan Location 2 Hub 1" 21 | } 22 | variable "region1-vnet1-address-space" { 23 | type = string 24 | description = "VNET address space for region 1 vnet" 25 | } 26 | variable "region1-vnet1-snet1-range" { 27 | type = string 28 | description = "Subnet address space for region 1 subnet" 29 | } 30 | variable "region1-vnet1-bastion-snet-range" { 31 | type = string 32 | description = "Subnet address space for region 1 Bastion subnet" 33 | } 34 | variable "region2-vnet1-address-space" { 35 | type = string 36 | description = "VNET address space for region 2 vnet" 37 | } 38 | variable "region2-vnet1-snet1-range" { 39 | type = string 40 | description = "Subnet address space for region 2 subnet" 41 | } 42 | variable "region2-vnet1-bastion-snet-range" { 43 | type = string 44 | description = "Subnet address space for region 2 Bastion subnet" 45 | } 46 | variable "vmsize" { 47 | type = string 48 | description = "vm size" 49 | } 50 | variable "adminusername" { 51 | type = string 52 | description = "admin username" 53 | } 54 | # Optional Resources 55 | variable "azfw" { 56 | type = bool 57 | description = "Sets if Azure Firewalls and Policy are created or not" 58 | } -------------------------------------------------------------------------------- /Core-Environment-DemoLab-v1/rg.tf: -------------------------------------------------------------------------------- 1 | data "azurerm_client_config" "current" {} 2 | # Resource Groups 3 | resource "azurerm_resource_group" "rg-ide" { 4 | for_each = var.regions 5 | name = "rg-${each.value.code}-ide" 6 | location = each.value.region 7 | tags = { environment = "identity", region = each.value.code, tfcreated = "true" } 8 | } 9 | resource "azurerm_resource_group" "rg-sec" { 10 | for_each = var.regions 11 | name = "rg-${each.value.code}-sec" 12 | location = each.value.region 13 | tags = { environment = "security", region = each.value.code, tfcreated = "true" } 14 | } 15 | resource "azurerm_resource_group" "rg-con" { 16 | for_each = var.regions 17 | name = "rg-${each.value.code}-con" 18 | location = each.value.region 19 | tags = { environment = "connectivity", region = each.value.code, tfcreated = "true" } 20 | } 21 | resource "azurerm_resource_group" "rg-man" { 22 | for_each = var.regions 23 | name = "rg-${each.value.code}-man" 24 | location = each.value.region 25 | tags = { environment = "management", region = each.value.code, tfcreated = "true" } 26 | } 27 | resource "azurerm_resource_group" "rg-log" { 28 | for_each = var.regions 29 | name = "rg-${each.value.code}-log" 30 | location = each.value.region 31 | tags = { environment = "logging", region = each.value.code, tfcreated = "true" } 32 | } 33 | resource "azurerm_resource_group" "rg-aut" { 34 | for_each = var.regions 35 | name = "rg-${each.value.code}-aut" 36 | location = each.value.region 37 | tags = { environment = "automation", region = each.value.code, tfcreated = "true" } 38 | } 39 | resource "azurerm_resource_group" "rg-avd" { 40 | for_each = var.regions 41 | name = "rg-${each.value.code}-avd" 42 | location = each.value.region 43 | tags = { environment = "avd", region = each.value.code, tfcreated = "true" } 44 | } -------------------------------------------------------------------------------- /Azure-Backup-Demo-Resources/FileShare.tf: -------------------------------------------------------------------------------- 1 | # random string 2 | resource "random_id" "vaultid2" { 3 | byte_length = 5 4 | prefix = "rsv" 5 | } 6 | resource "random_id" "storage2" { 7 | byte_length = 5 8 | prefix = "str" 9 | } 10 | # Resource Group 11 | resource "azurerm_resource_group" "rg2" { 12 | name = "rg-backup-02" 13 | location = var.location 14 | } 15 | # Recovery Services Vault 16 | resource "azurerm_recovery_services_vault" "rsv2" { 17 | name = random_id.vaultid2.hex 18 | location = var.location 19 | resource_group_name = azurerm_resource_group.rg2.name 20 | sku = "Standard" 21 | 22 | soft_delete_enabled = true 23 | } 24 | # Storage Account and Share 25 | resource "azurerm_storage_account" "storage2" { 26 | name = random_id.storage2.hex 27 | location = var.location 28 | resource_group_name = azurerm_resource_group.rg2.name 29 | account_tier = "Standard" 30 | account_replication_type = "LRS" 31 | } 32 | resource "azurerm_storage_share" "share2" { 33 | name = "tf-demo2" 34 | storage_account_name = azurerm_storage_account.storage2.name 35 | quota = 1 36 | } 37 | # Azure Backup Configuration 38 | resource "azurerm_backup_container_storage_account" "storage2" { 39 | resource_group_name = azurerm_resource_group.rg2.name 40 | recovery_vault_name = azurerm_recovery_services_vault.rsv2.name 41 | storage_account_id = azurerm_storage_account.storage2.id 42 | } 43 | # Backup Policy 44 | resource "azurerm_backup_policy_file_share" "backup-pol2" { 45 | name = "terraform-example-backup-02" 46 | resource_group_name = azurerm_resource_group.rg2.name 47 | recovery_vault_name = azurerm_recovery_services_vault.rsv2.name 48 | 49 | backup { 50 | frequency = "Daily" 51 | time = "23:00" 52 | } 53 | 54 | retention_daily { 55 | count = 10 56 | } 57 | } -------------------------------------------------------------------------------- /Virtual-WAN-Demo/README.md: -------------------------------------------------------------------------------- 1 | # Azure Virtual WAN Demo Environment 2 | 3 | ## Overview 4 | This is a Terraform based demonstration of Azure Virtual WAN. The environment is designed to provide a simple foundation that you can add additional services (Gateways, Firewalls, etc.) into, allowing the demonstration of concepts and technologies. This lab has two options - with or without Azure Firewall, and is based on a two-region design. 5 | 6 | ## What does this Lab deploy? 7 | 8 | ### Without Azure Firewall: 9 | 10 | ![Virtual WAN Demo Lab](https://raw.githubusercontent.com/jakewalsh90/Terraform-Azure/main/Virtual-WAN-Demo/images/Virtual-WAN.png?raw=true) 11 | 12 | ### With Azure Firewall: 13 | 14 | ![Virtual WAN Demo Lab - with Azure Firewall](https://raw.githubusercontent.com/jakewalsh90/Terraform-Azure/main/Virtual-WAN-Demo/images/Virtual-WAN-with-Firewall.png?raw=true) 15 | 16 | ### What does this Lab Deploy? 17 | 18 | This lab deploys the following Resources: 19 | 20 | 1. A Resource Group in two Azure Regions (based on variables) 21 | 2. A Virtual WAN in the Primary Region 22 | 3. A Virtual WAN Hub in two Azure Regions 23 | 4. A vNet in each Azure Region which is connected to the Virtual WAN Hub. 24 | 6. A Subnet and NSG in each of the above vNets. 25 | 7. A Subnet in each Region to be used for Azure Bastion. 26 | 8. Azure Bastion in each Region to allow for access to the VMs for Testing. 27 | 9. A Virtual Machine in each Azure Region (in the Regional vNets), to allow testing of Connectivity. 28 | 10. A Custom Script Extension that runs on both VMs to add a few testing Apps (using Chocolatey) and allows ICMP through Windows Firewall for testing. 29 | 30 | ### Enabling Azure Firewall 31 | 32 | To enable Azure Firewall set the following variable to true within the terraform.tfvars file: 33 | 34 | https://github.com/jakewalsh90/Terraform-Azure/blob/63d63c1e764c64e2143f01939f9ef04f866b4ae3/Virtual-WAN-Demo/terraform.tfvars#L17-L18 -------------------------------------------------------------------------------- /Virtual-WAN-Demo/vwan.tf: -------------------------------------------------------------------------------- 1 | # virtual-wan Resources 2 | # virtual-wan 3 | resource "azurerm_virtual_wan" "virtual-wan1" { 4 | name = "virtual-wan-demo-01" 5 | resource_group_name = azurerm_resource_group.region1-rg1.name 6 | location = var.region1 7 | 8 | # Configuration 9 | office365_local_breakout_category = "OptimizeAndAllow" 10 | 11 | tags = { 12 | Environment = var.environment_tag 13 | } 14 | } 15 | # virtual-wan Hub 1 16 | resource "azurerm_virtual_hub" "region1-vhub1" { 17 | name = "${var.region1}-virtual-wan-hub-01" 18 | resource_group_name = azurerm_resource_group.region1-rg1.name 19 | location = var.region1 20 | virtual_wan_id = azurerm_virtual_wan.virtual-wan1.id 21 | address_prefix = var.virtual-wan-region1-hub1-prefix1 22 | 23 | tags = { 24 | Environment = var.environment_tag 25 | } 26 | } 27 | # virtual-wan Hub 2 28 | resource "azurerm_virtual_hub" "region2-vhub1" { 29 | name = "${var.region2}-virtual-wan-hub-02" 30 | resource_group_name = azurerm_resource_group.region2-rg1.name 31 | location = var.region2 32 | virtual_wan_id = azurerm_virtual_wan.virtual-wan1.id 33 | address_prefix = var.virtual-wan-region2-hub1-prefix1 34 | 35 | tags = { 36 | Environment = var.environment_tag 37 | } 38 | } 39 | # virtual-wan Hub Connection 1 40 | resource "azurerm_virtual_hub_connection" "region1-connection1" { 41 | name = "${var.region1}-conn-vnet1-to-virtual-wan-hub" 42 | virtual_hub_id = azurerm_virtual_hub.region1-vhub1.id 43 | remote_virtual_network_id = azurerm_virtual_network.region1-vnet1.id 44 | } 45 | # virtual-wan Hub Connection 2 46 | resource "azurerm_virtual_hub_connection" "region2-connection1" { 47 | name = "${var.region2}-conn-vnet1-to-virtual-wan-hub" 48 | virtual_hub_id = azurerm_virtual_hub.region2-vhub1.id 49 | remote_virtual_network_id = azurerm_virtual_network.region2-vnet1.id 50 | } -------------------------------------------------------------------------------- /Azure Lab Services/lab.tf: -------------------------------------------------------------------------------- 1 | # Resource Group for Lab 2 | resource "azurerm_resource_group" "rg" { 3 | name = "rg-${var.labname}-${var.region}" 4 | location = var.region 5 | tags = { 6 | Environment = var.labname 7 | Function = "AzureLabServices" 8 | } 9 | } 10 | # Lab Service Plan 11 | resource "azurerm_lab_service_plan" "plan1" { 12 | name = "lsp-${var.labname}-${var.region}" 13 | resource_group_name = azurerm_resource_group.rg.name 14 | location = var.region 15 | allowed_regions = [var.region] 16 | 17 | support { 18 | email = "jake@jakewalsh.co.uk" 19 | instructions = "Welcome to your Azure Lab, please raise a support request if you encounter any issues" 20 | url = "https://jakewalsh.co.uk" 21 | } 22 | tags = { 23 | Environment = var.labname 24 | Function = "AzureLabServices" 25 | } 26 | } 27 | # Lab 28 | resource "azurerm_lab_service_lab" "lab1" { 29 | name = "lab-${var.labname}-${var.region}" 30 | resource_group_name = azurerm_resource_group.rg.name 31 | location = var.region 32 | title = "Lab 1" 33 | description = "Virtual Machine for Lab Environment" 34 | lab_plan_id = azurerm_lab_service_plan.plan1.id 35 | 36 | connection_setting { 37 | client_rdp_access = "Public" 38 | } 39 | 40 | security { 41 | open_access_enabled = false 42 | } 43 | 44 | virtual_machine { 45 | shared_password_enabled = true 46 | 47 | admin_user { 48 | username = var.labusername 49 | password = azurerm_key_vault_secret.vmpassword.value 50 | } 51 | 52 | image_reference { 53 | offer = "windows-11" 54 | publisher = "MicrosoftWindowsDesktop" 55 | sku = "win11-21h2-pro" 56 | version = "latest" 57 | } 58 | 59 | sku { 60 | name = "Classic_Fsv2_8_16GB_128_S_SSD" 61 | capacity = 1 62 | } 63 | } 64 | tags = { 65 | Environment = var.labname 66 | Function = "AzureLabServices" 67 | } 68 | } -------------------------------------------------------------------------------- /Virtual-WAN-Demo/firewall.tf: -------------------------------------------------------------------------------- 1 | # Azure Firewall 2 | resource "azurerm_firewall" "region1-azfw" { 3 | count = var.azfw ? 1 : 0 4 | name = "${var.region1}-fw01" 5 | location = var.region1 6 | resource_group_name = azurerm_resource_group.region1-rg1.name 7 | sku_tier = "Standard" 8 | sku_name = "AZFW_Hub" 9 | firewall_policy_id = azurerm_firewall_policy.fw-pol01[0].id 10 | virtual_hub { 11 | virtual_hub_id = azurerm_virtual_hub.region1-vhub1.id 12 | public_ip_count = 1 13 | } 14 | } 15 | resource "azurerm_firewall" "region2-azfw" { 16 | count = var.azfw ? 1 : 0 17 | name = "${var.region2}-fw01" 18 | location = var.region2 19 | resource_group_name = azurerm_resource_group.region2-rg1.name 20 | sku_tier = "Standard" 21 | sku_name = "AZFW_Hub" 22 | firewall_policy_id = azurerm_firewall_policy.fw-pol01[0].id 23 | virtual_hub { 24 | virtual_hub_id = azurerm_virtual_hub.region2-vhub1.id 25 | public_ip_count = 1 26 | } 27 | } 28 | # Azure Firewall Policy 29 | resource "azurerm_firewall_policy" "fw-pol01" { 30 | count = var.azfw ? 1 : 0 31 | name = "fw-pol01" 32 | resource_group_name = azurerm_resource_group.region1-rg1.name 33 | location = var.region1 34 | } 35 | # Azure Firewall Policy Rule Collection Group 36 | resource "azurerm_firewall_policy_rule_collection_group" "network-rules1" { 37 | count = var.azfw ? 1 : 0 38 | name = "fw-pol01-rules" 39 | firewall_policy_id = azurerm_firewall_policy.fw-pol01[0].id 40 | priority = 100 41 | network_rule_collection { 42 | name = "network_rules1" 43 | priority = 100 44 | action = "Allow" 45 | rule { 46 | name = "network_rule_collection1_rule1" 47 | protocols = ["TCP", "UDP", "ICMP"] 48 | source_addresses = ["*"] 49 | destination_addresses = ["*"] 50 | destination_ports = ["*"] 51 | } 52 | } 53 | } -------------------------------------------------------------------------------- /Core-Environment-DemoLab-v1/keyvault.tf: -------------------------------------------------------------------------------- 1 | # Key Vault 2 | resource "random_id" "kvname" { 3 | byte_length = 5 4 | prefix = "kv-" 5 | } 6 | resource "azurerm_key_vault" "keyvault" { 7 | name = random_id.kvname.hex 8 | resource_group_name = azurerm_resource_group.rg-sec["region1"].name 9 | location = var.regions.region1.region 10 | enabled_for_disk_encryption = true 11 | tenant_id = var.tenant_id 12 | soft_delete_retention_days = 7 13 | purge_protection_enabled = false 14 | 15 | sku_name = "standard" 16 | 17 | access_policy { 18 | tenant_id = data.azurerm_client_config.current.tenant_id 19 | object_id = data.azurerm_client_config.current.object_id 20 | 21 | key_permissions = ["Get", ] 22 | 23 | secret_permissions = ["Get", "Backup", "Delete", "List", "Purge", "Recover", "Restore", "Set", ] 24 | 25 | storage_permissions = ["Get", ] 26 | } 27 | access_policy { 28 | tenant_id = data.azurerm_client_config.current.tenant_id 29 | object_id = var.admin_id 30 | 31 | key_permissions = ["Get", ] 32 | 33 | secret_permissions = ["Get", "Backup", "Delete", "List", "Purge", "Recover", "Restore", "Set", ] 34 | 35 | storage_permissions = ["Get", ] 36 | } 37 | tags = { environment = "security", region = var.regions.region1.code, tfcreated = "true" } 38 | } 39 | # Secret for VM Passwords 40 | resource "random_password" "vmpassword" { 41 | length = 20 42 | special = true 43 | } 44 | resource "azurerm_key_vault_secret" "vmpassword" { 45 | name = "vmpassword" 46 | value = random_password.vmpassword.result 47 | key_vault_id = azurerm_key_vault.keyvault.id 48 | depends_on = [azurerm_key_vault.keyvault] 49 | } 50 | # Secret for VPN Pre-Shared Key 51 | resource "random_password" "vpnpsk" { 52 | length = 20 53 | special = true 54 | } 55 | resource "azurerm_key_vault_secret" "vpnpsk" { 56 | name = "vpnpsk" 57 | value = random_password.vpnpsk.result 58 | key_vault_id = azurerm_key_vault.keyvault.id 59 | depends_on = [azurerm_key_vault.keyvault] 60 | } -------------------------------------------------------------------------------- /Cross-Region-Load-Balancer-Lab/CrossRegionLB.tf: -------------------------------------------------------------------------------- 1 | # Public IP - Cross Region Load Balancer 2 | resource "azurerm_public_ip" "pip-cr-lb" { 3 | name = "pip-cross-region-lb" 4 | location = var.regions.region1.location 5 | resource_group_name = "rg-${var.regions.region1.location}-con" 6 | allocation_method = "Static" 7 | sku = "Standard" 8 | sku_tier = "Global" 9 | domain_name_label = "lb-global-${random_id.dns-name.hex}" 10 | depends_on = [azurerm_resource_group.rg-con] 11 | } 12 | # Cross-Region Load Balancer 13 | resource "azurerm_lb" "cross-region-lb" { 14 | name = "cross-region-lb-${var.regions.region1.location}" 15 | location = var.regions.region1.location 16 | resource_group_name = "rg-${var.regions.region1.location}-con" 17 | sku = "Standard" 18 | sku_tier = "Global" 19 | 20 | frontend_ip_configuration { 21 | name = "PublicIPAddress" 22 | public_ip_address_id = azurerm_public_ip.pip-cr-lb.id 23 | } 24 | } 25 | resource "azurerm_lb_backend_address_pool" "cross-region-lb-pool" { 26 | loadbalancer_id = azurerm_lb.cross-region-lb.id 27 | name = "BackEndAddressPool" 28 | } 29 | resource "azurerm_lb_backend_address_pool_address" "cross-region-lb-pool-address" { 30 | for_each = var.regions 31 | name = "regional-lb-${each.value.location}" 32 | backend_address_pool_id = azurerm_lb_backend_address_pool.cross-region-lb-pool.id 33 | backend_address_ip_configuration_id = azurerm_lb.regional-lb[each.key].frontend_ip_configuration[0].id 34 | } 35 | resource "azurerm_lb_rule" "cross-region-lb-rule" { 36 | loadbalancer_id = azurerm_lb.cross-region-lb.id 37 | name = "LBRule" 38 | protocol = "Tcp" 39 | frontend_port = 80 40 | backend_port = 80 41 | frontend_ip_configuration_name = azurerm_lb.cross-region-lb.frontend_ip_configuration[0].name 42 | backend_address_pool_ids = [azurerm_lb_backend_address_pool.cross-region-lb-pool.id] 43 | } -------------------------------------------------------------------------------- /Dual-Region-Azure-BaseLab/terraform.tfvars: -------------------------------------------------------------------------------- 1 | environment_tag = "jakewalsh90-Dual-Region-Azure-BaseLab" 2 | azure-rg-1 = "baselabv2-region1infra" 3 | azure-rg-2 = "baselabv2-security" 4 | azure-rg-3 = "baselabv2-region2infra" 5 | loc1 = "uk south" 6 | loc2 = "east us" 7 | region1-vnet1-name = "region1-vnet1-hub1" 8 | region1-vnet2-name = "region1-vnet2-spoke1" 9 | region1-vnet1-address-space = "10.10.0.0/16" 10 | region1-vnet2-address-space = "10.11.0.0/16" 11 | region2-vnet1-name = "region2-vnet1-hub1" 12 | region2-vnet2-name = "region2-vnet2-spoke1" 13 | region2-vnet1-address-space = "10.20.0.0/16" 14 | region2-vnet2-address-space = "10.21.0.0/16" 15 | region1-vnet1-snet1-name = "region1-vnet1-snet-infra1" 16 | region1-vnet1-snet2-name = "region1-vnet1-snet-infra2" 17 | region1-vnet1-snet3-name = "region1-vnet1-snet-infra3" 18 | region1-vnet2-snet1-name = "region1-vnet2-snet-infra1" 19 | region1-vnet2-snet2-name = "region1-vnet2-snet-infra2" 20 | region1-vnet2-snet3-name = "region1-vnet2-snet-anf1" 21 | region1-vnet1-snet1-range = "10.10.1.0/24" 22 | region1-vnet1-snet2-range = "10.10.2.0/24" 23 | region1-vnet1-snet3-range = "10.10.3.0/24" 24 | region1-vnet2-snet1-range = "10.11.1.0/24" 25 | region1-vnet2-snet2-range = "10.11.2.0/24" 26 | region1-vnet2-snet3-range = "10.11.3.0/24" 27 | region2-vnet1-snet1-name = "region2-vnet1-snet-infra1" 28 | region2-vnet1-snet2-name = "region2-vnet1-snet-infra2" 29 | region2-vnet1-snet3-name = "region2-vnet1-snet-infra3" 30 | region2-vnet2-snet1-name = "region2-vnet2-snet-infra1" 31 | region2-vnet2-snet2-name = "region2-vnet2-snet-infra2" 32 | region2-vnet2-snet3-name = "region2-vnet2-snet-anf1" 33 | region2-vnet1-snet1-range = "10.20.1.0/24" 34 | region2-vnet1-snet2-range = "10.20.2.0/24" 35 | region2-vnet1-snet3-range = "10.20.3.0/24" 36 | region2-vnet2-snet1-range = "10.21.1.0/24" 37 | region2-vnet2-snet2-range = "10.21.2.0/24" 38 | region2-vnet2-snet3-range = "10.21.3.0/24" 39 | vmsize-domaincontroller = "Standard_D2s_v4" 40 | adminusername = "labadmin" -------------------------------------------------------------------------------- /Azure-NetApp-Files-CRR-BaseLab/terraform.tfvars: -------------------------------------------------------------------------------- 1 | environment_tag = "jakewalsh90-Dual-Region-Azure-BaseLab" 2 | azure-rg-1 = "baselabv2-region1infra" 3 | azure-rg-2 = "baselabv2-security" 4 | azure-rg-3 = "baselabv2-region2infra" 5 | loc1 = "germany west central" 6 | loc2 = "uk south" 7 | region1-vnet1-name = "region1-vnet1-hub1" 8 | region1-vnet2-name = "region1-vnet2-spoke1" 9 | region1-vnet1-address-space = "10.10.0.0/16" 10 | region1-vnet2-address-space = "10.11.0.0/16" 11 | region2-vnet1-name = "region2-vnet1-hub1" 12 | region2-vnet2-name = "region2-vnet2-spoke1" 13 | region2-vnet1-address-space = "10.20.0.0/16" 14 | region2-vnet2-address-space = "10.21.0.0/16" 15 | region1-vnet1-snet1-name = "region1-vnet1-snet-infra1" 16 | region1-vnet1-snet2-name = "region1-vnet1-snet-infra2" 17 | region1-vnet1-snet3-name = "region1-vnet1-snet-infra3" 18 | region1-vnet2-snet1-name = "region1-vnet2-snet-infra1" 19 | region1-vnet2-snet2-name = "region1-vnet2-snet-infra2" 20 | region1-vnet2-snet3-name = "region1-vnet2-snet-anf1" 21 | region1-vnet1-snet1-range = "10.10.1.0/24" 22 | region1-vnet1-snet2-range = "10.10.2.0/24" 23 | region1-vnet1-snet3-range = "10.10.3.0/24" 24 | region1-vnet2-snet1-range = "10.11.1.0/24" 25 | region1-vnet2-snet2-range = "10.11.2.0/24" 26 | region1-vnet2-snet3-range = "10.11.3.0/24" 27 | region2-vnet1-snet1-name = "region2-vnet1-snet-infra1" 28 | region2-vnet1-snet2-name = "region2-vnet1-snet-infra2" 29 | region2-vnet1-snet3-name = "region2-vnet1-snet-infra3" 30 | region2-vnet2-snet1-name = "region2-vnet2-snet-infra1" 31 | region2-vnet2-snet2-name = "region2-vnet2-snet-infra2" 32 | region2-vnet2-snet3-name = "region2-vnet2-snet-anf1" 33 | region2-vnet1-snet1-range = "10.20.1.0/24" 34 | region2-vnet1-snet2-range = "10.20.2.0/24" 35 | region2-vnet1-snet3-range = "10.20.3.0/24" 36 | region2-vnet2-snet1-range = "10.21.1.0/24" 37 | region2-vnet2-snet2-range = "10.21.2.0/24" 38 | region2-vnet2-snet3-range = "10.21.3.0/24" 39 | vmsize-domaincontroller = "Standard_D2s_v4" 40 | adminusername = "labadmin" -------------------------------------------------------------------------------- /Cross-Region-Load-Balancer-Lab/VirtualMachines.tf: -------------------------------------------------------------------------------- 1 | # NICs 2 | resource "azurerm_network_interface" "nics" { 3 | for_each = var.regions 4 | name = "nic-${each.value.location}-vm" 5 | resource_group_name = azurerm_resource_group.rg-host[each.key].name 6 | location = each.value.location 7 | 8 | ip_configuration { 9 | name = "internal" 10 | subnet_id = azurerm_subnet.subnet-con[each.key].id 11 | private_ip_address_allocation = "Static" 12 | private_ip_address = cidrhost(cidrsubnet("${each.value.cidr}", 2, 0), 4) 13 | } 14 | } 15 | # Virtual Machines 16 | resource "azurerm_windows_virtual_machine" "vms" { 17 | for_each = var.regions 18 | name = "vm-${each.value.location}" 19 | resource_group_name = azurerm_resource_group.rg-host[each.key].name 20 | location = each.value.location 21 | size = "Standard_B4ms" 22 | admin_username = var.adminuser 23 | admin_password = azurerm_key_vault_secret.vmpassword.value 24 | enable_automatic_updates = "true" 25 | network_interface_ids = [ 26 | azurerm_network_interface.nics[each.key].id, 27 | ] 28 | 29 | os_disk { 30 | caching = "ReadWrite" 31 | storage_account_type = "StandardSSD_LRS" 32 | } 33 | 34 | source_image_reference { 35 | publisher = "MicrosoftWindowsServer" 36 | offer = "WindowsServer" 37 | sku = "2022-Datacenter" 38 | version = "latest" 39 | } 40 | } 41 | # Setup script to install IIS 42 | resource "azurerm_virtual_machine_extension" "vmsetup" { 43 | for_each = var.regions 44 | name = "cse-${each.value.location}-01" 45 | virtual_machine_id = azurerm_windows_virtual_machine.vms[each.key].id 46 | publisher = "Microsoft.Compute" 47 | type = "CustomScriptExtension" 48 | type_handler_version = "1.9" 49 | 50 | protected_settings = <reboot region2-dc01-vm (After region1-dc01-vm has been setup and DNS is functional a reboot clears any stale DNS records on the 2nd DC). 45 | 46 | The next setup scripts are in C:\baselabSetup of the region2-dc01-vm after deployment, and should be run in this order: 47 | 48 | 1. baselab_DC2JoinDomain.ps1 - joins the VM to the Domain. 49 | 2. baselab_DC2Promote.ps1 - promotes the VM to a Domain Controller. 50 | 51 | The lab is now deployed and ready to use! 52 | -------------------------------------------------------------------------------- /Azure-OpenAI-Demo-1/azuredeploy.tf: -------------------------------------------------------------------------------- 1 | # Resource Group 2 | resource "azurerm_resource_group" "rg1" { 3 | name = "rg-${var.region}-aoai" 4 | location = var.region 5 | } 6 | # Random IDs for OAI Resources 7 | resource "random_id" "cognitive" { 8 | byte_length = 6 9 | } 10 | resource "random_id" "pn-cognitive" { 11 | byte_length = 6 12 | } 13 | # Cognitive Services - without Private Networking 14 | resource "azurerm_cognitive_account" "cognitive1" { 15 | count = var.privatenetworking ? 0 : 1 16 | name = "oai-${random_id.cognitive.hex}" 17 | location = azurerm_resource_group.rg1.location 18 | resource_group_name = azurerm_resource_group.rg1.name 19 | sku_name = "S0" 20 | kind = "OpenAI" 21 | } 22 | # Cognitive Deployments - without Private Networking 23 | resource "azurerm_cognitive_deployment" "gpt-35-turbo" { 24 | count = var.privatenetworking ? 0 : 1 25 | name = "gpt-35-turbo" 26 | cognitive_account_id = azurerm_cognitive_account.cognitive1[0].id 27 | model { 28 | format = "OpenAI" 29 | name = "gpt-35-turbo" 30 | } 31 | scale { 32 | type = "Standard" 33 | } 34 | } 35 | resource "azurerm_cognitive_deployment" "text-embedding-ada-002" { 36 | count = var.privatenetworking ? 0 : 1 37 | name = "text-embedding-ada-002" 38 | cognitive_account_id = azurerm_cognitive_account.cognitive1[0].id 39 | model { 40 | format = "OpenAI" 41 | name = "text-embedding-ada-002" 42 | } 43 | scale { 44 | type = "Standard" 45 | } 46 | } 47 | # Cognitive Services - with Private Networking 48 | resource "azurerm_cognitive_account" "pn-cognitive1" { 49 | count = var.privatenetworking ? 1 : 0 50 | name = "oai-${random_id.pn-cognitive.hex}" 51 | location = azurerm_resource_group.rg1.location 52 | resource_group_name = azurerm_resource_group.rg1.name 53 | sku_name = "S0" 54 | kind = "OpenAI" 55 | custom_subdomain_name = "oai-${random_id.pn-cognitive.hex}" 56 | 57 | network_acls { 58 | default_action = "Deny" 59 | virtual_network_rules { 60 | subnet_id = azurerm_subnet.subnet1-aoai[0].id 61 | } 62 | } 63 | 64 | } 65 | # Cognitive Deployments - with Private Networking 66 | resource "azurerm_cognitive_deployment" "pn-gpt-35-turbo" { 67 | count = var.privatenetworking ? 1 : 0 68 | name = "gpt-35-turbo" 69 | cognitive_account_id = azurerm_cognitive_account.pn-cognitive1[0].id 70 | model { 71 | format = "OpenAI" 72 | name = "gpt-35-turbo" 73 | } 74 | scale { 75 | type = "Standard" 76 | } 77 | } 78 | resource "azurerm_cognitive_deployment" "pn-text-embedding-ada-002" { 79 | count = var.privatenetworking ? 1 : 0 80 | name = "text-embedding-ada-002" 81 | cognitive_account_id = azurerm_cognitive_account.pn-cognitive1[0].id 82 | model { 83 | format = "OpenAI" 84 | name = "text-embedding-ada-002" 85 | } 86 | scale { 87 | type = "Standard" 88 | } 89 | } 90 | # VNET and Subnet for Private Networking - if required 91 | resource "azurerm_virtual_network" "vnet1" { 92 | count = var.privatenetworking ? 1 : 0 93 | name = "vnet-${var.region}-aoai" 94 | location = azurerm_resource_group.rg1.location 95 | resource_group_name = azurerm_resource_group.rg1.name 96 | address_space = [var.region1-cidr] 97 | } 98 | resource "azurerm_subnet" "subnet1-aoai" { 99 | count = var.privatenetworking ? 1 : 0 100 | name = "subnet1-aoai" 101 | resource_group_name = azurerm_resource_group.rg1.name 102 | virtual_network_name = azurerm_virtual_network.vnet1[0].name 103 | address_prefixes = [var.region1-subnet] 104 | service_endpoints = ["Microsoft.CognitiveServices"] 105 | } -------------------------------------------------------------------------------- /Virtual-WAN-Demo/networks.tf: -------------------------------------------------------------------------------- 1 | # Networks 2 | # Region 1 VNET 1 3 | resource "azurerm_virtual_network" "region1-vnet1" { 4 | name = "${var.region1}-vnet-01" 5 | location = var.region1 6 | resource_group_name = azurerm_resource_group.region1-rg1.name 7 | address_space = [var.region1-vnet1-address-space] 8 | tags = { 9 | Environment = var.environment_tag 10 | } 11 | } 12 | resource "azurerm_subnet" "region1-vnet1-snet1" { 13 | name = "${var.region1}-vnet-01-snet-01" 14 | resource_group_name = azurerm_resource_group.region1-rg1.name 15 | virtual_network_name = azurerm_virtual_network.region1-vnet1.name 16 | address_prefixes = [var.region1-vnet1-snet1-range] 17 | } 18 | resource "azurerm_subnet" "region1-bastion-snet" { 19 | name = "AzureBastionSubnet" 20 | resource_group_name = azurerm_resource_group.region1-rg1.name 21 | virtual_network_name = azurerm_virtual_network.region1-vnet1.name 22 | address_prefixes = [var.region1-vnet1-bastion-snet-range] 23 | } 24 | # Region 2 VNET 1 25 | resource "azurerm_virtual_network" "region2-vnet1" { 26 | name = "${var.region2}-vnet-01" 27 | location = var.region2 28 | resource_group_name = azurerm_resource_group.region2-rg1.name 29 | address_space = [var.region2-vnet1-address-space] 30 | tags = { 31 | Environment = var.environment_tag 32 | } 33 | } 34 | resource "azurerm_subnet" "region2-vnet1-snet1" { 35 | name = "${var.region2}-vnet-01-snet-01" 36 | resource_group_name = azurerm_resource_group.region2-rg1.name 37 | virtual_network_name = azurerm_virtual_network.region2-vnet1.name 38 | address_prefixes = [var.region2-vnet1-snet1-range] 39 | } 40 | resource "azurerm_subnet" "region2-bastion-snet" { 41 | name = "AzureBastionSubnet" 42 | resource_group_name = azurerm_resource_group.region2-rg1.name 43 | virtual_network_name = azurerm_virtual_network.region2-vnet1.name 44 | address_prefixes = [var.region2-vnet1-bastion-snet-range] 45 | } 46 | # NSGs 47 | #Lab NSG 48 | resource "azurerm_network_security_group" "region1-nsg" { 49 | name = "${var.region1}-nsg-01" 50 | location = var.region1 51 | resource_group_name = azurerm_resource_group.region1-rg1.name 52 | 53 | security_rule { 54 | name = "RDP-In" 55 | priority = 100 56 | direction = "Inbound" 57 | access = "Allow" 58 | protocol = "*" 59 | source_port_range = "*" 60 | destination_port_range = "3389" 61 | source_address_prefix = "*" 62 | destination_address_prefix = "*" 63 | } 64 | tags = { 65 | Environment = var.environment_tag 66 | } 67 | } 68 | resource "azurerm_network_security_group" "region2-nsg" { 69 | name = "${var.region2}-nsg-01" 70 | location = var.region2 71 | resource_group_name = azurerm_resource_group.region2-rg1.name 72 | 73 | security_rule { 74 | name = "RDP-In" 75 | priority = 100 76 | direction = "Inbound" 77 | access = "Allow" 78 | protocol = "*" 79 | source_port_range = "*" 80 | destination_port_range = "3389" 81 | source_address_prefix = "*" 82 | destination_address_prefix = "*" 83 | } 84 | tags = { 85 | Environment = var.environment_tag 86 | } 87 | } 88 | # NSG Association 89 | resource "azurerm_subnet_network_security_group_association" "region1-vnet1-snet1" { 90 | subnet_id = azurerm_subnet.region1-vnet1-snet1.id 91 | network_security_group_id = azurerm_network_security_group.region1-nsg.id 92 | } 93 | resource "azurerm_subnet_network_security_group_association" "region2-vnet1-snet1" { 94 | subnet_id = azurerm_subnet.region2-vnet1-snet1.id 95 | network_security_group_id = azurerm_network_security_group.region2-nsg.id 96 | } 97 | -------------------------------------------------------------------------------- /CIDRHost-Demo/readme.md: -------------------------------------------------------------------------------- 1 | # Overview 2 | This lab demonstrates the use of cidrhost Function within Terraform. [https://www.terraform.io/language/functions/cidrhost](https://www.terraform.io/language/functions/cidrhost) 3 | 4 | ### ✅ With this function you can calculate a host IP address from a network prefix. 5 | 6 | In my example, the following Resources are created: 7 | 8 | - VNETs and Subnets (for NICs later on in the lab). I've also used Count in the Spoke Subnets to show how this Function works when using Count. Note: this is done using cidrsubnet, for which I have another Lab for in this Repo. 9 | - DNS entries for the VNETs are set using cidrhost so you can control these automatically too. 10 | - a Network Interface Card in the Hub (using cidrhost) 11 | - a Network Interface Card in the Hub (using cidrhost and join, along with the each.key option as Count is used here) 12 | - a Network Security Group that makes use of cidrhost within two example rulesets - so this shows how you can use these dynamically within objects too. (NSGs, DNS entries, Route Tables etc.) 13 | - a Route Table that has two Routes in. One demonstrates cidrhost in it's pure form, the other is from the Spoke Subnet that makes use of the Count option, so you can see this in use too. 14 | 15 | ## Using cidrhost - My Demo Environment 16 | 17 | ⚠ Note: you'll need to customise this example and calculation for your needs, this is just to demonstrate the concept! 18 | 19 | Within my demo environment, I am creating the following, based on a Single Azure Region. IP address spacing is as below: 20 | 21 | - In my first Azure Region, the assigned CIDR range is ```10.x.0.0/19``` (for the whole Region) 22 | - For each VNET I am using /21 (2046 addresses per VNET), ```10.x.0.0/21``` 23 | - This means I can use /24 for each Subnet, giving simple easy to understand Subnets that provide ample room for Resources. 24 | 25 | ✅ Thanks to the cidrsubnet function, I have only 1 variable in my terraform.tfvars file, which specifies a range for the whole region! 26 | 27 | ### Setting DNS on the VNET 28 | 29 | To set DNS on the VNET I need to provide two IP addresses, which would likely be assigned to NVAs, Load Balancers or Domain Controllers. To do this, I used the cidrhost function to calculate the IPs. This allows the IPs to be set before the NICs are even created. In the case below, my VNET is ```10.x.0.0/21``` (calculated using cidrsubnet from the Regional Variable of ```10.x.0.0/19```). 30 | 31 | dns_servers = [cidrhost("${var.region1cidr}", 4), cidrhost("${var.region1cidr}", 5)] 32 | 33 | ### Network Interface Card 34 | 35 | Network Interface Cards are also set in a similar way to the DNS entries above: 36 | 37 | private_ip_address = cidrhost("${var.region1cidr}", 4) 38 | 39 | ### Network Interface Card - on a Subnet using Count 40 | 41 | When Count is used, we can't use the same method as above (for obvious reasons - all NICs would be assigned the same IP). To overcome this we need to add ```[count.index]``` into the mix, and use join to add the Subnet Range and the Host element together: 42 | 43 | private_ip_address = cidrhost(join(", ", "${azurerm_subnet.region1-spoke1-subnets[count.index].address_prefixes}"), 4) 44 | 45 | This allows cidrhost (in combination with join) to increment the Private IP for each Resource created by Count (so it will increase the IP by 1 for each Resource created using Count) 46 | 47 | ### Network Security Group 48 | 49 | Within the Network Security Groups, we can use cidrhost easily within rules - simply by taking the relevant code item (so for example, if we wish to add a rule for a specific NIC, we'd take the cidrhost block from the NICs private IP section): 50 | 51 | source_address_prefix = cidrhost("${var.region1cidr}", 4) 52 | 53 | Example when Count and Count Index have been used: 54 | 55 | source_address_prefix = cidrhost(join(", ", "${azurerm_subnet.region1-spoke1-subnets[0].address_prefixes}"), 4) 56 | 57 | ### Route Table 58 | 59 | Route Tables are similar to the NSG example above, and interface addresses can be added in the same way: 60 | 61 | next_hop_in_ip_address = cidrhost("${var.region1cidr}", 4) 62 | 63 | Example when Count and Count Index have been used: 64 | 65 | next_hop_in_ip_address = cidrhost(join(", ", "${azurerm_subnet.region1-spoke1-subnets[0].address_prefixes}"), 4) 66 | -------------------------------------------------------------------------------- /CIDRSubnet-Demo/readme.md: -------------------------------------------------------------------------------- 1 | # Overview 2 | This lab demonstrates the use of cidrsubnet Function within Terraform. [https://www.terraform.io/language/functions/cidrsubnet](https://www.terraform.io/language/functions/cidrsubnet) 3 | 4 | Within this function you can split a CIDR range up easily use it within VNETs, Subnets, and more - all by referencing a single variable. 5 | 6 | In my example, the following Resources are created: 7 | 8 | - Resource Group 9 | - 3 VNETs 10 | - X numbers of Subnets per VNET (Using Count) 11 | 12 | ## Using cidrsubnet - My Demo Environment 13 | 14 | ⚠ Note: you'll need to customise this example and calculation for your needs, this is just to demonstrate the concept! 15 | 16 | Within my demo environment, I am creating the following, based on a Single Azure Region. IP address spacing is as below: 17 | 18 | - In my first Azure Region, the assigned CIDR range is ```10.x.0.0/19``` (for the whole Region) 19 | - For each VNET I am using /21 (2046 addresses per VNET), ```10.x.0.0/21``` 20 | - This means I can use /24 for each Subnet, giving simple easy to understand Subnets that provide ample room for Resources. 21 | 22 | ✅ Thanks to the cidrsubnet function, I have only 1 variable in my terraform.tfvars file, which specifies a range for the whole region! 23 | 24 | ## Using cidrsubnet - VNETs 25 | 26 | To use CIDR Subnet, we need to add the following line to our VNET: 27 | 28 | address_space = [cidrsubnet("${var.region1cidr}", 2, 0)] 29 | 30 | This is essentially taking a variable (var.region1cidr) which is listed in my tfvars file as ```"10.10.0.0/19"``` - thanks to cidrsubnet, this is the only place the CIDR range is noted. Everything else is split automatically, and we don't need to use lots of additional variables for each range. 31 | 32 | cidrsubnet works by splitting the CIDR range out like this: **```cidrsubnet(prefix, newbits, netnum)```** 33 | 34 | So in my case, I am asking for the prefix of ```10.x.0.0/19``` to be updated to ```10.x.0.0/21``` (that's the 2 in the newbits section being added to the Subnet Mask). I am then selecting net number 0. 35 | 36 | This results in the VNET being given the range of ```10.x.0.0/21``` 37 | 38 | For additional VNETs, we can just select the next netnum, for example: 39 | 40 | address_space = [cidrsubnet("${var.region1cidr}", 2, 1)] 41 | 42 | Would give us 10.x.8.0/21, or 43 | 44 | address_space = [cidrsubnet("${var.region1cidr}", 2, 2)] 45 | 46 | Would give us ```10.x.16.0/21```, and so on... 47 | 48 | ## Using cidrsubnet - Subnets 49 | 50 | Within Subnets, we just need to break down the network further. For example, the below will change my original variable of ```10.x.0.0/19```, to ```10.x.0.0/24``` and select net number 0, which is ```10.x.0.0/24```: 51 | 52 | address_prefixes = [cidrsubnet("${var.region1cidr}", 5, 0)] 53 | 54 | However, in my example, I am also using Count, to create multiple Subnets. Like this: 55 | 56 | address_prefixes = [cidrsubnet("${var.region1cidr}", 5, "${count.index}")] 57 | 58 | Count index is added above so that the CIDR range is incremented with each Subnet created. The full resource block is like this: 59 | 60 | resource "azurerm_subnet" "region1-hub1-subnets" { 61 | count = 8 62 | name = "snet-${var.region1}-vnet-hub-01-${count.index}" 63 | resource_group_name = azurerm_resource_group.rg1.name 64 | virtual_network_name = azurerm_virtual_network.region1-hub1.name 65 | address_prefixes = [cidrsubnet("${var.region1cidr}", 5, "${count.index}")] 66 | } 67 | 68 | This will start from ```10.x.0.0/24```, then ```10.x.1.0/24``` etc. 69 | 70 | This works well as you can customise the number of subnets to your requirement, based on the CIDR range initially specified (as a single variable), and count keeps thing neat and to a single block. 71 | 72 | Note - for subsequent VNETs, you will need to increment the count index to take into account the next available Subnets to be used. For example: 73 | 74 | resource "azurerm_subnet" "region1-spoke1-subnets" { 75 | count = 8 76 | name = "snet-${var.region1}-vnet-spoke-01-${count.index}" 77 | resource_group_name = azurerm_resource_group.rg1.name 78 | virtual_network_name = azurerm_virtual_network.region1-spoke1.name 79 | address_prefixes = [cidrsubnet("${var.region1cidr}", 5, "${count.index + 8}")] 80 | } 81 | -------------------------------------------------------------------------------- /Azure-NetApp-Files-CRR-BaseLab/README.md: -------------------------------------------------------------------------------- 1 | # Dual Region Base Lab Environment for Azure NetApp Files Cross Region Replication 2 | 3 | ## For a lab overview, please visit my blog: [here](https://jakewalsh.co.uk/uk-windows-virtual-desktop-user-group-azure-netapp-files-cross-region-replication/). If you are familiar with the Dual Region Base Lab - you can skip to the Azure NetApp Files section at the bottom of this page! 4 | 5 | ## Overview 6 | This code creates a simple Lab environment within two Azure Regions. It is a copy of the Dual-Region-Azure-BaseLab](../Dual-Region-Azure-BaseLab), but includes Azure NetApp Files Accounts and Capacity Pools. 7 | 8 | *It is not intended for production use!* 9 | 10 | ## Actions 11 | The following resources are deployed: 12 | 13 | 1. Three Resource Groups, one for the Lab infrastructure in each Region, and another for Security related items. 14 | 2. Four VNETs, a Hub and a Spoke in each region, which are peered. There is also a Global peering between the two Hub VNETS. DNS is set on the VNETs to the Domain Controller IP, Azure DNS, and finally, Google DNS. 15 | 3. Three Subnets in each VNET, with a Subnet delegated to Azure NetApp Files in the Spoke VNET. 16 | 4. Uses the [Automatic-ClientIP-NSG](../Automatic-ClientIP-NSG) to setup a Network Security Group that allows RDP access in - this NSG rule uses the external IP of the machine that runs Terraform. 17 | 5. Associates the created NSG to all Lab Subnets. 18 | 6. Creates a Key Vault with a randomised name, using [Azure-KeyVault-with-Secret](../Azure-KeyVault-with-Secret), and then creates a password as a Secret within the Key Vault that is used later to setup two VMs. 19 | 7. Creates Public IPs for the Domain Controller VMs. 20 | 8. Creates a Network Interface Card and associates the above Public IP. 21 | 9. Creates a Data Disk for NTDS Storage on the Domain Controller VM. 22 | 10. Creates a Windows 2022 VM to act as a Domain Controller. The Username for this VM is a Variable, and the Password is saved as a Secret in the Key Vault. (It was automatically generated in Step 6). 23 | 11. Attaches the Data Disk created in step 9, with caching Turned off. 24 | 12. Sets up Azure NetApp Files Accounts and Capacity Pools in Region 1 and Region 2. 25 | 13. Runs a Setup script on the Domain Controller VM (baselab_DCSetup.ps1 within this repos PowerShell folder), as a Custom Script Extension - that carries out the following actions: 26 | 27 | - Uses Chocolatey to install Google Chrome, Putty, Notepad++, WinSCP, Sysinternals, and bginfo. 28 | - Creates a directory - c:\BaselabSetup. 29 | - Downloads two further PowerShell scripts (found within this repos PowerShell folder) which will be used to setup the Domain Controller, and create a Lab OU Structure after deployment. 30 | - Sets a Windows Firewall Rule to allow File/Printer sharing. 31 | - Installs the Windows Features required for Active Directory and DNS. 32 | 33 | ## Manual Steps to complete Lab Environment 34 | #### The 4 powershell scripts should be run to complete the setup process on the created Virtual Machines. Follow the instructions below to complete the Lab Setup. 35 | 36 | #### First Region 37 | 38 | The setup scripts are in C:\baselabSetup of the region1-dc01-vm after deployment, and should be run in this order: 39 | 40 | 1. baselab_DomainSetup.ps1 - the machine will reboot after this. 41 | 2. baselab_LabStructure.ps1 - this will setup a basic OU structure. 42 | 43 | The AD Domain is now created and you can move onto the Second Region Active Directory setup steps. 44 | 45 | #### Second Region 46 | 47 | After the first DC has been promoted, and has come back online, reboot region2-dc01-vm (After region1-dc01-vm has been setup and DNS is functional a reboot clears any stale DNS records on the 2nd DC). 48 | 49 | The next setup scripts are in C:\baselabSetup of the region2-dc01-vm after deployment, and should be run in this order: 50 | 51 | 1. baselab_DC2JoinDomain.ps1 - joins the VM to the Domain. 52 | 2. baselab_DC2Promote.ps1 - promotes the VM to a Domain Controller. 53 | 54 | The lab is now deployed and ready to use! 55 | 56 | #### Azure NetApp Files 57 | 58 | To start using Azure NetApp files, you will need to create the Active Directory Connections, and then create any shares/replication. This lab just creates all the supporting elements. For setup videos/guides, please see this post on by blog [https://jakewalsh.co.uk/uk-windows-virtual-desktop-user-group-azure-netapp-files-cross-region-replication/](https://jakewalsh.co.uk/uk-windows-virtual-desktop-user-group-azure-netapp-files-cross-region-replication/). 59 | --------------------------------------------------------------------------------