Kurz: Přidání koncového bodu HTTPS do front-endové služby webového rozhraní API ASP.NET Core využívající Kestrel

Tento kurz je třetí částí série. Zjistíte, jak povolit HTTPS ve službě ASP.NET Core spuštěné v Service Fabric. Až budete hotovi, budete mít hlasovací aplikaci s webovým front-endem ASP.NET Core s povoleným HTTPS, který bude naslouchat na portu 443. Pokud nechcete hlasovací aplikaci vytvářet ručně, v tématu popisujícím vytvoření aplikace Service Fabric v .NET si můžete stáhnout zdrojový kód dokončené aplikace.

Ve třetí části této série se naučíte:

  • Definovat ve službě koncový bod HTTPS
  • Nakonfigurovat Kestrel k používání HTTPS
  • Instalace certifikátu TLS/SSL na uzly vzdáleného clusteru
  • Poskytnout účtu NETWORK SERVICE přístup k privátnímu klíči certifikátu
  • Otevřít port 443 v nástroji pro vyrovnávání zatížení Azure
  • Nasadit aplikaci do vzdáleného clusteru

V této sérii kurzů se naučíte:

Poznámka

K interakci s Azure doporučujeme použít modul Azure Az PowerShell. Začněte tím, že si projdete téma Instalace Azure PowerShellu. Informace o tom, jak migrovat na modul Az PowerShell, najdete v tématu Migrace Azure PowerShellu z AzureRM na Az.

Požadavky

Než začnete s tímto kurzem:

Získání certifikátu nebo vytvoření certifikátu podepsaného svým držitelem pro vývoj

Pro produkční aplikace používejte certifikát od certifikační autority (CA). Pro účely vývoje a testování můžete vytvořit a používat certifikát podepsaný svým držitelem. Sada Service Fabric SDK poskytuje skript CertSetup.ps1, který vytvoří certifikát podepsaný svým držitelem a importuje ho do úložiště certifikátů Cert:\LocalMachine\My. Otevřete příkazový řádek jako správce a spuštěním následujícího příkazu vytvořte certifikát s předmětem CN=mytestcert:

PS C:\program files\microsoft sdks\service fabric\clustersetup\secure> .\CertSetup.ps1 -Install -CertSubjectName CN=mytestcert

Pokud už máte soubor certifikátu PFX, spuštěním následujícího příkazu importujte certifikát do úložiště certifikátů Cert:\LocalMachine\My:


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

Definice koncového bodu HTTPS v manifestu služby

Spusťte sadu Visual Studio jako správce a otevřete řešení Voting. V Průzkumníku řešení otevřete soubor VotingWeb/PackageRoot/ServiceManifest.xml. Manifest služby definuje koncové body služby. Vyhledejte část Endpoints (Koncové body) a upravte stávající koncový bod ServiceEndpoint. Změňte název na EndpointHttps a nastavte protokol na https, typ na Vstup a port na 443. Uložte provedené změny.

<?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>

Nakonfigurovat Kestrel k používání HTTPS

V Průzkumníku řešení otevřete soubor VotingWeb/VotingWeb.cs. Nakonfigurujte Kestrel k používání HTTPS a vyhledejte certifikát v úložišti Cert:\LocalMachine\My. Přidejte následující příkazy using:

using System.Net;
using Microsoft.Extensions.Configuration;
using System.Security.Cryptography.X509Certificates;

Aktualizujte ServiceInstanceListener k používání nového koncového bodu EndpointHttps a naslouchání na portu 443. Při konfiguraci webového hostitele na používání serveru Kestrel musíte Kestrel nakonfigurovat tak, aby naslouchal IPv6 adresám na všech síťových rozhraních: 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();
        }))

Přidejte také následující metodu, aby Kestrel mohl vyhledat certifikát v úložišti Cert:\LocalMachine\My pomocí předmětu.

Pokud jste certifikát podepsaný svým držitelem vytvořili pomocí předchozího příkazu PowerShellu, nahraďte "<your_CN_value>" za "mytestcert", nebo použijte cn vašeho certifikátu. Mějte na paměti, že v případě místního nasazení do localhost je vhodnější použít cn=localhost, aby se zabránilo výjimkám ověřování.

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];
    }
}


Udělení přístupu k privátnímu klíči certifikátu službě NETWORK SERVICE

V předchozím kroku jste importovali certifikát do úložiště Cert:\LocalMachine\My na vývojovém počítači. Teď explicitně udělte účtu, který spouští službu (ve výchozím nastavení NETWORK SERVICE), přístup k privátnímu klíči certifikátu. Tento krok můžete provést ručně (pomocí nástroje certlm.msc), ale lepší je automaticky spustit skript PowerShellu tak, že nakonfigurujete spouštěcí skript v SetupEntryPointu manifestu služby.

Poznámka

Service Fabric podporuje deklaraci certifikátů koncových bodů podle kryptografického otisku nebo běžného názvu subjektu. V takovém případě modul runtime nastaví vazbu a seznam ACL privátní klíč certifikátu k identitě, se kterou služba běží. Modul runtime také bude monitorovat změny nebo obnovení certifikátu a odpovídajícím způsobem znovu vytvoří seznam ACL odpovídajícího privátního klíče.

Konfigurace vstupního bodu nastavení služby

V Průzkumníku řešení otevřete soubor VotingWeb/PackageRoot/ServiceManifest.xml. V části CodePackage přidejte uzel SetupEntryPoint a pak uzel ExeHost. V uzlu ExeHost nastavte Program na Setup.bat a WorkingFolder na CodePackage. Při spuštění služby VotingWeb se před spuštěním VotingWeb.exe provede skript Setup.bat ve složce CodePackage.

<?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>

Přidání dávkových skriptů a instalačních skriptů PowerShellu

Pokud chcete spustit PowerShell z bodu SetupEntryPoint, můžete spustit PowerShell.exe v dávkovém souboru odkazujícím na soubor PowerShellu. Nejprve do projektu služby přidejte dávkový soubor. V Průzkumník řešení klikněte pravým tlačítkem na VotingWeb, vyberte Přidat novou>položku a přidejte nový soubor s názvem "Setup.bat". Upravte soubor Setup.bat a přidejte následující příkaz:

powershell.exe -ExecutionPolicy Bypass -Command ".\SetCertAccess.ps1"

Upravte vlastnosti souboru Setup.bat a nastavte možnost Kopírovat do výstupního adresáře na hodnotu Kopírovat, pokud je novější.

Nastavení vlastností souboru

V Průzkumník řešení klikněte pravým tlačítkem na VotingWeb, vyberte Přidat novou>položku a přidejte nový soubor s názvem "SetCertAccess.ps1". Upravte soubor SetCertAccess.ps1 a přidejte následující skript:

$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;
    }
}

Upravte vlastnosti souboru SetCertAccess.ps1 a nastavte možnost Kopírovat do výstupního adresáře na hodnotu Kopírovat, pokud je novější.

Spuštění instalačního skriptu jako místní správce

Ve výchozím nastavení se spustitelný soubor vstupního bodu nastavení služby spouští pod stejnými přihlašovacími údaji jako Service Fabric (obvykle pod účtem NetworkService). Soubor SetCertAccess.ps1 vyžaduje oprávnění správce. V manifestu aplikace můžete změnit oprávnění zabezpečení tak, aby se spouštěcí skript spouštěl pod účtem místního správce.

V Průzkumníku řešení otevřete soubor Voting/ApplicationPackageRoot/ApplicationManifest.xml. Nejprve vytvořte část Principals (Instanční objekty) a přidejte nového uživatele (například SetupAdminUser). Přidejte uživatelský účet SetupAdminUser do systémové skupiny Správci. Dále v části ServiceManifestImport souboru VotingWebPkg nakonfigurujte RunAsPolicy pro použití instančního objektu SetupAdminUser na vstupní bod nastavení. Tato zásada říká Service Fabric, že se soubor Setup.bat spouští jako SetupAdminUser (s oprávněními správce).

<?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>

Aplikaci spustíte místně.

V Průzkumník řešení vyberte hlasovací aplikaci a nastavte vlastnost Adresa URL aplikace na "https://localhost:443".

Uložte všechny soubory a stisknutím klávesy F5 aplikaci místně spusťte. Po nasazení aplikace se webový prohlížeč otevře na https://localhost:443. Pokud používáte certifikát podepsaný svým držitelem, zobrazí se upozornění, že váš počítač nedůvěřuje zabezpečení tohoto webu. Pokračujte na webovou stránku.

Snímek obrazovky s hlasovací ukázkovou aplikací Service Fabric spuštěnou v okně prohlížeče s adresou URL https://localhost/.

Instalace certifikátu na uzlech clusteru

Před nasazením aplikace do Azure nainstalujte certifikát do Cert:\LocalMachine\My úložiště všech uzlů vzdáleného clusteru. Služby se můžou přesouvat do různých uzlů clusteru. Při spuštění webové front-end služby na uzlu clusteru vyhledá spouštěcí skript certifikát a nakonfiguruje přístupová oprávnění.

Nejprve exportujte certifikát do souboru PFX. Otevřete aplikaci certlm.msc a přejděte na Osobní>certifikáty. Klikněte pravým tlačítkem na certifikát mytestcert a vyberte Exportovat všechny úlohy>.

Export certifikátu

V průvodci exportem zvolte Ano, exportovat privátní klíč a zvolte formát PFX (Personal Information Exchange). Exportujte soubor do umístění C:\Users\sfuser\votingappcert.pfx.

Dále nainstalujte certifikát do vzdáleného clusteru pomocí těchto poskytnutých skriptů PowerShellu.

Upozornění

Certifikát podepsaný svým držitelem je dostačující pro vývoj a testování aplikací. Pro produkční aplikace místo certifikátu podepsaného svým držitelem používejte certifikát od certifikační autority (CA).

Otevření portu 443 v nástroji pro vyrovnávání zatížení Azure a virtuální síti

Pokud ještě není otevřený, otevřete port 443 v nástroji pro vyrovnávání zatížení.

$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

To samé udělejte pro přidruženou virtuální síť.

$rulename="allowAppPort$port"
$nsgname="voting-vnet-security"
$RGname="voting_RG"
$port=443

# Get the NSG 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 NSG.
$nsg | Set-AzNetworkSecurityGroup

Nasazení aplikace do Azure

Uložte všechny soubory, přepněte z režimu Ladění do Vydání a stisknutím klávesy F6 znovu spusťte sestavení. V Průzkumníku řešení klikněte pravým tlačítkem na aplikaci Voting a vyberte Publikovat. Vyberte koncový bod připojení clusteru vytvořeného v tématu Nasazení aplikace do clusteru nebo vyberte jiný cluster. Kliknutím na Publikovat publikujte aplikaci do vzdáleného clusteru.

Po nasazení aplikace otevřete webový prohlížeč a přejděte na adresu https://mycluster.region.cloudapp.azure.com:443 (v adrese URL aktualizujte koncový bod připojení pro váš cluster). Pokud používáte certifikát podepsaný svým držitelem, zobrazí se upozornění, že váš počítač nedůvěřuje zabezpečení tohoto webu. Pokračujte na webovou stránku.

Snímek obrazovky s ukázkovou aplikací Service Fabric Voting v okně prohlížeče s adresou URL https://mycluster.region.cloudapp.azure.com:443.

Další kroky

V této části kurzu jste se naučili:

  • Definovat ve službě koncový bod HTTPS
  • Nakonfigurovat Kestrel k používání HTTPS
  • Instalace certifikátu TLS/SSL na vzdálené uzly clusteru
  • Poskytnout účtu NETWORK SERVICE přístup k privátnímu klíči certifikátu
  • Otevřít port 443 v nástroji pro vyrovnávání zatížení Azure
  • Nasadit aplikaci do vzdáleného clusteru

Přejděte k dalšímu kurzu: