From caed7103420ebbc1ff4a1c3eaa82fe46ed4b9e5f Mon Sep 17 00:00:00 2001 From: Lukas Bezdicka Date: Mon, 15 Dec 2014 12:29:43 -0500 Subject: [PATCH] Option to install FreeIPA Option to setup FreeIPA server and join hosts into IPA. If also SSL for AMQP or Horizon is enabled it gets all certificates from freeipa. Currently experimental and unsupported option. Joining FreeIPA domain requires change of resolver on hosts and mod_ssl colides with mod_nss in case of running FreeIPA server on Controller node thus making allinone setup difficult. Requires: https://github.com/redhat-openstack/openstack-puppet-modules/pull/244 Change-Id: I84e0dee07bf3a4066350a66aebb45678a9a316ba Closes-Bug: rhbz#903645 --- packstack/installer/output_messages.py | 11 + packstack/modules/ospluginutils.py | 54 +++++ .../plugins/{amqp_002.py => amqp_003.py} | 39 +++- packstack/plugins/ceilometer_800.py | 11 + packstack/plugins/cinder_250.py | 11 + packstack/plugins/dashboard_500.py | 25 ++- packstack/plugins/freeipa_002.py | 210 ++++++++++++++++++ packstack/plugins/glance_200.py | 11 + packstack/plugins/heat_650.py | 11 + packstack/plugins/neutron_350.py | 11 + packstack/plugins/nova_300.py | 14 ++ packstack/plugins/prescript_000.py | 17 ++ packstack/plugins/puppet_950.py | 12 +- packstack/plugins/swift_600.py | 20 +- .../modules/packstack/manifests/ipa_client.pp | 110 +++++++++ .../puppet/templates/ceilometer_rabbitmq.pp | 51 ++++- packstack/puppet/templates/cinder_rabbitmq.pp | 50 ++++- .../templates/glance_ceilometer_rabbitmq.pp | 47 +++- packstack/puppet/templates/heat_rabbitmq.pp | 65 +++++- packstack/puppet/templates/horizon.pp | 105 ++++++--- packstack/puppet/templates/ipa_certmonger.pp | 1 + packstack/puppet/templates/ipa_server.pp | 19 ++ packstack/puppet/templates/keystone.pp | 26 ++- packstack/puppet/templates/keystone_swift.pp | 1 + packstack/puppet/templates/nagios_server.pp | 11 +- .../puppet/templates/neutron_rabbitmq.pp | 57 ++++- .../puppet/templates/nova_common_rabbitmq.pp | 57 ++++- packstack/puppet/templates/prescript.pp | 4 - packstack/puppet/templates/swift_proxy.pp | 1 + 29 files changed, 939 insertions(+), 123 deletions(-) rename packstack/plugins/{amqp_002.py => amqp_003.py} (86%) create mode 100644 packstack/plugins/freeipa_002.py create mode 100644 packstack/puppet/modules/packstack/manifests/ipa_client.pp create mode 100644 packstack/puppet/templates/ipa_certmonger.pp create mode 100644 packstack/puppet/templates/ipa_server.pp diff --git a/packstack/installer/output_messages.py b/packstack/installer/output_messages.py index 295d6fdde..3a31e61f5 100644 --- a/packstack/installer/output_messages.py +++ b/packstack/installer/output_messages.py @@ -67,6 +67,17 @@ WARN_NM_ENABLED = ("Warning: NetworkManager is active on %s. OpenStack " "networking currently does not work on systems that have " "the Network Manager service enabled.") +WARN_IPA_INSTALLED = ("Warning: In order to join domain IPA hosts have their " + "DNS resolver set to CONFIG_IPA_HOST!") +WARN_IPA_CONTROLLER_SWIFT = ("Warning: FreeIPA was set up on controller node! " + "We had to switch swift_proxy port to 8081 and this " + "port isn't labeled properly so unless you set SElinux to " + "permissive mode, swift proxy won't work.") +WARN_IPA_CONTROLLER_HORIZON = ("Warning: FreeIPA was set up on controller node! " + "We couldn't set dashboard configuration from puppet-horizon. " + "Any Horizon SSL configuration will be ignored, dashboard will" + "be accessible from http and https with certificates " + "provided by ipa mod_nss configuration.") ERR_PING = "Error: the provided hostname is unreachable" ERR_SSH = "Error: could not connect to the ssh server: %s" diff --git a/packstack/modules/ospluginutils.py b/packstack/modules/ospluginutils.py index 63cffe054..46dd11060 100644 --- a/packstack/modules/ospluginutils.py +++ b/packstack/modules/ospluginutils.py @@ -106,6 +106,60 @@ def createFirewallResources(hiera_key, default_value='{}'): return "create_resources(packstack::firewall, %s)\n\n" % hiera_function +def createIpaHostResources(hiera_key, default_value='{}'): + hiera_function = "hiera('%s', %s)" % (hiera_key, default_value) + return "create_resources(ipa::hostadd, %s)\n\n" % hiera_function + + +def createIpaClientResources(hiera_key, default_value='{}'): + hiera_function = "hiera('%s', %s)" % (hiera_key, default_value) + return "create_resources(packstack::ipa_client, %s)\n\n" % hiera_function + + +def createIpaServiceResources(hiera_key, default_value='{}'): + hiera_function = "hiera('%s', %s)" % (hiera_key, default_value) + return "create_resources(ipa::serviceadd, %s)\n\n" % hiera_function + + +def createIpaCertmongerResources(hiera_key, default_value='{}'): + hiera_function = "hiera('%s', %s)" % (hiera_key, default_value) + return ("create_resources(certmonger::request_ipa_cert, %s)\n\n" + % hiera_function) + + +def generateIpaServiceManifests(config, ipa_host, ipa_service, ssl_key_file, + ssl_cert_file): + ipa_hosts = config['IPA_HOSTS_DICT'] + ipa_hostname = ipa_hosts.get(ipa_host) + ipa_server_service = dict() + key = "freeipa_service_%s_%s" % (ipa_host, ipa_service) + config_name = "FREEIPA_SERVICE_%s_%s" % (ipa_host, ipa_service) + ipa_server_service.setdefault(key, {}) + ipa_server_service[key]['name'] = ("%s/%s.packstack@PACKSTACK" + % (ipa_service, ipa_hostname)) + config[config_name] = ipa_server_service + manifestfile = "%s_ipa.pp" % config['CONFIG_IPA_HOST'] + manifestdata = createIpaServiceResources(config_name) + appendManifestFile(manifestfile, manifestdata) + + ipa_client_cert = dict() + key = "freeipa_cert_%s_%s" % (ipa_host, ipa_service) + config_name = "FREEIPA_CERTIFICATE_%s_%s" % (ipa_host, ipa_service) + ipa_client_cert.setdefault(key, {}) + ipa_client_cert[key]['name'] = ("openssl-%s/%s.packstack@PACKSTACK" + % (ipa_service, ipa_hostname)) + ipa_client_cert[key]['seclib'] = 'openssl' + ipa_client_cert[key]['principal'] = ("%s/%s.packstack@PACKSTACK" + % (ipa_service, ipa_hostname)) + ipa_client_cert[key]['key'] = ssl_key_file + ipa_client_cert[key]['cert'] = ssl_cert_file + ipa_client_cert[key]['hostname'] = "%s.packstack" % ipa_hostname + config[config_name] = ipa_client_cert + manifestfile = "%s_ipa_crts.pp" % ipa_host + manifestdata = createIpaCertmongerResources(config_name) + appendManifestFile(manifestfile, manifestdata, 'ipa-crts') + + def gethostlist(CONF): hosts = [] for key, value in CONF.items(): diff --git a/packstack/plugins/amqp_002.py b/packstack/plugins/amqp_003.py similarity index 86% rename from packstack/plugins/amqp_002.py rename to packstack/plugins/amqp_003.py index 9ed18734c..ce03197f7 100644 --- a/packstack/plugins/amqp_002.py +++ b/packstack/plugins/amqp_003.py @@ -24,6 +24,7 @@ from packstack.modules.ospluginutils import appendManifestFile from packstack.modules.ospluginutils import createFirewallResources from packstack.modules.ospluginutils import getManifestTemplate +from packstack.modules.ospluginutils import generateIpaServiceManifests # ------------- AMQP Packstack Plugin Initialization -------------- @@ -141,6 +142,21 @@ def initConfig(controller): "NEED_CONFIRM": False, "CONDITION": False}, + {"CMD_OPTION": "amqp-ssl-cacert-file", + "USAGE": ("The filename of the CAcertificate that the AMQP service " + "is going to use for verification"), + "PROMPT": ("Enter the filename of the SSL CAcertificate for the AMQP" + " service"), + "OPTION_LIST": [], + "VALIDATORS": [validators.validate_not_empty], + "DEFAULT_VALUE": "/etc/pki/tls/certs/amqp_selfcert.pem", + "MASK_INPUT": False, + "LOOSE_VALIDATION": True, + "CONF_NAME": "CONFIG_AMQP_SSL_CACERT_FILE", + "USE_DEFAULT": False, + "NEED_CONFIRM": False, + "CONDITION": False}, + {"CMD_OPTION": "amqp-ssl-key-file", "USAGE": ("The filename of the private key that the AMQP service " "is going to use"), @@ -230,13 +246,22 @@ def create_manifest(config, messages): config['CONFIG_AMQP_PROTOCOL'] = 'ssl' config['CONFIG_AMQP_CLIENTS_PORT'] = "5671" if config['CONFIG_AMQP_SSL_SELF_SIGNED'] == 'y': - server.append( - "openssl req -batch -new -x509 -nodes -keyout %s " - "-out %s -days 1095" - % (config['CONFIG_AMQP_SSL_KEY_FILE'], - config['CONFIG_AMQP_SSL_CERT_FILE']) - ) - server.execute() + if config['CONFIG_IPA_INSTALL'] != 'y': + server.append( + "openssl req -batch -new -x509 -nodes -keyout %s " + "-out %s -days 1095" + % (config['CONFIG_AMQP_SSL_KEY_FILE'], + config['CONFIG_AMQP_SSL_CERT_FILE']) + ) + server.execute() + else: + config['CONFIG_AMQP_SSL_CACERT_FILE'] = '/etc/ipa/ca.crt' + ipa_host = config['CONFIG_AMQP_HOST'] + ipa_service = 'AMQP' + ssl_key_file = config['CONFIG_AMQP_SSL_KEY_FILE'] + ssl_cert_file = config['CONFIG_AMQP_SSL_CERT_FILE'] + generateIpaServiceManifests(config, ipa_host, ipa_service, + ssl_key_file, ssl_cert_file) else: # Set default values config['CONFIG_AMQP_CLIENTS_PORT'] = "5672" diff --git a/packstack/plugins/ceilometer_800.py b/packstack/plugins/ceilometer_800.py index c27161b3e..0d0a6e2b2 100644 --- a/packstack/plugins/ceilometer_800.py +++ b/packstack/plugins/ceilometer_800.py @@ -26,6 +26,7 @@ from packstack.modules.ospluginutils import appendManifestFile from packstack.modules.ospluginutils import createFirewallResources from packstack.modules.ospluginutils import getManifestTemplate +from packstack.modules.ospluginutils import generateIpaServiceManifests # ------------- Ceilometer Packstack Plugin Initialization -------------- @@ -275,6 +276,16 @@ def create_manifest(config, messages): sentinel_fallbacks = '' config['CONFIG_REDIS_SENTINEL_FALLBACKS'] = sentinel_fallbacks + if (config['CONFIG_IPA_INSTALL'] == 'y' and + config['CONFIG_AMQP_ENABLE_SSL'] and + config['CONFIG_AMQP_SSL_SELF_SIGNED'] == 'y'): + ipa_host = config['CONFIG_CONTROLLER_HOST'] + ssl_key_file = '/etc/pki/tls/private/ssl_amqp_ceilometer.key' + ssl_cert_file = '/etc/pki/tls/certs/ssl_amqp_ceilometer.crt' + ipa_service = 'ceilometer' + generateIpaServiceManifests(config, ipa_host, ipa_service, + ssl_key_file, ssl_cert_file) + fw_details = dict() key = "ceilometer_api" fw_details.setdefault(key, {}) diff --git a/packstack/plugins/cinder_250.py b/packstack/plugins/cinder_250.py index 368bc4946..ea67275b8 100644 --- a/packstack/plugins/cinder_250.py +++ b/packstack/plugins/cinder_250.py @@ -30,6 +30,7 @@ from packstack.modules.ospluginutils import appendManifestFile from packstack.modules.ospluginutils import createFirewallResources from packstack.modules.ospluginutils import getManifestTemplate +from packstack.modules.ospluginutils import generateIpaServiceManifests # ------------------ Cinder Packstack Plugin initialization ------------------ @@ -729,6 +730,16 @@ def create_manifest(config, messages): if config['CONFIG_UNSUPPORTED'] != 'y': config['CONFIG_STORAGE_HOST'] = config['CONFIG_CONTROLLER_HOST'] + if (config['CONFIG_IPA_INSTALL'] == 'y' and + config['CONFIG_AMQP_ENABLE_SSL'] and + config['CONFIG_AMQP_SSL_SELF_SIGNED'] == 'y'): + ipa_host = config['CONFIG_STORAGE_HOST'] + ssl_key_file = '/etc/pki/tls/private/ssl_amqp_cinder.key' + ssl_cert_file = '/etc/pki/tls/certs/ssl_amqp_cinder.crt' + ipa_service = 'cinder' + generateIpaServiceManifests(config, ipa_host, ipa_service, + ssl_key_file, ssl_cert_file) + manifestdata = getManifestTemplate(get_mq(config, "cinder")) manifestfile = "%s_cinder.pp" % config['CONFIG_STORAGE_HOST'] manifestdata += getManifestTemplate("cinder") diff --git a/packstack/plugins/dashboard_500.py b/packstack/plugins/dashboard_500.py index 3e87af391..0fedec033 100644 --- a/packstack/plugins/dashboard_500.py +++ b/packstack/plugins/dashboard_500.py @@ -25,6 +25,7 @@ from packstack.modules.ospluginutils import appendManifestFile from packstack.modules.ospluginutils import getManifestTemplate +from packstack.modules.ospluginutils import generateIpaServiceManifests # ------------- Horizon Packstack Plugin Initialization -------------- @@ -129,7 +130,6 @@ def initSequences(controller): def create_manifest(config, messages): config["CONFIG_HORIZON_SECRET_KEY"] = uuid.uuid4().hex horizon_host = config['CONFIG_CONTROLLER_HOST'] - manifestfile = "%s_horizon.pp" % horizon_host proto = "http" config["CONFIG_HORIZON_PORT"] = 80 @@ -141,6 +141,9 @@ def create_manifest(config, messages): # Are we using the users cert/key files if config["CONFIG_SSL_CERT"]: + if config['CONFIG_IPA_HOST'] == config['CONFIG_CONTROLLER_HOST']: + raise RuntimeError("FreeIPA on same host as controller won't " + " work with user provided certificates.") ssl_cert = config["CONFIG_SSL_CERT"] ssl_key = config["CONFIG_SSL_KEY"] ssl_chain = config["CONFIG_SSL_CACHAIN"] @@ -163,11 +166,20 @@ def create_manifest(config, messages): host_resources.append((ssl_key, 'ssl_ps_server.key')) host_resources.append((ssl_chain, 'ssl_ps_chain.crt')) else: - messages.append( - "%sNOTE%s : A certificate was generated to be used for ssl, " - "You should change the ssl certificate configured in " - "/etc/httpd/conf.d/ssl.conf on %s to use a CA signed cert." - % (utils.COLORS['red'], utils.COLORS['nocolor'], horizon_host)) + if config['CONFIG_IPA_INSTALL'] == 'y': + ipa_host = config['CONFIG_CONTROLLER_HOST'] + ssl_key_file = '/etc/pki/tls/private/ssl_ps_server.key' + ssl_cert_file = '/etc/pki/tls/certs/ssl_ps_server.crt' + ipa_service = 'HTTP' + generateIpaServiceManifests(config, ipa_host, ipa_service, + ssl_key_file, ssl_cert_file) + else: + messages.append( + "%sNOTE%s : A certificate was generated to be used for " + "ssl, You should change the ssl certificate configured " + "in /etc/httpd/conf.d/ssl.conf on %s to use a CA signed " + "cert." % (utils.COLORS['red'], utils.COLORS['nocolor'], + horizon_host)) else: config["CONFIG_HORIZON_SSL"] = False @@ -180,6 +192,7 @@ def create_manifest(config, messages): if config["CONFIG_NEUTRON_FWAAS"] == 'y': config["CONFIG_HORIZON_NEUTRON_FW"] = True + manifestfile = "%s_horizon.pp" % horizon_host manifestdata = getManifestTemplate("horizon") appendManifestFile(manifestfile, manifestdata) diff --git a/packstack/plugins/freeipa_002.py b/packstack/plugins/freeipa_002.py new file mode 100644 index 000000000..94a7f0607 --- /dev/null +++ b/packstack/plugins/freeipa_002.py @@ -0,0 +1,210 @@ +# -*- coding: utf-8 -*- +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +""" +Installs and configures freeipa +""" + +from packstack.installer import validators +from packstack.installer import processors +from packstack.installer import utils +from packstack.installer import output_messages + +from packstack.modules.common import filtered_hosts +from packstack.modules.ospluginutils import getManifestTemplate +from packstack.modules.ospluginutils import appendManifestFile +from packstack.modules.ospluginutils import createFirewallResources +from packstack.modules.ospluginutils import createIpaHostResources +from packstack.modules.ospluginutils import createIpaClientResources + + +PLUGIN_NAME = "IPA" +PLUGIN_NAME_COLORED = utils.color_text(PLUGIN_NAME, 'blue') + + +def initConfig(controller): + conf_params = { + "IPA": [ + {"CMD_OPTION": "ipa-host", + "USAGE": ("The IP address of the server on which to install " + "the IPA service. It's stronly discouraged to " + "install IPA on controller node!"), + "PROMPT": "Enter the IP address of the IPA server", + "OPTION_LIST": [], + "VALIDATORS": [validators.validate_ssh], + "DEFAULT_VALUE": utils.get_localhost_ip(), + "MASK_INPUT": False, + "LOOSE_VALIDATION": True, + "CONF_NAME": "CONFIG_IPA_HOST", + "USE_DEFAULT": False, + "NEED_CONFIRM": False, + "CONDITION": False}, + + {"CMD_OPTION": "ipa-dm-password", + "USAGE": "Password for IPA domain manager", + "PROMPT": "Enter the password for IPA domain manager", + "OPTION_LIST": [], + "VALIDATORS": [validators.validate_not_empty], + "PROCESSORS": [processors.process_password], + "DEFAULT_VALUE": "PW_PLACEHOLDER", + "MASK_INPUT": True, + "LOOSE_VALIDATION": True, + "CONF_NAME": "CONFIG_IPA_DM_PASSWORD", + "USE_DEFAULT": False, + "NEED_CONFIRM": True, + "CONDITION": False}, + + {"CMD_OPTION": "ipa-admin-password", + "USAGE": "Password for IPA admin user", + "PROMPT": "Enter the password for IPA admin user", + "OPTION_LIST": [], + "VALIDATORS": [validators.validate_not_empty], + "PROCESSORS": [processors.process_password], + "DEFAULT_VALUE": "PW_PLACEHOLDER", + "MASK_INPUT": True, + "LOOSE_VALIDATION": True, + "CONF_NAME": "CONFIG_IPA_ADMIN_PASSWORD", + "USE_DEFAULT": False, + "NEED_CONFIRM": True, + "CONDITION": False}, + ] + } + conf_groups = [ + {"GROUP_NAME": "IPA", + "DESCRIPTION": "IPA Config parameters", + "PRE_CONDITION": "CONFIG_IPA_INSTALL", + "PRE_CONDITION_MATCH": "y", + "POST_CONDITION": False, + "POST_CONDITION_MATCH": True}, + ] + for group in conf_groups: + params = conf_params[group["GROUP_NAME"]] + controller.addGroup(group, params) + + +def initSequences(controller): + config = controller.CONF + if config['CONFIG_IPA_INSTALL'] != 'y': + return + + ipa_hosts = dict() + for host in filtered_hosts(config, exclude=False): + server = utils.ScriptRunner(host) + server.append('hostname -s | head -n1') + retcode, hostname = server.execute() + if hostname != 'localhost': + server.append('hostname "$(hostname -s).packstack"') + server.execute() + ipa_hosts[host] = str(hostname).strip() + else: + raise RuntimeError("localhost is not a valid hostname") + if len(ipa_hosts.values()) != len(set(ipa_hosts.values())): + raise RuntimeError("Duplicate hostnames set on hosts") + # there is no other way to sneak ipa_hosts to other plugins than to put + # it into config :( + config['IPA_HOSTS_DICT'] = ipa_hosts + + ipasteps = [ + {'title': 'Adding IPA manifest entries', + 'functions': [create_manifest]} + ] + controller.addSequence("Installing IPA", [], [], ipasteps) + + +# -------------------------- step functions -------------------------- + +def create_manifest(config, messages): + # Yeah, ipa is demo and for development, sane user shouldn't use it + # we need to make sure he notices that. + msg = output_messages.WARN_IPA_INSTALLED + messages.append(utils.color_text(msg, 'yellow')) + + ipa_hosts = config['IPA_HOSTS_DICT'] + + if config['CONFIG_IPA_HOST'] == config['CONFIG_CONTROLLER_HOST']: + msg = output_messages.WARN_IPA_CONTROLLER_HORIZON + messages.append(utils.color_text(msg, 'yellow')) + + ipa_host = ipa_hosts.get(config['CONFIG_IPA_HOST']) + config['CONFIG_IPA_SERVER_HOSTNAME'] = ipa_host + + manifestfile = "%s_ipa.pp" % config['CONFIG_IPA_HOST'] + manifestdata = getManifestTemplate('ipa_server.pp') + + for ipaddress, hostname in ipa_hosts.items(): + if ipaddress != config['CONFIG_IPA_HOST']: + ipa_client_details = dict() + key = "freeipa_host_%s" % hostname + config_name = "FREEIPA_HOST_%s" % hostname + ipa_client_details.setdefault(key, {}) + ipa_client_details[key]['name'] = "%s.packstack" % hostname + ipa_client_details[key]['otp'] = "%s.packstack" % hostname + config[config_name] = ipa_client_details + manifestdata += createIpaHostResources(config_name) + + # All hosts should be able to talk to ipa + for host in filtered_hosts(config, exclude=False): + fw_details = dict() + ports = ['80', '443', '389', '636', '88', '464', '53'] + key = "freeipa_tcp_%s" % host + config_name = "FIREWALL_FREEIPA_TCP_RULES_%s" % host + fw_details.setdefault(key, {}) + fw_details[key]['service_name'] = "ipa_tcp" + fw_details[key]['ports'] = ports + fw_details[key]['chain'] = "INPUT" + fw_details[key]['proto'] = 'tcp' + fw_details[key]['host'] = "%s" % host + config[config_name] = fw_details + manifestdata += createFirewallResources(config_name) + + fw_details = dict() + key = "freeipa_udp_%s" % host + config_name = "FIREWALL_FREEIPA_UDP_RULES_%s" % host + fw_details.setdefault(key, {}) + fw_details[key]['service_name'] = "ipa_udp" + fw_details[key]['ports'] = ['88', '464', '53', '123'] + fw_details[key]['chain'] = "INPUT" + fw_details[key]['proto'] = 'udp' + fw_details[key]['host'] = "%s" % host + config[config_name] = fw_details + manifestdata += createFirewallResources(config_name) + + appendManifestFile(manifestfile, manifestdata, 'ipa-server') + + for ipaddress, hostname in ipa_hosts.items(): + if ipaddress != config['CONFIG_IPA_HOST']: + admin_install = False + else: + admin_install = True + manifestfile = "%s_ipa_client.pp" % ipaddress + ipa_client_details = dict() + key = "freeipa_client_%s" % hostname + config_name = "FREEIPA_CLIENT_%s" % hostname + ipa_server_hostname = config['CONFIG_IPA_SERVER_HOSTNAME'] + config['IPA_ADMIN_INSTALL'] = admin_install + ipa_client_details.setdefault(key, {}) + ipa_client_details[key]['ipa_hostname'] = hostname + ipa_client_details[key]['ipa_domain'] = 'packstack' + ipa_client_details[key]['ipa_host_ip'] = ipaddress + ipa_client_details[key]['ipa_server_hostname'] = ipa_server_hostname + ipa_client_details[key]['ipa_server_ip'] = config['CONFIG_IPA_HOST'] + ipa_client_details[key]['ipa_admin_install'] = admin_install + config[config_name] = ipa_client_details + manifestdata = createIpaClientResources(config_name) + appendManifestFile(manifestfile, manifestdata, 'ipa-client') + + for ipaddress, hostname in ipa_hosts.items(): + manifestfile = "%s_ipa_crts.pp" % ipaddress + manifestdata = getManifestTemplate('ipa_certmonger.pp') + appendManifestFile(manifestfile, manifestdata, 'ipa-crts') diff --git a/packstack/plugins/glance_200.py b/packstack/plugins/glance_200.py index 88b0a9a3a..4bb20093a 100644 --- a/packstack/plugins/glance_200.py +++ b/packstack/plugins/glance_200.py @@ -24,6 +24,7 @@ from packstack.modules.ospluginutils import appendManifestFile from packstack.modules.ospluginutils import createFirewallResources from packstack.modules.ospluginutils import getManifestTemplate +from packstack.modules.ospluginutils import generateIpaServiceManifests # ------------- Glance Packstack Plugin Initialization -------------- @@ -128,6 +129,16 @@ def create_manifest(config, messages): if config['CONFIG_UNSUPPORTED'] != 'y': config['CONFIG_STORAGE_HOST'] = config['CONFIG_CONTROLLER_HOST'] + if (config['CONFIG_IPA_INSTALL'] == 'y' and + config['CONFIG_AMQP_ENABLE_SSL'] and + config['CONFIG_AMQP_SSL_SELF_SIGNED'] == 'y'): + ipa_host = config['CONFIG_STORAGE_HOST'] + ssl_key_file = '/etc/pki/tls/private/ssl_amqp_glance.key' + ssl_cert_file = '/etc/pki/tls/certs/ssl_amqp_glance.crt' + ipa_service = 'glance' + generateIpaServiceManifests(config, ipa_host, ipa_service, + ssl_key_file, ssl_cert_file) + manifestfile = "%s_glance.pp" % config['CONFIG_STORAGE_HOST'] manifestdata = getManifestTemplate("glance") if config['CONFIG_CEILOMETER_INSTALL'] == 'y': diff --git a/packstack/plugins/heat_650.py b/packstack/plugins/heat_650.py index 03bfd4eff..be392f6a0 100644 --- a/packstack/plugins/heat_650.py +++ b/packstack/plugins/heat_650.py @@ -26,6 +26,7 @@ from packstack.modules.ospluginutils import appendManifestFile from packstack.modules.ospluginutils import createFirewallResources from packstack.modules.ospluginutils import getManifestTemplate +from packstack.modules.ospluginutils import generateIpaServiceManifests # ------------- Heat Packstack Plugin Initialization -------------- @@ -185,6 +186,16 @@ def create_manifest(config, messages): manifestdata += getManifestTemplate("heat") manifestdata += getManifestTemplate("keystone_heat") + if (config['CONFIG_IPA_INSTALL'] == 'y' and + config['CONFIG_AMQP_ENABLE_SSL'] and + config['CONFIG_AMQP_SSL_SELF_SIGNED'] == 'y'): + ipa_host = config['CONFIG_CONTROLLER_HOST'] + ssl_key_file = '/etc/pki/tls/private/ssl_amqp_heat.key' + ssl_cert_file = '/etc/pki/tls/certs/ssl_amqp_heat.crt' + ipa_service = 'heat' + generateIpaServiceManifests(config, ipa_host, ipa_service, + ssl_key_file, ssl_cert_file) + fw_details = dict() key = "heat" fw_details.setdefault(key, {}) diff --git a/packstack/plugins/neutron_350.py b/packstack/plugins/neutron_350.py index 0c597fd0e..23a6697bf 100644 --- a/packstack/plugins/neutron_350.py +++ b/packstack/plugins/neutron_350.py @@ -27,6 +27,7 @@ from packstack.modules.ospluginutils import appendManifestFile from packstack.modules.ospluginutils import createFirewallResources from packstack.modules.ospluginutils import getManifestTemplate +from packstack.modules.ospluginutils import generateIpaServiceManifests # ------------- Neutron Packstack Plugin Initialization -------------- @@ -575,6 +576,16 @@ def create_manifests(config, messages): plugin_manifest = 'neutron_ml2_plugin' for host in q_hosts: + if (config['CONFIG_IPA_INSTALL'] == 'y' and + config['CONFIG_AMQP_ENABLE_SSL'] and + config['CONFIG_AMQP_SSL_SELF_SIGNED'] == 'y'): + ipa_host = host + ssl_key_file = '/etc/pki/tls/private/ssl_amqp_neutron.key' + ssl_cert_file = '/etc/pki/tls/certs/ssl_amqp_neutron.crt' + ipa_service = 'neutron' + generateIpaServiceManifests(config, ipa_host, ipa_service, + ssl_key_file, ssl_cert_file) + manifest_file = "%s_neutron.pp" % (host,) manifest_data = getManifestTemplate("neutron") manifest_data += getManifestTemplate(get_mq(config, "neutron")) diff --git a/packstack/plugins/nova_300.py b/packstack/plugins/nova_300.py index 1c13cf129..8fbd081ba 100644 --- a/packstack/plugins/nova_300.py +++ b/packstack/plugins/nova_300.py @@ -32,6 +32,7 @@ from packstack.modules.ospluginutils import getManifestTemplate from packstack.modules.ospluginutils import manifestfiles from packstack.modules.ospluginutils import NovaConfig +from packstack.modules.ospluginutils import generateIpaServiceManifests # ------------- Nova Packstack Plugin Initialization -------------- @@ -699,6 +700,19 @@ def create_common_manifest(config, messages): data += getManifestTemplate("nova_common_nopw") appendManifestFile(os.path.split(manifestfile)[1], data) + ipa_nova_hosts = compute_hosts + ipa_nova_hosts |= set([config.get('CONFIG_CONTROLLER_HOST')]) + for host in ipa_nova_hosts: + if (config['CONFIG_IPA_INSTALL'] == 'y' and + config['CONFIG_AMQP_ENABLE_SSL'] and + config['CONFIG_AMQP_SSL_SELF_SIGNED'] == 'y'): + ipa_host = host + ssl_key_file = '/etc/pki/tls/private/ssl_amqp_nova.key' + ssl_cert_file = '/etc/pki/tls/certs/ssl_amqp_nova.crt' + ipa_service = 'nova' + generateIpaServiceManifests(config, ipa_host, ipa_service, + ssl_key_file, ssl_cert_file) + def create_neutron_manifest(config, messages): if config['CONFIG_NEUTRON_INSTALL'] != "y": diff --git a/packstack/plugins/prescript_000.py b/packstack/plugins/prescript_000.py index c00586ce1..798a0b8b3 100644 --- a/packstack/plugins/prescript_000.py +++ b/packstack/plugins/prescript_000.py @@ -102,6 +102,23 @@ def initConfig(controller): "CONDITION": False, "DEPRECATES": ['CONFIG_MYSQL_INSTALL']}, + {"CMD_OPTION": "ipa-install", + "USAGE": ( + "Set to 'y' if you would like Packstack to install and " + "integrate Openstack with FreeIPA. NOTE: This is unsupported " + "option." + ), + "PROMPT": "Should Packstack deploy and integrate with FreeIPA", + "OPTION_LIST": ["y", "n"], + "VALIDATORS": [validators.validate_options], + "DEFAULT_VALUE": "n", + "MASK_INPUT": False, + "LOOSE_VALIDATION": False, + "CONF_NAME": "CONFIG_IPA_INSTALL", + "USE_DEFAULT": False, + "NEED_CONFIRM": False, + "CONDITION": False}, + {"CMD_OPTION": "os-glance-install", "USAGE": ( "Set to 'y' if you would like Packstack to install " diff --git a/packstack/plugins/puppet_950.py b/packstack/plugins/puppet_950.py index 982172b3f..907856bd0 100644 --- a/packstack/plugins/puppet_950.py +++ b/packstack/plugins/puppet_950.py @@ -187,12 +187,12 @@ def install_deps(config, messages): def copy_puppet_modules(config, messages): os_modules = ' '.join(('apache', 'ceilometer', 'certmonger', 'cinder', 'concat', 'firewall', 'glance', 'heat', 'horizon', - 'inifile', 'ironic', 'keystone', 'memcached', - 'mongodb', 'mysql', 'neutron', 'nova', 'nssdb', - 'openstack', 'packstack', 'qpid', 'rabbitmq', - 'redis', 'remote', 'rsync', 'sahara', 'ssh', - 'stdlib', 'swift', 'sysctl', 'tempest', 'trove', - 'vcsrepo', 'vlan', 'vswitch', 'xinetd', + 'inifile', 'ipa', 'ironic', 'keystone', + 'memcached', 'mongodb', 'mysql', 'neutron', 'nova', + 'nssdb', 'openstack', 'packstack', 'qpid', + 'rabbitmq', 'redis', 'remote', 'rsync', 'sahara', + 'ssh', 'stdlib', 'swift', 'sysctl', 'tempest', + 'trove', 'vcsrepo', 'vlan', 'vswitch', 'xinetd', 'openstacklib')) # write puppet manifest to disk diff --git a/packstack/plugins/swift_600.py b/packstack/plugins/swift_600.py index 160e2a479..7634faf04 100644 --- a/packstack/plugins/swift_600.py +++ b/packstack/plugins/swift_600.py @@ -25,6 +25,7 @@ from packstack.installer import processors from packstack.installer.exceptions import ParamValidationError from packstack.installer import utils +from packstack.installer import output_messages from packstack.installer.utils import split_hosts from packstack.modules.ospluginutils import appendManifestFile @@ -155,9 +156,19 @@ def initConfig(controller): def initSequences(controller): - if controller.CONF['CONFIG_SWIFT_INSTALL'] != 'y': + config = controller.CONF + if config['CONFIG_SWIFT_INSTALL'] != 'y': return + # If FreeIPA is installed on same host as swift ipa services collide + # on swift proxy port. This is unsupported setup but we still try to + # make it work. + if (config['CONFIG_IPA_INSTALL'] == 'y' and + config['CONFIG_IPA_HOST'] == config['CONFIG_CONTROLLER_HOST']): + config['CONFIG_SWIFT_PROXY_PORT'] = '8081' + else: + config['CONFIG_SWIFT_PROXY_PORT'] = '8080' + steps = [ {'title': 'Adding Swift Keystone manifest entries', 'functions': [create_keystone_manifest]}, @@ -305,7 +316,7 @@ def create_proxy_manifest(config, messages): fw_details[key]['host'] = "ALL" fw_details[key]['service_name'] = "swift proxy" fw_details[key]['chain'] = "INPUT" - fw_details[key]['ports'] = ['8080'] + fw_details[key]['ports'] = "%s" % config['CONFIG_SWIFT_PROXY_PORT'] fw_details[key]['proto'] = "tcp" config['FIREWALL_SWIFT_PROXY_RULES'] = fw_details @@ -356,6 +367,11 @@ def create_storage_manifest(config, messages): def create_common_manifest(config, messages): + if (config['CONFIG_IPA_INSTALL'] == 'y' and + config['CONFIG_IPA_HOST'] == config['CONFIG_CONTROLLER_HOST']): + msg = output_messages.WARN_IPA_CONTROLLER_SWIFT + messages.append(utils.color_text(msg, 'yellow')) + for manifestfile, marker in manifestfiles.getFiles(): if manifestfile.endswith("_swift.pp"): data = getManifestTemplate("swift_common") diff --git a/packstack/puppet/modules/packstack/manifests/ipa_client.pp b/packstack/puppet/modules/packstack/manifests/ipa_client.pp new file mode 100644 index 000000000..84dea849c --- /dev/null +++ b/packstack/puppet/modules/packstack/manifests/ipa_client.pp @@ -0,0 +1,110 @@ +# == Define: packstack::ipa_client +# +# Full description of defined resource type packstack::ipa_client here +# +# === Parameters +# +# [*ipa_hostname*] +# +# [*ipa_domain*] +# +# [*ipa_server_hostname*] +# +# [*ipa_host_ip*] +# +# [*ipa_server_ip*] +# +# [*ipa_admin_install*] +# +# === Examples +# +# Provide some examples on how to use this type: +# +# packstack::ipa_client { 'namevar': +# basedir => '/tmp/src', +# } +# +# === Authors +# +# Lukas Bezdicka +# +# === Copyright +# +# Copyright 2014 Red Hat, Inc. +# +define packstack::ipa_client ( + $ipa_hostname, + $ipa_domain, + $ipa_server_hostname, + $ipa_host_ip, + $ipa_server_ip, + $ipa_admin_install = true +) { + + $realm = upcase("${ipa_domain}") + + class { 'ipa': + client => true, + domain => $ipa_domain, + realm => $realm, + # sssd is started by ipa-client-install and ensuring service is racy in ::ipa + sssd => false, + ipaservers => ["${ipa_server_hostname}.${ipa_domain}"], + desc => "${ipa_hostname}", + clntpkg => $::operatingsystem ? { + 'Fedora' => 'freeipa-client', + default => 'ipa-client', + }, + otp => "${ipa_hostname}.packstack", + } + + ipa::clientinstall { "$::fqdn": + domain => $ipa_domain, + masterfqdn => "${ipa_server_hostname}.${ipa_domain}", + realm => $realm, + otp => "${ipa_hostname}.packstack", + mkhomedir => false, + fixedprimary => true, + } + + file { '/etc/hostname': + content => "${::fqdn}", + } + + if !($ipa_admin_install) { + + $configured_interface = inline_template("<%= scope.lookupvar('::interfaces').split(',').reject { |int| ( scope.lookupvar('::ipaddress_' + int) != @ipa_host_ip ) }[0] -%>") + + # Ugly hack, we need clients to talk to DNS provided by IPA + service { 'network': + ensure => 'running', + before => Class["ipa"], + } + + file { '/etc/dhcp/dhclient.conf': + ensure => 'present', + } + + file_line { 'dhcp-force-ipa-dns': + path => '/etc/dhcp/dhclient.conf', + match => 'prepend domain-name-servers .*;', + line => "prepend domain-name-servers ${ipa_server_ip},;", + notify => Service['network'], + require => File['/etc/dhcp/dhclient.conf'], + } + + file_line { "ifcfg-PEERDNS-no-${configured_interface}": + path => "/etc/sysconfig/network-scripts/ifcfg-${configured_interface}", + match => '^PEERDNS=.*', + line => 'PEERDNS="no"', + notify => Service['network'], + } + + file_line { "ifcfg-DNS1-no-${configured_interface}": + path => "/etc/sysconfig/network-scripts/ifcfg-${configured_interface}", + match => '^DNS1=.*', + line => "DNS1=${ipa_server_ip}", + notify => Service['network'], + } + } +} diff --git a/packstack/puppet/templates/ceilometer_rabbitmq.pp b/packstack/puppet/templates/ceilometer_rabbitmq.pp index ad0c2df47..c4adf8269 100644 --- a/packstack/puppet/templates/ceilometer_rabbitmq.pp +++ b/packstack/puppet/templates/ceilometer_rabbitmq.pp @@ -1,9 +1,44 @@ -class { 'ceilometer': - metering_secret => hiera('CONFIG_CEILOMETER_SECRET'), - rabbit_host => hiera('CONFIG_AMQP_HOST'), - verbose => true, - debug => hiera('CONFIG_DEBUG_MODE'), - rabbit_port => hiera('CONFIG_AMQP_CLIENTS_PORT'), - rabbit_userid => hiera('CONFIG_AMQP_AUTH_USER'), - rabbit_password => hiera('CONFIG_AMQP_AUTH_PASSWORD'), +$ipa_install = hiera('CONFIG_IPA_INSTALL') +$amqp_enable_ssl = hiera('CONFIG_AMQP_ENABLE_SSL') +$amqp_ssl_self_signed = hiera('CONFIG_AMQP_SSL_SELF_SIGNED','n') + +if ($ipa_install == 'y' and + $amqp_enable_ssl and + $amqp_ssl_self_signed == 'y') { + $kombu_ssl_ca_certs = '/etc/ipa/ca.crt' + $kombu_ssl_keyfile = '/etc/pki/tls/private/ssl_amqp_ceilometer.key' + $kombu_ssl_certfile = '/etc/pki/tls/certs/ssl_amqp_ceilometer.crt' + + $files_to_set_owner = [ $kombu_ssl_keyfile, $kombu_ssl_certfile ] + file { $files_to_set_owner: + owner => 'ceilometer', + group => 'ceilometer', + require => Package['openstack-ceilometer-common'], + } + File[$files_to_set_owner] ~> Service<||> + + class { 'ceilometer': + metering_secret => hiera('CONFIG_CEILOMETER_SECRET'), + verbose => true, + debug => hiera('CONFIG_DEBUG_MODE'), + rabbit_host => hiera('CONFIG_AMQP_HOST'), + rabbit_port => hiera('CONFIG_AMQP_CLIENTS_PORT'), + rabbit_use_ssl => $amqp_enable_ssl, + rabbit_userid => hiera('CONFIG_AMQP_AUTH_USER'), + rabbit_password => hiera('CONFIG_AMQP_AUTH_PASSWORD'), + kombu_ssl_ca_certs => $kombu_ssl_ca_certs, + kombu_ssl_keyfile => $kombu_ssl_keyfile, + kombu_ssl_certfile => $kombu_ssl_certfile, + } +} else { + class { 'ceilometer': + metering_secret => hiera('CONFIG_CEILOMETER_SECRET'), + verbose => true, + debug => hiera('CONFIG_DEBUG_MODE'), + rabbit_host => hiera('CONFIG_AMQP_HOST'), + rabbit_port => hiera('CONFIG_AMQP_CLIENTS_PORT'), + rabbit_use_ssl => $amqp_enable_ssl, + rabbit_userid => hiera('CONFIG_AMQP_AUTH_USER'), + rabbit_password => hiera('CONFIG_AMQP_AUTH_PASSWORD'), + } } diff --git a/packstack/puppet/templates/cinder_rabbitmq.pp b/packstack/puppet/templates/cinder_rabbitmq.pp index ffc32c18a..dfbd9afe4 100644 --- a/packstack/puppet/templates/cinder_rabbitmq.pp +++ b/packstack/puppet/templates/cinder_rabbitmq.pp @@ -1,12 +1,46 @@ $cinder_rab_cfg_cinder_db_pw = hiera('CONFIG_CINDER_DB_PW') $cinder_rab_cfg_mariadb_host = hiera('CONFIG_MARIADB_HOST') +$ipa_install = hiera('CONFIG_IPA_INSTALL') +$amqp_enable_ssl = hiera('CONFIG_AMQP_ENABLE_SSL') +$amqp_ssl_self_signed = hiera('CONFIG_AMQP_SSL_SELF_SIGNED','n') -class {'cinder': - rabbit_host => hiera('CONFIG_AMQP_HOST'), - rabbit_port => hiera('CONFIG_AMQP_CLIENTS_PORT'), - rabbit_userid => hiera('CONFIG_AMQP_AUTH_USER'), - rabbit_password => hiera('CONFIG_AMQP_AUTH_PASSWORD'), - database_connection => "mysql://cinder:${cinder_rab_cfg_cinder_db_pw}@${cinder_rab_cfg_mariadb_host}/cinder", - verbose => true, - debug => hiera('CONFIG_DEBUG_MODE'), +if ($ipa_install == 'y' and + $amqp_enable_ssl and + $amqp_ssl_self_signed == 'y') { + $kombu_ssl_ca_certs = '/etc/ipa/ca.crt' + $kombu_ssl_keyfile = '/etc/pki/tls/private/ssl_amqp_cinder.key' + $kombu_ssl_certfile = '/etc/pki/tls/certs/ssl_amqp_cinder.crt' + + $files_to_set_owner = [ $kombu_ssl_keyfile, $kombu_ssl_certfile ] + file { $files_to_set_owner: + owner => 'cinder', + group => 'cinder', + require => Class['cinder'], + notify => Service['cinder-api'], + } + + class {'cinder': + rabbit_host => hiera('CONFIG_AMQP_HOST'), + rabbit_port => hiera('CONFIG_AMQP_CLIENTS_PORT'), + rabbit_userid => hiera('CONFIG_AMQP_AUTH_USER'), + rabbit_password => hiera('CONFIG_AMQP_AUTH_PASSWORD'), + rabbit_use_ssl => $amqp_enable_ssl, + database_connection => "mysql://cinder:${cinder_rab_cfg_cinder_db_pw}@${cinder_rab_cfg_mariadb_host}/cinder", + verbose => true, + debug => hiera('CONFIG_DEBUG_MODE'), + kombu_ssl_ca_certs => $kombu_ssl_ca_certs, + kombu_ssl_keyfile => $kombu_ssl_keyfile, + kombu_ssl_certfile => $kombu_ssl_certfile, + } +} else { + class {'cinder': + rabbit_host => hiera('CONFIG_AMQP_HOST'), + rabbit_port => hiera('CONFIG_AMQP_CLIENTS_PORT'), + rabbit_use_ssl => $amqp_enable_ssl, + rabbit_userid => hiera('CONFIG_AMQP_AUTH_USER'), + rabbit_password => hiera('CONFIG_AMQP_AUTH_PASSWORD'), + database_connection => "mysql://cinder:${cinder_rab_cfg_cinder_db_pw}@${cinder_rab_cfg_mariadb_host}/cinder", + verbose => true, + debug => hiera('CONFIG_DEBUG_MODE'), + } } diff --git a/packstack/puppet/templates/glance_ceilometer_rabbitmq.pp b/packstack/puppet/templates/glance_ceilometer_rabbitmq.pp index 0d3eb1c2a..3272071d5 100644 --- a/packstack/puppet/templates/glance_ceilometer_rabbitmq.pp +++ b/packstack/puppet/templates/glance_ceilometer_rabbitmq.pp @@ -1,9 +1,42 @@ +$ipa_install = hiera('CONFIG_IPA_INSTALL') +$amqp_enable_ssl = hiera('CONFIG_AMQP_ENABLE_SSL') +$amqp_ssl_self_signed = hiera('CONFIG_AMQP_SSL_SELF_SIGNED','n') -class { 'glance::notify::rabbitmq': - rabbit_host => hiera('CONFIG_AMQP_HOST'), - rabbit_port => hiera('CONFIG_AMQP_CLIENTS_PORT'), - rabbit_use_ssl => hiera('CONFIG_AMQP_ENABLE_SSL'), - rabbit_userid => hiera('CONFIG_AMQP_AUTH_USER'), - rabbit_password => hiera('CONFIG_AMQP_AUTH_PASSWORD'), -} +if ($ipa_install == 'y' and + $amqp_enable_ssl and + $amqp_ssl_self_signed == 'y') { + + $kombu_ssl_ca_certs = '/etc/ipa/ca.crt' + $kombu_ssl_keyfile = '/etc/pki/tls/private/ssl_amqp_glance.key' + $kombu_ssl_certfile = '/etc/pki/tls/certs/ssl_amqp_glance.crt' + + $files_to_set_owner = [ $kombu_ssl_keyfile, $kombu_ssl_certfile ] + file { $files_to_set_owner: + owner => 'glance', + group => 'glance', + require => Class['glance::notify::rabbitmq'], + notify => Service['glance-api'], + } + + class { 'glance::notify::rabbitmq': + rabbit_host => hiera('CONFIG_AMQP_HOST'), + rabbit_port => hiera('CONFIG_AMQP_CLIENTS_PORT'), + rabbit_use_ssl => $amqp_enable_ssl, + rabbit_userid => hiera('CONFIG_AMQP_AUTH_USER'), + rabbit_password => hiera('CONFIG_AMQP_AUTH_PASSWORD'), + kombu_ssl_ca_certs => $kombu_ssl_ca_certs, + kombu_ssl_keyfile => $kombu_ssl_keyfile, + kombu_ssl_certfile => $kombu_ssl_certfile, + } +} else { + + class { 'glance::notify::rabbitmq': + rabbit_host => hiera('CONFIG_AMQP_HOST'), + rabbit_port => hiera('CONFIG_AMQP_CLIENTS_PORT'), + rabbit_use_ssl => $amqp_enable_ssl, + rabbit_userid => hiera('CONFIG_AMQP_AUTH_USER'), + rabbit_password => hiera('CONFIG_AMQP_AUTH_PASSWORD'), + } + +} diff --git a/packstack/puppet/templates/heat_rabbitmq.pp b/packstack/puppet/templates/heat_rabbitmq.pp index 9d383a0ac..dad303979 100644 --- a/packstack/puppet/templates/heat_rabbitmq.pp +++ b/packstack/puppet/templates/heat_rabbitmq.pp @@ -2,16 +2,57 @@ $heat_rabbitmq_cfg_heat_db_pw = hiera('CONFIG_HEAT_DB_PW') $heat_rabbitmq_cfg_mariadb_host = hiera('CONFIG_MARIADB_HOST') -class { 'heat': - keystone_host => $heat_rabbitmq_cfg_ctrl_host, - keystone_password => hiera('CONFIG_HEAT_KS_PW'), - auth_uri => "http://${heat_rabbitmq_cfg_ctrl_host}:35357/v2.0", - keystone_ec2_uri => "http://${heat_rabbitmq_cfg_ctrl_host}:35357/v2.0", - rpc_backend => 'heat.openstack.common.rpc.impl_kombu', - rabbit_host => hiera('CONFIG_AMQP_HOST'), - rabbit_userid => hiera('CONFIG_AMQP_AUTH_USER'), - rabbit_password => hiera('CONFIG_AMQP_AUTH_PASSWORD'), - verbose => true, - debug => hiera('CONFIG_DEBUG_MODE'), - database_connection => "mysql://heat:${heat_rabbitmq_cfg_heat_db_pw}@${heat_rabbitmq_cfg_mariadb_host}/heat", +$ipa_install = hiera('CONFIG_IPA_INSTALL') +$amqp_enable_ssl = hiera('CONFIG_AMQP_ENABLE_SSL') +$amqp_ssl_self_signed = hiera('CONFIG_AMQP_SSL_SELF_SIGNED','n') + +if ($ipa_install == 'y' and + $amqp_enable_ssl and + $amqp_ssl_self_signed == 'y') { + $kombu_ssl_ca_certs = '/etc/ipa/ca.crt' + $kombu_ssl_keyfile = '/etc/pki/tls/private/ssl_amqp_heat.key' + $kombu_ssl_certfile = '/etc/pki/tls/certs/ssl_amqp_heat.crt' + + $files_to_set_owner = [ $kombu_ssl_keyfile, $kombu_ssl_certfile ] + file { $files_to_set_owner: + owner => 'heat', + group => 'heat', + require => Package['openstack-heat-common'], + } + File[$files_to_set_owner] ~> Service<||> + + class { 'heat': + keystone_host => $heat_rabbitmq_cfg_ctrl_host, + keystone_password => hiera('CONFIG_HEAT_KS_PW'), + auth_uri => "http://${heat_rabbitmq_cfg_ctrl_host}:35357/v2.0", + keystone_ec2_uri => "http://${heat_rabbitmq_cfg_ctrl_host}:35357/v2.0", + rpc_backend => 'heat.openstack.common.rpc.impl_kombu', + rabbit_host => hiera('CONFIG_AMQP_HOST'), + rabbit_port => hiera('CONFIG_AMQP_CLIENTS_PORT'), + rabbit_use_ssl => $amqp_enable_ssl, + rabbit_userid => hiera('CONFIG_AMQP_AUTH_USER'), + rabbit_password => hiera('CONFIG_AMQP_AUTH_PASSWORD'), + verbose => true, + debug => hiera('CONFIG_DEBUG_MODE'), + database_connection => "mysql://heat:${heat_rabbitmq_cfg_heat_db_pw}@${heat_rabbitmq_cfg_mariadb_host}/heat", + kombu_ssl_ca_certs => $kombu_ssl_ca_certs, + kombu_ssl_keyfile => $kombu_ssl_keyfile, + kombu_ssl_certfile => $kombu_ssl_certfile, + } +} else { + class { 'heat': + keystone_host => $heat_rabbitmq_cfg_ctrl_host, + keystone_password => hiera('CONFIG_HEAT_KS_PW'), + auth_uri => "http://${heat_rabbitmq_cfg_ctrl_host}:35357/v2.0", + keystone_ec2_uri => "http://${heat_rabbitmq_cfg_ctrl_host}:35357/v2.0", + rpc_backend => 'heat.openstack.common.rpc.impl_kombu', + rabbit_host => hiera('CONFIG_AMQP_HOST'), + rabbit_port => hiera('CONFIG_AMQP_CLIENTS_PORT'), + rabbit_use_ssl => $amqp_enable_ssl, + rabbit_userid => hiera('CONFIG_AMQP_AUTH_USER'), + rabbit_password => hiera('CONFIG_AMQP_AUTH_PASSWORD'), + verbose => true, + debug => hiera('CONFIG_DEBUG_MODE'), + database_connection => "mysql://heat:${heat_rabbitmq_cfg_heat_db_pw}@${heat_rabbitmq_cfg_mariadb_host}/heat", + } } diff --git a/packstack/puppet/templates/horizon.pp b/packstack/puppet/templates/horizon.pp index dffe895b7..a925dad6b 100644 --- a/packstack/puppet/templates/horizon.pp +++ b/packstack/puppet/templates/horizon.pp @@ -14,6 +14,69 @@ false => 'False', } +$controller_host = hiera('CONFIG_CONTROLLER_HOST') +$ipa_install = hiera('CONFIG_IPA_INSTALL') +$ipa_host = hiera('CONFIG_IPA_HOST',undef) + +$is_horizon_ssl = hiera('CONFIG_HORIZON_SSL') + +if $is_horizon_ssl == true { + $horizon_cert = '/etc/pki/tls/certs/ssl_ps_server.crt' + $horizon_key = '/etc/pki/tls/private/ssl_ps_server.key' + + if $ipa_install { + $horizon_ca = '/etc/ipa/ca.crt' + } else { + $horizon_ca = '/etc/pki/tls/certs/ssl_ps_chain.crt' + + file {'/etc/pki/tls/certs/ps_generate_ssl_certs.ssh': + ensure => present, + content => template('packstack/ssl/generate_ssl_certs.sh.erb'), + mode => '0755', + } + + exec {'/etc/pki/tls/certs/ps_generate_ssl_certs.ssh': + require => File['/etc/pki/tls/certs/ps_generate_ssl_certs.ssh'], + notify => Service['httpd'], + before => Class['horizon'], + } -> + exec { 'nova-novncproxy-restart': + # TODO: FIXME: this definetly does not belong to horizon.pp + # ps_generate_ssl_certs.ssh is generating ssl certs for nova-novncproxy + # so openstack-nova-novncproxy should be restarted. + path => ['/sbin', '/usr/sbin', '/bin', '/usr/bin'], + command => 'systemctl restart openstack-nova-novncproxy.service', + logoutput => 'on_failure', + } + } + + $files_to_set_owner = [ $horizon_cert, $horizon_key ] + file { $files_to_set_owner: + owner => 'apache', + group => 'apache', + require => Package['httpd'], + notify => Service['httpd'], + } + + apache::listen { '443': } + +} + +if ($ipa_install and ($ipa_host == $controller_host)) { + $configure_apache = false + $conf_template = '/etc/httpd/conf/httpd.conf' +} else { + $configure_apache = true + $conf_template = undef +} + +class{ 'apache': + purge_configs => false, + default_mods => true, + default_confd_files => true, + conf_template => $conf_template, +} + class {'horizon': secret_key => hiera('CONFIG_HORIZON_SECRET_KEY'), keystone_url => "http://${keystone_host}:5000/v2.0", @@ -25,47 +88,15 @@ django_debug => $is_django_debug, file_upload_temp_dir => '/var/tmp', listen_ssl => hiera('CONFIG_HORIZON_SSL'), - horizon_cert => '/etc/pki/tls/certs/ssl_ps_server.crt', - horizon_key => '/etc/pki/tls/private/ssl_ps_server.key', - horizon_ca => '/etc/pki/tls/certs/ssl_ps_chain.crt', + horizon_cert => $horizon_cert, + horizon_key => $horizon_key, + horizon_ca => $horizon_ca, neutron_options => { 'enable_lb' => hiera('CONFIG_HORIZON_NEUTRON_LB'), 'enable_firewall' => hiera('CONFIG_HORIZON_NEUTRON_FW'), }, -} - -$is_horizon_ssl = hiera('CONFIG_HORIZON_SSL') - -if $is_horizon_ssl == true { - file {'/etc/pki/tls/certs/ps_generate_ssl_certs.ssh': - ensure => present, - content => template('packstack/ssl/generate_ssl_certs.sh.erb'), - mode => '0755', - } - - exec {'/etc/pki/tls/certs/ps_generate_ssl_certs.ssh': - require => File['/etc/pki/tls/certs/ps_generate_ssl_certs.ssh'], - notify => Service['httpd'], - before => Class['horizon'], - } -> - exec { 'nova-novncproxy-restart': - # ps_generate_ssl_certs.ssh is generating ssl certs for nova-novncproxy - # so openstack-nova-novncproxy should be restarted. - path => ['/sbin', '/usr/sbin', '/bin', '/usr/bin'], - command => 'systemctl restart openstack-nova-novncproxy.service', - logoutput => 'on_failure', - } - - apache::listen { '443': } - - # little bit of hatred as we'll have to patch upstream puppet-horizon - file_line {'horizon_ssl_wsgi_fix': - path => '/etc/httpd/conf.d/15-horizon_ssl_vhost.conf', - match => 'WSGIProcessGroup.*', - line => ' WSGIProcessGroup horizon-ssl', - require => File['15-horizon_ssl_vhost.conf'], - notify => Service['httpd'], - } + configure_apache => $configure_apache, + notify => Service['httpd'], } class { 'memcached': } diff --git a/packstack/puppet/templates/ipa_certmonger.pp b/packstack/puppet/templates/ipa_certmonger.pp new file mode 100644 index 000000000..d79ad2706 --- /dev/null +++ b/packstack/puppet/templates/ipa_certmonger.pp @@ -0,0 +1 @@ +include certmonger::server diff --git a/packstack/puppet/templates/ipa_server.pp b/packstack/puppet/templates/ipa_server.pp new file mode 100644 index 000000000..f3bca1939 --- /dev/null +++ b/packstack/puppet/templates/ipa_server.pp @@ -0,0 +1,19 @@ +file_line { 'hosts-record': + path => '/etc/hosts', + match => "${ipa_server_ip} ${::fqdn} ${::hostname}.*", + line => "${ipa_server_ip} ${::fqdn} ${::hostname}", + before => Class['ipa'], +} + +class { 'ipa': + master => true, + domain => 'packstack', + realm => 'PACKSTACK', + dspw => hiera('CONFIG_IPA_DM_PASSWORD'), + adminpw => hiera('CONFIG_IPA_ADMIN_PASSWORD'), + svrpkg => $::operatingsystem ? { + 'Fedora' => 'freeipa-server', + default => 'ipa-server', + }, + dns => true, +} diff --git a/packstack/puppet/templates/keystone.pp b/packstack/puppet/templates/keystone.pp index f9d932ec2..edfe02b4d 100644 --- a/packstack/puppet/templates/keystone.pp +++ b/packstack/puppet/templates/keystone.pp @@ -7,6 +7,17 @@ $keystone_api_version_str = hiera('CONFIG_KEYSTONE_API_VERSION') $keystone_url = "http://${keystone_endpoint_cfg_ctrl_host}:5000/${keystone_api_version_str}" $keystone_admin_url = "http://${keystone_endpoint_cfg_ctrl_host}:35357/${keystone_api_version_str}" +$controller_host = hiera('CONFIG_CONTROLLER_HOST') +$ipa_install = hiera('CONFIG_IPA_INSTALL') +$ipa_host = hiera('CONFIG_IPA_HOST',undef) + +if ($ipa_install and ($ipa_host == $controller_host)) { + $configure_apache = false + $conf_template = '/etc/httpd/conf/httpd.conf' +} else { + $configure_apache = true + $conf_template = undef +} class { 'keystone': admin_token => hiera('CONFIG_KEYSTONE_ADMIN_TOKEN'), @@ -21,8 +32,19 @@ if $keystone_service_name == 'httpd' { include packstack::apache_common - class { 'keystone::wsgi::apache': - ssl => $keystone_use_ssl, + class{ 'apache': + purge_configs => false, + default_mods => true, + default_confd_files => true, + conf_template => $conf_template, + } + + if $configure_apache { + class { 'keystone::wsgi::apache': + ssl => $keystone_use_ssl, + } + } else { + info ("TODO: FIXME: BROOOOKEEEEEN") } } diff --git a/packstack/puppet/templates/keystone_swift.pp b/packstack/puppet/templates/keystone_swift.pp index f07db840c..406c1b70e 100644 --- a/packstack/puppet/templates/keystone_swift.pp +++ b/packstack/puppet/templates/keystone_swift.pp @@ -2,4 +2,5 @@ public_address => hiera('CONFIG_CONTROLLER_HOST'), region => hiera('CONFIG_KEYSTONE_REGION'), password => hiera('CONFIG_SWIFT_KS_PW'), + port => hiera('CONFIG_SWIFT_PROXY_PORT'), } diff --git a/packstack/puppet/templates/nagios_server.pp b/packstack/puppet/templates/nagios_server.pp index c9c39e342..6c55085fd 100644 --- a/packstack/puppet/templates/nagios_server.pp +++ b/packstack/puppet/templates/nagios_server.pp @@ -13,6 +13,13 @@ before => Class['nagios_configs'] } +class{ 'apache': + purge_configs => false, + default_mods => true, + default_confd_files => true, + conf_template => '/etc/httpd/conf/httpd.conf', +} + class nagios_configs(){ file { ['/etc/nagios/nagios_command.cfg', '/etc/nagios/nagios_host.cfg']: ensure => 'present', @@ -75,10 +82,6 @@ include concat::setup -class { 'apache': - purge_configs => false, -} - class { 'apache::mod::php': } service { ['nagios']: diff --git a/packstack/puppet/templates/neutron_rabbitmq.pp b/packstack/puppet/templates/neutron_rabbitmq.pp index b4f62f39e..4beb7d385 100644 --- a/packstack/puppet/templates/neutron_rabbitmq.pp +++ b/packstack/puppet/templates/neutron_rabbitmq.pp @@ -1,12 +1,49 @@ +$ipa_install = hiera('CONFIG_IPA_INSTALL') +$amqp_enable_ssl = hiera('CONFIG_AMQP_ENABLE_SSL') +$amqp_ssl_self_signed = hiera('CONFIG_AMQP_SSL_SELF_SIGNED','n') -class { 'neutron': - rabbit_host => hiera('CONFIG_AMQP_HOST'), - rabbit_port => hiera('CONFIG_AMQP_CLIENTS_PORT'), - rabbit_user => hiera('CONFIG_AMQP_AUTH_USER'), - rabbit_password => hiera('CONFIG_AMQP_AUTH_PASSWORD'), - core_plugin => hiera('CONFIG_NEUTRON_CORE_PLUGIN'), - allow_overlapping_ips => true, - service_plugins => hiera_array('SERVICE_PLUGINS'), - verbose => true, - debug => hiera('CONFIG_DEBUG_MODE'), +if ($ipa_install == 'y' and + $amqp_enable_ssl and + $amqp_ssl_self_signed == 'y') { + $kombu_ssl_ca_certs = '/etc/ipa/ca.crt' + $kombu_ssl_keyfile = '/etc/pki/tls/private/ssl_amqp_neutron.key' + $kombu_ssl_certfile = '/etc/pki/tls/certs/ssl_amqp_neutron.crt' + + $files_to_set_owner = [ $kombu_ssl_keyfile, $kombu_ssl_certfile ] + file { $files_to_set_owner: + owner => 'neutron', + group => 'neutron', + require => Class['neutron'], + } + + File[$files_to_set_owner] ~> Service <||> + + class { 'neutron': + rabbit_host => hiera('CONFIG_AMQP_HOST'), + rabbit_port => hiera('CONFIG_AMQP_CLIENTS_PORT'), + rabbit_use_ssl => $amqp_enable_ssl, + rabbit_user => hiera('CONFIG_AMQP_AUTH_USER'), + rabbit_password => hiera('CONFIG_AMQP_AUTH_PASSWORD'), + core_plugin => hiera('CONFIG_NEUTRON_CORE_PLUGIN'), + allow_overlapping_ips => true, + service_plugins => hiera_array('SERVICE_PLUGINS'), + verbose => true, + debug => hiera('CONFIG_DEBUG_MODE'), + kombu_ssl_ca_certs => $kombu_ssl_ca_certs, + kombu_ssl_keyfile => $kombu_ssl_keyfile, + kombu_ssl_certfile => $kombu_ssl_certfile, + } +} else { + class { 'neutron': + rabbit_host => hiera('CONFIG_AMQP_HOST'), + rabbit_port => hiera('CONFIG_AMQP_CLIENTS_PORT'), + rabbit_use_ssl => $amqp_enable_ssl, + rabbit_user => hiera('CONFIG_AMQP_AUTH_USER'), + rabbit_password => hiera('CONFIG_AMQP_AUTH_PASSWORD'), + core_plugin => hiera('CONFIG_NEUTRON_CORE_PLUGIN'), + allow_overlapping_ips => true, + service_plugins => hiera_array('SERVICE_PLUGINS'), + verbose => true, + debug => hiera('CONFIG_DEBUG_MODE'), + } } diff --git a/packstack/puppet/templates/nova_common_rabbitmq.pp b/packstack/puppet/templates/nova_common_rabbitmq.pp index 38cf67596..a8d986c09 100644 --- a/packstack/puppet/templates/nova_common_rabbitmq.pp +++ b/packstack/puppet/templates/nova_common_rabbitmq.pp @@ -9,15 +9,52 @@ } $nova_common_rabbitmq_cfg_storage_host = hiera('CONFIG_STORAGE_HOST') +$ipa_install = hiera('CONFIG_IPA_INSTALL') +$amqp_enable_ssl = hiera('CONFIG_AMQP_ENABLE_SSL') +$amqp_ssl_self_signed = hiera('CONFIG_AMQP_SSL_SELF_SIGNED','n') -class { 'nova': - glance_api_servers => "${nova_common_rabbitmq_cfg_storage_host}:9292", - rabbit_host => hiera('CONFIG_AMQP_HOST'), - rabbit_port => hiera('CONFIG_AMQP_CLIENTS_PORT'), - rabbit_userid => hiera('CONFIG_AMQP_AUTH_USER'), - rabbit_password => hiera('CONFIG_AMQP_AUTH_PASSWORD'), - verbose => true, - debug => hiera('CONFIG_DEBUG_MODE'), - nova_public_key => $public_key, - nova_private_key => $private_key, +if ($ipa_install == 'y' and + $amqp_enable_ssl and + $amqp_ssl_self_signed == 'y') { + $kombu_ssl_ca_certs = '/etc/ipa/ca.crt' + $kombu_ssl_keyfile = '/etc/pki/tls/private/ssl_amqp_nova.key' + $kombu_ssl_certfile = '/etc/pki/tls/certs/ssl_amqp_nova.crt' + + $files_to_set_owner = [ $kombu_ssl_keyfile, $kombu_ssl_certfile ] + file { $files_to_set_owner: + owner => 'nova', + group => 'nova', + require => Package['nova-common'], + } + + File[$files_to_set_owner] ~> Service <||> + + class { 'nova': + glance_api_servers => "${nova_common_rabbitmq_cfg_storage_host}:9292", + rabbit_host => hiera('CONFIG_AMQP_HOST'), + rabbit_port => hiera('CONFIG_AMQP_CLIENTS_PORT'), + rabbit_userid => hiera('CONFIG_AMQP_AUTH_USER'), + rabbit_password => hiera('CONFIG_AMQP_AUTH_PASSWORD'), + verbose => true, + debug => hiera('CONFIG_DEBUG_MODE'), + nova_public_key => $public_key, + nova_private_key => $private_key, + rabbit_use_ssl => $amqp_enable_ssl, + kombu_ssl_ca_certs => $kombu_ssl_ca_certs, + kombu_ssl_keyfile => $kombu_ssl_keyfile, + kombu_ssl_certfile => $kombu_ssl_certfile, + } +} else { + class { 'nova': + glance_api_servers => "${nova_common_rabbitmq_cfg_storage_host}:9292", + rabbit_host => hiera('CONFIG_AMQP_HOST'), + rabbit_port => hiera('CONFIG_AMQP_CLIENTS_PORT'), + rabbit_use_ssl => $amqp_enable_ssl, + rabbit_userid => hiera('CONFIG_AMQP_AUTH_USER'), + rabbit_password => hiera('CONFIG_AMQP_AUTH_PASSWORD'), + verbose => true, + debug => hiera('CONFIG_DEBUG_MODE'), + nova_public_key => $public_key, + nova_private_key => $private_key, + } } diff --git a/packstack/puppet/templates/prescript.pp b/packstack/puppet/templates/prescript.pp index 33dcf7852..e03c30b09 100644 --- a/packstack/puppet/templates/prescript.pp +++ b/packstack/puppet/templates/prescript.pp @@ -1,9 +1,5 @@ include firewall -if $::ipaddress == hiera('CONFIG_CONTROLLER_HOST') { - include ::apache -} - # We don't have openstack-selinux package for Fedora if $::operatingsystem != 'Fedora' { package{ 'openstack-selinux': diff --git a/packstack/puppet/templates/swift_proxy.pp b/packstack/puppet/templates/swift_proxy.pp index 4b3b7b4bf..f1a453639 100644 --- a/packstack/puppet/templates/swift_proxy.pp +++ b/packstack/puppet/templates/swift_proxy.pp @@ -5,6 +5,7 @@ class { 'swift::proxy': proxy_local_net_ip => hiera('CONFIG_CONTROLLER_HOST'), + port => hiera('CONFIG_SWIFT_PROXY_PORT'), pipeline => [ 'catch_errors', 'bulk',