Issues in passing key vault secrets to the Data.tf and referencing in Main.tf - azure-keyvault

I have created multiple key vault secrets in the Azure portal and trying pass them in terraform Data.tf. But i am not sure how to pass multiple secrets and refer in the main.tf. Can someone help on this.
My requirement is to pass multiple values in the Name attribute and refer in Main.tf
data.tf
data "azurerm_key_vault" "key_vault" {
name = "test-key-vault-cts"
resource_group_name = "gcdmvrlyprd03-30cf06a8"
}
data "azurerm_key_vault_secret" "admin_password" {
name = "admin-password"
key_vault_id = data.azurerm_key_vault.key_vault.id
}
Main.tf
module "location_us-west" {
source = "./Modules"
web_server_location = "westus2"
web_server_rg = "${var.web_server_rg}-us-west"
resource_prefix = "${var.resource_prefix}-us-west"
web_server_address_space = "10.0.0.0/22"
#web_server_address_prefix = "10.0.1.0/24"
web_server_name = var.web_server_name
environment = var.environment
size = var.vm_size
admin_user = var.user
admin_password = data.azurerm_key_vault_secret.admin_password.value
web_server_count = var.web_server_count
web_server_subnets = {
"web-server" = "10.0.1.0/24"
"AzureBastionSubnet" = "10.0.2.0/24"
}
}

If you want to reference a second secret via data, create a second block of code.
data "azurerm_key_vault_secret" "admin_password2" {
name = "admin-password2"
key_vault_id = data.azurerm_key_vault.key_vault.id
}

In my opinion, you can put the data sources together with the module location_us-west in the main.tf file. So that you can quote the data.azurerm_key_vault_secret.admin_password.value directly. I don't recommend you desperate the data sources from the main.tf file if you just want to quote the secrets without any other actions.
And for the secrets, you need to put the names for multiple secrets to get them from the Key vault. So if you want to get multiple secrets only one time, you can change the code like this example:
variable "secret_names" {
type = list
default = [
"test1",
"test2"
]
}
data "azurerm_key_vault" "example" {
name = "key_vault_name"
resource_group_name = "group_name"
}
data "azurerm_key_vault_secret" "example" {
count = length(var.secret_names)
name = element(var.secret_names, count.index)
key_vault_id = data.azurerm_key_vault.example.id
}
Then the output data.azurerm_key_vault_secret.example.*.value will contain all the secret values in a list.

Related

Error: "zone": conflicts with availability_set_id - Azure - Terraform

We have some Linux clusters (two machines each) running on Azure and we would like that each node of the cluster be created in different zones and using availability set.
We are trying to create the VM on Azure using Terraform:
resource "azurerm_linux_virtual_machine" "move-az-test" {
count = "1"
name = "move-az-test01"
location = var.azure_location_short
resource_group_name = azurerm_resource_group.rg.name
size = "Standard_B1S"
zone = 1
computer_name = "move-az01"
disable_password_authentication = true
admin_username = var.os_user
admin_password = var.os_password
availability_set_id = azurerm_availability_set.avset.id
network_interface_ids = [azurerm_network_interface.move-az-nic.id]
source_image_reference {
publisher = "OpenLogic"
offer = "CentOS"
sku = "7.6"
version = "latest"
}
os_disk {
name = "move-az-test0_OsDisk"
caching = "ReadWrite"
disk_size_gb = "128"
storage_account_type = "Standard_LRS"
}
}
But we have the message error: Error: "zone": conflicts with availability_set_id
The short answer is that the availability set and the availability zone can't exist at the same time. You can take deeper learning about them. The former is in a logical grouping of the VMs and the latter improves the availability on the physical regions.

How to create multiple vm nics in a loop using terraform with static ipaddress assigned

