On 16.10.2014 11:53, Jan Cholasta wrote:
Dne 16.10.2014 v 11:24 Petr Vobornik napsal(a):
On 16.10.2014 09:54, Jan Cholasta wrote:
Dne 13.10.2014 v 12:42 Petr Vobornik napsal(a):
On 8.10.2014 18:51, Petr Vobornik wrote:
On 1.10.2014 18:15, Petr Vobornik wrote:
Hello list,
Patch for: https://fedorahosted.org/freeipa/ticket/4419
New revisions of 761 and 763 with updated API and ACIs:
ipa host-allow-operation HOSTNAME retrieve-keytab --users=STR --groups
STR
ipa host-disallow-operation HOSTNAME retrieve-keytab --users=STR
--groups STR
ipa host-allow-operation HOSTNAME create-keytab --users=STR
--groups STR
ipa host-disallow-operation HOSTNAME create-keytab --users=STR
--groups STR
ipa service-allow-operation PRINCIPAL retrieve-keytab --users=STR
--groups STR
ipa service-disallow-operation PRINCIPAL retrieve-keytab
--users=STR
--groups STR
ipa service-allow-operation PRINCIPAL create-keytab --users=STR
--groups STR
ipa service-disallow-operation PRINCIPAL create-keytab --users=STR
--groups STR
ACIs are targeted to specific operations by including subtypes.
patch #761 rebased because of VERSION bump
Since we are apparently not going to treat ipaAllowedToPerform as a
member attribute, you should remove reference to it from
attribute_members and relationships attributes of service and host.
I still think of it a as member attribute, at least internally.
Given the implementation, I see you can't remove it from
attribute_members, but it should be removed from relationships nonetheless.
affected parts of relationships removed
What's up with ipaallowedtoperform_subtypes_map? Why rename the
operations?
It's not renaming. It's a change of internal raw LDAP value into
self-describing name consistent with terminology of ipa-getkeytab
OK, you are obviously not responsible for this mess, so let's go with it.
You probably don't want to hardcode 'ipaallowedtoperform_read_keys' in
rename_ipaallowedtoperform_to_ldap().
Fixed, but it doesn't make much difference given that the method has
only one purpose.
Sorry, I missed the comment at the beginning of service_allow_operation,
it indeed does not make any difference. (I can't say I'm a fan of such
ugly hacks though.)
Why do you override get_args() in service_{,dis}allow_operation instead
of overriding takes_args?
Fixed
I'm not particularly happy about the '_subtype' option bussiness, but at
least it's not invasive, so I guess it's OK.
Note that I still think this API sucks and we should instead go with the
generic member-like attribute approach, or take our time to design it
properly so that it fits in the framework (no time in 4.1) instead of
making it a hacky Franken-API like it is now.
--
Petr Vobornik
From 7c3aed88ffd9e03158eb1c67d5b56c969c0ebee5 Mon Sep 17 00:00:00 2001
From: Petr Vobornik <[email protected]>
Date: Thu, 2 Oct 2014 16:57:08 +0200
Subject: [PATCH] keytab manipulation permission management
Adds new API:
ipa host-allow-operation HOSTNAME retrieve-keytab --users=STR --groups STR
ipa host-disallow-operation HOSTNAME retrieve-keytab --users=STR --groups STR
ipa host-allow-operation HOSTNAME create-keytab --users=STR --groups STR
ipa host-disallow-operation HOSTNAME create-keytab --users=STR --groups STR
ipa service-allow-operation PRINCIPAL retrieve-keytab --users=STR --groups STR
ipa service-disallow-operation PRINCIPAL retrieve-keytab --users=STR --groups STR
ipa service-allow-operation PRINCIPAL create-keytab --users=STR --groups STR
ipa service-disallow-operation PRINCIPAL create-keytab --users=STR --groups STR
these methods add or remove user or group DNs in `ipaallowedtoperform` attr with
`read_keys` and `write_keys` subtypes.
service|host-mod|show outputs these attrs as:
Users allowed to retrieve keytab: user1
Groups allowed to retrieve keytab: group1
Users allowed to create keytab: user1
Groups allowed to create keytab: group1
Adding of object class is implemented as a reusable method since this code is
used on many places and most likely will be also used in new features. Older
code may be refactored later.
https://fedorahosted.org/freeipa/ticket/4419
---
ACI.txt | 4 ++
API.txt | 52 +++++++++++++++++++
VERSION | 4 +-
ipalib/plugins/baseldap.py | 17 ++++++
ipalib/plugins/host.py | 49 ++++++++++++++++--
ipalib/plugins/service.py | 125 +++++++++++++++++++++++++++++++++++++++++++--
6 files changed, 240 insertions(+), 11 deletions(-)
diff --git a/ACI.txt b/ACI.txt
index bc031ff1f24b9e9f08fe9ba78e5a262162f32cef..6fc88233e340d6eabe4ad819176e3cfa98d8c9ce 100644
--- a/ACI.txt
+++ b/ACI.txt
@@ -95,6 +95,8 @@ aci: (targetattr = "userpassword")(targetfilter = "(objectclass=ipahost)")(versi
dn: cn=computers,cn=accounts,dc=ipa,dc=example
aci: (targetattr = "krblastpwdchange || krbprincipalkey")(targetfilter = "(objectclass=ipahost)")(version 3.0;acl "permission:System: Manage Host Keytab";allow (write) groupdn = "ldap:///cn=System: Manage Host Keytab,cn=permissions,cn=pbac,dc=ipa,dc=example";)
dn: cn=computers,cn=accounts,dc=ipa,dc=example
+aci: (targetattr = "createtimestamp || entryusn || ipaallowedtoperform;read_keys || ipaallowedtoperform;write_keys || modifytimestamp || objectclass")(targetfilter = "(objectclass=ipahost)")(version 3.0;acl "permission:System: Manage Host Keytab Permissions";allow (compare,read,search,write) groupdn = "ldap:///cn=System: Manage Host Keytab Permissions,cn=permissions,cn=pbac,dc=ipa,dc=example";)
+dn: cn=computers,cn=accounts,dc=ipa,dc=example
aci: (targetattr = "ipasshpubkey")(targetfilter = "(objectclass=ipahost)")(version 3.0;acl "permission:System: Manage Host SSH Public Keys";allow (write) groupdn = "ldap:///cn=System: Manage Host SSH Public Keys,cn=permissions,cn=pbac,dc=ipa,dc=example";)
dn: cn=computers,cn=accounts,dc=ipa,dc=example
aci: (targetattr = "description || ipaassignedidview || l || macaddress || nshardwareplatform || nshostlocation || nsosversion || userclass")(targetfilter = "(objectclass=ipahost)")(version 3.0;acl "permission:System: Modify Hosts";allow (write) groupdn = "ldap:///cn=System: Modify Hosts,cn=permissions,cn=pbac,dc=ipa,dc=example";)
@@ -193,6 +195,8 @@ aci: (targetfilter = "(objectclass=ipaservice)")(version 3.0;acl "permission:Sys
dn: cn=services,cn=accounts,dc=ipa,dc=example
aci: (targetattr = "krblastpwdchange || krbprincipalkey")(targetfilter = "(objectclass=ipaservice)")(version 3.0;acl "permission:System: Manage Service Keytab";allow (write) groupdn = "ldap:///cn=System: Manage Service Keytab,cn=permissions,cn=pbac,dc=ipa,dc=example";)
dn: cn=services,cn=accounts,dc=ipa,dc=example
+aci: (targetattr = "createtimestamp || entryusn || ipaallowedtoperform;read_keys || ipaallowedtoperform;write_keys || modifytimestamp || objectclass")(targetfilter = "(objectclass=ipaservice)")(version 3.0;acl "permission:System: Manage Service Keytab Permissions";allow (compare,read,search,write) groupdn = "ldap:///cn=System: Manage Service Keytab Permissions,cn=permissions,cn=pbac,dc=ipa,dc=example";)
+dn: cn=services,cn=accounts,dc=ipa,dc=example
aci: (targetattr = "usercertificate")(targetfilter = "(objectclass=ipaservice)")(version 3.0;acl "permission:System: Modify Services";allow (write) groupdn = "ldap:///cn=System: Modify Services,cn=permissions,cn=pbac,dc=ipa,dc=example";)
dn: cn=services,cn=accounts,dc=ipa,dc=example
aci: (targetattr = "createtimestamp || entryusn || ipakrbauthzdata || ipakrbprincipalalias || ipauniqueid || krbcanonicalname || krblastpwdchange || krbobjectreferences || krbpasswordexpiration || krbprincipalaliases || krbprincipalexpiration || krbprincipalname || managedby || memberof || modifytimestamp || objectclass || usercertificate")(targetfilter = "(objectclass=ipaservice)")(version 3.0;acl "permission:System: Read Services";allow (compare,read,search) userdn = "ldap:///all";)
diff --git a/API.txt b/API.txt
index 1af78509732b13eec07208114cea00e56c1059b4..0dbc7b2c8d4fb5d337d4436395f2213713c4d019 100644
--- a/API.txt
+++ b/API.txt
@@ -1819,6 +1819,19 @@ option: Str('version?', exclude='webui')
output: Output('completed', <type 'int'>, None)
output: Output('failed', <type 'dict'>, None)
output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None))
+command: host_allow_operation
+args: 2,6,3
+arg: Str('fqdn', attribute=True, cli_name='hostname', multivalue=False, primary_key=True, query=True, required=True)
+arg: StrEnum('operation', values=(u'retrieve-keytab', u'create-keytab'))
+option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
+option: Str('group*', alwaysask=True, cli_name='groups', csv=True)
+option: Flag('no_members', autofill=True, default=False, exclude='webui')
+option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui')
+option: Str('user*', alwaysask=True, cli_name='users', csv=True)
+option: Str('version?', exclude='webui')
+output: Output('completed', <type 'int'>, None)
+output: Output('failed', <type 'dict'>, None)
+output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None))
command: host_del
args: 1,3,3
arg: Str('fqdn', attribute=True, cli_name='hostname', multivalue=True, primary_key=True, query=True, required=True)
@@ -1835,6 +1848,19 @@ option: Str('version?', exclude='webui')
output: Output('result', <type 'bool'>, None)
output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
output: PrimaryKey('value', None, None)
+command: host_disallow_operation
+args: 2,6,3
+arg: Str('fqdn', attribute=True, cli_name='hostname', multivalue=False, primary_key=True, query=True, required=True)
+arg: StrEnum('operation', values=(u'retrieve-keytab', u'create-keytab'))
+option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
+option: Str('group*', alwaysask=True, cli_name='groups', csv=True)
+option: Flag('no_members', autofill=True, default=False, exclude='webui')
+option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui')
+option: Str('user*', alwaysask=True, cli_name='users', csv=True)
+option: Str('version?', exclude='webui')
+output: Output('completed', <type 'int'>, None)
+output: Output('failed', <type 'dict'>, None)
+output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None))
command: host_find
args: 1,34,4
arg: Str('criteria?', noextrawhitespace=False)
@@ -3473,6 +3499,19 @@ option: Str('version?', exclude='webui')
output: Output('completed', <type 'int'>, None)
output: Output('failed', <type 'dict'>, None)
output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None))
+command: service_allow_operation
+args: 2,6,3
+arg: Str('krbprincipalname', attribute=True, cli_name='principal', multivalue=False, primary_key=True, query=True, required=True)
+arg: StrEnum('operation', values=(u'retrieve-keytab', u'create-keytab'))
+option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
+option: Str('group*', alwaysask=True, cli_name='groups', csv=True)
+option: Flag('no_members', autofill=True, default=False, exclude='webui')
+option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui')
+option: Str('user*', alwaysask=True, cli_name='users', csv=True)
+option: Str('version?', exclude='webui')
+output: Output('completed', <type 'int'>, None)
+output: Output('failed', <type 'dict'>, None)
+output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None))
command: service_del
args: 1,2,3
arg: Str('krbprincipalname', attribute=True, cli_name='principal', multivalue=True, primary_key=True, query=True, required=True)
@@ -3488,6 +3527,19 @@ option: Str('version?', exclude='webui')
output: Output('result', <type 'bool'>, None)
output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
output: PrimaryKey('value', None, None)
+command: service_disallow_operation
+args: 2,6,3
+arg: Str('krbprincipalname', attribute=True, cli_name='principal', multivalue=False, primary_key=True, query=True, required=True)
+arg: StrEnum('operation', values=(u'retrieve-keytab', u'create-keytab'))
+option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
+option: Str('group*', alwaysask=True, cli_name='groups', csv=True)
+option: Flag('no_members', autofill=True, default=False, exclude='webui')
+option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui')
+option: Str('user*', alwaysask=True, cli_name='users', csv=True)
+option: Str('version?', exclude='webui')
+output: Output('completed', <type 'int'>, None)
+output: Output('failed', <type 'dict'>, None)
+output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None))
command: service_find
args: 1,11,4
arg: Str('criteria?', noextrawhitespace=False)
diff --git a/VERSION b/VERSION
index 03f713bd9d7e245eb4fe7fd36a5ae62dc49be266..b1b38544bd48bc5e559ec0a0aef390d4a31af60f 100644
--- a/VERSION
+++ b/VERSION
@@ -90,5 +90,5 @@ IPA_DATA_VERSION=20100614120000
# #
########################################################
IPA_API_VERSION_MAJOR=2
-IPA_API_VERSION_MINOR=105
-# Last change: abbra - ID views attributes
+IPA_API_VERSION_MINOR=106
+# Last change: pvoborni - manage authorization of keytab operations
diff --git a/ipalib/plugins/baseldap.py b/ipalib/plugins/baseldap.py
index e589a53219766a2aa41bbb4abef7fc3a12fcc267..375441c0fd55efe70d5a6f5bed6700e618874082 100644
--- a/ipalib/plugins/baseldap.py
+++ b/ipalib/plugins/baseldap.py
@@ -494,6 +494,23 @@ def host_is_master(ldap, fqdn):
return
+def add_missing_object_class(ldap, objectclass, dn, entry_attrs=None, update=True):
+ """
+ Add object class if missing into entry. Fetches entry if not passed. Updates
+ the entry by default.
+
+ Returns the entry
+ """
+
+ if not entry_attrs:
+ entry_attrs = ldap.get_entry(dn, ['objectclass'])
+ if (objectclass.lower() not in (o.lower() for o in entry_attrs['objectclass'])):
+ entry_attrs['objectclass'].append(objectclass)
+ if update:
+ ldap.update_entry(entry_attrs)
+ return entry_attrs
+
+
class LDAPObject(Object):
"""
Object representing a LDAP entry.
diff --git a/ipalib/plugins/host.py b/ipalib/plugins/host.py
index bbee09395dc55730d400944729a5bed48670f785..ee6ebc7a6cfdef193dc19d6e274d760829c7bae5 100644
--- a/ipalib/plugins/host.py
+++ b/ipalib/plugins/host.py
@@ -28,10 +28,12 @@ from ipalib.plugins.baseldap import (LDAPQuery, LDAPObject, LDAPCreate,
LDAPDelete, LDAPUpdate, LDAPSearch,
LDAPRetrieve, LDAPAddMember,
LDAPRemoveMember, host_is_master,
- pkey_to_value)
+ pkey_to_value, add_missing_object_class)
from ipalib.plugins.service import (split_principal, validate_certificate,
set_certificate_attrs, ticket_flags_params, update_krbticketflags,
- set_kerberos_attrs)
+ set_kerberos_attrs, rename_ipaallowedtoperform_from_ldap,
+ rename_ipaallowedtoperform_to_ldap, service_allow_operation,
+ service_disallow_operation)
from ipalib.plugins.dns import (dns_container_exists, _record_types,
add_records_for_host_validation, add_records_for_host,
get_reverse_zone)
@@ -102,6 +104,9 @@ EXAMPLES:
""") + _("""
Add a host that can manage this host's keytab and certificate:
ipa host-add-managedby --hosts=test2 test
+""") + _("""
+ Allow user to create keytab:
+ ipa host-allow-operation test2 create-keytab --users=tuser1
""")
register = Registry()
@@ -201,6 +206,18 @@ host_output_params = (
Str('sshpubkeyfp*',
label=_('SSH public key fingerprint'),
),
+ Str('ipaallowedtoperform_read_keys_user',
+ label=_('Users allowed to retrieve keytab'),
+ ),
+ Str('ipaallowedtoperform_read_keys_group',
+ label=_('Groups allowed to retrieve keytab'),
+ ),
+ Str('ipaallowedtoperform_write_keys_user',
+ label=_('Users allowed to create keytab'),
+ ),
+ Str('ipaallowedtoperform_write_keys_group',
+ label=_('Groups allowed to create keytab'),
+ ),
)
@@ -241,17 +258,18 @@ class host(LDAPObject):
object_name = _('host')
object_name_plural = _('hosts')
object_class = ['ipaobject', 'nshost', 'ipahost', 'pkiuser', 'ipaservice']
+ possible_objectclasses = ['ipaallowedoperations']
permission_filter_objectclasses = ['ipahost']
# object_class_config = 'ipahostobjectclasses'
search_attributes = [
'fqdn', 'description', 'l', 'nshostlocation', 'krbprincipalname',
- 'nshardwareplatform', 'nsosversion', 'managedby'
+ 'nshardwareplatform', 'nsosversion', 'managedby', 'ipaallowedtoperform'
]
default_attributes = [
'fqdn', 'description', 'l', 'nshostlocation', 'krbprincipalname',
'nshardwareplatform', 'nsosversion', 'usercertificate', 'memberof',
'managedby', 'memberindirect', 'memberofindirect', 'macaddress',
- 'userclass'
+ 'userclass', 'ipaallowedtoperform'
]
uuid_attribute = 'ipauniqueid'
attribute_members = {
@@ -261,6 +279,8 @@ class host(LDAPObject):
'managing': ['host'],
'memberofindirect': ['hostgroup', 'netgroup', 'role', 'hbacrule',
'sudorule'],
+ 'ipaallowedtoperform_read_keys': ['user', 'group'],
+ 'ipaallowedtoperform_write_keys': ['user', 'group'],
}
bindable = True
relationships = {
@@ -344,6 +364,14 @@ class host(LDAPObject):
],
'default_privileges': {'Host Administrators', 'Host Enrollment'},
},
+ 'System: Manage Host Keytab Permissions': {
+ 'ipapermright': {'read', 'search', 'compare', 'write'},
+ 'ipapermdefaultattr': {
+ 'ipaallowedtoperform;write_keys',
+ 'ipaallowedtoperform;read_keys', 'objectclass'
+ },
+ 'default_privileges': {'Host Administrators'},
+ },
'System: Modify Hosts': {
'ipapermright': {'write'},
'ipapermdefaultattr': {
@@ -629,6 +657,7 @@ class host_add(LDAPCreate):
)
set_certificate_attrs(entry_attrs)
set_kerberos_attrs(entry_attrs, options)
+ rename_ipaallowedtoperform_from_ldap(entry_attrs, options)
if options.get('all', False):
entry_attrs['managing'] = self.obj.get_managed_hosts(dn)
@@ -888,6 +917,7 @@ class host_mod(LDAPUpdate):
entry_attrs['randompassword'] = unicode(getattr(context, 'randompassword'))
set_certificate_attrs(entry_attrs)
set_kerberos_attrs(entry_attrs, options)
+ rename_ipaallowedtoperform_from_ldap(entry_attrs, options)
self.obj.get_password_attributes(ldap, dn, entry_attrs)
if entry_attrs['has_password']:
# If an OTP is set there is no keytab, at least not one
@@ -974,6 +1004,7 @@ class host_find(LDAPSearch):
for entry_attrs in entries:
set_certificate_attrs(entry_attrs)
set_kerberos_attrs(entry_attrs, options)
+ rename_ipaallowedtoperform_from_ldap(entry_attrs, options)
self.obj.get_password_attributes(ldap, entry_attrs.dn, entry_attrs)
self.obj.suppress_netgroup_memberof(ldap, entry_attrs)
if entry_attrs['has_password']:
@@ -1012,6 +1043,7 @@ class host_show(LDAPRetrieve):
set_certificate_attrs(entry_attrs)
set_kerberos_attrs(entry_attrs, options)
+ rename_ipaallowedtoperform_from_ldap(entry_attrs, options)
if options.get('all', False):
entry_attrs['managing'] = self.obj.get_managed_hosts(dn)
@@ -1159,3 +1191,12 @@ class host_remove_managedby(LDAPRemoveMember):
self.obj.suppress_netgroup_memberof(ldap, entry_attrs)
return (completed, dn)
+
+@register()
+class host_allow_operation(service_allow_operation):
+ __doc__ = _('Allow users or groups to perform operation connected with this host.')
+
+
+@register()
+class host_disallow_operation(service_disallow_operation):
+ __doc__ = _('Disallow users or groups to perform operation connected with this host.')
diff --git a/ipalib/plugins/service.py b/ipalib/plugins/service.py
index 3ca5066f300a004c993660e0a5e220c364e38cbf..b3fd374a4841f6a62a04b74967f6d05c80be66a3 100644
--- a/ipalib/plugins/service.py
+++ b/ipalib/plugins/service.py
@@ -86,7 +86,10 @@ EXAMPLES:
Request a certificate for an IPA service:
ipa cert-request --principal=HTTP/web.example.com example.csr
-
+""") + _("""
+ Allow user to create keytab:
+ ipa service-allow-operation HTTP/web.example.com create-keytab --users=tuser1
+""") + _("""
Generate and retrieve a keytab for an IPA service:
ipa-getkeytab -s ipa.example.com -p HTTP/web.example.com -k /etc/httpd/httpd.keytab
@@ -127,7 +130,19 @@ output_params = (
),
Str('revocation_reason?',
label=_('Revocation reason'),
- )
+ ),
+ Str('ipaallowedtoperform_read_keys_user',
+ label=_('Users allowed to retrieve keytab'),
+ ),
+ Str('ipaallowedtoperform_read_keys_group',
+ label=_('Groups allowed to retrieve keytab'),
+ ),
+ Str('ipaallowedtoperform_write_keys_user',
+ label=_('Users allowed to create keytab'),
+ ),
+ Str('ipaallowedtoperform_write_keys_group',
+ label=_('Groups allowed to create keytab'),
+ ),
)
ticket_flags_params = (
@@ -152,6 +167,11 @@ _ticket_flags_map = {
_ticket_flags_default = _ticket_flags_map['ipakrbrequirespreauth']
+ipaallowedtoperform_subtypes_map = {
+ u'retrieve-keytab': 'read_keys',
+ u'create-keytab': 'write_keys',
+}
+
def split_principal(principal):
service = hostname = realm = None
@@ -290,6 +310,22 @@ def set_kerberos_attrs(entry_attrs, options):
if name in options or all_opt:
entry_attrs[name] = bool(ticket_flags & value)
+def rename_ipaallowedtoperform_from_ldap(entry_attrs, options):
+ if options.get('raw', False):
+ return
+
+ for subtype in (ipaallowedtoperform_subtypes_map.values()):
+ name = 'ipaallowedtoperform;%s' % subtype
+ if name in entry_attrs:
+ new_name = 'ipaallowedtoperform_%s' % subtype
+ entry_attrs[new_name] = entry_attrs.pop(name)
+
+def rename_ipaallowedtoperform_to_ldap(entry_attrs, member_attr, subtype):
+ if member_attr in entry_attrs:
+ new_name = 'ipaallowedtoperform;%s' % subtype
+ entry_attrs[new_name] = entry_attrs.pop(member_attr)
+
+
@register()
class service(LDAPObject):
"""
@@ -302,15 +338,18 @@ class service(LDAPObject):
'krbprincipal', 'krbprincipalaux', 'krbticketpolicyaux', 'ipaobject',
'ipaservice', 'pkiuser'
]
- possible_objectclasses = ['ipakrbprincipal']
+ possible_objectclasses = ['ipakrbprincipal', 'ipaallowedoperations']
permission_filter_objectclasses = ['ipaservice']
- search_attributes = ['krbprincipalname', 'managedby', 'ipakrbauthzdata']
+ search_attributes = ['krbprincipalname', 'managedby', 'ipakrbauthzdata',
+ 'ipaallowedtoperform']
default_attributes = ['krbprincipalname', 'usercertificate', 'managedby',
- 'ipakrbauthzdata', 'memberof']
+ 'ipakrbauthzdata', 'memberof', 'ipaallowedtoperform']
uuid_attribute = 'ipauniqueid'
attribute_members = {
'managedby': ['host'],
'memberof': ['role'],
+ 'ipaallowedtoperform_read_keys': ['user', 'group'],
+ 'ipaallowedtoperform_write_keys': ['user', 'group'],
}
bindable = True
relationships = {
@@ -346,6 +385,14 @@ class service(LDAPObject):
],
'default_privileges': {'Service Administrators', 'Host Administrators'},
},
+ 'System: Manage Service Keytab Permissions': {
+ 'ipapermright': {'read', 'search', 'compare', 'write'},
+ 'ipapermdefaultattr': {
+ 'ipaallowedtoperform;write_keys',
+ 'ipaallowedtoperform;read_keys', 'objectclass'
+ },
+ 'default_privileges': {'Service Administrators', 'Host Administrators'},
+ },
'System: Modify Services': {
'ipapermright': {'write'},
'ipapermdefaultattr': {'usercertificate'},
@@ -469,6 +516,7 @@ class service_add(LDAPCreate):
def post_callback(self, ldap, dn, entry_attrs, *keys, **options):
set_kerberos_attrs(entry_attrs, options)
+ rename_ipaallowedtoperform_from_ldap(entry_attrs, options)
return dn
@@ -561,6 +609,7 @@ class service_mod(LDAPUpdate):
assert isinstance(dn, DN)
set_certificate_attrs(entry_attrs)
set_kerberos_attrs(entry_attrs, options)
+ rename_ipaallowedtoperform_from_ldap(entry_attrs, options)
return dn
@@ -598,6 +647,7 @@ class service_find(LDAPSearch):
self.obj.get_password_attributes(ldap, entry_attrs.dn, entry_attrs)
set_certificate_attrs(entry_attrs)
set_kerberos_attrs(entry_attrs, options)
+ rename_ipaallowedtoperform_from_ldap(entry_attrs, options)
return truncated
@@ -620,6 +670,7 @@ class service_show(LDAPRetrieve):
set_certificate_attrs(entry_attrs)
set_kerberos_attrs(entry_attrs, options)
+ rename_ipaallowedtoperform_from_ldap(entry_attrs, options)
return dn
@@ -654,6 +705,70 @@ class service_remove_host(LDAPRemoveMember):
has_output_params = LDAPRemoveMember.has_output_params + output_params
+@register()
+class service_allow_operation(LDAPAddMember):
+ __doc__ = _('Allow users or groups to perform operation connected with this service.')
+
+ # We need to choose existing attribute_member to properly generate options
+ # for users and groups. The subtype is removed/modified in pre and post
+ # callback according to specified operation.
+ member_attributes = ['ipaallowedtoperform_read_keys']
+ has_output_params = LDAPAddMember.has_output_params + output_params
+ takes_args = (
+ StrEnum(
+ 'operation',
+ label=_('Operation'),
+ doc=_('Operation to disallow'),
+ values=tuple(ipaallowedtoperform_subtypes_map.keys())
+ )
+ )
+
+ def pre_callback(self, ldap, dn, found, not_found, *keys, **options):
+ attr = self.member_attributes[0]
+ rename_ipaallowedtoperform_to_ldap(found, attr, options['_subtype'])
+ rename_ipaallowedtoperform_to_ldap(not_found, attr, options['_subtype'])
+ add_missing_object_class(ldap, u'ipaallowedoperations', dn)
+ return dn
+
+ def post_callback(self, ldap, completed, failed, dn, entry_attrs, *keys, **options):
+ rename_ipaallowedtoperform_from_ldap(entry_attrs, options)
+ rename_ipaallowedtoperform_from_ldap(failed, options)
+ return (completed, dn)
+
+ def execute(self, *keys, **options):
+ options['_subtype'] = ipaallowedtoperform_subtypes_map[keys[-1]]
+ return super(service_allow_operation, self).execute(*keys[:-1], **options)
+
+
+@register()
+class service_disallow_operation(LDAPRemoveMember):
+ __doc__ = _('Disallow users or groups to perform operation connected with this service.')
+ member_attributes = ['ipaallowedtoperform_read_keys']
+ has_output_params = LDAPRemoveMember.has_output_params + output_params
+ takes_args = (
+ StrEnum(
+ 'operation',
+ label=_('Operation'),
+ doc=_('Operation to disallow'),
+ values=tuple(ipaallowedtoperform_subtypes_map.keys())
+ )
+ )
+
+ def pre_callback(self, ldap, dn, found, not_found, *keys, **options):
+ attr = self.member_attributes[0]
+ rename_ipaallowedtoperform_to_ldap(found, attr, options['_subtype'])
+ rename_ipaallowedtoperform_to_ldap(not_found, attr, options['_subtype'])
+ return dn
+
+ def post_callback(self, ldap, completed, failed, dn, entry_attrs, *keys, **options):
+ rename_ipaallowedtoperform_from_ldap(entry_attrs, options)
+ rename_ipaallowedtoperform_from_ldap(failed, options)
+ return (completed, dn)
+
+ def execute(self, *keys, **options):
+ options['_subtype'] = ipaallowedtoperform_subtypes_map[keys[-1]]
+ return super(service_disallow_operation, self).execute(*keys[:-1], **options)
+
@register()
class service_disable(LDAPQuery):
--
1.9.3
_______________________________________________
Freeipa-devel mailing list
[email protected]
https://www.redhat.com/mailman/listinfo/freeipa-devel