البرنامج التعليمي: إضافة نقطة نهاية HTTPS لتطبيق Service Fabric باستخدام Kestrel
هذا البرنامج التعليمي هو الجزء الثالث في سلسلة. تعرف على كيفية إضافة نقطة نهاية HTTPS في خدمة ASP.NET Core قيد التشغيل في Azure Service Fabric. عند الانتهاء، يكون لديك تطبيق تصويت يحتوي على واجهة ويب ASP.NET Core التي تدعم HTTPS والتي تستمع على المنفذ 443. إذا كنت لا تريد إنشاء تطبيق التصويت يدويا في الجزء الأول من سلسلة البرامج التعليمية، يمكنك تنزيل التعليمات البرمجية المصدر للحصول على التطبيق المكتمل.
في هذا البرنامج التعليمي، تتعلم كيفية:
- تعريف نقطة نهاية HTTPS في الخدمة
- إعداد Kestrel لاستخدام HTTPS
- تثبيت شهادة TLS/SSL على عقد نظام المجموعة البعيدة
- منح NetworkService حق الوصول إلى المفتاح الخاص للشهادة
- فتح منفذ 443 في موازن تحميل Azure
- نشر التطبيق على نظام المجموعة البعيدة
توضح لك سلسلة البرامج التعليمية كيفية:
- إنشاء تطبيق .NET Service Fabric
- نشر التطبيق على نظام المجموعة البعيدة
- إضافة نقطة نهاية HTTPS إلى خدمة الواجهة الأمامية الأساسية ASP.NET (هذا البرنامج التعليمي)
- تكوين CI/CD باستخدام Azure Pipelines
- إعداد المراقبة والتشخيصات للتطبيق
إشعار
نوصي باستخدام الوحدة النمطية Azure Az PowerShell للتفاعل مع Azure. للبدء، راجع تثبيت Azure PowerShell. لمعرفة كيفية الترحيل إلى الوحدة النمطية Az PowerShell، راجع ترحيل Azure PowerShell من AzureRM إلى Az.
المتطلبات الأساسية
قبل أن تبدأ هذا البرنامج التعليمي:
- إذا لم يكن لديك اشتراك Azure، فأنشئ حسابًا مجانًا.
- تثبيت Visual Studio 2019 الإصدار 16.5 أو أحدث، بما في ذلك حمل عمل تطوير Azure وعبء عمل تطوير ASP.NET والويب.
- تثبيت Service Fabric SDK.
الحصول على شهادة أو إنشاء شهادة تطوير موقعة ذاتيا
بالنسبة لتطبيقات الإنتاج، استخدم شهادة من مرجع مصدق (CA). لأغراض التطوير والاختبار، يمكنك إنشاء شهادة موقعة ذاتياً واستخدامها. يتضمن Service Fabric SDK البرنامج النصي CertSetup.ps1 . يقوم البرنامج النصي بإنشاء شهادة موقعة ذاتيا واستيرادها إلى مخزن الشهادات Cert:\LocalMachine\My . افتح نافذة موجه الأوامر كمسؤول وقم بتشغيل الأمر التالي لإنشاء شهادة تحتوي على الموضوع "CN=mytestcert":
PS C:\program files\microsoft sdks\service fabric\clustersetup\secure> .\CertSetup.ps1 -Install -CertSubjectName CN=mytestcert
إذا كان لديك بالفعل ملف Certificate Personal Information Exchange (PFX)، فقم بتشغيل ما يلي لاستيراد الشهادة إلى Cert:\LocalMachine\My certificate store:
PS C:\mycertificates> Import-PfxCertificate -FilePath .\mysslcertificate.pfx -CertStoreLocation Cert:\LocalMachine\My -Password (ConvertTo-SecureString "!Passw0rd321" -AsPlainText -Force)
PSParentPath: Microsoft.PowerShell.Security\Certificate::LocalMachine\My
Thumbprint Subject
---------- -------
3B138D84C077C292579BA35E4410634E164075CD CN=zwin7fh14scd.westus.cloudapp.azure.com
تعريف نقطة نهاية HTTPS في بيان الخدمة
افتح Visual Studio باستخدام الخيار تشغيل كمسؤول ، ثم افتح حل التصويت. في مستكشف الحلول، يرجى فتح VotingWeb/PackageRoot/ServiceManifest.xml. يُعرّف بيان الخدمة نقاط نهاية الخدمة. ابحث عن Endpoints
المقطع وقم بتحرير قيمة ServiceEndpoint
نقطة النهاية. غير الاسم إلى EndpointHttps
، واضبط البروتوكول على https
، والنوع إلى Input
، والمنفذ إلى 443
. احفظ تغييراتك.
<?xml version="1.0" encoding="utf-8"?>
<ServiceManifest Name="VotingWebPkg"
Version="1.0.0"
xmlns="http://schemas.microsoft.com/2011/01/fabric"
xmlns:xsd="https://www.w3.org/2001/XMLSchema"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance">
<ServiceTypes>
<StatelessServiceType ServiceTypeName="VotingWebType" />
</ServiceTypes>
<CodePackage Name="Code" Version="1.0.0">
<EntryPoint>
<ExeHost>
<Program>VotingWeb.exe</Program>
<WorkingFolder>CodePackage</WorkingFolder>
</ExeHost>
</EntryPoint>
</CodePackage>
<ConfigPackage Name="Config" Version="1.0.0" />
<Resources>
<Endpoints>
<Endpoint Protocol="https" Name="EndpointHttps" Type="Input" Port="443" />
</Endpoints>
</Resources>
</ServiceManifest>
تكوين Kestrel لاستخدام HTTPS
فتح ملف VotingWeb/VotingWeb.cs في مستكشف الحلول. قم بتكوين Kestrel لاستخدام HTTPS والبحث عن الشهادة في Cert:\LocalMachine\My store. أضف عبارات using
التالية:
using System.Net;
using Microsoft.Extensions.Configuration;
using System.Security.Cryptography.X509Certificates;
قم بتحديث قيمة ServiceInstanceListener
لاستخدام نقطة النهاية الجديدة EndpointHttps
والاستماع على المنفذ 443. عند إعداد مضيف الويب لاستخدام خادم Kestrel، يجب تكوين Kestrel للاستماع إلى عناوين IPv6 على جميع واجهات الشبكة: opt.Listen(IPAddress.IPv6Any, port, listenOptions => {...}
.
new ServiceInstanceListener(
serviceContext =>
new KestrelCommunicationListener(
serviceContext,
"EndpointHttps",
(url, listener) =>
{
ServiceEventSource.Current.ServiceMessage(serviceContext, $"Starting Kestrel on {url}");
return new WebHostBuilder()
.UseKestrel(opt =>
{
int port = serviceContext.CodePackageActivationContext.GetEndpoint("EndpointHttps").Port;
opt.Listen(IPAddress.IPv6Any, port, listenOptions =>
{
listenOptions.UseHttps(FindMatchingCertificateBySubject());
listenOptions.NoDelay = true;
});
})
.ConfigureAppConfiguration((builderContext, config) =>
{
config.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);
})
.ConfigureServices(
services => services
.AddSingleton<HttpClient>(new HttpClient())
.AddSingleton<FabricClient>(new FabricClient())
.AddSingleton<StatelessServiceContext>(serviceContext))
.UseContentRoot(Directory.GetCurrentDirectory())
.UseStartup<Startup>()
.UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.None)
.UseUrls(url)
.Build();
}))
بعد ذلك، أضف الأسلوب التالي بحيث يمكن ل Kestrel العثور على الشهادة في Cert:\LocalMachine\My store باستخدام الموضوع.
استبدل <your_CN_value>
ب mytestcert
إذا قمت بإنشاء شهادة موقعة ذاتيا باستخدام أمر PowerShell السابق، أو استخدم CN لشهادتك.
إذا كنت تستخدم نشرا محليا إلى localhost
، نوصي باستخدام CN=localhost
لتجنب استثناءات المصادقة.
private X509Certificate2 FindMatchingCertificateBySubject(string subjectCommonName)
{
using (var store = new X509Store(StoreName.My, StoreLocation.LocalMachine))
{
store.Open(OpenFlags.OpenExistingOnly | OpenFlags.ReadOnly);
var certCollection = store.Certificates;
var matchingCerts = new X509Certificate2Collection();
foreach (var enumeratedCert in certCollection)
{
if (StringComparer.OrdinalIgnoreCase.Equals(subjectCommonName, enumeratedCert.GetNameInfo(X509NameType.SimpleName, forIssuer: false))
&& DateTime.Now < enumeratedCert.NotAfter
&& DateTime.Now >= enumeratedCert.NotBefore)
{
matchingCerts.Add(enumeratedCert);
}
}
if (matchingCerts.Count == 0)
{
throw new Exception($"Could not find a match for a certificate with subject 'CN={subjectCommonName}'.");
}
return matchingCerts[0];
}
}
منح خدمة الشبكة حق الوصول إلى المفتاح الخاص للشهادة
في خطوة سابقة، قمت باستيراد الشهادة إلى Cert:\LocalMachine\My store على كمبيوتر التطوير.
الآن، امنح الحساب الذي يقوم بتشغيل الخدمة (خدمة الشبكة، بشكل افتراضي) حق الوصول إلى المفتاح الخاص للشهادة. يمكنك القيام بهذه الخطوة يدويا (باستخدام أداة certlm.msc )، ولكن من الأفضل تشغيل برنامج نصي PowerShell عن طريق تكوين برنامج نصي لبدء التشغيل في SetupEntryPoint
بيان الخدمة.
إشعار
يدعم Service Fabric الإعلان عن شهادات نقطة النهاية بواسطة بصمة الإبهام أو حسب الاسم الشائع للموضوع. في هذه الحالة، يقوم وقت التشغيل بإعداد الربط والتخصيص للمفتاح الخاص للشهادة للهوية التي تعمل بها الخدمة. يراقب وقت التشغيل أيضا الشهادة للتغييرات والتجديدات وتحديثات التخصيص للمفتاح الخاص المقابل.
تكوين نقطة إدخال لإعداد الخدمة
في مستكشف الحلول، يرجى فتح VotingWeb/PackageRoot/ServiceManifest.xml. في CodePackage
القسم ، أضف العقدة SetupEntryPoint
، ثم أضف عقدة ExeHost
. في ExeHost
، قم بتعيين Program
إلى Setup.bat
، ثم قم بتعيين WorkingFolder
إلى CodePackage
. عند بدء تشغيل خدمة VotingWeb، يتم تنفيذ البرنامج النصي Setup.bat في مجلد CodePackage قبل بدء VotingWeb.exe .
<?xml version="1.0" encoding="utf-8"?>
<ServiceManifest Name="VotingWebPkg"
Version="1.0.0"
xmlns="http://schemas.microsoft.com/2011/01/fabric"
xmlns:xsd="https://www.w3.org/2001/XMLSchema"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance">
<ServiceTypes>
<StatelessServiceType ServiceTypeName="VotingWebType" />
</ServiceTypes>
<CodePackage Name="Code" Version="1.0.0">
<SetupEntryPoint>
<ExeHost>
<Program>Setup.bat</Program>
<WorkingFolder>CodePackage</WorkingFolder>
</ExeHost>
</SetupEntryPoint>
<EntryPoint>
<ExeHost>
<Program>VotingWeb.exe</Program>
<WorkingFolder>CodePackage</WorkingFolder>
</ExeHost>
</EntryPoint>
</CodePackage>
<ConfigPackage Name="Config" Version="1.0.0" />
<Resources>
<Endpoints>
<Endpoint Protocol="https" Name="EndpointHttps" Type="Input" Port="443" />
</Endpoints>
</Resources>
</ServiceManifest>
إضافة الدفعة والبرامج النصية لإعداد PowerShell
لتشغيل PowerShell من قيمة ل SetupEntryPoint
، يمكنك تشغيل PowerShell.exe في ملف دفعي يشير إلى ملف PowerShell.
أولاً، إضافة ملف الدفعة لمشروع الخدمة. في مستكشف الحلول، انقر بزر الماوس الأيمن فوق VotingWeb، ثم حدد إضافة>عنصر جديد. إضافة ملف جديد يسمى Setup.bat. تحرير ملف Setup.bat وإضافة الأمر التالي:
powershell.exe -ExecutionPolicy Bypass -Command ".\SetCertAccess.ps1"
تعديل خصائص ملف Setup.bat لتعيين نسخ إلى دليل الإخراج إلى نسخ إذا كان أحدث.
في مستكشف الحلول، انقر بزر الماوس الأيمن فوق VotingWeb. ثم حدد إضافة>عنصر جديد، وأضف ملفا جديدا باسم SetCertAccess.ps1. قم بتحرير ملف SetCertAccess.ps1 لإضافة البرنامج النصي التالي:
$subject="mytestcert"
$userGroup="Network Service"
Write-Host "Checking permissions to certificate $subject.." -ForegroundColor DarkCyan
$cert = (gci Cert:\LocalMachine\My\ | where { $_.Subject.Contains($subject) })[-1]
if ($cert -eq $null)
{
$message="Certificate with subject:"+$subject+" does not exist at Cert:\LocalMachine\My\"
Write-Host $message -ForegroundColor Red
exit 1;
}elseif($cert.HasPrivateKey -eq $false){
$message="Certificate with subject:"+$subject+" does not have a private key"
Write-Host $message -ForegroundColor Red
exit 1;
}else
{
$keyName=$cert.PrivateKey.CspKeyContainerInfo.UniqueKeyContainerName
$keyPath = "C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys\"
if ($keyName -eq $null){
$privateKey = [System.Security.Cryptography.X509Certificates.RSACertificateExtensions]::GetRSAPrivateKey($cert)
$keyName = $privateKey.Key.UniqueName
$keyPath = "C:\ProgramData\Microsoft\Crypto\Keys"
}
$fullPath=$keyPath+$keyName
$acl=(Get-Item $fullPath).GetAccessControl('Access')
$hasPermissionsAlready = ($acl.Access | where {$_.IdentityReference.Value.Contains($userGroup.ToUpperInvariant()) -and $_.FileSystemRights -eq [System.Security.AccessControl.FileSystemRights]::FullControl}).Count -eq 1
if ($hasPermissionsAlready){
Write-Host "Account $userGroup already has permissions to certificate '$subject'." -ForegroundColor Green
return $false;
} else {
Write-Host "Need add permissions to '$subject' certificate..." -ForegroundColor DarkYellow
$permission=$userGroup,"Full","Allow"
$accessRule=new-object System.Security.AccessControl.FileSystemAccessRule $permission
$acl.AddAccessRule($accessRule)
Set-Acl $fullPath $acl
Write-Output "Permissions were added"
return $true;
}
}
تعديل خصائص ملف SetCertAccess.ps1 لتعيين نسخ إلى دليل الإخراج إلى نسخ إذا كان أحدث.
تشغيل البرنامج النصي للإعداد كمسؤول
بشكل افتراضي، يتم تشغيل نقطة إدخال إعداد الخدمة القابلة للتنفيذ باستخدام نفس بيانات الاعتماد مثل Service Fabric (عادة، حساب خدمة الشبكة). يتطلب SetCertAccess.ps1 أذونات المسؤول. في بيان التطبيق، يمكنك تغيير أذونات الأمان لتشغيل برنامج بدء التشغيل النصي ضمن حساب مسؤول محلي.
في مستكشف الحلول، يمكنك فتح Voting/ApplicationPackageRoot/ApplicationManifest.xml. أولا، أنشئ قسما Principals
وأضف مستخدما جديدا (على سبيل المثال، SetupAdminUser
). إضافة حساب المستخدم SetupAdminUser إلى مجموعة نظام المسؤولين.
بعد ذلك، في VotingWebPkg، في ServiceManifestImport
القسم ، قم بتكوين RunAsPolicy لتطبيق أساس SetupAdminUser على نقطة إدخال الإعداد. يخبر هذا النهج Service Fabric أن ملف Setup.bat يعمل ك SetupAdminUser (مع أذونات المسؤول).
<?xml version="1.0" encoding="utf-8"?>
<ApplicationManifest xmlns:xsd="https://www.w3.org/2001/XMLSchema" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" ApplicationTypeName="VotingType" ApplicationTypeVersion="1.0.0" xmlns="http://schemas.microsoft.com/2011/01/fabric">
<Parameters>
<Parameter Name="VotingData_MinReplicaSetSize" DefaultValue="3" />
<Parameter Name="VotingData_PartitionCount" DefaultValue="1" />
<Parameter Name="VotingData_TargetReplicaSetSize" DefaultValue="3" />
<Parameter Name="VotingWeb_InstanceCount" DefaultValue="-1" />
</Parameters>
<ServiceManifestImport>
<ServiceManifestRef ServiceManifestName="VotingDataPkg" ServiceManifestVersion="1.0.0" />
<ConfigOverrides />
</ServiceManifestImport>
<ServiceManifestImport>
<ServiceManifestRef ServiceManifestName="VotingWebPkg" ServiceManifestVersion="1.0.0" />
<ConfigOverrides />
<Policies>
<RunAsPolicy CodePackageRef="Code" UserRef="SetupAdminUser" EntryPointType="Setup" />
</Policies>
</ServiceManifestImport>
<DefaultServices>
<Service Name="VotingData">
<StatefulService ServiceTypeName="VotingDataType" TargetReplicaSetSize="[VotingData_TargetReplicaSetSize]" MinReplicaSetSize="[VotingData_MinReplicaSetSize]">
<UniformInt64Partition PartitionCount="[VotingData_PartitionCount]" LowKey="0" HighKey="25" />
</StatefulService>
</Service>
<Service Name="VotingWeb" ServicePackageActivationMode="ExclusiveProcess">
<StatelessService ServiceTypeName="VotingWebType" InstanceCount="[VotingWeb_InstanceCount]">
<SingletonPartition />
</StatelessService>
</Service>
</DefaultServices>
<Principals>
<Users>
<User Name="SetupAdminUser">
<MemberOf>
<SystemGroup Name="Administrators" />
</MemberOf>
</User>
</Users>
</Principals>
</ApplicationManifest>
تشغيل تطبيق ويب محليًا
في مستكشف الحلول، حدد تطبيق التصويت وضبط خاصية عنوان URL للتطبيق على https://localhost:443
.
احفظ جميع الملفات، ثم حدد F5 لتشغيل التطبيق محليا. بعد نشر التطبيق، يفتح مستعرض على https://localhost:443
. إذا كنت تستخدم شهادة موقعة ذاتيا، فسترى تحذيرا بأن جهاز الكمبيوتر الخاص بك لا يثق في أمان موقع الويب هذا. تابع إلى صفحة الويب.
تثبيت الشهادة على عقد نظام المجموعة
قبل نشر التطبيق إلى Azure، قم بتثبيت الشهادة في Cert:\LocalMachine\My store لجميع عقد نظام المجموعة البعيدة. يمكن نقل الخدمات إلى عقد مختلفة بنظام المجموعة. عند بدء تشغيل خدمة الويب الأمامية على عقدة نظام المجموعة، يبحث البرنامج النصي لبدء التشغيل عن الشهادة وتكوين أذونات الوصول.
لتثبيت الشهادة على عقد نظام المجموعة، قم أولا بتصدير الشهادة كملف PFX. افتح ملف تطبيق certlm.msc وانتقل إلى الشهادات الشخصية>. انقر بزر الماوس الأيمن فوق شهادة mytestcert، ثم حدد تصدير كافة المهام>.
في معالج التصدير، حدد نعم، وقم بتصدير المفتاح الخاص، ثم حدد تنسيق PFX. تصدير الملف إلى C:\Users\sfuser\votingappcert.pfx.
بعد ذلك، قم بتثبيت الشهادة على نظام المجموعة البعيد باستخدام البرامج النصية PowerShell.
تحذير
شهادة موقعة ذاتياً كافية لتطوير التطبيقات واختبارها. بالنسبة لتطبيقات الإنتاج، استخدم شهادة من مرجع مصدق (CA) بدلا من استخدام شهادة موقعة ذاتيا.
فتح منفذ 443 في موازن تحميل Azure والشبكة الظاهرية
افتح المنفذ 443 في موازن التحميل إذا لم يكن مفتوحا:
$probename = "AppPortProbe6"
$rulename="AppPortLBRule6"
$RGname="voting_RG"
$port=443
# Get the load balancer resource
$resource = Get-AzResource | Where {$_.ResourceGroupName –eq $RGname -and $_.ResourceType -eq "Microsoft.Network/loadBalancers"}
$slb = Get-AzLoadBalancer -Name $resource.Name -ResourceGroupName $RGname
# Add a new probe configuration to the load balancer
$slb | Add-AzLoadBalancerProbeConfig -Name $probename -Protocol Tcp -Port $port -IntervalInSeconds 15 -ProbeCount 2
# Add rule configuration to the load balancer
$probe = Get-AzLoadBalancerProbeConfig -Name $probename -LoadBalancer $slb
$slb | Add-AzLoadBalancerRuleConfig -Name $rulename -BackendAddressPool $slb.BackendAddressPools[0] -FrontendIpConfiguration $slb.FrontendIpConfigurations[0] -Probe $probe -Protocol Tcp -FrontendPort $port -BackendPort $port
# Set the goal state for the load balancer
$slb | Set-AzLoadBalancer
قم بنفس الشيء للشبكة الظاهرية المقترنة:
$rulename="allowAppPort$port"
$nsgname="voting-vnet-security"
$RGname="voting_RG"
$port=443
# Get the network security group resource
$nsg = Get-AzNetworkSecurityGroup -Name $nsgname -ResourceGroupName $RGname
# Add the inbound security rule.
$nsg | Add-AzNetworkSecurityRuleConfig -Name $rulename -Description "Allow app port" -Access Allow `
-Protocol * -Direction Inbound -Priority 3891 -SourceAddressPrefix "*" -SourcePortRange * `
-DestinationAddressPrefix * -DestinationPortRange $port
# Update the network security group
$nsg | Set-AzNetworkSecurityGroup
نشر التطبيق على Azure
احفظ جميع الملفات، والتبديل من Debug إلى Release، وحدد F6 لإعادة البناء. في مستكشف الحلول، انقر بزر الماوس الأيمن فوق التصويت وحدد نشر. يمكن تحديد نقطة نهاية الاتصال بنظام المجموعة التي تم إنشاؤها في نشر تطبيق بنظام المجموعةأو تحديد نظام مجموعة أخرى. حدد Publish لنشر التطبيق إلى نظام المجموعة البعيد.
عند نشر التطبيق، افتح مستعرض ويب وانتقل إلى https://mycluster.region.cloudapp.azure.com:443
(تحديث عنوان URL بنقطة نهاية الاتصال للمجموعة). إذا كنت تستخدم شهادة موقعة ذاتيا، فسترى تحذيرا بأن جهاز الكمبيوتر الخاص بك لا يثق في أمان موقع الويب هذا. تابع إلى صفحة الويب.
الخطوة التالية
تقدم إلى البرنامج التعليمي الآتي: