linux:rewinged
Différences
Ci-dessous, les différences entre deux révisions de la page.
| Les deux révisions précédentesRévision précédenteProchaine révision | Révision précédente | ||
| linux:rewinged [2026/09/12 07:32] – root | linux:rewinged [2026/09/18 17:40] (Version actuelle) – [13.2 Règles personnalisées] root | ||
|---|---|---|---|
| Ligne 130: | Ligne 130: | ||
| Restart=on-failure | Restart=on-failure | ||
| RestartSec=5 | RestartSec=5 | ||
| + | |||
| + | # Journalisation vers fichier, pour collecte Wazuh en JSON natif | ||
| + | StandardOutput=append:/ | ||
| + | StandardError=append:/ | ||
| # Durcissement | # Durcissement | ||
| Ligne 141: | Ligne 145: | ||
| MemoryDenyWriteExecute=true | MemoryDenyWriteExecute=true | ||
| ReadOnlyPaths=/ | ReadOnlyPaths=/ | ||
| - | ReadWritePaths=/ | + | ReadWritePaths=/ |
| [Install] | [Install] | ||
| Ligne 148: | Ligne 152: | ||
| <code bash> | <code bash> | ||
| + | mkdir -p / | ||
| + | chown rewinged: | ||
| + | |||
| systemctl daemon-reload | systemctl daemon-reload | ||
| systemctl enable --now rewinged | systemctl enable --now rewinged | ||
| systemctl status rewinged | systemctl status rewinged | ||
| </ | </ | ||
| + | |||
| + | Rotation du journal : | ||
| + | |||
| + | <file - / | ||
| + | / | ||
| + | daily | ||
| + | rotate 30 | ||
| + | compress | ||
| + | missingok | ||
| + | notifempty | ||
| + | copytruncate | ||
| + | su rewinged rewinged | ||
| + | } | ||
| + | </ | ||
| ===== 4. Pare-feu de la VM ===== | ===== 4. Pare-feu de la VM ===== | ||
| Ligne 253: | Ligne 274: | ||
| Forgejo. | Forgejo. | ||
| - | ==== 7.1 Rechargement | + | ==== 7.1 Rechargement |
| - | Vérifier d' | + | rewinged |
| - | dans ''/ | + | Confirmé au démarrage du service : |
| - | < | + | < |
| - | curl -s http://10.0.0.20:8080/ | + | {" |
| </ | </ | ||
| - | | + | **Conséquence** : aucun redémarrage |
| - | simple (7.2) | + | L' |
| - | * **404** : un redémarrage est nécessaire après | + | '' |
| - | | + | |
| ==== 7.2 Script de synchronisation ==== | ==== 7.2 Script de synchronisation ==== | ||
| Ligne 271: | Ligne 291: | ||
| <file bash / | <file bash / | ||
| #!/bin/bash | #!/bin/bash | ||
| - | set -e | + | # |
| - | cd /srv/winget | + | # Synchronise le depot de paquets depuis Forgejo. |
| + | # Execute par winget-sync.timer sous le compte rewinged. | ||
| + | # | ||
| + | set -euo pipefail | ||
| - | BEFORE=$(runuser -u rewinged -- git rev-parse HEAD) | + | REPO_DIR="/ |
| + | BRANCH=" | ||
| - | runuser -u rewinged -- git pull --ff-only | + | cd " |
| - | runuser -u rewinged -- git lfs pull | + | |
| - | AFTER=$(runuser | + | BEFORE=$(git rev-parse HEAD) |
| + | |||
| + | git fetch origin " | ||
| + | git merge --ff-only " | ||
| + | git lfs pull origin | ||
| + | |||
| + | AFTER=$(git rev-parse HEAD) | ||
| - | # Redemarrage uniquement si le depot a bouge. | ||
| - | # A supprimer si rewinged recharge les manifests a chaud (7.1). | ||
| if [ " | if [ " | ||
| - | logger -t winget-sync "Publication detectee: $BEFORE -> $AFTER" | + | |
| - | | + | if ! git verify-commit HEAD >/ |
| + | | ||
| + | | ||
| + | git reset --hard "$BEFORE" | ||
| + | exit 1 | ||
| + | | ||
| + | logger | ||
| fi | fi | ||
| exit 0 | exit 0 | ||
| </ | </ | ||
| + | |||
| + | Le bloc '' | ||
| + | clé publique du signataire est présente dans le trousseau du compte | ||
| + | '' | ||
| + | est ce qui rend la détection Wazuh exploitable (13.3). | ||
| <code bash> | <code bash> | ||
| + | chown root:root / | ||
| chmod 0755 / | chmod 0755 / | ||
| </ | </ | ||
| - | Le '' | + | Le script appartient à root en lecture seule pour '' |
| - | au lieu de fusionner silencieusement. Une divergence signifie une écriture | + | service exécute le script sans pouvoir le modifier. |
| - | locale, ce qui ne doit jamais arriver. | + | |
| + | Le '' | ||
| + | échoue | ||
| + | écriture | ||
| + | |||
| + | Le '' | ||
| + | corréler les alertes FIM Wazuh avec une publication légitime (section 12.2). | ||
| ==== 7.3 Unités systemd ==== | ==== 7.3 Unités systemd ==== | ||
| Ligne 305: | Ligne 350: | ||
| Description=Sync winget manifests and installers from Forgejo | Description=Sync winget manifests and installers from Forgejo | ||
| After=network-online.target | After=network-online.target | ||
| + | Wants=network-online.target | ||
| [Service] | [Service] | ||
| Type=oneshot | Type=oneshot | ||
| + | User=rewinged | ||
| + | Group=rewinged | ||
| + | WorkingDirectory=/ | ||
| ExecStart=/ | ExecStart=/ | ||
| + | |||
| + | # Durcissement | ||
| + | ProtectSystem=strict | ||
| + | ProtectHome=true | ||
| + | PrivateTmp=true | ||
| + | NoNewPrivileges=true | ||
| + | ReadWritePaths=/ | ||
| </ | </ | ||
| Ligne 318: | Ligne 374: | ||
| OnBootSec=1min | OnBootSec=1min | ||
| OnUnitActiveSec=1min | OnUnitActiveSec=1min | ||
| + | AccuracySec=10s | ||
| [Install] | [Install] | ||
| Ligne 330: | Ligne 387: | ||
| </ | </ | ||
| - | <WRAP center round important> | + | ==== 7.4 Propriété |
| - | L' | + | |
| - | systemd. Les opérations Git sont abaissées vers le compte '' | + | |
| - | '' | + | |
| - | l' | + | |
| - | L'alternative — unité sous '' | + | Le clone doit appartenir à '' |
| - | le redémarrage — est plus complexe pour un bénéfice équivalent. | + | root bloque la synchronisation. |
| - | </WRAP> | + | |
| + | <code bash> | ||
| + | # Preparation, | ||
| + | mkdir -p / | ||
| + | chown rewinged:rewinged / | ||
| + | |||
| + | # Clone, sous le compte de service | ||
| + | sudo -u rewinged git clone git@forgejo.makeitsimple.be: | ||
| + | </ | ||
| + | |||
| + | Rattrapage si le clone a déjà été fait en root : | ||
| + | |||
| + | <code bash> | ||
| + | chown -R rewinged: | ||
| + | sudo -u rewinged git -C /srv/winget status | ||
| + | </ | ||
| + | |||
| + | Git refuse d'opérer sur un dépôt dont le propriétaire diffère de l'utilisateur | ||
| + | courant ('' | ||
| + | oublié. | ||
| + | |||
| + | Vérification décisive : | ||
| + | |||
| + | <code bash> | ||
| + | sudo -u rewinged / | ||
| + | </ | ||
| + | |||
| + | Si elle passe, le timer passera aussi. | ||
| + | |||
| + | ==== 7.5 Variante avec redémarrage | ||
| + | |||
| + | À n' | ||
| + | après une montée de version de rewinged qui modifierait ce comportement. | ||
| + | |||
| + | Autorisation ciblée dans sudoers : | ||
| + | |||
| + | <file - / | ||
| + | rewinged ALL=(root) NOPASSWD: / | ||
| + | </ | ||
| + | |||
| + | <code bash> | ||
| + | visudo -c -f / | ||
| + | chmod 0440 / | ||
| + | </ | ||
| + | |||
| + | Ligne à ajouter dans le bloc conditionnel du script : | ||
| + | |||
| + | <code bash> | ||
| + | sudo / | ||
| + | </code> | ||
| - | **Ne pas redémarrer inconditionnellement.** Un '' | + | **Redémarrer uniquement sur changement de HEAD.** À raison de 1440 exécutions |
| - | justifie pas de couper le service. | + | par jour, un redémarrage systématique pollue les journaux et provoque des |
| - | redémarrage systématique pollue les journaux et provoque des micro-coupures | + | micro-coupures pendant les téléchargements. |
| - | pendant les téléchargements. La comparaison de '' | + | |
| - | redémarrages par semaine, et donne un signal net : un redémarrage équivaut à | + | |
| - | une publication. | + | |
| ===== 8. Format d'un manifest ===== | ===== 8. Format d'un manifest ===== | ||
| Ligne 383: | Ligne 482: | ||
| sur le PATH. | sur le PATH. | ||
| - | ===== 9. Extraction des codes MSI ===== | + | ===== 9. Convention pour les paquets par client ===== |
| + | |||
| + | RustDesk est publié en un paquet par client : le mot de passe d' | ||
| + | non-surveillé est préconfiguré dans le MSI et diffère d'un client à l' | ||
| + | |||
| + | ==== 9.1 Nommage ==== | ||
| + | |||
| + | < | ||
| + | PackageIdentifier: | ||
| + | </ | ||
| + | |||
| + | * manifest : '' | ||
| + | * installeur : '' | ||
| + | |||
| + | ==== 9.2 Conséquence opérationnelle ==== | ||
| + | |||
| + | À chaque version de RustDesk, autant de MSI à régénérer et de manifests à | ||
| + | republier qu'il y a de clients. À l' | ||
| + | doit être scriptée : un outil qui parcourt la liste des clients, appelle | ||
| + | '' | ||
| + | |||
| + | La saisie manuelle n'est pas tenable et expose au risque de coller le GUID | ||
| + | d'une version précédente. | ||
| + | |||
| + | ==== 9.3 Visibilité ==== | ||
| + | |||
| + | La source n'a pas de notion de périmètre : tout poste ayant enregistré | ||
| + | '' | ||
| + | clients. Sans conséquence sur l' | ||
| + | |||
| + | ==== 9.4 Alternative : paquet unique ==== | ||
| + | |||
| + | Le paquet par client existe parce que le mot de passe non-surveillé est | ||
| + | préconfiguré dans le MSI. Ce mot de passe peut aussi être posé **après** | ||
| + | installation, | ||
| + | |||
| + | === Ce qui n'est pas possible === | ||
| + | |||
| + | Le mot de passe permanent **ne se propage pas par API ni par stratégie**. | ||
| + | C'est un secret local à la machine. La demande d'en faire un paramètre de | ||
| + | stratégie Pro est ouverte depuis 2023 et n'a pas abouti. | ||
| + | |||
| + | Ne pas confondre trois objets distincts : | ||
| + | |||
| + | ^ Élément ^ Où il vit ^ Comment il se pose ^ | ||
| + | | Mot de passe permanent | Sur la machine, haché localement | '' | ||
| + | | Mot de passe du carnet | Côté serveur Pro | '' | ||
| + | | Stratégie Pro | Côté serveur Pro | Réglages client, **hors** mot de passe | | ||
| + | |||
| + | Le premier authentifie les connexions entrantes. Le second est celui que le | ||
| + | client technicien utilise pour remplir automatiquement le champ. | ||
| + | |||
| + | === Le flux en deux temps === | ||
| + | |||
| + | Le secret naît sur la machine, puis remonte vers le serveur. | ||
| + | |||
| + | <file powershell onboard-rustdesk.ps1> | ||
| + | $rd = " | ||
| + | |||
| + | # 1. Generer un mot de passe propre a CETTE machine | ||
| + | $pw = -join ((48..57)+(65..90)+(97..122) | Get-Random -Count 20 | % {[char]$_}) | ||
| + | |||
| + | # 2. Le poser localement | ||
| + | & $rd --password $pw | ||
| + | |||
| + | # 3. Recuperer l'ID attribue | ||
| + | $id = (& $rd --get-id).Trim() | ||
| + | |||
| + | # 4. Rattacher au carnet du client et y stocker le mot de passe | ||
| + | & $rd --assign ` | ||
| + | --token $env: | ||
| + | --address_book_name " | ||
| + | --address_book_alias $env: | ||
| + | --address_book_password $pw | ||
| + | |||
| + | # 5. Archiver dans Vaultwarden (ID + mot de passe) | ||
| + | </ | ||
| + | |||
| + | === Ce que cela change === | ||
| + | |||
| + | * **Un seul manifest** RustDesk pour l' | ||
| + | * **Un mot de passe par machine** au lieu d'un par client : la fuite d'un | ||
| + | secret n' | ||
| + | * Plus de régénération de MSI à chaque release | ||
| + | * Prérequis : Server Pro 1.5.8 et client 1.4.1 pour '' | ||
| + | |||
| + | === À valider avant de basculer === | ||
| + | |||
| + | <WRAP center round important> | ||
| + | Un dysfonctionnement de '' | ||
| + | signalé en mai 2025 : la commande retourne sans effet. Tester sur un poste | ||
| + | témoin, service arrêté puis démarré, avant de bâtir l' | ||
| + | </ | ||
| + | |||
| + | Vérifier également que le token API utilisé porte les seules permissions | ||
| + | '' | ||
| + | script — le passer par variable d' | ||
| + | Vaultwarden au moment de l' | ||
| + | |||
| + | ===== 10. Extraction des codes MSI ===== | ||
| Le '' | Le '' | ||
| Ligne 390: | Ligne 588: | ||
| logiciels déjà installés depuis d' | logiciels déjà installés depuis d' | ||
| - | ==== 9.1 Depuis un fichier MSI ==== | + | ==== 10.1 Depuis un fichier MSI ==== |
| À exécuter sur la machine de build (Windows). Lecture seule, sans installation | À exécuter sur la machine de build (Windows). Lecture seule, sans installation | ||
| Ligne 428: | Ligne 626: | ||
| tourne pas sur la VM Debian. | tourne pas sur la VM Debian. | ||
| - | ==== 9.2 Depuis un poste où le logiciel est installé ==== | + | ==== 10.2 Depuis un poste où le logiciel est installé ==== |
| Pour recenser les GUID en circulation dans le parc : | Pour recenser les GUID en circulation dans le parc : | ||
| Ligne 449: | Ligne 647: | ||
| </ | </ | ||
| - | ==== 9.3 Automatisation ==== | + | ==== 10.3 Automatisation ==== |
| L' | L' | ||
| Ligne 455: | Ligne 653: | ||
| '' | '' | ||
| - | ===== 10. Workflow de publication ===== | + | ===== 11. Workflow de publication ===== |
| - Construire l' | - Construire l' | ||
| Ligne 470: | Ligne 668: | ||
| </ | </ | ||
| - | ===== 11. Configuration des postes ===== | + | ===== 12. Configuration des postes ===== |
| - | ==== 11.1 Enregistrement de la source ==== | + | ==== 12.1 Enregistrement de la source ==== |
| <code powershell> | <code powershell> | ||
| Ligne 483: | Ligne 681: | ||
| l' | l' | ||
| - | ==== 11.2 Winget en contexte SYSTEM ==== | + | ==== 12.2 Winget en contexte SYSTEM ==== |
| '' | '' | ||
| Ligne 497: | Ligne 695: | ||
| un prompt bloque le processus indéfiniment. | un prompt bloque le processus indéfiniment. | ||
| - | ==== 11.3 Adoption du parc existant ==== | + | ==== 12.3 Adoption du parc existant ==== |
| Un paquet installé autrement que depuis la source privée n'est pas reconnu | Un paquet installé autrement que depuis la source privée n'est pas reconnu | ||
| Ligne 508: | Ligne 706: | ||
| À valider sur un poste témoin **avant** de dimensionner la campagne. | À valider sur un poste témoin **avant** de dimensionner la campagne. | ||
| - | ==== 11.4 Compatibilité ==== | + | ==== 12.4 Compatibilité ==== |
| ^ Système ^ App Installer ^ | ^ Système ^ App Installer ^ | ||
| Ligne 519: | Ligne 717: | ||
| le canal unique ou s'il faut un second canal. | le canal unique ou s'il faut un second canal. | ||
| - | ===== 12. Surveillance Wazuh ===== | + | ===== 13. Surveillance Wazuh ===== |
| - | ==== 12.1 FIM ==== | + | Trois sources distinctes : l' |
| + | rewinged, et l' | ||
| - | <file xml ossec.conf> | + | ==== 13.1 Configuration de l' |
| - | <syscheck> | + | |
| - | < | + | <file xml / |
| - | / | + | <ossec_config> |
| - | | + | |
| - | < | + | |
| - | / | + | < |
| - | | + | < |
| - | < | + | < |
| - | / | + | |
| - | </ | + | <!-- Manifests : decident de ce que le parc installe --> |
| - | </ | + | |
| + | tags=" | ||
| + | |||
| + | <!-- Installeurs : les binaires servis aux postes --> | ||
| + | | ||
| + | tags=" | ||
| + | |||
| + | <!-- Binaire rewinged et script de synchronisation --> | ||
| + | | ||
| + | tags=" | ||
| + | |||
| + | <!-- Unites systemd du service --> | ||
| + | < | ||
| + | | ||
| + | |||
| + | <!-- Bruit git interne --> | ||
| + | <ignore type=" | ||
| + | | ||
| + | |||
| + | <!-- Journal applicatif rewinged, deja en JSON --> | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | </ | ||
| + | |||
| + | <!-- Etat des services, toutes les 5 minutes --> | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | </ | ||
| + | |||
| + | </ | ||
| </ | </ | ||
| - | ==== 12.2 Réduction du bruit ==== | + | Le journal de '' |
| + | collecté par la configuration Wazuh par défaut. | ||
| - | La FIM se déclenche à chaque | + | ==== 13.2 Règles personnalisées ==== |
| - | légitime | + | |
| + | <file xml / | ||
| + | <group name=" | ||
| + | |||
| + | <rule id=" | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | </ | ||
| + | |||
| + | <rule id=" | ||
| + | < | ||
| + | <field name=" | ||
| + | < | ||
| + | </ | ||
| + | |||
| + | <rule id=" | ||
| + | < | ||
| + | <field name=" | ||
| + | < | ||
| + | </ | ||
| + | |||
| + | <rule id=" | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | </ | ||
| + | |||
| + | <rule id=" | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | </ | ||
| + | |||
| + | <rule id=" | ||
| + | < | ||
| + | < | ||
| + | </ | ||
| + | |||
| + | <rule id=" | ||
| + | < | ||
| + | <field name=" | ||
| + | < | ||
| + | </ | ||
| + | |||
| + | <rule id=" | ||
| + | < | ||
| + | <field name=" | ||
| + | < | ||
| + | < | ||
| + | </ | ||
| + | |||
| + | <rule id=" | ||
| + | < | ||
| + | <field name=" | ||
| + | < | ||
| + | < | ||
| + | </ | ||
| + | |||
| + | <rule id=" | ||
| + | < | ||
| + | < | ||
| + | </ | ||
| + | |||
| + | <rule id=" | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | </ | ||
| + | |||
| + | </ | ||
| + | </ | ||
| + | |||
| + | <WRAP center round important> | ||
| + | Les identifiants 100600–100631 sont donnés à titre indicatif. Les adapter à | ||
| + | la numérotation des règles personnalisées déjà en place. | ||
| + | </ | ||
| + | |||
| + | ==== 13.3 Traiter le bruit FIM ==== | ||
| + | |||
| + | La FIM se déclenche à chaque | ||
| + | nativement « alerter sauf si précédé de tel événement », il faut donc déplacer | ||
| + | le contrôle plutôt que tenter de corréler. | ||
| + | |||
| + | **Approche retenue** : la signature GPG des commits est le contrôle réel. | ||
| + | |||
| + | - Les commits | ||
| + | dans le trousseau du compte | ||
| + | - '' | ||
| + | d' | ||
| + | - La FIM sur '' | ||
| + | elle n' | ||
| + | - L' | ||
| + | |||
| + | Une modification de manifest effectuée directement sur le serveur ne passe pas | ||
| + | par un commit, donc ne déclenche pas 100611 — mais elle sera écrasée au | ||
| + | prochain '' | ||
| + | |||
| + | Les installeurs et les binaires, eux, ne changent pas hors publication : leurs | ||
| + | règles restent à niveau élevé. | ||
| + | |||
| + | ==== 13.4 Mise en place de la signature ==== | ||
| + | |||
| + | Côté poste de publication : | ||
| + | |||
| + | <code bash> | ||
| + | git config --global user.signingkey < | ||
| + | git config --global commit.gpgsign true | ||
| + | gpg --export --armor < | ||
| + | </ | ||
| + | |||
| + | Côté serveur rewinged : | ||
| + | |||
| + | <code bash> | ||
| + | sudo -u rewinged gpg --import mis-publication.pub | ||
| + | sudo -u rewinged gpg --edit-key < | ||
| + | sudo -u rewinged git -C /srv/winget verify-commit HEAD | ||
| + | </ | ||
| - | * signer les commits en GPG et vérifier | + | Idéalement |
| - | avant application — un fichier modifié sans commit signé devient alors une | + | l' |
| - | alerte non ambiguë | + | |
| - | * à défaut, corréler | + | |
| - | ==== 12.3 Alertes complémentaires | + | ==== 13.5 Ce qui reste non couvert |
| - | * arrêt du service | + | * **Publication légitime mais erronée** — un mauvais |
| - | * échecs répétés | + | ou un SHA256 incorrect signé |
| - | | + | Le garde-fou est la revue de la PR, pas la détection. |
| - | * volumétrie anormale de téléchargements sur ''/ | + | * **Compromission du poste de publication** |
| - | * saturation | + | utilisable par un attaquant, la chaîne entière est valide de son point de |
| + | | ||
| + | * **Saturation | ||
| + | | ||
| - | ===== 13. Points ouverts ===== | + | ===== 14. Points ouverts ===== |
| ^ Sujet ^ Action ^ | ^ Sujet ^ Action ^ | ||
| - | | Rechargement à chaud | Trancher le test 7.1 et simplifier le script si le rechargement est natif | | ||
| | Auto-internalisation | Valider le rapatriement des installeurs tiers depuis les URL éditeur | | | Auto-internalisation | Valider le rapatriement des installeurs tiers depuis les URL éditeur | | ||
| | Bug de matching | Tester sur un poste témoin avec un logiciel préinstallé | | | Bug de matching | Tester sur un poste témoin avec un logiciel préinstallé | | ||
| | Server 2019/2022 | Inventorier la proportion dans le parc | | | Server 2019/2022 | Inventorier la proportion dans le parc | | ||
| | Upgrade RustDesk | Vérifier que la mise à jour préserve '' | | Upgrade RustDesk | Vérifier que la mise à jour préserve '' | ||
| + | | '' | ||
| | Rétention LFS | Définir une politique de purge des anciennes versions d' | | Rétention LFS | Définir une politique de purge des anciennes versions d' | ||
| | Quota Forgejo | Dimensionner le stockage LFS et surveiller sa croissance | | | Quota Forgejo | Dimensionner le stockage LFS et surveiller sa croissance | | ||
| - | ===== 14. Références ===== | + | ===== 15. Références ===== |
| * [[https:// | * [[https:// | ||
| * [[https:// | * [[https:// | ||
| * [[https:// | * [[https:// | ||
linux/rewinged.1789198329.txt.gz · Dernière modification : de root
