mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2024-12-23 07:33:27 -06:00
fix sudorule runas user/groups https://fedorahosted.org/freeipa/ticket/570
This commit is contained in:
parent
974287895e
commit
1ea31a0cff
@ -87,6 +87,7 @@ add:schema-compat-entry-attribute: 'sudoCommand=%ifeq("cmdCategory","all","ALL",
|
||||
add:schema-compat-entry-attribute: 'sudoCommand=%ifeq("cmdCategory","all","ALL","!%deref_r(\"memberDenyCmd\",\"member\",\"sudoCmd\")")'
|
||||
add:schema-compat-entry-attribute: 'sudoRunAsUser=%{ipaSudoRunAsExtUser}'
|
||||
add:schema-compat-entry-attribute: 'sudoRunAsUser=%deref("ipaSudoRunAs","uid")'
|
||||
add:schema-compat-entry-attribute: 'sudoRunAsUser=%ifeq("ipaSudoRunAsUserCategory","all","ALL","%%%deref_f(\"ipaSudoRunAs\",\"(objectclass=posixGroup)\",\"cn\")")'
|
||||
add:schema-compat-entry-attribute: 'sudoRunAsGroup=%{ipaSudoRunAsExtGroup}'
|
||||
add:schema-compat-entry-attribute: 'sudoRunAsGroup=%deref("ipaSudoRunAs","cn")'
|
||||
add:schema-compat-entry-attribute: 'sudoOption=%{ipaSudoOpt}'
|
||||
|
@ -48,7 +48,7 @@ class sudorule(LDAPObject):
|
||||
'memberhost': ['host', 'hostgroup'],
|
||||
'memberallowcmd': ['sudocmd', 'sudocmdgroup'],
|
||||
'memberdenycmd': ['sudocmd', 'sudocmdgroup'],
|
||||
'ipasudorunas': ['user'],
|
||||
'ipasudorunas': ['user', 'group'],
|
||||
'ipasudorunasgroup': ['group'],
|
||||
}
|
||||
|
||||
@ -139,6 +139,16 @@ class sudorule(LDAPObject):
|
||||
label=_('External User'),
|
||||
doc=_('External User the rule applies to'),
|
||||
),
|
||||
Str('ipasudorunasextuser?',
|
||||
cli_name='runasexternaluser',
|
||||
label=_('RunAs External User'),
|
||||
doc=_('External User the commands can run as'),
|
||||
),
|
||||
Str('ipasudorunasextgroup?',
|
||||
cli_name='runasexternalgroup',
|
||||
label=_('RunAs External Group'),
|
||||
doc=_('External Group the commands can run as'),
|
||||
),
|
||||
)
|
||||
|
||||
api.register(sudorule)
|
||||
@ -429,6 +439,32 @@ class sudorule_add_runasuser(LDAPAddMember):
|
||||
member_attributes = ['ipasudorunas']
|
||||
member_count_out = ('%i object added.', '%i objects added.')
|
||||
|
||||
def post_callback(self, ldap, completed, failed, dn, entry_attrs, *keys, **options):
|
||||
completed_external = 0
|
||||
# Sift through the user failures. We assume that these are all
|
||||
# users that aren't stored in IPA, aka external users.
|
||||
if 'ipasudorunas' in failed and 'user' in failed['ipasudorunas']:
|
||||
(dn, entry_attrs_) = ldap.get_entry(dn, ['ipasudorunasextuser'])
|
||||
members = entry_attrs.get('ipasudorunas', [])
|
||||
external_users = entry_attrs_.get('ipasudorunasextuser', [])
|
||||
failed_users = []
|
||||
for user in failed['ipasudorunas']['user']:
|
||||
username = user[0].lower()
|
||||
user_dn = self.api.Object['user'].get_dn(username)
|
||||
if username not in external_users and user_dn not in members:
|
||||
external_users.append(username)
|
||||
completed_external += 1
|
||||
else:
|
||||
failed_users.append(username)
|
||||
if completed_external:
|
||||
try:
|
||||
ldap.update_entry(dn, {'ipasudorunasextuser': external_users})
|
||||
except errors.EmptyModlist:
|
||||
pass
|
||||
failed['ipasudorunas']['user'] = failed_users
|
||||
entry_attrs['ipasudorunasextuser'] = external_users
|
||||
return (completed + completed_external, dn)
|
||||
|
||||
api.register(sudorule_add_runasuser)
|
||||
|
||||
|
||||
@ -439,6 +475,30 @@ class sudorule_remove_runasuser(LDAPRemoveMember):
|
||||
member_attributes = ['ipasudorunas']
|
||||
member_count_out = ('%i object removed.', '%i objects removed.')
|
||||
|
||||
def post_callback(self, ldap, completed, failed, dn, entry_attrs, *keys, **options):
|
||||
# Run through the user failures and gracefully remove any defined as
|
||||
# as an externaluser.
|
||||
if 'ipasudorunas' in failed and 'user' in failed['ipasudorunas']:
|
||||
(dn, entry_attrs) = ldap.get_entry(dn, ['ipasudorunasextuser'])
|
||||
external_users = entry_attrs.get('ipasudorunasextuser', [])
|
||||
failed_users = []
|
||||
completed_external = 0
|
||||
for user in failed['ipasudorunas']['user']:
|
||||
username = user[0].lower()
|
||||
if username in external_users:
|
||||
external_users.remove(username)
|
||||
completed_external += 1
|
||||
else:
|
||||
failed_users.append(username)
|
||||
if completed_external:
|
||||
try:
|
||||
ldap.update_entry(dn, {'ipasudorunasextuser': external_users})
|
||||
except errors.EmptyModlist:
|
||||
pass
|
||||
failed['ipasudorunas']['user'] = failed_users
|
||||
entry_attrs['ipasudorunasextuser'] = external_users
|
||||
return (completed + completed_external, dn)
|
||||
|
||||
api.register(sudorule_remove_runasuser)
|
||||
|
||||
|
||||
@ -449,6 +509,32 @@ class sudorule_add_runasgroup(LDAPAddMember):
|
||||
member_attributes = ['ipasudorunasgroup']
|
||||
member_count_out = ('%i object added.', '%i objects added.')
|
||||
|
||||
def post_callback(self, ldap, completed, failed, dn, entry_attrs, *keys, **options):
|
||||
completed_external = 0
|
||||
# Sift through the group failures. We assume that these are all
|
||||
# groups that aren't stored in IPA, aka external groups.
|
||||
if 'ipasudorunasgroup' in failed and 'group' in failed['ipasudorunasgroup']:
|
||||
(dn, entry_attrs_) = ldap.get_entry(dn, ['ipasudorunasextgroup'])
|
||||
members = entry_attrs.get('ipasudorunasgroup', [])
|
||||
external_groups = entry_attrs_.get('ipasudorunasextgroup', [])
|
||||
failed_groups = []
|
||||
for group in failed['ipasudorunasgroup']['group']:
|
||||
groupname = group[0].lower()
|
||||
group_dn = self.api.Object['group'].get_dn(groupname)
|
||||
if groupname not in external_groups and group_dn not in members:
|
||||
external_groups.append(groupname)
|
||||
completed_external += 1
|
||||
else:
|
||||
failed_groups.append(groupname)
|
||||
if completed_external:
|
||||
try:
|
||||
ldap.update_entry(dn, {'ipasudorunasextgroup': external_groups})
|
||||
except errors.EmptyModlist:
|
||||
pass
|
||||
failed['ipasudorunasgroup']['group'] = failed_groups
|
||||
entry_attrs['ipasudorunasextgroup'] = external_groups
|
||||
return (completed + completed_external, dn)
|
||||
|
||||
api.register(sudorule_add_runasgroup)
|
||||
|
||||
|
||||
@ -459,6 +545,30 @@ class sudorule_remove_runasgroup(LDAPRemoveMember):
|
||||
member_attributes = ['ipasudorunasgroup']
|
||||
member_count_out = ('%i object removed.', '%i objects removed.')
|
||||
|
||||
def post_callback(self, ldap, completed, failed, dn, entry_attrs, *keys, **options):
|
||||
# Run through the group failures and gracefully remove any defined as
|
||||
# as an external group.
|
||||
if 'ipasudorunasgroup' in failed and 'group' in failed['ipasudorunasgroup']:
|
||||
(dn, entry_attrs) = ldap.get_entry(dn, ['ipasudorunasextgroup'])
|
||||
external_groups = entry_attrs.get('ipasudorunasextgroup', [])
|
||||
failed_groups = []
|
||||
completed_external = 0
|
||||
for group in failed['ipasudorunasgroup']['group']:
|
||||
groupname = group[0].lower()
|
||||
if groupname in external_groups:
|
||||
external_groups.remove(groupname)
|
||||
completed_external += 1
|
||||
else:
|
||||
failed_groups.append(groupname)
|
||||
if completed_external:
|
||||
try:
|
||||
ldap.update_entry(dn, {'ipasudorunasextgroup': external_groups})
|
||||
except errors.EmptyModlist:
|
||||
pass
|
||||
failed['ipasudorunasgroup']['group'] = failed_groups
|
||||
entry_attrs['ipasudorunasextgroup'] = external_groups
|
||||
return (completed + completed_external, dn)
|
||||
|
||||
api.register(sudorule_remove_runasgroup)
|
||||
|
||||
|
||||
|
@ -38,6 +38,7 @@ class test_sudorule(XMLRPC_test):
|
||||
test_user = u'sudorule_test_user'
|
||||
test_external_user = u'external_test_user'
|
||||
test_group = u'sudorule_test_group'
|
||||
test_external_group = u'external_test_group'
|
||||
test_host = u'sudorule._test_host'
|
||||
test_external_host = u'external._test_host'
|
||||
test_hostgroup = u'sudorule_test_hostgroup'
|
||||
@ -264,6 +265,60 @@ class test_sudorule(XMLRPC_test):
|
||||
entry = ret['result']
|
||||
assert 'externaluser' not in entry
|
||||
|
||||
def test_a_sudorule_add_runasexternaluser(self):
|
||||
"""
|
||||
Test adding an external runasuser to Sudo rule using
|
||||
`xmlrpc.sudorule_add_runasuser`.
|
||||
"""
|
||||
ret = api.Command['sudorule_add_runasuser'](
|
||||
self.rule_name, user=self.test_external_user
|
||||
)
|
||||
assert ret['completed'] == 1
|
||||
failed = ret['failed']
|
||||
entry = ret['result']
|
||||
assert_attr_equal(entry, 'ipasudorunasextuser', self.test_external_user)
|
||||
|
||||
def test_b_sudorule_remove_runasexternaluser(self):
|
||||
"""
|
||||
Test removing an external runasuser from Sudo rule using
|
||||
`xmlrpc.sudorule_remove_runasuser'.
|
||||
"""
|
||||
ret = api.Command['sudorule_remove_runasuser'](
|
||||
self.rule_name, user=self.test_external_user
|
||||
)
|
||||
assert ret['completed'] == 1
|
||||
failed = ret['failed']
|
||||
entry = ret['result']
|
||||
assert 'ipasudorunasextuser' not in entry
|
||||
|
||||
def test_a_sudorule_add_runasexternalgroup(self):
|
||||
"""
|
||||
Test adding an external runasgroup to Sudo rule using
|
||||
`xmlrpc.sudorule_add_runasgroup`.
|
||||
"""
|
||||
ret = api.Command['sudorule_add_runasgroup'](
|
||||
self.rule_name, group=self.test_external_group
|
||||
)
|
||||
print ret
|
||||
assert ret['completed'] == 1
|
||||
failed = ret['failed']
|
||||
entry = ret['result']
|
||||
assert_attr_equal(entry, 'ipasudorunasextgroup', self.test_external_group)
|
||||
|
||||
def test_b_sudorule_remove_runasexternalgroup(self):
|
||||
"""
|
||||
Test removing an external runasgroup from Sudo rule using
|
||||
`xmlrpc.sudorule_remove_runasgroup'.
|
||||
"""
|
||||
ret = api.Command['sudorule_remove_runasgroup'](
|
||||
self.rule_name, group=self.test_external_group
|
||||
)
|
||||
print ret
|
||||
assert ret['completed'] == 1
|
||||
failed = ret['failed']
|
||||
entry = ret['result']
|
||||
assert 'ipasudorunasextgroup' not in entry
|
||||
|
||||
def test_a_sudorule_add_option(self):
|
||||
"""
|
||||
Test adding an option to Sudo rule using
|
||||
|
Loading…
Reference in New Issue
Block a user