Note
This repository is publicly accessible as part of our open-source initiative. We welcome contributions from the community alongside our organization's primary development efforts.
This Terraform module is composed of several submodules, which are combined in the primary module to provide a complete solution. Each submodule can also be deployed independently—see ./modules/ for details.
For a typical deployment, refer to the quick start Usage example below or the examples provided in each submodule's documentation.
The module enables you to quickly and easily deploy a comprehensive AI stack on Azure, supporting everything from initial AI development to production- and enterprise-ready solutions.
We apply the highest security standards regarding networking and authentication. By default, all Azure services in this module have API key support disabled and communicate securely via Azure Identities (Entra ID Service Principals).
Note
This module uses both azurerm
provider and azapi
provider resources for Azure AI services that are not yet fully supported by the azurerm
provider. You must configure the azapi
provider, especially authentication, in your root module.
Caution
Once the azurerm
provider fully supports all required resources for this module, we will migrate from azapi
resources to azurerm
resources. This will introduce breaking changes and will be released as a new major version in accordance with semantic versioning.
Important
By default (create_rbac = true
), this module creates all necessary Azure role assignments to enable secure communication between services. Assigning Azure roles requires Owner permissions on the resource group where the AI stack is deployed. If you do not have these permissions, you can disable role assignment creation (create_rbac = false
). In this case, you must manually create the required Azure role assignments for the various AI service identities to ensure proper functionality.
The following role assignments are created to enable communication between AI services:
Role | Scope | Principal |
---|---|---|
Cognitive Services OpenAI Contributor | AI Service | AI Search Service Identity |
Search Index Data Reader | AI Search Service | AI Service Identity |
Search Service Contributor | AI Search Service | AI Service Identity |
Storage Blob Data Contributor | Storage Account | AI Service Identity |
Storage Blob Data Reader | Storage Account | AI Search Service Identity |
Tip
You will likely want to set the ai_developer_principal_id
variable to grant an Entra ID group or user access to the AI stack and permissions on the individual Azure AI services.
If ai_developer_principal_id
is set (optional), the following roles are assigned to the specified principal:
Role | Scope |
---|---|
Azure AI Developer | AI Foundry Hub |
Azure AI Developer | AI Foundry Project |
Contributor | Developer Resource Group |
Storage Blob Data Contributor | Storage Account |
Storage File Data Privileged Contributor | Storage Account |
Cognitive Services Contributor | AI Service |
Cognitive Services OpenAI Contributor | AI Service |
Cognitive Services User | AI Service |
User Access Administrator | AI Service |
Search Index Data Contributor | AI Search Service |
Search Service Contributor | AI Search Service |
This module creates a dedicated developer resource group, granting the specified group or user (ai_developer_principal_id
) Owner permissions. This ensures that AI developers can create additional resources without mixing them into the main resource group (resource_group_name
) where the module's Terraform resources are deployed. The developer resource group can be disabled if not needed.◊
The following resources were referenced during the development of this module and may be helpful for further module development:
- https://learn.microsoft.com/en-us/azure/templates/microsoft.machinelearningservices/2024-10-01-preview/workspaces?pivots=deployment-language-terraform
- https://learn.microsoft.com/en-us/azure/ai-studio/how-to/configure-private-link
- https://learn.microsoft.com/en-us/azure/ai-studio/how-to/secure-data-playground
- https://learn.microsoft.com/en-us/azure/machine-learning/how-to-managed-network
- https://learn.microsoft.com/en-us/azure/ai-studio/concepts/rbac-ai-studio
- https://learn.microsoft.com/en-us/azure/ai-studio/tutorials/deploy-chat-web-app
- https://learn.microsoft.com/en-us/azure/ai-services/cognitive-services-virtual-networks
- https://learn.microsoft.com/en-us/azure/ai-services/disable-local-auth
- https://learn.microsoft.com/en-us/azure/templates/microsoft.search/2025-02-01-preview/searchservices
- https://github.com/MicrosoftDocs/azure-ai-docs/blob/main/articles/ai-services/openai/how-to/use-web-app.md
- https://github.com/microsoft/sample-app-aoai-chatGPT?tab=readme-ov-file#using-microsoft-entra-id
- https://journeyofthegeek.com/2025/01/08/ai-foundry-the-basics/
- https://journeyofthegeek.com/2025/01/13/ai-foundry-credential-vs-identity-data-stores/
- https://journeyofthegeek.com/2025/01/27/ai-foundry-identity-authentication-and-authorization/
- https://www.georgeollis.com/using-managed-private-endpoints-in-azure-ai-foundry/
- https://github.com/Azure/terraform-azurerm-avm-res-machinelearningservices-workspace
- https://github.com/Azure/terraform-azurerm-avm-ptn-ai-foundry-enterprise
This example demonstrates the usage of this Terraform module with default settings.
data "http" "my_current_public_ip" { url = "https://ipv4.icanhazip.com" }
resource "azurerm_resource_group" "example" {
location = "swedencentral"
name = "rg-example-dev-swec-01"
}
module "example" {
source = "cloudeteer/ai-stack/azurerm"
basename = trimprefix(azurerm_resource_group.example.name, "rg-")
location = azurerm_resource_group.example.location
resource_group_name = azurerm_resource_group.example.name
public_network_access = true
allowed_ips = [chomp(data.http.my_current_public_ip.response_body)]
# Enables the creation of role assignments for AI Services to interact via
# Entra ID (Managed Identities). Requires the user to have at least the
# Owner role on the resource group. If disabled, role assignments must be
# created manually. See the 'create_rbac' input variable for details.
# create_rbac = true # (default)
}
The following providers are used by this module:
- azurerm (>= 4.14)
The following Modules are called:
Source: ./modules/ai-foundry-core
Version:
Source: ./modules/ai-foundry-services
Version:
The following resources are used by this module:
- azurerm_client_config.current (data source)
The following input variables are required:
Description: The basename of all resources deployed by this module. Please use only 28 characters or less.
Type: string
Description: The resource group where the resources will be deployed.
Type: string
The following input variables are optional (have default values):
Description: The principal ID of a user or group of AI Developers who will have access to this AI Foundry Hub.
The following roles will be assigned to the given principal ID:
Role | Scope |
---|---|
Azure AI Developer | AI Foundry Hub |
Azure AI Developer | AI Foundry Project |
Contributor | Developer Resource Group |
Storage Blob Data Contributor | Storage Account |
Storage File Data Privileged Contributor | Storage Account |
Cognitive Services Contributor | AI Service |
Cognitive Services OpenAI Contributor | AI Service |
Cognitive Services User | AI Service |
User Access Administrator | AI Service |
Search Index Data Contributor | AI Search Service |
Search Service Contributor | AI Search Service |
Argument | Description |
---|---|
isolation_mode |
Isolation mode for the managed network of a machine learning workspace. Possible values are AllowOnlyApprovedOutbound , AllowInternetOutbound , or Disabled . |
public_network_access |
Whether requests from Public Network are allowed. |
NOTE: The User Access Administrator
role is assigned with the condition that only the Cognitive Services OpenAI User
role can be assigned to user principals. This is necessary to successfully deploy a Web App on top of an AI Model through the AI Foundry Hub.
Type: string
Default: null
Description: List of IP addresses to allow access to the Azure AI service.
Type: list(string)
Default: []
Description: If set to true
(default), the following mandatory Azure role assignments will be created:
Role | Scope | Principal |
---|---|---|
Cognitive Services OpenAI Contributor | AI Service | AI Search Service Identity |
Search Index Data Reader | AI Search Service | AI Service Identity |
Search Service Contributor | AI Search Service | AI Service Identity |
Storage Blob Data Contributor | Storage Account | AI Service Identity |
Storage Blob Data Reader | Storage Account | AI Search Service Identity |
NOTE: If set to false
, these role assignments must be created manually to ensure the AI Foundry Hub Project functions correctly.
Type: bool
Default: true
Description: The description of this workspace.
Type: string
Default: null
Description: The friendly name for this workspace. This value in mutable.
Type: string
Default: null
Description: Network configuration for the AI Hub.
Optional arguments:
Argument | Description |
---|---|
isolation_mode |
Isolation mode for the managed network of a machine learning workspace. Possible values are AllowOnlyApprovedOutbound , AllowInternetOutbound , or Disabled . |
public_network_access |
Whether requests from Public Network are allowed. |
NOTE:
Type:
object({
isolation_mode = optional(string, "AllowOnlyApprovedOutbound")
public_network_access = optional(bool, false)
})
Default: {}
Description: Specifies whether the services allows authentication using local API keys.
Type: bool
Default: true
Description: Location of the resource group.
Type: string
Default: "swedencentral"
Description: A list of models to deploy to the workspace.
Required parameters:
Parameter | Description |
---|---|
name |
The name of the Cognitive Services Account Deployment model. Changing this forces a new resource to be created. |
Optional parameters:
Parameter | Description |
---|---|
deployment_name |
The name to assign to the model deployment. If not specified, the value of name will be used by default. This property allows you to customize the deployment resource name independently from the model name. |
format |
The format of the Cognitive Services Account Deployment model. Changing this forces a new resource to be created. Possible value is OpenAI . |
sku_capacity |
Tokens-per-Minute (TPM). The unit of measure for this field is in the thousands of Tokens-per-Minute. Defaults to 1 which means that the limitation is 1000 tokens per minute. If the resources SKU supports scale in/out then the capacity field should be included in the resources' configuration. If the scale in/out is not supported by the resources SKU then this field can be safely omitted. For more information about TPM please see the product documentation. |
sku_name |
The name of the SKU. Possible values include Standard , DataZoneStandard , DataZoneProvisionedManaged , GlobalBatch , GlobalProvisionedManaged , GlobalStandard , and ProvisionedManaged . |
version |
The version of Cognitive Services Account Deployment model. If version is not specified, the default version of the model at the time will be assigned. |
Note: DataZoneProvisionedManaged
, GlobalProvisionedManaged
, and ProvisionedManaged
are purchased on-demand at an hourly basis based on the number of deployed PTUs, with substantial term discount available via the purchase of Azure Reservations. Currently, this step cannot be completed using Terraform. For more details, please refer to the provisioned throughput onboarding documentation.
Type:
list(object({
name = string
deployment_name = optional(string)
format = optional(string)
sku_capacity = optional(number)
sku_name = optional(string)
version = optional(string)
}))
Default: []
Description: Allow Public Access on AI Services, Storage Account, Key Vault, etc.
Type: bool
Default: false
Description: The SKU which should be used for this Search Service. Possible values include basic, free, standard, standard2, standard3, storage_optimized_l1 and storage_optimized_l2. Changing this forces a new Search Service to be created. Some SKU´s may with some restrictions. See https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/search_service#sku-1
Type: string
Default: "standard"
Description: The sku name of the Azure Analysis Services server to create. Choose from: B1, B2, D1, S0, S1, S2, S3, S4, S8, S9. Some skus are region specific. See https://docs.microsoft.com/en-us/azure/analysis-services/analysis-services-overview#availability-by-region
Type: string
Default: "S0"
The following outputs are exported:
Description: The endpoint of the AI service
Description: The ID of the AI service
Description: The Azure Foundry Hub ID
Description: The management URL for the AI Foundry Hub on the Azure AI platform
Description: The principal ID of the managed identity assigned to the Azure Foundry Hub
Description: The Azure Key Vault ID
Description: The Azure Foundry Project ID
Description: The management URL for the AI Foundry Project on the Azure AI platform
Description: The principal ID of the managed identity assigned to the Azure Foundry Project
Description: The URL to access the AI Foundry Project on the Azure AI platform
Description: The ID of the AI service
Description: The name of the AI service
Description: The principal ID of the managed identity assigned to the Azure AI Search Service
We welcome all kinds of contributions, whether it's reporting bugs, submitting feature requests, or directly contributing to the development. Please read our Contributing Guidelines to learn how you can best contribute.
Thank you for your interest and support!
© 2024 CLOUDETEER GmbH
This project is licensed under the MIT License.