Implémenter l'isolation des applications à l'aide de l'unité NGINX

Auteur original : Artem Konev - Rédacteur technique principal

Lien d'origine : implémenter l'isolation des applications à l'aide de l'unité NGINX

Source de réimpression : site officiel chinois de NGINX

La seule communauté chinoise officielle de NGINX, le tout sur nginx.org.cn 


 

L'un des derniers développements de l'ensemble de fonctionnalités de l'unité NGINX est la prise en charge de l'isolation des applications, introduite dans la version 1.11.0 et implémentée via les espaces de noms Linux.
 
Passons brièvement en revue l' espace de noms Linux : il s'agit essentiellement d'un mécanisme du noyau qui prend en charge un groupe de processus pour partager diverses ressources système séparément des ressources partagées par d'autres groupes de processus. Le noyau garantit que les processus d'un espace de noms accèdent uniquement aux ressources affectées à cet espace de noms. Bien que les processus dans deux espaces de noms différents puissent partager certaines ressources, d'autres ressources sont « invisibles » pour un processus dans l'autre espace de noms. Les types de ressources qui peuvent être isolées dans un espace de noms varient selon le système d'exploitation et incluent les ID de processus et d'utilisateur, les entités de communication inter-processus, les points de montage dans le système de fichiers, les objets réseau, etc.
 
Cela semble un peu ennuyeux ? Peut-être, surtout si vous ne connaissez pas la technologie du système d'exploitation. Mais les espaces de noms sont l’un des facteurs clés de la révolution de la conteneurisation, et l’isolement des processus d’application au sein d’une seule instance de système d’exploitation permet d’obtenir les mécanismes critiques de sécurité et de mise à l’échelle nécessaires à l’exécution d’applications dans des conteneurs.

idée

Maintenant que nous avons établi que les espaces de noms peuvent être une bonne chose, que fait NGINX Unit avec eux ? Avant de plus amples explications, commençons par présenter brièvement les informations générales pertinentes et comprendre les propres pensées de Tiago :
 
"Je recherche de meilleurs moyens de surveiller et d'intercepter efficacement le trafic de mon application. Pendant mon temps libre, j'ai examiné les composants internes de l'unité NGINX et j'ai pensé que l'isolation des processus pourrait être une bonne solution. Cependant, je ne suis pas sûr. mais si c'est un scénario optimal. Auparavant, je pensais à eBPF et j'examinais comment il redirige les paquets au niveau du noyau, mais j'ai ensuite eu une idée différente. Puisque NGINX Unit exécute et gère les applications de la même manière qu'un environnement d'exécution de conteneur, alors si nous Que se passerait-il si Unit ajoutait la prise en charge de l'isolation des applications et l'utilisait à la place du runtime ?Cette idée coïncide avec l'une des idées futures de l'équipe NGINX Unit.
Dans le cluster, le runtime du conteneur démarre et arrête l'application, nous savons donc tout ce qui s'exécute dans le cluster. L'architecture de NGINX Unit fait non seulement la même chose, mais implémente également la surveillance et l'interception du trafic par défaut : le seul moyen d'accéder à l'application est via le modèle de mémoire partagée de NGINX Unit. Notamment, nous sommes même capables d'isoler le réseau, comme si nous ignorions les paramètres d'interface dans le conteneur, mais l'application peut toujours communiquer avec le monde extérieur en partageant la mémoire avec l'unité NGINX sans rencontrer d'attaques réseau coûteuses. "

Configuration

Du point de vue de la configuration, tout commence avec le nouvel objet d'isolation, qui définit les paramètres liés à l'espace de noms dans l'objet d'application.
 

Les options d'espace de noms dans l'objet d'isolation dépendent du système, car les types de ressources pouvant être isolées dans un espace de noms varient selon le système d'exploitation. Voici un exemple simple de création d'un ID utilisateur et d'un espace de noms de point de montage distincts pour votre application :

{
   "applications": {  
      "isolation_app": {  
         "type": "external",
         "executable": "/tmp/go-app",
         "isolation": {  
            "namespaces": {  
               "credential": true,
               "mount": "true"
            }
         }
      }
   }
}
Actuellement, l'unité NGINX prend en charge la configuration de 6 des 7 types d'isolation d'espace de noms pris en charge par le noyau Linux. Les options de configuration correspondantes sont cgroup, credential, pid, mount, network et uname. Le dernier type ipc n'est pas encore pris en charge.
 
