main.tf 10.6 KB
Newer Older
Daniel Scholl's avatar
Daniel Scholl committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//  Copyright © Microsoft Corporation
//
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.


/*
.Synopsis
   Terraform Main Control
.DESCRIPTION
   This file holds the main control.
*/

// *** WARNING  ****
// This template includes locks and won't delete by destroy if locks aren't removed first.
Daniel Scholl's avatar
Daniel Scholl committed
25
26
// Lock: Storage
// Lock: Graph DB
Daniel Scholl's avatar
Daniel Scholl committed
27
28
29
// *** WARNING  ****

terraform {
Daniel Scholl's avatar
Daniel Scholl committed
30
31
  required_version = ">= 0.14"

Daniel Scholl's avatar
Daniel Scholl committed
32
33
34
  backend "azurerm" {
    key = "terraform.tfstate"
  }
Daniel Scholl's avatar
Daniel Scholl committed
35
36
37
38

  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
39
      version = "=2.64.0"
Daniel Scholl's avatar
Daniel Scholl committed
40
41
42
43
44
45
46
47
48
49
50
51
52
53
    }
    azuread = {
      source  = "hashicorp/azuread"
      version = "=1.1.1"
    }
    random = {
      source  = "hashicorp/random"
      version = "=2.3.1"
    }
    null = {
      source  = "hashicorp/null"
      version = "=3.0.0"
    }
  }
Daniel Scholl's avatar
Daniel Scholl committed
54
55
}

Daniel Scholl's avatar
Daniel Scholl committed
56

Daniel Scholl's avatar
Daniel Scholl committed
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
#-------------------------------
# Providers
#-------------------------------
provider "azurerm" {
  features {}
}


#-------------------------------
# Private Variables
#-------------------------------
locals {
  // sanitize names
  prefix    = replace(trimspace(lower(var.prefix)), "_", "-")
  workspace = replace(trimspace(lower(terraform.workspace)), "-", "")
  suffix    = var.randomization_level > 0 ? "-${random_string.workspace_scope.result}" : ""

  // base prefix for resources, prefix constraints documented here: https://docs.microsoft.com/en-us/azure/architecture/best-practices/naming-conventions
  base_name    = length(local.prefix) > 0 ? "${local.prefix}-${local.workspace}${local.suffix}" : "${local.workspace}${local.suffix}"
  base_name_21 = length(local.base_name) < 22 ? local.base_name : "${substr(local.base_name, 0, 21 - length(local.suffix))}${local.suffix}"
  base_name_46 = length(local.base_name) < 47 ? local.base_name : "${substr(local.base_name, 0, 46 - length(local.suffix))}${local.suffix}"
  base_name_60 = length(local.base_name) < 61 ? local.base_name : "${substr(local.base_name, 0, 60 - length(local.suffix))}${local.suffix}"
  base_name_76 = length(local.base_name) < 77 ? local.base_name : "${substr(local.base_name, 0, 76 - length(local.suffix))}${local.suffix}"
  base_name_83 = length(local.base_name) < 84 ? local.base_name : "${substr(local.base_name, 0, 83 - length(local.suffix))}${local.suffix}"

  resource_group_name = format("%s-%s-%s-rg", var.prefix, local.workspace, random_string.workspace_scope.result)
  retention_policy    = var.log_retention_days == 0 ? false : true

  kv_name                 = "${local.base_name_21}-kv"
  storage_name            = "${replace(local.base_name_21, "-", "")}tbl"
87
  graphdb_name            = "${local.base_name}-graph"
Daniel Scholl's avatar
Daniel Scholl committed
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
  container_registry_name = "${replace(local.base_name_21, "-", "")}cr"
  osdupod_identity_name   = "${local.base_name}-osdu-identity"
  ai_name                 = "${local.base_name}-ai"
  logs_name               = "${local.base_name}-logs"
  ad_app_name             = "${local.base_name}-app"

  rbac_contributor_scopes = concat(
    [module.container_registry.container_registry_id],
    [module.keyvault.keyvault_id]
  )
  role = "Contributor"
  rbac_principals = [
    azurerm_user_assigned_identity.osduidentity.principal_id,
    module.service_principal.id
  ]
}


#-------------------------------
# Common Resources
#-------------------------------
data "azurerm_client_config" "current" {}

resource "random_string" "workspace_scope" {
  keepers = {
    # Generate a new id each time we switch to a new workspace or app id
    ws_name = replace(trimspace(lower(terraform.workspace)), "-", "")
    prefix  = replace(trimspace(lower(var.prefix)), "_", "-")
  }

  length  = max(1, var.randomization_level) // error for zero-length
  special = false
  upper   = false
}

Daniel Scholl's avatar
Daniel Scholl committed
123

Daniel Scholl's avatar
Daniel Scholl committed
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
#-------------------------------
# Resource Group
#-------------------------------
resource "azurerm_resource_group" "main" {
  name     = local.resource_group_name
  location = var.resource_group_location
  tags     = var.resource_tags

  lifecycle {
    ignore_changes = [tags]
  }
}


#-------------------------------
# Key Vault
#-------------------------------
module "keyvault" {
  source = "../../../modules/providers/azure/keyvault"

  keyvault_name       = local.kv_name
  resource_group_name = azurerm_resource_group.main.name
  secrets = {
    app-dev-sp-tenant-id = data.azurerm_client_config.current.tenant_id
  }

  resource_tags = var.resource_tags
}

module "keyvault_policy" {
Daniel Scholl's avatar
Daniel Scholl committed
154
155
  source = "../../../modules/providers/azure/keyvault-policy"

Daniel Scholl's avatar
Daniel Scholl committed
156
157
158
159
160
161
  vault_id  = module.keyvault.keyvault_id
  tenant_id = data.azurerm_client_config.current.tenant_id
  object_ids = [
    azurerm_user_assigned_identity.osduidentity.principal_id,
    module.service_principal.id
  ]
162
  key_permissions         = ["get", "encrypt", "decrypt"]
163
  certificate_permissions = ["get", "update", "import"]
Daniel Scholl's avatar
Daniel Scholl committed
164
165
166
167
168
169
170
171
172
173
174
  secret_permissions      = ["get"]
}

resource "azurerm_role_assignment" "kv_roles" {
  count = length(local.rbac_principals)

  role_definition_name = "Reader"
  principal_id         = local.rbac_principals[count.index]
  scope                = module.keyvault.keyvault_id
}

Daniel Scholl's avatar
Daniel Scholl committed
175

Daniel Scholl's avatar
Daniel Scholl committed
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
#-------------------------------
# Storage
#-------------------------------
module "storage_account" {
  source = "../../../modules/providers/azure/storage-account"

  name                = local.storage_name
  resource_group_name = azurerm_resource_group.main.name
  container_names     = []
  kind                = "StorageV2"
  replication_type    = var.storage_replication_type

  resource_tags = var.resource_tags
}

// Add Access Control to Principal
resource "azurerm_role_assignment" "storage_access" {
  count = length(local.rbac_principals)

  role_definition_name = local.role
  principal_id         = local.rbac_principals[count.index]
  scope                = module.storage_account.id
}

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
#-------------------------------
# CosmosDB
#-------------------------------
module "graph_account" {
  source = "../../../modules/providers/azure/cosmosdb"

  name                     = local.graphdb_name
  resource_group_name      = azurerm_resource_group.main.name
  primary_replica_location = var.cosmosdb_replica_location
  automatic_failover       = var.cosmosdb_automatic_failover
  consistency_level        = var.cosmosdb_consistency_level
  graph_databases          = var.cosmos_graph_databases
  graphs                   = var.cosmos_graphs

  resource_tags = var.resource_tags
}

// Add Access Control to Principal
resource "azurerm_role_assignment" "graph_access" {
  count = length(local.rbac_principals)

  role_definition_name = "Contributor"
  principal_id         = local.rbac_principals[count.index]
  scope                = module.graph_account.account_id
}

Daniel Scholl's avatar
Daniel Scholl committed
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

#-------------------------------
# Container Registry
#-------------------------------
module "container_registry" {
  source = "../../../modules/providers/azure/container-registry"

