Dela via


Självstudie: Lägga till en HTTPS-slutpunkt för ett Service Fabric-program med hjälp av Kestrel

Den här självstudien är del tre i en serie. Lär dig hur du lägger till en HTTPS-slutpunkt i en ASP.NET Core-tjänst som körs i Azure Service Fabric. När du är klar har du ett röstningsprogram som har en HTTPS-aktiverad ASP.NET Core-webbklientdel som lyssnar på port 443. Om du inte vill skapa röstningsprogrammet manuellt i del ett av självstudieserien kan du hämta källkoden för att hämta det färdiga programmet.

I den här självstudien lär du dig att:

  • Definiera en HTTPS-slutpunkt i tjänsten
  • Konfigurera Kestrel att använda HTTPS
  • Installera TLS/SSL-certifikatet på fjärrklusternoderna
  • Ge NetworkService åtkomst till certifikatets privata nyckel
  • Öppna port 443 i Azure-lastbalanseraren
  • Distribuera programmet till ett fjärrkluster

Självstudieserien visar hur du:

Kommentar

Vi rekommenderar att du använder Azure Az PowerShell-modulen för att interagera med Azure. Information om hur du kommer igång finns i Installera Azure PowerShell. Information om hur du migrerar till Az PowerShell-modulen finns i artikeln om att migrera Azure PowerShell från AzureRM till Az.

Förutsättningar

Innan du börjar den här självstudien:

Hämta ett certifikat eller skapa ett självsignerat utvecklingscertifikat

För produktionsprogram ska du använda ett certifikat från en certifikatutfärdare (CA). För utveckling och testning kan du skapa och använda ett självsignerat certifikat. Service Fabric SDK innehåller skriptet CertSetup.ps1 . Skriptet skapar ett självsignerat certifikat och importerar det till certifikatarkivet Cert:\LocalMachine\My . Öppna kommandotolken som administratör och kör följande kommando för att skapa ett certifikat med ämnet "CN=mytestcert":

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

Om du redan har en PFX-fil (Personal Information Exchange) för certifikat kör du följande för att importera certifikatet till certifikatarkivet 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

Definiera en HTTPS-slutpunkt i tjänstmanifestet

Öppna Visual Studio med alternativet Kör som administratör och öppna sedan röstningslösningen. Öppna VotingWeb/PackageRoot/ServiceManifest.xml i Solution Explorer. Tjänstmanifestet definierar tjänstens slutpunkter. Leta upp avsnittet Endpoints och redigera värdet för ServiceEndpoint slutpunkten. Ändra namnet till EndpointHttps, ange protokollet till https, typen till Inputoch porten till 443. Spara dina ändringar.

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

Konfigurera Kestrel för användning av HTTPS

Öppna filen VotingWeb/VotingWeb.cs i Solution Explorer. Konfigurera Kestrel att använda HTTPS och att söka efter certifikatet i Cert:\LocalMachine\My Store. Lägg till följande using-uttryck:

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

Uppdatera värdet för för ServiceInstanceListener att använda den nya EndpointHttps slutpunkten och lyssna på port 443. När du konfigurerar webbvärden för att använda Kestrel-servern måste du konfigurera Kestrel att lyssna efter IPv6-adresser i alla nätverksgränssnitt: 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();
        }))

Lägg sedan till följande metod så att Kestrel kan hitta certifikatet i certifikatet :\LocalMachine\My store med hjälp av ämnet.

Ersätt <your_CN_value> med mytestcert om du skapade ett självsignerat certifikat med hjälp av det tidigare PowerShell-kommandot, eller använd certifikatets CN.

Om du använder en lokal distribution till localhostrekommenderar vi att du använder CN=localhost för att undvika autentiseringsfel.

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


Bevilja nätverkstjänst åtkomst till certifikatets privata nyckel

I ett tidigare steg importerade du certifikatet till Cert:\LocalMachine\My Store på utvecklingsdatorn.

Ge nu uttryckligen det konto som kör tjänsten (nätverkstjänst, som standard) åtkomst till certifikatets privata nyckel. Du kan göra det här steget manuellt (med hjälp av verktyget certlm.msc ), men det är bättre att köra ett PowerShell-skript genom att konfigurera ett startskript i SetupEntryPoint tjänstmanifestet.

Kommentar

Service Fabric stöder deklarering av slutpunktscertifikat med tumavtryck eller efter ämnesnamn. I så fall konfigurerar körningen bindningen och allokeringen för certifikatets privata nyckel till den identitet som tjänsten körs som. Körningen övervakar även certifikatet för ändringar, förnyelser och allokeringsuppdateringar för motsvarande privata nyckel.

Konfigurera tjänstens konfigurationsstartpunkt

Öppna VotingWeb/PackageRoot/ServiceManifest.xml i Solution Explorer. I avsnittet CodePackage lägger du till SetupEntryPoint noden och lägger sedan till en ExeHost nod. I ExeHostanger du Program till Setup.batoch anger WorkingFolder till CodePackage. När VotingWeb-tjänsten startar körs Setup.bat-skriptet i mappen CodePackage innan VotingWeb.exe startar.

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

Lägga till konfigurationsskript för batch och PowerShell

Om du vill köra PowerShell från värdet för SetupEntryPointkan du köra PowerShell.exe i en batchfil som pekar på en PowerShell-fil.

Lägg först till batchfilen i tjänstens projekt. I Istraživač rešenja högerklickar du på VotingWeb och väljer sedan Lägg till>nytt objekt. Lägg till en ny fil med namnet Setup.bat. Redigera filen Setup.bat och lägg till följande kommando:

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

Ändra egenskaperna för Setup.bat-filen för att ange Kopiera till Utdatakatalog till Kopiera om det är nyare.

Skärmbild som visar hur du konfigurerar filegenskaperna.

Högerklicka på VotingWeb i Istraživač rešenja. Välj sedan Lägg till>nytt objekt och lägg till en ny fil med namnet SetCertAccess.ps1. Redigera filen SetCertAccess.ps1 för att lägga till följande 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;
    }
}

Ändra egenskaper för filen SetCertAccess.ps1 för att ange Kopiera till Utdatakatalog till Kopiera om det är nyare.

Kör installationsskriptet som administratör

Som standard körs startpunkten för tjänstinstallationen med samma autentiseringsuppgifter som Service Fabric (vanligtvis nätverkstjänstkontot). SetCertAccess.ps1 kräver administratörsbehörighet. Du kan ändra säkerhetsbehörigheterna i manifestet så att startskriptet körs under ett lokalt administratörskonto.

Öppna Voting/ApplicationPackageRoot/ApplicationManifest.xml i Solution Explorer. Skapa först ett Principals avsnitt och lägg till en ny användare (till exempel SetupAdminUser). Lägg till användarkontot SetupAdminUser i systemgruppen Administrators.

I VotingWebPkg i ServiceManifestImport avsnittet konfigurerar du sedan en RunAsPolicy för att tillämpa setupAdminUser-huvudnamnet på startpunkten för installationen. Den här principen anger för Service Fabric att Setup.bat-filen körs som SetupAdminUser (med administratörsbehörighet).

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

Köra appen lokalt

I Istraživač rešenja väljer du programmet Röstning och anger egenskapen Application URL till https://localhost:443.

Spara alla filer och välj sedan F5 för att köra programmet lokalt. När programmet har distribuerats öppnas en webbläsare till https://localhost:443. Om du använder ett självsignerat certifikat visas en varning om att datorn inte litar på webbplatsens säkerhet. Fortsätt till webbsidan.

Skärmbild som visar appen Service Fabric Voting Sample som körs i en webbläsare och localhost-URL:en.

Installera certifikatet på klusternoder

Innan du distribuerar programmet till Azure installerar du certifikatet i certifikatet :\LocalMachine\My store för alla fjärrklusternoder. Tjänster kan flyttas till olika noder i klustret. När klientwebbtjänsten startar på en klusternod letar startskriptet upp certifikatet och konfigurerar åtkomstbehörigheter.

Om du vill installera certifikatet på klusternoder exporterar du först certifikatet som en PFX-fil. Öppna programfilen certlm.msc och gå till Personliga>certifikat. Högerklicka på mytestcert-certifikatet och välj sedan Exportera alla uppgifter>.

Skärmbild som visar export av certifikatet.

I exportguiden väljer du Ja, exporterar den privata nyckeln och väljer sedan PFX-format. Exportera filen till C:\Users\sfuser\votingappcert.pfx.

Installera sedan certifikatet på fjärrklustret med hjälp av PowerShell-skript.

Varning

Ett självsignerat certifikat räcker för utveckling och testning. För produktionsprogram använder du ett certifikat från en certifikatutfärdare (CA) i stället för att använda ett självsignerat certifikat.

Öppna port 443 i Azure-lastbalanseraren och det virtuella nätverket

Öppna port 443 i lastbalanseraren om den inte är öppen:

$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

Gör samma sak för det associerade virtuella nätverket:

$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

Distribuera appen till Azure

Spara alla filer, växla från Felsökning till Släpp och välj F6 för att återskapa. I Istraživač rešenja högerklickar du på Röstning och väljer Publicera. Välj klustrets slutpunkt för anslutning som du skapade i Distribuera ett program till ett kluster, eller välj ett annat kluster. Välj Publicera för att publicera programmet till fjärrklustret.

När programmet distribueras öppnar du en webbläsare och går till https://mycluster.region.cloudapp.azure.com:443 (uppdatera URL:en med anslutningsslutpunkten för klustret). Om du använder ett självsignerat certifikat visas en varning om att datorn inte litar på webbplatsens säkerhet. Fortsätt till webbsidan.

Skärmbild som visar appen Service Fabric Voting Sample som körs i ett webbläsarfönster.

Gå vidare

Gå vidare till nästa kurs: