# Microsoft Azure AI Foundry Integration Connect your Microsoft Azure AI Foundry environment to Capsule Security for complete visibility into your AI agents, tools, knowledge bases, and conversation history. The integration covers both the classic Azure AI Foundry portal and the new Foundry experience. ## Overview img ### Setup Paths Capsule supports two setup paths for this integration: - **Standard Setup** — Capsule automatically discovers resources and assigns the required RBAC roles during the OAuth consent flow. This is the recommended path for most organizations. See [Step 1: Configure the Integration](#step-1-configure-the-integration-in-capsule). - **Manual Setup** — You pre-assign RBAC roles to the Capsule service principal yourself, then connect via OAuth. This is designed for organizations with strict least-privilege policies that do not allow the consenting admin to have role assignment permissions. See [Alternative Setup: Manual Setup](#alternative-setup-manual-setup). This integration uses Microsoft Entra ID (Azure AD) authentication to sync: - **Agents** — AI assistants across the classic and new Foundry experiences - **Tools** — Code Interpreter, File Search, Azure AI Search, Bing Grounding, OpenAPI, MCP (Foundry IQ), and Functions - **Knowledge Bases** — Vector stores and files attached to agents - **Conversations** — Thread messages and chat history - **Audit** — Run history with tool invocations and session tracking - **Deployments & Connections** — Model deployments and connection metadata - **Inference Logs** — Model request and response data via Azure Monitor diagnostic logs - **Invocation** — Send prompts to agents and capture responses for red-team assessments ## Prerequisites Before you begin, ensure you have: - An active **Azure subscription** with Azure AI Foundry resources deployed - An **Azure Entra ID** account with **Reader** access (and the ability to assign roles) on the subscriptions containing AI Foundry resources, used to perform the OAuth consent flow - Access to the **Capsule Security** portal With Standard Setup, Capsule assigns the roles it needs to its own service principal during the OAuth consent flow — you do not pre-assign them yourself. Capsule uses two built-in roles: - [**Azure AI Developer**](https://learn.microsoft.com/en-us/azure/role-based-access-control/built-in-roles/ai-machine-learning#azure-ai-developer) — control-plane access to discover and read accounts, projects, deployments, and connections - [**Azure AI User**](https://learn.microsoft.com/en-us/azure/role-based-access-control/built-in-roles/ai-machine-learning#azure-ai-user) — data-plane access to read and invoke agents, threads, responses, and assets The optional **Inference Logs** feature additionally requires [**Monitoring Contributor**](https://learn.microsoft.com/en-us/azure/role-based-access-control/built-in-roles/monitor#monitoring-contributor) (to configure diagnostic settings) and [**Log Analytics Reader**](https://learn.microsoft.com/en-us/azure/role-based-access-control/built-in-roles/monitor#log-analytics-reader) (to query the logs). Capsule's app also uses Microsoft Graph `Application.Read.All` to resolve its own service principal during setup. This is best-effort and not required for the integration to function. For more information about Azure RBAC roles, see [Azure role-based access control](https://learn.microsoft.com/en-us/azure/role-based-access-control/overview). ## Step 1: Configure the Integration in Capsule Start the integration setup from the Capsule Security portal. ### Steps 1. Log in to the **Capsule Security** portal 2. Click **Integrations** in the left sidebar 1. Find the **Azure AI Foundry** card and click **Set up Integration** 1. Click **Connect with Microsoft** 1. You'll be redirected to Microsoft's sign-in page ## Step 2: Authorize the Capsule Application Grant Capsule the necessary permissions to access your Azure AI Foundry resources. ### Steps 1. Sign in with your Azure/Microsoft account that has the required permissions (see Prerequisites) 2. Review the permissions requested by the Capsule application 1. Click **Accept** to grant consent ### Permissions explained During the OAuth consent flow, the consenting admin's token is used to assign roles and discover resources. After setup, Capsule uses its own service principal credentials for ongoing data synchronization. Capsule also uses Microsoft Graph `Application.Read.All` to resolve its own service principal during setup (best-effort; not required to function). Capsule assigns and uses these roles: | Role | Scope | Purpose | | --- | --- | --- | | [**Azure AI Developer**](https://learn.microsoft.com/en-us/azure/role-based-access-control/built-in-roles/ai-machine-learning#azure-ai-developer) | Subscription | Control-plane access to discover and read accounts, projects, deployments, and connections | | [**Azure AI User**](https://learn.microsoft.com/en-us/azure/role-based-access-control/built-in-roles/ai-machine-learning#azure-ai-user) | Subscription | Data-plane access to read and invoke agents, threads, responses, and assets | | [**Monitoring Contributor**](https://learn.microsoft.com/en-us/azure/role-based-access-control/built-in-roles/monitor#monitoring-contributor) | Subscription | **Inference Logs only** — configure diagnostic settings on AI Services resources | | [**Log Analytics Reader**](https://learn.microsoft.com/en-us/azure/role-based-access-control/built-in-roles/monitor#log-analytics-reader) | Log Analytics workspace | **Inference Logs only** — query `RequestResponse` and `Audit` diagnostic logs | The admin performing the OAuth consent needs **Reader** access (and role assignment permission) on the relevant subscriptions. #### Detailed permissions by role **Azure AI User** provides the following data-plane permissions on AI Services accounts and projects: | Permission | Purpose | | --- | --- | | `Microsoft.CognitiveServices/accounts/AIServices/agents/read` | Read agent definitions, threads, messages, runs, and run steps | | `Microsoft.CognitiveServices/accounts/AIServices/agents/write` | Create threads, messages, and runs to invoke agents | | `Microsoft.CognitiveServices/accounts/AIServices/assets/read` | Read files, vector stores, and vector store file associations | | `Microsoft.CognitiveServices/accounts/AIServices/responses/read` | Read Responses-API responses | | `Microsoft.CognitiveServices/accounts/AIServices/responses/write` | Invoke agents via the Responses API | | `Microsoft.CognitiveServices/accounts/AIServices/applications/invoke/action` | Invoke a published agent endpoint | **Azure AI Developer** provides the following control-plane permissions used during discovery: | Permission | Purpose | | --- | --- | | `Microsoft.Resources/subscriptions/read` | Discover Azure subscriptions | | `Microsoft.CognitiveServices/accounts/read` | Discover AI Services accounts across subscriptions | | `Microsoft.CognitiveServices/accounts/projects/read` | Discover AI Foundry projects within each account | | `Microsoft.CognitiveServices/accounts/deployments/read` | Read model deployments | | `Microsoft.CognitiveServices/accounts/connections/read` | Read connection metadata (never secrets) | **Log Analytics Reader** provides the following permissions on the Log Analytics workspace: | Permission | Purpose | | --- | --- | | `Microsoft.OperationalInsights/workspaces/read` | Access the Log Analytics workspace | | `Microsoft.OperationalInsights/workspaces/query/read` | Query `RequestResponse` and `Audit` log data | **Additional permissions** required on the AI Services account for automated diagnostic logging setup: | Permission | Purpose | | --- | --- | | `Microsoft.Insights/diagnosticSettings/read` | Read existing diagnostic settings configuration | | `Microsoft.Insights/diagnosticSettings/write` | Create diagnostic settings to enable `RequestResponse` and `Audit` log collection | For more information, see: - [Azure AI Foundry role-based access control](https://learn.microsoft.com/en-us/azure/ai-foundry/concepts/rbac-foundry) - [Azure built-in roles for AI + machine learning](https://learn.microsoft.com/en-us/azure/role-based-access-control/built-in-roles/ai-machine-learning) - [Enable diagnostic logging for Azure AI Services](https://learn.microsoft.com/en-us/azure/ai-services/diagnostic-logging) - [Monitor Azure OpenAI](https://learn.microsoft.com/en-us/azure/ai-foundry/openai/how-to/monitor-openai) - [User and admin consent in Azure](https://learn.microsoft.com/en-us/entra/identity/enterprise-apps/user-admin-consent-overview) ## Step 3: Automatic Project Discovery After you grant consent, Capsule automatically configures the integration. ### What happens - All Azure subscriptions you have access to are discovered - AI Foundry projects within those subscriptions are detected - Capsule begins syncing using the pre-assigned Azure AI User and Azure AI Developer roles - Capsule creates a diagnostic setting on each AI Services resource - The **Audit** and **RequestResponse** log categories are enabled - Logs are sent to a Log Analytics workspace for querying No manual project configuration is needed. For more information, see [Enable diagnostic logging for Azure AI Services](https://learn.microsoft.com/en-us/azure/ai-services/diagnostic-logging) and [Monitor Azure OpenAI](https://learn.microsoft.com/en-us/azure/ai-foundry/openai/how-to/monitor-openai). ## After Setup Once the integration is configured: - Initial sync begins automatically - First sync may take several minutes depending on data volume - View synced agents in **Inventory → Agents** - View conversations in **Observability → Filter Activity Type - Session** ## Alternative Setup: Manual Setup Use this setup path if your organization requires least-privilege access and wants full control over the permissions granted to the Capsule service principal. With Manual Setup, you run a setup script that creates a custom Azure role with only the exact permissions Capsule needs, then complete the standard OAuth consent flow. Capsule skips automatic role assignment during setup. ### Required Permissions The setup script creates a least-privilege custom role called **Capsule AI Foundry Reader** with only the permissions Capsule needs: | Permission | Plane | Purpose | | --- | --- | --- | | `Microsoft.Resources/subscriptions/read` | Control | Discover subscriptions | | `Microsoft.CognitiveServices/accounts/read` | Control | Discover AI Services accounts | | `Microsoft.CognitiveServices/accounts/projects/read` | Control | Discover AI Foundry projects | | `Microsoft.CognitiveServices/accounts/connections/read` | Control | Read connection metadata | | `Microsoft.CognitiveServices/accounts/deployments/read` | Control | Read model deployments | | `Microsoft.CognitiveServices/accounts/privateEndpointConnections/read` | Control | Read private endpoint connections | | `Microsoft.CognitiveServices/accounts/AIServices/agents/read` | Data | Read agents, threads, messages, runs, run steps | | `Microsoft.CognitiveServices/accounts/AIServices/agents/write` | Data | Create threads, messages, runs to invoke agents | | `Microsoft.CognitiveServices/accounts/AIServices/assets/read` | Data | Read files, vector stores | | `Microsoft.CognitiveServices/accounts/AIServices/responses/read` | Data | Read Responses-API responses | | `Microsoft.CognitiveServices/accounts/AIServices/responses/write` | Data | Invoke agents via the Responses API | | `Microsoft.CognitiveServices/accounts/AIServices/applications/invoke/action` | Data | Invoke a published agent endpoint | The role grants connection metadata read only (`connections/read`), never `connections/listsecrets` — secrets are never accessed. The consent flow also grants Microsoft Graph `Application.Read.All` for best-effort service principal lookup. The setup script creates this custom Azure role and assigns it to the Capsule service principal. ### Step 1: Run the Setup Script The setup script automates the entire manual setup process — creating the service principal, defining the custom role, assigning it, and verifying the configuration. **Prerequisites:** - [Azure CLI](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli) installed and logged in (`az login`) - Owner or User Access Administrator on the target subscription (to create role definitions and assignments) - The Capsule Application (Client) ID — contact the Capsule team to obtain this Save the script below to a file, make it executable, and run it: details summary azure-ai-foundry-manual-setup.sh (click to expand) ```bash #!/usr/bin/env bash set -euo pipefail readonly RED='\033[0;31m' readonly GREEN='\033[0;32m' readonly YELLOW='\033[1;33m' readonly BLUE='\033[0;34m' readonly NC='\033[0m' info() { echo -e "${BLUE}[INFO]${NC} $*"; } success() { echo -e "${GREEN}[OK]${NC} $*"; } warn() { echo -e "${YELLOW}[WARN]${NC} $*"; } fail() { echo -e "${RED}[ERROR]${NC} $*" >&2; exit 1; } usage() { cat </dev/null; then fail "Azure CLI (az) is not installed. See https://aka.ms/install-azure-cli" fi if ! az account show &>/dev/null; then fail "Not logged into Azure CLI. Run 'az login' first." fi az account set --subscription "$SUBSCRIPTION_ID" 2>/dev/null \ || fail "Cannot access subscription $SUBSCRIPTION_ID. Verify the ID and your permissions." success "Azure CLI authenticated — subscription $SUBSCRIPTION_ID selected" az resource show --ids "$AI_ACCOUNT_SCOPE" --query "id" -o tsv &>/dev/null \ || fail "AI Services account '${AI_ACCOUNT_NAME}' not found in resource group '${RESOURCE_GROUP}'" success "AI Services account '${AI_ACCOUNT_NAME}' found" info "Ensuring Capsule service principal exists in your tenant..." if ! az ad sp create --id "$CAPSULE_APP_ID" -o none 2>/dev/null; then info "Service principal already exists — continuing" fi SP_OBJECT_ID=$(az ad sp show --id "$CAPSULE_APP_ID" --query "id" -o tsv 2>/dev/null) \ || fail "Could not retrieve service principal for app ID $CAPSULE_APP_ID" success "Service principal object ID: ${SP_OBJECT_ID}" assign_role() { local role_id="$1" local scope="$2" local label="$3" info "Assigning ${label}..." if az role assignment create \ --assignee-object-id "$SP_OBJECT_ID" \ --assignee-principal-type ServicePrincipal \ --role "$role_id" \ --scope "$scope" \ -o none 2>/dev/null; then success "${label} assigned" else if az role assignment list \ --assignee "$SP_OBJECT_ID" \ --role "$role_id" \ --scope "$scope" \ --query "[0].id" -o tsv 2>/dev/null | grep -q .; then info "${label} already assigned — skipping" else fail "Failed to assign ${label}. Ensure you have Owner or User Access Administrator permissions." fi fi } readonly CUSTOM_ROLE_NAME="Capsule AI Foundry Reader" if [[ "$USE_CUSTOM_ROLE" == "true" ]]; then info "Creating custom role '${CUSTOM_ROLE_NAME}'..." EXISTING_SCOPE=$(az role definition list --name "$CUSTOM_ROLE_NAME" \ --query "[0].assignableScopes[0]" -o tsv 2>/dev/null) if [[ -n "$EXISTING_SCOPE" ]]; then if [[ "$EXISTING_SCOPE" == "$SUBSCRIPTION_SCOPE" ]]; then info "Custom role already exists with correct scope — skipping creation" else fail "Custom role '${CUSTOM_ROLE_NAME}' exists but is scoped to ${EXISTING_SCOPE}, not ${SUBSCRIPTION_SCOPE}. Delete the existing role or use --no-custom-role." fi else az role definition create --role-definition '{ "Name": "'"$CUSTOM_ROLE_NAME"'", "Description": "Least-privilege permissions for Capsule Security AI Foundry integration", "Actions": [ "Microsoft.Resources/subscriptions/read", "Microsoft.CognitiveServices/accounts/read", "Microsoft.CognitiveServices/accounts/projects/read", "Microsoft.CognitiveServices/accounts/connections/read", "Microsoft.CognitiveServices/accounts/deployments/read", "Microsoft.CognitiveServices/accounts/privateEndpointConnections/read" ], "DataActions": [ "Microsoft.CognitiveServices/accounts/AIServices/agents/read", "Microsoft.CognitiveServices/accounts/AIServices/agents/write", "Microsoft.CognitiveServices/accounts/AIServices/assets/read", "Microsoft.CognitiveServices/accounts/AIServices/responses/read", "Microsoft.CognitiveServices/accounts/AIServices/responses/write", "Microsoft.CognitiveServices/accounts/AIServices/applications/invoke/action" ], "NotActions": [], "NotDataActions": [], "AssignableScopes": [ "/subscriptions/'"$SUBSCRIPTION_ID"'" ] }' -o none || fail "Failed to create custom role definition" success "Custom role '${CUSTOM_ROLE_NAME}' created" fi info "Waiting for role definition to propagate..." for i in $(seq 1 36); do if az role definition list --name "$CUSTOM_ROLE_NAME" --query "[0].id" -o tsv 2>/dev/null | grep -q .; then success "Custom role is available" break fi if [[ $i -eq 36 ]]; then fail "Custom role '${CUSTOM_ROLE_NAME}' not visible after 3 minutes. Azure role propagation may be delayed — retry shortly." fi sleep 5 done assign_role "$CUSTOM_ROLE_NAME" "$SUBSCRIPTION_SCOPE" "$CUSTOM_ROLE_NAME" else assign_role "$ROLE_AI_USER" "$AI_ACCOUNT_SCOPE" "Azure AI User" assign_role "$ROLE_AI_DEVELOPER" "$AI_ACCOUNT_SCOPE" "Azure AI Developer" assign_role "$ROLE_READER" "$SUBSCRIPTION_SCOPE" "Reader" fi info "Verifying role assignments..." ASSIGNED_ROLES=$(az role assignment list \ --assignee "$SP_OBJECT_ID" \ --query "[].{role:roleDefinitionName, scope:scope}" \ -o table 2>/dev/null) || fail "Could not list role assignments" echo "" echo "$ASSIGNED_ROLES" echo "" success "All role assignments verified" info "Discovering AI Foundry project endpoints..." PROJECTS=$(az rest \ --method GET \ --url "https://management.azure.com${AI_ACCOUNT_SCOPE}/projects?api-version=2025-04-01-preview" \ --query "value[].{name:name, endpoint:properties.endpoints.\"AI Foundry API\"}" \ -o table 2>/dev/null) || true echo "" echo -e "${GREEN}════════════════════════════════════════════════════════════════${NC}" echo -e "${GREEN} Capsule Azure AI Foundry setup complete${NC}" echo -e "${GREEN}════════════════════════════════════════════════════════════════${NC}" echo "" echo "Use the following values in Capsule configuration:" echo "" echo -e " ${BLUE}Subscription ID:${NC} ${SUBSCRIPTION_ID}" echo -e " ${BLUE}Resource Group:${NC} ${RESOURCE_GROUP}" echo -e " ${BLUE}AI Account Name:${NC} ${AI_ACCOUNT_NAME}" echo -e " ${BLUE}SP Object ID:${NC} ${SP_OBJECT_ID}" if [[ -n "${PROJECTS:-}" ]]; then echo "" echo "Discovered projects:" echo "$PROJECTS" fi echo "" echo -e " ${BLUE}Roles Assigned:${NC}" if [[ "$USE_CUSTOM_ROLE" == "true" ]]; then echo " - ${CUSTOM_ROLE_NAME} on subscription ${SUBSCRIPTION_ID}" echo " (least-privilege custom role — replaces the built-in roles)" else echo " - Azure AI User on ${AI_ACCOUNT_NAME}" echo " - Azure AI Developer on ${AI_ACCOUNT_NAME}" echo " - Reader on subscription ${SUBSCRIPTION_ID}" fi echo "" ``` ```bash chmod +x azure-ai-foundry-manual-setup.sh ./azure-ai-foundry-manual-setup.sh \ --capsule-app-id "" \ --subscription-id "" \ --resource-group "" \ --ai-account-name "" ``` The script will: 1. Create the Capsule service principal in your tenant (idempotent) 2. Create the least-privilege **Capsule AI Foundry Reader** custom role with the permissions listed above 3. Assign the custom role to the service principal at subscription scope 4. Verify the role assignment 5. Discover AI Foundry project endpoints in your account ### Step 2: Complete Setup in Capsule Portal 1. Follow [Step 1: Configure the Integration in Capsule](#step-1-configure-the-integration-in-capsule) to start the setup 2. Enable the **Manual Setup** option before connecting 3. Complete the OAuth consent flow — Capsule will discover your projects using the pre-assigned role and skip automatic role assignment 4. Verify your agents appear in **Inventory → Agents** after the initial sync details summary Alternative: Use built-in Azure roles instead of a custom role If your organization prefers built-in roles over custom role definitions, you can assign these three roles instead. Pass `--no-custom-role` to the setup script, or assign them manually: | Role | Scope | Purpose | | --- | --- | --- | | [**Azure AI User**](https://learn.microsoft.com/en-us/azure/role-based-access-control/built-in-roles/ai-machine-learning#azure-ai-user) | AI Services account | Data plane access | | [**Azure AI Developer**](https://learn.microsoft.com/en-us/azure/role-based-access-control/built-in-roles/ai-machine-learning#azure-ai-developer) | AI Services account | Control plane access | | [**Reader**](https://learn.microsoft.com/en-us/azure/role-based-access-control/built-in-roles/general#reader) | Subscription | Discover subscriptions | ```bash ./azure-ai-foundry-manual-setup.sh \ --capsule-app-id "" \ --subscription-id "" \ --resource-group "" \ --ai-account-name "" \ --no-custom-role ``` These built-in roles include more permissions than Capsule requires but may be simpler to audit in organizations that restrict custom role definitions. ## Troubleshooting ### Common Issues 1. **Consent failed or permissions error** - Verify the consenting admin has **Reader** access and role assignment permission on the target subscriptions (Standard Setup assigns the **Azure AI Developer** and **Azure AI User** roles during consent) - For Manual Setup, verify the Capsule service principal already has the required roles assigned - Ensure your account has access to the subscriptions containing AI Foundry resources 2. **No projects discovered** - Confirm AI Foundry resources exist in your Azure subscriptions - Check that the resources are in subscriptions your account can access 3. **Sync not completing** - Allow several minutes for the initial sync to complete - Contact support if the issue persists 4. **No inference logs appearing** - Verify the Capsule service principal has the **Monitoring Contributor** role at the subscription level (required to create diagnostic settings) - Verify the Capsule service principal has the **Log Analytics Reader** role on the Log Analytics workspace - It can take up to two hours for logs to appear after diagnostic settings are configured - Check that the AI Services resource has a diagnostic setting with the **RequestResponse** category enabled in the Azure portal under **Monitoring → Diagnostic settings** ### Manual Setup Issues 1. **Role assignment command fails with "principal not found"** - Ensure you ran `az ad sp create --id ` first to create the service principal in your tenant - Verify the Capsule Application ID is correct 2. **Agent sync fails after Manual Setup** - Verify the **Azure AI User** role is assigned on the correct AI Services account (not just the subscription) - Run `az role assignment list --assignee --scope -o table` to check 3. **No projects discovered with Manual Setup** - Verify the **Azure AI Developer** role is assigned on the AI Services account - Verify the **Reader** role is assigned on the subscription - Confirm that the AI Services account has AI Foundry projects deployed ## Support For help with this integration: - **Email**: support@capsule.security - **Include**: Your organization ID, integration status, and any error messages For Azure-specific issues: - [Azure AI Foundry documentation](https://learn.microsoft.com/en-us/azure/ai-services/agents/) - [Azure support](https://azure.microsoft.com/en-us/support/)