modules/terraform/setup/infrastructure/main.tf (171 lines of code) (raw):
terraform {
required_version = ">=1.5.6"
required_providers {
azuredevops = {
source = "microsoft/azuredevops"
version = ">=0.2.0"
}
aws = {
source = "hashicorp/aws"
version = "<= 5.38"
}
azurerm = {
source = "hashicorp/azurerm"
version = "<= 3.93.0"
}
azuread = {
source = "hashicorp/azuread"
version = "~> 2.15.0"
}
}
}
provider "azurerm" {
features {}
storage_use_azuread = true
}
provider "aws" {
region = var.aws_config.region
}
provider "azuredevops" {
}
data "azurerm_subscription" "subscription" {
subscription_id = var.azure_config.subscription_id
}
provider "azuread" {
tenant_id = data.azurerm_subscription.subscription.tenant_id
}
data "azuredevops_project" "ado_project" {
name = var.azuredevops_config.project_name
}
## Step 1: Set up Github service connection
resource "azuredevops_serviceendpoint_github" "github_service_connection" {
project_id = data.azuredevops_project.ado_project.id
service_endpoint_name = var.github_config.service_connection_name
description = var.github_config.service_connection_description
auth_personal {
personal_access_token = null
}
}
## Step 2: Set up service connection to Azure
resource "azuredevops_serviceendpoint_azurerm" "azure_service_connection" {
project_id = data.azuredevops_project.ado_project.id
service_endpoint_name = var.azure_config.service_connection_name
description = var.azure_config.service_connection_description
service_endpoint_authentication_scheme = "WorkloadIdentityFederation"
azurerm_spn_tenantid = data.azurerm_subscription.subscription.tenant_id
azurerm_subscription_id = data.azurerm_subscription.subscription.subscription_id
azurerm_subscription_name = data.azurerm_subscription.subscription.display_name
}
## Step 3: Set up resource group and grant service principal permission in Azure
# Locals for tags
locals {
tags = var.tags
database_config_map = {
for db in var.azure_config.kusto_cluster.kusto_databases : db.name => db
}
}
# Service Principal
data "azuread_service_principal" "service_principal" {
application_id = azuredevops_serviceendpoint_azurerm.azure_service_connection.service_principal_id
}
# Role Assignment
resource "azurerm_role_assignment" "subscription_owner_role_assignment" {
role_definition_name = "owner"
scope = data.azurerm_subscription.subscription.id
principal_id = data.azuread_service_principal.service_principal.object_id
}
# Azure Resource Group
resource "azurerm_resource_group" "rg" {
name = var.resource_group_name
location = var.azure_config.resource_group.location
tags = local.tags
}
# Storage Account
resource "azurerm_storage_account" "storage" {
name = var.storage_account_name
resource_group_name = azurerm_resource_group.rg.name
location = azurerm_resource_group.rg.location
account_tier = var.azure_config.storage_account.account_tier
account_replication_type = var.azure_config.storage_account.account_replication_type
shared_access_key_enabled = var.azure_config.storage_account.shared_access_key_enabled
tags = local.tags
}
# Storage Role Assignment
resource "azurerm_role_assignment" "storage_blob_contributor_role_assignment" {
role_definition_name = "Storage Blob Data Contributor"
scope = azurerm_storage_account.storage.id
principal_id = data.azuread_service_principal.service_principal.object_id
}
# Storage Container
resource "azurerm_storage_container" "container" {
for_each = local.database_config_map
name = replace(each.key, "_", "-")
storage_account_name = azurerm_storage_account.storage.name
}
# Event Hub Namespace
resource "azurerm_eventhub_namespace" "eventhub_ns" {
name = "ADX-EG-telescope-${formatdate("MM-DD-YYYY-hh-mm-ss", timestamp())}"
location = azurerm_resource_group.rg.location
resource_group_name = azurerm_resource_group.rg.name
sku = "Standard"
capacity = 1
tags = local.tags
}
# Kusto Cluster
resource "azurerm_kusto_cluster" "cluster" {
name = var.kusto_cluster_name
resource_group_name = azurerm_resource_group.rg.name
location = var.azure_config.kusto_cluster.location != null ? var.azure_config.kusto_cluster.location : azurerm_resource_group.rg.location
sku {
name = var.azure_config.kusto_cluster.sku.name
capacity = var.azure_config.kusto_cluster.sku.capacity
}
identity {
type = "SystemAssigned"
}
tags = local.tags
}
# Storage Role Assignment for Kusto Cluster
resource "azurerm_role_assignment" "storage_blob_contributor_role_assignment_for_kusto_cluster" {
role_definition_name = "Storage Blob Data Contributor"
scope = azurerm_storage_account.storage.id
principal_id = azurerm_kusto_cluster.cluster.identity[0].principal_id
}
# Kusto Role Assignment
resource "azurerm_kusto_cluster_principal_assignment" "kusto_role_assignment" {
name = data.azuread_service_principal.service_principal.display_name
resource_group_name = azurerm_resource_group.rg.name
cluster_name = azurerm_kusto_cluster.cluster.name
tenant_id = data.azuread_service_principal.service_principal.application_tenant_id
principal_id = data.azuread_service_principal.service_principal.object_id
principal_type = "App"
role = "AllDatabasesAdmin"
}
# Kusto Database
resource "azurerm_kusto_database" "database" {
for_each = local.database_config_map
name = each.key
resource_group_name = azurerm_resource_group.rg.name
cluster_name = azurerm_kusto_cluster.cluster.name
location = var.azure_config.kusto_cluster.location != null ? var.azure_config.kusto_cluster.location : azurerm_resource_group.rg.location
hot_cache_period = each.value.hot_cache_period
soft_delete_period = each.value.soft_delete_period
}
## Step 3: Set up AWS IAM User and Access Key
# AWS IAM User
resource "aws_iam_user" "user" {
name = var.aws_config.user_name
path = "/"
}
resource "aws_iam_user_policy_attachment" "user_policy_attachment" {
count = length(var.aws_config.policy_names)
user = aws_iam_user.user.name
policy_arn = "arn:aws:iam::aws:policy/${var.aws_config.policy_names[count.index]}"
}
# AWS IAM Access Key
resource "aws_iam_access_key" "access_key" {
user = aws_iam_user.user.name
}
## Step 4: Set up service connection to AWS
resource "azuredevops_serviceendpoint_aws" "aws_service_connection" {
project_id = data.azuredevops_project.ado_project.id
service_endpoint_name = var.aws_config.service_connection_name
description = var.aws_config.service_connection_description
secret_access_key = aws_iam_access_key.access_key.secret
access_key_id = aws_iam_access_key.access_key.id
}
# Azure DevOps Non-Secret Variable Groups
resource "azuredevops_variable_group" "variable_groups" {
for_each = { for group in var.azuredevops_config.variable_groups : group.name => group }
project_id = data.azuredevops_project.ado_project.id
name = each.value.name
description = each.value.description
allow_access = each.value.allow_access
dynamic "variable" {
for_each = each.value.variables
content {
name = variable.value.name
value = variable.value.value
}
}
}