Sécurité

Les fonctionnalités présentées dans ce guide décrivent les fonctionnalités de gestion de la sécurité que vous pouvez implémenter dans votre application de contrôle des règles relatives aux appareils (DPC). Ce document contient des exemples de code. Vous pouvez également utiliser l'application Test DPC comme source d'exemple de code pour les fonctionnalités d'entreprise d'Android.

Une application DPC peut s'exécuter en mode propriétaire de profil sur des appareils personnels ou en mode propriétaire de l'appareil sur des appareils entièrement gérés. Ce tableau indique les fonctionnalités disponibles lorsque le DPC s'exécute en mode propriétaire de profil ou propriétaire de l'appareil:

Fonctionnalité Propriétaire du profil Propriétaire de l'appareil
Désactiver l'accès aux applications
Bloquer les applications provenant de sources inconnues
Restreindre des comptes sur Google Play
Activer la protection contre le rétablissement de la configuration d'usine pour les entreprises
Surveiller les journaux de processus d'entreprise et les rapports de bug distants
Accorder et supprimer l'accès à un certificat client
Réinitialisation du code secret sécurisé
Défi de sécurité du profil professionnel

Désactiver l'accès aux applications

Pour les organisations qui souhaitent empêcher les employés de jouer à des jeux ou de regarder YouTube sur leur appareil Android à certaines heures de la journée ou certains jours de la semaine, un DPC peut désactiver temporairement l'accès aux applications.

Pour désactiver l'accès aux applications, un DPC exécuté en mode propriétaire de l'appareil ou propriétaire de profil configure setPackagesSuspended(). L'application sélectionnée agit ensuite comme si elle était désactivée (le lanceur d'applications Google grise l'application). Lorsqu'un utilisateur appuie sur l'application, une boîte de dialogue système lui indique que l'application est suspendue.

Lorsqu'une application est suspendue, elle ne peut pas démarrer d'activités, et les notifications au package sont supprimées. Les packages suspendus n'apparaissent pas dans l'écran d'aperçu. Ils ne peuvent pas afficher de boîtes de dialogue (y compris des toasts et des snackbars), ni lire de contenu audio ni vibrer sur l'appareil.

Les lanceurs d'applications peuvent savoir si une application est suspendue en appelant la méthode isPackageSuspended(). Pour savoir comment configurer la suspension d'application, consultez setPackagesSuspended.

Bloquer des applications provenant de sources inconnues

Les applications qui ne sont pas installées à partir de Google Play (ou d'une autre plate-forme de téléchargement d'applications de confiance) sont appelées applications de sources inconnues. Les appareils et les données peuvent présenter un risque accru lorsque les utilisateurs installent ces applications.

Pour empêcher quelqu'un d'installer des applications provenant de sources inconnues, les composants administrateur des appareils entièrement gérés et des profils professionnels peuvent ajouter la restriction utilisateur DISALLOW_INSTALL_UNKNOWN_SOURCES.

Restriction au niveau de l'appareil dans le profil professionnel

Lorsque l'administrateur d'un profil professionnel ajoute DISALLOW_INSTALL_UNKNOWN_SOURCES, la restriction ne s'applique qu'au profil professionnel. Toutefois, l'administrateur d'un profil professionnel peut placer une restriction au niveau de l'appareil en définissant une configuration gérée pour Google Play. La restriction au niveau de l'appareil est disponible sur Android 8.0 (ou version ultérieure) lorsque l'application Google Play installée est à la version 80812500 ou ultérieure.

Pour limiter l'installation d'applications à Google Play, procédez comme suit:

  1. Définissez un groupe de configuration gérée pour le package Google Play com.android.vending.
  2. Dans le bundle, indiquez une valeur booléenne pour la clé verify_apps:device_wide_unknown_source_block.
  3. Ajoutez la restriction utilisateur ENSURE_VERIFY_APPS.

L'exemple suivant montre comment vérifier que Google Play accepte ce paramètre et définir la valeur sur true:

Kotlin

internal val DEVICE_WIDE_UNKNOWN_SOURCES = "verify_apps:device_wide_unknown_source_block"
internal val GOOGLE_PLAY_APK = "com.android.vending"

// ...

// Add the setting to Google Play's existing managed config. Supported in
// Google Play version 80812500 or higher--older versions ignore unsupported
// settings.
val dpm = context.getSystemService(Context.DEVICE_POLICY_SERVICE) as DevicePolicyManager
var existingConfig = dpm.getApplicationRestrictions(adminName, GOOGLE_PLAY_APK)
val newConfig = Bundle(existingConfig)
newConfig.putBoolean(DEVICE_WIDE_UNKNOWN_SOURCES, true)
dpm.setApplicationRestrictions(adminName, GOOGLE_PLAY_APK, newConfig)

// Make sure that Google Play Protect verifies apps.
dpm.addUserRestriction(adminName, UserManager.ENSURE_VERIFY_APPS)
dpm.addUserRestriction(adminName, UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES)

Java

static final String DEVICE_WIDE_UNKNOWN_SOURCES =
    "verify_apps:device_wide_unknown_source_block";
static final String GOOGLE_PLAY_APK = "com.android.vending";

// ...


// Add the setting to Google Play's existing managed config. Supported in
// Google Play version 80812500 or higher--older versions ignore unsupported
// settings.
DevicePolicyManager dpm =
    (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
Bundle existingConfig =
    dpm.getApplicationRestrictions(adminName, GOOGLE_PLAY_APK);
Bundle newConfig = new Bundle(existingConfig);
newConfig.putBoolean(DEVICE_WIDE_UNKNOWN_SOURCES, true);
dpm.setApplicationRestrictions(adminName, GOOGLE_PLAY_APK, newConfig);

// Make sure that Google Play Protect verifies apps.
dpm.addUserRestriction(adminName, UserManager.ENSURE_VERIFY_APPS);
dpm.addUserRestriction(adminName, UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES);

L'interface utilisateur reste active dans les paramètres système, mais le système bloque l'installation de l'application. Cette restriction affecte les futures installations (les applications précédemment installées restent sur l'appareil). Les utilisateurs d'appareils peuvent continuer à installer des applications dans leur profil personnel à l'aide d'Android Debug Bridge (adb).

Pour en savoir plus sur les sources inconnues, consultez la section Autres options de distribution.

Limiter les comptes sur Google Play

Il arrive parfois qu'une organisation souhaite autoriser les utilisateurs à ajouter des comptes Google personnels (pour lire les e-mails dans Gmail, par exemple), mais ne souhaite pas que ce compte personnel installe des applications. Votre DPC peut définir une liste de comptes que les utilisateurs peuvent utiliser dans Google Play.

Les composants d'administration d'appareils entièrement gérés ou de profils professionnels peuvent restreindre les comptes en définissant une configuration gérée pour Google Play. La restriction de compte est disponible lorsque la version 80970100 ou ultérieure de l'application Google Play est installée.

Pour limiter les comptes dans Google Play, procédez comme suit:

  1. Définissez un groupe de configuration gérée pour le package Google Play com.android.vending.
  2. Dans le groupe, placez les adresses e-mail séparées par une virgule en tant que valeur de chaîne pour la clé allowed_accounts.

L'exemple suivant montre comment limiter des comptes:

Kotlin

internal val ALLOWED_ACCOUNTS = "allowed_accounts"
internal val GOOGLE_PLAY_APK = "com.android.vending"

// ...

// Limit Google Play to one work and one personal account. Use
// a comma-separated list of account email addresses (usernames).
val googleAccounts = "ali@gmail.com,ali.connors@example.com"

// Supported in Google Play version 80970100 or higher.
val existingConfig = dpm.getApplicationRestrictions(adminName, GOOGLE_PLAY_APK)
val newConfig = Bundle(existingConfig)
newConfig.putString(ALLOWED_ACCOUNTS, googleAccounts)
dpm.setApplicationRestrictions(adminName, GOOGLE_PLAY_APK, newConfig)

Java

static final String ALLOWED_ACCOUNTS = "allowed_accounts";
static final String GOOGLE_PLAY_APK = "com.android.vending";

// ...


// Limit Google Play to one work and one personal account. Use
// a comma-separated list of account email addresses (usernames).
String googleAccounts = "ali@gmail.com,ali.connors@example.com";

// Supported in Google Play version 80970100 or higher.
Bundle existingConfig =
    dpm.getApplicationRestrictions(adminName, GOOGLE_PLAY_APK);
Bundle newConfig = new Bundle(existingConfig);
newConfig.putString(ALLOWED_ACCOUNTS, googleAccounts);
dpm.setApplicationRestrictions(adminName, GOOGLE_PLAY_APK, newConfig);

Pour limiter Google Play au seul compte professionnel, définissez allowed_accounts sur le seul compte géré dès que votre DPC connaît l'adresse e-mail du compte. Une chaîne vide empêche les utilisateurs d'utiliser un compte dans Google Play.

