Partager via


Guide du développeur Windows Protection des données (WIP)

Une application compatible différencie les données d’entreprise et personnelles et sait qui protéger en fonction des stratégies Windows Protection des données (WIP) définies par l’administrateur.

Dans ce guide, nous allons vous montrer comment en créer un. Lorsque vous avez terminé, les administrateurs de stratégie pourront approuver votre application pour consommer les données de leur organisation. De plus, les employés apprécieront que vous ayez conservé leurs données personnelles intactes sur leur appareil même s’ils se sont désinscrits de la gestion des périphériques mobiles (GPM) de leur organisation ou s’ils ont quitté totalement l’organisation.

Notez que ce guide vous aide à éclairer une application UWP. Si vous souhaitez éclairer une application de bureau Windows C++, consultez le guide du développeur windows Protection des données (WIP) (C++).

Vous pouvez en savoir plus sur wip et les applications compatibles ici : Windows Protection des données (WIP).

Vous trouverez ici un exemple complet.

Si vous êtes prêt à passer par chaque tâche, commençons.

Tout d’abord, rassemblez ce dont vous avez besoin

Vous en aurez besoin :

  • Machine virtuelle de test qui exécute Windows 10, version 1607 ou ultérieure. Vous allez déboguer votre application sur cette machine virtuelle de test.

  • Ordinateur de développement qui exécute Windows 10, version 1607 ou ultérieure. Il peut s’agir de votre machine virtuelle de test si Visual Studio l’a installé.

Configurer votre environnement de développement

Vous allez effectuer ces opérations :

Installer l’Assistant Développeur du programme d’installation WIP sur votre machine virtuelle de test

Utilisez cet outil pour configurer une stratégie Windows Protection des données sur votre machine virtuelle de test.

Téléchargez l’outil ici : Assistant Programme d’installation de WIP.

Création d’une stratégie de protection

Définissez votre stratégie en ajoutant des informations à chaque section de l’Assistant développeur de configuration WIP. Choisissez l’icône d’aide en regard de n’importe quel paramètre pour en savoir plus sur son utilisation.

Pour obtenir des conseils plus généraux sur l’utilisation de cet outil, consultez la section Notes de version sur la page de téléchargement de l’application.

Configurer un projet Visual Studio

  1. Sur votre ordinateur de développement, ouvrez votre projet.

  2. Ajoutez une référence aux extensions de bureau et mobiles pour plateforme Windows universelle (UWP).

    Ajouter des extensions UWP

  3. Ajoutez cette fonctionnalité à votre fichier manifeste de package :

       <rescap:Capability Name="enterpriseDataPolicy"/>
    

    Lecture facultative : le préfixe « récap » signifie Capacité restreinte. Consultez les fonctionnalités spéciales et restreintes.

  4. Ajoutez cet espace de noms à votre fichier manifeste de package :

      xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
    
  5. Ajoutez le préfixe d’espace de noms à l’élément <ignorableNamespaces> de votre fichier manifeste de package.

        <IgnorableNamespaces="uap mp rescap">
    

    De cette façon, si votre application s’exécute sur une version du système d’exploitation Windows qui ne prend pas en charge les fonctionnalités restreintes, Windows ignore la enterpriseDataPolicy fonctionnalité.

Configurer le débogage à distance

Installez Visual Studio Remote Tools sur votre machine virtuelle de test uniquement si vous développez votre application sur un ordinateur autre que votre machine virtuelle. Ensuite, sur votre ordinateur de développement, démarrez le débogueur distant et vérifiez si votre application s’exécute sur la machine virtuelle de test.

Consultez les instructions relatives au PC distant.

Ajouter ces espaces de noms à vos fichiers de code

Ajoutez ces instructions using en haut de vos fichiers de code (les extraits de code de ce guide les utilisent) :

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.Security.EnterpriseData;
using Windows.Web.Http;
using Windows.Storage.Streams;
using Windows.ApplicationModel.DataTransfer;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml;
using Windows.ApplicationModel.Activation;
using Windows.Web.Http.Filters;
using Windows.Storage;
using Windows.Data.Xml.Dom;
using Windows.Foundation.Metadata;
using Windows.Web.Http.Headers;

Déterminer s’il faut utiliser des API WIP dans votre application

Vérifiez que le système d’exploitation qui exécute votre application prend en charge WIP et que WIP est activé sur l’appareil.

bool use_WIP_APIs = false;

if ((ApiInformation.IsApiContractPresent
    ("Windows.Security.EnterpriseData.EnterpriseDataContract", 3)
    && ProtectionPolicyManager.IsProtectionEnabled))
{
    use_WIP_APIs = true;
}
else
{
    use_WIP_APIs = false;
}

N’appelez pas d’API WIP si le système d’exploitation ne prend pas en charge WIP ou WIP n’est pas activé sur l’appareil.

Lire les données d’entreprise

Pour lire des fichiers protégés, des points de terminaison réseau, des données et des données du Presse-papiers que vous acceptez à partir d’un contrat Share, votre application devra demander l’accès.

Windows Protection des données autorise votre application si votre application figure dans la liste autorisée de la stratégie de protection.

Dans cette section :

Lire les données d’un fichier

Étape 1 : Obtenir le handle de fichier

    Windows.Storage.StorageFolder storageFolder =
        Windows.Storage.ApplicationData.Current.LocalFolder;

    Windows.Storage.StorageFile file =
        await storageFolder.GetFileAsync(fileName);

Étape 2 : Déterminer si votre application peut ouvrir le fichier

Appelez FileProtectionManager.GetProtectionInfoAsync pour déterminer si votre application peut ouvrir le fichier.

FileProtectionInfo protectionInfo = await FileProtectionManager.GetProtectionInfoAsync(file);

if ((protectionInfo.Status != FileProtectionStatus.Protected &&
    protectionInfo.Status != FileProtectionStatus.Unprotected))
{
    return false;
}
else if (protectionInfo.Status == FileProtectionStatus.Revoked)
{
    // Code goes here to handle this situation. Perhaps, show UI
    // saying that the user's data has been revoked.
}

Une valeur FileProtectionStatus de Protected signifie que le fichier est protégé et que votre application peut l’ouvrir, car votre application se trouve dans la liste autorisée de la stratégie.

Une valeur FileProtectionStatus d’UnProtected signifie que le fichier n’est pas protégé et que votre application peut ouvrir le fichier même si votre application ne figure pas dans la liste autorisée de la stratégie.

API
FileProtectionManager.GetProtectionInfoAsync
FileProtectionInfo
FileProtectionStatus
ProtectionPolicyManager.IsIdentityManaged

Étape 3 : Lire le fichier dans un flux ou une mémoire tampon

Lire le fichier dans un flux

var stream = await file.OpenAsync(Windows.Storage.FileAccessMode.ReadWrite);

Lire le fichier dans une mémoire tampon

var buffer = await Windows.Storage.FileIO.ReadBufferAsync(file);

Lire des données à partir d’un point de terminaison réseau

Créez un contexte de thread protégé pour lire à partir d’un point de terminaison d’entreprise.

Étape 1 : Obtenir l’identité du point de terminaison réseau

Uri resourceURI = new Uri("http://contoso.com/stockData.xml");

Windows.Networking.HostName hostName =
    new Windows.Networking.HostName(resourceURI.Host);

string identity = await ProtectionPolicyManager.
    GetPrimaryManagedIdentityForNetworkEndpointAsync(hostName);

Si le point de terminaison n’est pas géré par la stratégie, vous obtenez une chaîne vide.

API
ProtectionPolicyManager.GetPrimaryManagedIdentityForNetworkEndpointAsync

Étape 2 : Créer un contexte de thread protégé

Si le point de terminaison est géré par stratégie, créez un contexte de thread protégé. Cela étiquette toutes les connexions réseau que vous effectuez sur le même thread à l’identité.

Il vous donne également accès aux ressources réseau d’entreprise gérées par cette stratégie.

if (!string.IsNullOrEmpty(identity))
{
    using (ThreadNetworkContext threadNetworkContext =
            ProtectionPolicyManager.CreateCurrentThreadNetworkContext(identity))
    {
        return await GetDataFromNetworkRedirectHelperMethod(resourceURI);
    }
}
else
{
    return await GetDataFromNetworkRedirectHelperMethod(resourceURI);
}

Cet exemple place les appels de socket dans un using bloc. Si ce n’est pas le cas, assurez-vous de fermer le contexte de thread une fois que vous avez récupéré votre ressource. Voir ThreadNetworkContext.Close.

Ne créez aucun fichier personnel sur ce thread protégé, car ces fichiers seront automatiquement chiffrés.

La méthode ProtectionPolicyManager.CreateCurrentThreadNetworkContext retourne un objet ThreadNetworkContext, que le point de terminaison soit géré ou non par la stratégie. Si votre application gère les ressources personnelles et d’entreprise, appelez ProtectionPolicyManager.CreateCurrentThreadNetworkContext pour toutes les identités. Après avoir obtenu la ressource, supprimez ThreadNetworkContext pour effacer toute balise d’identité du thread actuel.

API
ProtectionPolicyManager.GetForCurrentView
ProtectionPolicyManager.Identity
ProtectionPolicyManager.CreateCurrentThreadNetworkContext

Étape 3 : Lire la ressource dans une mémoire tampon

private static async Task<IBuffer> GetDataFromNetworkHelperMethod(Uri resourceURI)
{
    HttpClient client;

    client = new HttpClient();

    try { return await client.GetBufferAsync(resourceURI); }

    catch (Exception) { return null; }
}

(Facultatif) Utiliser un jeton d’en-tête au lieu de créer un contexte de thread protégé

public static async Task<IBuffer> GetDataFromNetworkbyUsingHeader(Uri resourceURI)
{
    HttpClient client;

    Windows.Networking.HostName hostName =
        new Windows.Networking.HostName(resourceURI.Host);

    string identity = await ProtectionPolicyManager.
        GetPrimaryManagedIdentityForNetworkEndpointAsync(hostName);

    if (!string.IsNullOrEmpty(identity))
    {
        client = new HttpClient();

        HttpRequestHeaderCollection headerCollection = client.DefaultRequestHeaders;

        headerCollection.Add("X-MS-Windows-HttpClient-EnterpriseId", identity);

        return await GetDataFromNetworkbyUsingHeaderHelperMethod(client, resourceURI);
    }
    else
    {
        client = new HttpClient();
        return await GetDataFromNetworkbyUsingHeaderHelperMethod(client, resourceURI);
    }

}

private static async Task<IBuffer> GetDataFromNetworkbyUsingHeaderHelperMethod(HttpClient client, Uri resourceURI)
{

    try { return await client.GetBufferAsync(resourceURI); }

    catch (Exception) { return null; }
}

Gérer les redirections de page

Parfois, un serveur web redirige le trafic vers une version plus récente d’une ressource.

Pour gérer ce problème, effectuez des demandes jusqu’à ce que l’état de réponse de votre demande ait la valeur OK.

Utilisez ensuite l’URI de cette réponse pour obtenir l’identité du point de terminaison. Voici une façon de procéder :

private static async Task<IBuffer> GetDataFromNetworkRedirectHelperMethod(Uri resourceURI)
{
    HttpClient client = null;

    HttpBaseProtocolFilter filter = new HttpBaseProtocolFilter();
    filter.AllowAutoRedirect = false;

    client = new HttpClient(filter);

    HttpResponseMessage response = null;

        HttpRequestMessage message = new HttpRequestMessage(HttpMethod.Get, resourceURI);
        response = await client.SendRequestAsync(message);

    if (response.StatusCode == HttpStatusCode.MultipleChoices ||
        response.StatusCode == HttpStatusCode.MovedPermanently ||
        response.StatusCode == HttpStatusCode.Found ||
        response.StatusCode == HttpStatusCode.SeeOther ||
        response.StatusCode == HttpStatusCode.NotModified ||
        response.StatusCode == HttpStatusCode.UseProxy ||
        response.StatusCode == HttpStatusCode.TemporaryRedirect ||
        response.StatusCode == HttpStatusCode.PermanentRedirect)
    {
        message = new HttpRequestMessage(HttpMethod.Get, message.RequestUri);
        response = await client.SendRequestAsync(message);

        try { return await response.Content.ReadAsBufferAsync(); }

        catch (Exception) { return null; }
    }
    else
    {
        try { return await response.Content.ReadAsBufferAsync(); }

        catch (Exception) { return null; }
    }
}

API
ProtectionPolicyManager.GetPrimaryManagedIdentityForNetworkEndpointAsync
ProtectionPolicyManager.CreateCurrentThreadNetworkContext
ProtectionPolicyManager.GetForCurrentView
ProtectionPolicyManager.Identity

Lire les données du Presse-papiers

Obtenir l’autorisation d’utiliser des données à partir du Presse-papiers

Pour obtenir des données à partir du Presse-papiers, demandez l’autorisation à Windows. Utilisez DataPackageView.RequestAccessAsync pour ce faire.

public static async Task PasteText(TextBox textBox)
{
    DataPackageView dataPackageView = Clipboard.GetContent();

    if (dataPackageView.Contains(StandardDataFormats.Text))
    {
        ProtectionPolicyEvaluationResult result = await dataPackageView.RequestAccessAsync();

        if (result == ProtectionPolicyEvaluationResult..Allowed)
        {
            string contentsOfClipboard = await dataPackageView.GetTextAsync();
            textBox.Text = contentsOfClipboard;
        }
    }
}

API
DataPackageView.RequestAccessAsync

Masquer ou désactiver des fonctionnalités qui utilisent des données du Presse-papiers

Déterminez si l’affichage actuel dispose de l’autorisation d’obtenir des données qui se trouve dans le Presse-papiers.

Si ce n’est pas le cas, vous pouvez désactiver ou masquer des contrôles qui permettent aux utilisateurs de coller des informations dans le Presse-papiers ou d’afficher un aperçu de son contenu.

private bool IsClipboardAllowedAsync()
{
    ProtectionPolicyEvaluationResult protectionPolicyEvaluationResult = ProtectionPolicyEvaluationResult.Blocked;

    DataPackageView dataPackageView = Clipboard.GetContent();

    if (dataPackageView.Contains(StandardDataFormats.Text))

        protectionPolicyEvaluationResult =
            ProtectionPolicyManager.CheckAccess(dataPackageView.Properties.EnterpriseId,
                ProtectionPolicyManager.GetForCurrentView().Identity);

    return (protectionPolicyEvaluationResult == ProtectionPolicyEvaluationResult.Allowed |
        protectionPolicyEvaluationResult == ProtectionPolicyEvaluationResult.ConsentRequired);
}

API
ProtectionPolicyEvaluationResult
ProtectionPolicyManager.GetForCurrentView
ProtectionPolicyManager.Identity

Empêcher les utilisateurs d’être invités avec une boîte de dialogue de consentement

Un nouveau document n’est pas personnel ou d’entreprise. C’est juste nouveau. Si un utilisateur y colle des données d’entreprise, Windows applique la stratégie et l’utilisateur est invité à utiliser une boîte de dialogue de consentement. Ce code empêche cela de se produire. Cette tâche ne vise pas à protéger les données. Il s’agit plus d’empêcher les utilisateurs de recevoir la boîte de dialogue de consentement dans les cas où votre application crée un nouvel élément.

private async void PasteText(bool isNewEmptyDocument)
{
    DataPackageView dataPackageView = Clipboard.GetContent();

    if (dataPackageView.Contains(StandardDataFormats.Text))
    {
        if (!string.IsNullOrEmpty(dataPackageView.Properties.EnterpriseId))
        {
            if (isNewEmptyDocument)
            {
                ProtectionPolicyManager.TryApplyProcessUIPolicy(dataPackageView.Properties.EnterpriseId);
                string contentsOfClipboard = contentsOfClipboard = await dataPackageView.GetTextAsync();
                // add this string to the new item or document here.          

            }
            else
            {
                ProtectionPolicyEvaluationResult result = await dataPackageView.RequestAccessAsync();

                if (result == ProtectionPolicyEvaluationResult.Allowed)
                {
                    string contentsOfClipboard = contentsOfClipboard = await dataPackageView.GetTextAsync();
                    // add this string to the new item or document here.
                }
            }
        }
    }
}

API
DataPackageView.RequestAccessAsync
ProtectionPolicyEvaluationResult
ProtectionPolicyManager.TryApplyProcessUIPolicy

Lire des données à partir d’un contrat Share

Lorsque les employés choisissent votre application pour partager leurs informations, votre application ouvre un nouvel élément qui contient ce contenu.

Comme nous l’avons mentionné précédemment, un nouvel élément n’est pas personnel ou d’entreprise. C’est juste nouveau. Si votre code ajoute du contenu d’entreprise à l’élément, Windows applique la stratégie et l’utilisateur est invité à utiliser une boîte de dialogue de consentement. Ce code empêche cela de se produire.

protected override async void OnShareTargetActivated(ShareTargetActivatedEventArgs args)
{
    bool isNewEmptyDocument = true;
    string identity = "corp.microsoft.com";

    ShareOperation shareOperation = args.ShareOperation;
    if (shareOperation.Data.Contains(StandardDataFormats.Text))
    {
        if (!string.IsNullOrEmpty(shareOperation.Data.Properties.EnterpriseId))
        {
            if (isNewEmptyDocument)
                // If this is a new and empty document, and we're allowed to access
                // the data, then we can avoid popping the consent dialog
                ProtectionPolicyManager.TryApplyProcessUIPolicy(shareOperation.Data.Properties.EnterpriseId);
            else
            {
                // In this case, we can't optimize the workflow, so we just
                // request consent from the user in this case.

                ProtectionPolicyEvaluationResult protectionPolicyEvaluationResult = await shareOperation.Data.RequestAccessAsync();

                if (protectionPolicyEvaluationResult == ProtectionPolicyEvaluationResult.Allowed)
                {
                    string text = await shareOperation.Data.GetTextAsync();

                    // Do something with that text.
                }
            }
        }
        else
        {
            // If the data has no enterprise identity, then we already have access.
            string text = await shareOperation.Data.GetTextAsync();

            // Do something with that text.
        }

    }

}

API
ProtectionPolicyManager.RequestAccessAsync
ProtectionPolicyEvaluationResult
ProtectionPolicyManager.TryApplyProcessUIPolicy

Protéger les données d’entreprise

Protégez les données d’entreprise qui quittent votre application. Les données quittent votre application lorsque vous l’affichez dans une page, enregistrez-la dans un fichier ou un point de terminaison réseau, ou via un contrat de partage.

Dans cette section :

Protéger les données qui s’affichent dans les pages

Lorsque vous affichez des données dans une page, indiquez à Windows quel type de données il s’agit (personnel ou entreprise). Pour ce faire, étiquetez l’affichage actuel de l’application ou marquez l’ensemble du processus d’application.

Lorsque vous balisez l’affichage ou le processus, Windows applique la stratégie sur celle-ci. Cela permet d’éviter les fuites de données résultant d’actions que votre application ne contrôle pas. Par exemple, sur un ordinateur, un utilisateur peut utiliser Ctrl-V pour copier des informations d’entreprise à partir d’une vue, puis coller ces informations dans une autre application. Windows protège contre cela. Windows permet également d’appliquer des contrats de partage.

Baliser l’affichage de l’application actuelle

Pour ce faire, si votre application a plusieurs vues où certaines vues consomment des données d’entreprise et certaines consomment des données personnelles.


// tag as enterprise data. "identity" the string that contains the enterprise ID.
// You'd get that from a file, network endpoint, or clipboard data package.
ProtectionPolicyManager.GetForCurrentView().Identity = identity;

// tag as personal data.
ProtectionPolicyManager.GetForCurrentView().Identity = String.Empty;

API
ProtectionPolicyManager.GetForCurrentView
ProtectionPolicyManager.Identity

Étiqueter le processus

Procédez ainsi si toutes les vues de votre application fonctionnent avec un seul type de données (personnel ou entreprise).

Cela vous empêche de devoir gérer des vues étiquetées indépendamment.



// tag as enterprise data. "identity" the string that contains the enterprise ID.
// You'd get that from a file, network endpoint, or clipboard data package.
bool result =
            ProtectionPolicyManager.TryApplyProcessUIPolicy(identity);

// tag as personal data.
ProtectionPolicyManager.ClearProcessUIPolicy();

API
ProtectionPolicyManager.TryApplyProcessUIPolicy

Protéger les données dans un fichier

Créez un fichier protégé, puis écrivez-y.

Étape 1 : Déterminer si votre application peut créer un fichier d’entreprise

Votre application peut créer un fichier d’entreprise si la chaîne d’identité est gérée par stratégie et que votre application figure dans la liste Autorisée de cette stratégie.

  if (!ProtectionPolicyManager.IsIdentityManaged(identity)) return false;

API
ProtectionPolicyManager.IsIdentityManaged

Étape 2 : Créer le fichier et le protéger sur l’identité

StorageFolder storageFolder = ApplicationData.Current.LocalFolder;
StorageFile storageFile = await storageFolder.CreateFileAsync("sample.txt",
    CreationCollisionOption.ReplaceExisting);

FileProtectionInfo fileProtectionInfo =
    await FileProtectionManager.ProtectAsync(storageFile, identity);

API
FileProtectionManager.ProtectAsync

Étape 3 : Écrire ce flux ou cette mémoire tampon dans le fichier

Écrire un flux

    if (fileProtectionInfo.Status == FileProtectionStatus.Protected)
    {
        var stream = await storageFile.OpenAsync(FileAccessMode.ReadWrite);

        using (var outputStream = stream.GetOutputStreamAt(0))
        {
            using (var dataWriter = new DataWriter(outputStream))
            {
                dataWriter.WriteString(enterpriseData);
            }
        }

    }

Écrire une mémoire tampon

     if (fileProtectionInfo.Status == FileProtectionStatus.Protected)
     {
         var buffer = Windows.Security.Cryptography.CryptographicBuffer.ConvertStringToBinary(
             enterpriseData, Windows.Security.Cryptography.BinaryStringEncoding.Utf8);

         await FileIO.WriteBufferAsync(storageFile, buffer);

      }

API
FileProtectionInfo
FileProtectionStatus

Protéger les données dans un fichier en tant que processus en arrière-plan

Ce code peut s’exécuter pendant que l’écran de l’appareil est verrouillé. Si l’administrateur a configuré une stratégie sécurisée « Protection des données sous verrou » (DPL), Windows supprime les clés de chiffrement requises pour accéder aux ressources protégées de la mémoire de l’appareil. Cela empêche les fuites de données si l’appareil est perdu. Cette même fonctionnalité supprime également les clés associées aux fichiers protégés lorsque leurs handles sont fermés.

Vous devrez utiliser une approche qui maintient le handle de fichier ouvert lorsque vous créez un fichier.

Étape 1 : Déterminer si vous pouvez créer un fichier d’entreprise

Vous pouvez créer un fichier d’entreprise si l’identité que vous utilisez est gérée par la stratégie et que votre application figure dans la liste autorisée de cette stratégie.

if (!ProtectionPolicyManager.IsIdentityManaged(identity)) return false;

API
ProtectionPolicyManager.IsIdentityManaged

Étape 2 : Créer un fichier et le protéger sur l’identité

FileProtectionManager.CreateProtectedAndOpenAsync crée un fichier protégé et conserve le handle de fichier ouvert pendant l’écriture.

StorageFolder storageFolder = ApplicationData.Current.LocalFolder;

ProtectedFileCreateResult protectedFileCreateResult =
    await FileProtectionManager.CreateProtectedAndOpenAsync(storageFolder,
        "sample.txt", identity, CreationCollisionOption.ReplaceExisting);

API
FileProtectionManager.CreateProtectedAndOpenAsync

Étape 3 : Écrire un flux ou une mémoire tampon dans le fichier

Cet exemple écrit un flux dans un fichier.

if (protectedFileCreateResult.ProtectionInfo.Status == FileProtectionStatus.Protected)
{
    IOutputStream outputStream =
        protectedFileCreateResult.Stream.GetOutputStreamAt(0);

    using (DataWriter writer = new DataWriter(outputStream))
    {
        writer.WriteString(enterpriseData);
        await writer.StoreAsync();
        await writer.FlushAsync();
    }

    outputStream.Dispose();
}
else if (protectedFileCreateResult.ProtectionInfo.Status == FileProtectionStatus.AccessSuspended)
{
    // Perform any special processing for the access suspended case.
}

API
ProtectedFileCreateResult.ProtectionInfo
FileProtectionStatus
ProtectedFileCreateResult.Stream

Protéger une partie d’un fichier

Dans la plupart des cas, il est plus propre de stocker les données d’entreprise et personnelles séparément, mais vous pouvez les stocker dans le même fichier si vous le souhaitez. Par exemple, Microsoft Outlook peut stocker des messages d’entreprise en même temps que des courriers personnels dans un seul fichier d’archivage.

Chiffrez les données d’entreprise, mais pas l’intégralité du fichier. De cette façon, les utilisateurs peuvent continuer à utiliser ce fichier même s’ils annulent l’inscription à partir de la gestion des appareils mobiles ou si leurs droits d’accès aux données d’entreprise sont révoqués. En outre, votre application doit suivre les données qu’elle chiffre afin qu’elle sache quelles données protéger lorsqu’elle lit le fichier en mémoire.

Étape 1 : Ajouter des données d’entreprise à un flux ou mémoire tampon chiffré

string enterpriseDataString = "<employees><employee><name>Bill</name><social>xxx-xxx-xxxx</social></employee></employees>";

var enterpriseData= Windows.Security.Cryptography.CryptographicBuffer.ConvertStringToBinary(
        enterpriseDataString, Windows.Security.Cryptography.BinaryStringEncoding.Utf8);

BufferProtectUnprotectResult result =
   await DataProtectionManager.ProtectAsync(enterpriseData, identity);

enterpriseData= result.Buffer;

API
DataProtectionManager.ProtectAsync
BufferProtectUnprotectResult.buffer

Étape 2 : Ajouter des données personnelles à un flux ou mémoire tampon non chiffré

string personalDataString = "<recipies><recipe><name>BillsCupCakes</name><cooktime>30</cooktime></recipe></recipies>";

var personalData = Windows.Security.Cryptography.CryptographicBuffer.ConvertStringToBinary(
    personalDataString, Windows.Security.Cryptography.BinaryStringEncoding.Utf8);

Étape 3 : Écrire à la fois des flux ou des mémoires tampons dans un fichier

StorageFolder storageFolder = ApplicationData.Current.LocalFolder;

StorageFile storageFile = await storageFolder.CreateFileAsync("data.xml",
    CreationCollisionOption.ReplaceExisting);

 // Write both buffers to the file and save the file.

var stream = await storageFile.OpenAsync(FileAccessMode.ReadWrite);

using (var outputStream = stream.GetOutputStreamAt(0))
{
    using (var dataWriter = new DataWriter(outputStream))
    {
        dataWriter.WriteBuffer(enterpriseData);
        dataWriter.WriteBuffer(personalData);

        await dataWriter.StoreAsync();
        await outputStream.FlushAsync();
    }
}

Étape 4 : Effectuer le suivi de l’emplacement de vos données d’entreprise dans le fichier

Il incombe à votre application de suivre les données contenues dans ce fichier appartenant à l’entreprise.

Vous pouvez stocker ces informations dans une propriété associée au fichier, dans une base de données ou dans un texte d’en-tête dans le fichier.

Cet exemple enregistre ces informations dans un fichier XML distinct.

StorageFile metaDataFile = await storageFolder.CreateFileAsync("metadata.xml",
   CreationCollisionOption.ReplaceExisting);

await Windows.Storage.FileIO.WriteTextAsync
    (metaDataFile, "<EnterpriseDataMarker start='0' end='" + enterpriseData.Length.ToString() +
    "'></EnterpriseDataMarker>");

Lire la partie protégée d’un fichier

Voici comment lire les données d’entreprise de ce fichier.

Étape 1 : Obtenir la position de vos données d’entreprise dans le fichier

Windows.Storage.StorageFolder storageFolder =
    Windows.Storage.ApplicationData.Current.LocalFolder;

 Windows.Storage.StorageFile metaDataFile =
   await storageFolder.GetFileAsync("metadata.xml");

string metaData = await Windows.Storage.FileIO.ReadTextAsync(metaDataFile);

XmlDocument doc = new XmlDocument();

doc.LoadXml(metaData);

uint startPosition =
    Convert.ToUInt16((doc.FirstChild.Attributes.GetNamedItem("start")).InnerText);

uint endPosition =
    Convert.ToUInt16((doc.FirstChild.Attributes.GetNamedItem("end")).InnerText);

Étape 2 : ouvrir le fichier de données et s’assurer qu’il n’est pas protégé

Windows.Storage.StorageFile dataFile =
    await storageFolder.GetFileAsync("data.xml");

FileProtectionInfo protectionInfo =
    await FileProtectionManager.GetProtectionInfoAsync(dataFile);

if (protectionInfo.Status == FileProtectionStatus.Protected)
    return false;

API
FileProtectionManager.GetProtectionInfoAsync
FileProtectionInfo
FileProtectionStatus

Étape 3 : Lire les données d’entreprise à partir du fichier

var stream = await dataFile.OpenAsync(Windows.Storage.FileAccessMode.ReadWrite);

stream.Seek(startPosition);

Windows.Storage.Streams.Buffer tempBuffer = new Windows.Storage.Streams.Buffer(50000);

IBuffer enterpriseData = await stream.ReadAsync(tempBuffer, endPosition, InputStreamOptions.None);

Étape 4 : Déchiffrer la mémoire tampon qui contient des données d’entreprise

DataProtectionInfo dataProtectionInfo =
   await DataProtectionManager.GetProtectionInfoAsync(enterpriseData);

if (dataProtectionInfo.Status == DataProtectionStatus.Protected)
{
    BufferProtectUnprotectResult result = await DataProtectionManager.UnprotectAsync(enterpriseData);
    enterpriseData = result.Buffer;
}
else if (dataProtectionInfo.Status == DataProtectionStatus.Revoked)
{
    // Code goes here to handle this situation. Perhaps, show UI
    // saying that the user's data has been revoked.
}

API
DataProtectionInfo
DataProtectionManager.GetProtectionInfoAsync

Protéger les données dans un dossier

Vous pouvez créer un dossier et le protéger. Ainsi, tous les éléments que vous ajoutez à ce dossier sont automatiquement protégés.

private async Task<bool> CreateANewFolderAndProtectItAsync(string folderName, string identity)
{
    if (!ProtectionPolicyManager.IsIdentityManaged(identity)) return false;

    StorageFolder storageFolder = ApplicationData.Current.LocalFolder;
    StorageFolder newStorageFolder =
        await storageFolder.CreateFolderAsync(folderName);

    FileProtectionInfo fileProtectionInfo =
        await FileProtectionManager.ProtectAsync(newStorageFolder, identity);

    if (fileProtectionInfo.Status != FileProtectionStatus.Protected)
    {
        // Protection failed.
        return false;
    }
    return true;
}

Assurez-vous que le dossier est vide avant de le protéger. Vous ne pouvez pas protéger un dossier qui contient déjà des éléments.

API
ProtectionPolicyManager.IsIdentityManaged
FileProtectionManager.ProtectAsync
FileProtectionInfo.Identity
FileProtectionInfo.Status

Protéger les données vers un point de terminaison réseau

Créez un contexte de thread protégé pour envoyer ces données à un point de terminaison d’entreprise.

Étape 1 : Obtenir l’identité du point de terminaison réseau

Windows.Networking.HostName hostName =
    new Windows.Networking.HostName(resourceURI.Host);

string identity = await ProtectionPolicyManager.
    GetPrimaryManagedIdentityForNetworkEndpointAsync(hostName);

API
ProtectionPolicyManager.GetPrimaryManagedIdentityForNetworkEndpointAsync

Étape 2 : Créer un contexte de thread protégé et envoyer des données au point de terminaison réseau

HttpClient client = null;

if (!string.IsNullOrEmpty(m_EnterpriseId))
{
    ProtectionPolicyManager.GetForCurrentView().Identity = identity;

    using (ThreadNetworkContext threadNetworkContext =
            ProtectionPolicyManager.CreateCurrentThreadNetworkContext(identity))
    {
        client = new HttpClient();
        HttpRequestMessage message = new HttpRequestMessage(HttpMethod.Put, resourceURI);
        message.Content = new HttpStreamContent(dataToWrite);

        HttpResponseMessage response = await client.SendRequestAsync(message);

        if (response.StatusCode == HttpStatusCode.Ok)
            return true;
        else
            return false;
    }
}
else
{
    return false;
}

API
ProtectionPolicyManager.GetForCurrentView
ProtectionPolicyManager.Identity
ProtectionPolicyManager.CreateCurrentThreadNetworkContext

Protéger les données que votre application partage par le biais d’un contrat de partage

Si vous souhaitez que les utilisateurs partagent du contenu à partir de votre application, vous devez implémenter un contrat de partage et gérer l’événement DataTransferManager.DataRequested .

Dans votre gestionnaire d’événements, définissez le contexte d’identité d’entreprise dans le package de données.

private void OnShareSourceOperation(object sender, RoutedEventArgs e)
{
    // Register the current page as a share source (or you could do this earlier in your app).
    DataTransferManager.GetForCurrentView().DataRequested += OnDataRequested;
    DataTransferManager.ShowShareUI();
}

private void OnDataRequested(DataTransferManager sender, DataRequestedEventArgs args)
{
    if (!string.IsNullOrEmpty(this.shareSourceContent))
    {
        var protectionPolicyManager = ProtectionPolicyManager.GetForCurrentView();
        DataPackage requestData = args.Request.Data;
        requestData.Properties.Title = this.shareSourceTitle;
        requestData.Properties.EnterpriseId = protectionPolicyManager.Identity;
        requestData.SetText(this.shareSourceContent);
    }
}

API
ProtectionPolicyManager.GetForCurrentView
ProtectionPolicyManager.Identity

Protéger les fichiers que vous copiez vers un autre emplacement

private async void CopyProtectionFromOneFileToAnother
    (StorageFile sourceStorageFile, StorageFile targetStorageFile)
{
    bool copyResult = await
        FileProtectionManager.CopyProtectionAsync(sourceStorageFile, targetStorageFile);

    if (!copyResult)
    {
        // Copying failed. To diagnose, you could check the file's status.
        // (call FileProtectionManager.GetProtectionInfoAsync and
        // check FileProtectionInfo.Status).
    }
}

API
FileProtectionManager.CopyProtectionAsync

Protéger les données d’entreprise lorsque l’écran de l’appareil est verrouillé

Supprimez toutes les données sensibles en mémoire lorsque l’appareil est verrouillé. Lorsque l’utilisateur déverrouille l’appareil, votre application peut ajouter ces données en toute sécurité.

Gérez l’événement ProtectionPolicyManager.ProtectedAccessSuspending afin que votre application sache quand l’écran est verrouillé. Cet événement est déclenché uniquement si l’administrateur configure une protection sécurisée des données sous la stratégie de verrouillage. Windows supprime temporairement les clés de protection des données configurées sur l’appareil. Windows supprime ces clés pour s’assurer qu’il n’existe aucun accès non autorisé aux données chiffrées pendant que l’appareil est verrouillé et éventuellement pas en possession de son propriétaire.

