# HackInScience
Julien Palard CPython core dev # C'est historique. Tu ne peux pas dire qu'HackInScience n'est pas né en 2014, parce que c'est historique. ## Enseigner le Python J'ai l'habitude. Mais à des groupes de ~6 pendant ~3 jours. ## C'est green ![Ruby Rhod](static/ruby-rhod.jpg) ## Enseigner le Python Un jour on m'a proposé un groupe de 50 pendant 7 jours. ## C'est pas green ![Ruby Rhod étranglé](static/pas-green.jpg) ## Mais on est devs Alors on a automatisé tout ce qui pouvait l'être. ::: notes Pour passer du temps avec ceux qui en ont besoin. # HackInScience.org C'est un petit Django, avec un peu de celery. ::: notes Pour répartir les corrections sur des machines qui ne font que ça. ## Démo en prod ! https://hackinscience.org ::: notes Faire un tour côté teams, et un tour côté admin aussi ! ## C'est moche ! J'ai dit que j'étais dev, pas dev front, toute aide est la bienvenue. ::: notes c'est du bootstrap. ## Je veux voir le code ! La première version fonctionnelle : 181 lignes de Python. Ça devrait loger dans quelques slides ;) ::: notes Aujourd'hui c'est 2700 lignes de code… ## Django models ```python class Exercise(models.Model): title = models.CharField(max_length=255) check = models.TextField() wording = models.TextField() ``` ::: notes Si vous connaissez déjà Django, concentrez-vous sur le contenu. ## Django models Un modèle Django c'est pas just pour l'ORM, ça aide à générer : - des migrations de DB ; - l'interface d'admin ; - les formulaires ; - les vues ; - l'API ; - l'autocomplétion dans l'IDE . - les requêtes SQL (l'ORM). ::: notes Un modèle permet au code de connaître de la structure de la base de donnée. Il n'est plus aveugle. C'est bien. ## Django view ```python class ExerciseListView(LoginRequiredMixin, ListView): model = Exercise template_name = "hkis/exercises.html" ``` ::: notes Vous saviez que la MRO de Python garanti un héritage de gauche à droite ? Ici il est garanti que les méthodes surchargées par `LoginRequiredMixin` sont exécutées avant celles de `ListView`. ## Django view ```python class ExerciseView(LoginRequiredMixin, DetailView): model = Exercise template_name = "hkis/exercise.html" ``` ## Une petite API ```python class ExerciseSerializer(serializers.HyperlinkedModelSerializer): class Meta: model = Exercise fields = '__all__' class ExerciseViewSet(viewsets.ModelViewSet): queryset = Exercise.objects.all() serializer_class = ExerciseSerializer router = routers.DefaultRouter() router.register('exercises', ExerciseViewSet) ``` ::: notes Pourquoi un "Router" ? Parce que derrière cette ViewSet il y a plein de vues ! Démo time ! ## Une interface d'admin ```python from django.contrib import admin from website.models import Answer, Exercise admin.site.register(Answer) admin.site.register(Exercise) ``` ::: notes Démo time ! # C'est utilisé ? Je n'ai pas de « pisteur », mais j'ai une DB. En octobre 2022 : 730 personnes ont résolu 10_780 exercices La moulinette a corrigé près de 50k rendus. ::: notes Google Analytics c'est illégal. Mais je sais écrire du SQL. Aucun tracker, aucune pub, aucun asset externe. 10k c'est peu ou beaucoup, je ne sais pas. ## Ça tient la charge ? Les exercices sont corrigés en environ 200ms, Deux serveurs se répartissent le travail (et ils s'ennuient). Les boucles infinies sont interrompues après 20s. ::: notes Il est très facile d'ajouter un serveur de correction au besoin. # Côté sécu Le code de chaque exercice est exécuté côté serveur, c'est un challenge niveau sécurité. ::: notes Python est réputé pour ne pas être sandboxable, du moins pas depuis l'intérieur de l'interpréteur. ## Namespaces Linux + seccomp + rlimit Les exercices sont exécutés dans des environements très restreints. ## seccomp `seccomp` (*secure computing*) c'est un outil du kernel Linux pour limiter les appels systèmes que peuvent faire les programmes. ## rlimit `rlimit` (*resource limit*) c'est un moyen de limiter les resources utilisées par un programme. On limite par exemple à 20s de CPU, 2000 threads, 100 fichiers ouverts, 1GB de RAM, …. ## namespaces C'est aussi une fonctionalité du kernel Linux, elle permet de faire croire à un processus qu'il a une ressource « juste pour lui ». ## C'est compliqué Configurer setccomp, rlimit, les namespaces, la vie et le reste correctement, c'est pas simple. Nous on utilise [firejail](https://github.com/netblue30/firejail). ## C'est simple Un petit appercu de comment on lance firejail : ```python FIREJAIL_OPTIONS = [ "--net=none", "--shell=none", "--x11=none", "--private-dev", "--private-tmp", "--caps.drop=all", "--nonewprivs", "--nosound", "--no3d", "--noroot", "--seccomp", ... ``` ::: notes C'est rassurant écrit comme ça, mais on sait que rien n'est parfait… # La rédaction d'exercices ## Via l'interface d'admin ## Via un repo git # L'hébergement d'instances locales # L'API # L'AFPy La PyConFr # Gandi # Questions - Mastodon : [@mdk@mamot.fr](https://mamot.fr/@mdk) - XMPP : mdk@chapril.org - HTTP : https://mdk.fr - SMTP : julien@python.org - Whatsapp : HAHAHA jamais.