Fix output format
This commit is contained in:
@@ -58,7 +58,7 @@ prometheus-exporter
|
||||
proxy
|
||||
rdma
|
||||
root
|
||||
runit
|
||||
# runit
|
||||
salt
|
||||
sambashare
|
||||
saned
|
||||
@@ -80,7 +80,6 @@ systemd-timesync
|
||||
tape
|
||||
tcpdump
|
||||
tty
|
||||
uallt_e
|
||||
users
|
||||
utempter
|
||||
utmp
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from __future__ import annotations
|
||||
from typing import Any
|
||||
|
||||
import argparse
|
||||
import json
|
||||
from collections import Counter
|
||||
from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
|
||||
def main():
|
||||
@@ -78,13 +78,6 @@ def main():
|
||||
for user in users.values():
|
||||
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)
|
||||
|
||||
for user in users.values():
|
||||
@@ -94,12 +87,7 @@ def main():
|
||||
if user.name in shadow:
|
||||
user.set_shadow_entry(shadow[user.name])
|
||||
|
||||
with open(args.output_dir / "users" / f"{user.name}.json", "w") as f:
|
||||
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)
|
||||
output_to_directory(users, groups, args.output_dir)
|
||||
|
||||
|
||||
def ensure_no_overlapping_uids(users: dict[str, User]):
|
||||
@@ -327,13 +315,16 @@ class User:
|
||||
if self.memberOf:
|
||||
result["memberOf"] = self.memberOf
|
||||
|
||||
if self.password is not None:
|
||||
result["privileged"] = {
|
||||
"hashedPassword": self.password,
|
||||
}
|
||||
|
||||
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
|
||||
class Group:
|
||||
@@ -348,6 +339,10 @@ class Group:
|
||||
"members": self.members,
|
||||
}
|
||||
|
||||
# TODO: parse gshadow
|
||||
def to_systemd_privileged_group_record(self) -> dict[str, Any] | None:
|
||||
return None
|
||||
|
||||
|
||||
def print_group_stats(
|
||||
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__":
|
||||
main()
|
||||
|
||||
Reference in New Issue
Block a user