Tutorial: Menambahkan titik akhir HTTPS ke layanan front-end ASP.NET Core Web API

Tutorial ini adalah bagian ketiga dari seri ini. Anda akan mempelajari cara mengaktifkan HTTPS di layanan ASP.NET Core yang berjalan di Service Fabric. Setelah selesai, Anda memiliki aplikasi voting dengan front-end web ASP.NET Core diaktifkan HTTPS yang mendengarkan di port 443. Jika Anda tidak ingin membuat aplikasi voting secara manual di Bangun aplikasi .NET Service Fabric, Anda dapat mengunduh kode sumber untuk aplikasi yang telah selesai.

Di bagian ketiga seri ini, Anda mempelajari cara:

  • Menetapkan titik akhir HTTPS dalam layanan
  • Mengonfigurasi Kestrel untuk menggunakan HTTPS
  • Menginstal sertifikat TLS/SSL pada node kluster jarak jauh
  • Memberikan akses NETWORK SERVICE ke kunci privat sertifikat
  • Membuka port 443 di penyeimbang muatan Azure
  • Menyebarkan aplikasi ke kluster jarak jauh

Dalam tutorial ini, Anda akan mempelajari cara:

Catatan

Artikel ini menggunakan modul Azure Az PowerShell, yang merupakan modul PowerShell yang direkomendasikan untuk berinteraksi dengan Azure. Untuk mulai menggunakan modul Az PowerShell, lihat Menginstal Azure PowerShell. Untuk mempelajari cara bermigrasi ke modul Az PowerShell, lihat Memigrasikan Azure PowerShell dari AzureRM ke Az.

Prasyarat

Sebelum Anda memulai tutorial ini:

Mendapatkan sertifikat atau membuat sertifikat pengembangan yang ditandatangani sendiri

Untuk aplikasi produksi, gunakan sertifikat dari otoritas sertifikat (CA). Untuk tujuan pengembangan dan pengujian, Anda dapat membuat dan menggunakan sertifikat yang ditandatangani sendiri. Service Fabric SDK menyediakan skrip CertSetup.ps1, yang membuat sertifikat yang ditandatangani sendiri dan mengimpornya ke penyimpanan sertifikat Cert:\LocalMachine\My. Buka prompt perintah sebagai administrator dan jalankan perintah berikut untuk membuat sertifikasi dengan subjek "CN=mytestcert":

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

Jika Anda sudah memiliki sertifikat file PFX, jalankan yang berikut untuk mengimpor sertifikat ke penyimpanan sertifikat 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

Tetapkan titik akhir HTTPS dalam manifest layanan

Luncurkan Visual Studio sebagai administrator dan buka solusi Voting. Di Penjelajah Solusi, buka VotingWeb/PackageRoot/ServiceManifest.xml. Manifes layanan menentukan titik akhir layanan. Temukan bagian Titik Akhir dan edit titik akhir "ServiceEndpoint" yang ada. Ganti namanya menjadi "EndpointHttps", atur protokol ke https, jenis ke Input, dan port ke 443. Simpan perubahan Anda.

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

Mengonfigurasi Kestrel untuk menggunakan HTTPS

Di Penjelajah Solusi, buka file VotingWeb/VotingWeb.cs. Konfigurasikan Kestrel untuk menggunakan HTTPS dan cari sertifikat di penyimpanan Cert:\LocalMachine\My. Tambahkan pernyataan penggunaan berikut ini:

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

Perbarui ServiceInstanceListener untuk menggunakan titik akhir endpointhttps dan mendengarkan di port 443. Saat mengonfigurasi host web untuk menggunakan server Kestrel, Anda harus mengonfigurasi Kestrel untuk mendengarkan alamat IPv6 di semua antarmuka jaringan: 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();
        }))

Tambahkan juga metode berikut sehingga Kestrel dapat menemukan sertifikat di penyimpanan Cert:\LocalMachine\My menggunakan subjek.

Ganti <"nilai_CN_Anda>" dengan "mytestcert" jika Anda membuat sertifikat yang ditandatangani sendiri dengan perintah PowerShell sebelumnya, atau gunakan CN sertifikat Anda. Perhatikan bahwa dalam kasus penyebaran lokal ke localhost, lebih baik menggunakan "CN =localhost" untuk menghindari pengecualian autentikasi.

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


Memberikan akses NETWORK SERVICE ke kunci privat sertifikat

Pada langkah sebelumnya, Anda mengimpor sertifikat ke penyimpanan Cert:\LocalMachine\My di komputer pengembangan. Sekarang, berikan secara eksplisit ke akun yang menjalankan layanan (NETWORK SERVICE, secara default), akses ke kunci privat sertifikat. Anda dapat melakukan langkah ini secara manual (menggunakan alat certlm.msc), tetapi lebih baik menjalankan skrip PowerShell secara otomatis dengan mengonfigurasi skrip startup di SetupEntryPoint manifes layanan.

Catatan

Service Fabric mendukung deklarasi sertifikat titik akhir dengan cap jempol atau nama umum subjek. Dalam hal ini, runtime akan menyiapkan pengikatan dan ACL kunci pribadi sertifikat untuk identitas yang dijalankan oleh layanan. Runtime juga akan memantau sertifikat untuk perubahan/perpanjangan, dan ACL ulang kunci privat yang sesuai.

Mengonfigurasi titik entri penyiapan layanan

Di Penjelajah Solusi, buka VotingWeb/PackageRoot/ServiceManifest.xml. Di bagian CodePackage, tambahkan node SetupEntryPoint kemudian node ExeHost. Di ExeHost, atur Program ke "Setup.bat" dan WorkingFolder ke "CodePackage". Ketika layanan VotingWeb dimulai, skrip Setup.bat dijalankan di folder CodePackage sebelum VotingWeb.exe dimulai.

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

Menambahkan skrip penyiapan batch dan PowerShell

Untuk menjalankan PowerShell dari titik titik SetupEntryPoint, Anda bisa menjalankan PowerShell.exe dalam file batch yang menunjuk ke file PowerShell. Pertama, tambahkan file batch proyek layanan. Di Penjelajah Solusi, klik kanan VotingWeb dan pilih Tambah->Item Baru dan tambahkan file baru bernama "Setup.bat". Edit file Setup.bat dan tambahkan perintah berikut:

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

Ubah properti file Setup.bat untuk mengatur Salin ke Direktori Output menjadi "Salin jika lebih baru".

Set file properties

Di Penjelajah Solusi, klik kanan VotingWeb dan pilih Tambah->Item Baru dan tambahkan file baru bernama "SetCertAccess.ps1". Edit file SetCertAccess.ps1 dan tambahkan skrip berikut:

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

Ubah properti file SetCertAccess.ps1 untuk mengatur Salin ke Direktori Output menjadi "Salin jika lebih baru".

Jalankan skrip penyiapan sebagai administrator lokal

Secara default, titik entri pengaturan layanan yang dapat dieksekusi berjalan dengan kredensial yang sama dengan Service Fabric (biasanya akun NetworkService). File SetCertAccess.ps1 memerlukan hak istimewa administrator. Dalam manifes aplikasi, Anda dapat mengubah izin keamanan untuk menjalankan skrip startup dengan akun administrator lokal.

Di Penjelajah Solusi, buka Voting/ApplicationPackageRoot/ApplicationManifest.xml. Pertama, buat bagian Prinsipal dan tambahkan pengguna baru (misalnya, "SetupAdminUser". Tambahkan akun pengguna SetupAdminUser ke grup sistem Administrator. Berikutnya, di bagian VotingWebPkg bagian ServiceManifestImport, konfigurasikan RunAsPolicy untuk menerapkan prinsipal SetupAdminUser ke titik entri penyiapan. Kebijakan ini memberi tahu Service Fabric bahwa file Setup.bat berjalan sebagai SetupAdminUser (dengan hak istimewa administrator).

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

Jalankan aplikasi secara lokal

Di Penjelajah Solusi, pilih aplikasi Voting dan atur properti URL Aplikasi ke "https://localhost:443".

Simpan semua file dan tekan F5 untuk menjalankan aplikasi secara lokal. Setelah aplikasi disebarkan, browser web terbuka ke https://localhost:443. Jika menggunakan sertifikat yang ditandatangani sendiri, Anda akan melihat peringatan bahwa PC Anda tidak mempercayai keamanan situs web ini. Lanjutkan ke halaman web.

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

Instal sertifikat pada node kluster

Sebelum menyebarkan aplikasi ke Azure, instal sertifikat ke penyimpanan Cert:\LocalMachine\My semua node kluster jarak jauh. Layanan dapat berpindah ke node kluster yang berbeda. Ketika layanan web front-end dimulai pada node kluster, skrip startup akan mencari sertifikat dan mengonfigurasi izin akses.

Pertama, ekspor sertifikat ke file PFX. Buka aplikasi certlm.msc dan navigasi ke Sertifikat>Pribadi. Klik kanan pada sertifikat mytestcert. dan pilih Ekspor>Semua Tugas.

Export certificate

Di wizard ekspor, pilih Ya, ekspor kunci privat dan pilih format Pertukaran Informasi Pribadi (PFX). Ekspor file ke C:\Users\sfuser\votingappcert.pfx.

Berikutnya, pasang sertifikat pada kluster jarak jauh menggunakan skrip Powershell yang disediakan ini.

Peringatan

Sertifikat yang ditandatangani sendiri cukup untuk aplikasi pengembangan dan pengujian. Untuk aplikasi produksi, gunakan sertifikat dari otoritas sertifikat (CA) alih-alih sertifikat yang ditandatangani sendiri.

Buka port 443 di penyeimbang muatan Azure dan jaringan virtual

Buka port 443 di penyeimbang muatan jika belum dilakukan.

$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

Lakukan hal yang sama untuk jaringan virtual terkait.

$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

Menyebarkan aplikasi ke Azure

Simpan semua file, alihkan dari Debug ke Rilis, dan tekan F6 untuk membangun kembali. Di Penjelajah Solusi, klik kanan pada Voting dan pilih Terbitkan. Pilih titik akhir koneksi kluster yang dibuat di Sebarkan aplikasi ke kluster, atau pilih kluster lain. Klik Terbitkan untuk mempublikasikan aplikasi ke kluster jarak jauh.

Setelah aplikasi disebarkan, buka browser web dan navigasi ke https://mycluster.region.cloudapp.azure.com:443 (perbarui URL dengan titik akhir koneksi untuk kluster Anda). Jika menggunakan sertifikat yang ditandatangani sendiri, Anda akan melihat peringatan bahwa PC Anda tidak mempercayai keamanan situs web ini. Lanjutkan ke halaman web.

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

Langkah berikutnya

Dalam bagian tutorial ini, Anda mempelajari cara:

  • Menetapkan titik akhir HTTPS dalam layanan
  • Mengonfigurasi Kestrel untuk menggunakan HTTPS
  • Menginstal sertifikat TLS/SSL pada node kluster jarak jauh
  • Memberikan akses NETWORK SERVICE ke kunci privat sertifikat
  • Membuka port 443 di penyeimbang muatan Azure
  • Menyebarkan aplikasi ke kluster jarak jauh

Lanjutkan ke tutorial berikutnya: