Article Figure 1 Listing 1 Sidebar jan2004.tar

Listing 1 rpkadd source

#!/bin/ksh
#
#  rpkgadd: Remote Package Management for Solaris
#
#  Author: Adam Ronthal
#
#  Copyright (c) 2003, CiRBA Inc.           http://www.cirba.com
#  This software is distributed under the terms of the X11 Public License.
#  Please type 'rpkgadd -l' for license terms.
#
#  Description
#  -----------
#  rpkgadd is a remote pkgadd tool to install Sun packages on remote machines
#  it requires sshd to be running on the target machine and ssh/scp to be 
#  installed on the local machine.
#
#  root or root-equivalent permissions are required on the target machine, 
#  though the password is never sent in the clear.
#
#  rsa or dsa keys are supported for authentication, though empty password 
#  keys are not recommended for the root account.  If empty passwords are 
#  to be used, it is strongly recommended to create a root-equivalent 
#  account (e.g. pkginstall)
#

############################
# Settings and Environment #
############################

export PATH=/usr/bin:/usr/local/bin

# Is this a NIS environment
#
NIS="no"

# Remove keys
#
RMKEYS="yes"

# Remove package source from remote server /var/spool/pkg when installed
#
DELPKG="yes"

# Default is to install packages, not uninstall them
#
RMPKG="no"

# Use DSA keys by default
#
KEYTYPE="dsa"

# Use 'root' as the default remote root if not specified
#
REMOTE_ROOT="root"

#############
# Functions #
#############

rpkgadd -p <package> -t <target_host> -u <root-user> [ -k rsa|dsa ] [ -mSehDl ]
rpkgadd -b <configfile>


f_usage()
{

echo "USAGE:   $0 -p <package> -t <target_host> -u <root-user> \
  [ -k rsa|dsa ] [ -mSehDl ]"
echo "         $0 -b <configfile>"
echo
echo "EXAMPLES: $0 -p SMCwget -t somehost -u pkginstall"
echo "          $0 -b rpkgadd.conf"
echo "          $0 -d -p SMCwget -t somehost -u pkginstall"
echo
echo "Use '$0 -h' for detailed usage instructions"

exit 1

}

f_help()
{
cat<<EOH
---------------------------------------------------------------------------
rpkgadd Detailed Usage
---------------------------------------------------------------------------
The following command options are supported:

-p      Name of the package to install.  Packages must be either
        standard solaris packages or DaTaStReAm packages.  If the
        package is a DaTaStReAm package, it will be converted using
        the pkgtrans utility first.

-t      Target host to install package on.

-u      Remote root account.  If not specified, it defaults to 'root'
        If rpkgadd is installed as part of your package infrastructure,
        we recommend the creation of a dedicated package maintenance 
        account.

-k      SSH key type to use.  If not specified, DSA keys will be used.  
        Valid arguments includ 'rsa' and 'dsa'. (optional)

-m      Maintain packages on remote host.  This option will override the
        default behavior of deleting packages from /var/spool/pkg on the
        target host once the package is installed. (optional)

-S      Save SSH keys on remote host.  This option will 
        override the default behavior of removing the SSH keys from the
        remote host.  This is useful if multiple packages will be installed.
        (optional)

-e      Expunge local copy of the RSA or DSA public keys.
        (optional)

-b      Batch processing mode. Required argument is the location of the
        configuration file which should contain the following colon (:) 
        delimited entries:

        target_host:root_user:pkgrm:remove_keys:remove_package_source: \
          keytype:pkg1:pkg2:...:pkg_n

        For example:

        sunspot:pkginstall:no:yes:yes:dsa:SMCwget:SMCtop

        Lines beginning with a # are comments and will be ignored.

        (optional)

-D      Removes the package from the specified target host. (Executes
        a 'pkgrm').

-h      Displays this help message.

-l      Displays the license agreement.
---------------------------------------------------------------------------
Copyright (c) 2003 CiRBA Inc.                       http://www.cirba.com  
This software is distributed under the terms of the X11 Public License.
EOH
}

