Esempio n. 1
0
    def test_404_connection(self):
        """Verify the apache status module gets disabled when hardening apache.

        Ported from amulet tests.
        """
        logging.info('Checking apache mod_status gets disabled.')

        unit_name = zaza_model.get_lead_unit_name('openstack-dashboard')
        keystone_unit = zaza_model.get_lead_unit_name('keystone')
        dashboard_relation = openstack_juju.get_relation_from_unit(
            keystone_unit, unit_name, 'identity-service')
        dashboard_ip = dashboard_relation['private-address']
        logging.debug("... dashboard_ip is:{}".format(dashboard_ip))

        logging.debug('Maybe enabling hardening for apache...')
        _app_config = zaza_model.get_application_config(self.application_name)
        logging.info(_app_config['harden'])
        with self.config_change(
            {'harden': _app_config['harden'].get('value', '')},
            {'harden': 'apache'}):
            try:
                urllib.request.urlopen(
                    'http://{}/server-status'.format(dashboard_ip))
            except urllib.request.HTTPError as e:
                if e.code == 404:
                    return
        # test failed if it didn't return 404
        msg = "Apache mod_status check failed."
        assert False, msg
Esempio n. 2
0
def _get_dashboard_ip():
    """Get the IP of the dashboard.

    :returns: The IP of the dashboard
    :rtype: str
    """
    unit_name = zaza_model.get_lead_unit_name('openstack-dashboard')
    keystone_unit = zaza_model.get_lead_unit_name('keystone')
    dashboard_relation = openstack_juju.get_relation_from_unit(
        keystone_unit, unit_name, 'identity-service')
    dashboard_ip = dashboard_relation['private-address']
    logging.debug("dashboard_ip is: {}".format(dashboard_ip))
    return dashboard_ip
Esempio n. 3
0
 def test_get_lead_unit_name(self):
     self.patch_object(model, 'get_juju_model', return_value='mname')
     self.patch_object(model, 'get_units')
     self.get_units.return_value = self.units
     self.patch_object(model, 'Model')
     self.Model.return_value = self.Model_mock
     self.assertEqual(model.get_lead_unit_name('app', 'model'), 'app/4')
Esempio n. 4
0
    def get_client_and_attempt_operation(self, ip):
        """Attempt to list users on the openstack-dashboard service.

        This is slightly complicated in that the client is actually a web-site.
        Thus, the test has to login first and then attempt the operation.  This
        makes the test a little more complicated.

        :param ip: the IP address to get the session against.
        :type ip: str
        :raises: PolicydOperationFailedException if operation fails.
        """
        unit = zaza_model.get_unit_from_name(
            zaza_model.get_lead_unit_name(self.application_name))
        logging.info("Dashboard is at {}".format(unit.public_address))
        overcloud_auth = openstack_utils.get_overcloud_auth()
        password = overcloud_auth['OS_PASSWORD'],
        logging.info("admin password is {}".format(password))
        # try to get the url which will either pass or fail with a 403
        overcloud_auth = openstack_utils.get_overcloud_auth()
        domain = 'admin_domain',
        username = '******',
        password = overcloud_auth['OS_PASSWORD'],
        client, response = _login(self.get_horizon_url(), domain, username,
                                  password)
        # now attempt to get the domains page
        _url = self.url.format(unit.public_address)
        result = client.get(_url)
        if result.status_code == 403:
            raise policyd.PolicydOperationFailedException("Not authenticated")
