Automating RHN Satellite Configuration Management

What is RHN satellite server?

The Red Hat (RH) Network (RHN) Satellite server is a management tool developed by Red Hat Inc. to assist with the monitoring of specific alarms and the updating of Red Hat Enterprise Linux (RHEL) server farms.

The satellite server is a localized version of the services provided by the RHN portal. Each server being administered by a satellite must first be registered on the satellite server and assigned to a software channel and organization. In addition the satellite server itself needs internet access to download and sync the rpm packages with the official Red Hat maintained repositories. It must also be registered with Red Hat via the customer portal as a satellite with the extra satellite server entitlement subscription enabled. Internet access is needed from the satellite server to the RHN portal to validate the entitlements for each server registered to it.

What is the satellite good for?

Satellite servers particularly excel at taking the burden off administrators to track outdated and vulnerable systems, deploy software packages, and finally to apply patches by scheduling updates during maintainance periods. Packages are managed by "software channels" which in turn map back to yum repositiories that can be official, third party, or custom made.

Over time RH has been adding features to the satellite servers making it more and more similar to tools like Puppet, Chef, and Foreman for configuration management and server deployment. These other tools outclass RHN satellite in this aspect as they are more specific and geared towards this one task as well as they can manage systems other than just RHEL. Nevertheless, for those in homogenious Red Hat centric environments who want a simple solution that fits within the RH ecosystem, the RHN satellite is a good option.

Automating the configuration management process

One key problem with the configuration management features as they are today is that deploying config files cannot be automated by the schedulor. Administrators must first log into the satellite web service and schedule the update. The scheduler can only run jobs to compare differences automatically but not push or pull changes as these must be initiated by the admin from the GUI. Also the scheduler cannot run in real time as it relies on a pull method whereby the clients initiate the request which takes at least 4 hours using the default settings.

One way of working around this limitation is to use the satellite CLI tools on the client to trigger the push and pull from the central satellite repo and then automating this via a cronjob. The script below is one such attempt at accomplishing this automation from the client side.

#!/bin/bash
#
# description: Update configuration files on the client for the channels that it is registered (pull) or update (push) files on satellite repo.
# author: Nneko Branche
#
#Copyright (c) 2014 Nneko Branche - Released under the MIT License.
#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, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
#The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
#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. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

USER=root
RETVAL=0
prog="rhncfg-update"

if ! $( [ "$1" == "push" ] || [ "$1" == "pull" ] );
then
	echo "usage: rhncfg-update.sh [push|pull]";
	exit -1;
fi	

#List files that differ from central repository
modcfgs=( `rhncfg-client verify -o | awk '{print $2}'` );

#Push modified configuration files to the central repo.
if [ "$1" == "push" ];
then
	# List the configuration channels and files registered for this client. Split the list into a {file, channel} hash
	declare -A cfglst;
	while read line; 
	do
		pair=`echo $line | awk '{if($1=="F"){print $2" "$3}}'`;
		OIFS="$IFS";
		IFS=' ';
	    read -a cfgpair <<< "${pair}";
	    IFS="$OIFS";
	    if [[ ${cfgpair[1]} =~ ^/ ]];
    	then
	    	cfglst["${cfgpair[1]}"]="${cfgpair[0]}";
	    else
	    	continue;
	    fi
	done < <(rhncfg-client list)

	#Find the channel associated with the modified file and update the central repository	
	for cfg in ${modcfgs[@]};
	do
		channel=${cfglst["$cfg"]};
		if [ "$channel" != "" ];
		then
			#Fetch username and password from ~/.rhncfgrc
			if [ -e ~/.rhncfgrc ];
			then
				#Read username and password from file and load into hash userparams
				declare -A userparams;
				while read params;
				do
					OIFS="$IFS";
					IFS=' ';
				    read -a param <<< "${params}";
				    IFS="$OIFS";
			    	userparams["${param[0]}"]="${param[1]}";
				done < <(cat ~/.rhncfgrc|awk -F= '{if($1=="password"||$1=="username"){print $1" "$2}}')

				logger -p daemon.notice -t $prog "updating file $cfg in configuration channel $channel...";
				if [ ${#userparams[@]} -eq 2 ];
				then
					logger -p daemon.notice -t $prog "attempting update using user parameters specified in .rhncfgrc";
					rhncfg-manager update --username ${userparams["username"]} --password ${userparams["password"]} -c $channel $cfg;
				else
					rhncfg-manager update -c $channel $cfg;
				fi
			fi
		fi
	done
fi

#Download modified files from the central repository if node is instructed to pull
if [ "$1" == "client" ];
then
	if [ ${#modcfgs[@]} -gt 1 ];
	then
		for file in ${modcfgs[@]};
		do
			if [ "$file" != "" ] && [ "$file" != "server" ];
			then
				logger -p daemon.notice -t $prog "deploying $file from central repository...";
				rhncfg-client get $file;
			fi
		done
	fi
fi

The latest downloadable version of the script can be found here

Possible script improvements

  1. Currently the script stores the satellite credentials in the rhncfgrc run control config file in the users home directory. However, these passwords are stored in plain text which is a security risk. This could be made better by using pgp or some other key based encryption mechanism to store the credentials by generating a hash which is then decoded with a public key file.