This configuration implements a virtual network with shared services used by all the configurations including:
- A resource group which contains all resources.
- A key vault for managing secrets.
- A log analytics workspace for log data and metrics.
- A storage account for blob storage.
- An automation account for configuration management.
- A virtual network for hosting virtual machines.
- A bastion for secure RDP and SSH access to virtual machines.
- A Windows Server virtual machine running Active Directory Domain Services with a pre-configured domain and DNS server.
Activity | Estimated time required |
---|---|
Pre-configuration | ~10 minutes |
Provisioning | ~20 minutes |
Smoke testing | ~5 minutes |
Before you start, make sure you have completed the following steps:
- All Prerequisites must be completed.
- The Azure subscription owner must create a service principal with a Contributor Azure RBAC role assignment in advance.
- The appId and password of the service principal must be known.
- The sandbox user must also have a Contributor Azure RBAC role assignment on the Azure subscription.
- Complete the steps in Configure client environment.
- Verify you can start a new Bash terminal session
- Verify the Azure CLI is installed by running
az --version
- Verify PowerShell Core is installed by running
pwsh --version
- Verify you have cloned a copy of the GitHub repo with the latest release of the source code.
This section describes how to provision this configuration using default settings.
-
Open a Bash terminal in your client environment and execute the following commands.
# Log out of Azure and clear cached credentials az logout # Clear cached credentials az account clear # Log into Azure az login
-
Change the current directory to the correct configuration
cd ~/azuresandbox/terraform-azurerm-vnet-shared
-
Find and copy the Subscription Id to be used for the configurations.
az account list -o table
-
Set the default Azure subscription using the Subscription Id from the previous step.
az account set -s 00000000-0000-0000-0000-000000000000
-
Add an environment variable containing the password for your service principal.
export TF_VAR_arm_client_secret=YourServicePrincipalSecret
-
Run bootstrap.sh using the default settings or your own custom settings.
./bootstrap.sh
- When prompted for arm_client_id, use the appId for the service principal created by the subscription owner.
- When prompted for resource_group_name use a custom value if there are other sandbox users using the same subscription.
- When prompted for adminuser, the default is bootstrapadmin.
- Important: If you use a custom value, avoid using restricted usernames.
- When prompted for skip_admin_password_gen, accept the default which is
no
.- Important: A strong password will be generated for you and stored in the adminpassword key vault secret.
-
Apply the Terraform configuration.
# Initialize providers terraform init # Check configuration for syntax errors terraform validate # Review plan output terraform plan # Apply plan terraform apply
-
Monitor output. Upon completion, you should see a message similar to the following:
Apply complete! Resources: 29 added, 0 changed, 0 destroyed.
Note: The script
aadsc-register-node-ps1
may report errors, but implements retry logic to ensure that Azure Automation Desired State Configuration node registration succeeds up to a maximum of 180 attempts. -
Inspect
terraform.tfstate
.# Review provisioned resources terraform state list # Review output variables terraform output
- Explore your newly provisioned resources in the Azure portal.
- Key vault
- Navigate to portal.azure.com > Key vaults > kv-xxxxxxxxxxxxxxx > Objects > Secrets > adminpassword > CURRENT VERSION > 00000000-0000-0000-0000-000000000000 > Show Secret Value
- Make a note of the Secret value. This is a strong password associated with the adminuser key vault secret. Together these credentials are used to set up initial administrative access to resources in #AzureSandbox.
- AD DS Domain Controller VM (adds1)
- Navigate to portal.azure.com > Automation Accounts > auto-xxxxxxxxxxxxxxxx-01 > Configuration Management > State configuration (DSC).
- Refresh the data on the Nodes tab and verify that all nodes are compliant.
- Review the data in the Configurations and Compiled configurations tabs as well.
- Bastion host
- Navigate to portal.azure.com > Bastions > bst-xxxxxxxxxxxxxxxx-1.
- Review the information in the Overview section.
- Key vault
This section provides additional information on various aspects of this configuration.
The bootstrap script bootstrap.sh is used to initialize variables and to ensure that all dependencies are in place for the Terraform configuration to be applied. In most real world projects, Terraform configurations will need to reference resources that are not being managed by Terraform because they already exist. It is also sometimes necessary to provision resources in advance to avoid circular dependencies in your Terraform configurations. For this reason, this configuration provisions several resources in advance using bootstrap.sh.
bootstrap.sh performs the following operations:
- Generates SSH keys for Linux Jumpbox VM
- Generates a Mime Multi Part Archive containing the following files:
- configure-vm-jumpbox-linux.yaml is Cloud Config Data used to configure the Linux Jumpbox VM.
- configure-vm-jumpbox-linux.sh is a User-Data Script used to configure the Linux Jumpbox VM.
- Creates a new resource group with the default name rg-sandbox-01 used by all the configurations.
- Creates a storage account with a randomly generated 15-character name like stxxxxxxxxxxxxx.
- Creates a key vault with a randomly generated name like kv-xxxxxxxxxxxxxxx.
- The permission model is set to Vault access policy. Azure role-based access control is not used to ensure that sandbox users only require a Contributor Azure RBAC role assignment in order to complete the configurations.
- Secrets are created that are used by all configurations. Note these secrets are static and will need to be manually updated if the values change.
- Log analytics workspace primary shared key: The name of this secret is the same as the id of the log analytics workspace, e.g. 00000000-0000-0000-0000-000000000000, and the value is the primary shared key which can be used to connect agents to the log analytics workspace.
- Storage account access key1: The name of this secret is the same as the storage account, e.g. stxxxxxxxxxxxxxxx, and the value is access key 1.
- Storage account kerberos key1: The name of this secret is the same as the storage account, e.g. stxxxxxxxxxxxxxxx-kerb1, and the value is kerberos key 1.
- adminpassword: The password used for default administrator credentials when new resources are provisioned.
- adminuser: The user name used for default administrator credentials when new resources are configured. The default value is bootstrapadmin.
- bootstrapadmin-ssh-key-private: The private SSH key used to secure SSH access to Linux VMs created in the configurations. The value of the adminpassword secret is used as the pass phrase.
- bootstrapadmin-ssh-key-public: The public SSH key used to secure SSH access to Linux VMs created in the configurations.
- Access policies are created to enable the administration and retrieval of secrets.
- AzureSandboxSPN is granted Get and Set secrets permissions.
- The sandbox user is granted Get, List and Set secrets permissions.
- Creates a terraform.tfvars file for generating and applying Terraform plans.
The script is idempotent and can be run multiple times even after the Terraform configuration has been applied.
This section lists the resources included in the Terraform configurations in this configuration.
The configuration for these resources can be found in 020-loganalytics.tf.
Resource name (ARM) | Notes |
---|---|
azurerm_log_analytics_workspace.log_analytics_workspace_01 (log‑xxxxxxxxxxxxxxxx‑01) | See below. |
random_id.log_analytics_workspace_01_name | Used to generate a random unique name for azurerm_log_analytics_workspace.log_analytics_workspace_01. |
azurerm_key_vault_secret.log_analytics_workspace_01_primary_shared_key | Secret used to access azurerm_log_analytics_workspace.log_analytics_workspace_01. |
The log analytics workspace is for use with services like Azure Monitor and Azure Security Center.
The configuration for these resources can be found in 030-automation.tf.
Resource name (ARM) | Notes |
---|---|
azurerm_automation_account.automation_account_01 (auto‑a9866e235174ab6a‑01) | See below. |
random_id.automation_account_01_name | Used to generate a random unique name for azurerm_automation_account.automation_account_01 |
This configuration makes extensive use of Azure Automation State Configuration (DSC) to configure virtual machines using Terraform Provisioners.
- configure-automation.ps1: This script is run by a provisioner in the azurerm_automation_account.automation_account_01 resource and does the following:
- Configures Azure Automation shared resources including:
- Modules
- Existing modules are updated to the most recent release where possible.
- Imports new modules including the following:
- Bootstraps Variables
- Bootstraps Credentials
- Modules
- Configures Azure Automation State Configuration (DSC) which is used to configure Windows Server virtual machines used in the configurations.
- Imports DSC Configurations used in this configuration.
- LabDomainConfig.ps1: configure a Windows Server virtual machine as an Active Directory Domain Services Domain Controller.
- Compiles DSC Configurations so they can be used later to Register a VM to be managed by State Configuration.
- Imports DSC Configurations used in this configuration.
- Configures Azure Automation shared resources including:
The configuration for these resources can be found in 040-network.tf.
Resource name (ARM) | Notes |
---|---|
azurerm_virtual_network.vnet_shared_01 (vnet‑shared‑01) | By default this virtual network is configured with an address space of 10.1.0.0/16 and is configured with DNS server addresses of 10.1.1.4 (the private ip for azurerm_windows_virtual_machine.vm_adds) and 168.63.129.16. |
azurerm_subnet.vnet_shared_01_subnets["AzureBastionSubnet"] | The default address prefix for this subnet is 10.1.0.0/27 which includes the private ip addresses for azurerm_bastion_host.bastion_host_01. A network security group is associated with this subnet and is configured according to Working with NSG access and Azure Bastion. |
azurerm_subnet.vnet_shared_01_subnets["snet-adds-01"] | The default address prefix for this subnet is 10.1.1.0/24 which includes the private ip address for azurerm_windows_virtual_machine.vm_adds. A network security group is associated with this subnet that permits ingress and egress from virtual networks, and egress to the Internet. |
azurerm_bastion_host.bastion_host_01 (bst‑xxxxxxxxxxxxxxxx‑1) | Used for secure RDP and SSH access to VMs. |
random_id.bastion_host_01_name | Used to generate a random name for azurerm_bastion_host.bastion_host_01. |
azurerm_public_ip.bastion_host_01 (pip‑xxxxxxxxxxxxxxxx‑1) | Public ip used by azurerm_bastion_host.bastion_host_01. |
random_id.public_ip_bastion_host_01_name | Used to generate a random name for azurerm_public_ip.bastion_host_01. |
The configuration for these resources can be found in 050-vm-adds.tf.
Resource name (ARM) | Notes |
---|---|
azurerm_windows_virtual_machine.vm_adds (adds1) | By default, provisions a Standard_B2s virtual machine for use as a domain controller and dns server. See below for more information. |
azurerm_network_interface.vm_adds_nic_01 (nic‑adds1‑1) | The configured subnet is azurerm_subnet.vnet_shared_01_subnets["snet-adds-01"]. |
This Windows Server VM is used as an Active Directory Domain Services Domain Controller and a DNS Server running in Active Directory-integrated mode.
- Guest OS: Windows Server 2022 Datacenter Core
- By default the Patch orchestration mode is set to
AutomaticByPlatform
. - admin_username and admin_password are configured using the key vault secrets adminuser and adminpassword.
- This resource has a dependency on azurerm_automation_account.automation_account_01.
- This resource is configured using a provisioner that runs aadsc-register-node.ps1 which registers the node with azurerm_automation_account.automation_account_01 and applies the configuration LabDomainConfig which includes the following:
- The
AD-Domain-Services
feature (which includes DNS) is installed. - A new mysandbox.local domain is configured
- The domain admin credentials are configured using the adminusername and adminpassword key vault secrets.
- The forest functional level is set to
WinThreshhold
- A DNS Server is automatically configured
- Server configuration
- Forwarder: 168.63.129.16.
- Note: This ensures that any DNS queries that can't be resolved by the DNS server are forwarded to the Azure recursive resolver as per Name resolution for resources in Azure virtual networks.
- Forwarder: 168.63.129.16.
- mysandbox.local DNS forward lookup zone configuration
- Zone type: Primary / Active Directory-Integrated
- Dynamic updates: Secure only
- Server configuration
- The
This section lists the output variables defined in the Terraform configurations in this sample. Some of these may be used for automation in other configurations.
Output variable | Sample value |
---|---|
aad_tenant_id | "00000000-0000-0000-0000-000000000000" |
adds_domain_name | "mysandbox.local" |
admin_password_secret | "adminpassword" |
admin_username_secret | "adminuser" |
arm_client_id | "00000000-0000-0000-0000-000000000000" |
automation_account_name | "auto-9a633c2bba9351cc-01" |
dns_server | "10.1.2.4" |
key_vault_id | "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-sandbox-01/providers/Microsoft.KeyVault/vaults/kv-XXXXXXXXXXXXXXX" |
key_vault_name | "kv-XXXXXXXXXXXXXXX" |
location | "eastus2" |
log_analytics_workspace_01_name | "log-XXXXXXXXXXXXXXXX-01" |
log_analytics_workspace_01_workspace_id | "00000000-0000-0000-0000-000000000000" |
resource_group_name | "rg-sandbox-01" |
storage_account_name | "stXXXXXXXXXXXXXXX" |
storage_container_name | "scripts" |
subscription_id | "00000000-0000-0000-0000-000000000000" |
tags | tomap( { "costcenter" = "10177772" "environment" = "dev" "project" = "#AzureSandbox" } ) |
vnet_shared_01_id | "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-sandbox-01/providers/Microsoft.Network/virtualNetworks/vnet-shared-01"" |
vnet_shared_01_name | "vnet-shared-01" |
- Move on to the next configuration terraform-azurerm-vnet-app.