Last reviewed: May 2026
Build the AWS services on the AI-900 exam with plain Terraform — one block at a time, each tied back to an exam domain. The same code works on OpenTofu.
By the end of this lab you'll have provisioned, with plain Terraform, the foundational Azure AI surface — a Resource Group, a multi-service Azure AI Services account (one key, all the AI APIs: Computer Vision, Language, Speech, Decision), a Storage Account for the inputs they'll consume, and a Diagnostic Setting that captures every AI API call to Log Analytics for governance review.
Every resource is plain Terraform. Drop the snippets into a single main.tf, run terraform init, then terraform apply step-by-step.
>= 1.5 or OpenTofu >= 1.6.az login).terraform apply fails on the AI account with a Responsible AI error, accept the terms via the Azure portal and re-run.Mostly free or very cheap:
Whole stack idles at < $1/month. Calling the AI APIs costs real money; destroy when done.
Standard Azure opener: pin azurerm ~> 4.0, the empty features {} block, and a random_id for globally-unique resource naming (AI Services accounts must be unique across all of Azure for their DNS name).
terraform {
required_version = ">= 1.5"
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "~> 4.0"
}
random = {
source = "hashicorp/random"
version = "~> 3.6"
}
}
}
provider "azurerm" {
features {}
}
resource "random_id" "suffix" {
byte_length = 2
}
locals {
tags = {
Project = "certlabpro-ai-900"
ManagedBy = "terraform"
}
}
resource "azurerm_resource_group" "main" {
name = "certlabpro-ai-900-rg"
location = "eastus"
tags = local.tags
}Almost every Azure AI scenario reads inputs from Azure Storage — images for Computer Vision, audio clips for Speech, text files for Language, training data for Custom models. We provision the storage account up front with secure defaults (HTTPS-only, TLS 1.2, public network access disabled, no public blob access).
The AI-900 Fundamentals of Machine Learning on Azure domain tests this Azure-Storage-as-the-data-substrate concept directly: any time the exam asks where AI training data lives, Azure Storage (or specifically Azure Blob Storage) is the answer.
resource "azurerm_storage_account" "ai_data" {
name = "ai900data${random_id.suffix.hex}"
resource_group_name = azurerm_resource_group.main.name
location = azurerm_resource_group.main.location
account_tier = "Standard"
account_replication_type = "LRS"
account_kind = "StorageV2"
https_traffic_only_enabled = true
min_tls_version = "TLS1_2"
public_network_access_enabled = false
allow_nested_items_to_be_public = false
tags = local.tags
}Azure AI Services (the rebranded Cognitive Services umbrella) gives you one key, one endpoint, and access to the full slate of AI APIs — Computer Vision, Language, Speech, Translator, Document Intelligence, Content Safety, and more. The single multi-service account is the AI-900 cost-anti-pattern question: it's more expensive per call than dedicated single-service accounts (Speech, Vision, Language each have their own free F0 tier), but it's much simpler to manage. AI-900 tests both shapes — the exam asks when you'd reach for which.
We set kind = "CognitiveServices" for the multi-service account and sku_name = "S0" for standard tier. The custom_subdomain_name is required for VNet integration (the AI-900 Responsible AI domain tests this as the prerequisite for private endpoints). local_auth_enabled = true keeps the API-key flow working; false would force Entra ID auth only.
resource "azurerm_cognitive_account" "ai" {
name = "certlabpro-ai-900-${random_id.suffix.hex}"
resource_group_name = azurerm_resource_group.main.name
location = azurerm_resource_group.main.location
kind = "CognitiveServices"
sku_name = "S0"
custom_subdomain_name = "certlabpro-ai-900-${random_id.suffix.hex}"
local_auth_enabled = true
identity {
type = "SystemAssigned"
}
tags = local.tags
}Responsible AI is an AI-900 pillar (one of five exam domains) — and the most concrete Responsible AI practice you can demonstrate with infrastructure is audit logging. We create a Log Analytics workspace as the diagnostic-log destination; in Step 5 we wire the AI account's diagnostic settings to send everything here.
Log Analytics is the central Azure observability service — Azure Monitor sends metrics here, Application Insights sends app telemetry here, Sentinel reads from here for SIEM. Provisioning it as the AI lab's audit destination doubles as a building block every other Azure cert assumes you'll have around.
resource "azurerm_log_analytics_workspace" "main" {
name = "certlabpro-ai-900-logs"
resource_group_name = azurerm_resource_group.main.name
location = azurerm_resource_group.main.location
sku = "PerGB2018"
retention_in_days = 30
tags = local.tags
}Diagnostic Settings are Azure's universal observability primitive: every Azure resource can stream its categorized logs and metrics to a Log Analytics workspace, an Event Hub, or a Storage Account. We turn on the AI account's Audit and RequestResponse log categories — Audit captures what was called, RequestResponse captures the actual request and response bodies (useful for incident response, scary if you have PII in prompts; AI-900 Responsible AI tests both halves of that trade-off).
With this final piece in place, every AI API call lands in the workspace from Step 4, queryable via KQL. That's the AI-900 closing the loop on Responsible AI: not just "we have a content filter" but "we have evidence of every request the AI saw".
resource "azurerm_monitor_diagnostic_setting" "ai" {
name = "certlabpro-ai-900-diag"
target_resource_id = azurerm_cognitive_account.ai.id
log_analytics_workspace_id = azurerm_log_analytics_workspace.main.id
enabled_log {
category = "Audit"
}
enabled_log {
category = "RequestResponse"
}
metric {
category = "AllMetrics"
enabled = true
}
}A standard terraform destroy tears down everything in this lab. Two notes:
random_id suffix usually dodges it.AI-900 covers Azure AI surfaces this lab can't fit — Azure OpenAI Service (covered in AI-102), Azure Machine Learning Studio + workspaces (DP-100), Bot Service, Computer Vision custom models, Custom Vision portal training, Language Studio's custom QnA and conversational language understanding, Document Intelligence custom models, Azure AI Search, Speech custom voice / pronunciation assessment, and the Responsible AI dashboard for ML interpretability.
We stick to the multi-service account + storage + audit logging primitives because they're the substrate every more-advanced Azure AI pattern attaches to. Once you understand how the multi-service account exposes the full API slate under one key, the per-service deep dives are easier to navigate.
For service-by-service conceptual coverage, see the Browse and Editorial sections of this cert page.