Partager via


Délégation et emprunt d’identité avec WCF

L’emprunt d’identité est une technique courante que les services utilisent pour restreindre l’accès 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 un exemple d'application, consultez Usurper l'identité du client. Pour obtenir un exemple d’utilisation de l’usurpation d’identité, consultez Comment usurper l’identité d’un client sur un service.

Importante

N’oubliez pas 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 peuvent avoir des privilèges plus élevés que le processus serveur.

Aperçu

En règle générale, les clients appellent un service pour que le service effectue une action au nom du client. L’emprunt d’identité permet au service d’agir en tant que client lors de l’exécution de l’action. La délégation permet à un service frontal de transférer la requête du client vers un service back-end de manière à ce que le service back-end puisse également usurper l'identité du client. L’emprunt d’identité est le plus couramment utilisé pour vérifier si un client est autorisé à effectuer une action particulière, tandis que la délégation est un moyen de transmettre les fonctionnalités d’emprunt d’identité, ainsi que l’identité du client, à un service principal. La délégation est une fonctionnalité de domaine Windows qui peut être utilisée lorsque l’authentification Kerberos est effectuée. La délégation est distincte du flux d’identité et, étant donné que la délégation transfère la possibilité d’emprunter l’identité du client sans possession du mot de passe du client, il s’agit d’une opération privilégiée beaucoup plus élevée que le flux d’identité.

L’emprunt d’identité et la délégation nécessitent que le client dispose d’une identité Windows. Si un client ne possède pas d’identité Windows, la seule option disponible consiste à transmettre l’identité du client au deuxième service.

Principes fondamentaux de l'usurpation d'identité

Windows Communication Foundation (WCF) prend en charge l'usurpation d'identité pour divers identifiants 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. Les scénarios de déploiement courants impliquant l’emprunt d’identité et la sécurité SOAP et les options WCF sont également abordés 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

La sécurité SOAP WCF a deux méthodes distinctes pour l’exécution de l’emprunt d’identité. La méthode utilisée dépend du type de reliure. 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 :

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.

La mesure dans laquelle le service peut emprunter l’identité du client dépend des privilèges que le compte de service conserve lorsqu’il tente d’emprunter l’identité, le type d’emprunt d’identité utilisé et éventuellement l’étendue de l’emprunt d’identité que le client autorise.

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 Form ou console s’exécute généralement sous le compte actuellement connecté, afin que ce compte puisse être usurpé par défaut. Toutefois, lorsque le client est une page ASP.NET et que cette page est hébergée dans IIS 6.0 ou IIS 7.0, le client s’exécute sous le Network Service compte par défaut. 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 contexte de sécurité (SCT) avec état sont utilisées, l’emprunt de l’identité du client est impossible. Pour plus d’informations sur l’utilisation de scT avec état dans une session sécurisée, consultez Guide pratique pour 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’usurpation 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 opération en permettant à l’utilisateur de spécifier l’exigence d’emprunt d’identité dans l’attribut OperationBehaviorAttribute . Par exemple, dans le code suivant, l’infrastructure WCF usurpe 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 Hello méthode réussit uniquement si la liste de contrôle d’accès (ACL) 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 Impersonation ( ImpersonationOption ou ImpersonationOption.Required ) à la propriété ImpersonationOption.Allowed, tel qu'indiqué dans l'exemple suivant.

Remarque

Lorsqu’un service a des informations d’identification supérieures à celles du client distant, les informations d’identification du service sont utilisées si la propriété Impersonation est définie sur Allowed. Autrement dit, si un utilisateur à privilèges faibles fournit ses informations d’identification, un service à privilèges supérieurs exécute la méthode avec les informations d’identification du service et peut utiliser des ressources que l’utilisateur à privilèges faibles ne serait pas en mesure d’utiliser.

[ServiceContract]
public interface IHelloContract
{
    [OperationContract]
    string Hello(string message);
}

public class HelloService : IHelloService
{
    [OperationBehavior(Impersonation = ImpersonationOption.Required)]
    public string Hello(string message)
    {
        return "hello";
    }
}

