# Az - AI Foundry, AI Hubs, Azure OpenAI & AI Search

{{#include ../../../banners/hacktricks-training.md}}

## Why These Services Matter

Azure AI Foundry is Microsoft's umbrella for building GenAI applications. A hub aggregates AI projects, Azure ML workspaces, compute, data stores, registries, prompt flow assets, and connections to downstream services such as **Azure OpenAI** and **Azure AI Search**. Every component commonly exposes:

- **Long-lived API keys** (OpenAI, Search, data connectors) replicated inside Azure Key Vault or workspace connection objects.
- **Managed Identities (MI)** that control deployments, vector indexing jobs, model evaluation pipelines, and Git/GitHub Enterprise operations.
- **Cross-service links** (storage accounts, container registries, Application Insights, Log Analytics) that inherit hub/project permissions.
- **Multi-tenant connectors** (Hugging Face, Azure Data Lake, Event Hubs) that may leak upstream credentials or tokens.

Compromise of a single hub/project can therefore imply control over downstream managed identities, compute clusters, online endpoints, and any search indexes or OpenAI deployments referenced by prompt flows.

## Core Components & Security Surface

- **AI Hub (`Microsoft.MachineLearningServices/hubs`)**: Top-level object that defines region, managed network, system datastores, default Key Vault, Container Registry, Log Analytics, and hub-level identities. A compromised hub lets an attacker inject new projects, registries, or user-assigned identities.
- **AI Projects (`Microsoft.MachineLearningServices/workspaces`)**: Host prompt flows, data assets, environments, component pipelines, and online/batch endpoints. Projects inherit hub resources and can also override with their own storage, kv, and MI. Each workspace stores secrets under `/connections` and `/datastores`.
- **Managed Compute & Endpoints**: Includes managed online endpoints, batch endpoints, serverless endpoints, AKS/ACI deployments, and on-demand inference servers. Tokens fetched from Azure Instance Metadata Service (IMDS) inside these runtimes usually carry the workspace/project MI role assignments (commonly `Contributor` or `Owner`).
- **AI Registries & Model Catalog**: Allow region-scoped sharing of models, environments, components, data, and evaluation results. Registries can automatically sync to GitHub/Azure DevOps, meaning PATs may be embedded inside connection definitions.
- **Azure OpenAI (`Microsoft.CognitiveServices/accounts` with `kind=OpenAI`)**: Provides GPT family models. Access is controlled via role assignments + admin/query keys. Many Foundry prompt flows keep the generated keys as secrets or environment variables accessible from compute jobs.
- **Azure AI Search (`Microsoft.Search/searchServices`)**: Vector/index storage typically connected via a Search admin key stored inside a project connection. Index data can hold sensitive embeddings, retrieved documents, or raw training corpora.

## Security-Relevant Architecture

### Managed Identities & Role Assignments

- AI hubs/projects can enable **system-assigned** or **user-assigned** identities. These identities usually hold roles on storage accounts, key vaults, container registries, Azure OpenAI resources, Azure AI Search services, Event Hubs, Cosmos DB, or custom APIs.
- Online endpoints inherit the project MI or can override with a dedicated user-assigned MI per deployment.
- Prompt Flow connections and Automated Agents can request tokens via `DefaultAzureCredential`; capturing the metadata endpoint from compute gives tokens for lateral movement.

### Network Boundaries

- Hubs/projects support **`publicNetworkAccess`**, **private endpoints**, **Managed VNet** and **managedOutbound`** rules. Misconfigured `allowInternetOutbound` or open scoring endpoints permit direct exfiltration.
- Azure OpenAI and AI Search support **firewall rules**, **Private Endpoint Connections (PEC)**, **shared private link resources**, and `trustedClientCertificates`. When public access is enabled these services accept requests with any source IP that knows the key.

### Data & Secret Stores

- Default hub/project deployments create a **storage account**, **Azure Container Registry**, **Key Vault**, **Application Insights**, and **Log Analytics** workspace inside a hidden managed resource group (pattern: `mlw-<workspace>-rg`).
- Workspace **datastores** reference blob/data lake containers and can embed SAS tokens, service principal secrets, or storage access keys.
- Workspace **connections** (for Azure OpenAI, AI Search, Cognitive Services, Git, Hugging Face, etc.) keep credentials in the workspace Key Vault and surface them through the management plane when listing the connection (values are base64-encoded JSON).
- **AI Search admin keys** provide full read/write access to indexes, skillsets, data sources, and can retrieve documents that feed RAG systems.

### Monitoring & Supply Chain

- AI Foundry supports GitHub/Azure DevOps integration for code and prompt flow assets. OAuth tokens or PATs live in the Key Vault + connection metadata.
- Model Catalog may mirror Hugging Face artifacts. If `trust_remote_code=true`, arbitrary Python executes during deployment.
- Data/feature pipelines log to Application Insights or Log Analytics, exposing connection strings.

## Enumeration with `az`

```bash
# Install the Azure ML / AI CLI extension (if missing)
az extension add --name ml

# Enumerate AI Hubs (workspaces with kind=hub) and inspect properties
az ml workspace list --filtered-kinds hub --resource-group <RG> --query "[].{name:name, location:location, rg:resourceGroup}" -o table
az resource show --name <HUB> --resource-group <RG> \
  --resource-type Microsoft.MachineLearningServices/workspaces \
  --query "{location:location, publicNetworkAccess:properties.publicNetworkAccess, identity:identity, managedResourceGroup:properties.managedResourceGroup}" -o jsonc

# Enumerate AI Projects (kind=project) under a hub or RG
az resource list --resource-type Microsoft.MachineLearningServices/workspaces --query "[].{name:name, rg:resourceGroup, location:location}" -o table
az ml workspace list --filtered-kinds project --resource-group <RG> \
  --query "[?contains(properties.hubArmId, '/workspaces/<HUB>')].{name:name, rg:resourceGroup, location:location}"

# Show workspace level settings (managed identity, storage, key vault, container registry)
az ml workspace show --name <WS> --resource-group <RG> \
  --query "{managedNetwork:properties.managedNetwork, storageAccount:properties.storageAccount, containerRegistry:properties.containerRegistry, keyVault:properties.keyVault, identity:identity}"

# List workspace connections (OpenAI, AI Search, Git, data sources)
az ml connection list --workspace-name <WS> --resource-group <RG> --populate-secrets -o table
az ml connection show --workspace-name <WS> --resource-group <RG> --name <CONNECTION>
# For REST (returns base64 encoded secrets)
az rest --method GET \
  --url "https://management.azure.com/subscriptions/<SUB>/resourceGroups/<RG>/providers/Microsoft.MachineLearningServices/workspaces/<WS>/connections/<CONN>?api-version=2024-04-01"

# Enumerate datastores and extract credentials/SAS
az ml datastore list --workspace-name <WS> --resource-group <RG>
az ml datastore show --name <DATASTORE> --workspace-name <WS> --resource-group <RG>

# List managed online/batch endpoints and deployments (capture identity per deployment)
az ml online-endpoint list --workspace-name <WS> --resource-group <RG>
az ml online-endpoint show --name <ENDPOINT> --workspace-name <WS> --resource-group <RG>
az ml online-deployment show --name <DEPLOYMENT> --endpoint-name <ENDPOINT> --workspace-name <WS> --resource-group <RG> \
  --query "{identity:identity, environment:properties.environmentId, codeConfiguration:properties.codeConfiguration}"

# Discover prompt flows, components, environments, data assets
az ml component list --workspace-name <WS> --resource-group <RG>
az ml data list --workspace-name <WS> --resource-group <RG> --type uri_folder
az ml environment list --workspace-name <WS> --resource-group <RG>
az ml job list --workspace-name <WS> --resource-group <RG> --type pipeline

# List hub/project managed identities and their role assignments
az identity list --resource-group <RG>
az role assignment list --assignee <MI-PRINCIPAL-ID> --all

# Azure OpenAI resources (filter kind==OpenAI)
az resource list --resource-type Microsoft.CognitiveServices/accounts \
  --query "[?kind=='OpenAI'].{name:name, rg:resourceGroup, location:location}" -o table
az cognitiveservices account list --resource-group <RG> \
  --query "[?kind=='OpenAI'].{name:name, location:location}" -o table
az cognitiveservices account show --name <AOAI-NAME> --resource-group <RG>
az cognitiveservices account keys list --name <AOAI-NAME> --resource-group <RG>
az cognitiveservices account deployment list --name <AOAI-NAME> --resource-group <RG>
az cognitiveservices account network-rule list --name <AOAI-NAME> --resource-group <RG>

# Azure AI Search services
az search service list --resource-group <RG>
az search service show --name <SEARCH-NAME> --resource-group <RG> \
  --query "{sku:sku.name, publicNetworkAccess:properties.publicNetworkAccess, privateEndpoints:properties.privateEndpointConnections}"
az search admin-key show --service-name <SEARCH-NAME> --resource-group <RG>
az search query-key list --service-name <SEARCH-NAME> --resource-group <RG>
az search shared-private-link-resource list --service-name <SEARCH-NAME> --resource-group <RG>

# AI Search data-plane (requires admin key in header)
az rest --method GET \
  --url "https://<SEARCH-NAME>.search.windows.net/indexes?api-version=2024-07-01" \
  --headers "api-key=<ADMIN-KEY>"
az rest --method GET \
  --url "https://<SEARCH-NAME>.search.windows.net/datasources?api-version=2024-07-01" \
  --headers "api-key=<ADMIN-KEY>"
az rest --method GET \
  --url "https://<SEARCH-NAME>.search.windows.net/indexers?api-version=2024-07-01" \
  --headers "api-key=<ADMIN-KEY>"

# Linkage between workspaces and search / openAI (REST helper)
az rest --method GET \
  --url "https://management.azure.com/subscriptions/<SUB>/resourceGroups/<RG>/providers/Microsoft.MachineLearningServices/workspaces/<WS>/connections?api-version=2024-04-01" \
  --query "value[?properties.target=='AzureAiSearch' || properties.target=='AzureOpenAI']"
```

## What to Look For During Assessment

- **Identity scope**: Projects often reuse a powerful user-assigned identity attached to multiple services. Capturing IMDS tokens from any managed compute inherits those privileges.
- **Connection objects**: Base64 payload includes the secret plus metadata (endpoint URL, API version). Many teams leave OpenAI + Search admin keys here rather than rotating frequently.
- **Git & external source connectors**: PATs or OAuth refresh tokens may allow push access to code that defines pipelines/prompt flows.
- **Datastores & data assets**: Provide SAS tokens valid for months; data assets may point to customer PII, embeddings, or training corpora.
- **Managed Network overrides**: `allowInternetOutbound=true` or `publicNetworkAccess=Enabled` makes it trivial to exfiltrate secrets from jobs/endpoints.
- **Hub-managed resource group**: Contains the storage account (`<workspace>storage`), container registry, KV, and Log Analytics. Access to that RG often means full takeover even if portal hides it.

## References

- [Azure AI Foundry architecture](https://learn.microsoft.com/en-us/azure/ai-studio/concepts/ai-resources)
- [Azure Machine Learning CLI v2](https://learn.microsoft.com/en-us/azure/machine-learning/how-to-configure-cli)
- [Azure OpenAI security controls](https://learn.microsoft.com/en-us/azure/ai-services/openai/how-to/network-security)
- [Azure AI Search security](https://learn.microsoft.com/en-us/azure/search/search-security-overview)

{{#include ../../../banners/hacktricks-training.md}}
