Files
packstack/packstack/plugins/serverprep_901.py
Derek Higgins 624d49a0e8 Securely create temp directorys / files
The temp directory packstack was using was being created in
an insecure manor with world readable permissions. This commit ensures
temp directories are created securly on both the local and remote
hosts

o Create var directory with tempfile.mkdtemp
o remove other places where var directory was created
o change permissions of all files that do (or may) contain
  sensitive data to 600
o No longer append data to mainifest file, it is now created and
  writen out in once
o Attempts to remove data on remote hosts after the packstach run

CVE-2013-0261
https://bugzilla.redhat.com/show_bug.cgi?id=908101

Change-Id: Ie7105207d3da128d630628c1df037ffafc94beb8
2013-02-12 09:16:06 -05:00

412 lines
20 KiB
Python

"""
prepare server
"""
import os
import logging
import os
from packstack.installer import basedefs
from packstack.installer import common_utils as utils
from packstack.installer import engine_validators as validate
from packstack.installer.exceptions import InstallError
from packstack.modules.ospluginutils import gethostlist
# Controller object will be initialized from main flow
controller = None
# Plugin name
PLUGIN_NAME = "OS-SERVERPREPARE"
PLUGIN_NAME_COLORED = utils.getColoredText(PLUGIN_NAME, basedefs.BLUE)
logging.debug("plugin %s loaded", __name__)
def initConfig(controllerObject):
global controller
controller = controllerObject
logging.debug("Adding SERVERPREPARE KEY configuration")
conf_params = {"SERVERPREPARE": [
{"CMD_OPTION" : "use-epel",
"USAGE" : "Install OpenStack from EPEL. If set to \"y\" EPEL will be installed on each server",
"PROMPT" : "Should Packstack install EPEL on each server",
"OPTION_LIST" : ["y", "n"],
"VALIDATORS" : [validate.validate_options],
"DEFAULT_VALUE" : "n",
"MASK_INPUT" : False,
"LOOSE_VALIDATION": True,
"CONF_NAME" : "CONFIG_USE_EPEL",
"USE_DEFAULT" : False,
"NEED_CONFIRM" : False,
"CONDITION" : False },
{"CMD_OPTION" : "additional-repo",
"USAGE" : "A comma separated list of URLs to any additional yum repositories to install",
"PROMPT" : "Enter a comma separated list of URLs to any additional yum repositories to install",
"OPTION_LIST" : [],
"DEFAULT_VALUE" : "",
"MASK_INPUT" : False,
"LOOSE_VALIDATION": True,
"CONF_NAME" : "CONFIG_REPO",
"USE_DEFAULT" : False,
"NEED_CONFIRM" : False,
"CONDITION" : False },
{"CMD_OPTION" : "rh-username",
"USAGE" : "To subscribe each server with Red Hat subscription manager, include this with CONFIG_RH_PASSWORD",
"PROMPT" : "To subscribe each server to Red Hat enter a username here",
"OPTION_LIST" : [],
"DEFAULT_VALUE" : "",
"MASK_INPUT" : False,
"LOOSE_VALIDATION": True,
"CONF_NAME" : "CONFIG_RH_USERNAME",
"USE_DEFAULT" : False,
"NEED_CONFIRM" : False,
"CONDITION" : False },
{"CMD_OPTION" : "rh-password",
"USAGE" : "To subscribe each server with Red Hat subscription manager, include this with CONFIG_RH_USERNAME",
"PROMPT" : "To subscribe each server to Red Hat enter your password here",
"OPTION_LIST" : [],
"DEFAULT_VALUE" : "",
"MASK_INPUT" : True,
"LOOSE_VALIDATION": True,
"CONF_NAME" : "CONFIG_RH_PASSWORD",
"USE_DEFAULT" : False,
"NEED_CONFIRM" : False,
"CONDITION" : False },
{"CMD_OPTION" : "rh-beta-repo",
"USAGE" : "To subscribe each server with Red Hat subscription manager, to Red Hat Beta RPM's",
"PROMPT" : "To subscribe each server to Red Hat Beta RPM's enter y",
"OPTION_LIST" : ["y", "n"],
"VALIDATORS" : [validate.validate_options],
"DEFAULT_VALUE" : "n",
"MASK_INPUT" : False,
"LOOSE_VALIDATION": True,
"CONF_NAME" : "CONFIG_RH_BETA_REPO",
"USE_DEFAULT" : False,
"NEED_CONFIRM" : False,
"CONDITION" : False },
{"CMD_OPTION" : "rhn-satellite-server",
"USAGE" : ("To subscribe each server with RHN Satellite,"
"fill Satellite's URL here. Note that either "
"satellite's username/password or activtion "
"key has to be provided/"),
"PROMPT" : ("To subscribe each server with RHN Satellite "
"enter RHN Satellite server URL"),
"OPTION_LIST" : [],
"DEFAULT_VALUE" : "",
"MASK_INPUT" : False,
"LOOSE_VALIDATION": False,
"CONF_NAME" : "CONFIG_SATELLITE_URL",
"USE_DEFAULT" : False,
"NEED_CONFIRM" : False,
"CONDITION" : False },
{"CMD_OPTION" : "rhn-satellite-username",
"USAGE" : "Username to access RHN Satellite",
"PROMPT" : ("Enter RHN Satellite username or leave plain "
"if you will use activation key instead"),
"OPTION_LIST" : [],
"DEFAULT_VALUE" : "",
"MASK_INPUT" : False,
"LOOSE_VALIDATION": True,
"CONF_NAME" : "CONFIG_SATELLITE_USERNAME",
"USE_DEFAULT" : False,
"NEED_CONFIRM" : False,
"CONDITION" : False },
{"CMD_OPTION" : "rhn-satellite-password",
"USAGE" : "Password to access RHN Satellite",
"PROMPT" : ("Enter RHN Satellite password or leave plain "
"if you will use activation key instead"),
"OPTION_LIST" : [],
"DEFAULT_VALUE" : "",
"MASK_INPUT" : True,
"LOOSE_VALIDATION": False,
"CONF_NAME" : "CONFIG_SATELLITE_PASSWORD",
"USE_DEFAULT" : False,
"NEED_CONFIRM" : False,
"CONDITION" : False },
{"CMD_OPTION" : "rhn-satellite-activation-key",
"USAGE" : "Activation key for subscription to RHN Satellite",
"PROMPT" : ("Enter RHN Satellite activation key or leave plain "
"if you used username/password instead"),
"OPTION_LIST" : [],
"DEFAULT_VALUE" : "",
"MASK_INPUT" : True,
"LOOSE_VALIDATION": False,
"CONF_NAME" : "CONFIG_SATELLITE_AKEY",
"USE_DEFAULT" : False,
"NEED_CONFIRM" : False,
"CONDITION" : False },
{"CMD_OPTION" : "rhn-satellite-cacert",
"USAGE" : "Specify a path or URL to a SSL CA certificate to use",
"PROMPT" : "Specify a path or URL to a SSL CA certificate to use",
"OPTION_LIST" : [],
"DEFAULT_VALUE" : "",
"MASK_INPUT" : True,
"LOOSE_VALIDATION": False,
"CONF_NAME" : "CONFIG_SATELLITE_CACERT",
"USE_DEFAULT" : False,
"NEED_CONFIRM" : False,
"CONDITION" : False },
{"CMD_OPTION" : "rhn-satellite-profile",
"USAGE" : ("If required specify the profile name that should "
"be used as an identifier for the system in RHN "
"Satellite"),
"PROMPT" : ("If required specify the profile name that should "
"be used as an identifier for the system in RHN "
"Satellite"),
"OPTION_LIST" : [],
"DEFAULT_VALUE" : "",
"MASK_INPUT" : True,
"LOOSE_VALIDATION": False,
"CONF_NAME" : "CONFIG_SATELLITE_PROFILE",
"USE_DEFAULT" : False,
"NEED_CONFIRM" : False,
"CONDITION" : False },
{"CMD_OPTION" : "rhn-satellite-proxy-host",
"USAGE" : "Specify a HTTP proxy to use with RHN Satellite",
"PROMPT" : "Specify a HTTP proxy to use with RHN Satellite",
"OPTION_LIST" : [],
"DEFAULT_VALUE" : "",
"MASK_INPUT" : True,
"LOOSE_VALIDATION": False,
"CONF_NAME" : "CONFIG_SATELLITE_PROXY",
"USE_DEFAULT" : False,
"NEED_CONFIRM" : False,
"CONDITION" : False },
{"CMD_OPTION" : "rhn-satellite-proxy-username",
"USAGE" : "Specify a username to use with an authenticated HTTP proxy",
"PROMPT" : "Specify a username to use with an authenticated HTTP proxy",
"OPTION_LIST" : [],
"DEFAULT_VALUE" : "",
"MASK_INPUT" : True,
"LOOSE_VALIDATION": False,
"CONF_NAME" : "CONFIG_SATELLITE_PROXY_USERNAME",
"USE_DEFAULT" : False,
"NEED_CONFIRM" : False,
"CONDITION" : False },
{"CMD_OPTION" : "rhn-satellite-proxy-password",
"USAGE" : "Specify a password to use with an authenticated HTTP proxy.",
"PROMPT" : "Specify a password to use with an authenticated HTTP proxy.",
"OPTION_LIST" : [],
"DEFAULT_VALUE" : "",
"MASK_INPUT" : True,
"LOOSE_VALIDATION": False,
"CONF_NAME" : "CONFIG_SATELLITE_PROXY_PASSWORD",
"USE_DEFAULT" : False,
"NEED_CONFIRM" : False,
"CONDITION" : False },
{"CMD_OPTION" : "rhn-satellite-flags",
"USAGE" : ("Comma separated list of flags passed to rhnreg_ks. Valid "
"flags are: novirtinfo, norhnsd, nopackages"),
"PROMPT" : "Enter comma separated list of flags passed to rhnreg_ks",
"OPTION_LIST" : ['novirtinfo', 'norhnsd', 'nopackages'],
"VALIDATORS" : [validate_multi_options],
"DEFAULT_VALUE" : "",
"MASK_INPUT" : True,
"LOOSE_VALIDATION": False,
"CONF_NAME" : "CONFIG_SATELLITE_FLAGS",
"USE_DEFAULT" : False,
"NEED_CONFIRM" : False,
"CONDITION" : False },
]
}
conf_groups = [
{ "GROUP_NAME" : "SERVERPREPARE",
"DESCRIPTION" : "Server Prepare Configs ",
"PRE_CONDITION" : utils.returnYes,
"PRE_CONDITION_MATCH" : "yes",
"POST_CONDITION" : False,
"POST_CONDITION_MATCH" : True},
]
for group in conf_groups:
paramList = conf_params[group["GROUP_NAME"]]
controller.addGroup(group, paramList)
def validate_multi_options(param, options=None):
"""
Validates if comma separated values given in params are members
of options.
"""
# TO-DO: Move this to packstack.installer.setup_validators and modify
# it to raise exception as soon as I1bb3486e will be accepted
options = options or []
for i in param.split(','):
if i.strip() not in options:
msg = 'Given value is not member of allowed values %s: %s'
# TO-DO: raise ParamValidationError(msg % (options, param))
print msg % (options, param)
return False
return True
def run_rhn_reg(host, server_url, username=None, password=None,
cacert=None, activation_key=None, profile_name=None,
proxy_host=None, proxy_user=None, proxy_pass=None,
flags=None):
"""
Registers given host to given RHN Satellite server. To successfully
register either activation_key or username/password is required.
"""
logging.debug('Setting RHN Satellite server: %s.' % locals())
mask = []
cmd = ['/usr/sbin/rhnreg_ks']
server = utils.ScriptRunner(host)
# check satellite server url
server_url = server_url.rstrip('/').endswith('/XMLRPC') \
and server_url \
or '%s/XMLRPC' % server_url
cmd.extend(['--serverUrl', server_url])
if activation_key:
cmd.extend(['--activationkey', activation_key])
elif username:
cmd.extend(['--username', username])
if password:
cmd.extend(['--password', password])
mask.append(password)
else:
raise InstallError('Either RHN Satellite activation key or '
'username/password must be provided.')
if cacert:
# use and if required download given certificate
location = "/etc/sysconfig/rhn/%s" % os.path.basename(cacert)
if not os.path.isfile(location):
logging.debug('Downloading cacert from %s.' % server_url)
wget_cmd = ('ls %(location)s &> /dev/null && echo -n "" || '
'wget -nd --no-check-certificate --timeout=30 '
'--tries=3 -O "%(location)s" "%(cacert)s"' %
locals())
server.append(wget_cmd)
cmd.extend(['--sslCACert', location])
if profile_name:
cmd.extend(['--profilename', profile_name])
if proxy_host:
cmd.extend(['--proxy', proxy_host])
if proxy_user:
cmd.extend(['--proxyUser', proxy_user])
if proxy_pass:
cmd.extend(['--proxyPassword', proxy_pass])
mask.append(proxy_pass)
flags = flags or []
flags.append('force')
for i in flags:
cmd.append('--%s' % i)
server.append(' '.join(cmd))
server.append('yum clean metadata')
server.execute(maskList=mask)
def run_rhsm_reg(host, username, password, beta):
"""
Registers given host to Red Hat Repositories via subscription manager.
"""
server = utils.ScriptRunner(host)
# register host
cmd = ('subscription-manager register --username=\"%s\" '
'--password=\"%s\" --autosubscribe || true')
server.append(cmd % (username, password.replace('"','\\"')))
# subscribe to required channel
cmd = ('subscription-manager list --consumed | grep -i openstack || '
'subscription-manager subscribe --pool %s')
pool = ("$(subscription-manager list --available | "
"grep -e 'Red Hat OpenStack' -m 1 -A 2 | grep 'Pool Id' | "
"awk '{print $3}')")
server.append(cmd % pool)
server.append("yum clean all")
server.append("yum-config-manager --enable rhel-server-ost-6-folsom-rpms")
if beta:
server.append("yum-config-manager --enable rhel-6-server-beta-rpms")
server.append("yum clean metadata")
server.execute(maskList=[password])
def initSequences(controller):
preparesteps = [
{'title': 'Preparing servers', 'functions':[serverprep]}
]
controller.addSequence("Preparing servers", [], [], preparesteps)
def serverprep():
config = controller.CONF
rh_username = config["CONFIG_RH_USERNAME"].strip()
rh_password = config["CONFIG_RH_PASSWORD"].strip()
sat_registered = set()
satellite_flags = map(lambda i: i.strip(),
config["CONFIG_SATELLITE_FLAGS"].split(','))
satellite_url = config["CONFIG_SATELLITE_URL"]
satellite_args = {'username': config["CONFIG_SATELLITE_USERNAME"].strip(),
'password': config["CONFIG_SATELLITE_PASSWORD"].strip(),
'cacert': config["CONFIG_SATELLITE_CACERT"].strip(),
'activation_key': config["CONFIG_SATELLITE_AKEY"].strip(),
'profile_name': config["CONFIG_SATELLITE_PROFILE"].strip(),
'proxy_host': config["CONFIG_SATELLITE_PROXY"].strip(),
'proxy_user': config["CONFIG_SATELLITE_PROXY_USERNAME"].strip(),
'proxy_pass': config["CONFIG_SATELLITE_PROXY_PASSWORD"].strip(),
'flags': satellite_flags}
for hostname in gethostlist(config):
if '/' in hostname:
hostname = hostname.split('/')[0]
server = utils.ScriptRunner(hostname)
# install epel if on rhel (or popular derivative thereof) and epel is configured
if config["CONFIG_USE_EPEL"] == 'y':
server.append("REPOFILE=$(mktemp)")
server.append("cat /etc/yum.conf > $REPOFILE")
server.append("echo -e '[packstack-epel]\nname=packstack-epel\n"
"enabled=1\n"
"mirrorlist=https://mirrors.fedoraproject.org/metalink?repo=epel-6&arch=$basearch'"
">> $REPOFILE")
server.append("grep -e 'Red Hat Enterprise Linux' -e 'CentOS' -e 'Scientific Linux' /etc/redhat-release && "
"( rpm -q epel-release || yum install -y --nogpg -c $REPOFILE epel-release ) || echo -n ''")
server.append("rm -rf $REPOFILE")
# Create the packstack tmp directory
server.append("mkdir -p %s" % basedefs.PACKSTACK_VAR_DIR)
# Separately create the tmp directory for this packstack run, this will fail if
# the directory already exists
server.append("mkdir --mode 0700 %s" % basedefs.VAR_DIR)
# set highest priority of RHOS repository if EPEL is installed
server.append("rpm -q epel-release && yum install -y yum-plugin-priorities || true")
subs_cmd = ('rpm -q epel-release && openstack-config --set %(repo_file)s %(repo)s priority %(priority)s || true')
server.append(subs_cmd % {"repo_file": "/etc/yum.repos.d/redhat.repo",
"repo": "rhel-server-ost-6-folsom-rpms",
"priority": 1})
# Add yum repositories if configured
CONFIG_REPO = config["CONFIG_REPO"].strip()
if CONFIG_REPO:
for i, url in enumerate(CONFIG_REPO.split(',')):
reponame = 'packstack_%d' % i
server.append('echo "[%s]\nname=%s\nbaseurl=%s\nenabled=1\npriority=1\ngpgcheck=0"'
' > /etc/yum.repos.d/%s.repo' % (reponame, reponame, url, reponame))
server.append("yum clean metadata")
server.execute()
# Subscribe to Red Hat Repositories if configured
if rh_username:
run_rhsm_reg(hostname, rh_username, rh_password, config["CONFIG_RH_BETA_REPO"] == 'y')
# Subscribe to RHN Satellite if configured
if satellite_url and hostname not in sat_registered:
run_rhn_reg(hostname, satellite_url, **satellite_args)
sat_registered.add(hostname)