Menu

Virtual Geek

Tales from real IT system administrators world and non-production environment

Terraform passing different credentials to different subscriptions with provider alias

Terraform passing different credentials to different subscriptions with provider alias.png

While planning and designing Terraform configuration files for Azure deployment, I wanted to deploy resources to different environment in different subscriptions. In the designing code idea was to use different multiple credentials while deploying environments and referencing them with alias.

To achieve this here is my very simple demo code. I have created two Resource Groups and two App Registration (Service Principal) named dev and prod in Microsoft Azure Portal. For each Resource Group I have role assigned of Owner to respective matching name of Service principal. For example as you can see in the below screenshot from Access Control (IAM) pane view of dev resource group.

In the dev resource group for simplicity I have assigned Owner role permission to dev named service principal. Same setting is configured on prod Resource Group. Named with prod service principal has Owner role assigned to prod resource group. Here dev SP can only create resources in dev RG and so does the same for prod named entitiesAll names are corresponding. 

Microsoft Azure Resource group IAM access control role assignment privileges terraform alias provider different credentials for different environment and resources configuration.png

Using the same configuration, when writing provider block in terraform code, I have added 2 azurerm provider blocks with one alias is for dev and another alias is for prod. Respectively for each dev and prod block, I have provided (Same name as dev and prod) service principal client_id, client_secret, subscription_id and tenant_id information. I will be deploying Storage Account in each resource group dev and prod as per given permissions to the resource group. In the the storage account block I have mentioned which provider alias it should use to authenticate against subscription/tenant and deploy the resources with correct permissions. 

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
provider "azurerm" {
  features {}
  alias           = "dev"
  client_id       = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
  client_secret   = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
  subscription_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
  tenant_id       = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
}

provider "azurerm" {
  features {}
  alias           = "prod"
  client_id       = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
  client_secret   = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
  subscription_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
  tenant_id       = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
}

locals {
  devEng  = "dev"
  prodEng = "prod"

  location                 = "East Us"
  account_tier             = "Standard"
  account_replication_type = "LRS"
}

resource "azurerm_storage_account" "dev" {
  provider = azurerm.dev

  name                     = "vcloudlabsa${local.devEng}"
  resource_group_name      = local.devEng
  location                 = local.location
  account_tier             = local.account_tier
  account_replication_type = local.account_replication_type
}

resource "azurerm_storage_account" "prod" {
  provider = azurerm.prod

  name                     = "vcloudlabsa${local.prodEng}"
  resource_group_name      = local.prodEng
  location                 = local.location
  account_tier             = local.account_tier
  account_replication_type = local.account_replication_type
}

