|
|
ac7d03 |
From 48f20550f175503cb226bac47c570a2ff3e79be1 Mon Sep 17 00:00:00 2001
|
|
|
ac7d03 |
From: Martin Babinsky <mbabinsk@redhat.com>
|
|
|
ac7d03 |
Date: Fri, 12 May 2017 15:15:37 +0200
|
|
|
ac7d03 |
Subject: [PATCH] Add an attribute reporting client PKINIT-capable servers
|
|
|
ac7d03 |
|
|
|
ac7d03 |
A new multi-valued server attribute `pkinit_server` was added which
|
|
|
ac7d03 |
reports IPA masters that have PKINIT configuration usable by clients.
|
|
|
ac7d03 |
|
|
|
ac7d03 |
The existing tests were modified to allow for testing the new attribute.
|
|
|
ac7d03 |
|
|
|
ac7d03 |
https://pagure.io/freeipa/issue/6937
|
|
|
ac7d03 |
|
|
|
ac7d03 |
Reviewed-By: Jan Cholasta <jcholast@redhat.com>
|
|
|
ac7d03 |
Reviewed-By: Stanislav Laznicka <slaznick@redhat.com>
|
|
|
ac7d03 |
---
|
|
|
ac7d03 |
ipaserver/servroles.py | 7 ++
|
|
|
ac7d03 |
ipatests/test_ipaserver/test_serverroles.py | 109 +++++++++++++---------------
|
|
|
ac7d03 |
2 files changed, 59 insertions(+), 57 deletions(-)
|
|
|
ac7d03 |
|
|
|
ac7d03 |
diff --git a/ipaserver/servroles.py b/ipaserver/servroles.py
|
|
|
ac7d03 |
index 84fed1046b3b46dc9f5f8bbe6e03354725f1136c..f6e79338b9187aa741fe45b9fae42476cc65f724 100644
|
|
|
ac7d03 |
--- a/ipaserver/servroles.py
|
|
|
ac7d03 |
+++ b/ipaserver/servroles.py
|
|
|
ac7d03 |
@@ -625,4 +625,11 @@ attribute_instances = (
|
|
|
ac7d03 |
u"DNSSEC",
|
|
|
ac7d03 |
u"dnssecKeyMaster",
|
|
|
ac7d03 |
),
|
|
|
ac7d03 |
+ ServerAttribute(
|
|
|
ac7d03 |
+ u"pkinit_server_server",
|
|
|
ac7d03 |
+ u"PKINIT enabled server",
|
|
|
ac7d03 |
+ u"ipa_master_server",
|
|
|
ac7d03 |
+ u"KDC",
|
|
|
ac7d03 |
+ u"pkinitEnabled"
|
|
|
ac7d03 |
+ )
|
|
|
ac7d03 |
)
|
|
|
ac7d03 |
diff --git a/ipatests/test_ipaserver/test_serverroles.py b/ipatests/test_ipaserver/test_serverroles.py
|
|
|
ac7d03 |
index e671272783d8d71c2ee56074459433b98b79dd0a..b373a4d32f60e5ef48bcf07ac29162516113e8a8 100644
|
|
|
ac7d03 |
--- a/ipatests/test_ipaserver/test_serverroles.py
|
|
|
ac7d03 |
+++ b/ipatests/test_ipaserver/test_serverroles.py
|
|
|
ac7d03 |
@@ -58,7 +58,7 @@ _adtrust_agents = DN(
|
|
|
ac7d03 |
|
|
|
ac7d03 |
|
|
|
ac7d03 |
master_data = {
|
|
|
ac7d03 |
- 'ca-dns-dnssec-keymaster': {
|
|
|
ac7d03 |
+ 'ca-dns-dnssec-keymaster-pkinit-server': {
|
|
|
ac7d03 |
'services': {
|
|
|
ac7d03 |
'CA': {
|
|
|
ac7d03 |
'enabled': True,
|
|
|
ac7d03 |
@@ -72,14 +72,19 @@ master_data = {
|
|
|
ac7d03 |
'DNSSEC': {
|
|
|
ac7d03 |
'enabled': True,
|
|
|
ac7d03 |
'config': ['DNSSecKeyMaster']
|
|
|
ac7d03 |
+ },
|
|
|
ac7d03 |
+ 'KDC': {
|
|
|
ac7d03 |
+ 'enabled': True,
|
|
|
ac7d03 |
+ 'config': ['pkinitEnabled']
|
|
|
ac7d03 |
}
|
|
|
ac7d03 |
},
|
|
|
ac7d03 |
'expected_roles': {
|
|
|
ac7d03 |
'enabled': ['IPA master', 'CA server', 'DNS server']
|
|
|
ac7d03 |
},
|
|
|
ac7d03 |
- 'expected_attributes': {'DNS server': 'dnssec_key_master_server'}
|
|
|
ac7d03 |
+ 'expected_attributes': {'DNS server': 'dnssec_key_master_server',
|
|
|
ac7d03 |
+ 'IPA master': 'pkinit_server_server'}
|
|
|
ac7d03 |
},
|
|
|
ac7d03 |
- 'ca-kra-renewal-master': {
|
|
|
ac7d03 |
+ 'ca-kra-renewal-master-pkinit-server': {
|
|
|
ac7d03 |
'services': {
|
|
|
ac7d03 |
'CA': {
|
|
|
ac7d03 |
'enabled': True,
|
|
|
ac7d03 |
@@ -88,11 +93,16 @@ master_data = {
|
|
|
ac7d03 |
'KRA': {
|
|
|
ac7d03 |
'enabled': True,
|
|
|
ac7d03 |
},
|
|
|
ac7d03 |
+ 'KDC': {
|
|
|
ac7d03 |
+ 'enabled': True,
|
|
|
ac7d03 |
+ 'config': ['pkinitEnabled']
|
|
|
ac7d03 |
+ },
|
|
|
ac7d03 |
},
|
|
|
ac7d03 |
'expected_roles': {
|
|
|
ac7d03 |
'enabled': ['IPA master', 'CA server', 'KRA server']
|
|
|
ac7d03 |
},
|
|
|
ac7d03 |
- 'expected_attributes': {'CA server': 'ca_renewal_master_server'}
|
|
|
ac7d03 |
+ 'expected_attributes': {'CA server': 'ca_renewal_master_server',
|
|
|
ac7d03 |
+ 'IPA master': 'pkinit_server_server'}
|
|
|
ac7d03 |
},
|
|
|
ac7d03 |
'dns-trust-agent': {
|
|
|
ac7d03 |
'services': {
|
|
|
ac7d03 |
@@ -234,7 +244,7 @@ class MockMasterTopology(object):
|
|
|
ac7d03 |
no_members=True,
|
|
|
ac7d03 |
raw=True)['result']}
|
|
|
ac7d03 |
|
|
|
ac7d03 |
- self.existing_attributes = self._check_test_host_attributes()
|
|
|
ac7d03 |
+ self.original_dns_configs = self._remove_test_host_attrs()
|
|
|
ac7d03 |
|
|
|
ac7d03 |
def iter_domain_data(self):
|
|
|
ac7d03 |
MasterData = namedtuple('MasterData',
|
|
|
ac7d03 |
@@ -287,7 +297,6 @@ class MockMasterTopology(object):
|
|
|
ac7d03 |
pass
|
|
|
ac7d03 |
|
|
|
ac7d03 |
def _add_svc_entries(self, master_dn, svc_desc):
|
|
|
ac7d03 |
- self._add_ipamaster_services(master_dn)
|
|
|
ac7d03 |
for name in svc_desc:
|
|
|
ac7d03 |
svc_dn = self.get_service_dn(name, master_dn)
|
|
|
ac7d03 |
svc_mods = svc_desc[name]
|
|
|
ac7d03 |
@@ -298,6 +307,8 @@ class MockMasterTopology(object):
|
|
|
ac7d03 |
enabled=svc_mods['enabled'],
|
|
|
ac7d03 |
other_config=svc_mods.get('config', None)))
|
|
|
ac7d03 |
|
|
|
ac7d03 |
+ self._add_ipamaster_services(master_dn)
|
|
|
ac7d03 |
+
|
|
|
ac7d03 |
def _remove_svc_master_entries(self, master_dn):
|
|
|
ac7d03 |
try:
|
|
|
ac7d03 |
entries = self.ldap.connection.search_s(
|
|
|
ac7d03 |
@@ -317,7 +328,11 @@ class MockMasterTopology(object):
|
|
|
ac7d03 |
"""
|
|
|
ac7d03 |
for svc_name in self.ipamaster_services:
|
|
|
ac7d03 |
svc_dn = self.get_service_dn(svc_name, master_dn)
|
|
|
ac7d03 |
- self.ldap.add_entry(str(svc_dn), _make_service_entry_mods())
|
|
|
ac7d03 |
+ try:
|
|
|
ac7d03 |
+ self.api.Backend.ldap2.get_entry(svc_dn)
|
|
|
ac7d03 |
+ except errors.NotFound:
|
|
|
ac7d03 |
+ self.ldap.add_entry(
|
|
|
ac7d03 |
+ str(svc_dn), _make_service_entry_mods())
|
|
|
ac7d03 |
|
|
|
ac7d03 |
def _add_members(self, dn, fqdn, member_attrs):
|
|
|
ac7d03 |
_entry, attrs = self.ldap.connection.search_s(
|
|
|
ac7d03 |
@@ -376,57 +391,36 @@ class MockMasterTopology(object):
|
|
|
ac7d03 |
except (ldap.NO_SUCH_OBJECT, ldap.NO_SUCH_ATTRIBUTE):
|
|
|
ac7d03 |
pass
|
|
|
ac7d03 |
|
|
|
ac7d03 |
- def _check_test_host_attributes(self):
|
|
|
ac7d03 |
- existing_attributes = set()
|
|
|
ac7d03 |
-
|
|
|
ac7d03 |
- for service, value, attr_name in (
|
|
|
ac7d03 |
- ('CA', 'caRenewalMaster', 'ca renewal master'),
|
|
|
ac7d03 |
- ('DNSSEC', 'DNSSecKeyMaster', 'dnssec key master')):
|
|
|
ac7d03 |
+ def _remove_test_host_attrs(self):
|
|
|
ac7d03 |
+ original_dns_configs = []
|
|
|
ac7d03 |
|
|
|
ac7d03 |
- svc_dn = DN(('cn', service), self.test_master_dn)
|
|
|
ac7d03 |
+ for attr_name in (
|
|
|
ac7d03 |
+ 'caRenewalMaster', 'dnssecKeyMaster', 'pkinitEnabled'):
|
|
|
ac7d03 |
try:
|
|
|
ac7d03 |
- svc_entry = self.api.Backend.ldap2.get_entry(svc_dn)
|
|
|
ac7d03 |
+ svc_entry = self.api.Backend.ldap2.find_entry_by_attr(
|
|
|
ac7d03 |
+ 'ipaConfigString', attr_name, 'ipaConfigObject',
|
|
|
ac7d03 |
+ base_dn=self.test_master_dn)
|
|
|
ac7d03 |
except errors.NotFound:
|
|
|
ac7d03 |
continue
|
|
|
ac7d03 |
else:
|
|
|
ac7d03 |
- config_string_val = svc_entry.get('ipaConfigString', [])
|
|
|
ac7d03 |
+ original_dns_configs.append(
|
|
|
ac7d03 |
+ (svc_entry.dn, list(svc_entry.get('ipaConfigString', [])))
|
|
|
ac7d03 |
+ )
|
|
|
ac7d03 |
+ svc_entry[u'ipaConfigString'].remove(attr_name)
|
|
|
ac7d03 |
+ self.api.Backend.ldap2.update_entry(svc_entry)
|
|
|
ac7d03 |
|
|
|
ac7d03 |
- if value in config_string_val:
|
|
|
ac7d03 |
- existing_attributes.add(attr_name)
|
|
|
ac7d03 |
-
|
|
|
ac7d03 |
- return existing_attributes
|
|
|
ac7d03 |
-
|
|
|
ac7d03 |
- def _remove_ca_renewal_master(self):
|
|
|
ac7d03 |
- if 'ca renewal master' not in self.existing_attributes:
|
|
|
ac7d03 |
- return
|
|
|
ac7d03 |
+ return original_dns_configs
|
|
|
ac7d03 |
|
|
|
ac7d03 |
- ca_dn = DN(('cn', 'CA'), self.test_master_dn)
|
|
|
ac7d03 |
- ca_entry = self.api.Backend.ldap2.get_entry(ca_dn)
|
|
|
ac7d03 |
-
|
|
|
ac7d03 |
- config_string_val = ca_entry.get('ipaConfigString', [])
|
|
|
ac7d03 |
- try:
|
|
|
ac7d03 |
- config_string_val.remove('caRenewalMaster')
|
|
|
ac7d03 |
- except KeyError:
|
|
|
ac7d03 |
- return
|
|
|
ac7d03 |
-
|
|
|
ac7d03 |
- ca_entry.update({'ipaConfigString': config_string_val})
|
|
|
ac7d03 |
- self.api.Backend.ldap2.update_entry(ca_entry)
|
|
|
ac7d03 |
-
|
|
|
ac7d03 |
- def _restore_ca_renewal_master(self):
|
|
|
ac7d03 |
- if 'ca renewal master' not in self.existing_attributes:
|
|
|
ac7d03 |
- return
|
|
|
ac7d03 |
-
|
|
|
ac7d03 |
- ca_dn = DN(('cn', 'CA'), self.test_master_dn)
|
|
|
ac7d03 |
- ca_entry = self.api.Backend.ldap2.get_entry(ca_dn)
|
|
|
ac7d03 |
-
|
|
|
ac7d03 |
- config_string_val = ca_entry.get('ipaConfigString', [])
|
|
|
ac7d03 |
- config_string_val.append('caRenewalMaster')
|
|
|
ac7d03 |
-
|
|
|
ac7d03 |
- ca_entry.update({'ipaConfigString': config_string_val})
|
|
|
ac7d03 |
- self.api.Backend.ldap2.update_entry(ca_entry)
|
|
|
ac7d03 |
+ def _restore_test_host_attrs(self):
|
|
|
ac7d03 |
+ for dn, config in self.original_dns_configs:
|
|
|
ac7d03 |
+ try:
|
|
|
ac7d03 |
+ svc_entry = self.api.Backend.ldap2.get_entry(dn)
|
|
|
ac7d03 |
+ svc_entry['ipaConfigString'] = config
|
|
|
ac7d03 |
+ self.api.Backend.ldap2.update_entry(svc_entry)
|
|
|
ac7d03 |
+ except (errors.NotFound, errors.EmptyModlist):
|
|
|
ac7d03 |
+ continue
|
|
|
ac7d03 |
|
|
|
ac7d03 |
def setup_data(self):
|
|
|
ac7d03 |
- self._remove_ca_renewal_master()
|
|
|
ac7d03 |
for master_data in self.iter_domain_data():
|
|
|
ac7d03 |
# create host
|
|
|
ac7d03 |
self._add_host_entry(master_data.fqdn)
|
|
|
ac7d03 |
@@ -449,7 +443,6 @@ class MockMasterTopology(object):
|
|
|
ac7d03 |
)
|
|
|
ac7d03 |
|
|
|
ac7d03 |
def teardown_data(self):
|
|
|
ac7d03 |
- self._restore_ca_renewal_master()
|
|
|
ac7d03 |
for master_data in self.iter_domain_data():
|
|
|
ac7d03 |
# first remove the master entries and service containers
|
|
|
ac7d03 |
self._remove_svc_master_entries(master_data.dn)
|
|
|
ac7d03 |
@@ -466,6 +459,8 @@ class MockMasterTopology(object):
|
|
|
ac7d03 |
# finally remove host entry
|
|
|
ac7d03 |
self._del_host_entry(master_data.fqdn)
|
|
|
ac7d03 |
|
|
|
ac7d03 |
+ self._restore_test_host_attrs()
|
|
|
ac7d03 |
+
|
|
|
ac7d03 |
|
|
|
ac7d03 |
@pytest.fixture(scope='module')
|
|
|
ac7d03 |
def mock_api(request):
|
|
|
ac7d03 |
@@ -665,14 +660,14 @@ class TestServerRoleStatusRetrieval(object):
|
|
|
ac7d03 |
|
|
|
ac7d03 |
def test_unknown_role_status_raises_notfound(self, mock_api, mock_masters):
|
|
|
ac7d03 |
unknown_role = 'IAP maestr'
|
|
|
ac7d03 |
- fqdn = mock_masters.get_fqdn('ca-dns-dnssec-keymaster')
|
|
|
ac7d03 |
+ fqdn = mock_masters.get_fqdn('ca-dns-dnssec-keymaster-pkinit-server')
|
|
|
ac7d03 |
with pytest.raises(errors.NotFound):
|
|
|
ac7d03 |
mock_api.Backend.serverroles.server_role_retrieve(
|
|
|
ac7d03 |
fqdn, unknown_role)
|
|
|
ac7d03 |
|
|
|
ac7d03 |
def test_no_servrole_queries_all_roles_on_server(self, mock_api,
|
|
|
ac7d03 |
mock_masters):
|
|
|
ac7d03 |
- master_name = 'ca-dns-dnssec-keymaster'
|
|
|
ac7d03 |
+ master_name = 'ca-dns-dnssec-keymaster-pkinit-server'
|
|
|
ac7d03 |
enabled_roles = master_data[master_name]['expected_roles']['enabled']
|
|
|
ac7d03 |
result = self.find_role(None, mock_api, mock_masters,
|
|
|
ac7d03 |
master=master_name)
|
|
|
ac7d03 |
@@ -688,7 +683,7 @@ class TestServerRoleStatusRetrieval(object):
|
|
|
ac7d03 |
invalid_substr = 'fwfgbb'
|
|
|
ac7d03 |
|
|
|
ac7d03 |
assert (not self.find_role(invalid_substr, mock_api, mock_masters,
|
|
|
ac7d03 |
- 'ca-dns-dnssec-keymaster'))
|
|
|
ac7d03 |
+ 'ca-dns-dnssec-keymaster-pkinit-server'))
|
|
|
ac7d03 |
|
|
|
ac7d03 |
|
|
|
ac7d03 |
class TestServerAttributes(object):
|
|
|
ac7d03 |
@@ -706,7 +701,7 @@ class TestServerAttributes(object):
|
|
|
ac7d03 |
actual_attr_masters = self.config_retrieve(
|
|
|
ac7d03 |
assoc_role, mock_api)[attr_name]
|
|
|
ac7d03 |
|
|
|
ac7d03 |
- assert actual_attr_masters == [fqdn]
|
|
|
ac7d03 |
+ assert fqdn in actual_attr_masters
|
|
|
ac7d03 |
|
|
|
ac7d03 |
def test_set_attribute_on_the_same_provider_raises_emptymodlist(
|
|
|
ac7d03 |
self, mock_api, mock_masters):
|
|
|
ac7d03 |
@@ -744,10 +739,10 @@ class TestServerAttributes(object):
|
|
|
ac7d03 |
original_renewal_master = self.config_retrieve(
|
|
|
ac7d03 |
role_name, mock_api)[attr_name]
|
|
|
ac7d03 |
|
|
|
ac7d03 |
- other_ca_server = mock_masters.get_fqdn('trust-controller-ca')
|
|
|
ac7d03 |
+ other_ca_server = [mock_masters.get_fqdn('trust-controller-ca')]
|
|
|
ac7d03 |
|
|
|
ac7d03 |
for host in (other_ca_server, original_renewal_master):
|
|
|
ac7d03 |
- self.config_update(mock_api, **{attr_name: [host]})
|
|
|
ac7d03 |
+ self.config_update(mock_api, **{attr_name: host})
|
|
|
ac7d03 |
|
|
|
ac7d03 |
assert (
|
|
|
ac7d03 |
- self.config_retrieve(role_name, mock_api)[attr_name] == [host])
|
|
|
ac7d03 |
+ self.config_retrieve(role_name, mock_api)[attr_name] == host)
|
|
|
ac7d03 |
--
|
|
|
ac7d03 |
2.9.4
|
|
|
ac7d03 |
|