Par défaut, tous les types d'isolement sont désactivés (option définie sur false), ce qui signifie que l'application réside dans l'espace de noms de l'unité NGINX. Lorsque vous activez un type d'isolation spécifique pour une application en définissant son option sur true, NGINX Unit crée un espace de noms distinct de ce type pour l'application. Par exemple, une application peut se trouver dans le même espace de noms qu'une unité NGINX, en plus d'avoir son propre espace de noms de montage ou d'informations d'identification distinct.
 
Pour plus de détails sur les options de l'objet d'isolation, consultez la documentation de l'unité NGINX .
 
Remarque : Au moment de la rédaction, toutes les applications doivent utiliser le même espace de noms IPC que l'unité NGINX ; il s'agit d'une exigence du mécanisme de mémoire partagée. Vous pouvez ajouter l'option ipc à la configuration, mais son paramétrage n'a aucun effet. Cette exigence peut changer dans les versions futures.
 

Mappage des ID d'utilisateur et de groupe

 
L'isolation des applications dans NGINX Unit inclut la prise en charge du mappage UID et GID, qui peut être configuré si l'isolation des informations d'identification est activée (ce qui signifie que votre application s'exécute dans un espace de noms d'informations d'identification distinct). Vous pouvez mapper une série d'ID dans l'espace de noms de l'application (que nous appelons "espace de noms de conteneur") à l'espace de noms d'informations d'identification du processus parent de l'application (que nous appelons "espace de noms d'hôte"). Des plages d'ID de même longueur.
 
Par exemple, supposons que vous ayez une application exécutée avec des informations d'identification d'utilisateur non privilégiés et que vous activiez l'isolation des informations d'identification pour créer un espace de noms de conteneur pour l'application. L'unité NGINX vous permet de mapper l'UID d'un utilisateur non privilégié dans l'espace de noms d'hôte à l'UID 0 (racine) dans l'espace de noms du conteneur. De par sa conception, tout UID ayant une valeur de 0 dans un espace de noms dispose d'autorisations complètes dans cet espace de noms, mais ses autorisations pour mapper l'UID correspondant dans l'espace de noms d'hôte sont toujours limitées. Par conséquent, l’application semble disposer de fonctionnalités racine, mais uniquement pour les ressources situées dans son espace de noms. Il en va de même pour le mappage GID.
 

Ici, nous mappons les 10 valeurs de plage UID commençant à partir de l'UID 500 dans l'espace de noms de l'hôte aux valeurs de plage UID commençant à partir de l'UID 0 dans l'espace de noms du conteneur (hôte : 500-509, conteneur : 0-9). De même, nous mappons les 20 valeurs de plage GID commençant à partir du GID 1000 dans l'espace de noms de l'hôte aux valeurs de plage commençant à partir de GID 0 dans l'espace de noms du conteneur (hôte : 1000-1019, conteneur : 0-19) :

{
   "applications": {  
      "isolation_app": {  
         "type": "external",
         "executable": "/bin/app",
         "isolation": {  
            "namespaces": {  
               "credential": true
            },
            "uidmap": [  
               {  
                  "container": 0,
                  "host": 500,
                  "size": 10
               }
            ],
            "gidmap": [  
               {  
                  "container": 0,
                  "host": 1000,
                  "size": 20
               }
            ]
         }
      }
   }
}

 

 
Si vous ne créez pas de mappage UID et GID explicite, par défaut, l'UID (EUID) actuellement effectif du processus d'unité NGINX non privilégié dans l'espace de noms d'hôte est mappé à l'UID racine dans l'espace de noms du conteneur. Notez également que le mappage UID/GID n'est disponible que si le système d'exploitation hôte prend en charge les espaces de noms utilisateur. Cela dit, passons à la compréhension de l'impact de l'isolation des applications sur les applications exécutées dans NGINX Unit.

Premiers pas : isolation de base des applications

Commençons par les bases et comprenons comment cette fonctionnalité se comporte au moment de l'exécution. Pour ce faire, nous prendrons une application Go de notre référentiel officiel (exécutée lors du test des nouvelles versions) :
Ce code répond à la demande avec une liste au format JSON d'ID de processus d'application et d'espace de noms, énumérant le contenu du répertoire /proc/self/ns/. Ensuite, nous configurons l'application dans NGINX Unit, en ignorant pour l'instant l'objet d'isolation :
 
{  
   "listeners": {  
      "*:8080": {  
         "pass": "applications/go-app"
      }
   },
   "applications": {  
      "go-app": {  
         "type": "external",
         "executable": "/tmp/go-app"
      }
   }
}

Réponse HTTP de l'instance d'application en cours d'exécution :

$ curl -X GET http://localhost:8080

