Fix output format

This commit is contained in:
2026-05-29 10:54:37 +09:00
parent d9dcbbf0db
commit 1bc8e2cce0
2 changed files with 90 additions and 21 deletions
+1 -2
View File
@@ -58,7 +58,7 @@ prometheus-exporter
proxy proxy
rdma rdma
root root
runit # runit
salt salt
sambashare sambashare
saned saned
@@ -80,7 +80,6 @@ systemd-timesync
tape tape
tcpdump tcpdump
tty tty
uallt_e
users users
utempter utempter
utmp utmp
+89 -19
View File
@@ -1,13 +1,13 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
from __future__ import annotations from __future__ import annotations
from typing import Any
import argparse import argparse
import json import json
from collections import Counter from collections import Counter
from dataclasses import dataclass from dataclasses import dataclass
from pathlib import Path from pathlib import Path
from typing import Any
def main(): def main():
@@ -78,13 +78,6 @@ def main():
for user in users.values(): for user in users.values():
user.email = f"{user.name}@{args.email_domain}" user.email = f"{user.name}@{args.email_domain}"
if not args.output_dir.exists():
args.output_dir.mkdir(parents=True)
user_dir = args.output_dir / "users"
user_dir.mkdir(exist_ok=True)
group_dir = args.output_dir / "groups"
group_dir.mkdir(exist_ok=True)
# print_group_stats(groups, users) # print_group_stats(groups, users)
for user in users.values(): for user in users.values():
@@ -94,12 +87,7 @@ def main():
if user.name in shadow: if user.name in shadow:
user.set_shadow_entry(shadow[user.name]) user.set_shadow_entry(shadow[user.name])
with open(args.output_dir / "users" / f"{user.name}.json", "w") as f: output_to_directory(users, groups, args.output_dir)
json.dump(user.to_systemd_user_record(), f, indent=2)
for group in groups.values():
with open(args.output_dir / "groups" / f"{group.name}.json", "w") as f:
json.dump(group.to_systemd_group_record(), f, indent=2)
def ensure_no_overlapping_uids(users: dict[str, User]): def ensure_no_overlapping_uids(users: dict[str, User]):
@@ -327,13 +315,16 @@ class User:
if self.memberOf: if self.memberOf:
result["memberOf"] = self.memberOf result["memberOf"] = self.memberOf
if self.password is not None:
result["privileged"] = {
"hashedPassword": self.password,
}
return result return result
def to_systemd_privileged_user_record(self) -> dict[str, Any] | None:
if self.password is None:
return None
return {
"hashedPassword": self.password,
}
@dataclass @dataclass
class Group: class Group:
@@ -348,6 +339,10 @@ class Group:
"members": self.members, "members": self.members,
} }
# TODO: parse gshadow
def to_systemd_privileged_group_record(self) -> dict[str, Any] | None:
return None
def print_group_stats( def print_group_stats(
groups: dict[str, Group], groups: dict[str, Group],
@@ -373,5 +368,80 @@ def print_group_stats(
) )
def output_to_directory(
users: dict[str, User],
groups: dict[str, Group],
output_dir: Path,
):
if not output_dir.exists():
output_dir.mkdir(parents=True)
for user in users.values():
user_record = user.to_systemd_user_record()
with open(output_dir / f"{user.name}.user", "w") as f:
json.dump(user_record, f, indent=2)
symlink_path = output_dir / f"{user.uid}.user"
if symlink_path.exists():
symlink_path.unlink()
symlink_path.symlink_to(f"./{user.name}.user")
privileged_user_record = user.to_systemd_privileged_user_record()
if privileged_user_record:
priv_path = output_dir / f"{user.name}.user-privileged"
priv_path.touch(exist_ok=True)
priv_path.chmod(0o600)
with open(priv_path, "w") as f:
json.dump(privileged_user_record, f, indent=2)
symlink_path = output_dir / f"{user.uid}.user-privileged"
if symlink_path.exists():
symlink_path.unlink()
symlink_path.symlink_to(f"./{user.name}.user-privileged")
for group in groups.values():
group_record = group.to_systemd_group_record()
with open(output_dir / f"{group.name}.group", "w") as f:
json.dump(group_record, f, indent=2)
symlink_path = output_dir / f"{group.gid}.group"
if symlink_path.exists():
symlink_path.unlink()
symlink_path.symlink_to(f"./{group.name}.group")
privileged_group_record = group.to_systemd_privileged_group_record()
if privileged_group_record:
priv_path = output_dir / f"{group.name}.group-privileged"
priv_path.touch(exist_ok=True)
priv_path.chmod(0o600)
with open(priv_path, "w") as f:
json.dump(privileged_group_record, f, indent=2)
symlink_path = output_dir / f"{group.gid}.group-privileged"
if symlink_path.exists():
symlink_path.unlink()
symlink_path.symlink_to(f"./{group.name}.group-privileged")
groups_by_gid = {group.gid: group for group in groups.values()}
for user in users.values():
primary_group = groups_by_gid.get(user.gid)
if not primary_group:
print(
f"Warning: User {user.name} has primary GID {user.gid} which does not correspond to any group"
)
else:
with open(
output_dir / f"{user.name}:{primary_group.name}.membership", "w"
) as f:
json.dump({}, f)
for group in groups.values():
if user.name in group.members:
with open(
output_dir / f"{user.name}:{group.name}.membership", "w"
) as f:
json.dump({}, f)
if __name__ == "__main__": if __name__ == "__main__":
main() main()