Advertisement
Guest User

Untitled

a guest
Nov 12th, 2019
104
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 11.67 KB | None | 0 0
  1. #!/usr/bin/python3.6
  2. # coding=utf-8
  3.  
  4. import re, subprocess, shlex, sys
  5.  
  6. class FTPuser:
  7.     def __init__(self, _name, _share, _mode, _password, _isrNumber):
  8.         self.name               = _name
  9.         self.share              = _share
  10.         self.mode               = _mode
  11.         self.password           = _password
  12.         self.isr                = _isrNumber
  13.         self.users              = set()  # tutaj trzymać wszystkich userów którzy mają pasujący login, hindus, hindus-s1 etc, etc,
  14.         self.userGroups         = set()
  15.         self.workingUsername    = None
  16.         self.workingRWGroup     = ""
  17.         self.workingREGroup     = ""
  18.         self.checkIfUserExists()
  19.  
  20.  
  21.     def setNewPassword(self):
  22.         """
  23.                works only on Red Hat Systems,
  24.                sets user password to value of _password from constructor
  25.                function works by default well :)
  26.  
  27.  
  28.                jak się Niemcy beda rzucali, to można zrobić bezpośrednia edycje /etc/shadow,
  29.                ale wolalbym sie w to nie wchodzić
  30.                :return:
  31.        """
  32.         haslo = self.password
  33.         haslo = haslo.encode() # we need byte oriented data to pass
  34.         proc = subprocess.Popen(['passwd', '{0}'.format(self.workingUsername), '--stdin'], stdin=subprocess.PIPE)
  35.         proc.stdin.write(haslo)
  36.         proc.communicate()
  37.  
  38.         if proc.returncode != 0:
  39.             print("There were problems with setting password")
  40.         else:
  41.             print("Password set up succesfully")
  42.  
  43.  
  44.     def checkIfUserExists(self):
  45.         """
  46.        Tutaj generalnie zasada jest prosta:
  47.        Tworzymy usera: username-s*
  48.        najpierw leci regex i wychwytujemy ilu takich userów już istnieje
  49.        następnie dodajemy wedle konwencji, np. a060626-s5
  50.        jeden user = jeden folder
  51.        :return:
  52.        """
  53.         reName = re.compile(r'^{0}-s.*'.format(self.name))
  54.         with open("/etc/passwd", 'r') as rfile:
  55.             for line in rfile.readlines():
  56.                 if reName.match(line):
  57.                     self.users.add(line.split(":")[0])
  58.  
  59.         userCount = len(self.users)
  60.  
  61.         def ReturnUserCount():
  62.             Susers = len(userCount)
  63.  
  64.             if Susers == 0:
  65.                 workingUser = "{0}-s1".format(self.name)
  66.             else:
  67.                 workingUser = "{0}-s{1}".format(self.name, str(len(Susers)+1))
  68.  
  69.             return workingUser
  70.  
  71.         def AddUser(_username):
  72.             addUserCommand = "useradd -c \"Created by python script regarding to ISR number {0}\" -s /bin/false {0}".format(_username)
  73.             thread = subprocess.Popen(shlex.split(addUserCommand))
  74.             thread.wait()
  75.             if thread.returncode != 0:
  76.                 print("Fatal Error when adding user")
  77.                 print(thread.stderr)
  78.                 exit(1)
  79.             else:
  80.                 print("Added user: {0}".format(_username))
  81.                 self.setNewPassword()
  82.  
  83.  
  84.         self.workingUsername = ReturnUserCount()
  85.         AddUser(self.workingUsername)
  86.  
  87.         self.defaultRoot() #wywołać funkcję sprawdzającą
  88.  
  89.     def workingGroupNAmes(self):
  90.         rwGRoups = set()
  91.         reGroups = set()
  92.         rwGroup = re.compile(r'^ftpRWusr.*')
  93.         reGroup = re.compile(r'^ftpREusr.*')
  94.  
  95.         def ReturnGroupCount():
  96.             RWGroups = len(rwGRoups)
  97.             REGroups = len(reGroups)
  98.  
  99.             if RWGroups == 0:
  100.                 workingRWGroup = "ftpRWusr"
  101.             else:
  102.                 workingRWGroup = "ftpRWusr{0}".format(str(len(RWGroups)+1))
  103.  
  104.             if REGroups == 0:
  105.                 workingREGroup = "ftpREusr"
  106.             else:
  107.                 workingREGroup = "ftpREusr{0}".format(str(len(REGroups)+1))
  108.  
  109.             return workingRWGroup, workingREGroup
  110.  
  111.         def AddGroup(_group_name):
  112.             addGroupCommand = "groupadd {0}".format(str(_group_name))
  113.             print("Added group ftpRWusr")
  114.             thread = subprocess.Popen(shlex.split(addGroupCommand))
  115.             thread.wait()
  116.             if thread.returncode != 0:
  117.                 print("Fatal Error when adding groups")
  118.                 print(thread.stderr)
  119.                 exit(1)
  120.             else:
  121.                 print("Added group {0}".format(_group_name))
  122.  
  123.         with open("/etc/group", 'r') as groups:
  124.             for line in groups.readlines():
  125.                 if rwGroup.match(line):
  126.                     rwGRoups.add(line)  # musimy wiedzieć ile mamy grup RW żeby stworzyć kolejne
  127.                 if reGroup.match(line):
  128.                     reGroups.add(line)  # musimy wiedziec ile mamy grup RE żeby stworzyć kolejne
  129.  
  130.  
  131.         self.workingRWGroup, self.workingREGroup = ReturnGroupCount()
  132.  
  133.         AddGroup(self.workingRWGroup)
  134.         AddGroup(self.workingREGroup)
  135.  
  136.  
  137.  
  138.     def defaultRoot(self):
  139.         """
  140.        Ta funkcja manipuluje bezpośrednio na kodzie /etc/proftpd.conf
  141.        :return:
  142.        """
  143.         pathTosearch = re.compile(r'^{0}'.format(self.share)) #to jest nasz mountpoint podawany w klasie
  144.         pathExists = False
  145.         with open ("/etc/proftpd.conf", 'r') as rfile:
  146.             for line in rfile.readlines():
  147.                 if line.startswith("DefaultRoot"):
  148.                     if pathTosearch.fullmatch(line.split()[1]):  #jeśli ścieżka do której chcemy dodać naszego usera istnieje i jest skonfigurowana
  149.                         self.ManipulateText()
  150.                         pathExists = True
  151.                         break
  152.  
  153.  
  154.         if pathExists == False:
  155.             """
  156.            jesli sciezka nie istnieje to:
  157.            1) Tworzymy 2 grupy: RW i RE wedle konwencji
  158.            2) dopisujemy dyrektywe DefaultRoot /sciezka grupa
  159.            3) Tworzymy blok tekstu <Directory /sciezka>, dopisujemy na koncu tekstu z odpowiednimi nowymi grupami
  160.            """
  161.             self.workingGroupNAmes()
  162.  
  163.             with open("/etc/proftpd.conf", "r") as _buf:
  164.                 bufor = _buf.readlines()
  165.                 defRootLineNum = 0
  166.                 for i, line in enumerate(bufor):
  167.                     if line.startswith("#DefaultRoot"):
  168.                         defRootLineNum = i
  169.  
  170.             bufor.insert(defRootLineNum+1, "DefaultRoot\t\t{0}\t\t{1}\n".format(self.share, self.workingRWGroup))
  171.             bufor.insert(defRootLineNum + 1, "DefaultRoot\t\t{0}\t\t{1}\n".format(self.share, self.workingREGroup))
  172.             bufor.append("\n<Directory {0}>"
  173.                          "\nUmask 0022"
  174.                          "\n<Limit WRITE>"
  175.                          "\n\tAllowGroup {1}"
  176.                          "\n</Limit>"
  177.                          "\n<Limit READ>"
  178.                          "\n\tAllowGroup {2}"
  179.                          "\n</Limit>"
  180.                          "\n</Directory>\n".format(self.share, self.workingRWGroup, self.workingREGroup))
  181.             bufor = "".join(bufor)
  182.  
  183.             """
  184.            Tutaj \/\/\/\/ zapisujemy plik z bufora pamięci
  185.            """
  186.             with open("/etc/proftpd.conf", 'w') as writeableFile:
  187.                 writeableFile.write(bufor)
  188.  
  189.  
  190.             proc = subprocess.Popen(['sudo', 'mkdir','-p', '{0}'.format(self.share),])  # upewniamy się że taka ścieżka istnieje - to nie takie oczywiste jak się wydaje
  191.             proc.wait()
  192.             proc = subprocess.Popen(['systemctl', 'restart', 'proftpd'])                # po kazdej zmianie w konfigach trzeba restartowac proftpd
  193.             proc.wait()
  194.             if proc.returncode != 0:
  195.                 print("Something went wrong when restarting proftpd, but it'ss restarted using ansible too, so don't worry, I'm here just for testing")
  196.             else:
  197.                 print("Proftpd restarted sucessfully")
  198.         else:
  199.             print("Path currently exists - going to function ManipulateText()")
  200.         self.ManipulateText()
  201.  
  202.     def ManipulateText(self):
  203.         """
  204.        Where the magic happens, regexami wyszukujemy odpowiednie linie konfigów i wyciagami wie dyrektywy AllowGroup bo one s w zasadzie tylko kluczowe
  205.        :return:
  206.        """
  207.         dirRegex        = re.compile(r'^<Directory {0}>'.format(self.share), re.IGNORECASE)
  208.         endDirRegex     = re.compile(r'</Directory>', re.IGNORECASE)
  209.         limitWriteRegex = re.compile(r'<Limit WRITE>', re.IGNORECASE)
  210.         limitREADRegex  = re.compile(r'<Limit READ>', re.IGNORECASE)
  211.         limitALLRegex   = re.compile(r'<Limit ALL>', re.IGNORECASE)
  212.         limitEND        = re.compile(r'</Limit>',re.IGNORECASE)
  213.         allowGroupREGEX = re.compile(r'AllowGroup.*', re.IGNORECASE)
  214.         conf_line = 0
  215.         end_conf_line = 0
  216.         limit_write_found = False
  217.         limit_write_position = 0
  218.         limit_read_found = False
  219.         limit_read_position = 0
  220.         limit_all_found = False
  221.         limit_all_position = 0
  222.  
  223.         with open('/etc/proftpd.conf', 'r') as proconf:
  224.             lines = proconf.readlines()
  225.  
  226.         for i, val in enumerate(lines):
  227.             if dirRegex.match(val):
  228.                 conf_line = i
  229.  
  230.         while True:
  231.             if limitWriteRegex.search(lines[conf_line]):
  232.                 limit_write_found = True
  233.                 limit_write_position = conf_line
  234.  
  235.             if limitREADRegex.search(lines[conf_line]):
  236.                 limit_read_found = True
  237.                 limit_read_position = conf_line
  238.  
  239.             if limitALLRegex.search(lines[conf_line]):
  240.                 limit_all_found = True
  241.                 limit_all_position = conf_line
  242.  
  243.             if endDirRegex.search(lines[conf_line]):
  244.                 end_conf_line = conf_line
  245.                 break
  246.             conf_line += 1
  247.  
  248.             def AddUserToGroup(_start_index):
  249.                 for i in range(_start_index, end_conf_line):
  250.                     if allowGroupREGEX.search(lines[i]):
  251.                         addToGroupCommand = "usermod -aG {0} {1}".format(lines[i].split()[1], self.workingUsername)
  252.                         thread = subprocess.Popen(shlex.split(addToGroupCommand))
  253.                         thread.wait()
  254.                         if thread.returncode != 0:
  255.                             print("Can't add user: {0}, to group {1}".format(self.workingUsername, lines[i].split()[1]))
  256.                         else:
  257.                             print("Added user: {0}, to group {1}".format(self.workingUsername, lines[i].split()[1]))
  258.                         # self.addACLonTheMountpoint()   #Windows subsystem linux nie obsluguje ACL - bede testował an prodzie
  259.                     if limitEND.match(lines[i]):
  260.                         break
  261.  
  262.             if self.mode == "rw":
  263.                 if limit_write_found == True:
  264.                     AddUserToGroup(limit_write_position)
  265.                 if limit_all_found == True:
  266.                     AddUserToGroup(limit_all_position)
  267.  
  268.             if self.mode == "ro" and limit_read_found==True:
  269.                 AddUserToGroup(limit_read_position)
  270.  
  271.         print("Everything went fine, exiting")
  272.         exit(0)
  273.  
  274. if __name__ == '__main__':
  275.     #a050525 = FTPuser("a060626", "/opt/jboss", "rw", "haselko", "1023120937")
  276.     if len(sys.args) != 6:
  277.         print("Not enough arguments, please find below documentation:"
  278.               "\nArg 1: username        [a060626]"
  279.               "\nArg 2: share           [/opt/jboss/data]"
  280.               "\nArg 3: mode            [rw|ro = read-write, read-only]"
  281.               "\nArg 4: password        [not the best security, but whatever]"
  282.               "\nArg 5: TicketNumber:   [21321321]"
  283.               "\nExample: "
  284.               "\nuser@serer:/current/directory$ ./main.py a060626 /opt/jboss dbsrv23 rw badpassword 324324342")
  285.     else:
  286.         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