Below is the output from the apply command. Complete deployment is clean and installed correctly, just to note it doesn't mention provider alias related information any where in the output.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
terraform apply --auto-approve  

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # azurerm_storage_account.dev will be created
  + resource "azurerm_storage_account" "dev" {
      + access_tier                        = (known after apply)
      + account_kind                       = "StorageV2"
      + account_replication_type           = "LRS"
      + account_tier                       = "Standard"
      + allow_nested_items_to_be_public    = true
      + cross_tenant_replication_enabled   = true
      + default_to_oauth_authentication    = false
      + dns_endpoint_type                  = "Standard"
      + enable_https_traffic_only          = (known after apply)
      + https_traffic_only_enabled         = (known after apply)
      + id                                 = (known after apply)
      + infrastructure_encryption_enabled  = false
      + is_hns_enabled                     = false
      + large_file_share_enabled           = (known after apply)
      + local_user_enabled                 = true
      + location                           = "eastus"
      + min_tls_version                    = "TLS1_2"
      + name                               = "vcloudlabsadev"
      + nfsv3_enabled                      = false
      + primary_access_key                 = (sensitive value)
      + primary_blob_connection_string     = (sensitive value)
      + primary_blob_endpoint              = (known after apply)
      + primary_blob_host                  = (known after apply)
      + primary_blob_internet_endpoint     = (known after apply)
      + primary_blob_internet_host         = (known after apply)
      + primary_blob_microsoft_endpoint    = (known after apply)
      + primary_blob_microsoft_host        = (known after apply)
      + primary_connection_string          = (sensitive value)
      + primary_dfs_endpoint               = (known after apply)
      + primary_dfs_host                   = (known after apply)
      + primary_dfs_internet_endpoint      = (known after apply)
      + primary_dfs_internet_host          = (known after apply)
      + primary_dfs_microsoft_endpoint     = (known after apply)
      + primary_dfs_microsoft_host         = (known after apply)
      + primary_file_endpoint              = (known after apply)
      + primary_file_host                  = (known after apply)
      + primary_file_internet_endpoint     = (known after apply)
      + primary_file_internet_host         = (known after apply)
      + primary_file_microsoft_endpoint    = (known after apply)
      + primary_file_microsoft_host        = (known after apply)
      + primary_location                   = (known after apply)
      + primary_queue_endpoint             = (known after apply)
      + primary_queue_host                 = (known after apply)
      + primary_queue_microsoft_endpoint   = (known after apply)
      + primary_queue_microsoft_host       = (known after apply)
      + primary_table_endpoint             = (known after apply)
      + primary_table_host                 = (known after apply)
      + primary_table_microsoft_endpoint   = (known after apply)
      + primary_table_microsoft_host       = (known after apply)
      + primary_web_endpoint               = (known after apply)
      + primary_web_host                   = (known after apply)
      + primary_web_internet_endpoint      = (known after apply)
      + primary_web_internet_host          = (known after apply)
      + primary_web_microsoft_endpoint     = (known after apply)
      + primary_web_microsoft_host         = (known after apply)
      + public_network_access_enabled      = true
      + queue_encryption_key_type          = "Service"
      + resource_group_name                = "dev"
      + secondary_access_key               = (sensitive value)
      + secondary_blob_connection_string   = (sensitive value)
      + secondary_blob_endpoint            = (known after apply)
      + secondary_blob_host                = (known after apply)
      + secondary_blob_internet_endpoint   = (known after apply)
      + secondary_blob_internet_host       = (known after apply)
      + secondary_blob_microsoft_endpoint  = (known after apply)
      + secondary_blob_microsoft_host      = (known after apply)
      + secondary_connection_string        = (sensitive value)
      + secondary_dfs_endpoint             = (known after apply)
      + secondary_dfs_host                 = (known after apply)
      + secondary_dfs_internet_endpoint    = (known after apply)
      + secondary_dfs_internet_host        = (known after apply)
      + secondary_dfs_microsoft_endpoint   = (known after apply)
      + secondary_dfs_microsoft_host       = (known after apply)
      + secondary_file_endpoint            = (known after apply)
      + secondary_file_host                = (known after apply)
      + secondary_file_internet_endpoint   = (known after apply)
      + secondary_file_internet_host       = (known after apply)
      + secondary_file_microsoft_endpoint  = (known after apply)
      + secondary_file_microsoft_host      = (known after apply)
      + secondary_location                 = (known after apply)
      + secondary_queue_endpoint           = (known after apply)
      + secondary_queue_host               = (known after apply)
      + secondary_queue_microsoft_endpoint = (known after apply)
      + secondary_queue_microsoft_host     = (known after apply)
      + secondary_table_endpoint           = (known after apply)
      + secondary_table_host               = (known after apply)
      + secondary_table_microsoft_endpoint = (known after apply)
      + secondary_table_microsoft_host     = (known after apply)
      + secondary_web_endpoint             = (known after apply)
      + secondary_web_host                 = (known after apply)
      + secondary_web_internet_endpoint    = (known after apply)
      + secondary_web_internet_host        = (known after apply)
      + secondary_web_microsoft_endpoint   = (known after apply)
      + secondary_web_microsoft_host       = (known after apply)
      + sftp_enabled                       = false
      + shared_access_key_enabled          = true
      + table_encryption_key_type          = "Service"

      + blob_properties (known after apply)

      + network_rules (known after apply)

      + queue_properties (known after apply)

      + routing (known after apply)

      + share_properties (known after apply)
    }

  # azurerm_storage_account.prod will be created
  + resource "azurerm_storage_account" "prod" {
      + access_tier                        = (known after apply)
      + account_kind                       = "StorageV2"
      + account_replication_type           = "LRS"
      + account_tier                       = "Standard"
      + allow_nested_items_to_be_public    = true
      + cross_tenant_replication_enabled   = true
      + default_to_oauth_authentication    = false
      + dns_endpoint_type                  = "Standard"
      + enable_https_traffic_only          = (known after apply)
      + https_traffic_only_enabled         = (known after apply)
      + id                                 = (known after apply)
      + infrastructure_encryption_enabled  = false
      + is_hns_enabled                     = false
      + large_file_share_enabled           = (known after apply)
      + local_user_enabled                 = true
      + location                           = "eastus"
      + min_tls_version                    = "TLS1_2"
      + name                               = "vcloudlabsaprod"
      + nfsv3_enabled                      = false
      + primary_access_key                 = (sensitive value)
      + primary_blob_connection_string     = (sensitive value)
      + primary_blob_endpoint              = (known after apply)
      + primary_blob_host                  = (known after apply)
      + primary_blob_internet_endpoint     = (known after apply)
      + primary_blob_internet_host         = (known after apply)
      + primary_blob_microsoft_endpoint    = (known after apply)
      + primary_blob_microsoft_host        = (known after apply)
      + primary_connection_string          = (sensitive value)
      + primary_dfs_endpoint               = (known after apply)
      + primary_dfs_host                   = (known after apply)
      + primary_dfs_internet_endpoint      = (known after apply)
      + primary_dfs_internet_host          = (known after apply)
      + primary_dfs_microsoft_endpoint     = (known after apply)
      + primary_dfs_microsoft_host         = (known after apply)
      + primary_file_endpoint              = (known after apply)
      + primary_file_host                  = (known after apply)
      + primary_file_internet_endpoint     = (known after apply)
      + primary_file_internet_host         = (known after apply)
      + primary_file_microsoft_endpoint    = (known after apply)
      + primary_file_microsoft_host        = (known after apply)
      + primary_location                   = (known after apply)
      + primary_queue_endpoint             = (known after apply)
      + primary_queue_host                 = (known after apply)
      + primary_queue_microsoft_endpoint   = (known after apply)
      + primary_queue_microsoft_host       = (known after apply)
      + primary_table_endpoint             = (known after apply)
      + primary_table_host                 = (known after apply)
      + primary_table_microsoft_endpoint   = (known after apply)
      + primary_table_microsoft_host       = (known after apply)
      + primary_web_endpoint               = (known after apply)
      + primary_web_host                   = (known after apply)
      + primary_web_internet_endpoint      = (known after apply)
      + primary_web_internet_host          = (known after apply)
      + primary_web_microsoft_endpoint     = (known after apply)
      + primary_web_microsoft_host         = (known after apply)
      + public_network_access_enabled      = true
      + queue_encryption_key_type          = "Service"
      + resource_group_name                = "prod"
      + secondary_access_key               = (sensitive value)
      + secondary_blob_connection_string   = (sensitive value)
      + secondary_blob_endpoint            = (known after apply)
      + secondary_blob_host                = (known after apply)
      + secondary_blob_internet_endpoint   = (known after apply)
      + secondary_blob_internet_host       = (known after apply)
      + secondary_blob_microsoft_endpoint  = (known after apply)
      + secondary_blob_microsoft_host      = (known after apply)
      + secondary_connection_string        = (sensitive value)
      + secondary_dfs_endpoint             = (known after apply)
      + secondary_dfs_host                 = (known after apply)
      + secondary_dfs_internet_endpoint    = (known after apply)
      + secondary_dfs_internet_host        = (known after apply)
      + secondary_dfs_microsoft_endpoint   = (known after apply)
      + secondary_dfs_microsoft_host       = (known after apply)
      + secondary_file_endpoint            = (known after apply)
      + secondary_file_host                = (known after apply)
      + secondary_file_internet_endpoint   = (known after apply)
      + secondary_file_internet_host       = (known after apply)
      + secondary_file_microsoft_endpoint  = (known after apply)
      + secondary_file_microsoft_host      = (known after apply)
      + secondary_location                 = (known after apply)
      + secondary_queue_endpoint           = (known after apply)
      + secondary_queue_host               = (known after apply)
      + secondary_queue_microsoft_endpoint = (known after apply)
      + secondary_queue_microsoft_host     = (known after apply)
      + secondary_table_endpoint           = (known after apply)
      + secondary_table_host               = (known after apply)
      + secondary_table_microsoft_endpoint = (known after apply)
      + secondary_table_microsoft_host     = (known after apply)
      + secondary_web_endpoint             = (known after apply)
      + secondary_web_host                 = (known after apply)
      + secondary_web_internet_endpoint    = (known after apply)
      + secondary_web_internet_host        = (known after apply)
      + secondary_web_microsoft_endpoint   = (known after apply)
      + secondary_web_microsoft_host       = (known after apply)
      + sftp_enabled                       = false
      + shared_access_key_enabled          = true
      + table_encryption_key_type          = "Service"

      + blob_properties (known after apply)

      + network_rules (known after apply)

      + queue_properties (known after apply)

      + routing (known after apply)

      + share_properties (known after apply)
      + shared_access_key_enabled          = true
      + table_encryption_key_type          = "Service"

      + blob_properties (known after apply)

      + network_rules (known after apply)

      + queue_properties (known after apply)

      + routing (known after apply)

      + share_properties (known after apply)
    }

