160 lines
2.7 KiB
Python
160 lines
2.7 KiB
Python
from __future__ import annotations
|
|
|
|
import pwd
|
|
import subprocess
|
|
|
|
|
|
def user_exists(
|
|
username: str,
|
|
) -> bool:
|
|
try:
|
|
pwd.getpwnam(
|
|
username
|
|
)
|
|
return True
|
|
except KeyError:
|
|
return False
|
|
|
|
|
|
def _run(
|
|
command: list[str],
|
|
) -> subprocess.CompletedProcess:
|
|
return subprocess.run(
|
|
command,
|
|
capture_output=True,
|
|
text=True,
|
|
check=False,
|
|
)
|
|
|
|
|
|
def is_locked(
|
|
username: str,
|
|
) -> bool:
|
|
if not user_exists(username):
|
|
return False
|
|
|
|
result = _run(
|
|
[
|
|
"passwd",
|
|
"-S",
|
|
username,
|
|
]
|
|
)
|
|
|
|
if result.returncode != 0:
|
|
return False
|
|
|
|
parts = result.stdout.strip().split()
|
|
|
|
if len(parts) < 2:
|
|
return False
|
|
|
|
status = parts[1].upper()
|
|
|
|
return status.startswith("L")
|
|
|
|
|
|
def lock_user(
|
|
username: str,
|
|
) -> None:
|
|
if not user_exists(username):
|
|
raise RuntimeError(
|
|
f"Linux user does not exist: {username}"
|
|
)
|
|
|
|
result = _run(
|
|
[
|
|
"passwd",
|
|
"-l",
|
|
username,
|
|
]
|
|
)
|
|
|
|
if result.returncode != 0:
|
|
error = (
|
|
result.stderr.strip()
|
|
or result.stdout.strip()
|
|
or "unknown error"
|
|
)
|
|
|
|
raise RuntimeError(
|
|
f"Unable to lock {username}: {error}"
|
|
)
|
|
|
|
|
|
def unlock_user(
|
|
username: str,
|
|
) -> None:
|
|
if not user_exists(username):
|
|
raise RuntimeError(
|
|
f"Linux user does not exist: {username}"
|
|
)
|
|
|
|
result = _run(
|
|
[
|
|
"passwd",
|
|
"-u",
|
|
username,
|
|
]
|
|
)
|
|
|
|
if result.returncode != 0:
|
|
error = (
|
|
result.stderr.strip()
|
|
or result.stdout.strip()
|
|
or "unknown error"
|
|
)
|
|
|
|
raise RuntimeError(
|
|
f"Unable to unlock {username}: {error}"
|
|
)
|
|
|
|
|
|
def terminate_user(
|
|
username: str,
|
|
) -> None:
|
|
if not user_exists(username):
|
|
return
|
|
|
|
result = _run(
|
|
[
|
|
"loginctl",
|
|
"terminate-user",
|
|
username,
|
|
]
|
|
)
|
|
|
|
if result.returncode != 0:
|
|
error = (
|
|
result.stderr.strip()
|
|
or result.stdout.strip()
|
|
)
|
|
|
|
if error:
|
|
raise RuntimeError(
|
|
f"Unable to terminate "
|
|
f"{username}: {error}"
|
|
)
|
|
|
|
|
|
def get_uid(
|
|
username: str,
|
|
) -> int | None:
|
|
try:
|
|
return pwd.getpwnam(
|
|
username
|
|
).pw_uid
|
|
except KeyError:
|
|
return None
|
|
|
|
|
|
def get_home(
|
|
username: str,
|
|
) -> str | None:
|
|
try:
|
|
return pwd.getpwnam(
|
|
username
|
|
).pw_dir
|
|
except KeyError:
|
|
return None
|