<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

L’infrastructure WCF peut emprunter l’identité de l’appelant uniquement si l’appelant est authentifié avec des informations d’identification qui peuvent être mappées à un compte d’utilisateur Windows. Si le service est configuré pour s’authentifier à l’aide d’informations d’identification qui ne peuvent pas être mappées à 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é (SCT) avec état est créé, ce qui génère un InvalidOperationException. Pour plus d’informations, consultez Scénarios non pris en charge.

Usurpation 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 WindowsIdentity propriété de la ServiceSecurityContext propriété pour retourner une instance de la WindowsIdentity classe et appeler la Impersonate méthode avant d’utiliser l’instance.

Remarque

Assurez-vous d’utiliser l’instruction Using en Visual Basic ou l’instruction using en 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#, veillez à ramener le niveau d'usurpation d'identité à son état initial. L’échec de cette opération peut constituer la base d’attaques par déni de service et d’élévation de privilèges.

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

Emprunt d'identité pour toutes les méthodes de service

Dans certains cas, vous devez effectuer toutes les méthodes d’un service dans le contexte de l’appelant. Au lieu d’activer explicitement cette fonctionnalité par méthode, utilisez le ServiceAuthorizationBehavior. Comme indiqué dans le code suivant, définissez la ImpersonateCallerForAllOperations propriété sur true. Le ServiceAuthorizationBehavior est récupéré à partir des collections de comportements de la classe ServiceHost. Notez également que la propriété Impersonation de OperationBehaviorAttribute appliquée à chaque méthode doit également être définie sur Allowed ou Required.

// Code to create a ServiceHost not shown.
ServiceAuthorizationBehavior MyServiceAuthorizationBehavior =
    serviceHost.Description.Behaviors.Find<ServiceAuthorizationBehavior>();
MyServiceAuthorizationBehavior.ImpersonateCallerForAllOperations = true;
' Code to create a ServiceHost not shown.
Dim MyServiceAuthorizationBehavior As ServiceAuthorizationBehavior
MyServiceAuthorizationBehavior = serviceHost.Description.Behaviors.Find _
(Of ServiceAuthorizationBehavior)()
MyServiceAuthorizationBehavior.ImpersonateCallerForAllOperations = True

Le tableau suivant décrit le comportement WCF pour toutes les combinaisons possibles de ImpersonationOption et ImpersonateCallerForAllServiceOperations.

ImpersonationOption ImpersonateCallerForAllServiceOperations Comportement
Obligatoire n/a Le WCF usurpe l'identité de l'appelant
Autorisé faux WCF n’usurpe pas l’identité de l’appelant
Autorisé vrai Le WCF usurpe l'identité de l'appelant
Non autorisé faux WCF n’usurpe pas l’identité de l’appelant
Non autorisé vrai Rejeté. (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 a un contrôle partiel sur le niveau d’emprunt d’identité que le service effectue lorsqu’une information d’identification du client Windows est utilisée. Un scénario se produit lorsque le client spécifie un niveau d’imitation anonyme. 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 AllowedImpersonationLevel propriété de la WindowsClientCredential classe, accessible en tant que propriété de la classe générique ChannelFactory<TChannel> .

Remarque

Si vous spécifiez un niveau d’emprunt d’identité d’Anonymous, le client se connecte au 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é comme Anonymous, Identification, Impersonation ou Delegation. Seul un jeton au niveau spécifié est produit, comme indiqué dans le code suivant.

ChannelFactory<IEcho> cf = new ChannelFactory<IEcho>("EchoEndpoint");
cf.Credentials.Windows.AllowedImpersonationLevel  =
    System.Security.Principal.TokenImpersonationLevel.Impersonation;
Dim cf As ChannelFactory(Of IEcho) = New ChannelFactory(Of 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 peuvent être délégués Jeton mis en cache ImpersonationLevel
Anonyme Oui n/a Usurpation d'identité
Anonyme Non n/a Identification
Identification n/a n/a Identification
Usurpation d'identité Oui n/a Usurpation d'identité
Usurpation d'identité Non n/a Identification
Délégation Oui Oui Délégation
Délégation Oui Non Usurpation d'identité
Délégation 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 transmettant son nom d’utilisateur et son mot de passe au service, un client permet à WCF de se connecter en tant que cet utilisateur, ce qui équivaut à définir la propriété AllowedImpersonationLevelDelegation. (Le AllowedImpersonationLevel est disponible dans les classes WindowsClientCredential et HttpDigestClientCredential.) Le tableau suivant fournit le niveau de simulation d'identité obtenu lorsque le service reçoit les informations d'identification du nom d'utilisateur.

AllowedImpersonationLevel Le Service a SeImpersonatePrivilege Le service et le client peuvent être délégués Jeton mis en cache ImpersonationLevel
n/a Oui Oui Délégation
n/a Oui Non Usurpation d'identité
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 peuvent être délégués Jeton mis en cache ImpersonationLevel
Oui Oui n/a Usurpation d'identité
Oui Non n/a Identification
Non n/a n/a Identification

Mappage d’un certificat client à un compte Windows

Il est possible qu’un client s’authentifie auprès d’un service à l’aide d’un certificat et que le service mappe le client à un compte existant via Active Directory. Le code XML suivant montre 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 montre 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("http://localhost/Calculator");  
ServiceHost sh = new ServiceHost(typeof(HelloService), httpUri);  
sh.Credentials.ClientCertificate.Authentication.MapClientCertificateToWindowsAccount = true;  

Délégation

Pour déléguer à un service back-end, un service doit effectuer une authentification Kerberos multi-étape (SSPI sans recours à NTLM) ou une authentification directe Kerberos vers le service back-end à l’aide de l’identité Windows du client. Pour déléguer à un service back-end, créez un ChannelFactory<TChannel> et un canal, puis communiquez via le canal en se faisant passer pour le 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 de la délégation nécessite que la stratégie de domaine Windows soit configurée pour autoriser 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.

Remarque

Lorsqu’un client s’authentifie auprès du service frontal à l’aide d’un nom d’utilisateur et d’un mot de passe correspondant à un compte Windows sur le service principal, le service frontal peut s’authentifier auprès du service principal en réutilisant le nom d’utilisateur et le mot de passe du client. Il s’agit d’une forme particulièrement puissante de flux d’identité, car le passage du nom d’utilisateur et du mot de passe au service principal permet au service principal d’effectuer l’emprunt d’identité, mais il ne constitue pas une délégation, car Kerberos n’est pas utilisé. Les contrôles Active Directory sur la délégation ne s’appliquent pas à l’authentification par nom d’utilisateur et mot de passe.

Capacité de délégation en tant que fonction du niveau d’usurpation d’identité

Niveau d'emprunt d'identité Le service peut effectuer une délégation inter-processus 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 : 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("http://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);
        }
    }
}
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("http://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

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 pour le faire. La procédure suivante répertorie les étapes qui activent la délégation contrainte. Pour plus d’informations sur les différences entre la délégation et la délégation contrainte, consultez la partie des extensions Kerberos Windows Server 2003 qui traite de la discussion contrainte.

  1. Sur le contrôleur de domaine, désactivez la case à cocher « Compte est sensible et ne peut pas être délégué » pour le compte sous lequel l'application cliente s'exécute.

  2. Sur le contrôleur de domaine, activez la case à cocher Compte approuvé pour la délégation pour le compte sous lequel l’application cliente s’exécute.

  3. Sur le contrôleur de domaine, configurez l’ordinateur de niveau intermédiaire afin qu’il soit approuvé pour la délégation, en cliquant sur l’option Approuver l’ordinateur pour la délégation .

  4. Sur le contrôleur de domaine, configurez l’ordinateur de niveau intermédiaire pour qu’il utilise la délégation contrainte, en cliquant sur l’option Approuver cet ordinateur pour la délégation aux services spécifiés uniquement .

Pour obtenir des instructions plus détaillées sur la configuration de la délégation contrainte, consultez Transition de protocole Kerberos et Délégation contrainte.

Voir aussi