CodingIsMyPassion
CodingIsMyPassion

Reputation: 37

Connect Azure Email Communication Service to Azure Communication Service using Terraform

I'm trying to set up new Azure resources, Azure Email Communication Service(AECS) and Azure Communication Service(ACS). Is there a way to connect AECS to ACS only using Terraform?

I want to do this https://mailtrap.io/blog/azure-send-email/ not using Azure UI, programatically on Terraform.

I also want to set up custom domain and get verified for my email services using terraform. Is it possible?

Thanks!

I searched online, but didn't find any resource.

Upvotes: 2

Views: 920

Answers (2)

Onisim Iacob
Onisim Iacob

Reputation: 51

I just wrote a medium article on how to handle the creation with both azure managed domain and custom domain using Terraform. There is little to no documentation about this so I'm glad that now there is at least a TF code that works :D

But basically the code is this. The variables and the rest of the stuff is explained on the link above.

# Create the resource group
resource "azurerm_resource_group" "rg" {
  name     = "${local.name}-rg"
  location = var.location
}

# Random ID for the Communication Service
resource "random_id" "name" {
  byte_length = 8
}

# Create the Communication Service
resource "azurerm_communication_service" "acs" {
  name                = var.enable_custom_domain == false ? "AzureManagedDomain${random_id.name.hex}" : split(".", var.custom_domain)[0]
  resource_group_name = azurerm_resource_group.rg.name
  data_location       = var.data_location
}

# Create the Email Communication Service
resource "azurerm_email_communication_service" "acs-email" {
  name                = var.enable_custom_domain == false ? "AzureManagedDomain${random_id.name.hex}" : split(".", var.custom_domain)[0]
  resource_group_name = azurerm_resource_group.rg.name
  data_location       = var.data_location
}

# Create the Email Communication Service Domain
resource "azurerm_email_communication_service_domain" "email_domain" {
  name             = var.enable_custom_domain == false ? "AzureManagedDomain" : var.custom_domain
  email_service_id = azurerm_email_communication_service.acs-email.id

  domain_management = var.enable_custom_domain == false ? "AzureManaged" : "CustomerManaged"
}

# Define TXT Records for Domain Verification
resource "azurerm_dns_txt_record" "domain" {
  count               = var.enable_custom_domain == false ? 0 : 1
  name                = "@" #element(azurerm_email_communication_service_domain.email_domain.verification_records[0].domain[*].name, count.index)
  zone_name           = var.custom_domain
  resource_group_name = var.custom_domain_rg
  ttl                 = element(azurerm_email_communication_service_domain.email_domain.verification_records[0].domain[*].ttl, count.index)

  # Record for Domain Verification
  record {
    value = element(azurerm_email_communication_service_domain.email_domain.verification_records[0].domain[*].value, count.index)
  }

  # Record for SPF Verification
  record {
    value = element(azurerm_email_communication_service_domain.email_domain.verification_records[0].spf[*].value, count.index)
  }
  depends_on = [azurerm_email_communication_service_domain.email_domain]
}

# Define CNAME DKIM Records
resource "azurerm_dns_cname_record" "dkim" {
  count               = var.enable_custom_domain == false ? 0 : 1
  name                = element(azurerm_email_communication_service_domain.email_domain.verification_records[0].dkim[*].name, count.index)
  zone_name           = var.custom_domain
  resource_group_name = var.custom_domain_rg
  ttl                 = element(azurerm_email_communication_service_domain.email_domain.verification_records[0].dkim[*].ttl, count.index)
  record              = element(azurerm_email_communication_service_domain.email_domain.verification_records[0].dkim[*].value, count.index)
  depends_on          = [azurerm_email_communication_service_domain.email_domain]
}

# Define CNAME DKIM2 Records
resource "azurerm_dns_cname_record" "dkim2" {
  count               = var.enable_custom_domain == false ? 0 : 1
  name                = element(azurerm_email_communication_service_domain.email_domain.verification_records[0].dkim2[*].name, count.index)
  zone_name           = var.custom_domain
  resource_group_name = var.custom_domain_rg
  ttl                 = element(azurerm_email_communication_service_domain.email_domain.verification_records[0].dkim2[*].ttl, count.index)
  record              = element(azurerm_email_communication_service_domain.email_domain.verification_records[0].dkim2[*].value, count.index)
  depends_on          = [azurerm_email_communication_service_domain.email_domain]
}

# Initiate Domain Verification
# Horrendous API: https://learn.microsoft.com/en-us/rest/api/communication/resourcemanager/domains/initiate-verification?view=rest-communication-resourcemanager-2023-03-31&tabs=HTTP
resource "azapi_resource_action" "validate_domain" {
  count       = var.enable_custom_domain == false ? 0 : 1
  type        = "Microsoft.Communication/emailServices/domains@2023-03-31"
  action      = "initiateVerification"
  resource_id = azurerm_email_communication_service_domain.email_domain.id

  body = jsonencode({
    verificationType = "Domain" # or use "SPF", "DKIM", "DMARC", "DKIM2" as needed
  })
  depends_on = [azurerm_dns_txt_record.domain]
}

# Initiate SPF Verification
resource "azapi_resource_action" "validate_spf" {
  count       = var.enable_custom_domain == false ? 0 : 1
  type        = "Microsoft.Communication/emailServices/domains@2023-03-31"
  action      = "initiateVerification"
  resource_id = azurerm_email_communication_service_domain.email_domain.id

  body = jsonencode({
    verificationType = "SPF" # or use "SPF", "DKIM", "DMARC", "DKIM2" as needed
  })
  depends_on = [azapi_resource_action.validate_domain]
}

# Initiate DKIM Verification
resource "azapi_resource_action" "validate_dkim" {
  count       = var.enable_custom_domain == false ? 0 : 1
  type        = "Microsoft.Communication/emailServices/domains@2023-03-31"
  action      = "initiateVerification"
  resource_id = azurerm_email_communication_service_domain.email_domain.id

  body = jsonencode({
    verificationType = "DKIM" # or use "SPF", "DKIM", "DMARC", "DKIM2" as needed
  })
  depends_on = [azapi_resource_action.validate_spf]
}

# Initiate DKIM2 Verification
resource "azapi_resource_action" "validate_dkim2" {
  count       = var.enable_custom_domain == false ? 0 : 1
  type        = "Microsoft.Communication/emailServices/domains@2023-03-31"
  action      = "initiateVerification"
  resource_id = azurerm_email_communication_service_domain.email_domain.id

  body = jsonencode({
    verificationType = "DKIM2" # or use "SPF", "DKIM", "DMARC", "DKIM2" as needed
  })
  depends_on = [azapi_resource_action.validate_dkim]
}

# Association of the Email Domain with the Communication Service
resource "azurerm_communication_service_email_domain_association" "email_domain_association" {
  communication_service_id = azurerm_communication_service.acs.id
  email_service_domain_id  = azurerm_email_communication_service_domain.email_domain.id
  depends_on = [
    azapi_resource_action.validate_dkim2
  ]
}

# Create a sender username
# resource "azapi_resource" "no_reply_user" {
#   type      = "Microsoft.Communication/emailServices/domains/senderUsernames@2023-04-01-preview"
#   name      = "no_reply"
#   parent_id = azurerm_email_communication_service_domain.email_domain.id
#   body = jsonencode({
#     properties = {
#       displayName = "no_reply"
#       username    = "no_reply"
#     }
#   })
# }

I hope this helps!

Upvotes: 5

Jahnavi
Jahnavi

Reputation: 7898

To connect Azure Email Communication Service to Azure Communication Service, there is no direct service provider registered for it. Instead, you can use azapi_update_resource as detailed below.

Firstly, I have created a communication service and an email communication service with terraform and referenced them in the azapi_update_resource with below configuration.

terraform {
  required_providers {
    azapi = {
      source = "Azure/azapi"
      version = "1.13.1"
    }
  }
}
provider "azapi" {}
provider "azurerm"{
features{}
}
resource "azurerm_communication_service" "example" {
  name                = "jahcomm"
  resource_group_name = data.azurerm_resource_group.example.name
  data_location       = "United States"
}
resource "azurerm_email_communication_service" "example" {
  name                = "jah-emailcommunicationservice"
  resource_group_name = data.azurerm_resource_group.example.name
  data_location       = "United States"
}

Communication service and an email service has been deployed.

enter image description here

enter image description here

Now I have used azapi_update_resource to link the services with a domain as shown below.

resource "azapi_update_resource" "update" {
  type      = "Microsoft.Communication/communicationServices@2022-07-01-preview"
  resource_id = data.azurerm_communication_service.example.id

  body = jsonencode({
    properties = {
      linkedDomains = [
        "/subscriptions/xxxx/resourceGroups/xxxx/providers/Microsoft.Communication/EmailServices/jah-emailcommunicationservice/domains/AzureManagedDomain"
      ]    
    }
  })
}

Deployment succeeded:

enter image description here

enter image description here

Refer Github issue for the relevant information.

Upvotes: 3

Related Questions