diff --git a/novajoin_tempest_plugin/tests/scenario/novajoin_manager.py b/novajoin_tempest_plugin/tests/scenario/novajoin_manager.py index e3b8113..987e0a4 100644 --- a/novajoin_tempest_plugin/tests/scenario/novajoin_manager.py +++ b/novajoin_tempest_plugin/tests/scenario/novajoin_manager.py @@ -138,12 +138,8 @@ class NovajoinScenarioTest(manager.ScenarioTest): self.assertTrue(all(x in result for x in params)) def verify_overcloud_host_is_ipaclient(self, hostip, user): - keypair = '/home/stack/.ssh/id_rsa' - cmd = ['ssh', '-i', keypair, - '{user}@{hostip}'.format(user=user, hostip=hostip), - '-C', 'id admin'] - - result = subprocess.check_output(cmd) + cmd = 'id admin' + result = self.execute_on_controller(user, hostip, cmd) params = ['uid', 'gid', 'groups'] self.assertTrue(all(x in result for x in params)) @@ -155,12 +151,8 @@ class NovajoinScenarioTest(manager.ScenarioTest): self.assertTrue('track: yes' in result) def verify_overcloud_cert_tracked(self, hostip, user, cert_id): - keypair = '/home/stack/.ssh/id_rsa' - cmd = ['ssh', '-i', keypair, - '{user}@{hostip}'.format(user=user, hostip=hostip), - '-C', 'sudo getcert list -i {certid}'.format(certid=cert_id)] - - result = subprocess.check_output(cmd) + cmd = 'sudo getcert list -i {certid}'.format(certid=cert_id) + result = self.execute_on_controller(user, hostip, cmd) self.assertTrue('track: yes' in result) def verify_cert_revoked(self, serial): @@ -199,3 +191,37 @@ class NovajoinScenarioTest(manager.ScenarioTest): service = principal.split('/', 1)[0] host = principal.split('/', 1)[1] self.verify_service(service, host, verify_certs) + + def verify_overcloud_tls_connection(self, controller_ip, user, hostport): + """ Check TLS connection. Failure will raise an exception""" + cmd = ('echo \'GET / HTTP/1.0\r\n\' | openssl s_client -quiet ' + '-connect {hostport} -tls1_2'.format(hostport=hostport)) + self.execute_on_controller(user, controller_ip, cmd) + + def get_server_id(self, name): + params = {'all_tenants': '', 'name': name} + resp = self.servers_client.list_servers(detail=True, **params) + print(resp) + links = resp['servers'][0]['links'] + for link in links: + if link['rel'] == 'self': + href = link['href'] + return href.split('/')[-1] + return None + + def get_rabbitmq_host(self, user, controller_ip): + cmd = 'sudo hiera -c /etc/puppet/hiera.yaml rabbitmq::ssl_interface' + return self.execute_on_controller(user, controller_ip, cmd) + + def get_rabbitmq_port(self, user, controller_ip): + cmd = 'sudo hiera -c /etc/puppet/hiera.yaml rabbitmq::ssl_port' + return self.execute_on_controller(user, controller_ip, cmd) + + def execute_on_controller(self, user, hostip, target_cmd): + keypair = '/home/stack/.ssh/id_rsa' + cmd = ['ssh', '-i', keypair, + '{user}@{hostip}'.format(user=user, hostip=hostip), + '-C', target_cmd] + return subprocess.check_output(cmd) + + diff --git a/novajoin_tempest_plugin/tests/scenario/test_tripleo_deployment.py b/novajoin_tempest_plugin/tests/scenario/test_tripleo_deployment.py index c96cf37..d565b05 100644 --- a/novajoin_tempest_plugin/tests/scenario/test_tripleo_deployment.py +++ b/novajoin_tempest_plugin/tests/scenario/test_tripleo_deployment.py @@ -61,18 +61,6 @@ class TripleOTest(novajoin_manager.NovajoinScenarioTest): if not CONF.novajoin.tripleo: raise cls.skipException('Tripleo configuration is not enabled') - def _get_server_id(self, name): - # params = {'name': name} - params = {'all_tenants': '', 'name': name} - resp = self.servers_client.list_servers(detail=True, **params) - print(resp) - links = resp['servers'][0]['links'] - for link in links: - if link['rel'] == 'self': - href = link['href'] - return href.split('/')[-1] - return None - def test_hosts_are_registered(self): hosts = list(CONF.novajoin.tripleo_controllers) hosts.append(CONF.novajoin.tripleo_undercloud) @@ -83,7 +71,7 @@ class TripleOTest(novajoin_manager.NovajoinScenarioTest): def test_verify_compact_services_created(self): for host in CONF.novajoin.tripleo_controllers: metadata = self.servers_client.list_server_metadata( - self._get_server_id(host))['metadata'] + self.get_server_id(host))['metadata'] services = metadata['compact_services'] compact_services = ast.literal_eval(services) print(compact_services) @@ -96,7 +84,7 @@ class TripleOTest(novajoin_manager.NovajoinScenarioTest): def test_verify_controller_managed_services(self): for host in CONF.novajoin.tripleo_controllers: metadata = self.servers_client.list_server_metadata( - self._get_server_id(host))['metadata'] + self.get_server_id(host))['metadata'] managed_services = [metadata[key] for key in metadata.keys() if key.startswith('managed_service_')] print(managed_services) @@ -106,7 +94,7 @@ class TripleOTest(novajoin_manager.NovajoinScenarioTest): def test_verify_service_certs_are_tracked(self): for host in CONF.novajoin.tripleo_controllers: - server_id = self._get_server_id(host) + server_id = self.get_server_id(host) server = self.servers_client.show_server(server_id)['server'] server_ip = self.get_server_ip(server) @@ -119,7 +107,7 @@ class TripleOTest(novajoin_manager.NovajoinScenarioTest): def test_overcloud_is_ipaclient(self): for host in CONF.novajoin.tripleo_controllers: - server_id = self._get_server_id(host) + server_id = self.get_server_id(host) server = self.servers_client.show_server(server_id)['server'] server_ip = self.get_server_ip(server) self.verify_overcloud_host_is_ipaclient( diff --git a/novajoin_tempest_plugin/tests/scenario/test_tripleo_tls.py b/novajoin_tempest_plugin/tests/scenario/test_tripleo_tls.py new file mode 100644 index 0000000..9e218b4 --- /dev/null +++ b/novajoin_tempest_plugin/tests/scenario/test_tripleo_tls.py @@ -0,0 +1,117 @@ +# Copyright (c) 2017 Red Hat +# +# 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. +import re + +from novajoin_tempest_plugin.tests.scenario import novajoin_manager +from oslo_log import log as logging +from tempest import config + +CONF = config.CONF +LOG = logging.getLogger(__name__) + + +class TripleOTLSTest(novajoin_manager.NovajoinScenarioTest): + + """The test suite for tripleO configuration + + Novajoin is currently deployed in tripleO as part of the + undercloud as part of a tripleO deployment. + + This test is to validate that all the nodes and services + for an HA deployment have been correctly created. + + This means: + * Validating that the undercloud is enrolled in IPA + * Validating that the controller is enrolled in IPA + * Validating that the compute node is enrolled + * Validating that HA services have been created in IPA + * Validating that certs are being tracked. + * Validate that TLS connections are being established for + all internal services + """ + + @classmethod + def skip_checks(cls): + super(TripleOTLSTest, cls).skip_checks() + if not CONF.novajoin.tripleo: + raise cls.skipException('Tripleo configuration is not enabled') + + def get_haproxy_cfg(self, hostip): + print(hostip) + return "/home/stack/haproxy.cfg" + + def parse_haproxy_cfg(self, haproxy_file): + with open(haproxy_file) as f: + content = f.readlines() + content = [x.strip() for x in content] + + params = [] + services = {} + service_tag = None + for x in content: + if x.startswith('listen'): + service_tag = re.search('listen (.*)', x).group(1) + params = [] + if service_tag is not None: + if x.startswith('bind'): + params.append(x) + if x.startswith('server'): + params.append(x) + services[service_tag] = params + return services + + def test_haproxy_tls_connections(self): + for controller in CONF.novajoin.tripleo_controllers: + controller_id = self.get_server_id(controller) + controller_data = self.servers_client.show_server( + controller_id)['server'] + controller_ip = self.get_server_ip(controller_data) + + haproxy_file = self.get_haproxy_cfg(controller_ip) + services = self.parse_haproxy_cfg(haproxy_file) + + for tag, params in services.items(): + # TODO(alee) make sure tag/param is not on an exception list + # if so continue + + print("*** Testing {service}".format(service=tag)) + for param in params: + print(param) + self.assertTrue("ssl" in param) + hostport = self.get_hostport(param) + self.verify_overcloud_tls_conn( + controller_ip=controller_ip, + user='heat-admin', + hostport=hostport) + + def get_hostport(self, param): + if param.startswith("bind"): + return re.search('bind (\S*) .*', param).group(1) + if param.startswith('server'): + return re.search('server (\S*) (\S*) .*', param).group(2) + + def test_rabbitmq_tls_connection(self): + for controller in CONF.novajoin.tripleo_controllers: + controller_id = self.get_server_id(controller) + controller_data = self.servers_client.show_server( + controller_id)['server'] + controller_ip = self.get_server_ip(controller_data) + rabbitmq_host = self.get_rabbitmq_host(controller_ip, 'heat-admin') + rabbitmq_port = self.get_rabbitmq_port(controller_ip, 'heat-admin') + self.verify_overcloud_tls_conn( + controller_ip=controller_ip, + user='heat-admin', + hostport="{host}:{port}".format(host=rabbitmq_host, + port=rabbitmq_port) + )