f_show_lic()
{
cat<<EOL
COPYRIGHT AND PERMISSION NOTICE

Copyright (c) 2003 CiRBA, Inc.

All rights reserved.

Permission is hereby granted, free of charge, to any person obtaining a copy 
of this software and associated documentation files (the "Software"), to deal 
in the Software without restriction, including without limitation the rights 
to use, copy, modify, merge, publish, distribute, and/or sell copies of the 
Software, and to permit persons to whom the Software is furnished to do so, 
provided that the above copyright notice(s) and this permission notice appear 
in all copies of the Software and that both the above copyright notice(s) and 
this permission notice appear in supporting documentation.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. 
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE 
BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, 
OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

Except as contained in this notice, the name of a copyright holder shall 
not be used in advertising or otherwise to promote the sale, use or other 
dealings in this Software without prior written authorization of the 
copyright holder.
EOL
}

f_process_pkg()
{

CURPKG=$1
echo "Preparing package for file transfer..."
tar -clf - ./${CURPKG} | gzip > ./${CURPKG}.tar.gz
echo "Transfering package to $TARGET"
scp  -q -i $MYHOME/.ssh/pkgkey ./${CURPKG}.tar.gz $REMOTE_ROOT@$TARGET:/var/spool/pkg

echo "Installing package on $TARGET..."
ssh -i $MYHOME/.ssh/pkgkey -l $REMOTE_ROOT $TARGET "cd /var/spool/pkg && \
  gzcat $CURPKG.tar.gz | tar xf -; rm $CURPKG.tar.gz; pkgadd $CURPKG"

echo "Cleaning up..."
rm $CURPKG.tar.gz

if [ "$DELPKG" = "yes" ]; then
   ssh -i $MYHOME/.ssh/pkgkey -l $REMOTE_ROOT $TARGET "cd /var/spool/pkg \
     && rm -Rf $CURPKG"
fi

}

f_remove_keys()
{
ssh -i $MYHOME/.ssh/pkgkey -l $REMOTE_ROOT $TARGET "ksh -c 'if [ -f \
  ~${REMOTE_ROOT}/.ssh/authorized_keys ]; then cat \
  ~${REMOTE_ROOT}/.ssh/authorized_keys | sed -e /pkgkey\$/d > \
  ~${REMOTE_ROOT}/.ssh/ak.tmp && mv ~${REMOTE_ROOT}/.ssh/ak.tmp  \
  ~${REMOTE_ROOT}/.ssh/authorized_keys;  fi; if [ -f  \
  ~${REMOTE_ROOT}/.ssh/authorized_keys2 ]; then cat  \
  ~${REMOTE_ROOT}/.ssh/authorized_keys2 | sed -e /pkgkey\$/d >  \
  ~${REMOTE_ROOT}/.ssh/ak2.tmp && mv ~${REMOTE_ROOT}/.ssh/ak2.tmp  \
  ~${REMOTE_ROOT}/.ssh/authorized_keys2; fi'"
}

f_add_keys()
{

# Add the public key to the target host's authorized_keys files.  We want 
# to support all versions of SSH, so we populate both the authorized_keys 
# and the authorized_keys2 files.
#
cat $MYHOME/.ssh/pkgkey.pub | ssh -l $REMOTE_ROOT $TARGET "ksh -c 'if \
  [ ! -d ~/.ssh ]; then mkdir -m 0700 ~/.ssh;  fi; cat - \
  >>~/.ssh/authorized_keys2; cp -p \
  ~/.ssh/authorized_keys2 ~/.ssh/authorized_keys; chmod -R 0700 ~/.ssh'"

}

f_main_engine()
{

echo "Target host is $TARGET"

# Check if we're adding or removing a package
#
if [ "$RMPKG" != "yes" ]; then

   # We standardize the package format to the traditional Solaris
   # format.  If the package is in DaTaStReAm format, we convert
   # it using pkgtrans.

   if [ -d $PACKAGE ]; then
      PTYPE=standard
      echo "Package is standard format."
   elif [ -f $PACKAGE ]; then
      DS=`head -1 $PACKAGE | grep "DaTaStReAm"`
      if [ "x$DS" != "x" ]; then
         PTYPE=datastream
         echo "Package is in DaTaStReAm format. Translating."
         TRANSD_PACKS=`pkgtrans -o $PACKAGE . all 2>&1 | grep \
           "Transferring" |  sed -e 's/.*<//g' -e 's/>.*//g'` 
      fi
   else
      echo "Cannot determine format of package."
      exit 1
   fi
   
   #  Since the translation process could result in multiple packages,
   #  we deal with that here by getting the name(s) of the packages from
   #  from the output of pkgtrans above, and looping through them.
   # 
   if [ "x$PTYPE" = "xstandard" ]; then
      f_process_pkg $PACKAGE
   else
      for i in $TRANSD_PACKS; do
         f_process_pkg $i
         rm -Rf $i
      done
   fi

# We're removing a package here.
#
else 
   ssh -i $MYHOME/.ssh/pkgkey -l $REMOTE_ROOT $TARGET "pkgrm ${PACKAGE}"
fi

}

