#!/bin/ksh
#  ALTRAN_PROLOG_BEGIN_TAG                                                    
#  This is an automatically generated prolog.                                  
#                                                                              
#  Copyright (C) Altran ACT S.A.S. 2019,2021.  All rights reserved.  
#                                                                              
#  ALTRAN_PROLOG_END_TAG                                                      
#                                                                              
# IBM_PROLOG_BEGIN_TAG 
# This is an automatically generated prolog. 
#  
# 61haes_r714 src/43haes/usr/sbin/cluster/cspoc/utilities/cl_rbac_conf.sh 1.3 
#  
# Licensed Materials - Property of IBM 
#  
# COPYRIGHT International Business Machines Corp. 2010,2011 
# All Rights Reserved 
#  
# US Government Users Restricted Rights - Use, duplication or 
# disclosure restricted by GSA ADP Schedule Contract with IBM Corp. 
#  
# IBM_PROLOG_END_TAG 
# @(#)  7d4c34b 43haes/usr/sbin/cluster/cspoc/utilities/cl_rbac_conf.sh, 726, 2147A_aha726, Feb 05 2021 09:50 PM
#including source file for initialization
. /usr/es/sbin/cluster/cspoc/cl_federatedsec_source
fsec_init
export PATH=$(/usr/es/sbin/cluster/utilities/cl_get_path all)
#====================================================
# Get the location of the clutils.log file
#====================================================
CLUTIL_LOG_DIR=$(clodmget -q "name = clutils.log" -n -f value HACMPlogs)
if [[ -z $CLUTIL_LOG_DIR ]]
then
        CLUTIL_LOG_DIR="/var/hacmp/log"
fi
CLUTIL_LOG="$CLUTIL_LOG_DIR/clutils.log"
##MAIN START##

CMDS_FILE=${HA_BASE_PATH}/cspoc/cl_rbac_cmds # file to fetch PowerHA SM commands to categorize roles
SERVER_LIST=$(clodmget -n -q "group=LDAPServer and name=ServerList" -f value HACMPLDAP|sort -u 2>/dev/null) 
[[ -z $SERVER_LIST ]] && ret_fail "Server list not found." 1 
BIND_DN=$(clodmget -n -q "group=LDAPServer and name=AdminDN" -f value HACMPLDAP|sort -u 2>/dev/null) 
[[ -z $BIND_DN ]] && ret_fail "Bind DN not found." 1 
BIND_PW=$(clodmget -n -q "group=LDAPServer and name=AdminDNPwd" -f value HACMPLDAP|sort -u 2>/dev/null) 
[[ -z $BIND_PW ]] && ret_fail "Bind password not found." 1 
SUFFIX=$(clodmget -n -q "group=LDAPServer and name=BaseDN" -f value HACMPLDAP|sort -u 2>/dev/null) 
[[ -z $SUFFIX ]] && ret_fail "Base suffix not found." 1 
BASE_PATH=$(clodmget -n -q "group=LDAPServer and name=BasePath" -f value HACMPLDAP|sort -u 2>/dev/null) 
[[ -z $BASE_PATH ]] && ret_fail "Base path not found." 1 
TMP_LDIF_FILE=${FSEC_LOG_DIR}/rbacload.$$.ldif # temprory file to load rbac data
SSL_PORT_NUM="$1"
CLNT_KDB_PATH="$2"
CLNT_KDB_PW="$3"
 dspmsg -s 129 cspoc.cat 130 "INFO: Running RBAC configuration, it may take quite a bit of time, please wait...\n" 
#loading rbac data
rbactoldif -d $SUFFIX > $TMP_LDIF_FILE #to load existing rbac data
${BASE_PATH}/bin/idsldapadd -h `echo $SERVER_LIST|awk -F, '{print $1}'` -D $BIND_DN -w  $BIND_PW -K $CLNT_KDB_PATH -P $CLNT_KDB_PW -p $SSL_PORT_NUM \
	-c -f $TMP_LDIF_FILE  > ${FSEC_LOG_DIR}/rbactoldif.log.$$ 2>&1
ret_code=$?
if [[ $ret_code -ne 0 ]] && [[ $ret_code -ne 20 ]] && [[ $ret_code -ne 68 ]]
then
	ret_fail "ldapadd failed." $ret_code
fi
#this is a current problem, based on that modifying nscontrol file, it should work without modifying
STANZAS="authorizations roles privcmds privdevs privfiles"
for X in $STANZAS
do
	run_on_allnode "chsec -f /etc/nscontrol.conf -s $X -a secorder=files,LDAP" >/dev/null \
		|| ret_fail "changing secorder=files,LDAP failed in one of the node." $?
done
#creating authorizations
/usr/bin/mkauth -R LDAP dfltmsg="PowerHA SM authorization" PowerHASM >/dev/null
RETCODE=$?
if [[ $RETCODE -eq 17 ]]
then
	chauth -R LDAP dfltmsg="PowerHA SM authorization" PowerHASM >/dev/null || ret_fail "chauth failed." $?
elif [[ $RETCODE -ne 0 ]]
then
	ret_fail "mkauth failed!" $RETCODE
fi  
/usr/bin/mkauth -R LDAP dfltmsg="PowerHA SM admin authorization" PowerHASM.admin >/dev/null
RETCODE=$?
if [[ $RETCODE -eq 17 ]]
then
	chauth -R LDAP dfltmsg="PowerHA SM admin authorization" PowerHASM.admin >/dev/null || ret_fail "chauth failed." $?
elif [[ $RETCODE -ne 0 ]]
then
	ret_fail "mkauth failed!" $RETCODE
fi  
/usr/bin/mkauth -R LDAP dfltmsg="PowerHA SM monitor authorization" PowerHASM.mon >/dev/null
RETCODE=$?
if [[ $RETCODE -eq 17 ]]
then
	chauth -R LDAP dfltmsg="PowerHA SM monitor authorization" PowerHASM.mon >/dev/null || ret_fail "chauth failed." $?
elif [[ $RETCODE -ne 0 ]]
then
	ret_fail "mkauth failed!" $RETCODE
fi  
/usr/bin/mkauth -R LDAP dfltmsg="PowerHA SM operations authorization" PowerHASM.op >/dev/null
RETCODE=$?
if [[ $RETCODE -eq 17 ]]
then
	chauth -R LDAP dfltmsg="PowerHA SM operations authorization" PowerHASM.op >/dev/null || ret_fail "chauth failed." $?
elif [[ $RETCODE -ne 0 ]]
then
	ret_fail "mkauth failed!" $RETCODE
fi  
/usr/bin/mkauth -R LDAP dfltmsg="PowerHA SM view authorization" PowerHASM.view >/dev/null
RETCODE=$?
if [[ $RETCODE -eq 17 ]]
then
	chauth -R LDAP dfltmsg="PowerHA SM view authorization" PowerHASM.view >/dev/null || ret_fail "chauth failed." $?
elif [[ $RETCODE -ne 0 ]]
then
	ret_fail "mkauth failed!" $RETCODE