Esempio n. 5
0
    def test_404_connection(self):
        """Verify the apache status module gets disabled when hardening apache.

        Ported from amulet tests.
        """
        logging.info('Checking apache mod_status gets disabled.')

        unit = zaza_model.get_unit_from_name(
            zaza_model.get_lead_unit_name(self.application_name))
        logging.debug("... dashboard_ip is: {}".format(unit.public_address))

        logging.debug('Maybe enabling hardening for apache...')
        _app_config = zaza_model.get_application_config(self.application_name)
        logging.info(_app_config['harden'])

        request = urllib.request.Request('http://{}/server-status'.format(
            unit.public_address))
        with self.config_change(
            {'harden': _app_config['harden'].get('value', '')},
            {'harden': 'apache'}):
            try:
                _do_request(request)
            except urllib.request.HTTPError as e:
                # test failed if it didn't return 404
                msg = "Apache mod_status check failed."
                self.assertEqual(e.code, 404, msg)
        logging.info('OK')
Esempio n. 6
0
    def setUpClass(cls, application_name=None, model_alias=None):
        """Run setup for test class to create common resources."""
        cls.model_aliases = model.get_juju_model_aliases()
        if model_alias:
            cls.model_name = cls.model_aliases[model_alias]
        else:
            cls.model_name = model.get_juju_model()
        cls.test_config = lifecycle_utils.get_charm_config(fatal=False)

        if application_name:
            cls.application_name = application_name
        else:
            charm_under_test_name = cls.test_config['charm_name']
            deployed_app_names = model.sync_deployed(model_name=cls.model_name)
            if charm_under_test_name in deployed_app_names:
                # There is an application named like the charm under test.
                # Let's consider it the application under test:
                cls.application_name = charm_under_test_name
            else:
                # Let's search for any application whose name starts with the
                # name of the charm under test and assume it's the application
                # under test:
                for app_name in deployed_app_names:
                    if app_name.startswith(charm_under_test_name):
                        cls.application_name = app_name
                        break
                else:
                    logging.warning('Could not find application under test')
                    return

        cls.lead_unit = model.get_lead_unit_name(cls.application_name,
                                                 model_name=cls.model_name)
        logging.debug('Leader unit is {}'.format(cls.lead_unit))
Esempio n. 7
0
 def setUpClass(cls):
     """Run setup for test class to create common resourcea."""
     cls.keystone_session = openstack_utils.get_overcloud_keystone_session()
     cls.model_name = model.get_juju_model()
     cls.test_config = lifecycle_utils.get_charm_config()
     cls.application_name = cls.test_config['charm_name']
     cls.lead_unit = model.get_lead_unit_name(cls.application_name,
                                              model_name=cls.model_name)
     logging.debug('Leader unit is {}'.format(cls.lead_unit))
 def setUpClass(cls):
     """Run setup for tests."""
     cls.model_name = model.get_juju_model()
     cls.application_name = "nrpe"
     cls.lead_unit_name = model.get_lead_unit_name(
         cls.application_name, model_name=cls.model_name)
     cls.units = model.get_units(cls.application_name,
                                 model_name=cls.model_name)
     cls.nrpe_ip = model.get_app_ips(cls.application_name)[0]
Esempio n. 9
0
 def setUpClass(cls):
     super(Test, cls).setUpClass()
     cls.model_name = model.get_juju_model()
     cls.application_name = "lldpd"
     cls.lead_unit_name = model.get_lead_unit_name(
         cls.application_name, model_name=cls.model_name)
     cls.units = model.get_units(cls.application_name,
                                 model_name=cls.model_name)
     logging.debug("Leader unit is {}".format(cls.lead_unit_name))
Esempio n. 10
0
    def setUpClass(cls, application_name=None, model_alias=None):
        """Run setup for test class to create common resources.

        Note: the derived class may not use the application_name; if it's set
        to None then this setUpClass() method will attempt to extract the
        application name from the charm_config (essentially the test.yaml)
        using the key 'charm_name' in the test_config.  If that isn't present,
        then there will be no application_name set, and this is considered a
        generic scenario of a whole model rather than a particular charm under
        test.

        :param application_name: the name of the applications that the derived
            class is testing.  If None, then it's a generic test not connected
            to any single charm.
        :type application_name: Optional[str]
        :param model_alias: the alias to use if needed.
        :type model_alias: Optional[str]
        """
        cls.model_aliases = model.get_juju_model_aliases()
        if model_alias:
            cls.model_name = cls.model_aliases[model_alias]
        else:
            cls.model_name = model.get_juju_model()
        cls.test_config = lifecycle_utils.get_charm_config(fatal=False)

        if application_name:
            cls.application_name = application_name
        else:
            try:
                charm_under_test_name = cls.test_config['charm_name']
            except KeyError:
                logging.warning("No application_name and no charm config so "
                                "not setting the application_name. Likely a "
                                "scenario test.")
                return
            deployed_app_names = model.sync_deployed(model_name=cls.model_name)
            if charm_under_test_name in deployed_app_names:
                # There is an application named like the charm under test.
                # Let's consider it the application under test:
                cls.application_name = charm_under_test_name
            else:
                # Let's search for any application whose name starts with the
                # name of the charm under test and assume it's the application
                # under test:
                for app_name in deployed_app_names:
                    if app_name.startswith(charm_under_test_name):
                        cls.application_name = app_name
                        break
                else:
                    logging.warning('Could not find application under test')
                    return

        cls.lead_unit = model.get_lead_unit_name(
            cls.application_name,
            model_name=cls.model_name)
        logging.debug('Leader unit is {}'.format(cls.lead_unit))
Esempio n. 11
0
    def test_501_security_checklist_action(self):
        """Verify expected result on a default install.

        Ported from amulet tests.
        """
        logging.info("Testing security-checklist")
        unit_name = zaza_model.get_lead_unit_name('openstack-dashboard')
        action = zaza_model.run_action(unit_name, 'security-checklist')
        assert action.data.get(u"status") == "failed", \
            "Security check is expected to not pass by default"
Esempio n. 12
0
 def test_prometheus_metrics(self):
     """Validate that Prometheus has Ceph metrics."""
     try:
         zaza_model.get_application('prometheus2')
     except KeyError:
         raise unittest.SkipTest('Prometheus not present, skipping test')
     unit = zaza_model.get_unit_from_name(
         zaza_model.get_lead_unit_name('prometheus2'))
     self.assertEqual('3',
                      _get_mon_count_from_prometheus(unit.public_address))
Esempio n. 13
0
    def test_404_connection(self):
        """Verify the apache status module gets disabled when hardening apache.

        Ported from amulet tests.
        """
        logging.info('Checking apache mod_status gets disabled.')

        unit_name = zaza_model.get_lead_unit_name('openstack-dashboard')
        keystone_unit = zaza_model.get_lead_unit_name('keystone')
        dashboard_relation = openstack_juju.get_relation_from_unit(
            keystone_unit, unit_name, 'identity-service')
        dashboard_ip = dashboard_relation['private-address']
        logging.debug("... dashboard_ip is:{}".format(dashboard_ip))

        logging.debug('Maybe enabling hardening for apache...')
        _app_config = zaza_model.get_application_config(self.application_name)
        logging.info(_app_config['harden'])

        # NOTE(ajkavanagh): it seems that apache2 doesn't start quickly enough
        # for the test, and so it gets reset errors; repeat until either that
        # stops or there is a failure
        @tenacity.retry(wait=tenacity.wait_exponential(multiplier=1,
                                                       min=5,
                                                       max=10),
                        retry=tenacity.retry_if_exception_type(
                            http.client.RemoteDisconnected),
                        reraise=True)
        def _do_request():
            return urllib.request.urlopen(
                'http://{}/server-status'.format(dashboard_ip))

        with self.config_change(
            {'harden': _app_config['harden'].get('value', '')},
            {'harden': 'apache'}):
            try:
                _do_request()
            except urllib.request.HTTPError as e:
                # test failed if it didn't return 404
                msg = "Apache mod_status check failed."
                self.assertEqual(e.code, 404, msg)
        logging.info('OK')
