mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-02-25 18:55:28 -06:00
ipatests: Add integration tests for External IdP support
Tests for [RFE]: Added integration tests for external IdP authentication with keycloak-17 as identity provider. Related : https://pagure.io/freeipa/issue/8805 Related: https://pagure.io/freeipa/issue/8803 Related: https://pagure.io/freeipa/issue/8804 Signed-off-by: Anuja More <amore@redhat.com> Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com> Reviewed-By: Mohammad Rizwan Yusuf <myusuf@redhat.com>
This commit is contained in:
parent
5ca4e8ee33
commit
9cc703fd0e
159
ipatests/pytest_ipa/integration/create_quarkus.py
Normal file
159
ipatests/pytest_ipa/integration/create_quarkus.py
Normal file
@ -0,0 +1,159 @@
|
||||
import os
|
||||
import textwrap
|
||||
import time
|
||||
|
||||
from ipaplatform.paths import paths
|
||||
from ipatests.pytest_ipa.integration import tasks
|
||||
|
||||
|
||||
def setup_keycloakserver(host, version='17.0.0'):
|
||||
dir = "/opt/keycloak"
|
||||
password = host.config.admin_password
|
||||
tasks.install_packages(host, ["unzip", "java-11-openjdk-headless",
|
||||
"openssl", "maven", "wget",
|
||||
"firefox", "xorg-x11-server-Xvfb"])
|
||||
# add keycloak system user/group and folder
|
||||
url = "https://github.com/keycloak/keycloak/releases/download/{0}/keycloak-{0}.zip".format(version) # noqa: E501
|
||||
host.run_command(["wget", url, "-O", "{0}-{1}.zip".format(dir, version)])
|
||||
host.run_command(
|
||||
["unzip", "{0}-{1}.zip".format(dir, version), "-d", "/opt/"]
|
||||
)
|
||||
host.run_command(["mv", "{0}-{1}".format(dir, version), dir])
|
||||
host.run_command(["groupadd", "keycloak"])
|
||||
host.run_command(
|
||||
["useradd", "-r", "-g", "keycloak", "-d", dir, "keycloak"]
|
||||
)
|
||||
host.run_command(["chown", "-R", "keycloak:", dir])
|
||||
host.run_command(["chmod", "o+x", "{0}/bin/".format(dir)])
|
||||
host.run_command(["restorecon", "-R", dir])
|
||||
|
||||
# setup TLS certificate using IPA CA
|
||||
host.run_command(["kinit", "-k"])
|
||||
host.run_command(["ipa", "service-add", "HTTP/{0}".format(host.hostname)])
|
||||
|
||||
key = os.path.join(paths.OPENSSL_PRIVATE_DIR, "keycloak.key")
|
||||
crt = os.path.join(paths.OPENSSL_PRIVATE_DIR, "keycloak.crt")
|
||||
keystore = os.path.join(paths.OPENSSL_PRIVATE_DIR, "keycloak.store")
|
||||
|
||||
host.run_command(["ipa-getcert", "request", "-K",
|
||||
"HTTP/{0}".format(host.hostname),
|
||||
"-D", host.hostname, "-o", "keycloak",
|
||||
"-O", "keycloak", "-m", "0600",
|
||||
"-M", "0644",
|
||||
"-k", key, "-f", crt, "-w"])
|
||||
host.run_command(["keytool", "-import", "-keystore", keystore,
|
||||
"-file", "/etc/ipa/ca.crt",
|
||||
"-alias", "ipa_ca",
|
||||
"-trustcacerts", "-storepass", password, "-noprompt"])
|
||||
host.run_command(["chown", "keycloak:keycloak", keystore])
|
||||
|
||||
# Setup keycloak service and config files
|
||||
contents = textwrap.dedent("""
|
||||
KEYCLOAK_ADMIN=admin
|
||||
KEYCLOAK_ADMIN_PASSWORD={admin_pswd}
|
||||
KC_HOSTNAME={host}:8443
|
||||
KC_HTTPS_CERTIFICATE_FILE={crt}
|
||||
KC_HTTPS_CERTIFICATE_KEY_FILE={key}
|
||||
KC_HTTPS_TRUST_STORE_FILE={store}
|
||||
KC_HTTPS_TRUST_STORE_PASSWORD={store_pswd}
|
||||
KC_HTTP_RELATIVE_PATH=/auth
|
||||
""").format(admin_pswd=password, host=host.hostname, crt=crt, key=key,
|
||||
store=keystore, store_pswd=password)
|
||||
host.put_file_contents("/etc/sysconfig/keycloak", contents)
|
||||
|
||||
contents = textwrap.dedent("""
|
||||
[Unit]
|
||||
Description=Keycloak Server
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=idle
|
||||
EnvironmentFile=/etc/sysconfig/keycloak
|
||||
|
||||
User=keycloak
|
||||
Group=keycloak
|
||||
ExecStart=/opt/keycloak/bin/kc.sh start
|
||||
TimeoutStartSec=600
|
||||
TimeoutStopSec=600
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
""")
|
||||
host.put_file_contents("/etc/systemd/system/keycloak.service", contents)
|
||||
host.run_command(["systemctl", "daemon-reload"])
|
||||
|
||||
# Run build stage first
|
||||
env_vars = textwrap.dedent("""
|
||||
export KEYCLOAK_ADMIN=admin
|
||||
export KC_HOSTNAME={hostname}:8443
|
||||
export KC_HTTPS_CERTIFICATE_FILE=/etc/pki/tls/certs/keycloak.crt
|
||||
export KC_HTTPS_CERTIFICATE_KEY_FILE=/etc/pki/tls/private/keycloak.key
|
||||
export KC_HTTPS_TRUST_STORE_FILE=/etc/pki/tls/private/keycloak.store
|
||||
export KC_HTTPS_TRUST_STORE_PASSWORD={STORE_PASS}
|
||||
export KEYCLOAK_ADMIN_PASSWORD={ADMIN_PASS}
|
||||
export KC_HTTP_RELATIVE_PATH=/auth
|
||||
""").format(hostname=host.hostname, STORE_PASS=password,
|
||||
ADMIN_PASS=password)
|
||||
|
||||
content = host.get_file_contents('/etc/bashrc',
|
||||
encoding='utf-8')
|
||||
new_content = content + "\n{}".format(env_vars)
|
||||
host.put_file_contents('/etc/bashrc', new_content)
|
||||
host.run_command(['bash'])
|
||||
host.run_command(
|
||||
['su', '-', 'keycloak', '-c', '/opt/keycloak/bin/kc.sh build'])
|
||||
host.run_command(["systemctl", "start", "keycloak"])
|
||||
host.run_command(["/opt/keycloak/bin/kc.sh", "show-config"])
|
||||
|
||||
# Setup keycloak for use:
|
||||
kcadmin_sh = "/opt/keycloak/bin/kcadm.sh"
|
||||
|
||||
host.run_command([kcadmin_sh, "config", "truststore",
|
||||
"--trustpass", password, keystore])
|
||||
kcadmin = [kcadmin_sh, "config", "credentials", "--server",
|
||||
"https://{0}:8443/auth/".format(host.hostname),
|
||||
"--realm", "master", "--user", "admin",
|
||||
"--password", password
|
||||
]
|
||||
tasks.run_repeatedly(
|
||||
host, kcadmin, timeout=60)
|
||||
host.run_command(
|
||||
[kcadmin_sh, "create", "users", "-r", "master",
|
||||
"-s", "username=testuser1", "-s", "enabled=true",
|
||||
"-s", "email=testuser1@ipa.test"]
|
||||
)
|
||||
host.run_command(
|
||||
[kcadmin_sh, "set-password", "-r", "master",
|
||||
"--username", "testuser1", "--new-password", password]
|
||||
)
|
||||
|
||||
|
||||
def setup_keycloak_client(host):
|
||||
password = host.config.admin_password
|
||||
host.run_command(["/opt/keycloak/bin/kcreg.sh",
|
||||
"config", "credentials", "--server",
|
||||
"https://{0}:8443/auth/".format(host.hostname),
|
||||
"--realm", "master", "--user", "admin",
|
||||
"--password", password]
|
||||
)
|
||||
|
||||
client_json = textwrap.dedent("""
|
||||
{{
|
||||
"enabled" : true,
|
||||
"clientAuthenticatorType" : "client-secret",
|
||||
"redirectUris" : [ "https://ipa-ca.{redirect}/ipa/idp/*" ],
|
||||
"webOrigins" : [ "https://ipa-ca.{web}" ],
|
||||
"protocol" : "openid-connect",
|
||||
"attributes" : {{
|
||||
"oauth2.device.authorization.grant.enabled" : "true",
|
||||
"oauth2.device.polling.interval": "5"
|
||||
}}
|
||||
}}
|
||||
""").format(redirect=host.domain.name, web=host.domain.name)
|
||||
host.put_file_contents("/tmp/ipa_client.json", client_json)
|
||||
host.run_command(["/opt/keycloak/bin/kcreg.sh", "create",
|
||||
"-f", "/tmp/ipa_client.json",
|
||||
"-s", "clientId=ipa_oidc_client",
|
||||
"-s", "secret={0}".format(password)]
|
||||
)
|
||||
time.sleep(60)
|
116
ipatests/test_integration/test_idp.py
Normal file
116
ipatests/test_integration/test_idp.py
Normal file
@ -0,0 +1,116 @@
|
||||
from __future__ import absolute_import
|
||||
|
||||
import time
|
||||
|
||||
import textwrap
|
||||
from ipaplatform.paths import paths
|
||||
from ipatests.test_integration.base import IntegrationTest
|
||||
from ipatests.pytest_ipa.integration import tasks, create_quarkus
|
||||
|
||||
user_code_script = textwrap.dedent("""
|
||||
from selenium import webdriver
|
||||
from datetime import datetime
|
||||
from selenium.webdriver.firefox.options import Options
|
||||
from selenium.webdriver.common.by import By
|
||||
from selenium.webdriver.support.ui import WebDriverWait
|
||||
from selenium.webdriver.support import expected_conditions as EC
|
||||
options = Options()
|
||||
options.headless = True
|
||||
driver = webdriver.Firefox(executable_path="/opt/geckodriver", options=options)
|
||||
verification_uri = "{uri}"
|
||||
driver.get(verification_uri)
|
||||
try:
|
||||
element = WebDriverWait(driver, 90).until(
|
||||
EC.presence_of_element_located((By.ID, "username")))
|
||||
driver.find_element_by_id("username").send_keys("testuser1")
|
||||
driver.find_element_by_id("password").send_keys("{passwd}")
|
||||
driver.find_element_by_id("kc-login").click()
|
||||
element = WebDriverWait(driver, 90).until(
|
||||
EC.presence_of_element_located((By.ID, "kc-login")))
|
||||
driver.find_element_by_id("kc-login").click()
|
||||
assert "Device Login Successful" in driver.page_source
|
||||
finally:
|
||||
now = datetime.now().strftime("%M-%S")
|
||||
driver.get_screenshot_as_file("/var/log/httpd/screenshot-%s.png" % now)
|
||||
driver.quit()
|
||||
""")
|
||||
|
||||
|
||||
def add_user_code(host, verification_uri):
|
||||
contents = user_code_script.format(uri=verification_uri,
|
||||
passwd=host.config.admin_password)
|
||||
host.put_file_contents("/tmp/add_user_code.py", contents)
|
||||
tasks.run_repeatedly(
|
||||
host, ['python3', '/tmp/add_user_code.py'])
|
||||
|
||||
|
||||
def get_verification_uri(host, since, keycloak_server_name):
|
||||
command = textwrap.dedent("""
|
||||
journalctl -u ipa-otpd\\* --since="%s" | grep "user_code:" | awk '{ print substr($7,2,9) }'""" % since) # noqa: E501
|
||||
user_code = host.run_command(command).stdout_text.rstrip("\r\n")
|
||||
uri = ("https://{0}:8443/auth/realms/master/device?user_code={1}".format(
|
||||
keycloak_server_name, user_code))
|
||||
return uri
|
||||
|
||||
|
||||
def kinit_idp(host, user, keycloak_server):
|
||||
ARMOR = "/tmp/armor"
|
||||
tasks.kdestroy_all(host)
|
||||
# create armor for FAST
|
||||
host.run_command(["kinit", "-n", "-c", ARMOR])
|
||||
since = time.strftime('%Y-%m-%d %H:%M:%S')
|
||||
cmd = ["kinit", "-T", ARMOR, user]
|
||||
with host.spawn_expect(cmd, default_timeout=100) as e:
|
||||
e.expect('Authenticate at .+: ')
|
||||
uri = get_verification_uri(host, since, keycloak_server.hostname)
|
||||
if uri:
|
||||
add_user_code(keycloak_server, uri)
|
||||
e.sendline('\n')
|
||||
e.expect_exit()
|
||||
|
||||
test_idp = host.run_command(["klist", "-C"])
|
||||
assert "152" in test_idp.stdout_text
|
||||
|
||||
|
||||
class TestIDPKeycloak(IntegrationTest):
|
||||
|
||||
num_replicas = 1
|
||||
topology = 'line'
|
||||
|
||||
@classmethod
|
||||
def install(cls, mh):
|
||||
tasks.install_master(cls.master, setup_dns=True)
|
||||
tasks.install_client(cls.master, cls.replicas[0])
|
||||
content = cls.master.get_file_contents(paths.IPA_DEFAULT_CONF,
|
||||
encoding='utf-8')
|
||||
new_content = content + "\noidc_child_debug_level = 10"
|
||||
cls.master.put_file_contents(paths.IPA_DEFAULT_CONF, new_content)
|
||||
with tasks.remote_sssd_config(cls.master) as sssd_config:
|
||||
sssd_config.edit_domain(
|
||||
cls.master.domain, 'krb5_auth_timeout', 1100)
|
||||
tasks.clear_sssd_cache(cls.master)
|
||||
tasks.kinit_admin(cls.master)
|
||||
cls.master.run_command(["ipa", "config-mod", "--user-auth-type=idp",
|
||||
"--user-auth-type=password"])
|
||||
xvfb = ("nohup /usr/bin/Xvfb :99 -ac -noreset -screen 0 1400x1200x8 "
|
||||
"</dev/null &>/dev/null &")
|
||||
cls.replicas[0].run_command(xvfb)
|
||||
|
||||
def test_auth_keycloak_idp(self):
|
||||
keycloak_srv = self.replicas[0]
|
||||
create_quarkus.setup_keycloakserver(keycloak_srv)
|
||||
time.sleep(60)
|
||||
create_quarkus.setup_keycloak_client(keycloak_srv)
|
||||
tasks.kinit_admin(self.master)
|
||||
cmd = ["ipa", "idp-add", "keycloak", "--provider=keycloak",
|
||||
"--client-id=ipa_oidc_client", "--org=master",
|
||||
"--base-url={0}:8443/auth".format(keycloak_srv.hostname)]
|
||||
self.master.run_command(cmd, stdin_text="{0}\n{0}".format(
|
||||
keycloak_srv.config.admin_password))
|
||||
tasks.user_add(self.master, 'keycloakuser',
|
||||
extra_args=["--user-auth-type=idp",
|
||||
"--idp-user-id=testuser1@ipa.test",
|
||||
"--idp=keycloak"]
|
||||
)
|
||||
tasks.clear_sssd_cache(self.master)
|
||||
kinit_idp(self.master, 'keycloakuser', keycloak_srv)
|
Loading…
Reference in New Issue
Block a user