استخدام مراجع Key Vault كإعدادات تطبيق في Azure App Service وAzure Functions

إشعار

بدءا من 1 يونيو 2024، سيكون لجميع تطبيقات App Service التي تم إنشاؤها حديثا خيار إنشاء اسم مضيف افتراضي فريد باستخدام اصطلاح <app-name>-<random-hash>.<region>.azurewebsites.netالتسمية . ستظل أسماء التطبيقات الحالية دون تغيير.

مثال: myapp-ds27dh7271aah175.westus-01.azurewebsites.net

لمزيد من التفاصيل، راجع اسم المضيف الافتراضي الفريد لمورد App Service.

توضح لك هذه المقالة كيفية استخدام البيانات السرية من Azure Key Vault كقيم لإعدادات التطبيق أو سلسلة الاتصال في تطبيقات App Service أو Azure Functions.

يعد Azure Key Vault عبارة عن خدمة توفر إدارة مركزية للبيانات السرية، مع تحكم كامل في نُهج الوصول ومحفوظات التدقيق. عندما يكون إعداد التطبيق أو سلسلة الاتصال مرجعا لمخزن المفاتيح، يمكن أن تستخدمه التعليمات البرمجية للتطبيق مثل أي إعداد تطبيق آخر أو سلسلة الاتصال. وبهذه الطريقة، يمكنك الحفاظ على البيانات السرية بصرف النظر عن تكوين التطبيق. يتم تشفير إعدادات التطبيق بأمان في حالة الراحة، ولكن إذا كنت بحاجة إلى قدرات إدارة سرية، فيجب أن تنتقل إلى مخزن المفاتيح.

منح تطبيقك حق الوصول إلى key vault

لقراءة البيانات السرية من خزنة المفاتيح، تحتاج إلى إنشاء مخزن ومنح التطبيق الإذن للوصول إليه.

  1. قم بإنشاء مخزن مفاتيح باتباع Key Vault quickstart.

  2. قم بإنشاء هوية مُدارة لتطبيقك.

    تستخدم مراجع Key vault هوية التطبيق المعينة من قبل النظام بشكل افتراضي، ولكن يمكنك تحديد هوية معينة من قبل المستخدم.

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

الوصول إلى الخزائن المقيدة بالشبكة

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

  1. تأكد من أن التطبيق يحتوي على إمكانات شبكة صادرة مهيأة، كما هو موضح في ميزات شبكة خدمة التطبيقات وخيارات شبكة Azure Functions.

    يجب تكوين تطبيقات Linux التي تتصل بنقاط النهاية الخاصة بشكل صريح لتوجيه جميع حركة المرور عبر الشبكة الظاهرية. ستتم إزالة هذا المطلب في التحديث القادم. لتكوين هذا الإعداد، قم بتشغيل الأمر التالي:

    az webapp config set --subscription <sub> -g <group-name> -n <app-name> --generic-configurations '{"vnetRouteAllEnabled": true}'
    
  2. تأكد من أن تكوين المخزن يسمح للشبكة أو الشبكة الفرعية التي يستخدمها تطبيقك للوصول إليها.

الوصول إلى خزائن باستخدام هوية معينة من قبل المستخدم

تحتاج بعض التطبيقات إلى الإشارة إلى الأسرار في وقت الإنشاء، عندما لا تتوفر هوية معينة من قبل النظام بعد. في هذه الحالات، يمكن إنشاء هوية مخصصة للمستخدم ومنحها حق الوصول إلى المخزن مسبقًا.

بمجرد منحك أذونات للهوية المعينة من قبل المستخدم، اتبع الخطوات التالية:

  1. عيّن الهوية لتطبيقك إذا لم تكن قد قمت بذلك بالفعل.

  2. قم بتكوين التطبيق لاستخدام هذه الهوية للعمليات المرجعية لمخزن المفاتيح عن طريق تعيين الخاصية keyVaultReferenceIdentity إلى معرف المورد للهوية المعينة من قبل المستخدم.

    identityResourceId=$(az identity show --resource-group <group-name> --name <identity-name> --query id -o tsv)
    az webapp update --resource-group <group-name> --name <app-name> --set keyVaultReferenceIdentity=${identityResourceId}
    

ينطبق هذا الإعداد على جميع مراجع خزنة المفاتيح للتطبيق.

التدوير

