Exemples de stratégie MXC

Ces exemples montrent comment les exigences relatives aux charges de travail se traduisent en autorisations de ressources MXC. Vous pouvez commencer par le démarrage rapide C#, TypeScript ou Rust, puis adapter la configuration à votre charge de travail.

Le code JSON ci-dessous utilise la structure brute de configuration d’exécution pour le schéma MXC 1.0.0. Les configurations complètes incluent une version et une commande ; les sections étiquetées en tant que fragments doivent être incorporées dans une configuration existante. Lorsque vous créez en C#, TypeScript ou Rust, utilisez les types de SDK V1 correspondants, qui ne nécessitent pas de version de schéma spécifique.

Il s’agit d’exemples Windows. Remplacez les chemins d’accès par des ressources existantes sur votre hôte, accordez délibérément toutes les dépendances d’outils supplémentaires, puis vérifiez que votre version du Kit de développement logiciel (SDK) et votre back-end prennent en charge les contrôles sélectionnés.

Exécuter un outil propre au dépôt

Cette configuration complète utilise le même modèle de lecture en entrée/écriture en sortie que le guide de démarrage rapide. Créez C:\src\my-app\input.txt et le répertoire C:\src\mxc-output avant de l’exécuter. La commande peut lire le répertoire source et écrire dans le répertoire de sortie, mais ne peut pas écrire dans le répertoire source ni utiliser le réseau ou l’interface utilisateur.

{
  "$schema": "https://raw.githubusercontent.com/microsoft/mxc/main/schemas/stable/mxc-config.schema.1.0.0.json",
  "version": "1.0.0",
  "containment": "process",
  "process": {
    "commandLine": "C:\\Windows\\System32\\cmd.exe /d /c type input.txt > C:\\src\\mxc-output\\result.txt",
    "cwd": "C:\\src\\my-app",
    "env": [
      "SystemRoot=C:\\Windows",
      "LOCALAPPDATA=C:\\src\\mxc-output",
      "TEMP=C:\\src\\mxc-output",
      "TMP=C:\\src\\mxc-output"
    ],
    "timeout": 30000
  },
  "filesystem": {
    "readonlyPaths": ["C:\\src\\my-app", "C:\\Windows\\System32\\cmd.exe"],
    "readwritePaths": ["C:\\src\\mxc-output"]
  },
  "network": {
    "egress": { "default": "deny" },
    "ingress": { "default": "deny", "hostLoopback": "deny" }
  },
  "ui": {
    "disable": true,
    "clipboard": "none",
    "injection": false
  }
}

Cet exemple suppose que Windows est installé dans C:\Windows ; utilisez le répertoire système réel sur votre hôte. Une requête Windows ProcessContainer avec une liste explicite env doit inclure à la fois SystemRoot et LOCALAPPDATA. Lorsque vous remplacez la commande par un outil de génération ou d’analyse, configurez ses caches et fichiers temporaires pour utiliser le répertoire accessible en écriture dédié plutôt que d’accorder l’accès en écriture à l’ensemble du référentiel.

Protéger les informations d’identification dans le cadre d’une autorisation plus large

La configuration précédente accorde l’accès en lecture à C:\src\my-app. Si ce répertoire contient un fichier d’environnement ou un répertoire de secrets, ajoutez ce fragment à l’intérieur de sa section filesystem existante, en conservant les listes en lecture seule et en lecture-écriture :

{
  "deniedPaths": [
    "C:\\src\\my-app\\.env",
    "C:\\src\\my-app\\secrets"
  ]
}

Ces chemins refusés se trouvent dans le répertoire source autorisé. Conservez les référentiels non liés et les répertoires de profil utilisateur en dehors des autorisations.

Conservez les secrets en dehors des arborescences autorisées lorsque cela est possible. Vérifiez les octrois qui se chevauchent et les refus sur le backend sélectionné ; certains backends montés-répertoire rejettent les refus imbriqués au lieu de les appliquer.

Autoriser l’accès direct à une plage d’adresses IP

Ce fragment de configuration remplace la network section. Il autorise le trafic sortant sur le port TCP 443 vers une plage CIDR approuvée et refuse d’autres accès de sortie, d’entrée et de bouclage hôte. Fournissez des plages approuvées issues d’une configuration de confiance plutôt que de les accepter comme provenant de la charge de travail.

{
  "network": {
    "egress": {
      "default": "deny",
      "allow": [
        {
          "to": [{ "cidr": "192.0.2.0/24" }],
          "ports": [{ "protocol": "tcp", "port": 443 }]
        }
      ]
    },
    "ingress": { "default": "deny", "hostLoopback": "deny" }
  }
}

192.0.2.0/24 est une plage réservée à la documentation. Remplacez-le par les adresses approuvées du service prévu. La règle autorise TCP sur ce port-là, et pas exclusivement HTTPS, un seul nom d’hôte ou un seul service d’application. La résolution directe du nom d’hôte peut nécessiter une règle DNS distincte.

Cet exemple nécessite un back-end et un hôte qui prennent en charge les règles de sortie directe. Ne la combinez pas avec runtimeConfig.networkProxy. Pour les décisions HTTP(S) basées sur le nom d’hôte, utilisez plutôt une configuration basée sur proxy prise en charge.

Utiliser un proxy fourni par l’application

Votre application hôte doit démarrer son proxy avant de lancer la charge de travail. Cet exemple configure MXC pour qu’il utilise un proxy existant. Il n’implémente pas, ne démarre pas et n’approuve pas la stratégie de gestion des demandes du proxy.

