From 1034d3f5b68f6c8de4421ed4e8a70b79fb3fc331 Mon Sep 17 00:00:00 2001 From: "Todd C. Miller" Date: Tue, 14 Apr 2020 19:25:49 -0600 Subject: [PATCH] Update PolyPkg from my branch with systemd support. --- etc/sudo-logsrvd.pp | 19 +++ scripts/pp | 283 ++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 281 insertions(+), 21 deletions(-) diff --git a/etc/sudo-logsrvd.pp b/etc/sudo-logsrvd.pp index ae9d083f8..ebc4dd990 100644 --- a/etc/sudo-logsrvd.pp +++ b/etc/sudo-logsrvd.pp @@ -220,3 +220,22 @@ This makes it possible to have all sudo I/O logs on a central server." cmd=${sbindir}/sudo_logsrvd pidfile=${rundir}/sudo_logsrvd.pid %endif +%if [rpm,deb] + pp_systemd_service_description="Sudo central log server" + pp_systemd_service_exec="${cmd}" + pp_systemd_service_exec_args="-n" + pp_systemd_service_dir=`pkg-config systemd --variable=systemdsystemunitdir 2>/dev/null` + if test X"$pp_systemd_service_dir" = X""; then + if test -d /lib/systemd/system; then + pp_systemd_service_dir=/lib/systemd/system + else + pp_systemd_service_dir=/usr/lib/systemd/system + fi + fi + pp_systemd_service_man="man:sudo_logsrvd(8) man:sudo_logsrvd.conf(5)" + pp_systemd_service_documentation="https://www.sudo.ws/man.html" + pp_systemd_service_after="syslog.target network.target auditd.service" + pp_systemd_service_killmode="process" + pp_systemd_service_type="exec" + pp_systemd_system_target="multi-user.target" +%endif diff --git a/scripts/pp b/scripts/pp index aabf288d6..c42f93fb4 100755 --- a/scripts/pp +++ b/scripts/pp @@ -1,6 +1,6 @@ #!/bin/sh -# Copyright 2019 One Identity LLC. ALL RIGHTS RESERVED -pp_revision="20190919" +# Copyright 2020 One Identity LLC. ALL RIGHTS RESERVED +pp_revision="20200414" # Copyright 2018 One Identity LLC. ALL RIGHTS RESERVED. # # Redistribution and use in source and binary forms, with or without @@ -4071,45 +4071,66 @@ pp_deb_handle_services() { #-- add service start/stop code if test -n "$pp_services"; then + #-- append common %post install code + pp_systemd_service_install_common >> $pp_wrkdir/%post.run + #-- record the uninstall commands in reverse order for svc in $pp_services; do pp_load_service_vars $svc - # Create init script (unless one exists) - pp_deb_service_make_init_script $svc + # Create init script and systemd service file (unless they exists) + pp_deb_service_make_init_script $svc || + pp_error "could not create init script for service $svc" #-- append %post code to install the svc test x"yes" = x"$enable" && cat<<-. >> $pp_wrkdir/%post.run + case "\$1" in configure) # Install the service links - update-rc.d $svc defaults + _pp_systemd_init + if test -n "\$systemctl_cmd"; then + _pp_systemd_install $svc + _pp_systemd_enable $svc + else + update-rc.d $svc defaults + fi ;; esac . #-- prepend %preun code to stop svc cat<<-. | pp_prepend $pp_wrkdir/%preun.run + case "\$1" in remove|deconfigure|upgrade) # Stop the $svc service invoke-rc.d $svc stop + _pp_systemd_disable $svc ;; esac . #-- prepend %postun code to remove service cat<<-. | pp_prepend $pp_wrkdir/%postun.run + case "\$1" in purge) # Remove the service links update-rc.d $svc remove + _pp_systemd_remove $svc ;; esac . done + + pp_systemd_service_remove_common | pp_prepend $pp_wrkdir/%preun.run #pp_deb_service_remove_common | pp_prepend $pp_wrkdir/%preun.run + + # Actual systemd service removal is done in %postun. + # Otherwise, systemd may pick up the init.d script if it exists. + pp_systemd_service_remove_common | pp_prepend $pp_wrkdir/%postun.run fi } @@ -4478,6 +4499,8 @@ pp_backend_deb_init_svc_vars () { stop_runlevels=${pp_deb_default_stop_runlevels-"0 1 6"} # == lsb default-stop svc_description="${pp_deb_default_svc_description}" # == lsb short descr svc_process= + svc_init_filename="${pp_deb_svc_init_filename}" # == $svc.init + svc_init_filepath="${pp_deb_svc_init_filepath}" # == /etc/init.d/ by default lsb_required_start='$local_fs $network' lsb_should_start= @@ -4489,8 +4512,8 @@ pp_backend_deb_init_svc_vars () { } pp_deb_service_make_init_script () { - local svc=$1 - local script=/etc/init.d/$svc + local svc=${svc_init_filename:-$1} + local script="${svc_init_filepath:-"/etc/init.d"}/$svc" local out=$pp_destdir$script local _process _cmd @@ -4706,6 +4729,9 @@ esac : . chmod 755 $out + + # Create systemd service file + pp_systemd_make_service_file $svc } pp_backend_deb_function() { case "$1" in @@ -5846,7 +5872,7 @@ pp_backend_rpm () { . done >>$specfile - #-- NB: we don't put any %prep, %build or %install RPM sections + #-- NB: we do not put any %prep, %build or %install RPM sections # into the spec file. #-- add service start/stop code @@ -5857,7 +5883,8 @@ pp_backend_rpm () { for svc in $pp_services; do pp_load_service_vars $svc - pp_rpm_service_make_init_script $svc + pp_rpm_service_make_init_script $svc || + pp_error "could not create init script for service $svc" #-- append %post code to install the svc pp_rpm_service_install $svc >> $pp_wrkdir/%post.run @@ -5866,6 +5893,7 @@ pp_backend_rpm () { # (use files in case vars are modified) pp_rpm_service_remove $svc | pp_prepend $pp_wrkdir/%preun.run done + pp_rpm_service_remove_common | pp_prepend $pp_wrkdir/%preun.run fi @@ -6221,6 +6249,7 @@ pp_rpm_service_install_common () { fi } . + pp_systemd_service_install_common } pp_rpm_service_remove_common () { @@ -6246,22 +6275,30 @@ pp_rpm_service_remove_common () { fi } . + pp_systemd_service_remove_common } - pp_rpm_service_install () { - pp_rpm_service_make_init_script $1 >/dev/null || - pp_error "could not create init script for service $1" - echo "_pp_install_service $1" - test $enable = yes && echo "_pp_enable_service $1" + echo "" + echo "_pp_systemd_init" + echo 'if test -n "$systemctl_cmd"; then' + echo " _pp_systemd_install $1" + test $enable = yes && echo " _pp_systemd_enable $1" + echo "else" + echo " _pp_install_service $1" + test $enable = yes && echo " _pp_enable_service $1" + echo "fi" } pp_rpm_service_remove () { cat <<-. - if [ "\$1" = "remove" -o "\$1" = "0" ]; then - # only remove the service if not upgrade - _pp_remove_service $1 - fi + + if [ "\$1" = "remove" -o "\$1" = "0" ]; then + # only remove the service if not upgrade + _pp_remove_service $1 + _pp_systemd_disable $1 + _pp_systemd_remove $1 + fi . } @@ -6273,6 +6310,8 @@ pp_backend_rpm_init_svc_vars () { stop_runlevels=${pp_rpm_default_stop_runlevels-"0 1 6"} # == lsb default-stop svc_description="${pp_rpm_default_svc_description}" # == lsb short descr svc_process= + svc_init_filename="${pp_rpm_svc_init_filename}" # == $svc.init + svc_init_filepath="${pp_rpm_svc_init_filepath}" # == /etc/init.d/ by default lsb_required_start='$local_fs $network' lsb_should_start= @@ -6374,8 +6413,8 @@ pp_rpm_service_group_make_init_script () { } pp_rpm_service_make_init_script () { - local svc=$1 - local script=/etc/init.d/$svc + local svc=${svc_init_filename:-$1} + local script="${svc_init_filepath:-"/etc/init.d"}/$svc" local out=$pp_destdir$script local _process _cmd _rpmlevels @@ -6583,6 +6622,9 @@ pp_rpm_service_make_init_script () { . chmod 755 $out + + # Create systemd service file + pp_systemd_make_service_file $svc } pp_backend_rpm_function () { case "$1" in @@ -7298,7 +7340,7 @@ pp_backend_macos_flat () { # build the flat package layout pkgdir=$pp_wrkdir/pkg - bundledir=$pp_wrkdir/pkg/$name.pkg + bundledir=$pp_wrkdir/pkg/$name-${version}.pkg Resources=$pkgdir/Resources lprojdir=$Resources/en.lproj mkdir $pkgdir $bundledir $Resources $lprojdir || @@ -7442,6 +7484,7 @@ pp_backend_macos_flat () { cd $pp_destdir || pp_error "Can't cd to $pp_destdir" awk '{ print "." $6 }' $filelists | sed 's:/$::' | sort | /usr/bin/cpio -o | pp_macos_rewrite_cpio $filelists | gzip -9f -c > $bundledir/Payload ) + awk '{print $6}' $filelists > $name.files # Copy installer plugins if any if test -n "$pp_macos_installer_plugin"; then @@ -7462,6 +7505,8 @@ pp_backend_macos_flat () { *) xar_flags="$xar_flags --distribution";; esac (cd $pkgdir && /usr/bin/xar $xar_flags -cf "../$name-$version.pkg" *) + + echo "version=$version" > $name.uninstall } pp_backend_macos_cleanup () { @@ -8759,6 +8804,202 @@ pp_backend_bsd_function() { *) false;; esac } +pp_systemd_make_service_file() { + + local svc f + + svc="$1" + f="${pp_systemd_service_dir:-'/opt/quest/libexec/vas'}/$svc.service" + pp_add_file_if_missing $f run 644 v || return 0 + + cat <<. >$pp_destdir$f + +[Unit] +Description=${pp_systemd_service_description:-"systemd service file for $svc"} +${pp_systemd_service_man:+"Documentation=$pp_systemd_service_man"} +${pp_systemd_service_documentation:+"Documentation=$pp_systemd_service_documentation"} +${pp_systemd_service_requires:+"Requires=$pp_systemd_service_requires"} +After=${pp_systemd_service_after:-"syslog.target network.target auditd.service"} +${pp_systemd_service_before:+"Before=$pp_systemd_service_before"} +${pp_systemd_service_wants:+"Wants=$pp_systemd_service_wants"} +${pp_systemd_service_conflicts:+"Conflicts=$pp_systemd_service_conflicts"} + +[Service] +ExecStart=${pp_systemd_service_exec:-"/opt/quest/sbin/$svc"} ${pp_systemd_service_exec_args} +KillMode=${pp_systemd_service_killmode:-process} +Type=${pp_systemd_service_type:-forking} + +[Install] +WantedBy=${pp_systemd_system_target:-"multi-user.target"} +. +} + +pp_systemd_service_init_common () { + cat <<. + + _pp_systemd_init () { + systemd_service_dir=${pp_systemd_service_dir:-'/opt/quest/libexec/vas'} + systemd_target=${pp_systemd_system_target:-"multi-user.target"} + systemd_target_wants="\${systemd_target}.wants" + + pkg_config_cmd=${pp_systemd_pkg_config_cmd:-"\$(command -v pkg-config)"} + systemctl_cmd=${pp_systemd_systemctl_cmd:-"\$(command -v systemctl)"} + + # See if pkg-config is installed to get the default locations for this OS, if not installed then just use what we hard code. + # So far works on Debian 8, OpenSuse12.3, Ubuntu 16.04, RHEL 7.3 + # See systemd wiki for more OS interactions https://en.wikipedia.org/wiki/Systemd + if [ -x "\$pkg_config_cmd" ]; then + systemd_system_unit_dir="\$(pkg-config systemd --variable=systemdsystemunitdir)" + systemd_system_conf_dir="\$(pkg-config systemd --variable=systemdsystemconfdir)" + fi + + #if pkg-config does not exist or if the \$pkg_config_cmd command returns nothing + if test -z "\$systemd_system_unit_dir"; then + systemdsystemunitdirs="/lib/systemd/system /usr/lib/systemd/system" + for dir in \$systemdsystemunitdirs; do + if [ -d "\$dir/\$systemd_target_wants" ]; then + systemd_system_unit_dir="\$dir" + break + fi + done + fi + + # In the case where \$systemd_system_conf_dir is empty hard code the path + if test -z "\$systemd_system_conf_dir"; then + systemd_system_conf_dir="/etc/systemd/system" + fi + + # if the \$svc.pp file defines the systemd unit dir then use it. + ${pp_systemd_system_unit_dir:+"# systemd_system_unit_dir defined by variable pp_systemd_system_unit_dir from the \$svc.pp file"} + systemd_system_unit_dir="${pp_systemd_system_unit_dir:-"\$systemd_system_unit_dir"}" + + # if the \$svc.pp file defines the systemd conf dir then use it. + ${pp_systemd_system_conf_dir:+"# systemd_system_conf_dir defined by variable pp_systemd_system_conf_dir from the \$svc.pp file"} + systemd_system_conf_dir="${pp_systemd_system_conf_dir:-"\$systemd_system_conf_dir"}" + } +. +} + +pp_systemd_service_install_common () { + pp_systemd_service_init_common + + cat<<'.' + + _pp_systemd_install () { + local svc="$1" + + # If $systemctl_cmd is not set, then call _pp_systemd_init. If still not + # set, we do not know where the systemctl command is so do nothing; + # systemd must not be on this system. + if test -z "$systemctl_cmd"; then + _pp_systemd_init + fi + + if test -x "$systemctl_cmd" && test -d "$systemd_system_conf_dir/$systemd_target_wants"; then + # If our service file still exists (upgrade) remove the link/file and systemctl + # will recreate it if/when we enable the $svc service. + if test -e "$systemd_system_conf_dir/$systemd_target_wants/$svc.service" ; then + rm -f "$systemd_system_conf_dir/$systemd_target_wants/$svc.service" + fi + + # Copy the $svc.service file to the correct systemd_system_unit_dir location + if [ "x$systemd_service_dir" != "x$systemd_system_unit_dir" ]; then + cp -f "$systemd_service_dir/$svc.service" "$systemd_system_unit_dir/$svc.service" + chmod 644 "$systemd_system_unit_dir/$svc.service" + fi + fi + } + + _pp_systemd_enable () { + local svc="$1" + local RUNNING + + # If $systemctl_cmd is not set, then call _pp_systemd_init. If still not + # set, we do not know where the systemctl command is so do nothing; + # systemd must not be on this system. + if test -z "$systemctl_cmd"; then + _pp_systemd_init + fi + + if test -x "$systemctl_cmd" && test -f "$systemd_system_unit_dir/$svc.service"; then + # stop the daemon using the old init script before enabling systemd for the service + # we do this so we do not "orphan" the process. Because init started it and if we enable systemd + # it will not know about this process and will not be able to stop it. + if [ -x "/etc/init.d/$svc" ]; then + /etc/init.d/$svc status > /dev/null 2>&1 + RUNNING=$? + if [ $RUNNING -eq 0 ]; then + /etc/init.d/$svc stop > /dev/null 2>&1 + fi + else + RUNNING=1 + fi + + # Enable the $svc.service + $systemctl_cmd daemon-reload >/dev/null 2>&1 + $systemctl_cmd enable $svc.service >/dev/null 2>&1 + + # Now that the service has been enabled, start it again if it was running before. + if [ $RUNNING -eq 0 ]; then + /etc/init.d/$svc start > /dev/null 2>&1 + fi + fi + } +. +} + +pp_systemd_service_remove_common () { + pp_systemd_service_init_common + + cat<<'.' + + _pp_systemd_disable () { + local svc="$1" + + # If $systemctl_cmd is not set, then call _pp_systemd_init. + # If still not set, we do not know where the systemctl command + # is so do nothing; systemd must not be on this system. + if test -z "$systemctl_cmd"; then + _pp_systemd_init + fi + + systemd_service_file="$systemd_system_conf_dir/$systemd_target_wants/$svc.service" + + # Remove systemd symlink (enabled) unit service file + if test -e $systemd_service_file; then + # Disable the $svc service + if test -x "$systemctl_cmd"; then + $systemctl_cmd disable $svc.service > /dev/null 2>&1 + else + # For some reason systemctl is not install but our service file exists + # Just delete the symlink then + rm -f "$systemd_service_file" + fi + fi + } + + _pp_systemd_remove () { + local svc="$1" + + # If $systemctl_cmd is not set, then call _pp_systemd_init. + # If still not set, we do not know where the systemctl command + # is so do nothing; systemd must not be on this system. + if test -z "$systemctl_cmd"; then + _pp_systemd_init + fi + + # Remove the systemd unit service file + if test -e "$systemd_system_unit_dir/$svc.service"; then + rm -f "$systemd_system_unit_dir/$svc.service" + fi + + if test -x "$systemctl_cmd"; then + $systemctl_cmd daemon-reload + $systemctl_cmd reset-failed $svc.service >/dev/null 2>&1 || true + fi + } +. +} quest_require_vas () {