# Passerelles d’agents locales avec le MDM macOS

Une passerelle d’agent locale doit être déployée comme une application de bureau sensible du point de vue de la sécurité, et non comme un système de distribution de secrets partagés. Le MDM gère l’application signée, sa version, son état de lancement et sa suppression. Le développeur gère les identifiants qu’il place dans un coffre local ainsi que les approbations qui permettent à un agent d’utiliser ces identifiants.

Cette séparation ne relève pas seulement d’une administration bien ordonnée. Lorsque l’équipe informatique fait transiter des clés API par le MDM, toute compromission du plan de gestion, d’un export d’inventaire, d’un script de déploiement ou d’un profil de configuration peut exposer les secrets. Lorsqu’un agent reçoit lui-même la clé, chaque journal, transcription d’outil, historique shell et limite de prompt devient une partie de la surface d’attaque du secret. Une passerelle sert précisément à empêcher l’identifiant d’entrer dans le processus de l’agent. Ne défaites pas cette protection pendant le déploiement.

Voici le modèle opérationnel que j’utiliserais pour un parc de Mac gérés : distribuer un paquet d’application vérifiable, le lancer dans le bon contexte utilisateur, faire passer les versions par des anneaux, demander à chaque développeur d’inscrire ses propres identifiants localement et retirer les appareils selon une séquence qui supprime l’accès avant d’effacer le matériel.

## Le MDM doit distribuer la passerelle, pas l’autorité du développeur

Le MDM doit savoir quel Mac possède l’application approuvée et quelle version il exécute. Il ne doit pas devenir un coffre pour les jetons API personnels, les clés privées SSH ou les fichiers d’identifiants copiés-collés.

On confond souvent deux réalités parce qu’elles sont toutes deux appelées « configuration ». Installer une application relève de la configuration du parc. Donner à une personne ou à un agent l’autorisation d’appeler une API de production relève d’une autorité déléguée. La première appartient au MDM. La seconde doit rester dans un coffre local contrôlé par l’utilisateur, avec une limite d’approbation claire.

Cette distinction a une conséquence concrète lors de l’intégration. Le flux MDM peut installer la passerelle avant que le développeur ouvre son éditeur. Le premier lancement doit toutefois lui demander de créer ou déverrouiller son propre coffre et d’y ajouter uniquement les identifiants qu’il est autorisé à utiliser. L’équipe informatique peut documenter les types d’identifiants approuvés et les comptes de service requis, mais elle ne doit pas collecter les secrets pour les redistribuer plus tard.

Cela rend également le départ d’un collaborateur plus fiable. Supprimer une application gérée ne révoque pas un jeton cloud copié dans un profil plusieurs mois auparavant. Avec un coffre local, l’utilisateur peut supprimer directement un identifiant, tandis que le propriétaire du service peut toujours révoquer le jeton à sa source. Vous disposez ainsi de deux moyens indépendants de mettre fin à l’accès, au lieu de dépendre d’un seul script de nettoyage fragile.

Pour Sallyport, cette séparation est volontaire : l’application conserve les clés API et SSH dans son coffre local chiffré et effectue elle-même les actions HTTP ou SSH, au lieu de transmettre les identifiants à l’agent connecté. Le déploiement doit préserver cette propriété.

Un enregistrement MDM pertinent pour la passerelle ne contient que des informations opérationnelles :

- numéro de série de l’appareil ou identifiant de gestion
- anneau de déploiement et version de l’application attribués
- reçu du paquet et résultat de l’installation
- responsable principal du support et date d’expiration d’une exception
- état de l’application : requise, facultative ou en attente de suppression

N’ajoutez pas dans l’inventaire les noms de secrets, valeurs de jetons, chemins de clés privées ou historiques d’approbation. Ces informations exposent un contexte sensible ou donnent à tort l’impression que le MDM peut reconstituer l’accès de travail d’un utilisateur.

## Le paquet est le contrat de déploiement