I am trying to create 2 VM's in Azure using Terraform and each VM requires 4 nics, one in each subnet of the vnet and these nics must be configured with static IP addresses. Is there any way to accomplish this using loops ideally with for_each?
I can do this with 'dynamic' ip address assignment for the ip_configuration block without-issues but need it working with 'static' IP assignment and don't know how to pass the ip address inside the ip_configuration block of the network interface resource block.
I don't know if dynamic block is the right model for this here but I tried to use nested loop with dynamic ip_configuration block without much luck :-(
Here is what I have so far (Snippet for nics for subnet1) and would love to get some help;
variable "subnet1IpAddresses" {
type = map(string)
description = "The subnet1 IP address to assign to vm nodes."
default = {
"1" = "10.10.1.4"
"2" = "10.10.1.5"
}
}
locals {
vmName = [format("%s%s%s%s%s", var.envPrefix, "-", var.dptPrefix, var.vmPrefix, "01"), format("%s%s%s%s%s", var.envPrefix, "-", var.dptPrefix, var.vmPrefix, "02")]
subnet1Ip = [var.subnet1IpAddresses[1], var.subnet1IpAddresses[2]]
}
#create NIC for each NVA and Assign Static IP addresses.
resource "azurerm_network_interface" "subnet1Nics" {
for_each = toset(local.vmName)
name = "${each.value}subnet1-nic"
resource_group_name = azurerm_resource_group.rg.name
location = azurerm_resource_group.rg.location
enable_ip_forwarding = "true"
enable_accelerated_networking = "true"
dynamic ip_configuration {
for_each = local.subnet1Ip
content {
name = "ipconfig1"
subnet_id = azurerm_subnet.snet1.id
private_ip_address = ip_configuration.value
private_ip_address_allocation = "static"
primary = "true"
}
}
}
The problem with the above code 'as-is' is that it try to create two ip_configurations for the same VM so VM1 will have nic1 with two IP configurations i.e. (10.10.1.4 and 10.10.1.5) but that's not what I need.
Simply put, below is the outcome I desire for this specific example and hoping someone can help with it.
VM1's nic1 with IP (10.10.1.4)
VM2's nic1 with IP (10.10.1.5)
Thanks.
Here is an example for your purpose: 2 VMs, each VM has 4 NICs, 4 subnets in the VNet, each NIC of the VM in a subnet.
main.tf:
provider "azurerm" {
features {}
}
variable "nics" {}
variable "vnet_prefix" {}
variable "subnet_prefixes" {}
resource "azurerm_resource_group" "group" {
name = "charlesVM"
location = "East Asia"
}
resource "azurerm_virtual_network" "vnet" {
name = "charles-vnet"
resource_group_name = azurerm_resource_group.group.name
location = azurerm_resource_group.group.location
address_space = var.vnet_prefix
}
resource "azurerm_subnet" "subnets" {
count = length(var.subnet_prefixes)
name = "subnet-${count.index}"
resource_group_name = azurerm_resource_group.group.name
virtual_network_name = azurerm_virtual_network.vnet.name
address_prefix = element(var.subnet_prefixes, count.index)
}
resource "azurerm_network_interface" "nics" {
count = length(var.nics)
name = "nic-${count.index}"
location = azurerm_resource_group.group.location
resource_group_name = azurerm_resource_group.group.name
ip_configuration {
name = "config-${count.index}"
subnet_id = element(azurerm_subnet.subnets[*].id, count.index % 4)
private_ip_address_allocation = "Static"
private_ip_address = element(var.nics, count.index)
}
}
locals {
vm_nics = chunklist(azurerm_network_interface.nics[*].id, 4)
}
resource "azurerm_linux_virtual_machine" "vm" {
count = 2
name = "azurevm-${count.index}"
resource_group_name = azurerm_resource_group.group.name
location = azurerm_resource_group.group.location
size = "Standard_DS3_v2"
admin_username = "adminuser"
network_interface_ids = element(local.vm_nics, count.index)
admin_ssh_key {
username = "adminuser"
public_key = file("~/.ssh/id_rsa.pub")
}
os_disk {
caching = "ReadWrite"
storage_account_type = "Standard_LRS"
}
source_image_reference {
publisher = "Canonical"
offer = "UbuntuServer"
sku = "16.04-LTS"
version = "latest"
}
}
terraform.tfvar:
nics = [
"10.0.0.4",
"10.0.1.4",
"10.0.2.4",
"10.0.3.4",
"10.0.0.5",
"10.0.1.5",
"10.0.2.5",
"10.0.3.5"
]
vnet_prefix = ["10.0.0.0/16"]
subnet_prefixes = [
"10.0.0.0/24",
"10.0.1.0/24",
"10.0.2.0/24",
"10.0.3.0/24"
]
Note that you want to use the static IP address, then you need to calculate them manually to avoid the conflict, and make sure each IP address of the NIC is right in the subnet. And you also need to choose the right VM size that can support 4 NICs for one VM.

terraform azurerm_scheduled_query_rules_log

Hi I'm running terraform
Terraform v0.13.4
provider registry.terraform.io/hashicorp/azurerm v2.41.0
I'm trying to set up azure metric monitoring for vm
resource "azurerm_scheduled_query_rules_log" "scheduled_rules" {
for_each = local.alert_rules
name = "${var.client_initial}-${each.key}"
location = var.resource_group_name.location
resource_group_name = var.resource_group_name
criteria {
metric_name = each.value.metric_name
dimension {
name = "Computer"
operator = "Include"
values = var.virtual_machines
}
}
data_source_id = var.log_analytics_workspace_ID
description = each.value.description
enabled = true
}
However when i run plan, it tells me
53: resource "azurerm_scheduled_query_rules_log" "scheduled_rules" {
The provider provider.azurerm does not support resource type
"azurerm_scheduled_query_rules_log".
I see this new resource is introduced in azurerm 2.1, not sure why it's not available on 2.41.0?
I also face the same error. It should be the resource azurerm_monitor_scheduled_query_rules_log instead of azurerm_scheduled_query_rules_log. There might be some mistakes or do not update in the terraform Example Usage.
Here is a working example with Terraform v0.14.3 + azurerm v2.41.0
# Example: LogToMetric Action for the named Computer
resource "azurerm_monitor_scheduled_query_rules_log" "example" {
name = format("%s-queryrule", "some")
location = azurerm_resource_group.example.location
resource_group_name = azurerm_resource_group.example.name
criteria {
metric_name = "Average_% Idle Time"
dimension {
name = "Computer"
operator = "Include"
values = ["targetVM"]
}
}
data_source_id = azurerm_log_analytics_workspace.example.id
description = "Scheduled query rule LogToMetric example"
enabled = true
}

Need more detail on how to deploy an Azure IaaS into a specific Availability Zone?

Need more detail on how to create a resource for placing an IaaS into an specific availability zone during azurerm terraform deployment?
https://www.terraform.io/docs/providers/azurerm/r/virtual_machine.html#zones
This link does not give me enough detail on how to write the option of choosing a specific availability zone for a VM that will be deployed using azure terraform.
zones  - (Optional) A list of a single item of the Availability Zone which the Virtual Machine should be allocated in.
The documentation is saying that you need a terraform list with a single item which is the zone that you want the VM created. Here is what that looks like for East US using Zone 1.
resource "azurerm_virtual_machine" "main" {
name = "${var.prefix}-vm"
location = "${azurerm_resource_group.main.location}"
resource_group_name = "${azurerm_resource_group.main.name}"
network_interface_ids = ["${azurerm_network_interface.main.id}"]
vm_size = "Standard_DS1_v2"
# Zone info
zones = [1]
storage_image_reference {
publisher = "Canonical"
offer = "UbuntuServer"
sku = "16.04-LTS"
version = "latest"
}
storage_os_disk {
name = "myosdisk1"
caching = "ReadWrite"
create_option = "FromImage"
managed_disk_type = "Standard_LRS"
}
os_profile {
computer_name = "hostname"
admin_username = "testadmin"
admin_password = "Password1234!"
}
os_profile_linux_config {
disable_password_authentication = false
}
tags = {
environment = "staging"
}
}

Pass several parameters in StartLogin function

I am building a custom connector to connect to our API via OAuth2. This is so we can use our api as a data source to powerbi.
// Resource definition
Resource = [
Description = "MyAPI",
Type = "Custom",
MakeResourcePath = (env) => env,
ParseResourcePath = (env) => {env},
Authentication = [OAuth=[StartLogin = StartLogin, FinishLogin = FinishLogin, Refresh = Refresh]],
......
Icons = [
Icon16 = { Extension.Contents("MyAPI10.png"), Extension.Contents("MyAPI20.png") }
],
Label = "MyAPI"
]
in
Extension.Module("MyAPI", { Resource })
I used MakeResourcePath and ParseResourcePath to pass the Environment parameter (which is taken as input from the user in power bi site/desktop). This is passed to StartLogin to make the OAuth authorize call.
StartLogin = (env, state, display) =>
let
resourceUrl = getOAuthUrlFromEnvName(env) & "/oauth/authorize",
AuthorizeUrl = resourceUrl & "?" & Uri.BuildQueryString([
client_id = getClientIdFromEnv(env),
response_type = "code",
state = state, // added by VM
redirect_uri = redirect_uri])
in
[
LoginUri = AuthorizeUrl,
CallbackUri = redirect_uri,
WindowHeight = windowHeight,
WindowWidth = windowWidth,
Context = env
],
I need another parameter as input from the user now. It's called hostname in ui. How do I pass hostname and environment both to StartLogin function? I basically need these two variables to construct resourceUrl. Any references would be helpful too.
You don't need to pass the variables into StartLogin function to construct the AuthorizeUrl. Instead, you can just declare them as global variables so the StartLogin can access them to construct the AuthorizeUrl.
e.g.
hostname = ...;
environment = ...;
authorize_uri = hostname & "/" & getOAuthUrlFromEnvName(environment) & "/oauth/authorize?"
StartLogin = (resourceUrl, state, display) =>
let
authorizeUrl = authorize_uri & "?" & Uri.BuildQueryString([
...

Resources