|
|
ac7d03 |
From bd2a0a8d363af6c8b1491314d5da5f3c146e4ce6 Mon Sep 17 00:00:00 2001
|
|
|
ac7d03 |
From: Stanislav Laznicka <slaznick@redhat.com>
|
|
|
ac7d03 |
Date: Mon, 27 Mar 2017 08:18:29 +0200
|
|
|
ac7d03 |
Subject: [PATCH] Reworked the renaming mechanism
|
|
|
ac7d03 |
|
|
|
ac7d03 |
The rename operation on *_mod commands was only allowed when
|
|
|
ac7d03 |
the primary key of an entry was also its RDN. With these changes,
|
|
|
ac7d03 |
it should be possible to rename the rest of the entries as well.
|
|
|
ac7d03 |
|
|
|
ac7d03 |
An attribute to the base LDAPObject was added to whitelist the
|
|
|
ac7d03 |
objects we want to allow to be renamed. It replaced an old
|
|
|
ac7d03 |
attribute rdn_is_primary_key which was used for the very same
|
|
|
ac7d03 |
purpose but the name was confusing because it was not set
|
|
|
ac7d03 |
correctly for certain objects.
|
|
|
ac7d03 |
|
|
|
ac7d03 |
https://pagure.io/freeipa/issue/2466
|
|
|
ac7d03 |
https://pagure.io/freeipa/issue/6784
|
|
|
ac7d03 |
|
|
|
ac7d03 |
Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
|
|
|
ac7d03 |
Reviewed-By: Jan Cholasta <jcholast@redhat.com>
|
|
|
ac7d03 |
Reviewed-By: Martin Basti <mbasti@redhat.com>
|
|
|
ac7d03 |
---
|
|
|
ac7d03 |
ipaserver/plugins/automount.py | 2 +-
|
|
|
ac7d03 |
ipaserver/plugins/baseldap.py | 32 ++++++++++++++++++++------------
|
|
|
ac7d03 |
ipaserver/plugins/baseuser.py | 2 +-
|
|
|
ac7d03 |
ipaserver/plugins/ca.py | 2 +-
|
|
|
ac7d03 |
ipaserver/plugins/dns.py | 2 +-
|
|
|
ac7d03 |
ipaserver/plugins/group.py | 2 +-
|
|
|
ac7d03 |
ipaserver/plugins/idviews.py | 6 +++---
|
|
|
ac7d03 |
ipaserver/plugins/otptoken.py | 2 +-
|
|
|
ac7d03 |
ipaserver/plugins/permission.py | 2 +-
|
|
|
ac7d03 |
ipaserver/plugins/privilege.py | 2 +-
|
|
|
ac7d03 |
ipaserver/plugins/radiusproxy.py | 2 +-
|
|
|
ac7d03 |
ipaserver/plugins/role.py | 2 +-
|
|
|
ac7d03 |
ipaserver/plugins/servicedelegation.py | 2 +-
|
|
|
ac7d03 |
13 files changed, 34 insertions(+), 26 deletions(-)
|
|
|
ac7d03 |
|
|
|
ac7d03 |
diff --git a/ipaserver/plugins/automount.py b/ipaserver/plugins/automount.py
|
|
|
ac7d03 |
index c4cf2d6db876e13c78ecd73fc53bb356bf190e17..03f994c65832e7b6099739e951105c4b5a897391 100644
|
|
|
ac7d03 |
--- a/ipaserver/plugins/automount.py
|
|
|
ac7d03 |
+++ b/ipaserver/plugins/automount.py
|
|
|
ac7d03 |
@@ -456,7 +456,7 @@ class automountkey(LDAPObject):
|
|
|
ac7d03 |
default_attributes = [
|
|
|
ac7d03 |
'automountkey', 'automountinformation', 'description'
|
|
|
ac7d03 |
]
|
|
|
ac7d03 |
- rdn_is_primary_key = True
|
|
|
ac7d03 |
+ allow_rename = True
|
|
|
ac7d03 |
rdn_separator = ' '
|
|
|
ac7d03 |
|
|
|
ac7d03 |
takes_params = (
|
|
|
ac7d03 |
diff --git a/ipaserver/plugins/baseldap.py b/ipaserver/plugins/baseldap.py
|
|
|
ac7d03 |
index 79ba7fc4a14f8105cda481e1599b2acbd8394e45..dbe3cbd28c85ebc3d9254e24e14c5701adc673ab 100644
|
|
|
ac7d03 |
--- a/ipaserver/plugins/baseldap.py
|
|
|
ac7d03 |
+++ b/ipaserver/plugins/baseldap.py
|
|
|
ac7d03 |
@@ -36,7 +36,7 @@ from ipalib.text import _
|
|
|
ac7d03 |
from ipalib.util import json_serialize, validate_hostname
|
|
|
ac7d03 |
from ipalib.capabilities import client_has_capability
|
|
|
ac7d03 |
from ipalib.messages import add_message, SearchResultTruncated
|
|
|
ac7d03 |
-from ipapython.dn import DN
|
|
|
ac7d03 |
+from ipapython.dn import DN, RDN
|
|
|
ac7d03 |
from ipapython.version import API_VERSION
|
|
|
ac7d03 |
|
|
|
ac7d03 |
if six.PY3:
|
|
|
ac7d03 |
@@ -549,7 +549,7 @@ class LDAPObject(Object):
|
|
|
ac7d03 |
rdn_attribute = ''
|
|
|
ac7d03 |
uuid_attribute = ''
|
|
|
ac7d03 |
attribute_members = {}
|
|
|
ac7d03 |
- rdn_is_primary_key = False # Do we need RDN change to do a rename?
|
|
|
ac7d03 |
+ allow_rename = False
|
|
|
ac7d03 |
password_attributes = []
|
|
|
ac7d03 |
# Can bind as this entry (has userPassword or krbPrincipalKey)
|
|
|
ac7d03 |
bindable = False
|
|
|
ac7d03 |
@@ -1384,7 +1384,7 @@ class LDAPUpdate(LDAPQuery, crud.Update):
|
|
|
ac7d03 |
def get_options(self):
|
|
|
ac7d03 |
for option in super(LDAPUpdate, self).get_options():
|
|
|
ac7d03 |
yield option
|
|
|
ac7d03 |
- if self.obj.rdn_is_primary_key:
|
|
|
ac7d03 |
+ if self.obj.allow_rename:
|
|
|
ac7d03 |
yield self._get_rename_option()
|
|
|
ac7d03 |
|
|
|
ac7d03 |
def execute(self, *keys, **options):
|
|
|
ac7d03 |
@@ -1419,15 +1419,19 @@ class LDAPUpdate(LDAPQuery, crud.Update):
|
|
|
ac7d03 |
_check_limit_object_class(self.api.Backend.ldap2.schema.attribute_types(self.obj.disallow_object_classes), list(entry_attrs), allow_only=False)
|
|
|
ac7d03 |
|
|
|
ac7d03 |
rdnupdate = False
|
|
|
ac7d03 |
- try:
|
|
|
ac7d03 |
- if self.obj.rdn_is_primary_key and 'rename' in options:
|
|
|
ac7d03 |
- if not options['rename']:
|
|
|
ac7d03 |
- raise errors.ValidationError(name='rename', error=u'can\'t be empty')
|
|
|
ac7d03 |
- entry_attrs[self.obj.primary_key.name] = options['rename']
|
|
|
ac7d03 |
-
|
|
|
ac7d03 |
- if self.obj.rdn_is_primary_key and self.obj.primary_key.name in entry_attrs:
|
|
|
ac7d03 |
+ if 'rename' in options:
|
|
|
ac7d03 |
+ if not options['rename']:
|
|
|
ac7d03 |
+ raise errors.ValidationError(
|
|
|
ac7d03 |
+ name='rename', error=u'can\'t be empty')
|
|
|
ac7d03 |
+ entry_attrs[self.obj.primary_key.name] = options['rename']
|
|
|
ac7d03 |
+
|
|
|
ac7d03 |
+ # if setattr was used to change the RDN, the primary_key.name is
|
|
|
ac7d03 |
+ # already in entry_attrs
|
|
|
ac7d03 |
+ if self.obj.allow_rename and self.obj.primary_key.name in entry_attrs:
|
|
|
ac7d03 |
+ # perform RDN change if the primary key is also RDN
|
|
|
ac7d03 |
+ if (RDN((self.obj.primary_key.name, keys[-1])) ==
|
|
|
ac7d03 |
+ entry_attrs.dn[0]):
|
|
|
ac7d03 |
try:
|
|
|
ac7d03 |
- # RDN change
|
|
|
ac7d03 |
new_dn = DN((self.obj.primary_key.name,
|
|
|
ac7d03 |
entry_attrs[self.obj.primary_key.name]),
|
|
|
ac7d03 |
*entry_attrs.dn[1:])
|
|
|
ac7d03 |
@@ -1435,17 +1439,21 @@ class LDAPUpdate(LDAPQuery, crud.Update):
|
|
|
ac7d03 |
entry_attrs.dn,
|
|
|
ac7d03 |
new_dn)
|
|
|
ac7d03 |
|
|
|
ac7d03 |
- rdnkeys = keys[:-1] + (entry_attrs[self.obj.primary_key.name], )
|
|
|
ac7d03 |
+ rdnkeys = (keys[:-1] +
|
|
|
ac7d03 |
+ (entry_attrs[self.obj.primary_key.name], ))
|
|
|
ac7d03 |
entry_attrs.dn = self.obj.get_dn(*rdnkeys)
|
|
|
ac7d03 |
options['rdnupdate'] = True
|
|
|
ac7d03 |
rdnupdate = True
|
|
|
ac7d03 |
except errors.EmptyModlist:
|
|
|
ac7d03 |
# Attempt to rename to the current name, ignore
|
|
|
ac7d03 |
pass
|
|
|
ac7d03 |
+ except errors.NotFound:
|
|
|
ac7d03 |
+ self.obj.handle_not_found(*keys)
|
|
|
ac7d03 |
finally:
|
|
|
ac7d03 |
# Delete the primary_key from entry_attrs either way
|
|
|
ac7d03 |
del entry_attrs[self.obj.primary_key.name]
|
|
|
ac7d03 |
|
|
|
ac7d03 |
+ try:
|
|
|
ac7d03 |
# Exception callbacks will need to test for options['rdnupdate']
|
|
|
ac7d03 |
# to decide what to do. An EmptyModlist in this context doesn't
|
|
|
ac7d03 |
# mean an error occurred, just that there were no other updates to
|
|
|
ac7d03 |
diff --git a/ipaserver/plugins/baseuser.py b/ipaserver/plugins/baseuser.py
|
|
|
ac7d03 |
index 44adc76ec854dadbe0d8a4e8ca03e71c30df526c..bf24dbf542d3b481671dfe4e8cee14a2edcc26e0 100644
|
|
|
ac7d03 |
--- a/ipaserver/plugins/baseuser.py
|
|
|
ac7d03 |
+++ b/ipaserver/plugins/baseuser.py
|
|
|
ac7d03 |
@@ -164,7 +164,7 @@ class baseuser(LDAPObject):
|
|
|
ac7d03 |
'memberof': ['group', 'netgroup', 'role', 'hbacrule', 'sudorule'],
|
|
|
ac7d03 |
'memberofindirect': ['group', 'netgroup', 'role', 'hbacrule', 'sudorule'],
|
|
|
ac7d03 |
}
|
|
|
ac7d03 |
- rdn_is_primary_key = True
|
|
|
ac7d03 |
+ allow_rename = True
|
|
|
ac7d03 |
bindable = True
|
|
|
ac7d03 |
password_attributes = [('userpassword', 'has_password'),
|
|
|
ac7d03 |
('krbprincipalkey', 'has_keytab')]
|
|
|
ac7d03 |
diff --git a/ipaserver/plugins/ca.py b/ipaserver/plugins/ca.py
|
|
|
ac7d03 |
index f774f78bd6d4ad236b37d06b8b267e8dd78f93b7..9bb163dffa645c1cbb10976e62cbd4a714139319 100644
|
|
|
ac7d03 |
--- a/ipaserver/plugins/ca.py
|
|
|
ac7d03 |
+++ b/ipaserver/plugins/ca.py
|
|
|
ac7d03 |
@@ -68,7 +68,7 @@ class ca(LDAPObject):
|
|
|
ac7d03 |
'cn', 'description', 'ipacaid', 'ipacaissuerdn', 'ipacasubjectdn',
|
|
|
ac7d03 |
]
|
|
|
ac7d03 |
rdn_attribute = 'cn'
|
|
|
ac7d03 |
- rdn_is_primary_key = True
|
|
|
ac7d03 |
+ allow_rename = True
|
|
|
ac7d03 |
label = _('Certificate Authorities')
|
|
|
ac7d03 |
label_singular = _('Certificate Authority')
|
|
|
ac7d03 |
|
|
|
ac7d03 |
diff --git a/ipaserver/plugins/dns.py b/ipaserver/plugins/dns.py
|
|
|
ac7d03 |
index 7007928f3b4b2fd863077193671a03ae46119dc5..47ac963a0ae26fcaa81e70a8143bd7d0c172d20e 100644
|
|
|
ac7d03 |
--- a/ipaserver/plugins/dns.py
|
|
|
ac7d03 |
+++ b/ipaserver/plugins/dns.py
|
|
|
ac7d03 |
@@ -3000,7 +3000,7 @@ class dnsrecord(LDAPObject):
|
|
|
ac7d03 |
possible_objectclasses = ['idnsTemplateObject']
|
|
|
ac7d03 |
permission_filter_objectclasses = ['idnsrecord']
|
|
|
ac7d03 |
default_attributes = ['idnsname'] + _record_attributes
|
|
|
ac7d03 |
- rdn_is_primary_key = True
|
|
|
ac7d03 |
+ allow_rename = True
|
|
|
ac7d03 |
|
|
|
ac7d03 |
label = _('DNS Resource Records')
|
|
|
ac7d03 |
label_singular = _('DNS Resource Record')
|
|
|
ac7d03 |
diff --git a/ipaserver/plugins/group.py b/ipaserver/plugins/group.py
|
|
|
ac7d03 |
index 218da3c94d95bb399761acf9414182eff566c63b..1fb092d5f049e86f12681e5eb2397f98f1001697 100644
|
|
|
ac7d03 |
--- a/ipaserver/plugins/group.py
|
|
|
ac7d03 |
+++ b/ipaserver/plugins/group.py
|
|
|
ac7d03 |
@@ -173,7 +173,7 @@ class group(LDAPObject):
|
|
|
ac7d03 |
'memberofindirect': ['group', 'netgroup', 'role', 'hbacrule',
|
|
|
ac7d03 |
'sudorule'],
|
|
|
ac7d03 |
}
|
|
|
ac7d03 |
- rdn_is_primary_key = True
|
|
|
ac7d03 |
+ allow_rename = True
|
|
|
ac7d03 |
managed_permissions = {
|
|
|
ac7d03 |
'System: Read Groups': {
|
|
|
ac7d03 |
'replaces_global_anonymous_aci': True,
|
|
|
ac7d03 |
diff --git a/ipaserver/plugins/idviews.py b/ipaserver/plugins/idviews.py
|
|
|
ac7d03 |
index 6d4ac75209ea08e3c2969d53e1ae5372c3a535ac..b5ee32cf138677874497e2f345c932c352e20054 100644
|
|
|
ac7d03 |
--- a/ipaserver/plugins/idviews.py
|
|
|
ac7d03 |
+++ b/ipaserver/plugins/idviews.py
|
|
|
ac7d03 |
@@ -97,7 +97,7 @@ class idview(LDAPObject):
|
|
|
ac7d03 |
object_class = ['ipaIDView', 'top']
|
|
|
ac7d03 |
possible_objectclasses = ['ipaNameResolutionData']
|
|
|
ac7d03 |
default_attributes = ['cn', 'description', 'ipadomainresolutionorder']
|
|
|
ac7d03 |
- rdn_is_primary_key = True
|
|
|
ac7d03 |
+ allow_rename = True
|
|
|
ac7d03 |
|
|
|
ac7d03 |
label = _('ID Views')
|
|
|
ac7d03 |
label_singular = _('ID View')
|
|
|
ac7d03 |
@@ -848,7 +848,7 @@ class idoverrideuser(baseidoverride):
|
|
|
ac7d03 |
|
|
|
ac7d03 |
label = _('User ID overrides')
|
|
|
ac7d03 |
label_singular = _('User ID override')
|
|
|
ac7d03 |
- rdn_is_primary_key = True
|
|
|
ac7d03 |
+ allow_rename = True
|
|
|
ac7d03 |
|
|
|
ac7d03 |
# ID user overrides are bindable because we map SASL GSSAPI
|
|
|
ac7d03 |
# authentication of trusted users to ID user overrides in the
|
|
|
ac7d03 |
@@ -964,7 +964,7 @@ class idoverridegroup(baseidoverride):
|
|
|
ac7d03 |
|
|
|
ac7d03 |
label = _('Group ID overrides')
|
|
|
ac7d03 |
label_singular = _('Group ID override')
|
|
|
ac7d03 |
- rdn_is_primary_key = True
|
|
|
ac7d03 |
+ allow_rename = True
|
|
|
ac7d03 |
|
|
|
ac7d03 |
permission_filter_objectclasses = ['ipaGroupOverride']
|
|
|
ac7d03 |
managed_permissions = {
|
|
|
ac7d03 |
diff --git a/ipaserver/plugins/otptoken.py b/ipaserver/plugins/otptoken.py
|
|
|
ac7d03 |
index 98ecbe58b84622d7937a7e6eff77c5e41624bf4f..c66f0980f0fc2ed49b4224be40a18ce528a6da7b 100644
|
|
|
ac7d03 |
--- a/ipaserver/plugins/otptoken.py
|
|
|
ac7d03 |
+++ b/ipaserver/plugins/otptoken.py
|
|
|
ac7d03 |
@@ -143,7 +143,7 @@ class otptoken(LDAPObject):
|
|
|
ac7d03 |
relationships = {
|
|
|
ac7d03 |
'managedby': ('Managed by', 'man_by_', 'not_man_by_'),
|
|
|
ac7d03 |
}
|
|
|
ac7d03 |
- rdn_is_primary_key = True
|
|
|
ac7d03 |
+ allow_rename = True
|
|
|
ac7d03 |
|
|
|
ac7d03 |
label = _('OTP Tokens')
|
|
|
ac7d03 |
label_singular = _('OTP Token')
|
|
|
ac7d03 |
diff --git a/ipaserver/plugins/permission.py b/ipaserver/plugins/permission.py
|
|
|
ac7d03 |
index dd2a0183e90ed6da9e55fb0590ea0bd81bf0bd67..977c6fe363c501f820aa82ae5b2ea00d8c78c7ae 100644
|
|
|
ac7d03 |
--- a/ipaserver/plugins/permission.py
|
|
|
ac7d03 |
+++ b/ipaserver/plugins/permission.py
|
|
|
ac7d03 |
@@ -188,7 +188,7 @@ class permission(baseldap.LDAPObject):
|
|
|
ac7d03 |
'member': ['privilege'],
|
|
|
ac7d03 |
'memberindirect': ['role'],
|
|
|
ac7d03 |
}
|
|
|
ac7d03 |
- rdn_is_primary_key = True
|
|
|
ac7d03 |
+ allow_rename = True
|
|
|
ac7d03 |
managed_permissions = {
|
|
|
ac7d03 |
'System: Read Permissions': {
|
|
|
ac7d03 |
'replaces_global_anonymous_aci': True,
|
|
|
ac7d03 |
diff --git a/ipaserver/plugins/privilege.py b/ipaserver/plugins/privilege.py
|
|
|
ac7d03 |
index b3afbd289ac2e82d5569b5d5306be398a560413e..01d5396902d482eb5a9f21e7ece730a0a35157d6 100644
|
|
|
ac7d03 |
--- a/ipaserver/plugins/privilege.py
|
|
|
ac7d03 |
+++ b/ipaserver/plugins/privilege.py
|
|
|
ac7d03 |
@@ -101,7 +101,7 @@ class privilege(LDAPObject):
|
|
|
ac7d03 |
reverse_members = {
|
|
|
ac7d03 |
'member': ['permission'],
|
|
|
ac7d03 |
}
|
|
|
ac7d03 |
- rdn_is_primary_key = True
|
|
|
ac7d03 |
+ allow_rename = True
|
|
|
ac7d03 |
managed_permissions = {
|
|
|
ac7d03 |
'System: Read Privileges': {
|
|
|
ac7d03 |
'replaces_global_anonymous_aci': True,
|
|
|
ac7d03 |
diff --git a/ipaserver/plugins/radiusproxy.py b/ipaserver/plugins/radiusproxy.py
|
|
|
ac7d03 |
index 3391b8aed77205fb1a586d5472d8cfdbc9fd1cd5..be77c62432066beec951e5f50afe689e1d6debce 100644
|
|
|
ac7d03 |
--- a/ipaserver/plugins/radiusproxy.py
|
|
|
ac7d03 |
+++ b/ipaserver/plugins/radiusproxy.py
|
|
|
ac7d03 |
@@ -101,7 +101,7 @@ class radiusproxy(LDAPObject):
|
|
|
ac7d03 |
'ipatokenradiustimeout', 'ipatokenradiusretries', 'ipatokenusermapattribute'
|
|
|
ac7d03 |
]
|
|
|
ac7d03 |
search_attributes = ['cn', 'description', 'ipatokenradiusserver']
|
|
|
ac7d03 |
- rdn_is_primary_key = True
|
|
|
ac7d03 |
+ allow_rename = True
|
|
|
ac7d03 |
label = _('RADIUS Servers')
|
|
|
ac7d03 |
label_singular = _('RADIUS Server')
|
|
|
ac7d03 |
|
|
|
ac7d03 |
diff --git a/ipaserver/plugins/role.py b/ipaserver/plugins/role.py
|
|
|
ac7d03 |
index 5d0d1f8c657b8d840762135f5ff16db90fb4893f..e7f115c461a6a0421f9c43d0410daaf9d4307e76 100644
|
|
|
ac7d03 |
--- a/ipaserver/plugins/role.py
|
|
|
ac7d03 |
+++ b/ipaserver/plugins/role.py
|
|
|
ac7d03 |
@@ -92,7 +92,7 @@ class role(LDAPObject):
|
|
|
ac7d03 |
reverse_members = {
|
|
|
ac7d03 |
'member': ['privilege'],
|
|
|
ac7d03 |
}
|
|
|
ac7d03 |
- rdn_is_primary_key = True
|
|
|
ac7d03 |
+ allow_rename = True
|
|
|
ac7d03 |
managed_permissions = {
|
|
|
ac7d03 |
'System: Read Roles': {
|
|
|
ac7d03 |
'replaces_global_anonymous_aci': True,
|
|
|
ac7d03 |
diff --git a/ipaserver/plugins/servicedelegation.py b/ipaserver/plugins/servicedelegation.py
|
|
|
ac7d03 |
index c8052e957cc5f8d24f6a8d0621ca93422052e35b..4f94924fa76691bcd6c6fc2cef9eb7fb30fce48c 100644
|
|
|
ac7d03 |
--- a/ipaserver/plugins/servicedelegation.py
|
|
|
ac7d03 |
+++ b/ipaserver/plugins/servicedelegation.py
|
|
|
ac7d03 |
@@ -138,7 +138,7 @@ class servicedelegation(LDAPObject):
|
|
|
ac7d03 |
},
|
|
|
ac7d03 |
}
|
|
|
ac7d03 |
|
|
|
ac7d03 |
- rdn_is_primary_key = True
|
|
|
ac7d03 |
+ allow_rename = True
|
|
|
ac7d03 |
|
|
|
ac7d03 |
takes_params = (
|
|
|
ac7d03 |
Str(
|
|
|
ac7d03 |
--
|
|
|
ac7d03 |
2.12.1
|
|
|
ac7d03 |
|