Un paquet d’installation signé est l’artefact qui rend un déploiement de parc reproductible. Une image disque partagée dans une conversation, une archive zip extraite dans Téléchargements ou un script qui copie un paquet d’application dans /Applications ne constitue pas un contrat de déploiement.

La documentation de déploiement d’Apple indique que les paquets installés par la gestion des appareils doivent porter une signature que l’appareil peut vérifier. Elle recommande également les applications autonomes, ce qui évite les scripts d’installation personnalisés pour les déploiements ordinaires. C’est une bonne pratique dans ce cas. Les scripts multiplient les chemins d’échec, s’exécutent avec des privilèges difficiles à comprendre et restent souvent en place longtemps après une modification de la structure de l’application.

Créez un artefact de version pour chaque version publiée. Donnez-lui un nom de fichier versionné, conservez son checksum dans le registre des versions et exigez le même paquet dans chaque anneau. Un anneau doit tester l’exposition à la même version, et non à une variante impossible à retracer assemblée pour chaque groupe.

Avant d’envoyer un paquet au MDM, vérifiez le paquet et l’application installée sur un Mac de test propre. Ces commandes constituent un contrôle minimal utile :

```sh
pkgutil --check-signature Sallyport.pkg
spctl -a -vv -t install Sallyport.pkg
```

La première commande doit identifier un installateur signé et une chaîne de signature valide. La seconde doit évaluer le paquet pour l’installation. Après le déploiement, inspectez également le paquet de l’application :

```sh
codesign --verify --deep --strict --verbose=2 /Applications/Sallyport.app
spctl -a -vv /Applications/Sallyport.app
```

Ne considérez pas un statut MDM positif comme la preuve que le bon binaire est prêt. Le MDM peut signaler que le paquet est installé alors qu’un élément de connexion, un agent d’arrière-plan, un droit ou une exigence liée à la session utilisateur empêche ensuite l’application de fonctionner correctement. La vérification du paquet et les tests fonctionnels répondent à deux questions différentes.

Gardez le paquet simple. Il doit installer l’application à l’emplacement prévu, éviter de télécharger un second exécutable durant le postinstall et ne pas écrire d’identifiants ni de réglages propres à un utilisateur. Si un paquet a besoin d’un script postinstall élaboré pour faire fonctionner le produit, demandez-vous si la conception de l’application ou la limite du paquet n’est pas mal définie. Vous paierez le prix de ce script à chaque mise à niveau de macOS et lors de chaque analyse d’incident.

L’application installée doit pouvoir être supprimée comme une application, et non au terme d’une enquête médico-légale. Apple indique qu’un paquet d’application placé dans /Applications peut être géré et supprimé individuellement par le service de gestion des appareils. C’est une raison supplémentaire d’éviter de disperser les fichiers essentiels dans des répertoires arbitraires.

## Lancez l’application dans la session du développeur

Une passerelle qui demande une approbation locale ou doit accéder à un coffre protégé par l’utilisateur doit s’exécuter dans le contexte de l’utilisateur connecté. Un daemon root ne remplace pas ce contexte.

C’est ici que les équipes commettent une erreur prévisible. Elles voient « toujours en fonctionnement » et choisissent un LaunchDaemon parce qu’il démarre avant la connexion et survit à la déconnexion de l’utilisateur. Elles découvrent ensuite que le daemon ne peut pas afficher correctement une demande d’approbation, ne peut pas utiliser le trousseau ou le parcours d’autorisation biométrique de l’utilisateur et possède plus de privilèges que nécessaire.

Apple définit clairement cette limite. Un élément de connexion démarre lorsque l’utilisateur se connecte et s’exécute dans sa session. Un LaunchAgent s’exécute également pour l’utilisateur connecté. Un LaunchDaemon s’exécute au niveau du système, peut démarrer avant la connexion et s’exécute en tant que root. Apple décrit aussi les éléments de connexion comme adaptés à une application destinée à l’utilisateur qui doit rester active pendant sa session.