  container_registry_name = local.container_registry_name
  resource_group_name     = azurerm_resource_group.main.name

  container_registry_sku           = var.container_registry_sku
  container_registry_admin_enabled = false

  resource_tags = var.resource_tags
}


#-------------------------------
# Application Insights
#-------------------------------
module "app_insights" {
  source = "../../../modules/providers/azure/app-insights"

  appinsights_name                 = local.ai_name
  service_plan_resource_group_name = azurerm_resource_group.main.name
  appinsights_application_type     = "other"

  resource_tags = var.resource_tags
}


#-------------------------------
# Log Analytics
#-------------------------------
module "log_analytics" {
  source = "../../../modules/providers/azure/log-analytics"

  name                = local.logs_name
  resource_group_name = azurerm_resource_group.main.name

  solutions = [
    {
      solution_name = "ContainerInsights",
      publisher     = "Microsoft",
      product       = "OMSGallery/ContainerInsights",
    },
    {
      solution_name = "KeyVaultAnalytics",
      publisher     = "Microsoft",
      product       = "OMSGallery/KeyVaultAnalytics",
    }
  ]

  resource_tags = var.resource_tags
}


#-------------------------------
# AD Principal and Applications
#-------------------------------
module "service_principal" {
  source = "../../../modules/providers/azure/service-principal"

  name   = var.principal_name
  scopes = local.rbac_contributor_scopes
  role   = "Contributor"

  create_for_rbac = false
  object_id       = var.principal_objectId

  principal = {
    name     = var.principal_name
    appId    = var.principal_appId
    password = var.principal_password
  }
}


module "ad_application" {
Daniel Scholl's avatar
Daniel Scholl committed
305
306
  source = "../../../modules/providers/azure/ad-application"

Daniel Scholl's avatar
Daniel Scholl committed
307
308
  name                       = local.ad_app_name
  oauth2_allow_implicit_flow = true
Daniel Scholl's avatar
Daniel Scholl committed
309
310
  group_membership_claims    = "None"

Daniel Scholl's avatar
Daniel Scholl committed
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
342
343
344
345
  reply_urls = [
    "http://localhost:8080",
    "http://localhost:8080/auth/callback"
  ]

  api_permissions = [
    {
      name = "Microsoft Graph"
      oauth2_permissions = [
        "User.Read"
      ]
    }
  ]
}


#-------------------------------
# OSDU Identity
#-------------------------------
// Identity for OSDU Pod Identity
resource "azurerm_user_assigned_identity" "osduidentity" {
  name                = local.osdupod_identity_name
  resource_group_name = azurerm_resource_group.main.name
  location            = azurerm_resource_group.main.location

  tags = var.resource_tags
}


#-------------------------------
# Locks
#-------------------------------

// Lock the KV
resource "azurerm_management_lock" "kv_lock" {
Daniel Scholl's avatar
Daniel Scholl committed
346
347
  count = var.feature_flag.kv_lock ? 1 : 0

Daniel Scholl's avatar
Daniel Scholl committed
348
349
350
351
352
353
354
355
356
357
358
359
360
361
  name       = "osdu_cr_kv_lock"
  scope      = module.keyvault.keyvault_id
  lock_level = "CanNotDelete"
}

// Lock the Storage
resource "azurerm_management_lock" "sa_lock" {
  name       = "osdu_tbl_sa_lock"
  scope      = module.storage_account.id
  lock_level = "CanNotDelete"
}

// Lock the Container Registry
resource "azurerm_management_lock" "acr_lock" {
Daniel Scholl's avatar
Daniel Scholl committed
362
363
  count = var.feature_flag.acr_lock ? 1 : 0

Daniel Scholl's avatar
Daniel Scholl committed
364
365
366
367
  name       = "osdu_acr_lock"
  scope      = module.container_registry.container_registry_id
  lock_level = "CanNotDelete"
}
368
369
370
371
372
373
374

// Lock the GraphDB
resource "azurerm_management_lock" "graph_lock" {
  name       = "osdu_graph_db_lock"
  scope      = module.graph_account.account_id
  lock_level = "CanNotDelete"
}