مشاركة عبر


Secure MCP servers on Azure Container Apps

تشرح هذه المقالة كيفية مصادقة وتأمين خوادم MCP التي تعمل على Azure Container Apps. يختلف النهج حسب ما إذا كنت تستضيف تطبيق حاوية مستقل أو تستخدم خادم MCP المدار من المنصة في جلسات ديناميكية.

المتطلبات المسبقه

نظرة عامة على نماذج المصادقة

يدعم Azure Container Apps نموذجين للمصادقة لخوادم MCP. يلخص الجدول التالي الفروقات الرئيسية.

الجانب تطبيق الحاوية المستقلة جلسات ديناميكية MCP
آلية المصادقة تطبيقات الحاويات المدمجة للمصادقة مع Microsoft Entra ID مفتاح API عبر x-ms-apikey الرأس
نوع الرمز المميز رمز حامل OAuth 2.0 سلسلة مفاتيح API غير شفافة
موفر الهوية Microsoft Entra ID Azure Resource Manager
تدوير المفتاح/الرموز تدار بواسطة Microsoft Entra ID Regenerate عبر Azure Resource Manager API
نطاق التفويض قابل للتكوين حسب التطبيق مستوى مجموعة الجلسات
تشفير النقل TLS (تطبيق الحاويات موصول) TLS (نقطة نهاية جلسات تطبيقات الحاويات)

تطبيق حاوية مستقل مع مصادقة Microsoft Entra ID

عندما تقوم بنشر خادم MCP الخاص بك كتطبيق حاوية، فأنت تملك طبقة المصادقة. استخدم ميزة تطبيقات الحاويات <المصادقة المدمجة> المدعومة ب Microsoft Entra ID.

تكوين المصادقة المضمنة

الخطوات التالية تسجل تطبيق Microsoft Entra ID وتفعل المصادقة المدمجة على تطبيق الحاوية الخاص بك.

  1. تسجيل تطبيق في Microsoft Entra ID:

    APP_ID=$(az ad app create \
        --display-name "mcp-server-auth" \
        --sign-in-audience AzureADMyOrg \
        --query appId -o tsv)
    
  2. إنشاء مدير خدمة:

    az ad sp create --id $APP_ID
    
  3. قم بتعيين معرف التطبيق URI وعرض نطاق واجهة برمجة التطبيقات (API). هذه الإعدادات مطلوبة حتى يتمكن العملاء من طلب رموز الوصول لخادم MCP الخاص بك.

    az ad app update --id $APP_ID --identifier-uris "api://$APP_ID"
    
    OBJECT_ID=$(az ad app show --id $APP_ID --query id -o tsv)
    SCOPE_ID=$(uuidgen)
    
    az rest --method PATCH \
        --uri "https://graph.microsoft.com/v1.0/applications/$OBJECT_ID" \
        --headers "Content-Type=application/json" \
        --body "{
            \"api\": {
                \"oauth2PermissionScopes\": [{
                    \"id\": \"$SCOPE_ID\",
                    \"adminConsentDescription\": \"Access the MCP server\",
                    \"adminConsentDisplayName\": \"Access MCP Server\",
                    \"isEnabled\": true,
                    \"type\": \"User\",
                    \"userConsentDescription\": \"Access the MCP server\",
                    \"userConsentDisplayName\": \"Access MCP Server\",
                    \"value\": \"access_as_user\"
                }]
            }
        }"
    
  4. أضف سر عميل:

    CLIENT_SECRET=$(az ad app credential reset --id $APP_ID --query password -o tsv)
    TENANT_ID=$(az account show --query tenantId -o tsv)
    
  5. تفعيل المصادقة المدمجة في تطبيق الحاوية:

    az containerapp auth microsoft update \
        --name <CONTAINER_APP_NAME> \
        --resource-group <RESOURCE_GROUP> \
        --client-id $APP_ID \
        --client-secret $CLIENT_SECRET \
        --tenant-id $TENANT_ID \
        --issuer "https://login.microsoftonline.com/$TENANT_ID/v2.0" \
        --yes
    
  6. اضبط الإجراء غير المصادق عليه ليتطلب تسجيل الدخول:

    az containerapp auth update \
        --name <CONTAINER_APP_NAME> \
        --resource-group <RESOURCE_GROUP> \
        --unauthenticated-client-action Return401
    

الاتصال من عميل MCP باستخدام رمز حامل

عندما يحتاج خادم MCP الخاص بك إلى رمز حامل، قم بتكوين استرجاع الرموز في عميل MCP الخاص بك. المثال التالي يوضح تكوين .vscode/mcp.json ل GitHub Copilot:

{
    "servers": {
        "my-mcp-server": {
            "type": "http",
            "url": "https://<CONTAINER_APP_NAME>.<REGION>.azurecontainerapps.io/mcp",
            "headers": {
                "Authorization": "Bearer ${input:mcpBearerToken}"
            }
        }
    },
    "inputs": [
        {
            "id": "mcpBearerToken",
            "type": "promptString",
            "description": "Enter your bearer token for the MCP server",
            "password": true
        }
    ]
}

نصيحة

للتطوير، احصل على رمز باستخدام az account get-access-token --resource api://$APP_ID --query accessToken -o tsv ولصقه عند طلب الطلب. لسير العمل الآلي، قم بالدمج مع نظام إدارة الرموز في مؤسستك.

تكوين CORS

عملاء MCP الذين يتصلون من بيئات الويب يحتاجون إلى رؤوس CORS. استخدم الأمر التالي لتكوين CORS على تطبيق الحاوية الخاص بك:

az containerapp ingress cors update \
    --name <CONTAINER_APP_NAME> \
    --resource-group <RESOURCE_GROUP> \
    --allowed-origins "https://vscode.dev" "https://github.dev" \
    --allowed-methods "GET" "POST" "OPTIONS" \
    --allowed-headers "Content-Type" "Authorization" "Mcp-Session-Id" \
    --max-age 3600

الرؤوس التالية هي المفتاح للسماح:

  • Content-Type: مطلوب لطلبات JSON-RPC
  • Authorization: مطلوب لتوثيق رمز حامل
  • Mcp-Session-Id: يستخدمها عملاء MCP للجلسات ذات الحالة

‏‫ملاحظة‬

يتصل GitHub Copilot بخوادم MCP البعيدة من تطبيق سطح مكتب VS Code، وليس من المتصفح. CORS مطلوب فقط إذا كنت تنوي دعم عملاء MCP المعتمدين على المتصفح أو VS Code for the Web. تستخدم الدروس المستقلة أصول CORS البرية للبساطة؛ بالنسبة للإنتاج، اقتصر على أصول موثوقة محددة كما هو موضح هنا.

توصيات أمنية لخوادم MCP المستقلة

طبق أفضل الممارسات التالية لتقوية خادم MCP المستقل الخاص بك.

  • قيود الشبكة: استخدم قيود IP أو تكامل الشبكة الافتراضية للحد من الوصول إلى عناوين IP المعروفة للعميل.
  • Rate limiting: نفذ تحديد المعدل في كود التطبيق أو قدم التطبيق إدارة Azure API.
  • التحقق من صحة الإدخال: تحقق من صحة جميع وسائط الأدوات في كود خادم MCP الخاص بك. مدخلات أدوات MCP هي JSON عشوائية. عاملهم كأنهم غير موثوقين.
  • التصميم بدون حالة: يفضل خوادم MCP بدون حالة لتجنب مخاطر اختطاف الجلسة. في معظم حزم تطوير البرمجيات (MCP)، يعني هذا تعطيل توليد معرفات الجلسة على جانب الخادم (على سبيل المثال، sessionIdGenerator: undefined في TypeScript أو stateless_http=True في Python).
  • مجسات الصحة: قم بتكوين مجسات الصحة على نقطة نهاية منفصلة (مثل /healthz)، وليس على نقطة نهاية MCP. تتوقع نقاط نهاية MCP طلبات POST JSON-RPC وأخطاء إرجاع لمجسات GET العادية.

جلسات ديناميكية مع مصادقة مفاتيح API

مهم

خادم MCP المدار على المنصة للجلسات الديناميكية في مرحلة المعاينة. نسخة 2025-02-02-preview API وخصائصها mcpServerSettings قابلة للتغيير.

خادم MCP المدار من قبل المنصة في الجلسات الديناميكية يستخدم مصادقة مفاتيح API. المفتاح مرتبط بمجموعة الجلسات ويمنح الوصول إلى جميع الأدوات والجلسات في المجموعة.

تدفق مصادقة مفاتيح API

تصف الخطوات التالية كيفية عمل مصادقة مفاتيح API للجلسات الديناميكية.

  1. يرسل العميل طلب JSON-RPC مع الرأس x-ms-apikey .
  2. يقوم وكيل تجمع الجلسات بالتحقق من صحة المفتاح مقابل مستوى التحكم في Azure.
  3. إذا كان المفتاح صالحا، يتم تحويل الطلب إلى الجلسة. إذا لم يكن كذلك، يتم إرجاع خطأ في المصادقة.

استرجاع مفتاح API

استخدم الأمر التالي لجلب مفتاح API لمجموعة الجلسات الخاصة بك.

API_KEY=$(az rest --method POST \
    --uri "https://management.azure.com/subscriptions/<SUBSCRIPTION_ID>/resourceGroups/<RESOURCE_GROUP>/providers/Microsoft.App/sessionPools/<SESSION_POOL_NAME>/fetchMCPServerCredentials" \
    --uri-parameters api-version=2025-02-02-preview \
    --query "apiKey" -o tsv)

تدوير وتخزين مفتاح API

يمكنك إعادة توليد مفتاح API في أي وقت. تقوم المنصة بتخزين نتائج التحقق مؤقتا لمدة تصل إلى خمس دقائق، لذا قد تستمر المفاتيح الصالحة سابقا في العمل بعد إعادة التوليد حتى انتهاء صلاحية الذاكرة المؤقتة.

لتدوير مفتاح API، قم باستدعاء الإجراء regenerateCredentials في مجموعة الجلسات:

az rest --method POST \
    --uri "https://management.azure.com/subscriptions/<SUBSCRIPTION_ID>/resourceGroups/<RESOURCE_GROUP>/providers/Microsoft.App/sessionPools/<SESSION_POOL_NAME>/regenerateCredentials" \
    --uri-parameters api-version=2025-02-02-preview

بعد التجدد، استرجع المفتاح الجديد باستخدام fetchMCPServerCredentials ما هو موضح سابقا.

توصيات الأمان للجلسات الديناميكية

طبق أفضل الممارسات التالية لتأمين نشر MCP الديناميكي لجلساتك الديناميكية.

  • نطاق مفاتيح API: يمنح مفتاح API الوصول إلى كامل مجموعة الجلسات. أي عميل يمتلك المفتاح يمكنه إنشاء بيئات وتنفيذ الكود. لا تشارك المفتاح مع أطراف غير موثوقة.
  • عزل البيئة: كل جلسة تعمل في حاوية معزولة Hyper-V. تنفيذ الكود في جلسة واحدة لا يمكنه الوصول إلى بيانات جلسة أخرى.
  • خروج الشبكة: التحكم فيما إذا كانت الجلسات يمكنها الوصول إلى الإنترنت باستخدام sessionNetworkConfiguration.status. قم بتعيين إذا EgressDisabled لم تكن الجلسات بحاجة إلى وصول خارجي للشبكة.
  • مدة عمر الجلسة: قم بتكوين coolDownPeriodInSeconds تدمير جلسات الخمول تلقائيا. هذا الإعداد يحد من نافذة التعرض إذا تم اختراق الجلسة.
  • Secret storage: تخزين مفتاح واجهة برمجة التطبيقات في Azure Key Vault أو Container Apps secrets بدلا من ملفات الكود أو الإعدادات.

عدم تطابقات المصادقة الشائعة

خطأ شائع هو استخدام رأس مفتاح API (x-ms-apikey) مع تطبيق حاوية مستقل، أو استخدام رمز حامل مع نقطة نهاية MCP الخاصة بالجلسات. الجدول التالي يوضح ما يحدث عند الخلط بينهما.

عدم تطابق Result
x-ms-apikey تم إرسال العنوان إلى تطبيق مستقل يتم تجاهل الرأس؛ يواجه الطلب المصادقة المدمجة ويعيد 401 إذا تم تفعيل المصادقة
Authorization: Bearer أرسلت إلى جلسات MCP فشل التحقق من صحة المفتاح وعاد 401
رمز حامل مطلوب بدون نطاق واجهة برمجة تطبيقات مكشوفة يفشل اقتناء الرمز أو لا يحصل الرمز على جمهور صالح، مما يؤدي إلى 401

تأكد من أن تكوين عميل MCP الخاص بك يطابق نموذج الاستضافة الذي قمت بنشره.