{  
   "PID": 5778,
   "UID": 65534,
   "GID": 65534,
   "NS": {  
      "USER": 4026531837,
      "PID": 4026531836,
      "IPC": 4026531839,
      "CGROUP": 4026531835,
      "UTS": 4026531838,
      "MNT": 4026531840,
      "NET": 4026531992
   }
}
Nous ajoutons maintenant l'objet d'isolation pour activer l'isolation des applications. Le mécanisme d'isolation doit redémarrer l'application pour prendre effet. NGINX Unit effectuera cette tâche en coulisses, les mises à jour sont donc très transparentes du point de vue de l'utilisateur final.
{  
   "listeners": {  
      "*:8080": {  
         "pass": "applications/go-app"
      }
   },
   "applications": {  
      "go-app": {  
         "type": "external",
         "user": "root",
         "executable": "/tmp/go-app",
         "isolation": {  
            "namespaces": {  
               "cgroup": true,
               "credential": true,
               "mount": true,
               "network": true,
               "pid": true,
               "uname": true
            },
            "uidmap": [  
               {  
                  "host": 1000,
                  "container": 0,
                  "size": 1000
               }
            ],
            "gidmap": [  
               {  
                  "host": 1000,
                  "container": 0,
                  "size": 1000
               }
            ]
         }
      }
   }
}
Notez que l'option utilisateur est définie sur root. Cette configuration est requise pour activer le mappage vers l'UID/GID 0 dans l'espace de noms du conteneur.
 
Nous émettons à nouveau la commande :
$ curl -X GET http://localhost:8080

{  
   "PID": 1,
   "UID": 0,
   "GID": 0,
   "NS": {  
      "USER": 4026532180,
      "PID": 4026532184,
      "IPC": 4026531839,
      "CGROUP": 4026532185,
      "UTS": 4026532183,
      "MNT": 4026532181,
      "NET": 4026532187
   }
}
L'isolation des applications est désormais activée et les ID d'espace de noms ont changé : ce sont désormais des ID dans l'espace de noms du conteneur, et non dans l'espace de noms de l'hôte. La seule chose qui reste inchangée est l'IPC, pour les raisons évoquées ci-dessus .

Plongez plus profondément : isolation des applications Web

Pour mieux comprendre, explorons l'impact réel de l'isolation des applications sur le réseau, ce qui est très important pour les applications Web. Notre outil de choix pour cela est nsenter, qui fonctionne sur de nombreuses distributions de systèmes d'exploitation prises en charge par NGINX Unit. Cet utilitaire nous permet d'exécuter des commandes arbitraires dans l'espace de noms du processus, et nous l'utiliserons pour démontrer les changements provoqués par différents paramètres dans l'objet d'isolation de la même application Go configurée précédemment. Tout d'abord, nous découvrons le PID de l'hôte
 
Pour plus de détails sur le code, consultez le site officiel de la communauté NGINX
 
Après avoir déterminé le PID, nous pouvons entrer dans l'espace de noms du conteneur et afficher sa composition interne
 
Notez que seule l'interface de bouclage est disponible ; cependant, l'application est entièrement capable de gérer les requêtes HTTP externes via l'unité NGINX. Ensuite, nous supprimerons l'option réseau de la liste des espaces de noms configurés pour voir la configuration finale de l'interface réseau pour l'application avec l'isolation réseau désactivée.
 
Nous répétons ensuite les mêmes étapes ci-dessus
 
Il existe également des processus d'application qui utilisent toujours l'interface NGINX Unit (eth0) lors du démarrage.
 

La seule communauté chinoise officielle de NGINX, le tout sur nginx.org.cn
Plus d'informations techniques liées à NGINX, des questions et réponses interactives, une série de cours et des ressources événementielles : Site Web officiel de la communauté Open Source | Compte officiel WeChat
IntelliJ IDEA 2023.3 et JetBrains Family Bucket mise à jour annuelle de la version majeure nouveau concept de « programmation défensive » : faites-vous un travail stable GitHub.com exécute plus de 1 200 hôtes MySQL, comment passer en toute transparence à la version 8.0 ? L'équipe Web3 de Stephen Chow lancera une application indépendante le mois prochain. Firefox sera-t-il éliminé ? Sortie de Visual Studio Code 1.85, fenêtre flottante La CISA américaine recommande d'abandonner C/C++ pour éliminer les vulnérabilités de sécurité de la mémoire Yu Chengdong : Huawei lancera des produits disruptifs l'année prochaine et réécrira l'histoire de l'industrie TIOBE Décembre : C# devrait devenir le langage de programmation de l'année Un article écrit par Lei Jun il y a 30 ans : "Principe et conception du système expert de détermination des virus informatiques"
{{o.name}}
{{m.nom}}

Je suppose que tu aimes

Origine my.oschina.net/u/5246775/blog/10109984
conseillé
Classement