Add keycloak OIDC based federation tests
This patch adds federation tests for horizon and cover the scenario to make sure authentication via an external IDP like keycloak works. Note: The federation based tests are skipped for now as we don't have a mechanism upstream to run these in a job and will be skipped until such job is developed Change-Id: I5afd1c05a74d905b6c732df2659c9e5d155aa633
This commit is contained in:
@@ -242,6 +242,20 @@ ThemeGroup = [
|
||||
help='Default xpath for second dropdown of browse panel'),
|
||||
]
|
||||
|
||||
OIDCGroup = [
|
||||
cfg.StrOpt('keycloak_test_user1_username',
|
||||
default='kctestuser1',
|
||||
help='Username to use for keycloak test user 1'),
|
||||
cfg.StrOpt('keycloak_test_user1_password',
|
||||
default='nomoresecrets1',
|
||||
help='Password to use for keycloak test user 1.',
|
||||
secret=True),
|
||||
cfg.StrOpt('keycloak_test_user_home_project',
|
||||
default='SSOproject',
|
||||
help='Project to keep all objects belonging to a '
|
||||
'regular keycloak user.'),
|
||||
]
|
||||
|
||||
|
||||
def _get_config_files():
|
||||
conf_dir = os.path.join(
|
||||
@@ -270,6 +284,7 @@ def get_config():
|
||||
cfg.CONF.register_opts(PluginGroup, group="plugin")
|
||||
cfg.CONF.register_opts(VolumeGroup, group="volume")
|
||||
cfg.CONF.register_opts(ThemeGroup, group="theme")
|
||||
cfg.CONF.register_opts(OIDCGroup, group="OIDC")
|
||||
|
||||
return cfg.CONF
|
||||
|
||||
@@ -288,4 +303,5 @@ def list_opts():
|
||||
("plugin", PluginGroup),
|
||||
("volume", VolumeGroup),
|
||||
("theme", ThemeGroup),
|
||||
("OIDC", OIDCGroup),
|
||||
]
|
||||
|
@@ -133,3 +133,10 @@ browse_left_panel_sec=None,compute,compute,compute,compute,compute,volumes,volum
|
||||
b_l_p_sec_line_xpath=.//*[@id="sidebar-accordion-{main_panel}"]
|
||||
b_l_p_sec_line_req_btn=.//a[@data-target="#sidebar-accordion-{main_panel}-{sec_panel}"]
|
||||
b_l_p_sidebar_xpath=.//*[@id="sidebar-accordion-{main_panel}-{sec_panel}"]
|
||||
|
||||
#Parameters for keycloak test user
|
||||
[OIDC]
|
||||
#OIDC parameters for keycloak login
|
||||
keycloak_test_user1_username=kctestuser1
|
||||
keycloak_test_user1_password=nomoresecrets1
|
||||
keycloak_test_user_home_project=SSOproject
|
||||
|
@@ -18,6 +18,7 @@ from threading import Thread
|
||||
import time
|
||||
|
||||
import pytest
|
||||
from selenium.webdriver.support.ui import Select
|
||||
import xvfbwrapper
|
||||
|
||||
from horizon.test import webdriver
|
||||
@@ -45,6 +46,13 @@ class Session:
|
||||
config.identity.admin_home_project,
|
||||
),
|
||||
}
|
||||
self.oidc_credentials = {
|
||||
'user': (
|
||||
config.OIDC.keycloak_test_user1_username,
|
||||
config.OIDC.keycloak_test_user1_password,
|
||||
config.OIDC.keycloak_test_user_home_project,
|
||||
),
|
||||
}
|
||||
self.project_name_xpath = config.theme.project_name_xpath
|
||||
self.logout_url = '/'.join((
|
||||
config.dashboard.dashboard_url,
|
||||
@@ -78,6 +86,26 @@ class Session:
|
||||
self.current_project = self.driver.find_element_by_xpath(
|
||||
self.project_name_xpath).text
|
||||
|
||||
def login_oidc(self, user, project=None):
|
||||
# Keycloak/OIDC login
|
||||
username, password, home_project = self.oidc_credentials[user]
|
||||
if project is None:
|
||||
project = home_project
|
||||
self.driver.get(self.logout_url)
|
||||
select_auth = self.driver.find_element_by_id('id_auth_type')
|
||||
select_auth.click()
|
||||
select_opt = Select(select_auth)
|
||||
select_opt.select_by_visible_text('OpenID Connect')
|
||||
button = self.driver.find_element_by_css_selector(
|
||||
'.btn-primary')
|
||||
button.click()
|
||||
keycloak_user_field = self.driver.find_element_by_id('username')
|
||||
keycloak_user_field.send_keys(username)
|
||||
keycloak_pass_field = self.driver.find_element_by_id('password')
|
||||
keycloak_pass_field.send_keys(password)
|
||||
kc_login_button = self.driver.find_element_by_id('kc-login')
|
||||
kc_login_button.click()
|
||||
|
||||
|
||||
@pytest.fixture(scope='session')
|
||||
def login(driver, config):
|
||||
|
@@ -0,0 +1,64 @@
|
||||
# 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 pytest
|
||||
from selenium.common.exceptions import NoSuchElementException
|
||||
|
||||
from openstack_dashboard.test.selenium.conftest import Session
|
||||
|
||||
|
||||
@pytest.fixture(scope='session')
|
||||
def login_oidc(driver, config):
|
||||
session = Session(driver, config)
|
||||
return session.login_oidc
|
||||
|
||||
|
||||
def test_federation_keystone_user_login(login, driver, config):
|
||||
login('user')
|
||||
try:
|
||||
driver.find_element_by_xpath(
|
||||
config.theme.user_name_xpath)
|
||||
assert True
|
||||
except NoSuchElementException:
|
||||
assert False
|
||||
|
||||
|
||||
def test_federation_keystone_admin_login(login, driver, config):
|
||||
login('admin')
|
||||
try:
|
||||
driver.find_element_by_xpath(
|
||||
config.theme.user_name_xpath)
|
||||
assert True
|
||||
except NoSuchElementException:
|
||||
assert False
|
||||
|
||||
|
||||
def test_federation_keycloak_test_user_login(login_oidc, driver, config):
|
||||
login_oidc('user')
|
||||
project = config.OIDC.keycloak_test_user_home_project
|
||||
username = config.OIDC.keycloak_test_user1_username
|
||||
# Check that expected project exists
|
||||
try:
|
||||
project_element = driver.find_element_by_xpath(
|
||||
config.theme.project_name_xpath)
|
||||
project_element.find_element_by_xpath(
|
||||
f'.//*[normalize-space()="{project}"]')
|
||||
except NoSuchElementException:
|
||||
assert False, f"Project name '{project}' isn't found"
|
||||
# Check that expected username exists
|
||||
try:
|
||||
username_element = driver.find_element_by_xpath(
|
||||
config.theme.user_name_xpath)
|
||||
username_element.find_element_by_xpath(
|
||||
f'.//*[normalize-space()="{username}"]')
|
||||
except NoSuchElementException:
|
||||
assert False, f"Username '{username}' isn't found"
|
2
tox.ini
2
tox.ini
@@ -98,7 +98,7 @@ setenv =
|
||||
SELENIUM_HEADLESS=1
|
||||
commands =
|
||||
oslo-config-generator --namespace openstack_dashboard_integration_tests
|
||||
pytest -v --junitxml="{toxinidir}/test_reports/integration_pytest_results.xml" --html="{toxinidir}/test_reports/integration_pytest_results.html" --self-contained-html {posargs:{toxinidir}/openstack_dashboard/test/selenium/integration}
|
||||
pytest -v -k "not federation" --junitxml="{toxinidir}/test_reports/integration_pytest_results.xml" --html="{toxinidir}/test_reports/integration_pytest_results.html" --self-contained-html {posargs:{toxinidir}/openstack_dashboard/test/selenium/integration}
|
||||
|
||||
[testenv:ui-pytest]
|
||||
# Run pytest ui tests only
|
||||
|
Reference in New Issue
Block a user