Tutoriel : Ajouter un point de terminaison HTTPS à un service frontal API Web ASP.NET Core à l’aide de Kestrel
Ce tutoriel est le troisième de la série. Vous allez apprendre à activer HTTPS dans un service ASP.NET Core s’exécutant sur Service Fabric. À l’issue de cette procédure, vous disposerez d’une application de vote avec un service web frontal ASP.NET Core HTTPS écoutant le port 443. Si vous ne souhaitez pas créer l’application de vote manuellement en suivant les instructions de l’article Créer une application .NET Service Fabric, vous pouvez télécharger le code source pour obtenir l’application terminée.
Dans ce troisième volet, vous apprenez à :
- Définir un point de terminaison HTTPS dans le service
- Configurer Kestrel pour l’utilisation de HTTPS
- Installer le certificat TLS/SSL sur les nœuds du cluster distant
- Accorder l’accès SERVICE RÉSEAU à la clé privée du certificat
- Ouvrir le port 443 dans l’équilibreur de charge Azure
- Déployer l’application sur un cluster distant
Cette série de tutoriels vous montre comment effectuer les opérations suivantes :
- Créer une application .NET Service Fabric
- Déployer l’application sur un cluster distant
- Ajouter un point de terminaison HTTPS à un service frontal ASP.NET Core
- Configurer CI/CD à l’aide d’Azure Pipelines
- Configurer la surveillance et les diagnostics pour l’application
Notes
Nous vous recommandons d’utiliser le module Azure Az PowerShell pour interagir avec Azure. Pour commencer, consultez Installer Azure PowerShell. Pour savoir comment migrer vers le module Az PowerShell, consultez Migrer Azure PowerShell depuis AzureRM vers Az.
Prérequis
Avant de commencer ce tutoriel :
- Si vous n’avez pas d’abonnement Azure, créez un compte gratuit
- Installez Visual Studio 2019 version 16.5 ou ultérieure avec les charges de travail Développement Azure et Développement web et ASP.NET.
- Installez le Kit de développement logiciel (SDK) Service Fabric
Obtenir un certificat ou créer un certificat de développement auto-signé
Pour les applications de production, utilisez un certificat délivré par une autorité de certification (AC). Dans le cadre d’opérations de développement et de test, vous pouvez créer et utiliser un certificat auto-signé. Le Kit de développement logiciel (SDK) Service Fabric fournit le script CertSetup.ps1, qui crée un certificat auto-signé et l’importe dans le magasin de certificats Cert:\LocalMachine\My
. Ouvrez une invite de commandes en tant qu’administrateur, puis exécutez la commande ci-après pour créer un certificat avec le sujet « CN=mytestcert » :
PS C:\program files\microsoft sdks\service fabric\clustersetup\secure> .\CertSetup.ps1 -Install -CertSubjectName CN=mytestcert
Si vous disposez déjà d’un fichier PFX de certificat, exécutez la commande ci-après pour importer le certificat dans le magasin de certificats 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
Définir un point de terminaison HTTPS dans le manifeste de service
Lancez Visual Studio en tant qu’administrateur et ouvrez la solution de vote. Dans l’Explorateur de solutions, ouvrez VotingWeb/PackageRoot/ServiceManifest.xml. Le manifeste de service définit les points de terminaison de service. Recherchez la section Endpoints, modifiez le point de terminaison "ServiceEndpoint" existant en le remplaçant par "EndpointHttps", puis définissez le protocole sur https, le type sur Input et le port sur 443. Enregistrez vos modifications.
<?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>
Configurer Kestrel pour l’utilisation de HTTPS
Dans l’Explorateur de solutions, ouvrez le fichier VotingWeb/VotingWeb.cs. Configurez Kestrel pour l’utilisation de HTTPS et recherchez le certificat dans le magasin Cert:\LocalMachine\My
. Ajoutez les instructions using suivantes :
using System.Net;
using Microsoft.Extensions.Configuration;
using System.Security.Cryptography.X509Certificates;
Mettez à jour l’élément ServiceInstanceListener
pour qu’il utilise le nouveau point de terminaison EndpointHttps et qu’il écoute le port 443. Lors de la configuration de l’hôte web pour utiliser le serveur Kestrel, vous devez configurer Kestrel pour qu’il écoute les adresses IPv6 sur toutes les interfaces réseau : 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();
}))
Ajoutez également la méthode ci-après pour permettre à Kestrel de trouver le certificat dans le magasin Cert:\LocalMachine\My
au moyen du sujet.
Remplacez la chaîne « <your_CN_value> » par « mytestcert » si vous avez créé un certificat auto-signé avec la commande PowerShell précédente, ou utilisez le CN de votre certificat.
Sachez que dans le cas d’un déploiement local vers localhost
, il est préférable d’utiliser « CN=localhost » pour éviter les exceptions d’authentification.
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];
}
}
Accorder l’accès SERVICE RÉSEAU à la clé privée du certificat
Au cours d’une étape précédente, vous avez importé le certificat dans le magasin Cert:\LocalMachine\My
sur l’ordinateur de développement. Maintenant, octroyez explicitement au compte exécutant le service (SERVICE RÉSEAU, par défaut) l’accès à la clé privée du certificat. Vous pouvez effectuer cette étape manuellement (à l’aide de l’outil certlm.msc), mais il est préférable d’exécuter automatiquement un script PowerShell en configurant un script de démarrage dans l’élément SetupEntryPoint du manifeste de service.
Notes
Service Fabric prend en charge la déclaration de certificats de point de terminaison par empreinte ou par nom commun de sujet. Dans ce cas, le runtime configure la liaison et définit dans la liste de contrôle d’accès une entrée qui lie la clé privée du certificat à l’identité sous laquelle le service est en cours d’exécution. En outre, le runtime supervise le certificat pour savoir s’il doit faire l’objet de modifications ou d’un renouvellement, et redéfinit en conséquence la clé privée correspondante dans la liste de contrôle d’accès.
Configurer le point d’entrée d’installation du service
Dans l’Explorateur de solutions, ouvrez VotingWeb/PackageRoot/ServiceManifest.xml. Dans la section CodePackage, ajoutez le nœud SetupEntryPoint, puis un nœud ExeHost. Dans ExeHost, définissez Program sur « Setup.bat » et WorkingFolder sur « CodePackage ». Au démarrage du service VotingWeb, le script Setup.bat s’exécute dans le dossier CodePackage avant que VotingWeb.exe ne démarre.
<?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>
Ajouter le fichier de commandes et les scripts d’installation PowerShell
Pour exécuter PowerShell à partir du point SetupEntryPoint, vous pouvez exécuter PowerShell.exe dans un fichier de commandes qui pointe vers un fichier PowerShell. Commencez par ajouter le fichier de commandes au projet de service. Dans l’Explorateur de solutions, cliquez avec le bouton droit sur VotingWeb et sélectionnez Ajouter->Nouvel élément, puis ajoutez un nouveau fichier nommé « Setup.bat ». Modifiez le fichier Setup.bat et ajoutez la commande suivante :
powershell.exe -ExecutionPolicy Bypass -Command ".\SetCertAccess.ps1"
Modifiez les propriétés du fichier Setup.bat en définissant Copier dans le répertoire de sortie sur « Copier si plus récent ».
Dans l’Explorateur de solutions, cliquez avec le bouton droit sur VotingWeb et sélectionnez Ajouter->Nouvel élément, puis ajoutez un nouveau fichier nommé « SetCertAccess.ps1 ». Modifiez le fichier SetCertAccess.ps1, puis ajoutez le script suivant :
$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;
}
}
Modifiez les propriétés du fichier SetCertAccess.ps1 en définissant Copier dans le répertoire de sortie sur « Copier si plus récent ».
Exécuter le script d’installation an tant qu’administrateur local
Par défaut, l’exécutable du point d’entrée d’installation du service est exécuté avec les mêmes informations d’identification que Service Fabric (généralement, le compte NetworkService). Le fichier SetCertAccess.ps1 requiert des privilèges d’administrateur. Dans le manifeste de l’application, vous pouvez changer les autorisations de sécurité de manière à exécuter le script de démarrage sous un compte d’administrateur local.
Dans l’Explorateur de solutions, ouvrez Voting/ApplicationPackageRoot/ApplicationManifest.xml. Commencez par créer une section Principals et par y ajouter un nouvel utilisateur (par exemple, "SetupAdminUser"). Ajoutez le compte d’utilisateur SetupAdminUser au groupe des administrateurs système. Ensuite, dans la section VotingWebPkg ServiceManifestImport, configurez un élément RunAsPolicy pour appliquer le principal SetupAdminUser au point d’entrée d’installation. Cette stratégie indique à Service Fabric que le fichier Setup.bat s’exécute en tant que SetupAdminUser (avec des privilèges d’administrateur).
<?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>
Exécuter l’application localement
Dans l’Explorateur de solutions, sélectionnez l’application Voting et définissez la propriété URL de l’application sur « https://localhost:443" ».
Enregistrez tous les fichiers, puis appuyez sur la touche F5 pour exécuter l’application localement. Une fois l’application déployée, un navigateur web s’ouvre en accédant à l’adresse https://localhost:443. Si vous utilisez un certificat auto-signé, vous obtenez un message d’avertissement signalant que votre PC n’a pas confiance en la sécurité de ce site web. Poursuivez sur la page web.
Installer le certificat sur les nœuds de cluster
Avant de déployer l’application dans Azure, installez le certificat dans le magasin Cert:\LocalMachine\My
de tous les nœuds du cluster distant. Vous pouvez déplacer les services d’un nœud à l’autre du cluster. Lorsque le service web frontal démarrera sur un nœud de cluster, le script de démarrage recherchera le certificat et configurera les autorisations d’accès.
Commencez par exporter le certificat dans un fichier PFX. Ouvrez l’application certlm.msc, puis accédez à Personnel>Certificats. Cliquez avec le bouton droit sur le certificat mytestcert, puis sélectionnez Toutes les tâches>Exporter.
Dans l’Assistant Exportation, choisissez Oui, exporter la clé privée et choisissez le format PFX (Personal Information Exchange, Échange d’informations personnelles). Exportez le fichier vers C:\Users\sfuser\votingappcert.pfx.
Ensuite, installez le certificat sur le cluster à distance à l’aide de ces scripts PowerShell fournis.
Avertissement
Un certificat auto-signé suffit pour les applications de développement et de test. Pour les applications de production, utilisez un certificat délivré par une autorité de certification (AC) plutôt qu’un certificat auto-signé.
Ouvrir le port 443 dans l’équilibreur de charge et le réseau virtuel Azure
Ouvrez le port 443 dans l’équilibreur de charge s’il n’est pas encore ouvert.
$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
Faites de même pour le réseau virtuel associé.
$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
Déploiement de l’application dans Azure
Enregistrez tous les fichiers, basculez du mode Débogage vers le mode Mise en production, puis appuyez sur la touche F6 pour régénérer l’application. Dans l’Explorateur de solutions, cliquez avec le bouton droit sur Voting, puis sélectionnez Publier. Sélectionnez le point de terminaison de connexion du cluster créé au cours du didacticiel Déployer une application sur un cluster, ou sélectionnez un autre cluster. Cliquez sur Publier pour publier l’application sur le cluster distant.
Lors du déploiement de l’application, ouvrez un navigateur web et accédez à https://mycluster.region.cloudapp.azure.com:443
(mettez à jour l’URL avec le point de terminaison de connexion de votre cluster). Si vous utilisez un certificat auto-signé, vous obtenez un message d’avertissement signalant que votre PC n’a pas confiance en la sécurité de ce site web. Poursuivez sur la page web.
Étapes suivantes
Dans cette partie du tutoriel, vous avez appris à :
- Définir un point de terminaison HTTPS dans le service
- Configurer Kestrel pour l’utilisation de HTTPS
- Installer le certificat TLS/SSL sur les nœuds du cluster distant
- Accorder l’accès SERVICE RÉSEAU à la clé privée du certificat
- Ouvrir le port 443 dans l’équilibreur de charge Azure
- Déployer l’application sur un cluster distant
Passez au tutoriel suivant :