Руководство. Добавление конечной точки HTTPS для приложения Service Fabric с помощью Kestrel
Это руководство является частью трех в серии. Узнайте, как добавить конечную точку HTTPS в службу ASP.NET Core, запущенную в Azure Service Fabric. По завершении у вас есть приложение для голосования с поддержкой HTTPS, ASP.NET веб-интерфейс Core, который прослушивает порт 443. Если вы не хотите вручную создать приложение для голосования в одной из серии учебников, можно скачать исходный код , чтобы получить готовое приложение.
В этом руководстве описано следующее:
- Определение конечной точки HTTPS в службе.
- Настройка Kestrel для использования HTTPS
- Настройка TLS/SSL-сертификата на узлах удаленного кластера
- Предоставление сетевой службе доступа к закрытому ключу сертификата
- Открытие порта 443 в подсистеме балансировки нагрузки Azure
- Развертывание приложения в удаленном кластере.
В серии учебников показано, как:
- Создание приложения .NET Service Fabric.
- Развертывание приложения в удаленном кластере.
- Добавление конечной точки HTTPS в интерфейсную службу ASP.NET Core (это руководство)
- Настройка CI/CD с помощью Azure Pipelines
- Настройка мониторинга и диагностики приложения
Примечание.
Мы рекомендуем использовать модуль Azure Az PowerShell для взаимодействия с Azure. Сведения о начале работы см. в статье "Установка Azure PowerShell". Дополнительные сведения см. в статье Перенос Azure PowerShell с AzureRM на Az.
Необходимые компоненты
Перед началом работы с этим руководством выполните следующие действия:
- Если у вас еще нет подписки Azure, создайте бесплатную учетную запись.
- Установите Visual Studio 2019 версии 16.5 или более поздней версии, включая рабочую нагрузку разработки Azure и рабочую нагрузку ASP.NET и веб-разработки.
- Установите пакет SDK для Service Fabric.
Получение сертификата или создание самозаверяющего сертификата разработки
Для рабочих приложений в качестве сертификата нужно использовать сертификат из центра сертификации (ЦС). В целях тестирования и разработки вы можете создать и использовать самозаверяющий сертификат. Пакет SDK Service Fabric включает скрипт CertSetup.ps1 . Скрипт создает самозаверяющий сертификат и импортирует его в хранилище сертификатов Cert:\LocalMachine\My . Откройте окно командной строки от имени администратора и выполните следующую команду, чтобы создать сертификат, имеющий тему CN=mytestcert:
PS C:\program files\microsoft sdks\service fabric\clustersetup\secure> .\CertSetup.ps1 -Install -CertSubjectName CN=mytestcert
Если у вас уже есть файл Обмена персональными данными сертификата (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 . Добавьте следующие операторы 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 с помощью темы.
mytestcert
Замените <your_CN_value>
его, если вы создали самозаверяющий сертификат с помощью предыдущей команды 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 на компьютере разработки.
Теперь явно предоставьте учетной записи, которая выполняет службу (сетевая служба, по умолчанию) к закрытому ключу сертификата. Этот шаг можно выполнить вручную (с помощью средства certlm.msc ), но лучше запустить скрипт PowerShell, настроив скрипт запуска в SetupEntryPoint
манифесте службы.
Примечание.
Service Fabric поддерживает объявление сертификатов конечных точек по отпечатку или по общему имени субъекта. В этом случае среда выполнения настраивает привязку и выделение закрытого ключа сертификата для удостоверения, выполняемого службой. Среда выполнения также отслеживает сертификат для изменений, продления и выделения обновлений для соответствующего закрытого ключа.
Настройка точки входа установки службы
В обозревателе решений откройте файл VotingWeb/PackageRoot/ServiceManifest.xml. CodePackage
В разделе добавьте SetupEntryPoint
узел и добавьте ExeHost
узел. В ExeHost
, установите значение Setup.bat
Program
и установите для нее CodePackage
значение WorkingFolder
. При запуске службы 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, чтобы задать для копирования в выходной каталог значение Copy, если это еще больше.
Запуск скрипта установки от имени администратора
По умолчанию исполняемый файл точки входа программы установки службы выполняется с теми же учетными данными, что и 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>
Локальный запуск приложения
В Обозреватель решений выберите приложение Voting и задайте для свойства https://localhost:443
URL-адреса приложения значение .
Сохраните все файлы и выберите F5 для локального запуска приложения. После развертывания приложения откроется https://localhost:443
браузер. Если вы используете самозаверяющий сертификат, появится предупреждение о том, что компьютер не доверяет безопасности этого веб-сайта. Перейдите на веб-страницу.
Установка сертификата на узлах кластера
Перед развертыванием приложения в Azure установите сертификат в Cert:\LocalMachine\My store всех удаленных узлов кластера. Службы можно переместить в различные узлы кластера. Когда интерфейсная веб-служба запускается на узле кластера, скрипт запуска ищет сертификат и настраивает разрешения на доступ.
Чтобы установить сертификат на узлах кластера, сначала экспортируйте сертификат в виде PFX-файла. Откройте файл приложения certlm.msc и перейдите к личным>сертификатам. Щелкните правой кнопкой мыши сертификат mytestcert и выберите пункт "Все задачи>экспорта".
В мастере экспорта выберите "Да", экспортируйте закрытый ключ и выберите формат PFX. Экспортируйте файл в C:\Users\sfuser\votingappcert.pfx.
Затем установите сертификат в удаленном кластере с помощью скриптов PowerShell.
Предупреждение
Самозаверяющего сертификата достаточно для разработки и тестирования приложений. Для рабочих приложений используйте сертификат из центра сертификации (ЦС) вместо использования самозаверяющего сертификата.
Открытие порта 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
Сохраните все файлы, переключитесь из отладки в выпуск и выберите F6 для перестроения. В Обозреватель решений щелкните правой кнопкой мыши голосование и выберите "Опубликовать". Выберите конечную точку подключения кластера, созданного в статье Руководство по развертыванию приложения в кластере Service Fabric в Azure или выберите другой кластер. Выберите "Опубликовать", чтобы опубликовать приложение в удаленном кластере.
Когда приложение развертывается, откройте веб-браузер и перейдите https://mycluster.region.cloudapp.azure.com:443
по адресу (обновите URL-адрес с конечной точкой подключения для кластера). Если вы используете самозаверяющий сертификат, появится предупреждение о том, что компьютер не доверяет безопасности этого веб-сайта. Перейдите на веб-страницу.
Следующий шаг
Перейдите к следующему руководству: