|
|
@ -1,7 +1,7 @@
|
|
|
|
import sys
|
|
|
|
|
|
|
|
import os
|
|
|
|
import os
|
|
|
|
import subprocess
|
|
|
|
import subprocess
|
|
|
|
import pwd
|
|
|
|
import pwd
|
|
|
|
|
|
|
|
import lib.UserExceptions
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class System:
|
|
|
|
class System:
|
|
|
@ -35,7 +35,7 @@ class System:
|
|
|
|
:type username: str
|
|
|
|
:type username: str
|
|
|
|
:param cc: Tuple with commands separated to execute on the machine. (defaults to useradd -m)
|
|
|
|
:param cc: Tuple with commands separated to execute on the machine. (defaults to useradd -m)
|
|
|
|
:type cc: tuple
|
|
|
|
:type cc: tuple
|
|
|
|
:returns: True, when the user was successfully created, False when not
|
|
|
|
:return: True, if worked, raises lib.UserExceptions.UserExistsAlready when not
|
|
|
|
:rtype: bool
|
|
|
|
:rtype: bool
|
|
|
|
"""
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
@ -47,15 +47,12 @@ class System:
|
|
|
|
elif not self.dry:
|
|
|
|
elif not self.dry:
|
|
|
|
rt = subprocess.call(cc)
|
|
|
|
rt = subprocess.call(cc)
|
|
|
|
if rt != 0:
|
|
|
|
if rt != 0:
|
|
|
|
print(f"Could not create user {username}; '{cc}' returned '{rt}'", file=sys.stderr)
|
|
|
|
raise lib.UserExceptions.UserExistsAlready(f"User {username} exists already")
|
|
|
|
# @TODO Logging/Exception
|
|
|
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
return True
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
|
|
def unregister(self, username: str):
|
|
|
|
def unregister(self, username: str):
|
|
|
|
pass
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
# @TODO errno
|
|
|
|
|
|
|
|
def make_ssh_usable(self, username: str, pubkey: str, sshdir: str = ".ssh/") -> bool:
|
|
|
|
def make_ssh_usable(self, username: str, pubkey: str, sshdir: str = ".ssh/") -> bool:
|
|
|
|
""" Make SSH usable for our newly registered user
|
|
|
|
""" Make SSH usable for our newly registered user
|
|
|
|
|
|
|
|
|
|
|
@ -65,7 +62,8 @@ class System:
|
|
|
|
:type pubkey: str
|
|
|
|
:type pubkey: str
|
|
|
|
:param sshdir: Directory to write the authorized_keys File to. PWD is $HOME of said user. (defaults to ".ssh/")
|
|
|
|
:param sshdir: Directory to write the authorized_keys File to. PWD is $HOME of said user. (defaults to ".ssh/")
|
|
|
|
:type sshdir: str
|
|
|
|
:type sshdir: str
|
|
|
|
:return: True, when everything worked out good, false when something bad happened. Outputs the error of it.
|
|
|
|
:return: True, if worked, raises lib.UserExceptions.UnknownReturnCode, lib.UserExceptions.HomeDirExistsAlready
|
|
|
|
|
|
|
|
or lib.UserExceptions.ModifyFilesystem when not
|
|
|
|
:rtype: bool
|
|
|
|
:rtype: bool
|
|
|
|
"""
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
@ -80,8 +78,8 @@ class System:
|
|
|
|
except FileExistsError:
|
|
|
|
except FileExistsError:
|
|
|
|
pass # thats actually a good one for us :D
|
|
|
|
pass # thats actually a good one for us :D
|
|
|
|
except OSError as e:
|
|
|
|
except OSError as e:
|
|
|
|
print(f"Could not create {ssh_dir}: Exception: {e}", file=sys.stderr)
|
|
|
|
raise lib.UserExceptions.HomeDirExistsAlready(f"Could not create {ssh_dir}: Exception: {e}")
|
|
|
|
return False
|
|
|
|
|
|
|
|
try:
|
|
|
|
try:
|
|
|
|
with open(ssh_dir + "authorized_keys", "w") as f:
|
|
|
|
with open(ssh_dir + "authorized_keys", "w") as f:
|
|
|
|
print(pubkey, file=f)
|
|
|
|
print(pubkey, file=f)
|
|
|
@ -89,17 +87,17 @@ class System:
|
|
|
|
os.chmod(ssh_dir + "authorized_keys", 0o700) # directory is already 777?
|
|
|
|
os.chmod(ssh_dir + "authorized_keys", 0o700) # directory is already 777?
|
|
|
|
os.chmod(ssh_dir, 0o700) # directory is already 777?
|
|
|
|
os.chmod(ssh_dir, 0o700) # directory is already 777?
|
|
|
|
except OSError as e:
|
|
|
|
except OSError as e:
|
|
|
|
print(f"Could not write and/or chmod 0700 {ssh_dir} or {ssh_dir}/authorized_keys, Exception: {e}",
|
|
|
|
raise lib.UserExceptions.ModifyFilesystem(
|
|
|
|
file=sys.stderr)
|
|
|
|
f"Could not write and/or chmod 0700 {ssh_dir} or {ssh_dir}/authorized_keys, Exception: {e}")
|
|
|
|
return False # @TODO Exception in Log
|
|
|
|
|
|
|
|
try:
|
|
|
|
try:
|
|
|
|
pwdnam = pwd.getpwnam(username)
|
|
|
|
pwdnam = pwd.getpwnam(username)
|
|
|
|
os.chown(ssh_dir, pwdnam[2], pwdnam[3]) # 2=>uid, 3=>gid
|
|
|
|
os.chown(ssh_dir, pwdnam[2], pwdnam[3]) # 2=>uid, 3=>gid
|
|
|
|
os.chown(ssh_dir + "authorized_keys", pwd.getpwnam(username)[2], pwd.getpwnam(username)[3])
|
|
|
|
os.chown(ssh_dir + "authorized_keys", pwd.getpwnam(username)[2], pwd.getpwnam(username)[3])
|
|
|
|
except OSError as e:
|
|
|
|
except OSError as e: # by os.chown
|
|
|
|
print(f"Could not chown {ssh_dir} and/or authorized_keys to {username} and their group, Exception: {e}",
|
|
|
|
raise lib.UserExceptions.ModifyFilesystem(
|
|
|
|
file=sys.stderr)
|
|
|
|
f"Could not chown {ssh_dir} and/or authorized_keys to {username} and their group, Exception: {e}",)
|
|
|
|
return False # @TODO Exception in Log
|
|
|
|
except KeyError as e: # by PWD
|
|
|
|
|
|
|
|
raise lib.UserExceptions.General(f"PWD can't find {username}: {e}")
|
|
|
|
return True
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
|
|
def lock_user_pw(self, username: str, cc: tuple = tuple(["usermod", "--lock"])) -> bool:
|
|
|
|
def lock_user_pw(self, username: str, cc: tuple = tuple(["usermod", "--lock"])) -> bool:
|
|
|
@ -110,7 +108,7 @@ class System:
|
|
|
|
:param cc: Commands to run in the subprocess to lock it down(defaults to usermod --lock)
|
|
|
|
:param cc: Commands to run in the subprocess to lock it down(defaults to usermod --lock)
|
|
|
|
:type cc: tuple
|
|
|
|
:type cc: tuple
|
|
|
|
:rtype: bool
|
|
|
|
:rtype: bool
|
|
|
|
:return: True when the lock worked, false when not.
|
|
|
|
:return: True, if worked, raises lib.UserExceptions.UnknownReturnCode when not
|
|
|
|
"""
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
lock_command = cc
|
|
|
|
lock_command = cc
|
|
|
@ -121,9 +119,7 @@ class System:
|
|
|
|
elif not self.dry:
|
|
|
|
elif not self.dry:
|
|
|
|
rt = subprocess.call(cc)
|
|
|
|
rt = subprocess.call(cc)
|
|
|
|
if rt != 0:
|
|
|
|
if rt != 0:
|
|
|
|
print(f"Could not lock user '{username}'; '{cc}' returned '{rt}'", file=sys.stderr)
|
|
|
|
raise lib.UserExceptions.UnknownReturnCode(f"Could not lock user '{username}'; '{cc}' returned '{rt}'")
|
|
|
|
return False
|
|
|
|
|
|
|
|
# @TODO Exception in Log
|
|
|
|
|
|
|
|
return True
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
|
|
def add_to_usergroup(self, username: str, group: str = "tilde", cc: tuple = tuple(["usermod", "-a", "-G"])) -> bool:
|
|
|
|
def add_to_usergroup(self, username: str, group: str = "tilde", cc: tuple = tuple(["usermod", "-a", "-G"])) -> bool:
|
|
|
@ -135,7 +131,7 @@ class System:
|
|
|
|
:type group: str
|
|
|
|
:type group: str
|
|
|
|
:param cc: Commands to execute that adds your user to said specific group(defaults to usermod -a -G")
|
|
|
|
:param cc: Commands to execute that adds your user to said specific group(defaults to usermod -a -G")
|
|
|
|
:type cc: tuple
|
|
|
|
:type cc: tuple
|
|
|
|
:return: True, if worked, False when not.
|
|
|
|
:return: True, if worked, raises lib.UserExceptions.UnknownReturnCode when not
|
|
|
|
:rtype bool
|
|
|
|
:rtype bool
|
|
|
|
"""
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
@ -147,9 +143,8 @@ class System:
|
|
|
|
elif not self.dry:
|
|
|
|
elif not self.dry:
|
|
|
|
rt = subprocess.call(cc)
|
|
|
|
rt = subprocess.call(cc)
|
|
|
|
if rt != 0:
|
|
|
|
if rt != 0:
|
|
|
|
print(f"Could not add user '{username}' to group '{group}' with command '{cc}', returned '{rt}'",
|
|
|
|
raise lib.UserExceptions.UnknownReturnCode(
|
|
|
|
file=sys.stderr) # @TODO Exception in Log
|
|
|
|
f"Could not add user '{username}' to group '{group}' with command '{cc}', returned '{rt}'",)
|
|
|
|
return False
|
|
|
|
|
|
|
|
return True
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
@staticmethod
|
|
|
@ -174,7 +169,7 @@ class System:
|
|
|
|
:type username: str
|
|
|
|
:type username: str
|
|
|
|
:param cc: Commands to execute to delete the user from the System(defaults to userdel -r)
|
|
|
|
:param cc: Commands to execute to delete the user from the System(defaults to userdel -r)
|
|
|
|
:type cc: tuple
|
|
|
|
:type cc: tuple
|
|
|
|
:return: True, when worked, False if not.
|
|
|
|
:return: True, if worked, raises lib.UserExceptions.UnknownReturnCode when not
|
|
|
|
:rtype: bool
|
|
|
|
:rtype: bool
|
|
|
|
"""
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
@ -186,11 +181,19 @@ class System:
|
|
|
|
else:
|
|
|
|
else:
|
|
|
|
ret = subprocess.call(cc)
|
|
|
|
ret = subprocess.call(cc)
|
|
|
|
if ret != 0:
|
|
|
|
if ret != 0:
|
|
|
|
print(f"Could not delete user with command {cc}. Return code: {ret}")
|
|
|
|
raise lib.UserExceptions.UnknownReturnCode(
|
|
|
|
return False
|
|
|
|
f"Could not delete user with command {cc}. Return code: {ret}")
|
|
|
|
return True
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def AIO(username, pubkey, group="tilde"):
|
|
|
|
|
|
|
|
syst = System(dryrun=False)
|
|
|
|
|
|
|
|
syst.register(username)
|
|
|
|
|
|
|
|
syst.lock_user_pw(username)
|
|
|
|
|
|
|
|
syst.add_to_usergroup(username, group)
|
|
|
|
|
|
|
|
syst.make_ssh_usable(username, pubkey)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
if __name__ == "__main__":
|
|
|
|
try:
|
|
|
|
try:
|
|
|
|
S = System(dryrun=True)
|
|
|
|
S = System(dryrun=True)
|
|
|
|