fi  
run_on_allnode setkst >/dev/null
#reading POWERHASM commands file
while read LINE
do
    echo $LINE |grep "^#" > /dev/null 2>&1 && continue

    if echo $LINE |grep -w "ADMIN" > /dev/null 2>&1 ; then
        CMD_AUTH="PowerHASM.admin"
    elif echo $LINE |grep -w "OPERATOR" > /dev/null 2>&1 ; then
        CMD_AUTH="PowerHASM.op"
    elif echo $LINE |grep -w "MONITOR" > /dev/null 2>&1 ; then
        CMD_AUTH="PowerHASM.mon"
    elif echo $LINE |grep -w "VIEW" > /dev/null 2>&1 ; then
        CMD_AUTH="PowerHASM.view"
    fi

    CMD_PATH=$(echo $LINE | cut -f2 -d":")
    [[ -z $CMD_PATH ]] && ret_fail "Command not found." 1

    #Skipping the further process if command is listed in cl_rbac_cmds but it
    #is not found on the node in any path, as there may be a case
    #that the fileset is not installed.
    #In that case we will continue to enable RBAC for other commands instead of
    #exiting with an error.

    if [[ ! -s $CMD_PATH ]];then
        fileset=$(lslpp -wc $CMD_PATH | grep $CMD_PATH | grep -v "#" | cut -d: -f2)
        if [[ -z $fileset ]];then
            dspmsg -s 129 cspoc.cat 84 "WARNING: %s\n" "Failed to enable \"$CMD_PATH\" for RBAC because fileset is not installed. Please run the operation after installing the missing fileset."
        else
            dspmsg -s 129 cspoc.cat 84 "WARNING: %s\n" "Failed to enable \"$CMD_PATH\" for RBAC because \"$fileset\" is not properly installed. Please run the operation after installing the fileset properly."
        fi
        continue
    fi

    #this can be made more secure with respect to privileges by running each command with all
    #the options. Get a unique list of all the privileges for a particular command.
    #Basically each command has to run for all code paths using "tracepriv" just like truss to
    #get complete list of privileges required to run a particular command.

    #Get innate and inherit privileges for each command in cl_rbac_cmds file
    CMD_PRIVS=""
    INHERIT_PRIVS=""

    CMD_PRIVS=`echo $LINE | cut -f3 -d":"`
    INHERIT_PRIVS=$(echo $LINE | cut -f4 -d":")
    # Privilege "PV_LIVE_UPDATE" is introduced to support live update feature of AIX.
    # Remove this privilege from inherit privilege list on older version of AIX, where 
    # lvupdate feature is not supported.
    lspriv -v | grep -wq "PV_LIVE_UPDATE"
    if (( $? != 0 ));then
        if echo $INHERIT_PRIVS | grep -wq "PV_LIVE_UPDATE" ; then
            INHERIT_PRIVS=$(echo "$INHERIT_PRIVS" | sed "s/,PV_LIVE_UPDATE//g;s/PV_LIVE_UPDATE,//g")
        fi
    fi

    #Set security attibutes and innate privileges identified for the command
    if [[ -z $CMD_PRIVS ]]
    then
        STD_ERR=$(setsecattr -R LDAP -c accessauths=$CMD_AUTH secflags=FSF_EPS $CMD_PATH 2>&1 1>/dev/null)
        [[ -n $STD_ERR ]] && echo "setsecattr failed!\n$STD_ERR" >> $CLUTIL_LOG && unset STD_ERR && exit 1
    else
        STD_ERR=$(setsecattr -R LDAP -c accessauths=$CMD_AUTH innateprivs="$CMD_PRIVS" secflags=FSF_EPS $CMD_PATH 2>&1 1>/dev/null)
        [[ -n $STD_ERR ]] && echo "setsecattr failed to set innateprivs!\n$STD_ERR" >> $CLUTIL_LOG && unset STD_ERR && exit 1
    fi

    # Set inherit privileges identified for the command.
    if [[ -n $INHERIT_PRIVS ]]
    then
        STD_ERR=$(setsecattr -R LDAP -c inheritprivs="$INHERIT_PRIVS" $CMD_PATH 2>&1 1>/dev/null)
        [[ -n $STD_ERR ]] && echo "setsecattr failed to set inheritprivs!\n$STD_ERR" >> $CLUTIL_LOG && unset STD_ERR && exit 1
    fi

    # Command "cl_mkvg" requires effective user ID as 0 in order to execute successfully.
    # Set euid to 0 for this utility
    if  echo $CMD_PATH | grep -wq "cl_mkvg" ; then
        STD_ERR=$(setsecattr -R LDAP -c euid=0 $CMD_PATH 2>&1 1>/dev/null)
        [[ -n $STD_ERR ]] && echo "Command 'setsecattr -R LDAP -c euid=0 $CMD_PATH' \
failed to set effective user id!\n$STD_ERR" >> $CLUTIL_LOG && unset STD_ERR && exit 1
    fi

done < $CMDS_FILE
#changing file permission so that other users cannot access it unless they have required role
run_on_allnode "find /var/hacmp -type f|xargs -i chmod o-rwx {}" >/dev/null || ret_fail "chmod failed." $?
#setting read auths for all hacmp log files
hacmp_FILES=`find /var/hacmp -type f` || ret_fail "finding other log files failed." $?
for X in $hacmp_FILES
do
    STD_ERR=$(setsecattr -R LDAP -f readauths="PowerHASM.view" $X 2>&1 1>/dev/null)
    [[ -n $STD_ERR ]] && echo "setsecattr failed to set readauths!\n$STD_ERR" >> $CLUTIL_LOG && unset STD_ERR && exit 1
