Extract project outside tuto

This commit is contained in:
nemunaire 2017-11-09 01:26:51 +01:00
parent 453e7edcb9
commit 21dc57ade4
4 changed files with 182 additions and 183 deletions

View File

@ -1 +0,0 @@
../tutorial/3/project-body.md

88
subject/project-part1.md Normal file
View 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.

View File

@ -1 +0,0 @@
../tutorial/4/project-body.md

93
subject/project-part2.md Normal file
View 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)`.

View File

@ -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
View File

@ -0,0 +1 @@
../../subject/project-part1.md

View File

@ -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)`.