From 3346b9116ac1ae247f6afc9ee6c87aaad8770c0a Mon Sep 17 00:00:00 2001 From: Mikhail Samoylov Date: Mon, 14 Mar 2016 17:40:17 +0300 Subject: [PATCH] This test automate SSL checks. First test automate following test case: Check MOS services are NOT running ssl on public endpoints when TLS is disabled. Second test automate following test case: Check cluster creation with SSL is enabled only on Master node. Also test fixed typo in comment in test_cli.py Related bug: 1544542 Change-Id: I506c0a3763c208e04011e6f75577812d2a959f04 --- doc/base_tests.rst | 5 ++ fuelweb_test/helpers/decorators.py | 10 ++- fuelweb_test/helpers/os_actions.py | 4 ++ fuelweb_test/models/environment.py | 26 +++++++- fuelweb_test/models/nailgun_client.py | 9 ++- fuelweb_test/settings.py | 1 + fuelweb_test/tests/test_cli.py | 2 +- fuelweb_test/tests/test_ssl.py | 93 +++++++++++++++++++++++++++ 8 files changed, 143 insertions(+), 7 deletions(-) create mode 100644 fuelweb_test/tests/test_ssl.py diff --git a/doc/base_tests.rst b/doc/base_tests.rst index fb35808c8..6b9475bed 100644 --- a/doc/base_tests.rst +++ b/doc/base_tests.rst @@ -670,3 +670,8 @@ Deployment with platform components Template based tests -------------------- .. automodule:: fuelweb_test.actions_tests + +Test for ssl components +----------------------- +.. automodule:: fuelweb_test.tests.test_ssl + :members: \ No newline at end of file diff --git a/fuelweb_test/helpers/decorators.py b/fuelweb_test/helpers/decorators.py index 37f8961f8..4cd480395 100644 --- a/fuelweb_test/helpers/decorators.py +++ b/fuelweb_test/helpers/decorators.py @@ -51,7 +51,7 @@ def save_logs(url, path, auth_token=None, chunk_size=1024): if auth_token is not None: headers['X-Auth-Token'] = auth_token - stream = requests.get(url, headers=headers, stream=True) + stream = requests.get(url, headers=headers, stream=True, verify=False) if stream.status_code != 200: logger.error("%s %s: %s", stream.status_code, stream.reason, stream.content) @@ -315,7 +315,13 @@ def create_diagnostic_snapshot(env, status, name=""): task = env.fuel_web.task_wait(env.fuel_web.client.generate_logs(), 60 * 10) assert_true(task['status'] == 'ready', "Generation of diagnostic snapshot failed: {}".format(task)) - url = "http://{}:8000{}".format(env.get_admin_node_ip(), task['message']) + if settings.FORCE_HTTPS_MASTER_NODE: + url = "https://{}:8443{}".format(env.get_admin_node_ip(), + task['message']) + else: + url = "http://{}:8000{}".format(env.get_admin_node_ip(), + task['message']) + log_file_name = '{status}_{name}-{basename}'.format( status=status, name=name, diff --git a/fuelweb_test/helpers/os_actions.py b/fuelweb_test/helpers/os_actions.py index 8238d3138..7fe6126e6 100644 --- a/fuelweb_test/helpers/os_actions.py +++ b/fuelweb_test/helpers/os_actions.py @@ -621,3 +621,7 @@ class OpenStackActions(common.Common): } } return self.neutron.create_router(router_info)['router'] + + def get_keystone_endpoints(self): + endpoints = self.keystone.endpoints.list() + return endpoints diff --git a/fuelweb_test/models/environment.py b/fuelweb_test/models/environment.py index 74200516a..cb6c485ce 100644 --- a/fuelweb_test/models/environment.py +++ b/fuelweb_test/models/environment.py @@ -444,7 +444,8 @@ class EnvironmentModel(object): def setup_environment(self, custom=settings.CUSTOM_ENV, build_images=settings.BUILD_IMAGES, iso_connect_as=settings.ADMIN_BOOT_DEVICE, - security=settings.SECURITY_TEST): + security=settings.SECURITY_TEST, + force_ssl=settings.FORCE_HTTPS_MASTER_NODE): # Create environment and start the Fuel master node admin = self.d_env.nodes().admin self.d_env.start([admin]) @@ -565,6 +566,29 @@ class EnvironmentModel(object): ) logger.debug('Offloading settings:\n{0}\n'.format( ''.join(result['stdout']))) + if force_ssl: + self.enable_force_https(self.ssh_manager.admin_ip) + + @logwrap + def enable_force_https(self, admin_node_ip): + cmd = """ + echo -e '"SSL":\n "force_https": "true"' >> /etc/fuel/astute.yaml + """ + self.ssh_manager.execute_on_remote(admin_node_ip, cmd) + cmd = "find / -name \"nginx_services.pp\"" + puppet_manifest = \ + self.ssh_manager.execute_on_remote( + admin_node_ip, cmd)['stdout'][0].strip() + cmd = 'puppet apply {0}'.format(puppet_manifest) + self.ssh_manager.execute_on_remote(admin_node_ip, cmd) + cmd = """ + systemctl status nginx.service | + awk 'match($0, /\s+Active:.*\((\w+)\)/, a) {print a[1]}' + """ + wait(lambda: ( + self.ssh_manager.execute_on_remote( + admin_node_ip, cmd)['stdout'][0] != 'dead'), interval=10, + timeout=30) @update_rpm_packages @upload_manifests diff --git a/fuelweb_test/models/nailgun_client.py b/fuelweb_test/models/nailgun_client.py index 147cada79..d6b7d6ecb 100644 --- a/fuelweb_test/models/nailgun_client.py +++ b/fuelweb_test/models/nailgun_client.py @@ -16,6 +16,7 @@ from fuelweb_test import logwrap from fuelweb_test import logger from fuelweb_test.helpers.decorators import json_parse from fuelweb_test.helpers.http import HTTPClient +from fuelweb_test.settings import FORCE_HTTPS_MASTER_NODE from fuelweb_test.settings import KEYSTONE_CREDS from fuelweb_test.settings import OPENSTACK_RELEASE @@ -24,12 +25,14 @@ class NailgunClient(object): """NailgunClient""" # TODO documentation def __init__(self, admin_node_ip, **kwargs): - url = "http://{0}:8000".format(admin_node_ip) + if FORCE_HTTPS_MASTER_NODE: + url = "https://{0}:8443".format(admin_node_ip) + else: + url = "http://{0}:8000".format(admin_node_ip) logger.info('Initiate Nailgun client with url %s', url) self.keystone_url = "http://{0}:5000/v2.0".format(admin_node_ip) self._client = HTTPClient(url=url, keystone_url=self.keystone_url, - credentials=KEYSTONE_CREDS, - **kwargs) + credentials=KEYSTONE_CREDS, **kwargs) super(NailgunClient, self).__init__() def __repr__(self): diff --git a/fuelweb_test/settings.py b/fuelweb_test/settings.py index e3747ea8c..422f343c1 100644 --- a/fuelweb_test/settings.py +++ b/fuelweb_test/settings.py @@ -54,6 +54,7 @@ ADMIN_BOOT_DEVICE = os.environ.get('ADMIN_BOOT_DEVICE', 'cdrom') DNS = os.environ.get('DNS', '8.8.8.8') PUBLIC_TEST_IP = os.environ.get('PUBLIC_TEST_IP', '8.8.8.8') +FORCE_HTTPS_MASTER_NODE = get_var_as_bool('FORCE_HTTPS_MASTER_NODE', False) DISABLE_SSL = get_var_as_bool('DISABLE_SSL', False) VERIFY_SSL = get_var_as_bool('VERIFY_SSL', False) SSL_CN = os.environ.get('SSL_CN', 'public.fuel.local') diff --git a/fuelweb_test/tests/test_cli.py b/fuelweb_test/tests/test_cli.py index 1499ee5a2..85f5bc881 100644 --- a/fuelweb_test/tests/test_cli.py +++ b/fuelweb_test/tests/test_cli.py @@ -227,7 +227,7 @@ class CommandLineTest(test_cli_base.CommandLine): current_ssl_keypair) )) assert_equal(old_ssl_keypair, current_ssl_keypair, - message="SSL keypiars are not equal") + message="SSL keypairs are not equal") # Check floating ranges are equal after cluster deploy actual_floating_ranges = self.hiera_floating_ranges(controller_node) logger.info("Current floating ranges: {0}".format( diff --git a/fuelweb_test/tests/test_ssl.py b/fuelweb_test/tests/test_ssl.py new file mode 100644 index 000000000..d4b4745bd --- /dev/null +++ b/fuelweb_test/tests/test_ssl.py @@ -0,0 +1,93 @@ +import httplib +from urlparse import urlparse + +from proboscis import test +from proboscis.asserts import assert_equal + +from fuelweb_test.helpers.decorators import log_snapshot_after_test +from fuelweb_test.settings import DEPLOYMENT_MODE +from fuelweb_test.tests.base_test_case import SetupEnvironment +from fuelweb_test.tests.base_test_case import TestBasic +from fuelweb_test.helpers.os_actions import OpenStackActions + + +@test(groups=["ssl"]) +class SSL_Tests(TestBasic): + @test(depends_on=[SetupEnvironment.prepare_release], + groups=["master_node_with_https_only"]) + @log_snapshot_after_test + def master_node_with_https_only(self): + """Check cluster creation with SSL is enabled only on Master node + + Scenario: + 1. Revert the snapshot "ready" with forced https + 2. Check that we cannot connect to master node by http(8000 port) + 3. Bootstrap slaves nodes and + check here that they appears in nailgun + + Duration 30m + """ + self.show_step(1) + self.env.revert_snapshot("ready") + admin_ip = self.ssh_manager.admin_ip + self.show_step(2) + connection = httplib.HTTPConnection(admin_ip, 8000) + connection.request("GET", "/") + response = connection.getresponse() + assert_equal(str(response.status), '301', + message="HTTP was not disabled for master node") + self.show_step(3) + self.env.bootstrap_nodes(self.env.d_env.nodes().slaves[:2]) + nodes = self.fuel_web.client.list_nodes() + assert_equal(2, len(nodes)) + self.env.make_snapshot("master_node_with_https_only", is_make=True) + + @test(depends_on=['master_node_with_https_only'], + groups=["endpoints_with_disabled_ssl"]) + @log_snapshot_after_test + def endpoints_with_disabled_ssl(self): + """Check MOS services are NOT running ssl on public endpoints + when TLS is disabled + + Scenario: + 1. Revert snapshot "master_node_with_https_only" + 2. Create a new cluster + 3. Disable TLS for public endpoints + 4. Deploy cluster + 5. Run OSTF + 6. Check that all endpoints link to plain http protocol. + + Duration 30m + """ + self.show_step(1) + self.env.revert_snapshot("master_node_with_https_only") + self.show_step(2) + self.show_step(3) + cluster_id = self.fuel_web.create_cluster( + name=self.__class__.__name__, + configure_ssl=False, + mode=DEPLOYMENT_MODE) + self.fuel_web.update_nodes( + cluster_id, + { + 'slave-01': ['controller'], + 'slave-02': ['compute', 'cinder'], + } + ) + self.show_step(4) + self.fuel_web.deploy_cluster_wait(cluster_id) + self.show_step(5) + # Run OSTF + self.fuel_web.run_ostf(cluster_id=cluster_id, + test_sets=['smoke']) + self.show_step(6) + # Get controller ip address + controller_keystone_ip = self.fuel_web.get_public_vip(cluster_id) + action = OpenStackActions(controller_ip=controller_keystone_ip) + endpoint_list = action.get_keystone_endpoints() + for endpoint in endpoint_list: + url = urlparse(endpoint.publicurl) + assert_equal(url.scheme, "http", + message=( + "Endpoint id {0} uses {1} instead http.".format( + endpoint.id, url.scheme)))