How to make "terraform plan" use my config file - azure

I created an Azure service principal
I created a file called azureProviderAndCreds.tf that looks similar to the following:
variable subscription_id {}
variable tenant_id {}
variable client_id {}
variable client_secret {}
provider "azurerm" {
subscription_id = "<my-azure-subscription-id>"
tenant_id = "<tenantid-returned-from-creating-a-service-principal>"
client_id = "<appid-returned-from-creating-a-service-principal>"
client_secret = "<password-returned-from-creating-a-service-principal>"
}
I ran terraform init
I ran terraform plan
When executing terraform plan, the command asks me for the client_id.
I have this value defined in the azureProviderAndCreds.tf file. How do I get Terraform to look at my config file for that info?

I'd read through the docs to get a handle of the input variables basics.
But heres a couple quick things:
You are declaring variables and not actually using them in your provider:
provider "azurerm" {
subscription_id = "${var.subscription_id}"
tenant_id = "${var.tenant_id}"
client_id = "${var.client_id}"
client_secret = "${client_secret}"
}
You could set defaults for your variables when declaring them:
variable subscription_id {
default = "your-subscription-id"
}
Of you could create a .tfvars file like variables.tfvars and pass that when running plan:
subscription_id = "your-subscription-id"
tenant_id = "your-tenant-id"
client_id = "your-client-id"
client_secret = "your-client-secret"
terraform plan -var-file=variables.tfvars

Related

terraform still looking for azure cli login when using Azure Service Principal

I'm fairly new to Terraform. I'm trying to use Azure Service Principal for terraform. My code looks like below. However when I run terraform init, I get an error Error building ARM Config: obtain subscription() from Azure CLI: parsing json result from the Azure CLI: waiting for the Azure CLI: exit status 1: ERROR: Please run 'az login' to setup account.
(I have deliberately logged out of Azure CLI to verify that the terraform code is NOT using azure cli. And looks like it's still looking for Azure CLI.)
terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "=3.0.0"
}
}
backend "azurerm" {
resource_group_name = "rg-XXXX"
storage_account_name = "saXXXXX"
container_name = "XXXXX"
key = "XXXXX"
}
}
provider "azurerm" {
features {}
subscription_id = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
client_id = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
client_secret = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
tenant_id = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
}
There are missing info allowing terraform to connect to the azurerm backend.
https://developer.hashicorp.com/terraform/language/settings/backends/azurerm#resource_group_name-2
You need to add client_id, client_secret and tenant_id in the backend configuration
backend "azurerm" {
resource_group_name = "rg-XXXX"
storage_account_name = "saXXXXX"
container_name = "XXXXX"
key = "XXXXX"
client_id = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
client_secret = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
tenant_id = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
}
You may use environment variables for this. You won't have to repeat them and it will allow you to commit your template to a source code repository without sensitive information.

Where to save Azure app registration secrets

My questions is regarding Azure app registration secrets.
I have an app registration and its secrets (client_id, subscription_id, tenant_id and client_id)
I am able to provision the resources through terraform.
For the security purpose it is recommended to do not upload secrets to your git repo.
So my question is, where we can save these secrets so we can retrieve them at the runtime?
I have already saved them into Azure key vault and when I try to retrieve them in providers.tf I get an error
Cycle: data.azurerm_key_vault_secret.client-secret, provider["registry.terraform.io/hashicorp/azurerm"], data.azurerm_key_vault.my_key_vault
what am I doing wrong?
So finally I have found the solution on terraform's official website
First you have to set env variables in your .zprofile
export ARM_SUBSCRIPTION_ID=*******
export ARM_CLIENT_ID=*******
export ARM_CLIENT_SECRET=*******
export ARM_TENANT_ID=*******
Then you have to create a variables.tf file and then create variable blocks as
variable "subscription_id" {
}
variable "client_id" {
}
variable "client_secret" {
}
variable "tenant_id" {
}
and the last step is to access them in the providers.tf file
# Configuration options
provider "azurerm" {
subscription_id = var.subscription_id
client_id = var.client_id
client_secret = var.client_secret
tenant_id = var.tenant_id
features {
}
}

terraform Error: Cycle: data.azurerm_key_vault_secret

This is my first file main.tf
# Configure the Azure provider
provider "azurerm" {
environment = "public"
features {}
subscription_id = var.azure-subscription-id
client_id = var.azure-client-id
client_secret = "${data.azurerm_key_vault_secret.azure-client-secret1.value}"
tenant_id = var.azure-tenant-id
}
I have another file kv-data.tf
data "azurerm_key_vault_secret" "azure-client-secret1" {
name = "azure-client-secret"
vault_uri = "https://kv23.vault.azure.net/"
}
But I get this error. What is the correct way to access keyvault secret?
│ Error: Cycle: data.azurerm_key_vault_secret.azure-client-secret1,
provider["registry.terraform.io/hashicorp/azurerm"]
It is not possible to do this. To access Keyvault you would need credentials which is not supplied. You will have to hardcode it like other vars.