Pour une passerelle de barre des menus, le choix normal est un élément de connexion géré ou le mécanisme d’élément de connexion pris en charge par l’application. L’application doit démarrer lorsque l’utilisateur atteint le bureau, rester suffisamment visible pour que le développeur sache qu’elle est active et s’arrêter lorsque l’utilisateur se déconnecte. Ne dissimulez pas une limite de sécurité dans un processus que les utilisateurs ne peuvent ni inspecter ni quitter.

Si le MDM doit imposer le comportement de lancement, utilisez la charge utile d’élément de connexion géré d’Apple plutôt qu’un plist copié par un script. La charge utile `com.apple.loginitems.managed` peut spécifier le chemin de l’application et indiquer si elle doit être masquée. La documentation de gestion des appareils d’Apple fournit la structure de cette charge utile et la prend en charge sur macOS.

Voici un exemple représentatif. Remplacez les identifiants et le chemin par les valeurs de votre version publiée, puis générez les UUID avec vos outils habituels de création de profils.

```xml
\u003cdict\u003e
  \u003ckey\u003ePayloadType\u003c/key\u003e
  \u003cstring\u003ecom.apple.loginitems.managed\u003c/string\u003e
  \u003ckey\u003ePayloadIdentifier\u003c/key\u003e
  \u003cstring\u003edev.example.agent-gateway.login-item\u003c/string\u003e
  \u003ckey\u003ePayloadUUID\u003c/key\u003e
  \u003cstring\u003eREPLACE-WITH-UUID\u003c/string\u003e
  \u003ckey\u003ePayloadVersion\u003c/key\u003e
  \u003cinteger\u003e1\u003c/integer\u003e
  \u003ckey\u003eAutoLaunchedApplicationDictionary-managed\u003c/key\u003e
  \u003carray\u003e
    \u003cdict\u003e
      \u003ckey\u003ePath\u003c/key\u003e
      \u003cstring\u003e/Applications/Sallyport.app\u003c/string\u003e
      \u003ckey\u003eHide\u003c/key\u003e
      \u003cfalse/\u003e
    \u003c/dict\u003e
  \u003c/array\u003e
\u003c/dict\u003e
```

Cette configuration évite un problème banal mais coûteux : le paquet s’installe, l’application apparaît dans /Applications et le développeur pense que la passerelle protège son agent. En réalité, elle ne s’est jamais lancée après la connexion. Le relais MCP ne peut donc pas terminer une requête ou l’utilisateur ne voit jamais la carte d’approbation. Les contrôles d’inscription doivent tester une véritable connexion utilisateur, et pas seulement l’installation par l’agent MDM.

Un LaunchDaemon a des usages légitimes, mais éloignez-le du parcours du coffre. N’en utilisez un que si vous pouvez expliquer pourquoi la tâche doit fonctionner sans session graphique et pourquoi root est nécessaire. « Nous voulions que ce soit fiable » n’est pas une réponse. Une application de session utilisateur peut être fiable sans se faire passer pour un service machine.

## Les anneaux de mise à jour doivent tester le vrai travail des développeurs

Les anneaux de mise à jour fonctionnent lorsque chacun répond à une question opérationnelle différente. Ils échouent lorsqu’ils deviennent un moyen poli de repousser indéfiniment chaque mise à jour.

Commencez par un petit anneau interne. Placez-y les personnes qui empaquettent l’application, gèrent la configuration MDM et dépannent les postes de développement. Leur rôle est de détecter les échecs d’installation, les problèmes de lancement, les demandes de permission inattendues et les chemins de mise à niveau depuis la version précédente en production.

L’anneau suivant doit inclure des développeurs qui utilisent des outils et des modes d’accès différents. Ajoutez une personne qui utilise des API HTTP via un agent, une autre qui utilise SSH, une personne qui change souvent de réseau et une personne qui travaille avec un compte géré ordinaire plutôt qu’avec des privilèges d’administrateur local. Vous cherchez des différences dans l’utilisation réelle, pas un groupe d’enthousiastes prêts à excuser tous les défauts.

La production est l’anneau dans lequel la version devient la version par défaut. Conservez un petit groupe de blocage d’urgence uniquement pour une raison précise, avec un responsable et une date d’expiration. « Cette personne est occupée » n’est pas une politique de déploiement. C’est ainsi que les versions non prises en charge deviennent permanentes.

Traitez le déploiement comme une machine à états, et non comme un rituel du calendrier :

1. Installez le paquet signé dans l’anneau interne et confirmez l’évaluation du paquet et de l’application.
2. Demandez à chaque utilisateur de test de se déconnecter puis de se reconnecter, et confirmez que la passerelle démarre dans sa session.
3. Exécutez des actions réelles sans risque via le parcours de l’agent, notamment une requête HTTP et une commande SSH si ces canaux sont concernés.
4. Faites passer le paquet identique dans l’anneau pilote après examen des échecs, des tickets de support et des besoins de retour arrière.
5. Passez en production uniquement lorsque le chemin de mise à niveau depuis la version précédente fonctionne, et pas seulement une nouvelle installation.

Ne définissez pas la réussite par « la console MDM indique installé ». Définissez-la comme une chaîne d’événements observables : le reçu du paquet est présent, l’application signée réussit l’évaluation, elle démarre après la connexion, le développeur peut déverrouiller son propre coffre, l’agent atteint le relais local et une action autorisée renvoie un résultat.

Définissez le retour arrière avant le déploiement. Pour une mise à jour ordinaire, il doit signifier redéployer le paquet signé précédent, restaurer l’attribution de la version obligatoire précédente et vérifier que l’ancienne application peut lire correctement son état local. Il ne doit pas consister à demander aux développeurs de déplacer des applications entre des dossiers pendant que le support tente de déterminer quelle version ils utilisent.

La gestion déclarative des applications et des paquets d’Apple peut définir des paquets comme obligatoires ou facultatifs sur les Mac supervisés compatibles, et la gestion déclarative des applications prend le pas sur une commande d’installation concurrente. N’envoyez pas deux mécanismes de gestion vers la même cible en espérant que l’appareil choisira celui que vous aviez prévu. Choisissez le mécanisme qui fait autorité dans chaque anneau et consignez ce choix.

## Un coffre séparé transforme l’intégration et la récupération

Un coffre propre à chaque développeur fait du premier lancement une étape de sécurité, et non un défaut d’automatisation. L’utilisateur doit décider quels identifiants appartiennent à ce Mac, et l’appareil doit vérifier que l’utilisateur peut les déverrouiller.

C’est précisément le but. La passerelle d’agent locale peut recevoir une requête de Claude Code ou d’un autre agent compatible avec MCP, mais l’agent ne doit jamais recevoir l’identifiant en clair ni un faux emplacement qu’il pourrait ensuite détourner. La passerelle doit exécuter l’action HTTP ou SSH et renvoyer le résultat.

Dans Sallyport, l’échelle de décision fixe est utile parce qu’elle évite un langage de politiques que chaque équipe devrait apprendre et auditer. Un coffre verrouillé refuse toute action. Un nouveau processus d’agent reçoit par défaut une autorisation de session, tandis qu’un identifiant marqué pour une approbation à chaque appel demande une confirmation à chaque utilisation. Ces contrôles sont différents : formez les développeurs à les employer dans des situations différentes.

Utilisez le verrouillage du coffre lorsque l’ordinateur portable est sans surveillance ou lorsque le développeur a terminé son travail. Utilisez l’autorisation de session pour identifier une nouvelle exécution d’agent avant de lui accorder une latitude importante. Utilisez l’approbation à chaque appel pour les identifiants dont chaque utilisation mérite l’attention d’une personne, par exemple un jeton d’administration de production ou une identité SSH sensible.

Ne demandez pas aux développeurs de placer tous les identifiants sous approbation à chaque appel parce que cela semble plus sûr. Des demandes répétées les habituent à approuver sans lire. Placez la friction là où une requête erronée aurait des conséquences, et laissez les identifiants de développement ordinaires et peu risqués sous la limite de session. La fatigue liée aux approbations est un défaut de conception, pas la preuve que votre équipe prend la sécurité au sérieux.

La récupération doit respecter des limites tout aussi claires. L’équipe informatique peut réinstaller l’application de passerelle et réparer son état de lancement géré. Elle ne peut pas et ne doit pas restaurer le contenu du coffre d’un développeur depuis un enregistrement MDM. Si un Mac est remplacé, le développeur doit obtenir de nouveaux identifiants auprès du système source ou suivre la procédure approuvée de migration des identifiants. Cela peut être contraignant. C’est néanmoins plus sûr que de traiter une base de données de gestion de parc comme une sauvegarde de jetons de production.

Documentez le tableau des responsabilités avant le déploiement :

| Événement | Développeur | Équipe informatique ou postes de travail | Propriétaire du service |
| --- | --- | --- | --- |
| Configuration d’un nouveau Mac | Déverrouille le coffre et ajoute les identifiants autorisés | Installe l’application et la configuration de connexion | Accorde l’identifiant initial |
| Comportement inattendu de l’agent | Révoque la session et verrouille le coffre | Confirme l’état de l’appareil et de l’application | Révoque l’identifiant si nécessaire |
| Échec de mise à jour de l’application | Signale le comportement visible et la version | Répare l’attribution du paquet ou effectue un retour arrière | Généralement aucune action |
| Remplacement de l’appareil | Obtient un nouvel identifiant ou suit la migration approuvée | Retire l’ancien Mac et déploie le nouveau | Fait tourner ou réattribue l’accès |

Ce tableau évite le pire appel au support du déploiement : un développeur dit « mon agent a perdu l’accès », le support des postes répond « l’application est installée » et le propriétaire du service pense que quelqu’un a restauré un secret que personne n’était censé posséder.

## L’inventaire et les preuves d’action répondent à des questions différentes

L’inventaire MDM indique si l’application gérée a atteint un appareil. Il ne peut pas établir ce qu’un agent d’IA a demandé après l’installation, quelle autorité l’a approuvé ni quel appel API a été exécuté.

Conservez ces enregistrements séparément et rapprochez-les lorsque cela est nécessaire. L’enregistrement MDM doit fournir l’identité matérielle, l’état de gestion, la version attribuée, l’horodatage d’installation et l’état de suppression. La piste d’audit de la passerelle doit fournir la session, l’action individuelle et le résultat de la vérification. Si vous les fusionnez dans un seul tableur, vous exposerez soit trop de détails opérationnels au personnel chargé des postes, soit pas assez d’éléments aux personnes qui répondent aux incidents.

Sallyport consigne les exécutions d’agents dans un journal Sessions et les actions individuelles dans un journal Activity, tous deux projetés à partir d’un journal d’audit chiffré et chaîné par hachage. Sa commande `sp audit verify` vérifie la chaîne hors ligne sur le texte chiffré et n’a pas besoin de la clé du coffre. Un enquêteur peut donc vérifier que l’enregistrement n’a pas été modifié sans ouvrir les secrets de l’utilisateur.

Utilisez une procédure simple pour un incident ou une revue de version :

```sh
sp audit verify
```

Un résultat utile présente clairement une réussite ou un échec, puis la plage vérifiée, par exemple :

```text
Audit chain: valid
Records checked: 184
First record: 2026-07-01T14:22:09Z
Last record: 2026-07-22T09:15:44Z
```

Les champs exacts dépendent de la version installée de la commande. Conservez donc la sortie brute avec la version de l’application et l’identifiant de l’appareil. Ne copiez pas le contenu du coffre d’un développeur, la transcription de ses prompts ni un historique de terminal sans rapport avec la collecte du résultat d’audit.