Esempio n. 14
0
    def test_400_connection(self):
        """Test that dashboard responds to http request.

        Ported from amulet tests.
        """
        logging.info('Checking dashboard http response...')

        unit_name = zaza_model.get_lead_unit_name('openstack-dashboard')
        keystone_unit = zaza_model.get_lead_unit_name('keystone')
        dashboard_relation = openstack_juju.get_relation_from_unit(
            keystone_unit, unit_name, 'identity-service')
        dashboard_ip = dashboard_relation['private-address']
        logging.debug("... dashboard_ip is:{}".format(dashboard_ip))

        # NOTE(fnordahl) there is a eluding issue that currently makes the
        #                first request to the OpenStack Dashboard error out
        #                with 500 Internal Server Error in CI.  Temporarilly
        #                add retry logic to unwedge the gate.  This issue
        #                should be revisited and root caused properly when time
        #                allows.
        @tenacity.retry(wait=tenacity.wait_exponential(multiplier=1,
                                                       min=5,
                                                       max=10),
                        reraise=True)
        def do_request():
            logging.info("... trying to fetch the page")
            try:
                response = urllib.request.urlopen(
                    'http://{}/horizon'.format(dashboard_ip))
                logging.info("... fetched page")
            except Exception as e:
                logging.info("... exception raised was {}".format(str(e)))
                raise
            return response.read().decode('utf-8')

        html = do_request()
        self.assertIn('OpenStack Dashboard', html,
                      "Dashboard frontpage check failed")
Esempio n. 15
0
 def setUpClass(cls, application_name=None, model_alias=None):
     """Run setup for test class to create common resources."""
     cls.model_aliases = model.get_juju_model_aliases()
     if model_alias:
         cls.model_name = cls.model_aliases[model_alias]
     else:
         cls.model_name = model.get_juju_model()
     cls.test_config = lifecycle_utils.get_charm_config(fatal=False)
     if application_name:
         cls.application_name = application_name
     else:
         cls.application_name = cls.test_config['charm_name']
     cls.lead_unit = model.get_lead_unit_name(cls.application_name,
                                              model_name=cls.model_name)
     logging.debug('Leader unit is {}'.format(cls.lead_unit))
Esempio n. 16
0
    def test_100_services(self):
        """Verify the expected services are running.

        Ported from amulet tests.
        """
        logging.info('Checking openstack-dashboard services...')

        unit_name = zaza_model.get_lead_unit_name('openstack-dashboard')
        openstack_services = ['apache2']
        services = {}
        services[unit_name] = openstack_services

        for unit_name, unit_services in services.items():
            zaza_model.block_until_service_status(unit_name=unit_name,
                                                  services=unit_services,
                                                  target_status='running')
Esempio n. 17
0
    def test_401_authenticate(self):
        """Validate that authentication succeeds for client log in."""
        logging.info('Checking authentication through dashboard...')

        unit = zaza_model.get_unit_from_name(
            zaza_model.get_lead_unit_name(self.application_name))
        overcloud_auth = openstack_utils.get_overcloud_auth()
        password = overcloud_auth['OS_PASSWORD'],
        logging.info("admin password is {}".format(password))
        # try to get the url which will either pass or fail with a 403
        overcloud_auth = openstack_utils.get_overcloud_auth()
        domain = 'admin_domain',
        username = '******',
        password = overcloud_auth['OS_PASSWORD'],
        _login(unit.public_address, domain, username, password)
        logging.info('OK')
Esempio n. 18
0
    def test_200_haproxy_stats_config(self):
        """Verify that the HAProxy stats are properly setup."""
        logging.info('Checking dashboard HAProxy settings...')
        unit = zaza_model.get_unit_from_name(
            zaza_model.get_lead_unit_name(self.application_name))
        logging.debug("... dashboard_ip is:{}".format(
            zaza_model.get_unit_public_address(unit)))
        conf = '/etc/haproxy/haproxy.cfg'
        port = '8888'
        set_alternate = {
            'haproxy-expose-stats': 'True',
        }

        request = urllib.request.Request('http://{}:{}'.format(
            zaza_model.get_unit_public_address(unit), port))

        output = str(generic_utils.get_file_contents(unit, conf))

        password = None
        for line in output.split('\n'):
            if "stats auth" in line:
                password = line.split(':')[1]
                break
        else:
            raise ValueError("'stats auth' not found in output'")
        base64string = base64.b64encode(
            bytes('{}:{}'.format('admin', password), 'ascii'))
        request.add_header("Authorization",
                           "Basic {}".format(base64string.decode('utf-8')))

        # Expect default config to not be available externally.
        expected = 'bind 127.0.0.1:{}'.format(port)
        self.assertIn(expected, output)
        with self.assertRaises(urllib.error.URLError):
            _do_request(request)

        zaza_model.set_application_config(self.application_name, set_alternate)
        zaza_model.block_until_all_units_idle(model_name=self.model_name)

        # Once exposed, expect HAProxy stats to be available externally
        output = str(generic_utils.get_file_contents(unit, conf))
        expected = 'bind 0.0.0.0:{}'.format(port)
        html = _do_request(request).read().decode(encoding='utf-8')
        self.assertIn(expected, output)
        self.assertIn('Statistics Report for HAProxy', html,
                      "HAProxy stats check failed")
Esempio n. 19
0
    def test_302_router_settings(self):
        """Verify that the horizon router settings are correct.

        Ported from amulet tests.
        """
        # note this test is only valid after trusty-icehouse; however, all of
        # the zaza tests are after trusty-icehouse
        logging.info('Checking dashboard router settings...')
        unit_name = zaza_model.get_lead_unit_name('openstack-dashboard')
        conf = ('/usr/share/openstack-dashboard/openstack_dashboard/'
                'enabled/_40_router.py')

        cmd = 'cat {}'.format(conf)
        output = zaza_model.run_on_unit(unit_name, cmd)

        expected = {
            'DISABLED': "True",
        }
        mismatches = self.crude_py_parse(output['Stdout'], expected)
        assert not mismatches, ("mismatched keys on {} were:\n{}".format(
            conf, ", ".join(mismatches)))
Esempio n. 20
0
    def get_base_url(self):
        """Return the base url for http(s) requests.

        :returns: URL
        :rtype: str
        """
        vip = (zaza_model.get_application_config(
            self.application_name).get("vip").get("value"))
        if vip:
            ip = vip
        else:
            unit = zaza_model.get_unit_from_name(
                zaza_model.get_lead_unit_name(self.application_name))
            ip = unit.public_address

        logging.debug("Dashboard ip is:{}".format(ip))
        scheme = 'http'
        if self.use_https:
            scheme = 'https'
        url = '{}://{}'.format(scheme, ip)
        return url
Esempio n. 21
0
    def test_400_connection(self):
        """Test that dashboard responds to http request.

        Ported from amulet tests.
        """
        logging.info('Checking dashboard http response...')

        unit = zaza_model.get_unit_from_name(
            zaza_model.get_lead_unit_name(self.application_name))
        logging.debug("... dashboard_ip is:{}".format(unit.public_address))

        request = urllib.request.Request('http://{}/horizon'.format(
            unit.public_address))
        try:
            logging.info("... trying to fetch the page")
            html = _do_request(request)
            logging.info("... fetched page")
        except Exception as e:
            logging.info("... exception raised was {}".format(str(e)))
            raise
        return html.read().decode('utf-8')
        self.assertIn('OpenStack Dashboard', html,
                      "Dashboard frontpage check failed")
Esempio n. 22
0
    def test_050_local_settings_permissions_regression_check_lp1755027(self):
        """Assert regression check lp1755027.

        Assert the intended file permissions on openstack-dashboard's
        configuration file. Regression coverage for
        https://bugs.launchpad.net/bugs/1755027.

        Ported from amulet tests.
        """
        file_path = '/etc/openstack-dashboard/local_settings.py'
        expected_perms = '640'
        unit_name = zaza_model.get_lead_unit_name('openstack-dashboard')

        logging.info('Checking {} permissions...'.format(file_path))

        # NOTE(beisner): This could be a new test helper, but it needs
        # to be a clean backport to stable with high prio, so maybe later.
        cmd = 'stat -c %a {}'.format(file_path)
        output = zaza_model.run_on_unit(unit_name, cmd)
        perms = output['Stdout'].strip()
        assert perms == expected_perms, \
            ('{} perms of {} not expected ones of {}'
             .format(file_path, perms, expected_perms))
    def test_03_user_monitor(self):
        """Verify user monitors are applied."""
        user_monitors = {
            "version": "0.3",
            "monitors": {
                "local": {
                    "procrunning": {
                        "rsync": {
                            "max": 1,
                            "executable": "rsync",
                            "name": "RSYNc Running",
                            "min": 1,
                        },
                        "jujud": {
                            "max": 1,
                            "executable": "jujud",
                            "name": "Juju Running",
                            "min": 1,
                        },
                    }
                },
                "remote": {
                    "tcp": {
                        "ssh": {
                            "warning": 2,
                            "critical": 10,
                            "name": "SSH Running",
                            "timeout": 12,
                            "port": 22,
                            "string": "SSH.*",
                            "expect": None,
                        }
                    }
                },
            },
        }
        model.set_application_config(self.application_name,
                                     {"monitors": yaml.dump(user_monitors)})
        model.block_until_all_units_idle()

        local_nrpe_checks = {
            "check_proc_jujud_user.cfg":
            "command[check_proc_jujud_user]=/usr/lib/nagios/plugins/"
            "check_procs -w 1 -c 1 -C jujud",
            "check_proc_rsync_user.cfg":
            "command[check_proc_rsync_user]=/usr/lib/nagios/plugins/"
            "check_procs -w 1 -c 1 -C rsync",
        }

        for nrpe_check in local_nrpe_checks:
            logging.info(
                "Checking content of '{}' nrpe check".format(nrpe_check))
            cmd = "cat /etc/nagios/nrpe.d/" + nrpe_check
            result = model.run_on_unit(self.lead_unit_name, cmd)
            code = result.get("Code")
            if code != "0":
                logging.warning(
                    "Unable to find nrpe check {} at /etc/nagios/nrpe.d/".
                    format(nrpe_check))
                raise model.CommandRunFailed(cmd, result)
            content = result.get("Stdout")
            self.assertTrue(local_nrpe_checks[nrpe_check] in content)

        remote_nrpe_checks = {
            "check_tcp_H_HOSTADDRESS__E_p22_s_SSH____eNone_w2_c10_t12_t10.cfg":
            "/usr/lib/nagios/plugins/check_tcp -H $HOSTADDRESS$ "
            "-E -p 22 -s 'SSH.*' -e None -w 2 -c 10 -t 12 -t 10"
        }
        for nrpe_check in remote_nrpe_checks:
            logging.info(
                "Checking content of '{}' nrpe command in nagios unit".format(
                    nrpe_check))
            cmd = "cat /etc/nagios3/conf.d/commands/" + nrpe_check
            nagios_lead_unit_name = model.get_lead_unit_name(
                "nagios", model_name=self.model_name)
            result = model.run_on_unit(nagios_lead_unit_name, cmd)
            code = result.get("Code")
            if code != "0":
                logging.warning(
                    "Unable to find nrpe command {} at "
                    "/etc/nagios3/conf.d/commands/ in nagios unit".format(
                        nrpe_check))
                raise model.CommandRunFailed(cmd, result)
            content = result.get("Stdout")
            self.assertTrue(remote_nrpe_checks[nrpe_check] in content)
