mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2024-12-24 16:10:02 -06:00
e128e7d691
Pylint is a static analysis tool and therefore, couldn't always analyze dynamic stuff properly. Transformation plugins is a way to teach Pylint how to handle such cases. Particularly, with the help of FreeIPA own plugin, it is possible to tell Pylint about instance fields having a duck-typing nature. A drawback exposed here is that a static view (Pylint's) of code should be consistent with an actual one, otherwise, codebase will be polluted with various skips of pylint checks. * added missing fields to ipatests.test_integration.base.IntegrationTest * an attempt is made to clear `no-member` skips for ipatests * removed no longer needed `pytest` module transformation Related: https://pagure.io/freeipa/issue/8116 Signed-off-by: Stanislav Levin <slev@altlinux.org> Reviewed-By: Christian Heimes <cheimes@redhat.com>
244 lines
10 KiB
Python
244 lines
10 KiB
Python
#
|
|
# Copyright (C) 2019 FreeIPA Contributors see COPYING for license
|
|
#
|
|
"""
|
|
Module provides tests for the ipa-winsync-migrate command.
|
|
"""
|
|
import os
|
|
import base64
|
|
import re
|
|
|
|
import pytest
|
|
|
|
from ipaplatform.constants import constants as platformconstants
|
|
|
|
from ipatests.pytest_ipa.integration import tasks
|
|
from ipatests.test_integration.base import IntegrationTest
|
|
|
|
|
|
def get_windows_certificate(ad_host):
|
|
certs_path = '/cygdrive/c/Windows/System32/CertSrv/CertEnroll/'
|
|
cert_filename = '%s_%s-%s-CA.crt' % (
|
|
ad_host.hostname, ad_host.domain.name.split('.')[0],
|
|
ad_host.shortname.upper())
|
|
return ad_host.get_file_contents(os.path.join(certs_path, cert_filename))
|
|
|
|
|
|
def convert_crt_to_cer(data):
|
|
header = b'-----BEGIN CERTIFICATE-----\n'
|
|
trailer = b'-----END CERTIFICATE-----\n'
|
|
return header + base64.encodebytes(data) + trailer
|
|
|
|
|
|
def establish_winsync_agreement(master, ad):
|
|
win_cert = get_windows_certificate(ad)
|
|
cert_path = master.run_command(['mktemp']).stdout_text.strip()
|
|
master.put_file_contents(cert_path, convert_crt_to_cer(win_cert))
|
|
master.run_command(['kdestroy', '-A'])
|
|
master.run_command([
|
|
'ipa-replica-manage', 'connect', '--winsync',
|
|
'--binddn', 'cn=%s,cn=users,%s' % (ad.config.ad_admin_name,
|
|
ad.domain.basedn),
|
|
'--bindpw', ad.config.ad_admin_password,
|
|
'--password', master.config.dirman_password,
|
|
'--cacert', cert_path,
|
|
'--passsync', 'dummy',
|
|
ad.hostname, '-v'
|
|
])
|
|
master.run_command(['rm', cert_path])
|
|
|
|
|
|
def ipa_output_fields(s):
|
|
return [line.strip() for line in s.splitlines()]
|
|
|
|
|
|
class TestWinsyncMigrate(IntegrationTest):
|
|
topology = 'star'
|
|
num_ad_domains = 1
|
|
|
|
ipa_group = 'ipa_group'
|
|
ad_user = 'testuser'
|
|
default_shell = platformconstants.DEFAULT_SHELL
|
|
selinuxuser = platformconstants.SELINUX_USERMAP_ORDER.split("$")[0]
|
|
test_role = 'test_role'
|
|
test_hbac_rule = 'test_hbac_rule'
|
|
test_selinux_map = 'test_selinux_map'
|
|
test_role_with_nonposix_chars = '$the test,role!'
|
|
test_role_with_nonposix_chars_normalized = 'the_testrole'
|
|
collision_role1 = 'collision role'
|
|
collision_role2 = 'collision, role'
|
|
collision_role3 = 'collision_role'
|
|
collision_role_normalized = 'collision_role'
|
|
|
|
@classmethod
|
|
def install(cls, mh):
|
|
super(TestWinsyncMigrate, cls).install(mh)
|
|
|
|
cls.ad = cls.ads[0]
|
|
cls.trust_test_user = '%s@%s' % (cls.ad_user, cls.ad.domain.name)
|
|
tasks.configure_dns_for_trust(cls.master, cls.ad)
|
|
tasks.install_adtrust(cls.master)
|
|
cls.create_test_objects()
|
|
establish_winsync_agreement(cls.master, cls.ad)
|
|
tasks.kinit_admin(cls.master)
|
|
cls.setup_user_memberships(cls.ad_user)
|
|
# store user uid and gid
|
|
result = cls.master.run_command(['getent', 'passwd', cls.ad_user])
|
|
testuser_regex = (
|
|
r"^{0}:\*:(\d+):(\d+):{0}:/home/{0}:{1}$".format(
|
|
cls.ad_user, cls.default_shell,
|
|
)
|
|
)
|
|
m = re.match(testuser_regex, result.stdout_text)
|
|
cls.test_user_uid, cls.test_user_gid = m.groups()
|
|
|
|
@classmethod
|
|
def create_test_objects(cls):
|
|
tasks.group_add(cls.master, cls.ipa_group)
|
|
|
|
for role in [cls.test_role, cls.collision_role1, cls.collision_role2,
|
|
cls.collision_role3, cls.test_role_with_nonposix_chars]:
|
|
cls.master.run_command(['ipa', 'role-add', role])
|
|
|
|
cls.master.run_command(['ipa', 'hbacrule-add', cls.test_hbac_rule])
|
|
cls.master.run_command([
|
|
'ipa', 'selinuxusermap-add', cls.test_selinux_map,
|
|
'--selinuxuser', cls.selinuxuser])
|
|
|
|
@classmethod
|
|
def setup_user_memberships(cls, user):
|
|
cls.master.run_command(['ipa', 'group-add-member', cls.ipa_group,
|
|
'--users', user])
|
|
for role in [cls.test_role, cls.collision_role1, cls.collision_role2,
|
|
cls.collision_role3, cls.test_role_with_nonposix_chars]:
|
|
cls.master.run_command(['ipa', 'role-add-member', role,
|
|
'--users', user])
|
|
cls.master.run_command(['ipa', 'hbacrule-add-user',
|
|
cls.test_hbac_rule, '--users', user])
|
|
cls.master.run_command(['ipa', 'selinuxusermap-add-user',
|
|
cls.test_selinux_map, '--users', user])
|
|
|
|
def check_replication_agreement_exists(self, server_name, should_exist):
|
|
result = self.master.run_command(
|
|
['ipa-replica-manage', 'list', server_name])
|
|
if should_exist:
|
|
expected_message = '%s: winsync' % self.ad.hostname
|
|
else:
|
|
expected_message = ('Cannot find %s in public server list' %
|
|
server_name)
|
|
assert result.stdout_text.strip() == expected_message
|
|
|
|
def test_preconditions(self):
|
|
self.check_replication_agreement_exists(self.ad.hostname, True)
|
|
# check user exists at ipa server
|
|
result = self.master.run_command(['ipa', 'user-show', self.ad_user],
|
|
raiseonerr=False)
|
|
assert result.returncode == 0
|
|
|
|
def test_migration(self):
|
|
tasks.establish_trust_with_ad(self.master, self.ad.domain.name)
|
|
result = self.master.run_command([
|
|
'ipa-winsync-migrate', '-U', '--realm', self.ad.domain.name,
|
|
'--server', self.ad.hostname])
|
|
assert ('The ipa-winsync-migrate command was successful'
|
|
in result.stderr_text)
|
|
tasks.clear_sssd_cache(self.master)
|
|
|
|
def test_replication_agreement_deleted(self):
|
|
self.check_replication_agreement_exists(self.ad.hostname, False)
|
|
|
|
def test_user_deleted_from_ipa_server(self):
|
|
result = self.master.run_command(['ipa', 'user-show', self.ad_user],
|
|
raiseonerr=False)
|
|
assert result.returncode == 2
|
|
|
|
def test_user_attributes_preserved(self):
|
|
result = self.master.run_command(['getent', 'passwd',
|
|
self.trust_test_user])
|
|
passwd_template = (
|
|
'{trust_user}:*:{uid}:{gid}:{user}:/home/{domain}/{user}:{shell}')
|
|
expected_result = passwd_template.format(
|
|
user=self.ad_user, uid=self.test_user_uid, gid=self.test_user_gid,
|
|
domain=self.ad.domain.name, trust_user=self.trust_test_user,
|
|
shell=self.default_shell,
|
|
)
|
|
assert result.stdout_text.strip() == expected_result
|
|
|
|
def test_idoverride(self):
|
|
result = self.master.run_command([
|
|
'ipa', 'idoverrideuser-show', '--raw',
|
|
'Default Trust View', self.trust_test_user])
|
|
idoverride_fields = [line
|
|
for line in ipa_output_fields(result.stdout_text)
|
|
if 'ipaanchoruuid:' not in line]
|
|
expected_fields = [
|
|
'uid: %s' % self.ad_user,
|
|
'uidnumber: %s' % self.test_user_uid,
|
|
'gidnumber: %s' % self.test_user_gid,
|
|
'gecos: %s' % self.ad_user,
|
|
'loginshell: %s' % self.default_shell,
|
|
]
|
|
assert sorted(idoverride_fields) == sorted(expected_fields)
|
|
|
|
def test_groups_membership_preserved(self):
|
|
result = self.master.run_command([
|
|
'ipa', 'group-show', 'group_%s_winsync_external' % self.ipa_group])
|
|
output_fields = ipa_output_fields(result.stdout_text)
|
|
assert 'External member: %s' % self.trust_test_user in output_fields
|
|
assert 'Member of groups: %s' % self.ipa_group in output_fields
|
|
|
|
def test_role_membership_preserved(self):
|
|
result = self.master.run_command([
|
|
'ipa', 'group-show', 'role_%s_winsync_external' % self.test_role])
|
|
output_fields = ipa_output_fields(result.stdout_text)
|
|
assert 'External member: %s' % self.trust_test_user in output_fields
|
|
assert 'Roles: %s' % self.test_role
|
|
|
|
def test_selinuxusermap_membership_preserved(self):
|
|
wrapper_group = 'selinux_%s_winsync_external' % self.test_selinux_map
|
|
|
|
result = self.master.run_command(['ipa', 'selinuxusermap-show',
|
|
self.test_selinux_map])
|
|
assert ('User Groups: %s' % wrapper_group
|
|
in ipa_output_fields(result.stdout_text))
|
|
|
|
result = self.master.run_command(['ipa', 'group-show', wrapper_group])
|
|
assert ('External member: %s' % self.trust_test_user
|
|
in ipa_output_fields(result.stdout_text))
|
|
|
|
def test_hbacrule_membership_preserved(self):
|
|
result = self.master.run_command([
|
|
'ipa', 'group-show',
|
|
'hbacrule_%s_winsync_external' % self.test_hbac_rule])
|
|
output_fields = ipa_output_fields(result.stdout_text)
|
|
assert 'External member: %s' % self.trust_test_user in output_fields
|
|
assert 'Member of HBAC rule: %s' % self.test_hbac_rule in output_fields
|
|
|
|
def test_non_posix_chars_in_group_names_replaced(self):
|
|
result = self.master.run_command([
|
|
'ipa', 'role-show', self.test_role_with_nonposix_chars])
|
|
expected_group_name = ('role_%s_winsync_external' %
|
|
self.test_role_with_nonposix_chars_normalized)
|
|
assert ('Member groups: %s' % expected_group_name
|
|
in ipa_output_fields(result.stdout_text))
|
|
|
|
@pytest.mark.xfail(reason='BZ1698118', strict=True)
|
|
def test_collisions_resolved(self):
|
|
group = 'role_%s_winsync_external' % self.collision_role_normalized
|
|
result = self.master.run_command(['ipa', 'group-show', group])
|
|
output_fields = ipa_output_fields(result.stdout_text)
|
|
assert 'Roles: %s' % self.collision_role1 in output_fields
|
|
assert 'External member: %s' % self.trust_test_user in output_fields
|
|
|
|
group = 'role_%s_winsync_external1' % self.collision_role_normalized
|
|
result = self.master.run_command(['ipa', 'group-show', group])
|
|
output_fields = ipa_output_fields(result.stdout_text)
|
|
assert 'Roles: %s' % self.collision_role2 in output_fields
|
|
assert 'External member: %s' % self.trust_test_user in output_fields
|
|
|
|
group = 'role_%s_winsync_external2' % self.collision_role_normalized
|
|
result = self.master.run_command(['ipa', 'group-show', group])
|
|
output_fields = ipa_output_fields(result.stdout_text)
|
|
assert 'Roles: %s' % self.collision_role3 in output_fields
|
|
assert 'External member: %s' % self.trust_test_user in output_fields
|