Desafio 02: Criar e Configurar Recursos do Azure AI
45 min | Custo: ~$0.50 | Domínio: Planejar e Gerenciar Soluções de IA (20-25%)
Habilidades do exame cobertas
- Criar um recurso do Azure AI
- Escolher modelos de IA apropriados
- Determinar o endpoint padrão de um serviço
- Configurar acesso de rede para recursos do Azure AI
- Gerenciar chaves e proteger o acesso aos recursos
Visão Geral
Criar e configurar recursos do Azure AI corretamente é a base de todo cenário do AI-102. Este desafio vai além de clicar em "Criar" no portal—você provisionará recursos programaticamente, configurará restrições de rede, recuperará e rotacionará chaves, e validará a conectividade do endpoint.
Entender a relação entre tipos de recursos, SKUs, endpoints e chaves é crítico. Um recurso multi-serviço expõe um único endpoint como https://<region>.api.cognitive.microsoft.com/ enquanto recursos de serviço único podem ter padrões de endpoint específicos do serviço. Você precisa saber qual formato de endpoint cada serviço usa e como configurar regras de rede virtual e private endpoints para cargas de trabalho de produção.
Este desafio também cobre a configuração de definições de diagnóstico, nomes de subdomínio personalizados (necessários para autenticação Microsoft Entra), e a diferença entre endpoints regionais e personalizados.
Arquitetura
Você criará recursos com subdomínios personalizados, configurará regras de rede, validará a conectividade e configurará logging de diagnóstico—simulando uma implantação de serviços de IA pronta para produção.
Pré-requisitos
- Assinatura Azure com role de Contributor
- Azure CLI 2.50+ instalado
- Python 3.9+ com
pipou .NET 8 SDK - Pacotes Python
azure-identity,azure-mgmt-cognitiveservices
Implementação
Tarefa 1: Criar um Recurso com Subdomínio Personalizado
- Python SDK
- C# SDK
- REST API
from azure.identity import DefaultAzureCredential
from azure.mgmt.cognitiveservices import CognitiveServicesManagementClient
from azure.mgmt.cognitiveservices.models import (
Account, Sku, AccountProperties, NetworkRuleSet, NetworkRuleAction
)
credential = DefaultAzureCredential()
subscription_id = "YOUR_SUBSCRIPTION_ID"
client = CognitiveServicesManagementClient(credential, subscription_id)
# Create with custom subdomain (required for Entra ID auth)
account = client.accounts.begin_create(
resource_group_name="rg-ai102-challenge02",
account_name="ai102-mycompany-ai",
account=Account(
sku=Sku(name="S0"),
kind="AIServices",
location="eastus",
properties=AccountProperties(
custom_sub_domain_name="ai102-mycompany-ai",
public_network_access="Enabled"
)
)
).result()
print(f"Resource: {account.name}")
print(f"Endpoint: {account.properties.endpoint}")
print(f"Custom domain: https://{account.properties.custom_sub_domain_name}.cognitiveservices.azure.com/")
using Azure.Identity;
using Azure.ResourceManager;
using Azure.ResourceManager.CognitiveServices;
using Azure.ResourceManager.CognitiveServices.Models;
var credential = new DefaultAzureCredential();
var client = new ArmClient(credential);
var subscription = await client.GetDefaultSubscriptionAsync();
var resourceGroup = await subscription
.GetResourceGroupAsync("rg-ai102-challenge02");
var collection = resourceGroup.Value.GetCognitiveServicesAccounts();
// Custom subdomain enables Entra ID authentication
var data = new CognitiveServicesAccountData(Azure.Core.AzureLocation.EastUS)
{
Kind = "CognitiveServices",
Sku = new CognitiveServicesSku("S0"),
Properties = new CognitiveServicesAccountProperties
{
CustomSubDomainName = "ai102-mycompany-ai",
PublicNetworkAccess = ServiceAccountPublicNetworkAccess.Enabled
}
};
var result = await collection.CreateOrUpdateAsync(
Azure.WaitUntil.Completed, "ai102-mycompany-ai", data);
Console.WriteLine($"Resource: {result.Value.Data.Name}");
Console.WriteLine($"Endpoint: {result.Value.Data.Properties.Endpoint}");
Console.WriteLine($"Custom: https://{result.Value.Data.Properties.CustomSubDomainName}.cognitiveservices.azure.com/");
# Create resource group
az group create --name rg-ai102-challenge02 --location eastus
# Create multi-service resource with custom subdomain
az cognitiveservices account create \
--name ai102-mycompany-ai \
--resource-group rg-ai102-challenge02 \
--kind AIServices \
--sku S0 \
--location eastus \
--custom-domain ai102-mycompany-ai \
--yes
# Verify the endpoint
az cognitiveservices account show \
--name ai102-mycompany-ai \
--resource-group rg-ai102-challenge02 \
--query "{endpoint: properties.endpoint, customDomain: properties.customSubDomainName}" \
-o json
Tarefa 2: Recuperar e Gerenciar Chaves
- Python SDK
- C# SDK
- REST API
# Retrieve access keys
keys = client.accounts.list_keys(
resource_group_name="rg-ai102-challenge02",
account_name="ai102-mycompany-ai"
)
print(f"Key 1: {keys.key1[:8]}...")
print(f"Key 2: {keys.key2[:8]}...")
# Regenerate key 1 (rotate without downtime using key 2)
from azure.mgmt.cognitiveservices.models import RegenerateKeyParameters, KeyName
new_keys = client.accounts.regenerate_key(
resource_group_name="rg-ai102-challenge02",
account_name="ai102-mycompany-ai",
parameters=RegenerateKeyParameters(key_name=KeyName.KEY1)
)
print(f"New Key 1: {new_keys.key1[:8]}...")
print("Key 2 unchanged—zero-downtime rotation complete")
var account = await collection.GetAsync("ai102-mycompany-ai");
var resource = account.Value;
// Get current keys
var keys = await resource.GetKeysAsync();
Console.WriteLine($"Key 1: {keys.Value.Key1[..8]}...");
Console.WriteLine($"Key 2: {keys.Value.Key2[..8]}...");
// Regenerate key 1
var regenerated = await resource.RegenerateKeyAsync(
new RegenerateKeyContent(CognitiveServicesKeyName.Key1));
Console.WriteLine($"New Key 1: {regenerated.Value.Key1[..8]}...");
Console.WriteLine("Key 2 unchanged—zero-downtime rotation complete");
# List keys
az cognitiveservices account keys list \
--name ai102-mycompany-ai \
--resource-group rg-ai102-challenge02 \
-o json
# Regenerate key1 (use key2 during rotation)
az cognitiveservices account keys regenerate \
--name ai102-mycompany-ai \
--resource-group rg-ai102-challenge02 \
--key-name key1
# Verify connectivity with the new key
ENDPOINT=$(az cognitiveservices account show \
--name ai102-mycompany-ai \
--resource-group rg-ai102-challenge02 \
--query "properties.endpoint" -o tsv)
KEY=$(az cognitiveservices account keys list \
--name ai102-mycompany-ai \
--resource-group rg-ai102-challenge02 \
--query "key1" -o tsv)
curl -s "${ENDPOINT}language/:analyze-text?api-version=2023-04-01" \
-H "Ocp-Apim-Subscription-Key: ${KEY}" \
-H "Content-Type: application/json" \
-d '{"kind":"LanguageDetection","parameters":{"modelVersion":"latest"},"analysisInput":{"documents":[{"id":"1","text":"Hello world"}]}}'
Tarefa 3: Configurar Acesso de Rede
- Python SDK
- C# SDK
- REST API
from azure.mgmt.cognitiveservices.models import (
NetworkRuleSet, NetworkRuleAction, IpRule, VirtualNetworkRule
)
# Update resource with network restrictions
account = client.accounts.begin_create(
resource_group_name="rg-ai102-challenge02",
account_name="ai102-mycompany-ai",
account=Account(
sku=Sku(name="S0"),
kind="AIServices",
location="eastus",
properties=AccountProperties(
custom_sub_domain_name="ai102-mycompany-ai",
public_network_access="Enabled",
network_acls=NetworkRuleSet(
default_action=NetworkRuleAction.DENY,
ip_rules=[
IpRule(value="203.0.113.0/24"), # Corporate IP range
IpRule(value="198.51.100.42") # Developer IP
]
)
)
)
).result()
print(f"Network rules applied: default action = Deny")
print(f"Allowed IPs: 203.0.113.0/24, 198.51.100.42")
print(f"Public access: {account.properties.public_network_access}")
// Update with network restrictions
var updateData = new CognitiveServicesAccountData(Azure.Core.AzureLocation.EastUS)
{
Kind = "CognitiveServices",
Sku = new CognitiveServicesSku("S0"),
Properties = new CognitiveServicesAccountProperties
{
CustomSubDomainName = "ai102-mycompany-ai",
PublicNetworkAccess = ServiceAccountPublicNetworkAccess.Enabled,
NetworkAcls = new CognitiveServicesNetworkRuleSet
{
DefaultAction = CognitiveServicesNetworkRuleAction.Deny
}
}
};
// Add IP rules
updateData.Properties.NetworkAcls.IPRules.Add(
new CognitiveServicesIPRule("203.0.113.0/24"));
updateData.Properties.NetworkAcls.IPRules.Add(
new CognitiveServicesIPRule("198.51.100.42"));
var updated = await collection.CreateOrUpdateAsync(
Azure.WaitUntil.Completed, "ai102-mycompany-ai", updateData);
Console.WriteLine("Network rules applied: default action = Deny");
Console.WriteLine($"IP rules count: {updated.Value.Data.Properties.NetworkAcls.IPRules.Count}");
# Configure network rules - deny all except specific IPs
az cognitiveservices account network-rule add \
--name ai102-mycompany-ai \
--resource-group rg-ai102-challenge02 \
--ip-address 203.0.113.0/24
az cognitiveservices account network-rule add \
--name ai102-mycompany-ai \
--resource-group rg-ai102-challenge02 \
--ip-address 198.51.100.42
# Set default action to deny
az cognitiveservices account update \
--name ai102-mycompany-ai \
--resource-group rg-ai102-challenge02 \
--default-action Deny
# Verify network rules
az cognitiveservices account network-rule list \
--name ai102-mycompany-ai \
--resource-group rg-ai102-challenge02 \
-o table
# To completely disable public access (private endpoint only)
az cognitiveservices account update \
--name ai102-mycompany-ai \
--resource-group rg-ai102-challenge02 \
--public-network-access Disabled
Saída Esperada
Resource: ai102-mycompany-ai
Endpoint: https://ai102-mycompany-ai.cognitiveservices.azure.com/
Custom domain: https://ai102-mycompany-ai.cognitiveservices.azure.com/
Key 1: a3f8b2c1...
Key 2: 7d9e4f6a...
New Key 1: x1y2z3w4...
Key 2 unchanged—zero-downtime rotation complete
Network rules applied: default action = Deny
Allowed IPs: 203.0.113.0/24, 198.51.100.42
Public access: Enabled
Quebra & conserta
| Cenário | Sintoma | Causa Raiz | Correção |
|---|---|---|---|
| Conflito de subdomínio personalizado | Erro SubdomainAlreadyInUse | Outro recurso usa o mesmo subdomínio globalmente | Escolha um nome de subdomínio único |
| Rede bloqueada | 403 Forbidden após aplicar regras | IP do cliente não está na lista de permissões | Adicione o IP do cliente às regras de rede ou use private endpoint |
| Rotação de chave quebra o app | 401 Unauthorized após regeneração | App ainda usando a chave antiga | Atualize para a nova chave, ou use a Key 2 durante a rotação da Key 1 |
| Autenticação Entra falha | 401 com bearer token | Recurso sem subdomínio personalizado | Subdomínio personalizado é obrigatório para autenticação Microsoft Entra; recrie com --custom-domain |
| Formato de endpoint errado | 404 Not Found | Usando formato de endpoint regional com recurso de subdomínio personalizado | Use o formato https://<subdomain>.cognitiveservices.azure.com/ |
Verificação de Conhecimento
1. Por que um nome de subdomínio personalizado é obrigatório ao usar autenticação Microsoft Entra ID (Azure AD) com serviços do Azure AI?
2. Você precisa rotacionar as chaves de API de um recurso Azure AI em produção sem nenhum tempo de inatividade. Qual é o procedimento correto?
3. Qual é o formato de endpoint padrão para um recurso multi-serviço do Azure AI criado SEM um subdomínio personalizado?
4. Você configura regras de rede no seu recurso Azure AI com a ação padrão definida como 'Deny'. Qual tráfego ainda é permitido?
5. Qual SKU você deve escolher para um recurso multi-serviço do Azure AI de desenvolvimento/teste para minimizar custos enquanto acessa todas as APIs de serviço?
Limpeza
az group delete --name rg-ai102-challenge02 --yes --no-wait