done
#creating roles for respective auths
/usr/bin/mkrole -R LDAP authorizations="PowerHASM.admin,PowerHASM.op,PowerHASM.mon,PowerHASM.view" ha_admin >/dev/null
RETCODE=$?
if [[ $RETCODE -eq 17 ]]
then
	chrole -R LDAP authorizations="PowerHASM.admin,PowerHASM.op,PowerHASM.mon,PowerHASM.view" ha_admin >/dev/null || ret_fail "chrole failed." $?
elif [[ $RETCODE -ne 0 ]]
then
	ret_fail "mkrole failed!" $RETCODE
fi
/usr/bin/mkrole -R LDAP authorizations="PowerHASM.op,PowerHASM.mon,PowerHASM.view" ha_op >/dev/null 
RETCODE=$?
if [[ $RETCODE -eq 17 ]]
then
	chrole -R LDAP authorizations="PowerHASM.op,PowerHASM.mon,PowerHASM.view" ha_op >/dev/null || ret_fail "chrole failed." $?
elif [[ $RETCODE -ne 0 ]]
then
	ret_fail "mkrole failed!" $RETCODE
fi
/usr/bin/mkrole -R LDAP authorizations="PowerHASM.mon,PowerHASM.view" ha_mon >/dev/null 
RETCODE=$?
if [[ $RETCODE -eq 17 ]]
then
	chrole -R LDAP authorizations="PowerHASM.mon,PowerHASM.view" ha_mon >/dev/null || ret_fail "chrole failed." $?
elif [[ $RETCODE -ne 0 ]]
then
	ret_fail "mkrole failed!" $RETCODE
fi
/usr/bin/mkrole -R LDAP authorizations="PowerHASM.view" ha_view >/dev/null 
RETCODE=$?
if [[ $RETCODE -eq 17 ]]
then
	chrole -R LDAP authorizations="PowerHASM.view" ha_view >/dev/null || ret_fail "chrole failed." $?
elif [[ $RETCODE -ne 0 ]]
then
	ret_fail "mkrole failed!" $RETCODE
fi

#adding ODM entries
ODM_ENT_TMP=${FSEC_LOG_DIR}/odm_entry_tmp.$$

echo "HACMPLDAP:
       group="LDAPClient"
       type="RBAC"
       name="RBACConfig"
       value="YES"" > $ODM_ENT_TMP
	   
st=$(odmadd $ODM_ENT_TMP ) || { 
		 dspmsg -s 129 cspoc.cat 71 "ODM update is failed.\n"
		exit 1
		}


#Creating a new group "ldapha" in LDAP server and
#changing the group for all PowerHA ODMs exisiting in
#/etc/es/objrepos, so that they can be read from the
#code written in smitty list or dicover commands. 
#The PowerHA users should be assigned with this 
#ldapha group.

#As we are not sure while creating of the group ldapha 
#in ldap server what will be the id assigned to the group. 
#So if we don't specify the id while creation of group, 
#ldap server can take any id on its own which could coincide 
#with any existing group on nodes. 
#So this big number has been taken to make sure that 
#this id has not been taken in ldap server and nodes.

lsgroup -R LDAP ldapha >/dev/null
if (( $? != 0 ));then
    STD_ERR=$(mkgroup -R LDAP -a id=4294967290 ldapha 2>&1 1>/dev/null)
    [[ -n $STD_ERR ]] && echo "mkgroup failed!\n$STD_ERR" >> $CLUTIL_LOG && unset STD_ERR && exit 1
fi
run_on_allnode "/usr/es/sbin/cluster/cspoc/cl_rbac_permissions_conf enable" || ret_fail "run_on_allnode failed!" $?
#reflecting changes in all nodes
run_on_allnode setkst || ret_fail "run_on_allnode failed!" $?
rm -r $ODM_ENT_TMP
run_on_allnode "rm -rf $FSEC_LOG_DIR" || ret_fail "Removing log directory failed." $?

exit 0

##MAIN END##
