Samouczek: Dodawanie punktu końcowego HTTPS do usługi frontonu internetowego interfejsu API platformy ASP.NET Core za pomocą usługi Kestrel

Ten samouczek jest trzecią częścią serii. Dowiesz się, jak włączyć protokół HTTPS w usłudze platformy ASP.NET Core działającej w usłudze Service Fabric. Po zakończeniu będziesz mieć aplikację do głosowania z usługą internetową frontonu ASP.NET Core z włączonym protokołem HTTPS nasłuchującą na porcie 443. Jeśli nie chcesz ręcznie tworzyć aplikacji do głosowania w sekcji Tworzenie aplikacji platformy .NET w usłudze Service Fabric, możesz pobrać kod źródłowy ukończonej aplikacji.

Część trzecia serii zawiera informacje na temat wykonywania następujących czynności:

  • Definiowanie punktu końcowego HTTPS w usłudze
  • Konfigurowanie usługi Kestrel do używania protokołu HTTPS
  • Instalowanie certyfikatu TLS/SSL w węzłach klastra zdalnego
  • Udzielanie dostępu USŁUGA SIECIOWA do klucza prywatnego certyfikatu
  • Otwieranie portu 443 w module równoważenia obciążenia platformy Azure
  • Wdrażanie aplikacji w klastrze zdalnym

Ta seria samouczków zawiera informacje na temat wykonywania następujących czynności:

Uwaga

W tym artykule użyto modułu Azure Az programu PowerShell, który jest zalecanym modułem programu PowerShell do interakcji z platformą Azure. Aby rozpocząć pracę z modułem Azure PowerShell, zobacz Instalowanie programu Azure PowerShell. Aby dowiedzieć się, jak przeprowadzić migrację do modułu Az PowerShell, zobacz Migracja programu Azure PowerShell z modułu AzureRM do modułu Az.

Wymagania wstępne

Przed rozpoczęciem tego samouczka:

Uzyskaj certyfikat lub utwórz certyfikat programistyczny z podpisem własnym

W przypadku aplikacji produkcyjnych należy używać certyfikatu z urzędu certyfikacji. Dla celów projektowania i testowania możesz utworzyć i używać certyfikatu z podpisem własnym. Zestaw SDK usługi Service Fabric zawiera skrypt CertSetup.ps1, który tworzy certyfikat z podpisem własnym, a następnie importuje go do magazynu certyfikatów Cert:\LocalMachine\My. Otwórz wiersz polecenia jako administrator i uruchom następujące polecenie, aby utworzyć certyfikat z podmiotem „CN=mytestcert”:

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

Jeśli masz już plik PFX certyfikatu, uruchom następujące polecenie, aby zaimportować certyfikat do magazynu certyfikatów 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

Definiowanie punktu końcowego HTTPS w manifeście usługi

Uruchom program Visual Studio jako administrator i otwórz rozwiązanie do głosowania. W Eksploratorze rozwiązań otwórz plik VotingWeb/PackageRoot/ServiceManifest.xml. Manifest usługi definiuje punkty końcowe usługi. Znajdź sekcję Punkty końcowe i edytuj istniejący punkt końcowy „Punktu końcowy usługi”. Zmień nazwę na „EndpointHttps”, ustaw protokół https, typ dane wejściowe i port 443. Zapisz zmiany.

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

Konfigurowanie usługi Kestrel do używania protokołu HTTPS

W Eksploratorze rozwiązań otwórz plik VotingWeb/VotingWeb.cs. Skonfiguruj usługę Kestrel do używania protokołu HTTPS i wyszukiwania certyfikatu w magazynie Cert:\LocalMachine\My. Dodaj następujące instrukcje using:

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

Zaktualizuj element ServiceInstanceListener, aby używał nowego punktu końcowego EndpointHttps i nasłuchiwał na porcie 443. Podczas konfigurowania hosta internetowego w celu używania serwera Kestrel musisz skonfigurować usługę Kestrel do nasłuchiwania adresów IPv6 we wszystkich interfejsach sieciowych: 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();
        }))

Dodaj również następującą metodę, tak aby usługa Kestrel mogła znaleźć certyfikat w magazynie Cert:\LocalMachine\My przy użyciu podmiotu.