Activer la protection après rétablissement de la configuration d'usine de l'entreprise

Grâce à la protection des entreprises lors du rétablissement de la configuration d'usine, les organisations peuvent spécifier les comptes Google autorisés à provisionner un appareil dont la configuration d'usine a été rétablie.

La protection grand public contre le rétablissement de la configuration d'usine est conçue pour prévenir le vol d'appareils. Avant de permettre à quiconque de provisionner l'appareil après une réinitialisation non autorisée (par exemple, en utilisant un EMM), l'assistant de configuration demande à l'utilisateur de s'authentifier auprès de tous les comptes Google qui se trouvaient auparavant sur le profil personnel de l'appareil.

Dans un environnement d'entreprise, le rétablissement de la configuration d'usine est un outil important pour gérer les appareils d'un employé lorsqu'il quitte l'organisation. Toutefois, si l'organisation ne connaît pas les identifiants du compte d'un employé, la protection contre la réinitialisation aux paramètres d'usine peut empêcher l'organisation de délivrer un appareil à un autre employé.

Contrôler le provisionnement après un rétablissement de la configuration d'usine

En mode propriétaire de l'appareil, votre DPC peut utiliser setFactoryResetProtectionPolicy() pour contrôler les comptes autorisés à provisionner un appareil après une réinitialisation. Si cette configuration est définie sur null ou sur une liste vide, les comptes autorisés à provisionner un appareil après une réinitialisation sont les comptes figurant sur le profil personnel de l'appareil.

Un DPC peut configurer ces comptes tout au long de la durée de vie d'un appareil entièrement géré.

  1. L'administrateur informatique peut utiliser la méthode people.get de l'API People avec la valeur spéciale me. Cette opération récupère le userId pour le compte connecté. Le userID est renvoyé dans la clé resourceName au format people/[userId] sous la forme d'une chaîne d'entiers. Il est possible que les comptes nouvellement créés ne soient pas disponibles pour rétablir la configuration d'usine pendant 72 heures.
  2. Vous pouvez également autoriser un ou plusieurs administrateurs informatiques à déverrouiller l'appareil après une réinitialisation. Demandez à chacun de ces administrateurs informatiques de se connecter à son compte Google, de suivre également l'étape 1 et de partager son userId avec vous, afin que vous puissiez ajouter ces userIds à la liste à l'étape suivante.
  3. L'outil DPC définit une restriction d'application appropriée à l'aide de setFactoryResetProtectionPolicy() pour définir la liste des userId pouvant provisionner un appareil dont la configuration d'usine a été rétablie.
  4. L'outil DPC active les comptes qui peuvent provisionner des appareils après une réinitialisation en envoyant l'com.google.android.gms.auth.FRP_CONFIG_CHANGED de diffusion en tant qu'intent explicite pour éviter qu'ils ne soient supprimés en raison de restrictions en arrière-plan.

Kotlin

const val ACTION_FRP_CONFIG_CHANGED =
    "com.google.android.gms.auth.FRP_CONFIG_CHANGED"
const val GMSCORE_PACKAGE = "com.google.android.gms"

// ...

// List of userId that can provision a factory reset device.
// You can use the value returned calling people/me endpoint.
val accountIds = listOf("000000000000000000000")

dpm.setFactoryResetProtectionPolicy(
    adminName,
    FactoryResetProtectionPolicy.Builder()
        .setFactoryResetProtectionAccounts(accountIds)
        .setFactoryResetProtectionEnabled(true)
        .build()
)

val frpChangedIntent = Intent(ACTION_FRP_CONFIG_CHANGED)

frpChangedIntent.setPackage(GMSCORE_PACKAGE)
context.sendBroadcast(frpChangedIntent)

Java

static final String ACTION_FRP_CONFIG_CHANGED =
    "com.google.android.gms.auth.FRP_CONFIG_CHANGED";
static final String GMSCORE_PACKAGE = "com.google.android.gms";

// ...

// List of userId that can provision a factory reset device.
// You can use the value returned calling people/me endpoint.
List<String> accountIds = new ArrayList<String>();
accountIds.add("000000000000000000000");

dpm.setFactoryResetProtectionPolicy(
    adminName,
    new FactoryResetProtectionPolicy.Builder()
        .setFactoryResetProtectionAccounts(accountIds)
        .setFactoryResetProtectionEnabled(true)
        .build());

Intent frpChangedIntent = new Intent(ACTION_FRP_CONFIG_CHANGED);

frpChangedIntent.setPackage(GMSCORE_PACKAGE);
context.sendBroadcast(frpChangedIntent);

Legacy

Pour les appareils qui ne peuvent pas utiliser setFactoryResetProtectionPolicy(), introduit avec le niveau d'API 30, votre DPC peut utiliser setApplicationRestrictions pour ajouter les comptes sélectionnés à la configuration gérée factoryResetProtectionAdmin pour le package com.google.android.gms.

Kotlin

const val GOOGLE_PLAY_APK = "com.android.vending"
const val FACTORY_RESET_PROTECTION_ADMIN = "factoryResetProtectionAdmin"
const val DISABLE_FACTORY_RESET_PROTECTION_ADMIN = "disableFactoryResetProtectionAdmin"
const val GMSCORE_PACKAGE = "com.google.android.gms"

// ...

val existingConfig = dpm.getApplicationRestrictions(adminName, GOOGLE_PLAY_APK)
val newConfig = Bundle(existingConfig)
newConfig.putBoolean(DISABLE_FACTORY_RESET_PROTECTION_ADMIN, false)
newConfig.putString(FACTORY_RESET_PROTECTION_ADMIN, googleAccounts)
dpm.setApplicationRestrictions(adminName, GOOGLE_PLAY_APK, newConfig)

val frpChangedIntent = Intent(ACTION_FRP_CONFIG_CHANGED)

frpChangedIntent.setPackage(GMSCORE_PACKAGE)
context.sendBroadcast(frpChangedIntent)

Java

static final String GOOGLE_PLAY_APK = "com.android.vending";
static final String FACTORY_RESET_PROTECTION_ADMIN = "factoryResetProtectionAdmin";
static final String DISABLE_FACTORY_RESET_PROTECTION_ADMIN = "disableFactoryResetProtectionAdmin";
static final String GMSCORE_PACKAGE = "com.google.android.gms";

// ...

Bundle existingConfig =
        dpm.getApplicationRestrictions(adminName, GOOGLE_PLAY_APK);
Bundle newConfig = new Bundle(existingConfig);
newConfig.putBoolean(DISABLE_FACTORY_RESET_PROTECTION_ADMIN, false);
newConfig.putStringArray(FACTORY_RESET_PROTECTION_ADMIN,
        accountIds.toArray(new String[accountIds.size()]));
dpm.setApplicationRestrictions(adminName, GOOGLE_PLAY_APK, newConfig);

Intent frpChangedIntent = new Intent(ACTION_FRP_CONFIG_CHANGED);

frpChangedIntent.setPackage(GMSCORE_PACKAGE);
context.sendBroadcast(frpChangedIntent);

Désactiver la protection contre le rétablissement de la configuration d'usine de l'entreprise

Pour désactiver la protection contre le rétablissement de la configuration d'usine, votre DPC peut utiliser setFactoryResetProtectionPolicy() en transmettant la valeur null.

Kotlin

const val ACTION_FRP_CONFIG_CHANGED =
    "com.google.android.gms.auth.FRP_CONFIG_CHANGED"
const val GMSCORE_PACKAGE = "com.google.android.gms"

// ...

dpm.setFactoryResetProtectionPolicy(adminName, null)

val frpChangedIntent = Intent(ACTION_FRP_CONFIG_CHANGED)

frpChangedIntent.setPackage(GMSCORE_PACKAGE)
context.sendBroadcast(frpChangedIntent)

Java

static final String ACTION_FRP_CONFIG_CHANGED =
    "com.google.android.gms.auth.FRP_CONFIG_CHANGED";
static final String GMSCORE_PACKAGE = "com.google.android.gms";

// ...

dpm.setFactoryResetProtectionPolicy(adminName, null);

Intent frpChangedIntent = new Intent(ACTION_FRP_CONFIG_CHANGED);

frpChangedIntent.setPackage(GMSCORE_PACKAGE);
context.sendBroadcast(frpChangedIntent);

Legacy