Cette séparation améliore également le support courant. Si la console MDM affiche la version attendue mais que le développeur indique qu’une action a été refusée, examinez l’état local de la passerelle et le parcours d’approbation. Si l’audit montre une action alors que le MDM ne possède aucun enregistrement d’installation actuel, recherchez un appareil obsolète, un Mac récemment retiré ou une installation non gérée. Chaque système a une mission précise. Laissez-le la remplir correctement.

## Le retrait d’un appareil commence par l’accès, pas par l’effacement

Lorsqu’un Mac change de propriétaire, est perdu ou quitte l’entreprise, mettez fin à sa relation d’accès avant de l’effacer ou de le retirer de la propriété de l’organisation. L’effacement nettoie le disque. Il ne prouve pas que les identifiants cloud, les sessions d’agents actives ou les attributions d’appareils ont été traités correctement.

Pour un retour professionnel normal, procédez dans cet ordre :

1. Identifiez l’appareil, son dernier utilisateur, son enregistrement MDM et la date de sa dernière connexion.
2. Révoquez les sessions actives de la passerelle et demandez au propriétaire du service de faire tourner ou de révoquer les identifiants qui pourraient rester utilisables ailleurs.
3. Supprimez l’application gérée ou marquez-la pour suppression si le Mac reste en ligne assez longtemps pour recevoir la commande.
4. Conservez le minimum requis de preuves de gestion et d’audit conformément à vos règles de conservation.
5. Effacez le Mac avec la procédure approuvée de retour ou de réaffectation de l’organisation.

Ne retirez pas le Mac d’Apple Business Manager simplement parce qu’un salarié quitte l’entreprise. Ce retrait est une décision de propriété concernant un matériel vendu, perdu sans possibilité de récupération ou qui ne relève plus de votre contrôle. Apple avertit que cette opération est irréversible avec le parcours d’attribution habituel, empêche toute attribution MDM future et exige un effacement et une restauration après le retrait. Apple recommande également de ne pas retirer un appareil envoyé en réparation, car un appareil de remplacement pourrait ne pas revenir dans Apple Business Manager.

Pour un Mac professionnel réaffecté, conservez l’inscription de l’organisation, effacez l’appareil et inscrivez le prochain utilisateur selon votre procédure habituelle. Pour un appareil personnel sous un modèle d’inscription utilisateur, supprimez la gestion conformément à la politique convenue, confirmez quelles applications et quels réglages gérés disparaîtront et demandez au développeur de supprimer ses propres identifiants avant la remise. Apple indique que la désinscription peut supprimer les applications et contenus gérés tout en conservant les applications et réglages personnels sur les appareils inscrits par l’utilisateur.

Un Mac perdu nécessite une procédure accélérée. Révoquez d’abord les identifiants et les sessions, car la machine pourrait ne jamais se reconnecter. Utilisez ensuite les contrôles de gestion des appareils et le processus de révocation du propriétaire du service. Attendre qu’une commande de suppression d’application arrive sur l’appareil n’est pas une mesure de confinement.

## Le déploiement réussit lorsqu’il reste banal

Le meilleur déploiement d’une passerelle locale suscite peu de problèmes parce que chaque limite est explicite. L’équipe MDM distribue une application signée et contrôle son cycle de vie. Le développeur conserve ses identifiants dans un coffre local et voit lorsqu’un agent demande une autorité. Le propriétaire du service accorde et révoque les accès à la source. La piste d’audit enregistre les actions sans devenir un dépôt de secrets.

Commencez par le test qui révèle le plus d’hypothèses erronées : inscrivez un Mac géré propre, connectez-vous comme un développeur ordinaire, installez le paquet de production via le MDM, déconnectez-vous puis reconnectez-vous, ajoutez localement un identifiant sans importance, exécutez une action d’agent sans risque, vérifiez son enregistrement d’audit, puis supprimez l’application et recommencez depuis une nouvelle inscription. Si cette séquence nécessite des interventions non documentées, un script root caché ou un fichier d’identifiants copié, corrigez le déploiement avant d’ajouter une centaine d’appareils.
