Compare commits

...

10 Commits

Author SHA1 Message Date
Julien Palard c45632067b
Proofread Makefile. 2023-01-24 14:43:30 +01:00
Julien Palard caf3ee3017 Hello i18n. 2023-01-24 14:13:26 +01:00
Julien Palard cad60f2f32 formations 2023-01-23 11:24:39 +01:00
Julien Palard da952acb46 Mobian issue 2023-01-13 10:19:30 +01:00
Julien Palard 482c6741de bookmarks 2023-01-13 10:19:14 +01:00
Julien Palard e4b78d02ba Add a title. 2022-11-27 16:37:38 +01:00
Julien Palard 56a0c0dc9a typo 2022-11-27 16:36:39 +01:00
Julien Palard 017f782d49 Campus du libre. 2022-11-27 16:36:03 +01:00
Julien Palard 440452a8fc Usefull link. 2022-11-27 16:35:57 +01:00
Julien Palard 86aebaa08c Django isup 2022-11-06 12:13:39 +01:00
12 changed files with 410 additions and 36 deletions

3
.gitignore vendored
View File

@ -2,3 +2,6 @@
.venv/
output/
__pycache__/
Flex/
pelican-plugins/
.envrc

View File

@ -8,9 +8,9 @@ OUTPUTDIR=$(BASEDIR)/output
CONFFILE=$(BASEDIR)/pelicanconf.py
PUBLISHCONF=$(BASEDIR)/publishconf.py
SSH_HOST=51.15.187.166
SSH_HOST=mdk.fr
SSH_PORT=22
SSH_USER=mdk_fr
SSH_USER=mdk
SSH_TARGET_DIR=/var/www/mdk.fr/
@ -35,7 +35,6 @@ help:
@echo ' make serve [PORT=8000] serve site at http://localhost:8000'
@echo ' make serve-global [SERVER=0.0.0.0] serve (as root) to $(SERVER):80 '
@echo ' make devserver [PORT=8000] serve and regenerate together '
@echo ' make ssh_upload upload the web site via SSH '
@echo ' make rsync_upload upload the web site via rsync+ssh '
@echo ' '
@echo 'Set the DEBUG variable to 1 to enable debugging, e.g. make DEBUG=1 html '
@ -45,13 +44,16 @@ help:
Flex/.git/config:
git clone --depth 1 https://github.com/alexandrevicenzi/Flex
html: Flex/.git/config
pelican-plugins/.git/config:
git clone --depth 1 https://github.com/getpelican/pelican-plugins
html: Flex/.git/config pelican-plugins/.git/config
$(PELICAN) $(INPUTDIR) -o $(OUTPUTDIR) -s $(CONFFILE) $(PELICANOPTS)
clean:
[ ! -d $(OUTPUTDIR) ] || rm -rf $(OUTPUTDIR)
regenerate: Flex/.git/config
regenerate: Flex/.git/config pelican-plugins/.git/config
$(PELICAN) -r $(INPUTDIR) -o $(OUTPUTDIR) -s $(CONFFILE) $(PELICANOPTS)
serve:
@ -76,12 +78,9 @@ else
$(PELICAN) -lr $(INPUTDIR) -o $(OUTPUTDIR) -s $(CONFFILE) $(PELICANOPTS)
endif
publish: Flex/.git/config
publish: Flex/.git/config pelican-plugins/.git/config
$(PELICAN) $(INPUTDIR) -o $(OUTPUTDIR) -s $(PUBLISHCONF) $(PELICANOPTS)
ssh_upload: publish
scp -P $(SSH_PORT) -r $(OUTPUTDIR)/* $(SSH_USER)@$(SSH_HOST):$(SSH_TARGET_DIR)
rsync_upload: publish
rsync -e "ssh -p $(SSH_PORT)" -P -rvzc --cvs-exclude $(OUTPUTDIR)/ $(SSH_USER)@$(SSH_HOST):$(SSH_TARGET_DIR)

View File

@ -0,0 +1,90 @@
---
Title: Black screen at boot on my PinePhone
Date: 2023-01-13 09:33:00
Summary: My phone was no longer booting…
---
OK so today my [PinePhone](https://fr.wikipedia.org/wiki/PinePhone)
does no longer boot, it goes like this:
- Press power button to boot it,
- type rootfs passphrase (I use full disk encryption),
- Mobian "spash screen" for a short time,
- black screen, and that's it.
My first bet was a graphical issue due to a recent upgrade ("sweet"
memories of Ubuntu failing to start its X server after almost any
upgrade...) so I try to ssh to it first... "no route to host", damned!
It don't have its IP yet so it failed before network setup.
But it's a PinePhone, and it runs
[Mobian](https://mobian-project.org/), a Debian for mobiles, so I'm
not in the dark, let's read the boot logs first before going down the
rabbit hole of connecting a UART on the jack port to debug it over
serial:
- Press power button,
- type rootfs passphrase again,
- press a volume button to get rid of the Mobian splash to see logs
```text
The root filesystem on /dev/mapper/calamares_crypt requires a manual fsck
```
OK!
Looks easy, but without a keyboard? Let's mount the
[eMMC](https://en.wikipedia.org/wiki/MultiMediaCard#eMMC) over USB!
As my phone boots using [Tow-Boot](https://tow-boot.org/) it's easy:
- Shut it down (~8s on the power button).
- Plug it to laptop with a USB-C cable.
- Make it enter "USB Mass Storage mode" (by holding the
volume up button at startup before and during the second
vibration).
- Instantly my laptop sees it and udisks auto mounts it, gnome asks
for main partition passphrase to mount it too, nice!
- Boom, it disappears... and on `journalctl -e` I see `usb 1-5: device
descriptor read/64, error -71` ... `I/O error, dev sda` ...
At this point I think there's just two options: either my USB-C cable
was badly plugged, or my eMMC is dead. I vote for the USB-C cable
issue and try again.
- Rebooting phone in USB mass storage mode again, but this time
without giving my passphrase to avoid automount: it
needs an fsck anyway.
- I can browse `/media/mdk/boot` and see no read error in `sudo journalctl -f`.
- `sudo fdisk -l /dev/sda` sees ~30GiB and both partitions.
I use encryption so to fsck the root partition, I have to use `cryptsetup` first:
```bash
$ sudo cryptsetup open /dev/sda2 mobian # it asks for my passphrase
$ file /dev/mapper/mobian # That's the unencrypted view of my partition
/dev/mapper/mobian: symbolic link to ../dm-0
$ sudo fdisk -l /dev/mapper/mobian # Just out of curiosity
Disk /dev/mapper/mobian : 28.47 GiB, 30574379008 octets, 59715584 secteurs
$ sudo fsck /dev/mapper/mobian # Running fsck manually!
fsck from util-linux 2.38.1
e2fsck 1.46.6-rc1 (12-Sep-2022)
root contains a file system with errors, check forced.
[many many errors]
$ sudo mount /dev/mapper/mobian /mnt # To check if it works
$ ls /mnt # Yeah!
bin boot dev etc home lib lost+found media mnt opt proc root run sbin srv sys tmp usr var
$ sudo umount /mnt
$ sudo cryptsetup close mobian
```
It looks OK, let's reboot the phone...
It works!!!
I know, your grandma would not be able to do fix it that way (mine
neither), but I'm still very happy to be able to fix my phone myself
when it has issues.
What would people do when a phone does no longer boot? Buy another?

View File

@ -140,7 +140,6 @@ Date: 2021-05-05 15:21:00
## Cybersecurity/OSINT
- [The OSINT Framework](https://osintframework.com/)
- [This tool allows you to enumerate usernames across many websites](https://whatsmyname.app/)
- [OSINT Tool Comparison Table](https://docs.google.com/spreadsheets/d/18U1qcaPaqIF8ERVLI-g5Or3gUbv0qP_-JUtc0pbEs0E/edit#gid=0)
- [Have I been Pwned (« Have them been pwned :D »)](https://haveibeenpwned.com/)
- [theHarvester — E-mails, subdomains and names Harvester](https://github.com/laramies/theHarvester)
@ -160,6 +159,12 @@ Date: 2021-05-05 15:21:00
- [MetaGooFil — Metadata Harvester (old, python2)](https://github.com/laramies/metagoofil)
- [SpiderFoot — SpiderFoot automates OSINT for threat intelligence and mapping your attack surface.](https://github.com/smicallef/spiderfoot)
- [Machinae — Security Intelligence Collector](https://github.com/HurricaneLabs/machinae)
- [Sociétés Françaises](https://annuaire-entreprises.data.gouv.fr)
### Cybersecurity/OSINT/User enumeration
- [Whatsmyname — This tool allows you to enumerate usernames across many websites](https://whatsmyname.app/)
- [Sherlock — Can be used to find usernames across many social networks](https://sherlock-project.github.io/)
### Cybersecurity/OSINT/DNS Enumeration

View File

@ -0,0 +1,108 @@
status: hidden
title: Python — Django isup
slug: inuik9Ah-django-isup
robots: noindex
Le nom du rendu est `isup`, le protocole de rendu est
[](https://mdk.fr/pages/obiree2uaza2sh-rendu.html).
Le nom du projet Django est libre, l'app Django doit s'appeler `isup`.
## Survol
Votre projet sera composé de :
- Au moins deux modèles : `Domain` et `Check`.
- Un `Domain` est lié à un `django.contrib.auth.User` (son propriétaire) via une `models.ForeignKey`.
- Un `Domain` contient au minimum :
- `name` ou `domain` (le nom de domaine),
- `is_up` (booléen à True si le site est accessible),
- `since` qui indique depuis quand le site est up ou down.
- Un `Check` est lié à un domaine (un domaine peut avoir plusieurs checks).
- Un `Check` contient au minimum :
- La date de vérification,
- un booléen `is_up`
- un message d'explication comme « HTTPS certificate expired », « Timeout », « Up », ...
- Au moins une vue Django pour la page d'accueil.
- De quoi [créer un
compte](https://docs.djangoproject.com/en/4.0/topics/auth/default/#django.contrib.auth.forms.UserCreationForm)
(via Django, pas forcément via l'API), car seuls les utilisateurs
loggés peuvent créer des domaines (qui leur appartiendront).
- `djangorestframework` pour gérer la sérialisation des modèles, les permissions, les vues d'API, les routes d'API.
## L'API
Je m'attends à pouvoir utiliser votre API de cette manière :
```text
GET /api/domains/ # Lister tous les domaines connus et leurs état (avec de la pagination si nécessaire).
POST /api/domains/ -d '{"domain": "mdk.fr"}' # Pour ajouter un nom de domaine (qui appartient à celui qui fait le POST).
GET /api/domains/1/ # Afficher les informations du premier domaine.
PUT /api/domains/1/ # Modifier le domaine 1, seulement autorisé si j'en suis propriétaire.
DELETE /api/domains/1/ # Supprimer le domaine 1, seulement autorisé si j'en suis propriétaire.
GET /api/checks/ # Lister toutes les vérifications qui ont été effectuées.
GET /api/checks/?domain=1 # Lister toutes les vérifications effectuées pour le domaine 1.
GET /api/checks/1 # Afficher le check d'id 1.
```
Les checks sont en lecture seule, donc pas de `POST`, `PUT`, `DELETE` dessus.
Si vous voulez que votre API soit REST, la représentation d'un domaine **doit** contenir un lien vers ses `checks` :
```json
{
"domain": "mdk.fr",
"is_up": true,
"checks_url": "http://localhost:8000/uptime/checks/?domain=1",
"url": "http://localhost:8000/uptime/domains/1/"
}
```
## Vérification périodique des domaines connus.
Vous utiliserez une
[Management Command](https://docs.djangoproject.com/en/3.2/howto/custom-management-commands/)
pour mettre à jour votre table, c'est là que votre script implémenté en cours sera utile.
La commande peut s'appeler `check` par exemple. Sur un serveur de
prod, le serveur devra l'appeler périodiquement, par exemples toutes
les 5mn, via un
[timer](https://www.freedesktop.org/software/systemd/man/systemd.timer.html)
ou un [cron](https://manpages.debian.org/bullseye/cron/crontab.5.en.html).
En dev vous pouvez simplement lancer `python manage.py check` à la
main de temps en temps.
Cette commande doit lancer une nouvelle vérification de **tous** les
domaines connus, chaque résultat (up ou down) doit être documenté dans
le modèle `Checks`.
## La page d'accueil
La page d'accueil doit être la plus "Django-less" possible :
- Une simple route.
- Une simple vue d'une seule ligne avec `render`.
- Un template avec au besoin du HTML, du JS, du CSS mais **pas** de templating Django (pas de `{{`, pas de `{%`).
Vous êtes autorisés à stocker le JS et le CSS en
[statique](https://docs.djangoproject.com/en/4.0/howto/static-files/),
mais je n'ai rien contre tout mettre dans le même fichier vu que je
suis dev back #sinvergüenza.
Quand je dis « Django-less » je veux dire que le front doit pouvoir
fonctionner en dehors de Django, et que dans un vrai projet avec une
équipe *front* et une équipe *back* j'aimerai que cette home, ce JS,
et ce CSS puisse être géré dans un autre repo, sans qu'à aucun moment
les devs front n'aient besoin de savoir que c'est du Django côté back.
Vous pouvez donc utiliser le framework front à la mode cette semaine.
Pour récupérer la liste des noms de domaines et leur état, le front
devra donc utiliser l'API. Pas besoin d'être loggé pour ça, on ne
modifie rien, on ne fait que consulter, keep it simple stupid.

View File

@ -0,0 +1,10 @@
Title: Formations
Date: 2023-01-17 15:41:00
Développeur Python depuis 2009, formateur Python depuis 2015, je
propose ces formations :
- [Python initiation]({filename}/pages/python-initiation.md)
- [Python avancé]({filename}/pages/python-avancé.md)
Intéressés ? Contactez-moi par email : julien at palard.fr.

23
content/pages/index.en.md Normal file
View File

@ -0,0 +1,23 @@
Title: Julien Palard
Date: 2016-05-28
description: Julien Palard - mdk.fr
status: hidden
lang: en
URL:
save_as: index.html
CPython core developer, PSF fellow, independent Python trainer.
My projects:
- I build an interactive Python learning tool: [hackinscience.org](https://hackinscience.org/), it's free and [open-source](https://framagit.org/hackinscience/).
- I help translating the [Python documentation in French](https://docs.python.org/fr/) (come and help [here](https://github.com/python/python-docs-fr)).
- Other projects on [AFPy's gitea](https://git.afpy.org/mdk) and [my github](https://github.com/JulienPalard).
If you want to get in touch:
- By email: <a href=mailto:julien@palard.fr>julien@palard.fr</a>.
- On [Mastodon](https://joinmastodon.org): [@mdk@mamot.fr](https://mamot.fr/@mdk)
- On [IRC](https://web.libera.chat/#python-fr): `mdk`.
- Using [XMPP](https://xmpp.chapril.org/i/mdk@chapril.org): <a href=xmpp:mdk@chapril.org>mdk@chapril.org</a>.
- Here is My [GPG key](/Julien-Palard.pdf) and my [SSH keys](/id_rsa.pub).

View File

@ -2,20 +2,22 @@ Title: Julien Palard
Date: 2016-05-28
description: Julien Palard - mdk.fr
status: hidden
lang: fr
URL:
save_as: index.html
CPython core developer, PSF fellow, independent Python trainer.
Formateur Python indépendant, CPython core developer, PSF fellow.
My projects:
Mes projets:
- I build an interactive Python learning tool: [hackinscience.org](https://hackinscience.org/), it's free and [open-source](https://framagit.org/hackinscience/hkis-website).
- I help translating the [Python documentation in French](https://docs.python.org/fr/) (come and help [here](https://github.com/python/python-docs-fr)).
- Other projects on [AFPy's gitea](https://git.afpy.org/mdk) and [my github](https://github.com/JulienPalard).
- Je travaille sur un site dapprentissage de la programmation interactif : [hackinscience.org](https://hackinscience.org/).
- J'aide à la traduction de la [documentation de Python en Français](https://docs.python.org/fr/) (pour participer c'est [ici](https://git.afpy.org/AFPy/python-docs-fr)).
- Mes autres projets sont sur la [forge de l'AFPy](https://git.afpy.org/mdk) et sur [mon github](https://github.com/JulienPalard).
If you want to get in touch:
Pour me contacter :
- I'm [@mdk@mamot.fr](https://mamot.fr/@mdk) on [Mastodon](https://joinmastodon.org).
- I'm `mdk` on [IRC](https://web.libera.chat/#python-fr)
- I'm <a href=xmpp:mdk@chapril.org>mdk@chapril.org</a> on [XMPP](https://xmpp.chapril.org/i/mdk@chapril.org).
- I'm <a href=mailto:julien@palard.fr>julien@palard.fr</a> by email.
- Par email : <a href=mailto:julien@palard.fr>julien@palard.fr</a>.
- Sur [Mastodon](https://joinmastodon.org) : [@mdk@mamot.fr](https://mamot.fr/@mdk).
- Sur [irc://libera.chat](https://web.libera.chat/#python-fr) : `mdk`.
- Sur [XMPP](https://xmpp.chapril.org/i/mdk@chapril.org) <a href=xmpp:mdk@chapril.org>mdk@chapril.org</a>.
- Voilà ma [clé GPG](/Julien-Palard.pdf) et ma [clé SSH](/id_rsa.pub).

View File

@ -0,0 +1,61 @@
Title: Python avancé
Date: 2023-01-17 15:41:00
Cest la seconde de mes deux formations Python. Alors que la
[formation *initiation*]({filename}/pages/python-initiation.md)
enseigne lutilisation des classes et bibliothèques pour créer des
programmes simples, la formation *Python avancé*, de lautre côté du
miroir, enseigne la création de ces classes et bibliothèques pour
créer des bibliothèques réutilisables dans des programmes
arbitrairement complexes.
## Objectifs
À la fin de cette seconde formation les stagiaires maîtrisent Python
dans lobjectif de produire un code *lisible*, *maintenable*, et
*testé* sur tout type de projet.
Laccent est mis sur le partage et la réutilisation du code :
- Création de bibliothèque (modules, paquets).
- Packaging et distribution de ces bibliothèques.
- Gestion des dépendances dune bibliothèque et dun lutilisant.
- Test et documentation dune bibliothèque packagée.
## Prérequis
Le pré-requis de ce module est davoir suivi, ou davoir un niveau
équivalent, à la formation [Python
*initiation*]({filename}/pages/python-initiation.md), cest-à-dire :
être capable de lire et de modifier du Python, être capable de
résoudre des problèmes simples en Python.
## Le contenu
- Les différents protocoles de Python (le protocole ditération, « les dunder », …).
- Les classes et leurs instances (où on parle de la MRO, de `super()`, …).
- Le protocole descripteur.
- Le *garbage collector*.
- Les *floats* et lIEEE 754.
- Créer et gérer les exceptions, le `else` et le `finally` du `try`.
- Les gestionnaires de contexte.
- Les décorateurs.
- Les listes en compréhension.
- Lopérateur *walrus* (`:=`).
- Lencodage des chaînes de caractères.
- Le packaging (`pyproject.toml`, `python -m build`, `twine`, …).
- Lasynchrone avec `async` et `await`.
## Durée
Cette formation se déroule idéalement en cinq jours, mais elle est
réalisable en 3 jours.
## Contact
Pour en savoir plus, contactez-moi par email : julien at palard.fr.

View File

@ -0,0 +1,42 @@
Title: Python initiation
Date: 2023-01-17 15:41:00
Cest la première des deux formations Python que je propose,
accessible sans prérequis.
## Objectifs
À la fin de cette formation les stagiaires ont les bases de Python et
sont capable de produire des programmes simples, de maintenir et faire
évoluer des programmes existants.
- Implémenter un programme simple résolvant un problème bien défini.
- Lire, comprendre, et modifier le code dun autre développeur Python.
- Rédiger des tests.
## Le contenu
- Les types natifs (`bool`, `int`, `float`, `str`, …)
- Les opérateurs
- Les variables
- Les fonctions
- Les instructions (`for`, `if`, `while`, …)
- Les méthodes
- La notation en compréhension
- Les *slices*
- Les classes
- `pip` et les `venvs`
- Le packaging
- Les bonnes pratiques
## Durée
Cette formation se déroule idéalement en trois jours.
## Contact
Pour en savoir plus, contactez-moi par email : julien at palard.fr.

View File

@ -4,6 +4,11 @@ status: hidden
## Past
- 2022-11-26:
[Campus du Libre](https://www.campus-du-libre.org/): Démo d'HackInScience
[video](https://bbb.afpy.org/playback/presentation/2.3/62dfb87e2dfcc5d2947bceb86a2324d10dfdd55b-1669457837244),
[slides](https://mdk.fr/hkis-au-campus-du-libre).
- 2021-04-15:
[AFPy](https://discuss.afpy.org/t/en-attendant-la-pyconfr-du-15-avril-2021/222/3): Bash — trucs et astuces
[video](https://bbb.afpy.org/playback/presentation/2.0/playback.html?meetingId=fb67608c847ace007f60e5b9fa6917ff7040b495-1618502029253).

View File

@ -1,5 +1,6 @@
from datetime import date
AUTHOR = "Julien Palard"
SITENAME = "mdk.fr"
SITETITLE = "Julien Palard"
@ -15,16 +16,48 @@ DISABLE_URL_HASH = True
FAVICON = "/images/favicon.png"
DISPLAY_PAGES_ON_MENU = False
MAIN_MENU = False
MAIN_MENU = True
MENUITEMS = (
("Formations", "/pages/formations.html"),
("Conférences", "/pages/talks.html"),
("Articles", "/blog/"),
)
LINKS = (
("Blog", "/blog/"),
("My Talks", "/pages/talks.html"),
("My CV", "/Julien-Palard.pdf"),
("My SSH keys", "/id_rsa.pub"),
("My GPG key", "/pages/gpg.html"),
)
# Social widget
SOCIAL = (
("mastodon", "https://mamot.fr/@mdk"),
("github", "https://github.com/julienpalard"),
("stack-overflow", "https://stackoverflow.com/users/232831/julien-palard"),
("rss", "/feeds/all.atom.xml"),
)
# Path to Plugins
PLUGIN_PATHS = ['pelican-plugins']
# Enable i18n plugin, probably you already have some others here.
PLUGINS = ['i18n_subsites']
# Enable Jinja2 i18n extension used to parse translations.
JINJA_ENVIRONMENT = {'extensions': ['jinja2.ext.i18n']}
I18N_TEMPLATES_LANG = "en"
# Match languages for other configs.
OG_LOCALE = "fr_FR"
LOCALE = ("fr_FR", "fr_FR.utf8")
# Your language.
DEFAULT_LANG = "fr_FR"
I18N_SUBSITES = {
'en': {
'SITENAME': 'English Julien Palard',
'LOCALE': 'en_US',
'THEME_STATIC_DIR': '../theme'
}
}
PATH = "content"
TIMEZONE = "Europe/Paris"
@ -38,27 +71,20 @@ TRANSLATION_FEED_ATOM = None
AUTHOR_FEED_ATOM = None
AUTHOR_FEED_RSS = None
THEME_COLOR = "dark"
THEME_COLOR = "light"
THEME_COLOR_AUTO_DETECT_BROWSER_PREFERENCE = True
THEME_COLOR_ENABLE_USER_OVERRIDE = True
THEME_COLOR_ENABLE_USER_OVERRIDE = False
PYGMENTS_STYLE = "emacs"
PYGMENTS_STYLE_DARK = "monokai"
# Social widget
SOCIAL = (
("mastodon", "https://mamot.fr/@mdk"),
("github", "https://github.com/julienpalard"),
("stack-overflow", "https://stackoverflow.com/users/232831/julien-palard"),
("rss", "/feeds/all.atom.xml"),
)
USE_GOOGLE_FONTS = False
DEFAULT_PAGINATION = 10
THEME = "Flex"
THEME_STATIC_DIR = "theme"
ARTICLE_URL = "{category}/{slug}.html"
STATIC_PATHS = ["images"]
ARTICLE_SAVE_AS = "{category}/{slug}.html"
CATEGORY_URL = "{slug}/"
CATEGORY_SAVE_AS = "{slug}/index.html"