Back to the main page

The python script to create user's home

Intro

Basically, there are two LDAP directories, DSEE (Oracle's directory service enterprise edition), and CA-LDAP (freeIPA). DSEE is older and most people have account there and home. IPA is newer, hence we create account with UID to match DSEE one, and then I wrote this python script to create a home.

Algorithm



The script


#!/usr/bin/env python
# Zarko, 2018
# see the algorithm
# ---------------------------------------

from time import gmtime, strftime
import os
import getpass
import subprocess
import sys
import paramiko
import argparse
import logging, logging.handlers
# for sending email
import smtplib
from email.mime.image import MIMEImage
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText

# ------------ define colors
class color:
 PURPLE = '\033[95m'
 CYAN = '\033[96m'
 DARKCYAN = '\033[36m'
 BLUE = '\033[94m'
 GREEN = '\033[92m'
 YELLOW = '\033[93m'
 RED = '\033[91m'
 BOLD = '\033[1m'
 UNDERLINE = '\033[4m'
 END = '\033[0m'

# ------------------ define LOGGING -----------
LOG_FILE = '/var/log/mkipahome/mkipahome.log'
formatter = logging.Formatter('%(asctime)s:%(levelname)s: %(message)s')
handler = logging.handlers.TimedRotatingFileHandler(LOG_FILE, when='MIDNIGHT', backupCount=50, utc=False)
handler.setFormatter(formatter)
# Set up a specific logger with our desired output level
logger = logging.getLogger(__name__)
#logger = logging.getLogger('MyLogger')
logger.addHandler(handler)
logger.setLevel(logging.DEBUG)
# -- BASIC logging, no rotation
#logging.basicConfig(filename=LOG_FILE, level=logging.DEBUG, format='%(asctime)s : %(message)s')
# -- if you don't want log into file, but on screen
#logging.basicConfig(level=logging.DEBUG, format='%(asctime)s : %(message)s')
# ----------------------------------------------

logger.debug("")
logger.debug(color.GREEN + "START AT : " + strftime("%a, %d %b %Y %H:%M:%S", gmtime()) + color.END)

# -------------- Am I root ?
def i_am_root():
  """ Check if root runs script """
  i_am=getpass.getuser()
  return True if i_am != "root" else False
if not i_am_root():
  logger.debug(color.RED + "Root can't run this script, quitting."  + color.END + " Do it as yourself, since you'll need to SSH to other systems.")
  sys.exit(color.RED + "\nRoot can't run this script, quitting."  + color.END + "\nDo it as yourself, since you'll need to SSH to other systems.\n")

# ---------------- get who runs script
i_am=getpass.getuser()
logger.debug("The script is run by " + i_am)

# --------------- check for kerberos ticket
def has_kerberos_ticket():
   """
   Does a user who runs the script have valid kerberos ticket?
   """
   return True if subprocess.call(['klist', '-s']) == 0 else False
logger.debug("Check if operator has kerberos ticket")
if not has_kerberos_ticket():
   logger.debug("You do not have a kerberos ticket! Run 'kinit' to obtain one. Quitting.")
   sys.exit("You do not have a kerberos ticket! Run 'kinit' to obtain one. Quitting.")
logger.debug("Seems that operator has kerberos ticket")

# ------------------ argument work
parser = argparse.ArgumentParser(description='Creation of CA-LDAP home.')
parser.add_argument("-u", "--username", help="User who needs CA-LDAP home, must be CA-LDAP user login", required=True)
args = parser.parse_args()
user_name=args.username

# ------------ user in IPA ?
def user_in_ipa():
   """ Check if user has IPA account """
   return True if subprocess.call(['ipa', 'user-find', '--login', '%s' % user_name]) == 0 else False
if not user_in_ipa():
   logger.debug(color.RED + "User " + user_name + " doesn't exist in CA-LDAP, exiting!" + color.END)
   sys.exit(color.RED + "User with login name %s doesn't exist in CA-LDAP, exiting!" % user_name + color.END)
else:
   print (color.GREEN  + "OK : Good, user %s exists in CA-LDAP" % user_name + color.END)
   logger.debug("OK : Good, user %s exists in CA-LDAP" % user_name)

# ---------------- ask for passwords
logger.debug(color.CYAN + "Start asking for dsee/ca-ldap passwords" + color.END)

print("\nGood day " + color.YELLOW + i_am + color.END + ". You'll need " + color.BOLD + color.RED + "CA-LDAP" + color.END +
" and " + color.BOLD + color.RED + "DSEE" + color.END + " account for this to work. \n" +
"Since you are here, you have CA-LDAP one, but if you don't have DSEE one, \n" +
"then exit with ctrl+d and get DSEE account " + color.UNDERLINE + "ASAP." + color.END + "\n" +
"Meanwhile, ask CA-LDAP SME for help. \n" +
"\n")

my_dsee_passwd=raw_input(color.GREEN + "Enter DSEE password: " + color.END + "\n" +
"Note: if you use public key to SSH to DSEE systems (used to check for DSEE home)," +
" then anything you type here will work." +
"\n")

my_ipa_passwd=raw_input(color.GREEN + "Enter CA-LDAP password: " + color.END + "\n" +
"Note: if you use public key to SSH to ca-server4 (used to create CA-LDAP home)," +
" then anything you type here will work." +
"\n")

logger.debug(color.CYAN + "Done with asking for dsee/ca-ldap passwords" + color.END)
# --------------------------------------------------------------------------------------

dsee_server="dsee-server-whq.us.domain.com"
print("INFO : Using DSEE server : %s") % dsee_server
logger.debug(color.CYAN + "Using DSEE server " + dsee_server + color.END)

def user_in_dsee():
   """
   Check if user has DSEE account.
   """
   try:
       client = paramiko.SSHClient()
       print("INFO : Checking if %s exist in DSEE") % user_name
       logger.debug(color.CYAN + "Checking if " + user_name + " exist in DSEE" + color.END)
       client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
       client.connect(hostname=dsee_server, username=i_am, password=my_dsee_passwd)
       stdin, stdout, stderr = client.exec_command('/usr/bin/id %s' % user_name, get_pty=True)
       if stdout.channel.recv_exit_status() == 0:
          print("INFO : User %s has DSEE account.") % user_name
          logger.debug(color.CYAN + "User " + user_name + " has DSEE account." + color.END)
          automount_in_dsee()
       else:
          print("INFO : User %s does not have DSEE account.") % user_name
          logger.debug(color.CYAN + "User " + user_name + " does not have DSEE account." + color.END)
          ipa_home_exist()
   except paramiko.AuthenticationException:
       print ("ERROR : DSEE Auth failed")
       logger.debug(color.RED + "DSEE Auth failed" + color.END)
       sys.exit(10)
   except:
       print ("ERROR : DSEE connection failed for %s") % dsee_server
       logger.debug(color.RED + "DSEE connection failed for " + dsee_server + color.END)
       sys.exit(15)
       close()


def automount_in_dsee():
   """
   Check existance of DSEE automount.
   Need to define one global variable, to use in other functions
   """
   global dsee_automount_info
   try:
       client = paramiko.SSHClient()
       print ("INFO : Check if  %s has DSEE automount") % user_name
       logger.debug(color.CYAN + "Check if " + user_name +  " has DSEE automount" + color.END)
       client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
       client.connect(hostname=dsee_server, username=i_am, password=my_dsee_passwd)
       stdin, stdout, stderr = client.exec_command('/usr/bin/ldaplist -l auto_home %s | grep automountInformation' % user_name, get_pty=True)
       # exit status of remote command
       # print stdout.channel.recv_exit_status()
       if stdout.channel.recv_exit_status() == 0:
          lines = stdout.readlines()
          for line in lines:
             dsee_automount_info=line.replace("automountInformation:", "").strip()
             print ("OK : DSEE automount for %s is %s") % (user_name, dsee_automount_info)
             logger.debug(color.GREEN + "DSEE automount for " + user_name + " is " + dsee_automount_info + color.END)
             create_ipa_automount_dsee_home()
       else:
             print("INFO : User %s does not have DSEE automount.") % user_name
             logger.debug(color.CYAN + "User " + user_name + " does not have DSEE automount." + color.END)
             ipa_home_exist()
   except paramiko.AuthenticationException:
       print ("ERROR : DSEE Auth failed")
       logger.debug(color.RED + "DSEE Auth failed" + color.END)
       sys.exit(20)
   except:
       print ("ERROR : DSEE connection failed for %s") % dsee_server
       logger.debug(color.RED + "DSEE connection failed for + " + dsee_server + color.END)
       sys.exit(25)
       close()

def create_ipa_home():
   """ Create CA-LDAP or IPA home, via ca-server4 """
   try:
       client = paramiko.SSHClient()
       client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
       client.connect(hostname="ca-server4.us.domain.com", username=i_am, password=my_ipa_passwd)
       stdin, stdout, stderr = client.exec_command('sudo mkdir /homefolders/%s ; sudo chmod 700 /homefolders/%s ; sudo chown %s:%s /homefolders/%s' % (user_name, user_name, user_name, user_name, user_name))
       print("OK : IPA home is created for user %s ") % user_name
       logger.debug(color.GREEN + "IPA home is created for user " + user_name + color.END)
       # ipa home created, now check if automount exist
       ipa_automount_exist()
   except paramiko.AuthenticationException:
       print ("ERROR : ca-server4 Auth failed")
       logger.debug(color.RED + "ca-server4 Auth failed" + color.END)
       sys.exit(40)
   except:
       print ("ERROR : ca-server4 connection failed")
       logger.debug(color.RED + "ca-server4 connection failed" + color.END)
       sys.exit(45)
       close()


def create_ipa_automount_ipa_home():
   """ Create IPA automount with IPA home """
   try:
      subprocess.call(['ipa automountkey-add default auto.home --key %s --info "-rw,intr,soft,wsize=32768,rsize=32768,vers=3,tcp ca-sunstor1.us.domain.com:/export/home/%s"' % (user_name, user_name)], shell=True)
      print ("OK : CA-LDAP automount created for %s") % user_name
      logger.debug(color.GREEN + "CA-LDAP automount created for user " + user_name + color.END)
   except:
      logger.debug(color.RED + "Can't create CA-LDAP automount for " + user_name + color.END)
      print(color.RED + "\nERROR : Can't create CA-LDAP automount for %s.\n" + color.END) % user_name

def create_ipa_automount_dsee_home():
   """ Create IPA automount with DSEE home """
   try:
      print (dsee_automount_info)
      subprocess.call(['ipa automountkey-add default auto.home --key %s --info "-rw,intr,soft,vers=3 %s"' %(user_name, dsee_automount_info)], shell=True)
      print ("OK : CA-LDAP automount created for %s with DSEE home") % user_name
      logger.debug(color.GREEN + "CA-LDAP automount created for user " + user_name + " with DSEE home" + color.END)
   except:
      logger.debug(color.RED + "Can't create CA-LDAP automount for " + user_name + " with DSEE home" + color.END)
      print(color.RED + "\nERROR : Can't create CA-LDAP automount for %s with DSEE home.\n" + color.END) % user_name

def ipa_automount_exist():
   """ Check if IPA automount exists """
   # this is to capture command's output
   #result = subprocess.check_output(['ipa', 'automountkey-show', 'default', 'auto.home', '--key', '%s' % user_name])
   #print result
   result = subprocess.call(['ipa', 'automountkey-show', 'default', 'auto.home', '--key', '%s' % user_name])
   #return True if result == 0 else False
   if result == 0 :
     print (color.RED + "INFO : CA-LDAP automount for %s already exists!" % user_name + color.END)
     logger.debug(color.RED + "CA-LDAP automount for user " + user_name + " already exists!" + color.END)
   else:
     print ("INFO : Calling function to create CA-LDAP automount for %s") % user_name
     logger.debug(color.CYAN + "Calling function to create CA-LDAP automount for " + user_name + color.END)
     create_ipa_automount_ipa_home()

def ipa_home_exist():
   """ Check if ca-ldap home exist """
   try:
       client = paramiko.SSHClient()
       print("INFO : Doing connection check to ca-server4")
       logger.debug(color.CYAN + "Doing connection check to ca-server4" + color.END)
       client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
       client.connect(hostname="ca-server4.us.domain.com", username=i_am, password=my_ipa_passwd)
       print ("INFO : Connection to ca-server4: OK")
       logger.debug(color.CYAN + "Connection to ca-server4: OK" + color.END)
       print ("INFO : Check if CA-LDAP home already exists for %s") % user_name
       logger.debug(color.CYAN + "Check if CA-LDAP home already exists for user " + user_name + color.END)
       stdin, stdout, stderr = client.exec_command('sudo find /homefolders -maxdepth 1 -type d -name "%s"' % user_name)
       if stdout.channel.recv_exit_status() == 0:
          lines = stdout.readlines()
          if len(lines) == 0:     # exit=0 but list is empty, so no home exist
              print ("OK : Creating CA-LDAP home, via ca-server4, for user %s") % user_name
              logger.debug(color.GREEN + "Creating CA-LDAP home, via ca-server4, for user " + user_name + color.END)
              create_ipa_home()
          else:
              for line in lines:
                  print line.strip()
                  ipa_home=line.strip()
                  print ("INFO : User %s already has CA-LDAP home %s") % (user_name, ipa_home)
                  logger.debug(color.GREEN + "User " + user_name + " already has CA-LDAP home " + ipa_home + color.END)
                  ipa_automount_exist()
       else:
          logger.debug(color.RED + " Cannot determine is IPA home exist " + color.END)
          sys.exit("ERROR : Cannot determine if IPA home exist" )
   except paramiko.AuthenticationException:
       print ("ERROR : ca-server4 Auth failed")
       logger.debug(color.RED + "ca-server4 Auth failed" + color.END)
       sys.exit(30)
   except:
       print ("ERROR : Seems no change has been done via ca-server4")
       logger.debug(color.RED + "Seems no change has been done via ca-server4" + color.END)
       sys.exit(35)
       close()


# ----- MAIN --------------

if __name__ == '__main__':
    # print 'This program is being run by itself'
    user_in_dsee()
#else:
    # print 'I am being imported from another module'

#logger.debug("\n")
sys.exit(0)

Logging





Back to the main page