Pour les appareils qui ne peuvent pas utiliser setFactoryResetProtectionPolicy() (introduit avec le niveau d'API 30), votre DPC peut utiliser setApplicationRestrictions pour définir une clé-valeur true dans la configuration gérée disableFactoryResetProtectionAdmin du package com.google.android.gms.

Kotlin

const val GOOGLE_PLAY_APK = "com.android.vending"
const val FACTORY_RESET_PROTECTION_ADMIN = "factoryResetProtectionAdmin"
const val DISABLE_FACTORY_RESET_PROTECTION_ADMIN = "disableFactoryResetProtectionAdmin"
const val GMSCORE_PACKAGE = "com.google.android.gms"

// ...

val existingConfig = dpm.getApplicationRestrictions(adminName, GOOGLE_PLAY_APK)
val newConfig = Bundle(existingConfig)
newConfig.putBoolean(DISABLE_FACTORY_RESET_PROTECTION_ADMIN, true)

dpm.setApplicationRestrictions(
    adminName, GOOGLE_PLAY_SERVICES_PACKAGE, restrictions
)

val frpChangedIntent = Intent(ACTION_FRP_CONFIG_CHANGED)

frpChangedIntent.setPackage(GMSCORE_PACKAGE)
context.sendBroadcast(frpChangedIntent)

Java

static final String GOOGLE_PLAY_APK = "com.android.vending";
static final String FACTORY_RESET_PROTECTION_ADMIN = "factoryResetProtectionAdmin";
static final String DISABLE_FACTORY_RESET_PROTECTION_ADMIN = "disableFactoryResetProtectionAdmin";
static final String GMSCORE_PACKAGE = "com.google.android.gms";

// ...

Bundle existingConfig =
        dpm.getApplicationRestrictions(adminName, GOOGLE_PLAY_APK);
Bundle newConfig = new Bundle(existingConfig);
newConfig.putBoolean(DISABLE_FACTORY_RESET_PROTECTION_ADMIN, true);

dpm.setApplicationRestrictions(
    adminName, GOOGLE_PLAY_SERVICES_PACKAGE, restrictions);

Intent frpChangedIntent = new Intent(ACTION_FRP_CONFIG_CHANGED);

frpChangedIntent.setPackage(GMSCORE_PACKAGE);
context.sendBroadcast(frpChangedIntent);

Surveiller les journaux de processus d'entreprise et les rapports de bug distants

Dans votre console EMM, un administrateur peut surveiller des appareils entièrement gérés à l'aide des journaux de processus d'entreprise et des rapports de bug distants.

Enregistrer l'activité des appareils de l'entreprise

Un DPC exécuté en mode propriétaire de l'appareil peut identifier une activité suspecte en suivant à distance l'activité de l'appareil, y compris les lancements d'applications, l'activité Android Debug Bridge (adb) et les déverrouillages d'écran. Les journaux de processus ne nécessitent pas le consentement de l'utilisateur.

Pour activer ou désactiver la journalisation, un DPC appelle setSecurityLoggingEnabled().

Lorsqu'un nouveau lot de journaux est disponible, DeviceAdminReceiver reçoit le rappel onSecurityLogsAvailable(). Pour récupérer les journaux (après avoir reçu le rappel), un DPC appelle retrieveSecurityLogs().

Les DPC peuvent également appeler retrievePreRebootSecurityLogs() pour récupérer les journaux de sécurité générés lors du cycle de redémarrage précédent. Il s'agit de l'intervalle entre le dernier redémarrage de l'appareil et le précédent. Les appareils qui ne sont pas compatibles avec retrieveSecurityLogs() renvoient null. Si votre application récupère des journaux à l'aide de retrievePreRebootSecurityLogs() et de retrieveSecurityLogs(), vous devez rechercher les entrées en double.
Remarque: Cette fonctionnalité n'enregistre l'activité que sur les appareils entièrement gérés sur lesquels un seul utilisateur ou des utilisateurs affiliés sont configurés. Cette fonctionnalité ne fonctionne pas sur les appareils personnels, car elle enregistre l'activité à l'échelle de l'appareil.

Ce paramètre peut être utile dans l'audit post-événement de sécurité, car il enregistre les types d'actions suivants:

  • Chaque fois que l'application est entièrement démarrée. Cela peut vous aider à identifier s’il y a un logiciel malveillant qui commence par une application compromise.
  • Tentatives de déverrouillage infructueuses sur un appareil. Cela permet de déterminer si plusieurs tentatives de déverrouillage ont échoué sur une courte période.
  • Commandes adb potentiellement dangereuses lorsqu'un utilisateur connecte l'appareil à un ordinateur à l'aide d'un câble USB.

Pour savoir comment lire les journaux, consultez SecurityLog.

Lors du développement et des tests, vous pouvez forcer le système à mettre tous les journaux de sécurité existants à la disposition de votre DPC. Vous n'avez pas besoin d'attendre un lot complet. Sous Android 9.0 (niveau d'API 28) ou version ultérieure, exécutez la commande Android Debug Bridge (adb) suivante dans votre terminal:

adb shell dpm force-security-logs

Le système limite la fréquence d'utilisation de l'outil et signale tout ralentissement intentionnel dans la sortie du terminal. Si des journaux sont disponibles, votre DPC reçoit le rappel onSecurityLogsAvailable().

Demander un rapport de bug à distance

Un DPC exécuté en mode propriétaire de l'appareil peut demander à distance des rapports de bug pour les appareils d'utilisateurs n'ayant qu'un seul utilisateur ou des utilisateurs affiliés. Le rapport de bug capture l'activité de l'appareil au moment exact où il est demandé, mais peut également inclure l'activité des dernières heures, en fonction de la fréquence d'actualisation du tampon Logcat.

Pour demander à distance des rapports de bug, l'outil DPC appelle requestBugreport():

Accorder et supprimer l'accès à un certificat client

Si un DPC exécuté en mode propriétaire de profil ou propriétaire d'appareil autorise une application tierce à gérer les certificats, l'application peut s'accorder l'accès aux certificats qu'elle installe sans l'intervention d'un utilisateur. Pour installer un certificat auquel toutes les applications d'un profil peuvent accéder, utilisez installKeyPair().

Pour connaître les paramètres à configurer, consultez installKeyPair(). Cette fonctionnalité fonctionne conjointement avec l'API existante pour la gestion des certificats.

Scénario de déploiement

Sans la méthode installKeyPair():

  • Les utilisateurs doivent appuyer sur le nom du certificat, puis sur Autoriser chaque fois qu'ils souhaitent accorder l'accès à un certificat.
  • Les utilisateurs voient une invite lors de l'installation d'un certificat et doivent nommer le certificat.

Avec la méthode installKeyPair():

  • Les utilisateurs n'ont pas besoin d'appuyer sur Autoriser chaque fois qu'ils souhaitent accorder l'accès à un certificat.
  • Les utilisateurs ne peuvent pas renommer les certificats.
  • Les administrateurs disposent d'un contrôle accru, car ils peuvent bloquer les certificats des applications qui ne devraient pas avoir accès à des certificats spécifiques.

Supprimer un certificat client

Après avoir accordé l'accès à un certificat client, appelez removeKeyPair() pour supprimer à distance les certificats clients installés via installKeyPair().

Un DPC exécuté en mode propriétaire de l'appareil ou en mode propriétaire de profil, ou un programme d'installation de certificats délégués peut appeler removeKeyPair(). Cela supprime une paire certificat/clé privée installée sous un alias de clé privée donné.

Scénario de déploiement

Utilisez cette fonctionnalité si une entreprise migre vers un type de certificat client plus sécurisé. Si un administrateur déploie un nouveau certificat et que sa distribution prend beaucoup de temps, il peut révoquer les certificats obsolètes une fois la migration terminée.

Réinitialisation du code secret sécurisé

Votre DPC peut réinitialiser le mot de passe d'un utilisateur en autorisant la modification avec un jeton sécurisé préenregistré. Les propriétaires d'appareils et de profils peuvent appeler des API sécurisées de réinitialisation de code secret pour modifier respectivement le mot de passe des appareils et des profils professionnels. La réinitialisation du code secret sécurisé remplace resetPassword() par les améliorations suivantes:

Vous devez réinitialiser le code secret sécurisé si votre build DPC cible Android 8.0 (niveau d'API 26) ou une version ultérieure. L'appel de resetPassword() génère une erreur SecurityException dans les DPC ciblant Android 8.0 ou une version ultérieure. Vous devrez peut-être mettre à jour votre DPC.

Définir et activer un jeton

Votre DPC doit définir et activer un jeton avant de réinitialiser un mot de passe. Étant donné que votre DPC peut ne pas être en mesure d'utiliser le jeton immédiatement, vous devez le définir à l'avance lorsqu'un administrateur informatique pourrait avoir besoin de l'utiliser.

Un jeton de réinitialisation de mot de passe est une valeur aléatoire et cryptographiquement forte qui doit durer au moins 32 octets. Créez un jeton pour chaque appareil et profil. Ne réutilisez pas et ne partagez pas les jetons générés.

Nous vous recommandons de stocker des jetons, c'est-à-dire les moyens de déchiffrer un jeton chiffré, sur un serveur. Si vous stockez des jetons localement dans un espace de stockage chiffré par identifiants, votre DPC ne peut pas réinitialiser le mot de passe tant que l'utilisateur n'a pas déverrouillé l'appareil ou le profil. Si vous stockez les jetons localement dans le stockage chiffré de l'appareil, qui est compromis, un pirate informatique peut les utiliser pour accéder à un profil professionnel ou à un utilisateur principal.

Vous pouvez générer un nouveau jeton dans votre DPC ou récupérer un jeton sur un serveur. L'exemple ci-dessous montre un DPC qui génère lui-même un jeton et le signale à un serveur:

Kotlin

val token = ByteArray(32)

// Generate a new token
val random = SecureRandom()
random.nextBytes(token)

// Set the token to use at a later date
val success: Boolean
success = dpm.setResetPasswordToken(DeviceAdminReceiver.getComponentName(context), token)

// Activate the token and update success variable...

// Store the token on a server
if (success) {
 sendTokenToServer(token)
}

Java

byte token[] = new byte[32]; // Minimum size token accepted

// Generate a new token
SecureRandom random = new SecureRandom();
random.nextBytes(token);

// Set the token to use at a later date
boolean success;
success = dpm.setResetPasswordToken(DeviceAdminReceiver.getComponentName(getContext()), token);

// Activate the token and update success variable ...

// Store the token on a server
if (success) {
 sendTokenToServer(token);
}

Dans la plupart des cas, votre DPC doit activer un jeton après l'avoir défini. Toutefois, lorsque l'utilisateur ne possède pas de mot de passe d'écran de verrouillage, le système active immédiatement un jeton. Pour activer un jeton, demandez à l'utilisateur de confirmer ses identifiants. Votre DPC peut appeler la méthode KeyguardManager createConfirmDeviceCredentialIntent() pour obtenir un Intent qui lance la confirmation. Dans l'interface utilisateur, expliquez à l'utilisateur de l'appareil pourquoi vous lui demandez de s'authentifier. L'extrait ci-dessous montre comment activer un jeton dans votre DPC:

Kotlin

// In your DPC, you'll need to localize the user prompt
val ACTIVATE_TOKEN_PROMPT = "Use your credentials to enable remote password reset"
val ACTIVATE_TOKEN_REQUEST = 1

// Create or fetch a token and set it in setResetPasswordToken() ...
val keyguardManager = context.getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager
val confirmIntent = keyguardManager.createConfirmDeviceCredentialIntent(null, ACTIVATE_TOKEN_PROMPT)

if (confirmIntent != null) {
 startActivityForResult(confirmIntent, ACTIVATE_TOKEN_REQUEST)
 // Check your onActivityResult() callback for RESULT_OK
} else {
 // Null means the user doesn't have a lock screen so the token is already active.
 // Call isResetPasswordTokenActive() if you need to confirm
}

Java

// In your DPC, you'll need to localize the user prompt
static final String ACTIVATE_TOKEN_PROMPT =
 "Use your credentials to enable remote password reset";
static final int ACTIVATE_TOKEN_REQUEST = 1;

// Create or fetch a token and set it in setResetPasswordToken() ...

KeyguardManager keyguardManager = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
Intent confirmIntent = keyguardManager.createConfirmDeviceCredentialIntent(
  null, ACTIVATE_TOKEN_PROMPT);

if (confirmIntent != null) {
 startActivityForResult(confirmIntent, ACTIVATE_TOKEN_REQUEST);
 // Check your onActivityResult() callback for RESULT_OK
} else {
 // Null means the user doesn't have a lock screen so the token is already active.
 // Call isResetPasswordTokenActive() if you need to confirm
}

Vous devez activer un jeton défini par votre DPC avant que l'appareil redémarre. Android stocke un jeton désactivé en mémoire et ne le conserve pas après un redémarrage. Si l'utilisateur redémarre l'appareil avant d'activer un jeton, votre DPC peut définir à nouveau le même jeton ou en générer un nouveau.

Votre DPC peut confirmer qu'un jeton est actif en appelant isResetPasswordTokenActive() et en vérifiant que le résultat est true.

Une fois que votre DPC a défini et activé un jeton, celui-ci est valide jusqu'à ce qu'il le supprime ou le remplace (ou que la configuration d'usine de l'appareil soit rétablie). Le jeton est indépendant du mot de passe et n'est pas affecté par la modification ou l'effacement du mot de passe par l'utilisateur.

Supprimer un jeton

Vous pouvez appeler clearResetPasswordToken() pour supprimer un jeton que votre DPC a défini précédemment. Vous devrez peut-être révoquer un jeton compromis ou supprimer la possibilité de réinitialiser le mot de passe. L'exemple ci-dessous montre comment procéder dans votre DPC:

Kotlin

val dpm = getDpm()
val admin = DeviceAdminReceiver.getComponentName(requireActivity())

// Clear the token
if (!dpm.clearResetPasswordToken(admin)) {
 // Report the failure and possibly try later ...
}

Java

DevicePolicyManager dpm = getDpm();
ComponentName admin = DeviceAdminReceiver.getComponentName(getActivity());

// Clear the token
if (!dpm.clearResetPasswordToken(admin)) {
 // Report the failure and possibly try later ...
}

Réinitialiser le mot de passe

Lorsqu'un administrateur informatique doit réinitialiser le mot de passe, appelez resetPasswordWithToken() et transmettez à l'avance le jeton que votre DPC a défini et activé:

Kotlin

val token: ByteArray = getTokenFromServer()
val newPassword = "password"

try {
 val result: Boolean = dpm.resetPasswordWithToken(
 DeviceAdminReceiver.getComponentName(requireContext()),
 newPassword,
 token,
 0
 )

 if (result) {
 // The password is now 'password'
 } else {
 // Using 'password' doesn't meet password restrictions
 }
} catch (e: IllegalStateException) {
 // The token doesn't match the one set earlier.
}

Java

byte token[] = getTokenFromServer();
String newPassword = "password";

try {
 boolean result = dpm.resetPasswordWithToken(
  DeviceAdminReceiver.getComponentName(getContext()), newPassword, token, 0);

 if (result) {
 // The password is now 'password'
 } else {
 // Using `password` doesn't meet password restrictions
 }
} catch (IllegalStateException e) {
 // The token doesn't match the one set earlier.
}

Un appel à resetPasswordWithToken() renvoie false, et le mot de passe ne change pas lorsque le nouveau mot de passe ne répond pas aux contraintes suivantes:

  • Le nombre de caractères respecte les contraintes de longueur minimale du mot de passe. Appelez getPasswordMinimumLength() pour savoir si un administrateur informatique a défini une contrainte de longueur.
  • La plage et la complexité des caractères du mot de passe répondent à une contrainte de composition. Appelez getPasswordQuality() pour savoir si un administrateur informatique a défini une contrainte de composition.

Si les contraintes de qualité du mot de passe ne nécessitent pas de définir de mot de passe, vous pouvez transmettre null ou une chaîne vide à resetPasswordWithToken() pour supprimer le mot de passe.

Test de sécurité du profil professionnel

Un DPC exécuté en mode propriétaire de profil peut obliger les utilisateurs à spécifier un défi de sécurité pour les applications exécutées dans le profil professionnel. Le système affiche le défi de sécurité lorsque l'utilisateur tente d'ouvrir des applications professionnelles. Si l'utilisateur réussit la question de sécurité, le système déverrouille le profil professionnel et le déchiffre, si nécessaire.

Fonctionnement du test de sécurité du profil professionnel

  1. Si un DPC envoie un intent ACTION_SET_NEW_PASSWORD, le système invite l'utilisateur à configurer une question d'authentification de sécurité.
  2. Le DPC peut également envoyer un intent ACTION_SET_NEW_PARENT_PROFILE_PASSWORD pour inviter l'utilisateur à définir un verrouillage de l'appareil.

Un DPC peut définir les règles relatives aux mots de passe pour la question d'authentification au travail différemment des règles pour les autres mots de passe d'appareil. Par exemple, la longueur minimale de la réponse à la question d'authentification sur l'appareil peut être différente de la longueur requise pour d'autres mots de passe. Un DPC définit les règles de défi à l'aide des méthodes DevicePolicyManager habituelles, telles que setPasswordQuality() et setPasswordMinimumLength().

Points à prendre en compte

  • Le DPC peut réinitialiser le mot de passe sur le profil professionnel, mais pas le mot de passe (personnel). Si un utilisateur choisit de définir les mêmes mots de passe professionnels et personnels, resetPassword() sur le profil professionnel entraîne la réinitialisation du mot de passe sur le profil professionnel uniquement, qui sera différent de celui de l'écran de verrouillage de l'appareil.
  • Un DPC peut personnaliser l'écran d'identifiants du défi de tâche à l'aide de setOrganizationColor() et setOrganizationName().
  • Les administrateurs d'appareils ne peuvent pas utiliser resetPassword() pour effacer des mots de passe ou modifier des mots de passe déjà définis. Les administrateurs de l'appareil peuvent toujours définir un mot de passe, mais uniquement lorsque l'appareil n'a pas de mot de passe, de code ni de schéma.

Pour en savoir plus, consultez getParentProfileInstance() et la documentation de référence sous DevicePolicyManager.