Extract project outside tuto
This commit is contained in:
parent
453e7edcb9
commit
21dc57ade4
@ -1 +0,0 @@
|
|||||||
../tutorial/3/project-body.md
|
|
88
subject/project-part1.md
Normal file
88
subject/project-part1.md
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
### Palier 1 : Restreindre l'environnement (2 points)
|
||||||
|
|
||||||
|
Après avoir mis en place les bases de votre programme, commencez par créer les
|
||||||
|
différentes hiérarchies (si vous avez un noyau récent, vous pouvez utiliser les
|
||||||
|
cgroups-v2) dont vous allez avoir besoin pour limiter l'utilisation de
|
||||||
|
ressources.
|
||||||
|
|
||||||
|
Puis, mettez en place ces limites :
|
||||||
|
|
||||||
|
* pas plus d'1 GB de mémoire utilisée ;
|
||||||
|
* 1 seul CPU au maximum ;
|
||||||
|
* 100 PIDs ;
|
||||||
|
* ...
|
||||||
|
|
||||||
|
En bonus, vous pouvez gérer les cas où le noyau sur lequel s'exécute votre
|
||||||
|
moulinette ne possède pas tous ces *CGroup*s, au lieu de planter, ne rien faire
|
||||||
|
n'est pas forcément une mauvaise solution.
|
||||||
|
|
||||||
|
|
||||||
|
### Palier 2 : Réduire les *capabilities* (2 points)
|
||||||
|
|
||||||
|
Réduisez au maximum les *capabilities*, de telle sorte qu'il ne soit pas
|
||||||
|
possible de faire un ping dans l'environnement restreint :
|
||||||
|
|
||||||
|
<div lang="en-US">
|
||||||
|
```shell
|
||||||
|
42sh# ping 8.8.8.8
|
||||||
|
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
|
||||||
|
64 bytes from 8.8.8.8: icmp_seq=1 ttl=56 time=3.93 ms
|
||||||
|
64 bytes from 8.8.8.8: icmp_seq=2 ttl=56 time=3.97 ms
|
||||||
|
^C
|
||||||
|
--- 8.8.8.8 ping statistics ---
|
||||||
|
2 packets transmitted, 2 received, 0% packet loss, time 1002ms
|
||||||
|
rtt min/avg/max/mdev = 3.931/3.954/3.978/0.067 ms
|
||||||
|
|
||||||
|
42sh# ./mymoulette /bin/bash
|
||||||
|
bash# curl http://www.linuxcontainers.org/ | md5sum
|
||||||
|
59e714c4331e71ac3529a6502994ef1d
|
||||||
|
|
||||||
|
bash# ping 8.8.8.8
|
||||||
|
ping: icmp open socket: Permission denied
|
||||||
|
```
|
||||||
|
</div>
|
||||||
|
|
||||||
|
Astuces : `prctl(2)`, `capabilities(7)`, `capget(2)`, `capset(2)`, ...
|
||||||
|
|
||||||
|
Aidez-vous du visualisateur de *capabilities* de la partie 4, pour voir si vous
|
||||||
|
êtes sur la bonne voie.
|
||||||
|
|
||||||
|
|
||||||
|
### Palier 3 : Utilisable par un utilisateur (1 point)
|
||||||
|
|
||||||
|
Jouez avec les attributs étendus pour qu'un utilisateur non-privilégié puisse
|
||||||
|
exécuter votre moulinette. Ajoutez la/les commande(s) à votre Makefile ou
|
||||||
|
script d'installation.
|
||||||
|
|
||||||
|
|
||||||
|
### Création d'un environnement d'exécution minimal
|
||||||
|
|
||||||
|
Plutôt que d'utiliser votre système hôte au complet, avec tous ses programmes
|
||||||
|
et toutes ses bibliothèques, il faudrait utiliser un système contenant le
|
||||||
|
strict minimum. Recréez un environnement minimaliste, comme on a pu en voir
|
||||||
|
dans la partie sur les *chroot*.
|
||||||
|
|
||||||
|
**Ne mettez pas cet environnement dans votre tarball de rendu, il vous
|
||||||
|
sera seulement utile pour faire des tests.**
|
||||||
|
|
||||||
|
|
||||||
|
### Palier 4 : Isolation du pauvre (1 point)
|
||||||
|
|
||||||
|
Nous n'avons pas encore vu de meilleure méthode pour mieux isoler
|
||||||
|
l'environnement que de faire un `chroot`, ajoutez à votre programme cette
|
||||||
|
isolation rudimentaire. Et rendez-vous au prochain cours pour avoir une
|
||||||
|
meilleure isolation !
|
||||||
|
|
||||||
|
|
||||||
|
### Palier 5 (bonus) : automatisation de la création de l'environnement (5 points)
|
||||||
|
|
||||||
|
Pour *moulinéter* plusieurs étudiants en parallèle, vous allez avoir besoin de
|
||||||
|
plusieurs environnements identiques. Plutôt que de recopier cet environnement,
|
||||||
|
de le nettoyer, de le recréer, pour chaque étudiant, ajoutez à votre moulinette
|
||||||
|
un support pour LVM : utilisez des *snapshots* pour figer votre environnement
|
||||||
|
et le dupliquer facilement pour chaque étudiant.
|
||||||
|
|
||||||
|
L'usage est laissé à votre discrétion : vous pouvez ajouter un/des paramètres à
|
||||||
|
votre *moulette* pour indiquer le volume LVM à utiliser ou le définir en dur ou
|
||||||
|
encore séparer la création de l'environnement et de la snapshot initiale dans
|
||||||
|
un programme distinct.
|
@ -1 +0,0 @@
|
|||||||
../tutorial/4/project-body.md
|
|
93
subject/project-part2.md
Normal file
93
subject/project-part2.md
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
### Palier 5 : Une vraie isolation (3 points)
|
||||||
|
|
||||||
|
En plus du `chroot`, assignez de nouveaux *namespaces* au processus que vous
|
||||||
|
allez lancer : `cgroups`, `IPC`, `mount`, `net`, `PID`, `UTS`, `user`.
|
||||||
|
|
||||||
|
Il est requis que le nouveau processus ne puisse pas s'échapper de ses
|
||||||
|
*namespaces* !
|
||||||
|
|
||||||
|
Astuce : `unshare(2)`.
|
||||||
|
|
||||||
|
|
||||||
|
### Palier 6 : Empêcher les fuites d'information (2 points)
|
||||||
|
|
||||||
|
Démontez tous les systèmes de fichiers qui ne sont pas nécessaires au
|
||||||
|
fonctionnement de votre conteneur et remontez les partitions
|
||||||
|
|
||||||
|
N'oubliez pas de remonter les systèmes de fichiers pour lesquels cette
|
||||||
|
opération est nécessaire afin de terminer l'étape d'isolation.
|
||||||
|
|
||||||
|
Astuce : `mount(2)`.
|
||||||
|
|
||||||
|
|
||||||
|
### Palier 7 : Identification du conteneur (1 point)
|
||||||
|
|
||||||
|
Maintenant que vous avez votre conteneur, personalisez-le un peu en lui donnant
|
||||||
|
un nom unique.
|
||||||
|
|
||||||
|
Astuce : `sethostname(2)`
|
||||||
|
|
||||||
|
|
||||||
|
### Palier 8 : `pivot_root` (4 points)
|
||||||
|
|
||||||
|
Effectuez un `pivot_root(2)` de telle sorte qu'il ne reste plus de trace du
|
||||||
|
système de fichiers hôte.
|
||||||
|
|
||||||
|
Astuce : `pivot_root(2)`, `umount(2)`.
|
||||||
|
|
||||||
|
|
||||||
|
### Palier 9 : Bac à sable connecté (4 points)
|
||||||
|
|
||||||
|
Partant d'une liste d'interfaces sur la machine hôte similaire à :
|
||||||
|
|
||||||
|
<div lang="en-US">
|
||||||
|
```
|
||||||
|
42sh$ ip link
|
||||||
|
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1
|
||||||
|
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
|
||||||
|
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
|
||||||
|
link/ether 90:2b:34:5e:fa:a7 brd ff:ff:ff:ff:ff:ff
|
||||||
|
```
|
||||||
|
</div>
|
||||||
|
|
||||||
|
Vous devrez pouvoir `ping`er votre conteneur depuis votre hôte :
|
||||||
|
|
||||||
|
<div lang="en-US">
|
||||||
|
```
|
||||||
|
42sh$ ip address
|
||||||
|
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
|
||||||
|
[...]
|
||||||
|
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
|
||||||
|
[...]
|
||||||
|
3: veth3e06cad@if82: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP mode DEFAULT group default
|
||||||
|
link/ether 42:a2:a0:89:54:ef brd ff:ff:ff:ff:ff:ff
|
||||||
|
inet 10.10.10.41/24 brd 10.10.10.255 scope global veth3e06cad
|
||||||
|
valid_lft forever preferred_lft forever
|
||||||
|
42sh$ ping 10.10.10.42
|
||||||
|
PING 10.10.10.42 (10.10.10.42) 56(84) bytes of data.
|
||||||
|
64 bytes from 10.10.10.42: icmp_seq=1 ttl=56 time=3.90 ms
|
||||||
|
64 bytes from 10.10.10.42: icmp_seq=2 ttl=56 time=3.78 ms
|
||||||
|
^C
|
||||||
|
--- 10.10.10.42 ping statistics ---
|
||||||
|
2 packets transmitted, 2 received, 0% packet loss, time 1003ms
|
||||||
|
rtt min/avg/max/mdev = 3.789/3.847/3.906/0.085 ms
|
||||||
|
```
|
||||||
|
</div>
|
||||||
|
|
||||||
|
Dans l'exemple ci-dessus, l'interface dans le conteneur a l'IP `10.10.10.42`,
|
||||||
|
tandis que la machine hôte a l'IP `10.10.10.41`.
|
||||||
|
|
||||||
|
Astuces : vous pouvez utiliser la `libnetlink(3)` ou même faire des appels aux
|
||||||
|
programmes `ip(8)`, `brctl(8)`, ...
|
||||||
|
|
||||||
|
|
||||||
|
### Palier 10 (bonus) : seccomp (2 points)
|
||||||
|
|
||||||
|
Filtrez les appels systèmes de telle sorte qu'aucun programme exécuté dans
|
||||||
|
votre bac à sable ne puisse plus lancer les appels systèmes suivants :
|
||||||
|
|
||||||
|
* `nfsservctl(2)` ;
|
||||||
|
* `personality(2)` ;
|
||||||
|
* `pivot_root(2)`.
|
||||||
|
|
||||||
|
Astuce : `seccomp(2)`.
|
@ -1,88 +0,0 @@
|
|||||||
### Palier 1 : Restreindre l'environnement (2 points)
|
|
||||||
|
|
||||||
Après avoir mis en place les bases de votre programme, commencez par créer les
|
|
||||||
différentes hiérarchies (si vous avez un noyau récent, vous pouvez utiliser les
|
|
||||||
cgroups-v2) dont vous allez avoir besoin pour limiter l'utilisation de
|
|
||||||
ressources.
|
|
||||||
|
|
||||||
Puis, mettez en place ces limites :
|
|
||||||
|
|
||||||
* pas plus d'1 GB de mémoire utilisée ;
|
|
||||||
* 1 seul CPU au maximum ;
|
|
||||||
* 100 PIDs ;
|
|
||||||
* ...
|
|
||||||
|
|
||||||
En bonus, vous pouvez gérer les cas où le noyau sur lequel s'exécute votre
|
|
||||||
moulinette ne possède pas tous ces *CGroup*s, au lieu de planter, ne rien faire
|
|
||||||
n'est pas forcément une mauvaise solution.
|
|
||||||
|
|
||||||
|
|
||||||
### Palier 2 : Réduire les *capabilities* (2 points)
|
|
||||||
|
|
||||||
Réduisez au maximum les capabilities, de telle sorte qu'il ne soit pas possible
|
|
||||||
de faire un ping dans l'environnement restreint :
|
|
||||||
|
|
||||||
<div lang="en-US">
|
|
||||||
```shell
|
|
||||||
42sh# ping 8.8.8.8
|
|
||||||
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
|
|
||||||
64 bytes from 8.8.8.8: icmp_seq=1 ttl=56 time=3.93 ms
|
|
||||||
64 bytes from 8.8.8.8: icmp_seq=2 ttl=56 time=3.97 ms
|
|
||||||
^C
|
|
||||||
--- 8.8.8.8 ping statistics ---
|
|
||||||
2 packets transmitted, 2 received, 0% packet loss, time 1002ms
|
|
||||||
rtt min/avg/max/mdev = 3.931/3.954/3.978/0.067 ms
|
|
||||||
|
|
||||||
42sh# ./mymoulette /bin/bash
|
|
||||||
bash# curl http://www.linuxcontainers.org/ | md5sum
|
|
||||||
59e714c4331e71ac3529a6502994ef1d
|
|
||||||
|
|
||||||
bash# ping 8.8.8.8
|
|
||||||
ping: icmp open socket: Permission denied
|
|
||||||
```
|
|
||||||
</div>
|
|
||||||
|
|
||||||
Astuces : `prctl(2)`, `capabilities(7)`, `capget(2)`, `capset(2)`, ...
|
|
||||||
|
|
||||||
Aidez-vous du visualisateur de *capabilities* de la partie 4, pour voir si vous
|
|
||||||
êtes sur la bonne voie.
|
|
||||||
|
|
||||||
|
|
||||||
### Palier 3 : Utilisable par un utilisateur (1 point)
|
|
||||||
|
|
||||||
Jouez avec les attributs étendus pour qu'un utilisateur non-privilégié puisse
|
|
||||||
exécuter votre moulinette. Ajouter la/les commande(s) à votre Makefile ou
|
|
||||||
script d'installation.
|
|
||||||
|
|
||||||
|
|
||||||
### Création d'un environnement d'exécution minimal
|
|
||||||
|
|
||||||
Plutôt que d'utiliser votre système hôte au complet, avec tous ses programmes
|
|
||||||
et toutes ses bibliothèques, il faudrait utiliser un système contenant le
|
|
||||||
strict minimum. Recréez un environnement minimaliste, comme on a pu en voir
|
|
||||||
dans la partie sur les *chroot*.
|
|
||||||
|
|
||||||
**Ne mettez pas cet environnement dans votre tarball de rendu, il vous
|
|
||||||
sera seulement utile pour faire des tests.**
|
|
||||||
|
|
||||||
|
|
||||||
### Palier 4 : Isolation du pauvre (1 point)
|
|
||||||
|
|
||||||
Nous n'avons pas encore vu de meilleure méthode pour mieux isoler
|
|
||||||
l'environnement que de faire un `chroot`, ajouter à votre programme cette
|
|
||||||
isolation rudimentaire. Et rendez-vous au prochain cours pour avoir une
|
|
||||||
meilleure isolation !
|
|
||||||
|
|
||||||
|
|
||||||
### Palier 5 (bonus) : automatisation de la création de l'environnement (5 points)
|
|
||||||
|
|
||||||
Pour *moulinéter* plusieurs étudiants en parallèle, vous allez avoir besoin de
|
|
||||||
plusieurs environnements identiques. Plutôt que de recopier cet environnement,
|
|
||||||
de le nettoyer, de le recréer, pour chaque étudiant, ajoutez à votre moulinette
|
|
||||||
un support pour LVM : utiliser des *snapshots* pour figer votre environnement
|
|
||||||
et le dupliquer facilement pour chaque étudiant.
|
|
||||||
|
|
||||||
L'usage est laissé à votre discrétion : vous pouvez ajouter un/des paramètres à
|
|
||||||
votre *moulette* pour indiquer le volume LVM à utiliser ou le définir en dur ou
|
|
||||||
encore séparer la création de l'environnement et de la snapshot initiale dans
|
|
||||||
un programme distinct.
|
|
1
tutorial/3/project-body.md
Symbolic link
1
tutorial/3/project-body.md
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../subject/project-part1.md
|
@ -1,93 +0,0 @@
|
|||||||
### Stage 5 : Une vraie isolation (3 points)
|
|
||||||
|
|
||||||
En plus du `chroot`, assignez de nouveaux namespaces au processus que vous
|
|
||||||
allez lancer : CGroups, IPC, mount, net, PID, UTS, user.
|
|
||||||
|
|
||||||
Il est requis que le nouveau processus ne puisse pas s'échapper de ses
|
|
||||||
namespaces !
|
|
||||||
|
|
||||||
Astuce : `unshare(2)`.
|
|
||||||
|
|
||||||
|
|
||||||
### Stage 6 : Empêcher les fuites d'information (2 points)
|
|
||||||
|
|
||||||
Démonter tous les sytèmes de fichiers qui ne sont pas nécessaire au
|
|
||||||
fonctionnement de votre conteneur et remontez les partitions
|
|
||||||
|
|
||||||
N'oubliez pas de remonter les systèmes de fichiers pour lequel cette opération
|
|
||||||
est nécessaire pour terminer l'étape d'isolation.
|
|
||||||
|
|
||||||
Astuce : `mount(2)`.
|
|
||||||
|
|
||||||
|
|
||||||
### Stage 7 : Identification du conteneur (1 point)
|
|
||||||
|
|
||||||
Maintenant que vous avez votre conteneur, personalisez-le un peu en lui donnant
|
|
||||||
un nom unique.
|
|
||||||
|
|
||||||
Astuce : `sethostname(2)`
|
|
||||||
|
|
||||||
|
|
||||||
### Stage 8 : `pivot_root` (4 points)
|
|
||||||
|
|
||||||
Effectuer un `pivot_root(2)` de telle sorte qu'il ne reste plus de trace du
|
|
||||||
système de fichiers hôte.
|
|
||||||
|
|
||||||
Astuce : `pivot_root(2)`, `umount(2)`.
|
|
||||||
|
|
||||||
|
|
||||||
### Stage 9 : Bac à sable connecté (4 points)
|
|
||||||
|
|
||||||
Partant d'une liste d'interfaces sur la machine hôte similaire à :
|
|
||||||
|
|
||||||
<div lang="en-US">
|
|
||||||
```
|
|
||||||
42sh$ ip link
|
|
||||||
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1
|
|
||||||
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
|
|
||||||
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
|
|
||||||
link/ether 90:2b:34:5e:fa:a7 brd ff:ff:ff:ff:ff:ff
|
|
||||||
```
|
|
||||||
</div>
|
|
||||||
|
|
||||||
Vous devrez pouvoir `ping` votre conteneur depuis votre hôte :
|
|
||||||
|
|
||||||
<div lang="en-US">
|
|
||||||
```
|
|
||||||
42sh$ ip address
|
|
||||||
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
|
|
||||||
[...]
|
|
||||||
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
|
|
||||||
[...]
|
|
||||||
3: veth3e06cad@if82: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP mode DEFAULT group default
|
|
||||||
link/ether 42:a2:a0:89:54:ef brd ff:ff:ff:ff:ff:ff
|
|
||||||
inet 10.10.10.41/24 brd 10.10.10.255 scope global veth3e06cad
|
|
||||||
valid_lft forever preferred_lft forever
|
|
||||||
42sh$ ping 10.10.10.42
|
|
||||||
PING 10.10.10.42 (10.10.10.42) 56(84) bytes of data.
|
|
||||||
64 bytes from 10.10.10.42: icmp_seq=1 ttl=56 time=3.90 ms
|
|
||||||
64 bytes from 10.10.10.42: icmp_seq=2 ttl=56 time=3.78 ms
|
|
||||||
^C
|
|
||||||
--- 10.10.10.42 ping statistics ---
|
|
||||||
2 packets transmitted, 2 received, 0% packet loss, time 1003ms
|
|
||||||
rtt min/avg/max/mdev = 3.789/3.847/3.906/0.085 ms
|
|
||||||
```
|
|
||||||
</div>
|
|
||||||
|
|
||||||
Dans l'exemple ci-dessus, l'interface dans le conteneur a l'IP `10.10.10.42`,
|
|
||||||
tandis que la machine hôte a l'IP `10.10.10.41`.
|
|
||||||
|
|
||||||
Astuces : vous pouvez utiliser la `libnetlink(3)` ou même faire des appels aux
|
|
||||||
programmes `ip(8)`, `brctl(8)`, ...
|
|
||||||
|
|
||||||
|
|
||||||
### Stage 10 (bonus) : seccomp (2 points)
|
|
||||||
|
|
||||||
Filtrez les appels systèmes de telle sorte qu'aucun programme exécuté dans
|
|
||||||
votre bac à sable ne puisse plus appeler les appels systèmes suivants :
|
|
||||||
|
|
||||||
* `nfsservctl(2)` ;
|
|
||||||
* `personality(2)` ;
|
|
||||||
* `pivot_root(2)`.
|
|
||||||
|
|
||||||
Astuce : `seccomp(2)`.
|
|
Loading…
Reference in New Issue
Block a user