Gérez l’événement ProtectionPolicyManager.ProtectedAccessResumed afin que votre application sache quand l’écran est déverrouillé. Cet événement est déclenché, que l’administrateur configure une protection sécurisée des données sous la stratégie de verrouillage.

Supprimer des données sensibles en mémoire lorsque l’écran est verrouillé

Protégez les données sensibles et fermez les flux de fichiers ouverts par votre application sur des fichiers protégés pour vous assurer que le système ne met pas en cache les données sensibles en mémoire.

Cet exemple montre comment enregistrer le contenu d’un bloc de texte dans une mémoire tampon chiffrée et supprimer le contenu de ce bloc de texte.

private async void ProtectionPolicyManager_ProtectedAccessSuspending(object sender, ProtectedAccessSuspendingEventArgs e)
{
    Deferral deferral = e.GetDeferral();

    if (ProtectionPolicyManager.GetForCurrentView().Identity != String.Empty)
    {
        IBuffer documentBodyBuffer = CryptographicBuffer.ConvertStringToBinary
           (documentTextBlock.Text, BinaryStringEncoding.Utf8);

        BufferProtectUnprotectResult result = await DataProtectionManager.ProtectAsync
            (documentBodyBuffer, ProtectionPolicyManager.GetForCurrentView().Identity);

        if (result.ProtectionInfo.Status == DataProtectionStatus.Protected)
        {
            this.protectedDocumentBuffer = result.Buffer;
            documentTextBlock.Text = null;
        }
    }

    // Close any open streams that you are actively working with
    // to make sure that we have no unprotected content in memory.

    // Optionally, code goes here to use e.Deadline to determine whether we have more
    // than 15 seconds left before the suspension deadline. If we do then process any
    // messages queued up for sending while we are still able to access them.

    deferral.Complete();
}

API
ProtectionPolicyManager.ProtectedAccessSuspending
ProtectionPolicyManager.GetForCurrentView
ProtectionPolicyManager.Identity
DataProtectionManager.ProtectAsync
BufferProtectUnprotectResult.buffer
ProtectedAccessSuspendingEventArgs.GetDeferral
Report.Complete

Ajouter des données sensibles lorsque l’appareil est déverrouillé

ProtectionPolicyManager.ProtectedAccess Reprise est déclenché lorsque l’appareil est déverrouillé et que les clés sont à nouveau disponibles sur l’appareil.

ProtectedAccessResumedEventArgs.Identityes est une collection vide si l’administrateur n’a pas configuré de protection sécurisée des données sous la stratégie de verrouillage.

Cet exemple effectue l’inverse de l’exemple précédent. Il déchiffre la mémoire tampon, ajoute des informations de cette mémoire tampon à la zone de texte, puis supprime la mémoire tampon.

private async void ProtectionPolicyManager_ProtectedAccessResumed(object sender, ProtectedAccessResumedEventArgs e)
{
    if (ProtectionPolicyManager.GetForCurrentView().Identity != String.Empty)
    {
        BufferProtectUnprotectResult result = await DataProtectionManager.UnprotectAsync
            (this.protectedDocumentBuffer);

        if (result.ProtectionInfo.Status == DataProtectionStatus.Unprotected)
        {
            // Restore the unprotected version.
            documentTextBlock.Text = CryptographicBuffer.ConvertBinaryToString
                (BinaryStringEncoding.Utf8, result.Buffer);
            this.protectedDocumentBuffer = null;
        }
    }

}

API
ProtectionPolicyManager.ProtectedAccess Reprise
ProtectionPolicyManager.GetForCurrentView
ProtectionPolicyManager.Identity
DataProtectionManager.UnprotectAsync
BufferProtectUnprotectResult.Status

Gérer les données d’entreprise lorsque le contenu protégé est révoqué

Si vous souhaitez que votre application soit avertie lorsque l’appareil n’est pas inscrit à partir de GPM ou lorsque l’administrateur de stratégie révoque explicitement l’accès aux données d’entreprise, gérez l’événement ProtectionPolicyManager_ProtectedContentRevoked .

Cet exemple détermine si les données d’une boîte aux lettres d’entreprise pour une application de messagerie ont été révoquées.

private string mailIdentity = "contoso.com";

void MailAppSetup()
{
    ProtectionPolicyManager.ProtectedContentRevoked += ProtectionPolicyManager_ProtectedContentRevoked;
    // Code goes here to set up mailbox for 'mailIdentity'.
}

private void ProtectionPolicyManager_ProtectedContentRevoked(object sender, ProtectedContentRevokedEventArgs e)
{
    if (!new System.Collections.Generic.List<string>(e.Identities).Contains
        (this.mailIdentity))
    {
        // This event is not for our identity.
        return;
    }

    // Code goes here to delete any metadata associated with 'mailIdentity'.
}

API
ProtectionPolicyManager_ProtectedContentRevoked

Exemple windows Protection des données (WIP)