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
Sur votre ordinateur de développement, ouvrez votre projet.
Ajoutez une référence aux extensions de bureau et mobiles pour plateforme Windows universelle (UWP).
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.
Ajoutez cet espace de noms à votre fichier manifeste de package :
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
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 des données à partir d’un fichier
- Lire des données à partir d’un point de terminaison réseau
- Lire les données du Presse-papiers
- Lire des données à partir d’un contrat Share
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;
}
}
}
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
- Protéger les données dans un fichier en tant que processus en arrière-plan
- Protéger une partie d’un fichier
- Lire la partie protégée d’un fichier
- Protéger les données dans un dossier
- Protéger les données vers un point de terminaison réseau
- Protéger les données que votre application partage par le biais d’un contrat de partage
- Protéger les fichiers que vous copiez vers un autre emplacement
- Protéger les données d’entreprise lorsque l’écran de l’appareil est verrouillé
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();
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;
É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);
É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);
}
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;
É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);
É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).
}
}
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'.
}