Délégation et emprunt d'identité avec WCF
L'emprunt d'identité est une technique courante utilisée par les services pour restreindre l'accès du client aux ressources d'un domaine de service. Les ressources de domaine de service peuvent être des ressources d'ordinateur, telles que des fichiers locaux (emprunt d'identité), ou une ressource sur un autre ordinateur, tel qu'un partage de fichiers (délégation). Pour obtenir un exemple d'application, consultez Impersonating the Client. Pour obtenir un exemple sur l'utilisation de l'emprunt d'identité, consultez Comment : emprunter l'identité d'un client sur un service.
Remarque : |
---|
Sachez que lors de l'emprunt d'identité d'un client sur un service, le service s'exécute avec les informations d'identification du client, qui peut avoir des privilèges plus élevés que le processus serveur. |
Vue d'ensemble
Généralement, les clients appellent un client pour que celui-ci effectue une action au nom du client. L'emprunt d'identité permet au service d'agir comme le client lors de l'exécution de l'action. La délégation permet à un service frontal de transmettre la demande du client à un service principal d'une manière qui permet au service principal d'emprunter l'identité du client. L'emprunt d'identité est une méthode couramment utilisée pour vérifier si un client est autorisé à effectuer une action donnée. La délégation est une méthode permettant de transmettre les fonctions d'emprunt d'identité avec l'identité du client à un service principal. La délégation est une fonctionnalité du domaine Windows qui peut être utilisée dans le cadre de l'authentification Kerberos. La délégation n'est pas la même chose que le flux d'identité et comme la délégation transfère la possibilité d'emprunter l'identité du client sans connaître son mot de passe, elle représente une opération d'un niveau de privilège supérieur au flux d'identité.
L'emprunt d'identité et la délégation nécessitent que le client possède une identité Windows. Si ce n'est pas le cas, la seule option consiste à transmettre l'identité du client au second service.
Principes de base de l'emprunt d'identité
Windows Communication Foundation (WCF) prend en charge l'emprunt d'identité pour diverses informations d'identification du client. Cette rubrique décrit la prise en charge de modèle de service permettant d'emprunter l'identité de l'appelant pendant l'implémentation d'une méthode de service. Elle présente également des scénarios de déploiement courants impliquant l'emprunt d'identité et la sécurité SOAP, ainsi que les options WCF utilisées dans ces scénarios.
Cette rubrique se concentre sur l'emprunt d'identité et la délégation dans WCF lors de l'utilisation de la sécurité SOAP. Vous pouvez également utiliser l'emprunt d'identité et la délégation avec WCF lors de l'utilisation de la sécurité de transport, tel que décrit dans Utilisation de l'emprunt d'identité avec la sécurité de transport.
Deux méthodes
WCF La sécurité SOAP a deux méthodes distinctes d'exécution de l'emprunt d'identité. La méthode utilisée dépend de la liaison. L'une concerne l'emprunt d'identité à partir d'un jeton Windows fourni par l'authentification SSPI (Security Support Provider Interface) ou Kerberos, qui est ensuite mis en cache sur le service. La deuxième concerne l'emprunt d'identité à partir d'un jeton Windows fourni par les extensions Kerberos, collectivement appelées S4U (Service-for-User).
Emprunt d'identité avec jeton mis en cache
Vous pouvez effectuer l'emprunt d'identité avec jeton mis en cache à l'aide des éléments suivants :
WSHttpBinding, WSDualHttpBinding et NetTcpBinding avec une information d'identification de client Windows.
BasicHttpBinding avec BasicHttpSecurityMode défini à l'information d'identification TransportWithMessageCredential, ou toute autre liaison standard dans laquelle le client présente une information d'identification de nom d'utilisateur que le service peut mapper à un compte Windows valide.
Tout CustomBinding qui utilise une information d'identification de client Windows avec requireCancellation défini à true. (La propriété est disponible sur les classes suivantes : SecureConversationSecurityTokenParameters, SslSecurityTokenParameters et SspiSecurityTokenParameters.) Si une conversation sécurisée est utilisée sur la liaison, sa propriété requireCancellation doit également avoir la valeur true.
Tout CustomBinding où le client présente une information d'identification de nom d'utilisateur. Si une conversation sécurisée est utilisée sur la liaison, sa propriété requireCancellation doit également avoir la valeur true.
Emprunt d'identité basé sur S4U
Vous pouvez effectuer l'emprunt d'identité basé sur S4U à l'aide des éléments suivants :
WSHttpBinding, WSDualHttpBinding et NetTcpBinding avec une information d'identification de client de certificat que le service peut mapper à un compte Windows valide.
Tout CustomBinding qui utilise une information d'identification de client Windows avec la propriété requireCancellation définie à false.
Tout CustomBinding qui utilise un nom d'utilisateur ou une information d'identification de client Windows et une conversation sécurisée avec la propriété requireCancellation définie à false.
L'étendue à laquelle le service peut emprunter l'identité du client dépend des privilèges dont le compte de service dispose lorsqu'il tente l'emprunt d'identité, du type d'emprunt d'identité utilisé, et éventuellement de l'étendue d'emprunt d'identité autorisée par le client.
Remarque : |
---|
Lorsque le client et le service s'exécutent sur le même ordinateur et que le client s'exécute sous un compte système (par exemple, Local System ou Network Service), il n'est pas possible d'emprunter l'identité du client lorsqu'une session sécurisée est établie avec les jetons de contexte de sécurité avec état. Une application Windows Forms ou console s'exécute en général sous le compte actuellement connecté, afin que l'emprunt d'identité du compte puisse être effectué par défaut. Toutefois, lorsque le client est une page ASP.NET et que celle-ci est hébergée dans IIS 6.0 ou IIS 7.0, le client ne s'exécute pas par défaut sous le compte Network Service. Toutes les liaisons fournies par le système qui prennent en charge des sessions sécurisées utilisent par défaut un jeton de contexte de sécurité sans état. Toutefois, si le client est une page ASP.NET, et que des sessions sécurisées avec jetons de sécurité avec état sont utilisées, l'emprunt de l'identité du client est impossible. Pour plus d'informations sur le sujet suivant l'utilisation des jetons de sécurité avec état dans une session sécurisée, consultez Procédure : créer un jeton de contexte de sécurité pour une session sécurisée. |
Emprunt d'identité dans une méthode de service : modèle déclaratif
La plupart des scénarios d'emprunt d'identité impliquent l'exécution de la méthode de service dans le contexte de l'appelant. WCF fournit une fonctionnalité d'emprunt d'identité qui facilite cette procédure en permettant à l'utilisateur d'indiquer la spécification d'emprunt d'identité dans l'attribut OperationBehaviorAttribute. Par exemple, dans le code suivant, l'infrastructure WCF emprunte l'identité de l'appelant avant d'exécuter la méthode Hello
. Toute tentative d'accès aux ressources natives à l'intérieur de la méthode Hello
réussit uniquement si la liste de contrôle d'accès (ACL, Access Control List) de la ressource autorise les privilèges d'accès de l'appelant. Pour activer l'emprunt d'identité, affectez l'une des valeurs d'énumération ImpersonationOption (System.ServiceModel.ImpersonationOption.Required ou System.ServiceModel.ImpersonationOption.Allowed) à la propriété Impersonation, tel qu'indiqué dans l'exemple suivant.
Remarque : |
---|
Lorsqu'un service a des informations d'identification plus élevées que le client distant, celles-ci sont utilisées si la propriété Impersonation a la valeur Allowed. En d'autres termes, si un utilisateur à privilèges faibles fournit ses informations d'identification, un service à privilèges plus élevés exécute la méthode avec les informations d'identification du service, et peut utiliser des ressources que l'utilisateur à privilèges faibles n'aurait pas pu utiliser sinon. |
<ServiceContract()> _
Public Interface IHelloContract
<OperationContract()> _
Function Hello(ByVal message As String) As String
End Interface
Public Class HelloService
Implements IHelloService
<OperationBehavior(Impersonation := ImpersonationOption.Required)> _
Public Function Hello(ByVal message As String) As String Implements IHelloService.Hello
Return "hello"
End Function
End Class
[ServiceContract]
public interface IHelloContract
{
[OperationContract]
string Hello(string message);
}
public class HelloService : IHelloService
{
[OperationBehavior(Impersonation = ImpersonationOption.Required)]
public string Hello(string message)
{
return "hello";
}
}
L'infrastructure WCF peut emprunter l'identité de l'appelant uniquement si celui-ci est authentifié avec des informations d'identification qui peuvent être mappées à un compte d'utilisateur Windows. Si le service est configuré pour authentifier l'utilisation d'une information d'identification qui ne peut pas être mappée à un compte Windows, la méthode de service n'est pas exécutée.
Remarque : |
---|
Sur Windows XP, l'emprunt d'identité échoue si un jeton de contexte de sécurité avec état est créé, ce qui génère un InvalidOperationException. Pour plus d'informations, consultez Scénarios non pris en charge. |
Emprunt d'identité dans une méthode de service : modèle impératif
Un appelant n'a parfois pas besoin d'emprunter l'identité de l'ensemble de la méthode de service pour fonctionner, mais uniquement une partie de celle-ci. Dans ce cas, obtenez l'identité Windows de l'appelant à l'intérieur de la méthode de service et exécutez l'emprunt d'identité de manière impérative. Pour ce faire, utilisez la propriété WindowsIdentity de ServiceSecurityContext pour retourner une instance de la classe WindowsIdentity, et appelez la méthode Impersonate avant d'utiliser l'instance.
Remarque : |
---|
Assurez-vous d'utiliser l'instruction Visual Basic Using ou l'instruction using C# pour rétablir automatiquement l'action d'emprunt d'identité. Si vous n'utilisez pas l'instruction, ou si vous utilisez un langage de programmation autre que Visual Basic ou C#, assurez-vous de rétablir le niveau d'emprunt d'identité. Si vous ne le faites pas, vous risquez de vous exposer à des attaques par déni de service et d'élévation de privilège. |
Public Class HelloService
Implements IHelloService
<OperationBehavior()> _
Public Function Hello(ByVal message As String) As String _
Implements IHelloService.Hello
Dim callerWindowsIdentity As WindowsIdentity = _
ServiceSecurityContext.Current.WindowsIdentity
If (callerWindowsIdentity Is Nothing) Then
Throw New InvalidOperationException( _
"The caller cannot be mapped to a WindowsIdentity")
End If
Dim cxt As WindowsImpersonationContext = callerWindowsIdentity.Impersonate()
Using (cxt)
' Access a file as the caller.
End Using
Return "Hello"
End Function
End Class
public class HelloService : IHelloService
{
[OperationBehavior]
public string Hello(string message)
{
WindowsIdentity callerWindowsIdentity =
ServiceSecurityContext.Current.WindowsIdentity;
if (callerWindowsIdentity == null)
{
throw new InvalidOperationException
("The caller cannot be mapped to a WindowsIdentity");
}
using (callerWindowsIdentity.Impersonate())
{
// Access a file as the caller.
}
return "Hello";
}
}
Emprunt d'identité pour toutes les méthodes de service
Dans certains cas, vous devez exécuter toutes les méthodes d'un service dans le contexte de l'appelant. Au lieu d'activer explicitement cette fonction par méthode, utilisez ServiceAuthorizationBehavior. Comme indiqué dans le code suivant, affectez true à la propriété ImpersonateCallerForAllOperations. ServiceAuthorizationBehavior est récupéré des collections de comportements de la classe ServiceHost. Notez également que la propriété Impersonation de OperationBehaviorAttribute appliquée à chaque méthode doit également avoir la valeur Allowed ou Required.
' Code to create a ServiceHost not shown.
Dim MyServiceAuthoriationBehavior As ServiceAuthorizationBehavior
MyServiceAuthoriationBehavior= serviceHost.Description.Behaviors.Find _
(Of ServiceAuthorizationBehavior)()
MyServiceAuthoriationBehavior.ImpersonateCallerForAllOperations = True
// Code to create a ServiceHost not shown.
ServiceAuthorizationBehavior MyServiceAuthoriationBehavior =
serviceHost.Description.Behaviors.Find<ServiceAuthorizationBehavior>();
MyServiceAuthoriationBehavior.ImpersonateCallerForAllOperations = true;
Le tableau suivant décrit le comportement WCF de toutes les combinaisons possibles de ImpersonationOption et ImpersonateCallerForAllServiceOperations.
ImpersonationOption | ImpersonateCallerForAllServiceOperations | Comportement |
---|---|---|
Required |
n/a |
WCF emprunte l'identité de l'appelant |
Allowed |
false |
WCF n'emprunte par l'identité de l'appelant |
Allowed |
true |
WCF emprunte l'identité de l'appelant |
NotAllowed |
false |
WCF n'emprunte par l'identité de l'appelant |
NotAllowed |
true |
Non autorisé. (Une exception InvalidOperationException est levée.) |
Niveau d'emprunt d'identité obtenu à partir des informations d'identification Windows et emprunt d'identité avec jeton mis en cache
Dans certains scénarios, le client contrôle en partie le niveau d'emprunt d'identité que le service effectue lorsqu'une information d'identification de client Windows est utilisée. L'un de ces scénarios se produit lorsque le client spécifie un niveau d'emprunt d'identité à Anonymous. L'autre se produit lors de l'exécution de l'emprunt d'identité avec un jeton mis en cache. Pour ce faire, définissez la propriété AllowedImpersonationLevel de la classe WindowsClientCredential, qui est accessible en tant que propriété de la classe ChannelFactory générique.
Remarque : |
---|
Si vous spécifiez un niveau d'emprunt d'identité à Anonymous, le client ouvre une session sur le service de façon anonyme. Le service doit donc autoriser des ouvertures de session anonymes, indépendamment de l'exécution de l'emprunt d'identité. |
Le client peut spécifier le niveau d'emprunt d'identité à Anonymous, Identification, Impersonation ou Delegation. Un jeton est uniquement généré au niveau spécifié, tel qu'indiqué dans le code suivant.
Dim cf As ChannelFactory(Of IEcho) = New ChannelFactory(Of IEcho)("EchoEndpoint")
cf.Credentials.Windows.AllowedImpersonationLevel = _
System.Security.Principal.TokenImpersonationLevel.Impersonation
ChannelFactory<IEcho> cf = new ChannelFactory<IEcho>("EchoEndpoint");
cf.Credentials.Windows.AllowedImpersonationLevel =
System.Security.Principal.TokenImpersonationLevel.Impersonation;
Le tableau suivant spécifie le niveau d'emprunt d'identité que le service obtient lors de l'emprunt d'identité à partir d'un jeton mis en cache.
Valeur AllowedImpersonationLevel | Le Service a SeImpersonatePrivilege | Le Service et le client sont capables de délégation | Jeton ImpersonationLevel mis en cache |
---|---|---|---|
Anonymous |
Oui |
n/a |
Impersonation |
Anonyme |
Non |
n/a |
Identification |
Identification |
n/a |
n/a |
Identification |
Impersonation |
Oui |
n/a |
Impersonation |
Impersonation |
Non |
n/a |
Identification |
Delegation |
Oui |
Oui |
Delegation |
Delegation |
Oui |
Non |
Impersonation |
Delegation |
Non |
n/a |
Identification |
Niveau d'emprunt d'identité obtenu à partir des informations d'identification de nom d'utilisateur et emprunt d'identité avec jeton mis en cache
En passant son nom d'utilisateur et son mot de passe au service, un client permet à WCF d'ouvrir une session sous cet utilisateur, ce qui revient à affecter Delegation à la propriété AllowedImpersonationLevel. (AllowedImpersonationLevel est disponible sur les classes WindowsClientCredential et HttpDigestClientCredential.) Le tableau suivant indique le niveau d'emprunt d'identité obtenu lorsque le service reçoit des informations d'identification de nom d'utilisateur.
AllowedImpersonationLevel | Le Service a SeImpersonatePrivilege | Le Service et le client sont capables de délégation | Jeton ImpersonationLevel mis en cache |
---|---|---|---|
n/a |
Oui |
Oui |
Delegation |
n/a |
Oui |
Non |
Impersonation |
n/a |
Non |
n/a |
Identification |
Niveau d'emprunt d'identité obtenu à partir de l'emprunt d'identité basé sur S4U
Le Service a SeTcbPrivilege | Le Service a SeImpersonatePrivilege | Le Service et le client sont capables de délégation | Jeton ImpersonationLevel mis en cache |
---|---|---|---|
Oui |
Oui |
n/a |
Impersonation |
Oui |
Non |
n/a |
Identification |
Non |
n/a |
n/a |
Identification |
Mappage d'un certificat client à un compte Windows
Il est possible pour un client de s'authentifier auprès d'un service à l'aide d'un certificat et que le service mappe le client à un compte existant par le biais d'Active Directory. Le code XML suivant indique comment configurer le service pour mapper le certificat.
<behaviors>
<serviceBehaviors>
<behavior name="MapToWindowsAccount">
<serviceCredentials>
<clientCertificate>
<authentication mapClientCertificateToWindowsAccount="true" />
</clientCertificate>
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
Le code suivant indique comment configurer le service.
// Create a binding that sets a certificate as the client credential type.
WSHttpBinding b = new WSHttpBinding();
b.Security.Message.ClientCredentialType = MessageCredentialType.Certificate;
// Create a service host that maps the certificate to a Windows account.
Uri httpUri = new Uri("https://localhost/Calculator");
ServiceHost sh = new ServiceHost(typeof(HelloService), httpUri);
sh.Credentials.ClientCertificate.Authentication.MapClientCertificateToWindowsAccount = true;
Délégation
Pour déléguer à un service principal, un service doit effectuer une authentification Kerberos multi-leg (SSPI sans NTLM) ou une authentification directe Kerberos au service principal à l'aide de l'identité Windows du client. Pour déléguer à un service principal, créez un ChannelFactory et un canal, puis communiquez par le biais du canal lors de l'emprunt d'identité du client. Avec cette forme de délégation, la distance entre l'emplacement du service principal et le service frontal dépend du niveau d'emprunt d'identité atteint par le service frontal. Lorsque le niveau d'emprunt d'identité est Impersonation, les services frontaux et principaux doivent s'exécuter sur le même ordinateur. Lorsque le niveau d'emprunt d'identité est Delegation, les services frontaux et principaux peuvent être présents sur des ordinateurs séparés ou sur le même ordinateur. L'activation de l'emprunt d'identité au niveau délégation nécessite que la stratégie du domaine Windows soit configurée pour permettre la délégation. Pour plus d'informations sur la configuration d'Active Directory pour la prise en charge de la délégation, consultez Activation de l'authentification déléguée (page pouvant être en anglais).
Remarque : |
---|
Lorsqu'un client s'authentifie auprès du service frontal à l'aide d'un nom d'utilisateur et d'un mot de passe qui correspondent à un compte Windows, le service frontal peut s'authentifier auprès du service principal en réutilisant le nom et le mot de passe du client. Il s'agit d'une forme très puissante de flux d'identité, car la transmission d'un nom d'utilisateur et d'un mot de passe au service principal permet à ce service d'effectuer l'emprunt d'identité, mais elle ne constitue pas une délégation en l'absence de l'utilisation de Kerberos. Les contrôles Active Directory sur la délégation ne s'appliquent pas à l'authentification par nom d'utilisateur et par mot de passe. |
La délégation comme fonction du niveau d'emprunt d'identité
Niveau d'emprunt d'identité | Le service peut effectuer une délégation interprocessus | Le service peut effectuer une délégation sur plusieurs ordinateurs |
---|---|---|
Identification |
Non |
Non |
Impersonation |
Oui |
Non |
Delegation |
Oui |
Oui |
L'exemple de code suivant montre comment utiliser la délégation.
Public Class HelloService
Implements IHelloService
<OperationBehavior(Impersonation:=ImpersonationOption.Required)> _
Public Function Hello(ByVal message As String) As String Implements IHelloService.Hello
Dim callerWindowsIdentity As WindowsIdentity = ServiceSecurityContext.Current.WindowsIdentity
If (callerWindowsIdentity Is Nothing) Then
Throw New InvalidOperationException("The caller cannot be mapped to a Windows identity.")
End If
Dim backendServiceAddress As EndpointAddress = New EndpointAddress("https://localhost:8000/ChannelApp")
' Any binding that performs Windows authentication of the client can be used.
Dim channelFactory As ChannelFactory(Of IHelloService) = _
New ChannelFactory(Of IHelloService)(New NetTcpBinding(), backendServiceAddress)
Dim channel As IHelloService = channelFactory.CreateChannel()
Return channel.Hello(message)
End Function
End Class
public class HelloService : IHelloService
{
[OperationBehavior(Impersonation = ImpersonationOption.Required)]
public string Hello(string message)
{
WindowsIdentity callerWindowsIdentity = ServiceSecurityContext.Current.WindowsIdentity;
if (callerWindowsIdentity == null)
{
throw new InvalidOperationException
("The caller cannot be mapped to a Windows identity.");
}
using (callerWindowsIdentity.Impersonate())
{
EndpointAddress backendServiceAddress = new EndpointAddress("https://localhost:8000/ChannelApp");
// Any binding that performs Windows authentication of the client can be used.
ChannelFactory<IHelloService> channelFactory = new ChannelFactory<IHelloService>(new NetTcpBinding(), backendServiceAddress);
IHelloService channel = channelFactory.CreateChannel();
return channel.Hello(message);
}
}
}
Comment configurer une Application pour utiliser la délégation contrainte
Avant de pouvoir utiliser la délégation contrainte, l'expéditeur, le destinataire et le contrôleur de domaine doivent être configurés en conséquence. La procédure suivante répertorie les étapes qui permettent d'activer la délégation contrainte. Pour des informations sur les différences entre la délégation et la délégation contrainte, consultez la section Extensions Kerberos dans Windows Server 2003 (page pouvant être en anglais) qui traite de la délégation contrainte.
Dans le contrôleur de domaine, désactivez la case à cocher Le compte est sensible et ne peut pas être délégué pour le compte sous lequel s'exécute l'application cliente.
Dans le contrôleur de domaine, activez la case à cocher Le compte est approuvé pour la délégation pour le compte sous lequel s'exécute l'application cliente.
Dans le contrôleur de domaine, configurez l'ordinateur intermédiaire pour qu'il soit approuvé pour la délégation en cliquant sur l'option Approuver l'ordinateur pour la délégation.
Dans le contrôleur de domaine, configurez l'ordinateur intermédiaire pour utiliser la délégation contrainte en cliquant sur l'option N'approuver cet ordinateur que pour la délégation aux services spécifiés.
Pour des instructions plus détaillées sur la configuration de la délégation contrainte, consultez les rubriques suivantes sur MSDN :
Résolution des problèmes liés à la délégation Kerberos (page pouvant être en anglais)
Transition du protocole Kerberos et délégation contrainte (page pouvant être en anglais)
Voir aussi
Tâches
Impersonating the Client
Comment : emprunter l'identité d'un client sur un service
Référence
OperationBehaviorAttribute
Impersonation
ImpersonationOption
WindowsIdentity
ServiceSecurityContext
WindowsIdentity
ServiceAuthorizationBehavior
ImpersonateCallerForAllOperations
ServiceHost
AllowedImpersonationLevel
WindowsClientCredential
ChannelFactory
Identification
Concepts
Utilisation de l'emprunt d'identité avec la sécurité de transport
Outil Service Model Metadata Tool (Svcutil.exe)