إذا لم يتم تحديد الإصدار السري في المرجع، يستخدم التطبيق أحدث إصدار موجود في مخزن المفاتيح. عندما تتوفر إصدارات أحدث، مثل حدث التدوير، يقوم التطبيق تلقائيا بالتحديث والبدء في استخدام أحدث إصدار في غضون 24 ساعة. يرجع التأخير إلى أن خدمة التطبيقات تخزن مؤقتًا قيم مراجع خزنة المفاتيح وتعيد تعيينها كل 24 ساعة. يؤدي أي تغيير في التكوين إلى التطبيق إلى إعادة تشغيل التطبيق وإعادة تعبئة فورية لجميع الأسرار المشار إليها.

إعدادات تطبيق المصدر من key vault

لاستخدام مرجع key vault، قم بتعيين المرجع كقيمة للإعداد. يمكن لتطبيقك الرجوع إلى السر من خلال مفتاحه كالمعتاد. لا يلزم إجراء أية تغييرات في التعليمات البرمجية.

تلميح

يجب وضع علامة على معظم إعدادات التطبيق التي تستخدم مراجع خزنة المفاتيح كإعدادات فتحة، حيث يجب أن يكون لديك خزائن منفصلة لكل بيئة.

مرجع key vault هو من النموذج @Microsoft.KeyVault({referenceString})، حيث {referenceString} يوجد في أحد التنسيقات التالية:

سلسلة مرجعية ‏‏الوصف
SecretUri=secretUri يجب أن يكون SecretUri هو URI لمستوى البيانات الكامل للبيانات السرية في المخزن، على سبيل المثال https://myvault.vault.azure.net/secrets/mysecret. اختياريا، قم بتضمين إصدار، مثل https://myvault.vault.azure.net/secrets/mysecret/ec96f02080254f109c51a1f14cdb1931.
VaultName = vaultName ؛ SecretName = secretName ؛ SecretVersion = secretVersion اسم VaultName مطلوب وهو اسم المخزن. SecretName مطلوب وهو الاسم السري. يعد SecretVersion اختياريًا ولكن إذا كان موجودًا يشير إلى إصدار السر المطلوب استخدامه.

على سبيل المثال، قد يبدو المرجع الكامل بدون إصدار معين مثل السلسلة التالية:

@Microsoft.KeyVault(SecretUri=https://myvault.vault.azure.net/secrets/mysecret)

بديل:

@Microsoft.KeyVault(VaultName=myvault;SecretName=mysecret)

اعتبارات خاصة بتركيب ملفات Azure

يمكن للتطبيقات استخدام WEBSITE_CONTENTAZUREFILECONNECTIONSTRING إعداد التطبيق لتحميل ملفات Azure كنظام ملفات. يحتوي هذا الإعداد على فحوصات التحقق من الصحة للتأكد من إمكانية بدء تشغيل التطبيق بشكل صحيح. يعتمد النظام الأساسي على مشاركة محتوى داخل Azure Files، ويفترض اسمًا افتراضيًا ما لم يتم تحديد اسم عبر إعداد WEBSITE_CONTENTSHARE. بالنسبة لأي طلبات تعدل هذه الإعدادات، يتحقق النظام الأساسي مما إذا كانت مشاركة المحتوى هذه موجودة، ويحاول إنشائها إن لم يكن الأمر كذلك. إذا تعذر عليه تحديد موقع مشاركة المحتوى أو إنشائها، فإنه يحظر الطلب.

عند استخدام مراجع خزنة المفاتيح في هذا الإعداد، يفشل التحقق من الصحة بشكل افتراضي، لأنه لا يمكن حل السر نفسه أثناء معالجة الطلب الوارد. لتجنب هذه المشكلة، يمكنك تخطي عملية التحقق من خلال تعيين WEBSITE_SKIP_CONTENTSHARE_VALIDATION على "1". يخبر هذا الإعداد App Service بتجاوز جميع عمليات التحقق، ولا ينشئ مشاركة المحتوى نيابة عنك. يجب عليك التأكد من إنشائه مسبقا.

تنبيه

إذا تخطيت التحقق وكانت سلسلة الاتصال أو مشاركة المحتوى غير صالحة، فلن يتمكن التطبيق من البدء بشكل صحيح وسيعرض فقط أخطاء HTTP 500.

كجزء من إنشاء التطبيق، قد تفشل محاولة تحميل مشاركة المحتوى بسبب عدم نشر أذونات الهوية المدارة أو عدم إعداد تكامل الشبكة الظاهرية. يمكنك تأجيل إعداد ملفات Azure حتى وقت لاحق في قالب النشر لاستيعاب ذلك. راجع توزيع Azure Resource Manager لمعرفة المزيد. في هذه الحالة، تستخدم App Service نظام ملفات افتراضيا حتى يتم إعداد ملفات Azure، ولا يتم نسخ الملفات. يجب التأكد من عدم حدوث أي محاولات نشر خلال الفترة المؤقتة قبل تحميل ملفات Azure.

اعتبارات تقرير عن حالة النظام في Application Insights

يمكن للتطبيقات استخدام APPINSIGHTS_INSTRUMENTATIONKEY إعدادات التطبيق أو APPLICATIONINSIGHTS_CONNECTION_STRING للتكامل مع Application Insights. تستخدم تجارب المدخل ل App Service وAzure Functions أيضا هذه الإعدادات لعرض بيانات تتبع الاستخدام من المورد. إذا تم الرجوع إلى هذه القيم من Key Vault، فلن تتوفر هذه التجارب، وبدلا من ذلك تحتاج إلى العمل مباشرة مع مورد Application Insights لعرض بيانات تتبع الاستخدام. ومع ذلك، لا تعتبر هذه القيم أسرارا، لذلك قد تفكر بدلا من ذلك في تكوينها مباشرة بدلا من استخدام مراجع خزنة المفاتيح.

استخدام Azure Resource Manager

عند أتمتة عمليات نشر الموارد من خلال قوالب Azure Resource Manager، قد تحتاج إلى ترتيب تبعياتك بترتيب معين لجعل هذه الميزة تعمل. تأكد من تعريف إعدادات التطبيق كمورد خاص بها، بدلا من استخدام خاصية siteConfig في تعريف التطبيق. وذلك لأن التطبيق يحتاج إلى تعريف أولا بحيث يتم إنشاء الهوية المعينة من قبل النظام معها ويمكن استخدامها في نهج الوصول.

القالب الزائف التالي هو مثال على الشكل الذي قد يبدو عليه تطبيق الوظائف:

{
    //...
    "resources": [
        {
            "type": "Microsoft.Storage/storageAccounts",
            "name": "[variables('storageAccountName')]",
            //...
        },
        {
            "type": "Microsoft.Insights/components",
            "name": "[variables('appInsightsName')]",
            //...
        },
        {
            "type": "Microsoft.Web/sites",
            "name": "[variables('functionAppName')]",
            "identity": {
                "type": "SystemAssigned"
            },
            //...
            "resources": [
                {
                    "type": "config",
                    "name": "appsettings",
                    //...
                    "dependsOn": [
                        "[resourceId('Microsoft.Web/sites', variables('functionAppName'))]",
                        "[resourceId('Microsoft.KeyVault/vaults/', variables('keyVaultName'))]",
                        "[resourceId('Microsoft.KeyVault/vaults/secrets', variables('keyVaultName'), variables('storageConnectionStringName'))]",
                        "[resourceId('Microsoft.KeyVault/vaults/secrets', variables('keyVaultName'), variables('appInsightsKeyName'))]"
                    ],
                    "properties": {
                        "AzureWebJobsStorage": "[concat('@Microsoft.KeyVault(SecretUri=', reference(variables('storageConnectionStringName')).secretUriWithVersion, ')')]",
                        "WEBSITE_CONTENTAZUREFILECONNECTIONSTRING": "[concat('@Microsoft.KeyVault(SecretUri=', reference(variables('storageConnectionStringName')).secretUriWithVersion, ')')]",
                        "APPINSIGHTS_INSTRUMENTATIONKEY": "[concat('@Microsoft.KeyVault(SecretUri=', reference(variables('appInsightsKeyName')).secretUriWithVersion, ')')]",
                        "WEBSITE_ENABLE_SYNC_UPDATE_SITE": "true"
                        //...
                    }
                },
                {
                    "type": "sourcecontrols",
                    "name": "web",
                    //...
                    "dependsOn": [
                        "[resourceId('Microsoft.Web/sites', variables('functionAppName'))]",
                        "[resourceId('Microsoft.Web/sites/config', variables('functionAppName'), 'appsettings')]"
                    ],
                }
            ]
        },
        {
            "type": "Microsoft.KeyVault/vaults",
            "name": "[variables('keyVaultName')]",
            //...
            "dependsOn": [
                "[resourceId('Microsoft.Web/sites', variables('functionAppName'))]"
            ],
            "properties": {
                //...
                "accessPolicies": [
                    {
                        "tenantId": "[reference(resourceId('Microsoft.Web/sites/', variables('functionAppName')), '2020-12-01', 'Full').identity.tenantId]",
                        "objectId": "[reference(resourceId('Microsoft.Web/sites/', variables('functionAppName')), '2020-12-01', 'Full').identity.principalId]",
                        "permissions": {
                            "secrets": [ "get" ]
                        }
                    }
                ]
            },
            "resources": [
                {
                    "type": "secrets",
                    "name": "[variables('storageConnectionStringName')]",
                    //...
                    "dependsOn": [
                        "[resourceId('Microsoft.KeyVault/vaults/', variables('keyVaultName'))]",
                        "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]"
                    ],
                    "properties": {
                        "value": "[concat('DefaultEndpointsProtocol=https;AccountName=', variables('storageAccountName'), ';AccountKey=', listKeys(variables('storageAccountResourceId'),'2019-09-01').key1)]"
                    }
                },
                {
                    "type": "secrets",
                    "name": "[variables('appInsightsKeyName')]",
                    //...
                    "dependsOn": [
                        "[resourceId('Microsoft.KeyVault/vaults/', variables('keyVaultName'))]",
                        "[resourceId('Microsoft.Insights/components', variables('appInsightsName'))]"
                    ],
                    "properties": {
                        "value": "[reference(resourceId('microsoft.insights/components/', variables('appInsightsName')), '2019-09-01').InstrumentationKey]"
                    }
                }
            ]
        }
    ]
}

إشعار

في هذا المثال، يعتمد نشر التحكم بالمصادر على إعدادات التطبيق. يعد هذا عادةً سلوكًا غير آمن، حيث يعمل تحديث إعدادات التطبيق بشكل غير متزامن. ومع ذلك، نظرًا لأننا قمنا بتضمين إعداد التطبيق WEBSITE_ENABLE_SYNC_UPDATE_SITE، فإن التحديث متزامن. هذا يعني أن نشر التحكم بالمصادر سيبدأ بمجرد تحديث إعدادات التطبيق بالكامل. لمزيد من إعدادات التطبيق، راجع متغيرات البيئة وإعدادات التطبيق في Azure App Service.

استكشاف أخطاء مراجع خزنة المفاتيح وإصلاحها

إذا لم يتم حل مرجع بشكل صحيح، يتم استخدام السلسلة المرجعية بدلا من ذلك (على سبيل المثال، @Microsoft.KeyVault(...)). قد يتسبب التطبيق في طرح أخطاء، لأنه يتوقع سرا بقيمة مختلفة.

يرجع الفشل في الحل عادة إلى التكوين الخاطئ لنهج الوصول إلى Key Vault. ومع ذلك، قد يكون أيضًا بسبب سر لم يعد موجودًا أو خطأ نحوي في المرجع نفسه.

إذا كانت البنية صحيحة، يمكنك عرض الأسباب الأخرى للخطأ عن طريق التحقق من حالة الدقة الحالية في المدخل. انتقل إلى إعدادات التطبيق وحدد "تحرير" للمرجع المعني. يعرض مربع الحوار تحرير معلومات الحالة، بما في ذلك أي أخطاء. إذا لم تشاهد رسالة الحالة، فهذا يعني أن بناء الجملة غير صالح ولا يتم التعرف عليه كمرجع مخزن مفاتيح.

يمكنك أيضًا استخدام أحد أجهزة الكشف المدمجة للحصول على معلومات إضافية.

استخدام الكاشف لخدمة التطبيقات

  1. في المدخل، انتقل إلى التطبيق الخاص بك.
  2. حدد تشخيص المشكلات وحلها.
  3. اختر التوفر والأداء وحدد تطبيق الويب معطلاً.
  4. في مربع البحث، ابحث عن Key Vault Application Settings Diagnostics وحدده.

استخدام الكاشف لوظائف Azure

  1. في المدخل، انتقل إلى التطبيق الخاص بك.
  2. انتقل إلى ميزات النظام الأساسي.
  3. حدد تشخيص المشكلات وحلها.
  4. اختر التوفر والأداء وحدد تعطيل تطبيق الوظيفة أو الإبلاغ عن الأخطاء.
  5. حدد Key Vault Application Settings Diagnostics.