diff --git a/.github/workflows/azure-deploy.yml b/.github/workflows/azure-deploy.yml new file mode 100644 index 0000000..dc5310a --- /dev/null +++ b/.github/workflows/azure-deploy.yml @@ -0,0 +1,60 @@ +name: Deploy to Azure + +on: + push: + branches: + - master + +jobs: + deploy: + runs-on: windows-latest + + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Set up Terraform + uses: hashicorp/setup-terraform@v1 + with: + terraform_version: 0.15.5 + + - name: Install Azure CLI + run: | + Invoke-WebRequest -Uri https://aka.ms/installazurecliwindows -OutFile .\AzureCLI.msi + Start-Process msiexec.exe -Wait -ArgumentList '/I AzureCLI.msi /quiet' + + - name: Check Azure CLI version + run: az --version + + - name: Log in to Azure + run: | + az login --service-principal -u $env:AZURE_CLIENT_ID -p $env:AZURE_CLIENT_SECRET --tenant $env:AZURE_TENANT_ID + env: + AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }} + AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }} + AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }} + + - name: Show Azure Account + run: az account show + + - name: Terraform Init + run: terraform init + + - name: Terraform Plan + run: terraform plan -out=tfplan + + - name: Terraform Apply + run: terraform apply -auto-approve tfplan + + - name: Clean up Terraform files + run: | + # Remove .terraform directory if it exists + if (Test-Path .\.terraform) { + Remove-Item -Recurse -Force .\.terraform + } + + # Remove tfplan file if it exists + if (Test-Path .\tfplan) { + Remove-Item -Force .\tfplan + } + continue-on-error: true # Continue with the workflow even if cleanup fails diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..85e9353 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +*.terraform* +*.terraform.lock.hcl* +terraform.tfstate +terraform.tfstate.backup +*.DS_Store* \ No newline at end of file diff --git a/ansible.cfg b/ansible.cfg new file mode 100644 index 0000000..5a2c39a --- /dev/null +++ b/ansible.cfg @@ -0,0 +1,12 @@ +[azurevms] +# IPs from Azure + + + +[azurevms:vars] +ansible_user=admin +ansible_password=Password1911 +ansible_connection=winrm +ansible_winrm_transport=basic +ansible_winrm_server_cert_validation=ignore +ansible_port=5986 \ No newline at end of file diff --git a/ansibleConfigs/host b/ansibleConfigs/host new file mode 100644 index 0000000..e69de29 diff --git a/ansibleConfigs/iis.yml b/ansibleConfigs/iis.yml new file mode 100644 index 0000000..6ffff60 --- /dev/null +++ b/ansibleConfigs/iis.yml @@ -0,0 +1,42 @@ +--- +- hosts: azurevms + gather_facts: no + tasks: + - name: Install IIS features + win_feature: + name: + - web-Server + - web-common-Http + include_management_tools: yes + state: present + + - name: Enable IIS remote management + win_regedit: + path: HKLM:\SOFTWARE\Microsoft\Microsoft\WebManagement\Server + name: EnableRemoteManagement + data: 1 + type: dword + - name: Install WebDeploy + win_package: + path: https://download.microsoft.com/download/0/1/D/b462d350-1ac8-4373-a8c5-deadc8357530/WebDeploy_amd64_en-US.msi + product_id: '' + arguements: ADDLOCAL=ALL + state: present + - name: Start and set management service to auto + win_service: + name: WMSvc + start_mode: auto + state: started + - name: install net core iis hosting module with no frameworks + win_chocolatey: + name: "dotnetcore-windowshosting" + version: latest + install_args: "OPT_NO_SHARED_CONFIG_CHECK=1" + notify: restart IIS + - name: Create logging directory + win_file: + path: c:\logs + state: directory + handlers: + - name: restart IIS + win_shell: '& {iisreset}' diff --git a/lb.tf b/lb.tf new file mode 100644 index 0000000..43d721f --- /dev/null +++ b/lb.tf @@ -0,0 +1,63 @@ +resource "azurerm_public_ip" "lbip" { + name = "publicLbIp" + location = azurerm_resource_group.cliff.location + resource_group_name = azurerm_resource_group.cliff.name + allocation_method = "Static" +} + +resource "azurerm_public_ip" "vmIps" { + count = 2 + name = "publicVmIp-${count.index}" + location = azurerm_resource_group.cliff.location + resource_group_name = azurerm_resource_group.cliff.name + allocation_method = "Dynamic" + domain_name_label = "${var.domain_name_prefix}-${count.index}" +} + + +resource "azurerm_lb" "lb" { + name = "nobsloadbalancer" + location = azurerm_resource_group.cliff.location + resource_group_name = azurerm_resource_group.cliff.name + + frontend_ip_configuration { + name = "lb_frontend" + public_ip_address_id = azurerm_public_ip.lbip.id + } +} + +resource "azurerm_lb_backend_address_pool" "b_pool" { + loadbalancer_id = azurerm_lb.lb.id + name = "BackEndAddressPool1" +} + + +resource "azurerm_network_interface_backend_address_pool_association" "nic0" { + count = 2 + network_interface_id = azurerm_network_interface.mars[count.index].id + ip_configuration_name = "ip_config" + backend_address_pool_id = azurerm_lb_backend_address_pool.b_pool.id +} + +resource "azurerm_lb_probe" "lbprone" { + loadbalancer_id = azurerm_lb.lb.id + name = "http-running-probe" + port = 80 + resource_group_name = azurerm_resource_group.cliff.name +} + +resource "azurerm_lb_rule" "lbrule" { + name = "LBRule" + loadbalancer_id = azurerm_lb.lb.id + protocol = "Tcp" + frontend_port = 80 + backend_port = 80 + frontend_ip_configuration_name = "lb_frontend" + backend_address_pool_ids = [azurerm_lb_backend_address_pool.b_pool.id] + probe_id = azurerm_lb_probe.lbprone.id + resource_group_name = azurerm_resource_group.cliff.name +} + + + + diff --git a/nsg.tf b/nsg.tf new file mode 100644 index 0000000..31aa108 --- /dev/null +++ b/nsg.tf @@ -0,0 +1,48 @@ +resource "azurerm_network_security_group" "cliff-nsg" { + name = "nsg" + location = azurerm_resource_group.cliff.location + resource_group_name = azurerm_resource_group.cliff.name + + security_rule { + name = "allowWinRm" + priority = 101 + direction = "Inbound" + access = "Allow" + protocol = "Tcp" + source_port_range = "*" + destination_port_ranges = ["5986"] # Winrm over HTTPS + source_address_prefix = var.cloud_shell_source + destination_address_prefix = "*" # Allow traffic to any destination + } + + security_rule { + name = "allowWinRm2" + priority = 102 + direction = "Inbound" + access = "Allow" + protocol = "Tcp" + source_port_range = "*" + destination_port_ranges = ["5986"] # Winrm over HTTPS + source_address_prefix = var.cloud_shell_source + destination_address_prefix = "*" # Allow traffic to any destination + } + + security_rule { + name = "allowWinRm3" + priority = 103 + direction = "Inbound" + access = "Allow" + protocol = "Tcp" + source_port_range = "*" + destination_port_ranges = ["5986"] # Winrm over HTTPS + source_address_prefix = var.cloud_shell_source + destination_address_prefix = "*" # Allow traffic to any destination + } +} + + +resource "azurerm_network_interface_security_group_association" "nsg" { + count = 2 + network_interface_id = azurerm_network_interface.mars[count.index].id + network_security_group_id = azurerm_network_security_group.cliff-nsg.id +} diff --git a/output.tf b/output.tf new file mode 100644 index 0000000..684e378 --- /dev/null +++ b/output.tf @@ -0,0 +1,7 @@ +output "VMIps" { + value = azurerm_public_ip.vmIps.*.ip_address +} + +output "Load_Balancer_IP" { + value = azurerm_public_ip.lbip.ip_address +} \ No newline at end of file diff --git a/provider.tf b/provider.tf new file mode 100644 index 0000000..3d6dcf3 --- /dev/null +++ b/provider.tf @@ -0,0 +1,17 @@ + +provider "azurerm" { + subscription_id = var.subscription_id + skip_provider_registration = true + features {} +} + +resource "azurerm_resource_group" "cliff" { + name = var.resource_group + location = var.location +} + +resource "azurerm_availability_set" "cliff-as" { + name = "cliff-as" + location = azurerm_resource_group.cliff.location + resource_group_name = azurerm_resource_group.cliff.name +} \ No newline at end of file diff --git a/terraform.tfvars b/terraform.tfvars new file mode 100644 index 0000000..48b5948 --- /dev/null +++ b/terraform.tfvars @@ -0,0 +1,5 @@ +location = "eastus" +resource_group = "cliffRG" +cloud_shell_source = "192.168.1.0/24" +domain_name_prefix = "cliff-project" +management_ip = "192.168.65.0/24" \ No newline at end of file diff --git a/variable.tf b/variable.tf new file mode 100644 index 0000000..92928d9 --- /dev/null +++ b/variable.tf @@ -0,0 +1,24 @@ +variable "location" { + type = string +} + +variable "resource_group" { + type = string +} + +variable "cloud_shell_source" { + type = string +} + +variable "management_ip" { + type = string +} + +variable "domain_name_prefix" { + type = string +} +variable "subscription_id" { + description = "Azure Subscription ID" + type = string + default = "b462d350-1ac8-4373-a8c5-deadc8357530" +} \ No newline at end of file diff --git a/version.tf b/version.tf new file mode 100644 index 0000000..70b69f7 --- /dev/null +++ b/version.tf @@ -0,0 +1,8 @@ +terraform { + required_providers { + azurerm = { + source = "hashicorp/azurerm" + version = "2.88.0" + } + } +} \ No newline at end of file diff --git a/vm.tf b/vm.tf new file mode 100644 index 0000000..e28413a --- /dev/null +++ b/vm.tf @@ -0,0 +1,74 @@ +resource "azurerm_virtual_network" "main" { + name = "cliff-network" + address_space = ["10.0.0.0/16"] + location = azurerm_resource_group.cliff.location + resource_group_name = azurerm_resource_group.cliff.name +} + +resource "azurerm_subnet" "internal" { + name = "internal" + resource_group_name = azurerm_resource_group.cliff.name + virtual_network_name = azurerm_virtual_network.main.name + address_prefixes = ["10.0.2.0/24"] + + depends_on = [ + azurerm_virtual_network.main + ] +} + + +resource "azurerm_network_interface" "mars" { + count = 2 + name = "cliff_nic-${count.index}" + location = azurerm_resource_group.cliff.location + resource_group_name = azurerm_resource_group.cliff.name + ip_configuration { + name = "ip_config" + subnet_id = azurerm_subnet.internal.id + private_ip_address_allocation = "Dynamic" + public_ip_address_id = azurerm_public_ip.vmIps[count.index].id + } + depends_on = [ + azurerm_subnet.internal] +} + +resource "azurerm_windows_virtual_machine" "cliffvms" { + count = 2 + name = "cliffvms-${count.index}" + admin_username = "cadmin" + admin_password = "Password2021" + computer_name = "cliffvm-${count.index}" + location = var.location + resource_group_name = azurerm_resource_group.cliff.name + size = "Standard_DS1_v2" + availability_set_id = azurerm_availability_set.cliff-as.id + os_disk { + caching = "ReadWrite" + storage_account_type = "Standard_LRS" + } + network_interface_ids = [azurerm_network_interface.mars[count.index].id] + source_image_reference { + publisher = "MicrosoftWindowsServer" + offer = "WindowsServer" + sku = "2019-Datacenter" + version = "latest" + } + depends_on = [azurerm_availability_set.cliff-as] + +} + +resource "azurerm_virtual_machine_extension" "enablewinrm" { + count = 2 + name = "enablewinrm" + virtual_machine_id = azurerm_windows_virtual_machine.cliffvms[count.index].id + publisher = "Microsoft.Compute" + type = "CustomScriptExtension" + type_handler_version = "1.9" + auto_upgrade_minor_version = true + settings = <