Plan: 2 to add, 0 to change, 0 to destroy.
azurerm_storage_account.dev: Creating...
azurerm_storage_account.prod: Creating...
azurerm_storage_account.dev: Still creating... [10s elapsed]
azurerm_storage_account.prod: Still creating... [10s elapsed]
azurerm_storage_account.dev: Still creating... [20s elapsed]
azurerm_storage_account.prod: Still creating... [20s elapsed]
azurerm_storage_account.dev: Still creating... [30s elapsed]
azurerm_storage_account.prod: Still creating... [30s elapsed]
      + shared_access_key_enabled          = true
      + table_encryption_key_type          = "Service"

      + blob_properties (known after apply)

      + network_rules (known after apply)

      + queue_properties (known after apply)

      + routing (known after apply)

      + share_properties (known after apply)
    }

Plan: 2 to add, 0 to change, 0 to destroy.
azurerm_storage_account.dev: Creating...
azurerm_storage_account.prod: Creating...
azurerm_storage_account.dev: Still creating... [10s elapsed]
azurerm_storage_account.prod: Still creating... [10s elapsed]
azurerm_storage_account.dev: Still creating... [20s elapsed]
azurerm_storage_account.prod: Still creating... [20s elapsed]
      + shared_access_key_enabled          = true
      + table_encryption_key_type          = "Service"

      + blob_properties (known after apply)

      + network_rules (known after apply)

      + queue_properties (known after apply)

      + routing (known after apply)

      + share_properties (known after apply)
    }

Plan: 2 to add, 0 to change, 0 to destroy.
azurerm_storage_account.dev: Creating...
azurerm_storage_account.prod: Creating...
      + table_encryption_key_type          = "Service"

      + blob_properties (known after apply)

      + network_rules (known after apply)

      + queue_properties (known after apply)

      + routing (known after apply)

      + share_properties (known after apply)

      + network_rules (known after apply)

      + queue_properties (known after apply)

      + routing (known after apply)

      + share_properties (known after apply)
      + queue_properties (known after apply)

      + routing (known after apply)

      + share_properties (known after apply)
      + routing (known after apply)

      + share_properties (known after apply)

      + share_properties (known after apply)
      + share_properties (known after apply)
    }

Plan: 2 to add, 0 to change, 0 to destroy.
azurerm_storage_account.dev: Creating...
azurerm_storage_account.prod: Creating...
azurerm_storage_account.dev: Still creating... [10s elapsed]
azurerm_storage_account.prod: Still creating... [10s elapsed]
azurerm_storage_account.dev: Still creating... [20s elapsed]
azurerm_storage_account.prod: Still creating... [20s elapsed]
azurerm_storage_account.dev: Still creating... [30s elapsed]
azurerm_storage_account.prod: Still creating... [30s elapsed]
azurerm_storage_account.dev: Still creating... [40s elapsed]
azurerm_storage_account.prod: Still creating... [40s elapsed]
azurerm_storage_account.dev: Still creating... [50s elapsed]
azurerm_storage_account.prod: Still creating... [50s elapsed]
azurerm_storage_account.dev: Still creating... [1m0s elapsed]
azurerm_storage_account.prod: Still creating... [1m0s elapsed]
azurerm_storage_account.dev: Still creating... [1m10s elapsed]
azurerm_storage_account.prod: Still creating... [1m10s elapsed]
azurerm_storage_account.prod: Creation complete after 1m12s [id=/subscriptions/9e22xxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/prod/providers/Microsoft.Storage/storageAccounts/vcloudlabsaprod]
azurerm_storage_account.dev: Creation complete after 1m14s [id=/subscriptions/9e22xxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/dev/providers/Microsoft.Storage/storageAccounts/vcloudlabsadev]

Apply complete! Resources: 2 added, 0 changed, 0 destroyed.

Download this code terraform provider alias referencing using different credentials for different environment and resources.tf here or it is also available on github.com.

Below are the some of the other implementations and alternatives of the Terraform Providers alias configuration. It shows how to use provider aws with alias and reference it in the parent child module providers which I will cover in the deep in some next post.

provider "aws" {
  alias  = "east"
  region = "us-east-1"
}

resource "aws_instance" "example" {
  provider = aws.east
  # ...
}

######################################

#For child Module how to set alias provider
module "aws_vpc" {
  source = "./aws_vpc"
  providers = {
    aws = aws.east
  }
  # ...
}

#For parent module how to set alias provider
terraform {
  required_providers {
    aws = {
      source                = "hashicorp/aws"
      version               = "~> 3.0"
      configuration_aliases = [aws.alternate]
    }
  }
}

Useful Articles
Terraform refactoring moved block example
Terraform create Azure Virtual Machines from map of objects
Terraform variable validation example
Configure Azure Storage Account Blob as Terraform backend to store tfstate file Examples of most used general purpose terraform functions
Create storage account and Service Principal using PowerShell for Terraform Azure Backend
Unlocking TF State File on Azure backend with PowerShell and Terraform Force-Unlock Command
Azure DevOps Enable creation of classic build release pipelines grayed out
Adding parameters in Azure DevOps pipelines examples Part 1
Azure Web App Containers Cannot perform credential operations for providers Microsoft.ContainerRegistry ad admin user is disabled, enable it

 

Go Back

Comment

Blog Search

Page Views

12086168

Follow me on Blogarama