Azure development

This commit is contained in:
Chris Long
2020-06-14 18:45:18 -07:00
parent a033ea2b60
commit 5791b99c8f
35 changed files with 1236 additions and 17 deletions

View File

@@ -0,0 +1,17 @@
<FirstLogonCommands>
<SynchronousCommand>
<CommandLine>cmd /c "mkdir C:\terraform"</CommandLine>
<Description>Create the Terraform working directory</Description>
<Order>11</Order>
</SynchronousCommand>
<SynchronousCommand>
<CommandLine>cmd /c "copy C:\AzureData\CustomData.bin C:\terraform\winrm.ps1"</CommandLine>
<Description>Move the CustomData file to the working directory</Description>
<Order>12</Order>
</SynchronousCommand>
<SynchronousCommand>
<CommandLine>powershell.exe -sta -ExecutionPolicy Unrestricted -file C:\terraform\winrm.ps1</CommandLine>
<Description>Move the CustomData file to the working directory</Description>
<Order>13</Order>
</SynchronousCommand>
</FirstLogonCommands>

View File

@@ -0,0 +1,16 @@
powershell.exe -c "Set-NetConnectionProfile -InterfaceAlias Ethernet -NetworkCategory Private"
Enable-PSRemoting -Force
winrm quickconfig -q
winrm quickconfig -transport:http
powershell.exe -c "winrm set winrm/config '@{MaxTimeoutms=\`"1800000\`"}'"
powershell.exe -c "winrm set winrm/config/winrs '@{MaxMemoryPerShellMB=\`"800\`"}'"
powershell.exe -c "winrm set winrm/config/service '@{AllowUnencrypted=\`"true\`"}'"
powershell.exe -c "winrm set winrm/config/service/auth '@{Basic=\`"true\`"}'"
powershell.exe -c "winrm set winrm/config/client/auth '@{Basic=\`"true\`"}'"
powershell.exe -c "winrm set winrm/config/listener?Address=*+Transport=HTTP '@{Port=\`"5985\`"}'"
netsh advfirewall firewall set rule group="Windows Remote Administration" new enable=yes
netsh advfirewall firewall set rule name="Windows Remote Management (HTTP-In)" new enable=yes action=allow remoteip=any
reg add HKCU\Software\Microsoft\Windows\CurrentVersion\RunOnce /v StartWinRM /t REG_SZ /f /d "cmd.exe /c 'sc config winrm start= auto & sc start winrm'"
Restart-Service winrm
netsh advfirewall firewall add rule name="Port 5985" dir=in action=allow protocol=TCP localport=5985

View File

@@ -0,0 +1,6 @@
locals {
fleet_url = "https://${azurerm_public_ip.logger-publicip.ip_address}:8412"
splunk_url = "https://${azurerm_public_ip.logger-publicip.ip_address}:8000"
ata_url = "https://${azurerm_public_ip.wef-publicip.ip_address}"
guacamole_url = "https://${azurerm_public_ip.wef-publicip.ip_address}:8080/guacamole"
}

522
Azure/Terraform/main.tf Normal file
View File

@@ -0,0 +1,522 @@
# terraform init, plan, apply, destroy
# Note: does not support idempotence, don't execute twice with same scope.
# https://www.terraform.io/docs/providers/azurerm/index.html
# latest test: terraform 0.12.18
#
# FIXME!
# * apply: provisioning not working on Windows
# Error: Unsupported argument [...] An argument named "connection" is not expected here.
# apply => Error: timeout - last error: SSH authentication failed (root@:22): ssh: handshake failed: ssh: unable to authenticate, attempted methods [none publickey], no supported methods remain
# * apply: linux provisioning
# => works but script ends with error code for some reason (post bro install and splunk restart)
# Specify the provider and access details
provider "azurerm" {
version = "=2.12.0"
features {}
}
# https://github.com/terraform-providers/terraform-provider-azurerm/blob/1940d84dba45e41b2f1f868a22d7f7af1adea8a0/examples/virtual-machines/virtual_machine/vm-joined-to-active-directory/modules/active-directory/2-virtual-machine.tf
locals {
custom_data_content = file("${path.module}/files/winrm.ps1")
}
resource "azurerm_resource_group" "detectionlab" {
name = "DetectionLab-terraform"
location = "West US 2"
}
resource "azurerm_virtual_network" "detectionlab-network" {
name = "DetectionLab-vnet"
address_space = ["192.168.0.0/16"]
location = "West US 2"
resource_group_name = azurerm_resource_group.detectionlab.name
}
# Create a subnet to launch our instances into
resource "azurerm_subnet" "detectionlab-subnet" {
name = "DetectionLab-Subnet"
resource_group_name = azurerm_resource_group.detectionlab.name
virtual_network_name = azurerm_virtual_network.detectionlab-network.name
address_prefixes = ["192.168.38.0/24"]
}
resource "azurerm_network_security_group" "detectionlab-nsg" {
name = "DetectionLab-nsg"
location = "West US 2"
resource_group_name = azurerm_resource_group.detectionlab.name
# SSH access
security_rule {
name = "SSH"
priority = 1001
direction = "Inbound"
access = "Allow"
protocol = "Tcp"
source_port_range = "*"
destination_port_range = "22"
# source_address_prefix = "*"
source_address_prefixes = var.ip_whitelist
destination_address_prefix = "*"
}
# Splunk access
security_rule {
name = "Splunk"
priority = 1002
direction = "Inbound"
access = "Allow"
protocol = "Tcp"
source_port_range = "*"
destination_port_range = "8000"
source_address_prefixes = var.ip_whitelist
destination_address_prefix = "*"
}
# Fleet access
security_rule {
name = "Fleet"
priority = 1003
direction = "Inbound"
access = "Allow"
protocol = "Tcp"
source_port_range = "*"
destination_port_range = "8412"
source_address_prefixes = var.ip_whitelist
destination_address_prefix = "*"
}
# RDP
security_rule {
name = "RDP"
priority = 1004
direction = "Inbound"
access = "Allow"
protocol = "Tcp"
source_port_range = "*"
destination_port_range = "3389"
source_address_prefixes = var.ip_whitelist
destination_address_prefix = "*"
}
# WinRM
security_rule {
name = "WinRM"
priority = 1005
direction = "Inbound"
access = "Allow"
protocol = "Tcp"
source_port_range = "*"
destination_port_range = "5985-5986"
source_address_prefixes = var.ip_whitelist
destination_address_prefix = "*"
}
# Windows ATA
security_rule {
name = "WindowsATA"
priority = 1006
direction = "Inbound"
access = "Allow"
protocol = "Tcp"
source_port_range = "*"
destination_port_range = "443"
source_address_prefixes = var.ip_whitelist
destination_address_prefix = "*"
}
# Allow all traffic from the private subnet
security_rule {
name = "PrivateSubnet"
priority = 1007
direction = "Inbound"
access = "Allow"
protocol = "Tcp"
source_port_range = "*"
destination_port_range = "*"
source_address_prefix = "192.168.38.0/24"
destination_address_prefix = "*"
}
# Guacamole access
security_rule {
name = "Guacamole"
priority = 1008
direction = "Inbound"
access = "Allow"
protocol = "Tcp"
source_port_range = "*"
destination_port_range = "8080"
source_address_prefixes = var.ip_whitelist
destination_address_prefix = "*"
}
}
resource "azurerm_subnet_network_security_group_association" "detectionlab-nsga" {
subnet_id = azurerm_subnet.detectionlab-subnet.id
network_security_group_id = azurerm_network_security_group.detectionlab-nsg.id
}
resource "azurerm_public_ip" "logger-publicip" {
name = "logger-public-ip"
location = "West US 2"
resource_group_name = azurerm_resource_group.detectionlab.name
allocation_method = "Static"
tags = {
role = "logger"
}
}
resource "azurerm_network_interface" "logger-nic" {
name = "logger-nic"
location = "West US 2"
resource_group_name = azurerm_resource_group.detectionlab.name
ip_configuration {
name = "logger-NicConfiguration"
subnet_id = azurerm_subnet.detectionlab-subnet.id
private_ip_address_allocation = "Static"
private_ip_address = "192.168.38.105"
public_ip_address_id = azurerm_public_ip.logger-publicip.id
}
}
# Storage
resource "random_id" "randomId" {
keepers = {
# Generate a new ID only when a new resource group is defined
resource_group_name = azurerm_resource_group.detectionlab.name
}
byte_length = 8
}
resource "azurerm_storage_account" "detectionlab-storageaccount" {
name = "diag${random_id.randomId.hex}"
location = "West US 2"
resource_group_name = azurerm_resource_group.detectionlab.name
account_replication_type = "LRS"
account_tier = "Standard"
}
# Linux VM
resource "azurerm_virtual_machine" "logger" {
name = "logger"
location = "West US 2"
resource_group_name = azurerm_resource_group.detectionlab.name
network_interface_ids = [azurerm_network_interface.logger-nic.id]
vm_size = "Standard_D1_v2"
delete_os_disk_on_termination = true
storage_os_disk {
name = "OsDiskLogger"
caching = "ReadWrite"
create_option = "FromImage"
managed_disk_type = "Standard_LRS"
}
storage_image_reference {
publisher = "Canonical"
offer = "UbuntuServer"
sku = "18.04-LTS"
version = "latest"
}
os_profile {
computer_name = "logger"
admin_username = "vagrant"
admin_password = "vagrant"
}
os_profile_linux_config {
disable_password_authentication = true
ssh_keys {
path = "/home/vagrant/.ssh/authorized_keys"
key_data = file(var.public_key_path)
}
}
boot_diagnostics {
enabled = "true"
storage_uri = azurerm_storage_account.detectionlab-storageaccount.primary_blob_endpoint
}
# Provision
# https://github.com/terraform-providers/terraform-provider-azurerm/blob/master/examples/virtual-machines/provisioners/linux/main.tf
# https://www.terraform.io/docs/provisioners/connection.html
provisioner "remote-exec" {
connection {
host = azurerm_public_ip.logger-publicip.ip_address
user = "vagrant"
private_key = file(var.private_key_path)
}
inline = [
"sudo add-apt-repository universe && sudo apt-get -qq update && sudo apt-get -qq install -y git",
"echo 'logger' | sudo tee /etc/hostname && sudo hostnamectl set-hostname logger",
"sudo adduser --disabled-password --gecos \"\" vagrant && echo 'vagrant:vagrant' | sudo chpasswd",
"sudo mkdir /home/vagrant/.ssh && sudo cp /home/ubuntu/.ssh/authorized_keys /home/vagrant/.ssh/authorized_keys && sudo chown -R vagrant:vagrant /home/vagrant/.ssh",
"echo 'vagrant ALL=(ALL:ALL) NOPASSWD:ALL' | sudo tee -a /etc/sudoers",
"sudo git clone https://github.com/clong/DetectionLab.git /opt/DetectionLab",
"sudo sed -i 's/eth1/eth0/g' /opt/DetectionLab/Vagrant/bootstrap.sh",
"sudo sed -i 's/ETH1/ETH0/g' /opt/DetectionLab/Vagrant/bootstrap.sh",
"sudo sed -i 's#/usr/local/go/bin/go get -u#GOPATH=/root/go /usr/local/go/bin/go get -u#g' /opt/DetectionLab/Vagrant/bootstrap.sh",
"sudo sed -i 's#/vagrant/resources#/opt/DetectionLab/Vagrant/resources#g' /opt/DetectionLab/Vagrant/bootstrap.sh",
"sudo chmod +x /opt/DetectionLab/Vagrant/bootstrap.sh",
"sudo apt-get -qq update",
"sudo /opt/DetectionLab/Vagrant/bootstrap.sh 2>&1 |sudo tee /opt/DetectionLab/Vagrant/bootstrap.log",
]
}
tags = {
role = "logger"
}
}
# https://github.com/terraform-providers/terraform-provider-azurerm/tree/master/examples/virtual-machines/vm-joined-to-active-directory
# Windows VM
resource "azurerm_network_interface" "dc-nic" {
name = "dc-nic"
location = "West US 2"
resource_group_name = azurerm_resource_group.detectionlab.name
ip_configuration {
name = "DC-NicConfiguration"
subnet_id = azurerm_subnet.detectionlab-subnet.id
private_ip_address_allocation = "Static"
private_ip_address = "192.168.38.102"
public_ip_address_id = azurerm_public_ip.dc-publicip.id
}
}
resource "azurerm_public_ip" "dc-publicip" {
name = "dc-public-ip"
location = "West US 2"
resource_group_name = azurerm_resource_group.detectionlab.name
allocation_method = "Static"
tags = {
role = "dc"
}
}
resource "azurerm_network_interface" "wef-nic" {
name = "wef-nic"
location = "West US 2"
resource_group_name = azurerm_resource_group.detectionlab.name
ip_configuration {
name = "WEF-NicConfiguration"
subnet_id = azurerm_subnet.detectionlab-subnet.id
private_ip_address_allocation = "Static"
private_ip_address = "192.168.38.103"
public_ip_address_id = azurerm_public_ip.wef-publicip.id
}
}
resource "azurerm_public_ip" "wef-publicip" {
name = "wef-public-ip"
location = "West US 2"
resource_group_name = azurerm_resource_group.detectionlab.name
allocation_method = "Static"
tags = {
role = "wef"
}
}
resource "azurerm_network_interface" "win10-nic" {
name = "win10-nic"
location = "West US 2"
resource_group_name = azurerm_resource_group.detectionlab.name
ip_configuration {
name = "myNicConfiguration"
subnet_id = azurerm_subnet.detectionlab-subnet.id
private_ip_address_allocation = "Static"
private_ip_address = "192.168.38.104"
public_ip_address_id = azurerm_public_ip.win10-publicip.id
}
}
resource "azurerm_public_ip" "win10-publicip" {
name = "win10-public-ip"
location = "West US 2"
resource_group_name = azurerm_resource_group.detectionlab.name
allocation_method = "Static"
tags = {
role = "win10"
}
}
resource "azurerm_virtual_machine" "dc" {
name = "dc.windomain.local"
location = "West US 2"
resource_group_name = azurerm_resource_group.detectionlab.name
network_interface_ids = [azurerm_network_interface.dc-nic.id]
vm_size = "Standard_D1_v2"
delete_os_disk_on_termination = true
storage_image_reference {
publisher = "MicrosoftWindowsServer"
offer = "WindowsServer"
sku = "2016-Datacenter"
version = "latest"
}
os_profile {
computer_name = "dc"
admin_username = "vagrant"
admin_password = "Vagrant123"
custom_data = local.custom_data_content
}
os_profile_windows_config {
provision_vm_agent = true
enable_automatic_upgrades = false
# Auto-Login's required to configure WinRM
additional_unattend_config {
pass = "oobeSystem"
component = "Microsoft-Windows-Shell-Setup"
setting_name = "AutoLogon"
content = "<AutoLogon><Password><Value>Vagrant123</Value></Password><Enabled>true</Enabled><LogonCount>1</LogonCount><Username>vagrant</Username></AutoLogon>"
}
# Unattend config is to enable basic auth in WinRM, required for the provisioner stage.
# https://github.com/terraform-providers/terraform-provider-azurerm/blob/master/examples/virtual-machines/provisioners/windows/files/FirstLogonCommands.xml
additional_unattend_config {
pass = "oobeSystem"
component = "Microsoft-Windows-Shell-Setup"
setting_name = "FirstLogonCommands"
content = file("./files/FirstLogonCommands.xml")
}
}
storage_os_disk {
name = "OsDiskDc"
caching = "ReadWrite"
create_option = "FromImage"
managed_disk_type = "Standard_LRS"
}
tags = {
role = "dc"
}
}
resource "azurerm_virtual_machine" "wef" {
name = "wef.windomain.local"
location = "West US 2"
resource_group_name = azurerm_resource_group.detectionlab.name
network_interface_ids = [azurerm_network_interface.wef-nic.id]
vm_size = "Standard_D1_v2"
delete_os_disk_on_termination = true
storage_image_reference {
publisher = "MicrosoftWindowsServer"
offer = "WindowsServer"
sku = "2016-Datacenter"
version = "latest"
}
os_profile {
computer_name = "wef"
admin_username = "vagrant"
admin_password = "Vagrant123"
custom_data = local.custom_data_content
}
os_profile_windows_config {
provision_vm_agent = true
enable_automatic_upgrades = false
# Auto-Login's required to configure WinRM
additional_unattend_config {
pass = "oobeSystem"
component = "Microsoft-Windows-Shell-Setup"
setting_name = "AutoLogon"
content = "<AutoLogon><Password><Value>Vagrant123</Value></Password><Enabled>true</Enabled><LogonCount>1</LogonCount><Username>vagrant</Username></AutoLogon>"
}
# Unattend config is to enable basic auth in WinRM, required for the provisioner stage.
# https://github.com/terraform-providers/terraform-provider-azurerm/blob/master/examples/virtual-machines/provisioners/windows/files/FirstLogonCommands.xml
additional_unattend_config {
pass = "oobeSystem"
component = "Microsoft-Windows-Shell-Setup"
setting_name = "FirstLogonCommands"
content = file("./files/FirstLogonCommands.xml")
}
}
storage_os_disk {
name = "OsDiskWef"
caching = "ReadWrite"
create_option = "FromImage"
managed_disk_type = "Standard_LRS"
}
tags = {
role = "wef"
}
}
resource "azurerm_virtual_machine" "win10" {
name = "win10.windomain.local"
location = "West US 2"
resource_group_name = azurerm_resource_group.detectionlab.name
network_interface_ids = [azurerm_network_interface.win10-nic.id]
vm_size = "Standard_D1_v2"
delete_os_disk_on_termination = true
storage_image_reference {
publisher = "MicrosoftWindowsDesktop"
offer = "Windows-10"
sku = "19h1-pron"
version = "latest"
}
os_profile {
computer_name = "win10"
admin_username = "vagrant"
admin_password = "Vagrant123"
custom_data = local.custom_data_content
}
os_profile_windows_config {
provision_vm_agent = true
enable_automatic_upgrades = false
# Auto-Login's required to configure WinRM
additional_unattend_config {
pass = "oobeSystem"
component = "Microsoft-Windows-Shell-Setup"
setting_name = "AutoLogon"
content = "<AutoLogon><Password><Value>Vagrant123</Value></Password><Enabled>true</Enabled><LogonCount>1</LogonCount><Username>vagrant</Username></AutoLogon>"
}
# Unattend config is to enable basic auth in WinRM, required for the provisioner stage.
# https://github.com/terraform-providers/terraform-provider-azurerm/blob/master/examples/virtual-machines/provisioners/windows/files/FirstLogonCommands.xml
additional_unattend_config {
pass = "oobeSystem"
component = "Microsoft-Windows-Shell-Setup"
setting_name = "FirstLogonCommands"
content = file("./files/FirstLogonCommands.xml")
}
}
storage_os_disk {
name = "OsDiskWin10"
caching = "ReadWrite"
create_option = "FromImage"
managed_disk_type = "Standard_LRS"
}
tags = {
role = "win10"
}
}

View File

@@ -0,0 +1,35 @@
output "region" {
value = var.region
}
output "logger_public_ip" {
value = azurerm_public_ip.logger-publicip.ip_address
}
output "dc_public_ip" {
value = azurerm_public_ip.dc-publicip.ip_address
}
output "wef_public_ip" {
value = azurerm_public_ip.wef-publicip.ip_address
}
output "win10_public_ip" {
value = azurerm_public_ip.win10-publicip.ip_address
}
output "ata_url" {
value = local.ata_url
}
output "fleet_url" {
value = local.fleet_url
}
output "splunk_url" {
value = local.splunk_url
}
output "guacamole_url" {
value = local.guacamole_url
}

View File

@@ -0,0 +1,10 @@
# https://azure.microsoft.com/en-us/global-infrastructure/locations/
region = "US WEST 2"
public_key_name = "id_logger" # This can be changed to whatever you want
# These values must point to a valid keypair.
# You'll log into the logger host via: ssh -i /home/user/.ssh/id_logger vagrant@<public_logger_ip>
public_key_path = "/home/user/.ssh/id_logger.pub"
private_key_path = "/home/user/.ssh/id_logger"
# Replace the IP address below with the IP address(es) you'll be using
# to connect to DetectionLab
ip_whitelist = ["1.2.3.4/32"]

View File

@@ -0,0 +1,42 @@
variable "region" {
default = "West US 2"
}
variable "profile" {
default = "terraform"
}
variable "availability_zone" {
description = "https://docs.microsoft.com/en-us/azure/availability-zones/az-overview"
default = ""
}
variable "public_key_name" {
description = "A name for SSH Keypair to use to auth to logger. Can be anything you specify."
default = "id_logger"
}
variable "public_key_path" {
description = "Path to the public key to be loaded into the logger authorized_keys file"
type = string
default = "/home/user/.ssh/id_logger.pub"
}
# Note: must use ssh key without passphrase. not supported by Terraform.
variable "private_key_path" {
description = "Path to the private key to use to authenticate to logger."
type = string
default = "/home/user/.ssh/id_logger"
}
variable "ip_whitelist" {
description = "A list of CIDRs that will be allowed to access the instances"
type = list(string)
default = [""]
}
variable "external_dns_servers" {
description = "Configure lab to allow external DNS resolution"
type = list(string)
default = ["8.8.8.8"]
}