#############
# Main      #
#############

# We need to be called with at least one argument
# 
if [ $# -eq 0 ]; then
   f_usage
   exit 1
fi

# Check the command parameters
#
while getopts p:t:u:k:b:mSehDl args; do
   case $args in
     p)   PACKAGE=$OPTARG
          ;;
     t)   TARGET=$OPTARG
          ;;
     u)   REMOTE_ROOT=$OPTARG
          ;;
     k)   KEYTYPE=$OPTARG
          ;;
     m)   DELPKG="no"
          ;;
     S)   RMKEYS="no"
          ;;
     b)   BATCHCONFIG=$OPTARG
          BATCHMODE="yes"
          ;;
     e)   EXPUNGE="yes"
          ;;
     D)   RMPKG="yes"
          ;;
     h)   HELP="yes"
          ;;
     l)   LIC="yes"
          ;;
     *)   echo "Invalid option."
          f_usage
          ;;
   esac
done

# Respond to special requests
#
if [ "$HELP" = "yes" ]; then
   f_help
   exit 1
fi

if [ "$LIC" = "yes" ]; then
   f_show_lic
   exit 1
fi

# Generate a temporary (if necessary) dsa or rsa key for this session.  
# It will be removed from the target host's authorized keys file 
# automatically at the end of the run if the -r flag is NOT specified
#

# Get the current user and home directory
#
ME=`id | sed -e 's/).*//g' -e 's/.*(//g'`

if [ "$NIS" = "yes" ]; then
   export MYHOME=`ypcat passwd | grep $ME | cut -d: -f6`
else
   export MYHOME=`grep $ME /etc/passwd | cut -d: -f6`
fi

# Handle the creation and/or deletion of SSH keys
#
if [ "$EXPUNGE" = "yes" ]; then
   if [ -f $MYHOME/.ssh/pkgkey.pub ]; then
      rm $MYHOME/.ssh/pkgkey.pub
   fi
   if [ -f $MYHOME/.ssh/pkgkey ]; then
      rm $MYHOME/.ssh/pkgkey
   fi
fi

if [ ! -f $MYHOME/.ssh/pkgkey.pub ]; then
    if [ ! -d $MYHOME/.ssh ]; then
       mkdir -m 0700 $MYHOME/.ssh
    fi
   
   echo "----------------------------------------------------------------"
   echo "Hit return when asked for password.   authorized_keys files will"
   echo "be removed from the target host once packages are added unless  "
   echo "the '-r' is specified on the command line.                      "
   echo "----------------------------------------------------------------"

   ssh-keygen -t $KEYTYPE -C pkgkey -f $MYHOME/.ssh/pkgkey
fi


if [ "$BATCHMODE" = "yes" ]; then

   while read -u3 i; do         # READ FROM FD3 TO AVOID INTERACTIVE 
                                # CONFLICTS WITH pkgadd
      if [ "x`echo $i | egrep '^[^# ]'`" = "x" ]; then
         continue
      fi

      export TARGET=`echo $i | cut -f1 -d:`
      export REMOTE_ROOT=`echo $i | cut -f2 -d:`
      export RMPKG=`echo $i | cut -f3 -d:`
      export RMKEYS=`echo $i | cut -f4 -d:`
      export DELPKG=`echo $i | cut -f5 -d:`
      export KEYTYPE=`echo $i | cut -f6 -d:`
      export PKGS_TO_PROCESS=`echo $i | awk 'BEGIN { FS = ":"} \
        { for ( k = 7; k<= NF; k++ ) print $k }'`

      # Add keys to the target host
      #
      f_add_keys

      for p in $PKGS_TO_PROCESS; do
         export PACKAGE=$p
         f_main_engine   
      done

      # If we are removing the rsa/dsa ssh keys, we do that here.
      #
      if [ $RMKEYS = "yes" ]; then
         f_remove_keys
      fi

   done 3<$BATCHCONFIG

else
   # Add keys to the target host
   #
   f_add_keys

   f_main_engine   

   # If we are removing the rsa/dsa ssh keys, we do that here.
   #
   if [ $RMKEYS = "yes" ]; then
      f_remove_keys
   fi
fi