<s> """<STR_LIT>""" <EOL> import errno <EOL> import grp <EOL> import logging <EOL> import os <EOL> import pwd <EOL> import re <EOL> import stat <EOL> import tempfile <EOL> import time <EOL> def EnsureTrailingNewline ( line ) : <EOL> if line . endswith ( '<STR_LIT:\n>' ) : <EOL> return line <EOL> return line + '<STR_LIT:\n>' <EOL> def IsUserSudoerInLines ( user , sudoer_lines ) : <EOL> """<STR_LIT>""" <EOL> def IsUserSudoerEntry ( line ) : <EOL> return re . match ( r'<STR_LIT>' % user , line ) <EOL> return filter ( IsUserSudoerEntry , sudoer_lines ) <EOL> class Accounts ( object ) : <EOL> """<STR_LIT>""" <EOL> VALID_USERNAME_CHARS = set ( <EOL> map ( chr , range ( ord ( '<STR_LIT:A>' ) , ord ( '<STR_LIT>' ) + <NUM_LIT:1> ) ) + <EOL> map ( chr , range ( ord ( '<STR_LIT:a>' ) , ord ( '<STR_LIT:z>' ) + <NUM_LIT:1> ) ) + <EOL> map ( chr , range ( ord ( '<STR_LIT:0>' ) , ord ( '<STR_LIT>' ) + <NUM_LIT:1> ) ) + <EOL> [ '<STR_LIT:_>' , '<STR_LIT:->' , '<STR_LIT:.>' ] ) <EOL> def __init__ ( self , grp_module = grp , os_module = os , <EOL> pwd_module = pwd , system_module = None , <EOL> urllib2_module = None , time_module = time ) : <EOL> """<STR_LIT>""" <EOL> self . system_module = system_module <EOL> self . grp = grp_module <EOL> self . os = os_module <EOL> self . pwd = pwd_module <EOL> self . system = system_module <EOL> self . time_module = time_module <EOL> self . urllib2 = urllib2_module <EOL> self . default_user_groups = self . GroupsThatExist ( <EOL> [ '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' ] ) <EOL> def UpdateUser ( self , username , ssh_keys ) : <EOL> """<STR_LIT>""" <EOL> if not self . IsValidUsername ( username ) : <EOL> logging . warning ( <EOL> '<STR_LIT>' <EOL> '<STR_LIT>' , username ) <EOL> return <EOL> if not self . UserExists ( username ) : <EOL> self . system . UserAdd ( username , self . default_user_groups ) <EOL> if self . UserExists ( username ) : <EOL> if self . UserNoLogin ( username ) : <EOL> logging . debug ( <EOL> '<STR_LIT>' <EOL> '<STR_LIT>' , username ) <EOL> return <EOL> if ssh_keys : <EOL> self . MakeUserSudoer ( username ) <EOL> self . AuthorizeSshKeys ( username , ssh_keys ) <EOL> def IsValidUsername ( self , username ) : <EOL> """<STR_LIT>""" <EOL> def InvalidCharacterFilter ( c ) : <EOL> return c not in Accounts . VALID_USERNAME_CHARS <EOL> if filter ( InvalidCharacterFilter , username ) : <EOL> return False <EOL> if username . startswith ( '<STR_LIT:->' ) : <EOL> return False <EOL> return True <EOL> def GroupsThatExist ( self , groups_list ) : <EOL> """<STR_LIT>""" <EOL> def GroupExists ( group ) : <EOL> try : <EOL> self . grp . getgrnam ( group ) <EOL> return True <EOL> except KeyError : <EOL> return False <EOL> return filter ( GroupExists , groups_list ) <EOL> def GetUserInfo ( self , user ) : <EOL> """<STR_LIT>""" <EOL> pwent = self . pwd . getpwnam ( user ) <EOL> return ( pwent . pw_dir , pwent . pw_uid , pwent . pw_gid ) <EOL> def UserExists ( self , user ) : <EOL> """<STR_LIT>""" <EOL> try : <EOL> self . pwd . getpwnam ( user ) <EOL> return True <EOL> except KeyError : <EOL> return False <EOL> def UserNoLogin ( self , user ) : <EOL> """<STR_LIT>""" <EOL> pwent = self . pwd . getpwnam ( user ) <EOL> return pwent . pw_shell == '<STR_LIT>' <EOL> def LockSudoers ( self ) : <EOL> """<STR_LIT>""" <EOL> try : <EOL> f = self . os . open ( '<STR_LIT>' , os . O_EXCL | os . O_CREAT ) <EOL> self . os . close ( f ) <EOL> return True <EOL> except OSError as e : <EOL> if e . errno == errno . EEXIST : <EOL> logging . warning ( '<STR_LIT>' ) <EOL> else : <EOL> logging . warning ( '<STR_LIT>' , e ) <EOL> return False <EOL> def UnlockSudoers ( self ) : <EOL> """<STR_LIT>""" <EOL> try : <EOL> self . os . unlink ( '<STR_LIT>' ) <EOL> return True <EOL> except OSError as e : <EOL> if e . errno == errno . ENOENT : <EOL> return True <EOL> logging . warning ( '<STR_LIT>' , e ) <EOL> return False <EOL> def MakeUserSudoer ( self , user ) : <EOL> """<STR_LIT>""" <EOL> if not self . os . path . isfile ( '<STR_LIT>' ) : <EOL> logging . info ( '<STR_LIT>' , <EOL> user ) <EOL> return <EOL> with self . system . OpenFile ( '<STR_LIT>' , '<STR_LIT:r>' ) as sudoer_f : <EOL> sudoer_lines = sudoer_f . readlines ( ) <EOL> if IsUserSudoerInLines ( user , sudoer_lines ) : <EOL> return <EOL> if not self . LockSudoers ( ) : <EOL> logging . warning ( '<STR_LIT>' , <EOL> user ) <EOL> return <EOL> try : <EOL> with self . system . OpenFile ( '<STR_LIT>' , '<STR_LIT:r>' ) as sudoer_f : <EOL> sudoer_lines = sudoer_f . readlines ( ) <EOL> if IsUserSudoerInLines ( user , sudoer_lines ) : <EOL> return <EOL> sudoer_lines . append ( '<STR_LIT>' % user ) <EOL> sudoer_lines = [ EnsureTrailingNewline ( line ) for line in sudoer_lines ] <EOL> ( tmp_sudoers_fd , tmp_sudoers_fname ) = tempfile . mkstemp ( ) <EOL> with self . os . fdopen ( tmp_sudoers_fd , '<STR_LIT>' ) as tmp_sudoer_f : <EOL> tmp_sudoer_f . writelines ( sudoer_lines ) <EOL> tmp_sudoer_f . seek ( <NUM_LIT:0> ) <EOL> try : <EOL> if not self . system . IsValidSudoersFile ( tmp_sudoers_fname ) : <EOL> logging . warning ( <EOL> '<STR_LIT>' , user ) <EOL> return <EOL> self . os . chmod ( '<STR_LIT>' , <NUM_LIT:0> <NUM_LIT> ) <EOL> with self . system . OpenFile ( '<STR_LIT>' , '<STR_LIT:w>' ) as sudoer_f : <EOL> sudoer_f . writelines ( sudoer_lines ) <EOL> self . os . fchmod ( sudoer_f . fileno ( ) , stat . S_IWUSR | <NUM_LIT:0> <NUM_LIT> ) <EOL> try : <EOL> self . os . fchmod ( sudoer_f . fileno ( ) , <NUM_LIT:0> <NUM_LIT> ) <EOL> except ( IOError , OSError ) as e : <EOL> logging . warning ( '<STR_LIT>' , e ) <EOL> finally : <EOL> try : <EOL> self . os . unlink ( tmp_sudoers_fname ) <EOL> except ( IOError , OSError ) as e : <EOL> pass <EOL> except ( IOError , OSError ) as e : <EOL> logging . warning ( '<STR_LIT>' , user , e ) <EOL> finally : <EOL> self . UnlockSudoers ( ) <EOL> def AuthorizeSshKeys ( self , user , ssh_keys ) : <EOL> """<STR_LIT>""" <EOL> ( home_dir , uid , gid ) = self . GetUserInfo ( user ) <EOL> ssh_dir = os . path . join ( home_dir , '<STR_LIT>' ) <EOL> if not self . os . path . isdir ( ssh_dir ) : <EOL> if not self . EnsureHomeDir ( home_dir , uid , gid ) : <EOL> return False <EOL> if not self . EnsureDir ( ssh_dir , uid , gid , <NUM_LIT:0> <NUM_LIT> ) : <EOL> return False <EOL> authorized_keys_file = os . path . join ( ssh_dir , '<STR_LIT>' ) <EOL> try : <EOL> self . WriteAuthorizedSshKeysFile ( authorized_keys_file , ssh_keys , uid , gid ) <EOL> except IOError as e : <EOL> logging . warning ( '<STR_LIT>' , authorized_keys_file , e ) <EOL> def SetSELinuxContext ( self , path ) : <EOL> """<STR_LIT>""" <EOL> if self . system . IsExecutable ( '<STR_LIT>' ) : <EOL> result = self . system . RunCommand ( [ '<STR_LIT>' , path ] ) <EOL> if self . system . RunCommandFailed ( result ) : <EOL> logging . error ( '<STR_LIT>' , path ) <EOL> return False <EOL> else : <EOL> return True <EOL> else : <EOL> logging . debug ( '<STR_LIT>' , <EOL> path ) <EOL> return True <EOL> def EnsureHomeDir ( self , home_dir , uid , gid ) : <EOL> """<STR_LIT>""" <EOL> if self . os . path . isdir ( home_dir ) : <EOL> return True <EOL> if not self . EnsureDir ( home_dir , <NUM_LIT:0> , <NUM_LIT:0> , <NUM_LIT:0> <NUM_LIT> ) : <EOL> return False <EOL> self . os . chown ( home_dir , uid , gid ) <EOL> return True <EOL> def EnsureDir ( self , dir_path , uid , gid , mode ) : <EOL> """<STR_LIT>""" <EOL> if self . os . path . isdir ( dir_path ) : <EOL> return True <EOL> parent_dir = self . os . path . dirname ( dir_path ) <EOL> if not parent_dir == dir_path : <EOL> if not self . EnsureDir ( parent_dir , uid , gid , <NUM_LIT:0> <NUM_LIT> ) : <EOL> return False <EOL> try : <EOL> self . os . mkdir ( dir_path , mode ) <EOL> self . os . chown ( dir_path , uid , gid ) <EOL> self . SetSELinuxContext ( dir_path ) <EOL> except OSError as e : <EOL> if self . os . path . isdir ( dir_path ) : <EOL> logging . warning ( '<STR_LIT>' , dir_path , e ) <EOL> return True <EOL> logging . error ( '<STR_LIT>' , dir_path , e ) <EOL> return False <EOL> return True <EOL> def WriteAuthorizedSshKeysFile ( <EOL> self , authorized_keys_file , ssh_keys , uid , gid ) : <EOL> """<STR_LIT>""" <EOL> with self . system . CreateTempFile ( delete = False ) as keys_file : <EOL> new_keys_path = keys_file . name <EOL> if self . os . path . exists ( authorized_keys_file ) : <EOL> with self . system . OpenFile ( authorized_keys_file , '<STR_LIT:r>' ) as original_keys : <EOL> original_keys . seek ( <NUM_LIT:0> ) <EOL> lines = original_keys . readlines ( ) <EOL> else : <EOL> lines = [ ] <EOL> google_added_ixs = [ i for i in range ( len ( lines ) - <NUM_LIT:1> ) if <EOL> lines [ i ] . startswith ( '<STR_LIT>' ) ] <EOL> google_added_ixs += [ i + <NUM_LIT:1> for i in google_added_ixs ] <EOL> user_lines = [ <EOL> lines [ i ] for i in range ( len ( lines ) ) if i not in google_added_ixs ] <EOL> for user_line in user_lines : <EOL> keys_file . write ( EnsureTrailingNewline ( user_line ) ) <EOL> for ssh_key in ssh_keys : <EOL> keys_file . write ( '<STR_LIT>' ) <EOL> keys_file . write ( EnsureTrailingNewline ( ssh_key ) ) <EOL> stat = self . os . statvfs ( self . os . path . dirname ( authorized_keys_file ) ) <EOL> available_space = stat . f_bavail * stat . f_bsize <EOL> required_space = self . os . path . getsize ( new_keys_path ) + <NUM_LIT> * <NUM_LIT> <EOL> logging . debug ( '<STR_LIT>' , <EOL> required_space , available_space ) <EOL> if available_space < required_space : <EOL> raise IOError ( '<STR_LIT>' ) <EOL> try : <EOL> self . system . MoveFile ( new_keys_path , authorized_keys_file ) <EOL> finally : <EOL> try : <EOL> self . system . DeleteFile ( new_keys_path ) <EOL> except : <EOL> pass <EOL> self . os . chmod ( authorized_keys_file , <NUM_LIT:0> <NUM_LIT> ) <EOL> self . os . chown ( authorized_keys_file , uid , gid ) <EOL> self . SetSELinuxContext ( authorized_keys_file ) </s>