maintain terraform azure state file in one subscription and deploy to multiple cloud subscriptions

I need to store my terraform state file in a single azure storage account and deploy it to multiple cloud subscriptions(china and public cloud)..
I have my backend configured as below:
terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "=2.78.0"
}
}
backend "azurerm" {
resource_group_name = "Terraform-rg"
storage_account_name = "terraformstate"
container_name = "tfstate"
subscription_id = "00000000-0000-0000-0000-000000000000"
key = "prod"
}
}
provider "azurerm" {
features {}
}
provider "azurerm" {
features {}
alias = "sub2"
subscription_id = "xxxxxxx-xxxxx-xxxx-xxxx-xxxxxxxxxxx"
client_id = "xxxxxxx-xxxxx-xxxx-xxxx-xxxxxxxxxxx"
client_secret = var.client_secret
tenant_id = "xxxxxxx-xxxxx-xxxx-xxxx-xxxxxxxxxxx"
}
However, when I am trying to terraform init with this approach, I am getting the below error:
Failed to get configured named states: Error retrieving keys for Storage Account "terraformstate": storage.AccountsClient#ListKeys: Failure responding to request: StatusCode=404 -- Original Error: autorest/azure: Service returned an error. Status=404 Code="SubscriptionNotFound" Message="The subscription 'xxxxxxx-xxxxx-xxxx-xxxx-xxxxxxxxxxx' could not be found."
I was wondering if it is even possible to do this?
I also have a script to terraform init and terraform plan which would switch the cloud based on env..
"az cloud set --name AzureChinaCloud" for china and for non china "az cloud set --name AzureCloud"
The storage account subscription is in AzureCloud.. How do I authorise to write the state file for AzureChinaCloud in AzureCloud?
Is this approach even possible?
As mentioned in the comment section, The issue in your code is you are missing Environment parameter in the provider block . As you were manually setting the cloud environment so, the code was not able to find the Subscription in the Backend Configuration which is in public cloud .
So, the solution will be setting the parameter in the code like below and not manually using az CLI :
terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "=2.78.0"
}
}
backend "azurerm" {
resource_group_name = "Terraform-rg"
storage_account_name = "terraformstate"
container_name = "tfstate"
subscription_id = "00000000-0000-0000-0000-000000000000"
key = "prod"
}
}
provider "azurerm" {
features {}
}
provider "azurerm" {
features {}
alias = "USGovernment"
subscription_id = "xxxxxxx-xxxxx-xxxx-xxxx-xxxxxxxxxxx"
client_id = "xxxxxxx-xxxxx-xxxx-xxxx-xxxxxxxxxxx"
client_secret = var.client_secret
tenant_id = "xxxxxxx-xxxxx-xxxx-xxxx-xxxxxxxxxxx"
environment = "usgovernment"
}
provider "azurerm" {
features {}
alias = "China"
subscription_id = "xxxxxxx-xxxxx-xxxx-xxxx-xxxxxxxxxxx"
client_id = "xxxxxxx-xxxxx-xxxx-xxxx-xxxxxxxxxxx"
client_secret = var.client_secret
tenant_id = "xxxxxxx-xxxxx-xxxx-xxxx-xxxxxxxxxxx"
environment = "china"
}
Reference:
Docs overview | hashicorp/azurerm | Terraform Registry
SO thread

How to use the terraform state in another azure subscription

I am deploying an azure infrastructure with Terraform. The terraform state will be stored in a subscription which will be different from the main deployment subscription. I am using alias in provider declaration. My terraform code is like below:
terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "~> 2.38.0"
}
}
backend "azurerm" {
resource_group_name = "resourcegroup_name"
storage_account_name = "storageaccount_name"
container_name = "mystate"
key = "tfstatename1.tfstate"
}
}
provider "azurerm" {
features {}
}
provider "azurerm" {
features {}
alias = "second_subscription"
subscription_id = var.second_subscription_id
}
My terraform state should be stored in the subscription with alias.
How can i achieve that?
I don't think the azurerm backend configuration is taking input from the azurerm provider configuration. To some extent you could say it applies its own authentication mechanism. But there are some features they share nevertheless: e.g. both are capable of using the Azure CLI security context.
In order to explicitly target a subscription id for your backend configuration, you must add it to the backend configuration block. Like so:
backend "azurerm" {
resource_group_name = "resourcegroup_name"
storage_account_name = "storageaccount_name"
container_name = "mystate"
key = "tfstatename1.tfstate"
subscription_id = "091f1800-0de3-4fef-831a-003a74ce245f"
}
Reference: https://developer.hashicorp.com/terraform/language/settings/backends/azurerm

Resources