Le fragment de configuration suivant cible Windows ProcessContainer avec un mécanisme d’application du proxy à portée du système d’exploitation pris en charge. Fusionnez-le dans la configuration complète, en conservant la commande, les autorisations du système de fichiers, le délai d’expiration et les restrictions de l’interface utilisateur. Remplacez le point de terminaison et le nom du pair par ceux de votre proxy en cours d’exécution.

{
  "containment": "processcontainer",
  "network": {
    "egress": { "default": "deny" },
    "ingress": { "default": "allow", "hostLoopback": "deny" }
  },
  "runtimeConfig": {
    "networkProxy": "http://127.0.0.1:8080"
  },
  "processContainer": {
    "network": {
      "allowedProxyPeer": "<package-family-name-or-appcontainer-profile-name>"
    }
  }
}

allowedProxyPeer identifie le package installé pour le proxy ou le profil AppContainer non empaqueté. Le proxy doit écouter l’adresse et le port de bouclage configurés et répondre aux prérequis Windows documentés. MXC ne déduit pas cette identité de l’URL.

Important

Ce mappage Windows nécessite ingress.default: "allow", ce qui autorise également le trafic du serveur sur le réseau privé. hostLoopback: "deny" maintient fermé l’accès général au bouclage local de l’hôte tant que le pair proxy configuré est joignable. L’exemple n’est pas une configuration où tout le trafic entrant est refusé.

L’accès direct à Internet reste refusé sur le chemin de contrôle. Le proxy contrôle les requêtes HTTP(S) qu’il transfère. Un proxy hôte simple et non empaqueté sans identité AppContainer a besoin d’une configuration de compatibilité différente et plus large ; ne supprimez pas allowedProxyPeer et ne supposez pas que les mêmes restrictions restent.

Utilisez les types de SDK correspondants et vérifiez la prise en charge avant de vous appuyer sur l’accès proxy uniquement. Consultez les choix de déploiement du proxy ProcessContainer pour les prérequis Windows et la mise en réseau directionnelle pour d’autres back-ends.

Autoriser un outil visible sans accès étendu à l’interface utilisateur

Pour une charge de travail qui a besoin d’une fenêtre visible et d’une entrée du Presse-papiers, ce fragment de configuration remplace ui. Il autorise les lectures des fenêtres du système et du Presse-papiers, mais pas les écritures dans le presse-papiers ou les entrées de clavier synthétique et de pointeur :

{
  "ui": {
    "disable": false,
    "clipboard": "read",
    "injection": false
  }
}

Dans un Kit de développement logiciel (SDK) ContainerRequestV1, les propriétés d’interface utilisateur équivalentes sont disable, clipboardet allowInputInjection. Accordez les lectures du Presse-papiers uniquement lorsque la charge de travail les requiert. Vérifiez la prise en charge de l’interface utilisateur du runtime et testez les restrictions requises sur chaque hôte cible.

Réutiliser un sandbox avec état

Utilisez l’exécution prenant en compte l’état lorsque les commandes doivent partager un environnement. Provisionnez et démarrez-le, exécutez les commandes, puis arrêtez-le et déprovisionnez-le lorsque vous avez terminé. Organiser le nettoyage après l’échec et l’annulation, pas seulement la réussite.

Les appels prenant en charge l’état utilisent un ProvisionRequest spécifique à la phase et un ExecutionRequest distinct pour chaque commande, et non la configuration complète d’un coup ci-dessus. Le provisionnement retourne un objet opaque ContainerId; passez-le sans le modifier à des phases ultérieures. Utilisez MxcLifecycle dans .NET, les fonctions de cycle de vie TypeScript telles que provisionContainer, ou les fonctions Rust v1::container telles que provision_container, avec IsolationSession ou WSLc, les back-ends pris en charge par les API de cycle de vie V1. Consultez les concepts de cycle de vie, le cycle de vie des conteneurs MXC et le guide du sdk .NET, TypeScript ou Rust pour connaître les exigences exactes.

Vérifiez ce que chaque back-end de cycle de vie applique avant de le choisir. IsolationSession sépare l’utilisateur et la session de la charge de travail, mais n’applique pas le filtrage du système de fichiers MXC, de l’interface utilisateur ou du réseau, et sa requête doit autoriser explicitement tout le trafic réseau. La mise en réseau WSLc est entièrement isolée ou entièrement pontée, sans règles par destination. Pour plus d’informations, consultez Choisir un type de confinement et la sélection et les paramètres du backend.

Vérifiez les exemples

Pour chaque stratégie adaptée, testez à la fois le comportement prévu et les tentatives d’utilisation abusive :

  • Vérifiez que les entrées requises peuvent être lues et que les sorties requises peuvent être écrites.
  • Vérifiez que les informations d’identification et les fichiers non liés restent inaccessibles.
  • Vérifiez que les connexions directes, de réseau local, de boucle locale et de trafic entrant correspondent à la politique.
  • Pour l’accès via un proxy, vérifiez qu’une demande approuvée réussit et qu’une tentative d’accès direct à Internet échoue.
  • Vérifiez que le Presse-papiers, l’injection d’entrée et les fenêtres visibles correspondent à la stratégie d’interface utilisateur.
  • Vérifiez que les délais d’expiration et le nettoyage fonctionnent après la réussite, l’échec et l’annulation.

Utilisez le mode d’apprentissage pour examiner les autorisations manquantes. N’accordez pas automatiquement toutes les ressources qu’une exécution représentative observe.