Esempio n. 24
0
    def test_401_authenticate(self):
        """Validate that authentication succeeds for client log in.

        Ported from amulet tests.
        """
        logging.info('Checking authentication through dashboard...')

        unit_name = zaza_model.get_lead_unit_name('openstack-dashboard')
        keystone_unit = zaza_model.get_lead_unit_name('keystone')
        dashboard_relation = openstack_juju.get_relation_from_unit(
            keystone_unit, unit_name, 'identity-service')
        dashboard_ip = dashboard_relation['private-address']
        logging.debug("... dashboard_ip is:{}".format(dashboard_ip))

        url = 'http://{}/horizon/auth/login/'.format(dashboard_ip)

        overcloud_auth = openstack_utils.get_overcloud_auth()
        if overcloud_auth['OS_AUTH_URL'].endswith("v2.0"):
            api_version = 2
        else:
            api_version = 3
        keystone_client = openstack_utils.get_keystone_client(overcloud_auth)
        catalog = keystone_client.service_catalog.get_endpoints()
        logging.info(catalog)
        if api_version == 2:
            region = catalog['identity'][0]['publicURL']
        else:
            region = [
                i['url'] for i in catalog['identity']
                if i['interface'] == 'public'
            ][0]

        # NOTE(ajkavanagh) there used to be a trusty/icehouse test in the
        # amulet test, but as the zaza tests only test from trusty/mitaka
        # onwards, the test has been dropped
        if (openstack_utils.get_os_release() >=
                openstack_utils.get_os_release('bionic_stein')):
            expect = "Sign Out"
            # update the in dashboard seems to require region to be default in
            # this test configuration
            region = 'default'
        else:
            expect = 'Projects - OpenStack Dashboard'

        # NOTE(thedac) Similar to the connection test above we get occasional
        # intermittent authentication fails. Wrap in a retry loop.
        @tenacity.retry(wait=tenacity.wait_exponential(multiplier=1,
                                                       min=5,
                                                       max=10),
                        retry=tenacity.retry_unless_exception_type(
                            self.AuthExceptions),
                        reraise=True)
        def _do_auth_check(expect):
            # start session, get csrftoken
            client = requests.session()
            client.get(url)

            if 'csrftoken' in client.cookies:
                csrftoken = client.cookies['csrftoken']
            else:
                raise Exception("Missing csrftoken")

            # build and send post request
            auth = {
                'domain': 'admin_domain',
                'username': '******',
                'password': overcloud_auth['OS_PASSWORD'],
                'csrfmiddlewaretoken': csrftoken,
                'next': '/horizon/',
                'region': region,
            }

            # In the minimal test deployment /horizon/project/ is unauthorized,
            # this does not occur in a full deployment and is probably due to
            # services/information missing that horizon wants to display data
            # for.
            # Redirect to /horizon/identity/ instead.
            if (openstack_utils.get_os_release() >=
                    openstack_utils.get_os_release('xenial_queens')):
                auth['next'] = '/horizon/identity/'

            if (openstack_utils.get_os_release() >=
                    openstack_utils.get_os_release('bionic_stein')):
                auth['region'] = 'default'

            if api_version == 2:
                del auth['domain']

            logging.info('POST data: "{}"'.format(auth))
            response = client.post(url, data=auth, headers={'Referer': url})

            if expect not in response.text:
                msg = 'FAILURE code={} text="{}"'.format(
                    response, response.text)
                # NOTE(thedac) amulet.raise_status exits on exception.
                # Raise a custom exception.
                logging.info("Yeah, wen't wrong: {}".format(msg))
                raise self.FailedAuth(msg)
            raise self.PassedAuth()

        try:
            _do_auth_check(expect)
        except self.FailedAuth as e:
            assert False, str(e)
        except self.PassedAuth:
            pass