2 Commits
Author SHA1 Message Date
tuxgyverandClaude Opus 5 04a7b5dc64 chore: version 0.1.4
Livre le correctif de jointure Windows : le script PowerShell n'etait jamais
execute, la jointure echouait sans message avec un code retour 0.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-08 23:12:17 +02:00
tuxgyverandClaude Opus 5 3d4d6de0f8 fix: la jointure Windows n'executait jamais le script PowerShell
Le script etait envoye sur stdin de `powershell -Command -`, qui analyse
l'entree ligne par ligne. Le `}` fermant le try/catch n'etait suivi d'aucun
saut de ligne : le parseur gardait l'instruction incomplete en attente et la
jetait a la fermeture de stdin. PowerShell rendait la main avec le code 0
sans avoir appele Add-Computer, et l'utilisateur ne voyait qu'un « echec de
la jointure (code retour 0) » sans explication.

- Transmission du script d'un seul bloc via `-EncodedCommand` (base64
  UTF-16LE), ce qui supprime toute analyse ligne par ligne et propage
  correctement les codes de sortie. Le mot de passe reste hors de la ligne
  de commande : il ne transite que par l'environnement du sous-processus.
- Report de la sortie brute de PowerShell quand aucun marqueur n'est trouve,
  pour qu'un echec inattendu reste diagnosticable.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-08 23:09:54 +02:00
3 changed files with 52 additions and 10 deletions
+15
View File
@@ -1,5 +1,20 @@
# Changelog
## [0.1.4] - 2026-09-08
### Fixed
- La jointure de domaine sous Windows échouait sans aucun message, avec un code
retour 0. Le script PowerShell était transmis sur l'entrée standard de
`powershell -Command -`, qui analyse stdin ligne par ligne : le bloc
`try`/`catch` final, dépourvu de saut de ligne terminal, restait en attente
dans le parseur et n'était jamais exécuté. PowerShell rendait donc la main
sans avoir tenté la jointure. Le script est désormais transmis d'un bloc via
`-EncodedCommand`.
- En l'absence de marqueur de succès comme d'échec, le message d'erreur se
réduisait à « code retour 0 », impossible à diagnostiquer. La sortie brute de
PowerShell est maintenant reportée à l'utilisateur (le mot de passe ne
transitant que par l'environnement, il n'y apparaît jamais).
## [0.1.3] - 2026-09-08
### Fixed
+1 -1
View File
@@ -1 +1 @@
__version__ = "0.1.3"
__version__ = "0.1.4"
+36 -9
View File
@@ -2,6 +2,7 @@
from __future__ import annotations
import base64
import os
import shutil
import subprocess
@@ -19,6 +20,20 @@ def _ps_quote(value: str) -> str:
return value.replace("'", "''")
def _encode_command(script: str) -> str:
"""Encode un script pour `powershell -EncodedCommand` (base64 d'UTF-16LE).
Le script est ainsi transmis comme un bloc unique et atomique. L'alternative
`-Command -` fait analyser l'entrée standard ligne par ligne : la dernière
instruction d'un bloc `try`/`catch` restait en attente dans le parseur et
n'était jamais exécutée à la fermeture de stdin — PowerShell rendait alors
la main avec le code 0 sans avoir rien fait, et la jointure echouait sans
le moindre message. Le mot de passe reste hors du script (variable
d'environnement) : la ligne de commande ne l'expose pas.
"""
return base64.b64encode(script.encode("utf-16-le")).decode("ascii")
class WindowsAddComputerBackend(DomainJoinBackend):
def is_available(self) -> tuple[bool, str]:
if shutil.which("powershell") is None and shutil.which("powershell.exe") is None:
@@ -76,8 +91,16 @@ class WindowsAddComputerBackend(DomainJoinBackend):
try:
process = subprocess.Popen(
["powershell", "-NoProfile", "-NonInteractive", "-ExecutionPolicy", "Bypass", "-Command", "-"],
stdin=subprocess.PIPE,
[
"powershell",
"-NoProfile",
"-NonInteractive",
"-ExecutionPolicy",
"Bypass",
"-EncodedCommand",
_encode_command(script),
],
stdin=subprocess.DEVNULL,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
text=True,
@@ -90,12 +113,6 @@ class WindowsAddComputerBackend(DomainJoinBackend):
finally:
env[_PASSWORD_ENV_VAR] = ""
try:
process.stdin.write(script)
process.stdin.close()
except BrokenPipeError:
pass
output_lines: list[str] = []
if process.stdout:
for line in process.stdout:
@@ -114,5 +131,15 @@ class WindowsAddComputerBackend(DomainJoinBackend):
)
failure_detail = next((l for l in output_lines if l.strip().startswith(_FAILURE_PREFIX)), None)
message = failure_detail or f"Échec de la jointure au domaine (code retour {returncode})."
if failure_detail:
message = failure_detail
else:
# Sans ce report de la sortie brute, un echec inattendu se resumait a
# « code retour 0 », indiagnosticable. Le mot de passe n'apparait
# jamais dans cette sortie : il ne transite que par l'environnement.
detail = full_output.strip() or "aucune sortie produite par PowerShell"
message = (
f"Échec de la jointure au domaine (code retour {returncode}).\n"
f"Sortie de PowerShell : {detail}"
)
return JoinResult(success=False, message=message)