Zastąp ciąg „<your_CN_value>” wartością „mytestcert”, jeśli utworzono certyfikat z podpisem własnym za pomocą polecenia programu PowerShell, lub użyj nazwy pospolitej (CN) certyfikatu. Należy pamiętać, że w przypadku wdrożenia localhost lokalnego zaleca się użycie opcji "CN=localhost", aby uniknąć wyjątków uwierzytelniania.

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


Udzielanie usłudze SIECIOWEJ dostępu do klucza prywatnego certyfikatu

W poprzednim kroku zaimportowano certyfikat do magazynu Cert:\LocalMachine\My na komputerze dewelopera. Teraz jawnie nadaj kontu uruchomionej usłudze (USŁUGA SIECIowa) dostęp do klucza prywatnego certyfikatu. Ten krok można wykonać ręcznie (przy użyciu narzędzia certlm.msc), ale lepiej jest automatycznie uruchomić skrypt programu PowerShell, konfigurując skrypt uruchamiania w pliku SetupEntryPoint manifestu usługi.

Uwaga

Usługa Service Fabric obsługuje deklarowanie certyfikatów punktów końcowych przy użyciu odcisku palca lub nazwy pospolitej podmiotu. W takim przypadku środowisko uruchomieniowe skonfiguruje powiązanie i listę ACL klucza prywatnego certyfikatu do tożsamości, w ramach którego działa usługa. Środowisko uruchomieniowe będzie również monitorować certyfikat pod kątem zmian/odnowień i odpowiednio ponownie wyświetlić odpowiednie klucze prywatne.

Konfigurowanie punktu wejścia usługi instalatora

W Eksploratorze rozwiązań otwórz plik VotingWeb/PackageRoot/ServiceManifest.xml. W sekcji CodePackage dodaj węzeł SetupEntryPoint, a następnie węzeł ExeHost. W węźle ExeHost ustaw element Program na „Setup.bat” i element WorkingFolder na wartość „CodePackage”. Po uruchomieniu usługi VotingWeb skrypt Setup.bat jest wykonywany w folderze CodePackage przed uruchomieniem pliku 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>

Dodawanie partii i skryptów instalacji programu PowerShell

Aby uruchomić program PowerShell z punktu SetupEntryPoint, możesz uruchomić plik PowerShell.exe w pliku wsadowym, który wskazuje plik programu PowerShell. Najpierw dodaj plik wsadowy do projektu usługi. W Eksploratorze rozwiązań kliknij prawym przyciskiem myszy pozycję VotingWeb i wybierz polecenie Dodaj nowy>element i dodaj nowy plik o nazwie "Setup.bat". Edytuj plik Setup.bat pliku i dodaj następujące polecenie:

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

Zmodyfikuj właściwości pliku Setup.bat, aby ustawić opcję Kopiuj do katalogu wyjściowego na wartość „Kopiuj, jeśli nowszy”.

Set file properties

W Eksploratorze rozwiązań kliknij prawym przyciskiem myszy pozycję VotingWeb i wybierz polecenie Dodaj nowy>element i dodaj nowy plik o nazwie "SetCertAccess.ps1". Edytuj plik SetCertAccess.ps1 i dodaj następujący skrypt:

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

Zmodyfikuj właściwości pliku SetCertAccess.ps1, aby ustawić opcję Kopiuj do katalogu wyjściowego na wartość „Kopiuj, jeśli nowszy”.

Uruchamianie skryptu instalatora jako administrator lokalny

Domyślnie plik wykonywalny punktu wejścia instalatora usługi jest uruchamiany z tymi samymi poświadczeniami co usługa Service Fabric (zazwyczaj konto NetworkService). Plik SetCertAccess.ps1 wymaga uprawnień administratora. W manifeście aplikacji możesz zmienić uprawnienia zabezpieczeń do uruchamiania skryptu uruchamiania przy użyciu konta administratora lokalnego.

W Eksploratorze rozwiązań otwórz plik Voting/ApplicationPackageRoot/ApplicationManifest.xml. Najpierw utwórz sekcję Podmioty zabezpieczeń i dodaj nowego użytkownika (na przykład „SetupAdminUser”). Dodaj konto użytkownika SetupAdminUser do grupy systemowej Administratorzy. Następnie w sekcji ServiceManifestImport pliku VotingWebPkg skonfiguruj zasady RunAsPolicy, aby zastosować podmiot zabezpieczeń SetupAdminUser do punktu wejścia instalacji. Te zasady informują usługę Service Fabric, że plik Setup.bat jest uruchamiany jako SetupAdminUser (z uprawnieniami administratora).

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

Lokalne uruchamianie aplikacji

W Eksploratorze rozwiązań wybierz aplikację do głosowania i ustaw właściwość Adres URL aplikacji na "https://localhost:443".

Zapisz wszystkie pliki i naciśnij klawisz F5, aby uruchomić aplikację lokalnie. Po wdrożeniu aplikacji zostanie otwarta przeglądarka internetowa https://localhost:443. Jeśli używasz certyfikatu z podpisem własnym, zobaczysz ostrzeżenie, że komputer nie ufa zabezpieczeniom tej witryny internetowej. Kontynuuj przechodzenie do strony internetowej.

Screenshot of the Service Fabric Voting Sample app running in a browser window with the URL https://localhost/.

Instalowanie certyfikatu w węzłach klastra

Przed wdrożeniem aplikacji na platformie Azure należy zainstalować certyfikat w magazynie Cert:\LocalMachine\My wszystkich węzłów klastra zdalnego. Usługi można przenosić do różnych węzłów klastra. Po uruchomieniu usługi internetowej frontonu w węźle klastra skrypt uruchamiania wyszuka certyfikat i skonfiguruje uprawnienia dostępu.

Najpierw należy wyeksportować certyfikat do pliku PFX. Otwórz aplikację certlm.msc i przejdź do pozycji Certyfikaty osobiste>. Kliknij prawym przyciskiem myszy certyfikat mytestcert, a następnie wybierz pozycję Wszystkie zadania>Eksportowanie.

Export certificate

W kreatorze eksportu wybierz opcję Tak, eksportuj klucz prywatny i wybierz format Wymiana informacji osobistych (PFX). Wyeksportuj plik do pliku C:\Users\sfuser\votingappcert.pfx.

Następnie zainstaluj certyfikat w klastrze zdalnym przy użyciu podanych skryptów programu PowerShell.

Ostrzeżenie

Certyfikat z podpisem własnym jest wystarczający w przypadku programowania i testowania aplikacji. W przypadku aplikacji produkcyjnych należy użyć certyfikatu z certyfikatu urzędu certyfikacji zamiast certyfikatu z podpisem własnym.

Otwórz port 443 w usłudze Azure Load Balancer i sieci wirtualnej

Jeśli jeszcze tego nie zrobiono, otwórz port 443 w module równoważenia obciążenia.

$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

Zrób to samo dla skojarzonej sieci wirtualnej.

$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

Wdrożenie aplikacji na platformie Azure

Zapisz wszystkie pliki, przełącz z debugowania na wydanie i naciśnij klawisz F6, aby ponownie skompilować rozwiązanie. W Eksploratorze rozwiązań kliknij prawym przyciskiem myszy pozycję Voting (Głosowanie) i wybierz polecenie Opublikuj. Wybierz punkt końcowy połączenia klastra utworzonego w sekcji Wdrażanie aplikacji w klastrze lub wybierz inny klaster. Kliknij pozycję Opublikuj, aby opublikować aplikację w klastrze zdalnym.

Po wdrożeniu aplikacji otwórz przeglądarkę internetową i przejdź do strony https://mycluster.region.cloudapp.azure.com:443 (zaktualizuj adres URL przy użyciu punktu końcowego połączenia dla klastra). Jeśli używasz certyfikatu z podpisem własnym, zobaczysz ostrzeżenie, że komputer nie ufa zabezpieczeniom tej witryny internetowej. Kontynuuj przechodzenie do strony internetowej.

Screenshot of the Service Fabric Voting Sample app running in a browser window with the URL https://mycluster.region.cloudapp.azure.com:443.

Następne kroki

W tej części samouczka zawarto informacje na temat wykonywania następujących czynności:

  • Definiowanie punktu końcowego HTTPS w usłudze
  • Konfigurowanie usługi Kestrel do używania protokołu HTTPS
  • Instalowanie certyfikatu TLS/SSL w węzłach klastra zdalnego
  • Udzielanie dostępu USŁUGA SIECIOWA do klucza prywatnego certyfikatu
  • Otwieranie portu 443 w module równoważenia obciążenia platformy Azure
  • Wdrażanie aplikacji w klastrze zdalnym

Przejdź do następnego samouczka: