Skip to main content

deploy_users.py

For use on a newly deployed VM. Creates user accounts as per a users.json file in the following format: (Remove comments for use)

{
"user1": {
servers: ["*"] // Create an account for this user on all servers
},
"user2": {
servers: ["*:"] // Create an account for this user on all servers and add
// them to the sudo group.
},
"user3": {
servers: ["synthesis.local"] // Create an account for them if the current
// hostname is synthesis.local
},
"user4": {
servers: ["synthesis.local:", "webserver.local"] // Create an account for
// them on synthesis.local with the sudo group, and just
// a regular account on webserver.local
}
}
import json  
import os
import socket
import subprocess
import secrets
import string
import pwd

# Load Users files
with open("users.json", "r") as file:
data = json.load(file)

current_hostname = socket.gethostname()

def generate_password(length=16):
characters = string.ascii_letters + string.digits
return ''.join(secrets.choice(characters) for i in range(length))


def user_exists(username):
try:
pwd.getpwnam(username)
return True
except KeyError:
return False


def create_user(username, is_sudo, ssh_key):
if user_exists(username):
print(f"Skipping {username}, user already exists.")
return None

password = generate_password()
subprocess.run(["adduser", "--disabled-password", "--gecos", "", username], check=True)
subprocess.run(["chpasswd"], input=f"{username}:{password}".encode(), check=True)
subprocess.run(["passwd", "-e", username], check=True)

if is_sudo:
subprocess.run(["usermod", "-aG", "sudo", username], check=True)

# Add the user's ed25519 key to the authorized_keys file
ssh_dir = os.path.join(f"/home/{username}", ".ssh")
os.makedirs(ssh_dir, mode=0o700, exist_ok=True)
authorized_keys_file = os.path.join(ssh_dir, "authorized_keys")

with open(authorized_keys_file, "a") as file:
file.write(f"ssh-ed25519 {ssh_key}\n")

os.chown(ssh_dir, int(subprocess.check_output(['id', '-u', username])),
int(subprocess.check_output(['id', '-g', username])))
os.chown(authorized_keys_file, int(subprocess.check_output(['id', '-u', username])),
int(subprocess.check_output(['id', '-g', username])))
os.chmod(authorized_keys_file, 0o600)

return password


created_users = []

for username, user_data in data.items():
for server in user_data["servers"]:
flags = server.split(":")
hostname = flags[0]
is_sudo = False


print("hostname: " + hostname + " Current: " + current_hostname)
if hostname == "*" or hostname == current_hostname:
if len(flags) == 2 and flags[1] is not None and flags[1] == "*":
is_sudo = True
ssh_key = user_data.get("key_ed25519", "")
password = create_user(username, is_sudo, ssh_key)
if password is not None:
created_users.append((username, password))
break

print("Created users and their passwords:")
for username, password in created_users:
print(f"{username}: {password}")

Requires a users.json file, take the version from notes/Users