Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/python3.6
- # coding=utf-8
- import re, subprocess, shlex, sys
- class FTPuser:
- def __init__(self, _name, _share, _mode, _password, _isrNumber):
- self.name = _name
- self.share = _share
- self.mode = _mode
- self.password = _password
- self.isr = _isrNumber
- self.users = set() # tutaj trzymać wszystkich userów którzy mają pasujący login, hindus, hindus-s1 etc, etc,
- self.userGroups = set()
- self.workingUsername = None
- self.workingRWGroup = ""
- self.workingREGroup = ""
- self.checkIfUserExists()
- def setNewPassword(self):
- """
- works only on Red Hat Systems,
- sets user password to value of _password from constructor
- function works by default well :)
- jak się Niemcy beda rzucali, to można zrobić bezpośrednia edycje /etc/shadow,
- ale wolalbym sie w to nie wchodzić
- :return:
- """
- haslo = self.password
- haslo = haslo.encode() # we need byte oriented data to pass
- proc = subprocess.Popen(['passwd', '{0}'.format(self.workingUsername), '--stdin'], stdin=subprocess.PIPE)
- proc.stdin.write(haslo)
- proc.communicate()
- if proc.returncode != 0:
- print("There were problems with setting password")
- else:
- print("Password set up succesfully")
- def checkIfUserExists(self):
- """
- Tutaj generalnie zasada jest prosta:
- Tworzymy usera: username-s*
- najpierw leci regex i wychwytujemy ilu takich userów już istnieje
- następnie dodajemy wedle konwencji, np. a060626-s5
- jeden user = jeden folder
- :return:
- """
- reName = re.compile(r'^{0}-s.*'.format(self.name))
- with open("/etc/passwd", 'r') as rfile:
- for line in rfile.readlines():
- if reName.match(line):
- self.users.add(line.split(":")[0])
- userCount = len(self.users)
- def ReturnUserCount():
- Susers = len(userCount)
- if Susers == 0:
- workingUser = "{0}-s1".format(self.name)
- else:
- workingUser = "{0}-s{1}".format(self.name, str(len(Susers)+1))
- return workingUser
- def AddUser(_username):
- addUserCommand = "useradd -c \"Created by python script regarding to ISR number {0}\" -s /bin/false {0}".format(_username)
- thread = subprocess.Popen(shlex.split(addUserCommand))
- thread.wait()
- if thread.returncode != 0:
- print("Fatal Error when adding user")
- print(thread.stderr)
- exit(1)
- else:
- print("Added user: {0}".format(_username))
- self.setNewPassword()
- self.workingUsername = ReturnUserCount()
- AddUser(self.workingUsername)
- self.defaultRoot() #wywołać funkcję sprawdzającą
- def workingGroupNAmes(self):
- rwGRoups = set()
- reGroups = set()
- rwGroup = re.compile(r'^ftpRWusr.*')
- reGroup = re.compile(r'^ftpREusr.*')
- def ReturnGroupCount():
- RWGroups = len(rwGRoups)
- REGroups = len(reGroups)
- if RWGroups == 0:
- workingRWGroup = "ftpRWusr"
- else:
- workingRWGroup = "ftpRWusr{0}".format(str(len(RWGroups)+1))
- if REGroups == 0:
- workingREGroup = "ftpREusr"
- else:
- workingREGroup = "ftpREusr{0}".format(str(len(REGroups)+1))
- return workingRWGroup, workingREGroup
- def AddGroup(_group_name):
- addGroupCommand = "groupadd {0}".format(str(_group_name))
- print("Added group ftpRWusr")
- thread = subprocess.Popen(shlex.split(addGroupCommand))
- thread.wait()
- if thread.returncode != 0:
- print("Fatal Error when adding groups")
- print(thread.stderr)
- exit(1)
- else:
- print("Added group {0}".format(_group_name))
- with open("/etc/group", 'r') as groups:
- for line in groups.readlines():
- if rwGroup.match(line):
- rwGRoups.add(line) # musimy wiedzieć ile mamy grup RW żeby stworzyć kolejne
- if reGroup.match(line):
- reGroups.add(line) # musimy wiedziec ile mamy grup RE żeby stworzyć kolejne
- self.workingRWGroup, self.workingREGroup = ReturnGroupCount()
- AddGroup(self.workingRWGroup)
- AddGroup(self.workingREGroup)
- def defaultRoot(self):
- """
- Ta funkcja manipuluje bezpośrednio na kodzie /etc/proftpd.conf
- :return:
- """
- pathTosearch = re.compile(r'^{0}'.format(self.share)) #to jest nasz mountpoint podawany w klasie
- pathExists = False
- with open ("/etc/proftpd.conf", 'r') as rfile:
- for line in rfile.readlines():
- if line.startswith("DefaultRoot"):
- if pathTosearch.fullmatch(line.split()[1]): #jeśli ścieżka do której chcemy dodać naszego usera istnieje i jest skonfigurowana
- self.ManipulateText()
- pathExists = True
- break
- if pathExists == False:
- """
- jesli sciezka nie istnieje to:
- 1) Tworzymy 2 grupy: RW i RE wedle konwencji
- 2) dopisujemy dyrektywe DefaultRoot /sciezka grupa
- 3) Tworzymy blok tekstu <Directory /sciezka>, dopisujemy na koncu tekstu z odpowiednimi nowymi grupami
- """
- self.workingGroupNAmes()
- with open("/etc/proftpd.conf", "r") as _buf:
- bufor = _buf.readlines()
- defRootLineNum = 0
- for i, line in enumerate(bufor):
- if line.startswith("#DefaultRoot"):
- defRootLineNum = i
- bufor.insert(defRootLineNum+1, "DefaultRoot\t\t{0}\t\t{1}\n".format(self.share, self.workingRWGroup))
- bufor.insert(defRootLineNum + 1, "DefaultRoot\t\t{0}\t\t{1}\n".format(self.share, self.workingREGroup))
- bufor.append("\n<Directory {0}>"
- "\nUmask 0022"
- "\n<Limit WRITE>"
- "\n\tAllowGroup {1}"
- "\n</Limit>"
- "\n<Limit READ>"
- "\n\tAllowGroup {2}"
- "\n</Limit>"
- "\n</Directory>\n".format(self.share, self.workingRWGroup, self.workingREGroup))
- bufor = "".join(bufor)
- """
- Tutaj \/\/\/\/ zapisujemy plik z bufora pamięci
- """
- with open("/etc/proftpd.conf", 'w') as writeableFile:
- writeableFile.write(bufor)
- proc = subprocess.Popen(['sudo', 'mkdir','-p', '{0}'.format(self.share),]) # upewniamy się że taka ścieżka istnieje - to nie takie oczywiste jak się wydaje
- proc.wait()
- proc = subprocess.Popen(['systemctl', 'restart', 'proftpd']) # po kazdej zmianie w konfigach trzeba restartowac proftpd
- proc.wait()
- if proc.returncode != 0:
- print("Something went wrong when restarting proftpd, but it'ss restarted using ansible too, so don't worry, I'm here just for testing")
- else:
- print("Proftpd restarted sucessfully")
- else:
- print("Path currently exists - going to function ManipulateText()")
- self.ManipulateText()
- def ManipulateText(self):
- """
- Where the magic happens, regexami wyszukujemy odpowiednie linie konfigów i wyciagami wie dyrektywy AllowGroup bo one s w zasadzie tylko kluczowe
- :return:
- """
- dirRegex = re.compile(r'^<Directory {0}>'.format(self.share), re.IGNORECASE)
- endDirRegex = re.compile(r'</Directory>', re.IGNORECASE)
- limitWriteRegex = re.compile(r'<Limit WRITE>', re.IGNORECASE)
- limitREADRegex = re.compile(r'<Limit READ>', re.IGNORECASE)
- limitALLRegex = re.compile(r'<Limit ALL>', re.IGNORECASE)
- limitEND = re.compile(r'</Limit>',re.IGNORECASE)
- allowGroupREGEX = re.compile(r'AllowGroup.*', re.IGNORECASE)
- conf_line = 0
- end_conf_line = 0
- limit_write_found = False
- limit_write_position = 0
- limit_read_found = False
- limit_read_position = 0
- limit_all_found = False
- limit_all_position = 0
- with open('/etc/proftpd.conf', 'r') as proconf:
- lines = proconf.readlines()
- for i, val in enumerate(lines):
- if dirRegex.match(val):
- conf_line = i
- while True:
- if limitWriteRegex.search(lines[conf_line]):
- limit_write_found = True
- limit_write_position = conf_line
- if limitREADRegex.search(lines[conf_line]):
- limit_read_found = True
- limit_read_position = conf_line
- if limitALLRegex.search(lines[conf_line]):
- limit_all_found = True
- limit_all_position = conf_line
- if endDirRegex.search(lines[conf_line]):
- end_conf_line = conf_line
- break
- conf_line += 1
- def AddUserToGroup(_start_index):
- for i in range(_start_index, end_conf_line):
- if allowGroupREGEX.search(lines[i]):
- addToGroupCommand = "usermod -aG {0} {1}".format(lines[i].split()[1], self.workingUsername)
- thread = subprocess.Popen(shlex.split(addToGroupCommand))
- thread.wait()
- if thread.returncode != 0:
- print("Can't add user: {0}, to group {1}".format(self.workingUsername, lines[i].split()[1]))
- else:
- print("Added user: {0}, to group {1}".format(self.workingUsername, lines[i].split()[1]))
- # self.addACLonTheMountpoint() #Windows subsystem linux nie obsluguje ACL - bede testował an prodzie
- if limitEND.match(lines[i]):
- break
- if self.mode == "rw":
- if limit_write_found == True:
- AddUserToGroup(limit_write_position)
- if limit_all_found == True:
- AddUserToGroup(limit_all_position)
- if self.mode == "ro" and limit_read_found==True:
- AddUserToGroup(limit_read_position)
- print("Everything went fine, exiting")
- exit(0)
- if __name__ == '__main__':
- #a050525 = FTPuser("a060626", "/opt/jboss", "rw", "haselko", "1023120937")
- if len(sys.args) != 6:
- print("Not enough arguments, please find below documentation:"
- "\nArg 1: username [a060626]"
- "\nArg 2: share [/opt/jboss/data]"
- "\nArg 3: mode [rw|ro = read-write, read-only]"
- "\nArg 4: password [not the best security, but whatever]"
- "\nArg 5: TicketNumber: [21321321]"
- "\nExample: "
- "\nuser@serer:/current/directory$ ./main.py a060626 /opt/jboss dbsrv23 rw badpassword 324324342")
- else:
- usr = FTPuser(sys.args[1],sys.args[2],sys.args[3],sys.args[4], sys.args[5])
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement