On 04/27/2016 03:34 PM, Lukáš Hellebrandt wrote: > SSSD: https://github.com/lhellebr/sssd/commits/url_in_hbac > Apache module: https://github.com/lhellebr/mod_hbacauthz_pam > FreeIPA: http://pastebin.com/X6H9BTwk > > On 04/26/2016 03:56 PM, Petr Spacek wrote: >> On 26.4.2016 15:16, Jan Pazdziora wrote: >>> On Tue, Apr 26, 2016 at 02:16:54PM +0200, Petr Spacek wrote: >>>>>> >>>>>> * For backwards compatibility, lack of URI in request means any URI is >>>>>> matched (as described in the design document). Is it a good idea? Any >>>>>> other solution? >>>>> >>>>> For other attributes in HBAC rules, the lack of a value means nothing is >>>>> matched. To match anything, you have to set "${attribute}category" to >>>>> "all". I >>>>> would prefer if URI matching was consistent with this, if it's possible. >>>> >>>> My understanding is that requests lacking URI parameter should not match >>>> any >>>> HBAC rules with non-empty URI. This will be backwards compatible because >>>> old >>>> clients will simply ignore new rules which cannot be evaluated properly >>>> anyway >>>> (for lack of information in client's request). >>> >>> The problem is that old clients will not ack for the new attributes >>> (they have no idea they should ask for them), so they will only see >>> parts of the HBAC rules. >>> >>> So the question is -- what is the correct way to make sure that old >>> clients (that would not ask for the new attributes) are not served >>> any rules that have those new attributes set? >>> >>>>> BTW what is the reason to split URIs into separate fields? If it's just >>>>> case >>>>> sensitivity, I would like to point out that you can switch case >>>>> sensitivity on >>>>> and off in the middle of a Perl regex using "(?i)" and "(?-i)". >>>> >>>> Personally I would rather see host+scheme+port split into separate >>>> attributes. >>>> That would allow reporting like 'give me all rules for FTP' etc. without >>>> substring magic. >>>> >>>> And yes, I agree with Honza that multiple values should be evaluated as >>>> logical OR. >>>> >>>> E.g. >>>> >>>> schemes: {http, https, ftp, ftps} >>>> URI: /home/pspacek >>>> host: any >>>> allow: pspacek >>>> should grant user pspacek access to directory /home/pspacek on any host as >>>> long as the scheme is http/https/ftp/ftps. >>> >>> So you propose cartesian product of the schemes and URI attributes >>> to be used? >> >> Yes. >> >> >> Before we can discuss this further we need to see current LDAP schema and >> code. Lukas, please share the code with us. >> > >
Added a patch for backwards compatibility using different objectClass for rules containing some of the new attributes: SSSD: https://github.com/lhellebr/sssd/commits/url_in_hbac FreeIPA: attached patch file (works together with the previously submitted patch) -- Lukas Hellebrandt Associate Quality Engineer lhell...@redhat.com
From 5306556007a2448a8790f963abd52c6b89233605 Mon Sep 17 00:00:00 2001 From: Lukas Hellebrandt <lhell...@redhat.com> Date: Wed, 4 May 2016 18:33:27 +0200 Subject: [PATCH] Use new objectClass for backwards compatibility --- ACI.txt | 10 +++++----- Makefile | 2 +- install/share/60basev2.ldif | 1 + ipalib/plugins/hbacrule.py | 25 +++++++++++++++++++++---- 4 files changed, 28 insertions(+), 10 deletions(-) diff --git a/ACI.txt b/ACI.txt index 39f331264e3d724bae7d47a3bcbc9e42da93bbcd..419b90d2251086bf0b47f994041cc4ac79842214 100644 --- a/ACI.txt +++ b/ACI.txt @@ -85,15 +85,15 @@ aci: (targetattr = "businesscategory || cn || createtimestamp || description || dn: cn=groups,cn=accounts,dc=ipa,dc=example aci: (targetfilter = "(|(objectclass=ipausergroup)(objectclass=posixgroup))")(version 3.0;acl "permission:System: Remove Groups";allow (delete) groupdn = "ldap:///cn=System: Remove Groups,cn=permissions,cn=pbac,dc=ipa,dc=example";) dn: cn=hbac,dc=ipa,dc=example -aci: (targetfilter = "(objectclass=ipahbacrule)")(version 3.0;acl "permission:System: Add HBAC Rule";allow (add) groupdn = "ldap:///cn=System: Add HBAC Rule,cn=permissions,cn=pbac,dc=ipa,dc=example";) +aci: (targetfilter = "(|(objectclass=ipahbacrule)(objectclass=ipahbacruleuri))")(version 3.0;acl "permission:System: Add HBAC Rule";allow (add) groupdn = "ldap:///cn=System: Add HBAC Rule,cn=permissions,cn=pbac,dc=ipa,dc=example";) dn: cn=hbac,dc=ipa,dc=example -aci: (targetfilter = "(objectclass=ipahbacrule)")(version 3.0;acl "permission:System: Delete HBAC Rule";allow (delete) groupdn = "ldap:///cn=System: Delete HBAC Rule,cn=permissions,cn=pbac,dc=ipa,dc=example";) +aci: (targetfilter = "(|(objectclass=ipahbacrule)(objectclass=ipahbacruleuri))")(version 3.0;acl "permission:System: Delete HBAC Rule";allow (delete) groupdn = "ldap:///cn=System: Delete HBAC Rule,cn=permissions,cn=pbac,dc=ipa,dc=example";) dn: cn=hbac,dc=ipa,dc=example -aci: (targetattr = "externalhost || memberhost || memberservice || memberuser")(targetfilter = "(objectclass=ipahbacrule)")(version 3.0;acl "permission:System: Manage HBAC Rule Membership";allow (write) groupdn = "ldap:///cn=System: Manage HBAC Rule Membership,cn=permissions,cn=pbac,dc=ipa,dc=example";) +aci: (targetattr = "externalhost || memberhost || memberservice || memberuser")(targetfilter = "(|(objectclass=ipahbacrule)(objectclass=ipahbacruleuri))")(version 3.0;acl "permission:System: Manage HBAC Rule Membership";allow (write) groupdn = "ldap:///cn=System: Manage HBAC Rule Membership,cn=permissions,cn=pbac,dc=ipa,dc=example";) dn: cn=hbac,dc=ipa,dc=example -aci: (targetattr = "accessruletype || accesstime || cn || description || hostcategory || ipaenabledflag || servicecategory || sourcehost || sourcehostcategory || usercategory")(targetfilter = "(objectclass=ipahbacrule)")(version 3.0;acl "permission:System: Modify HBAC Rule";allow (write) groupdn = "ldap:///cn=System: Modify HBAC Rule,cn=permissions,cn=pbac,dc=ipa,dc=example";) +aci: (targetattr = "accessruletype || accesstime || cn || description || hostcategory || ipaenabledflag || servicecategory || sourcehost || sourcehostcategory || usercategory")(targetfilter = "(|(objectclass=ipahbacrule)(objectclass=ipahbacruleuri))")(version 3.0;acl "permission:System: Modify HBAC Rule";allow (write) groupdn = "ldap:///cn=System: Modify HBAC Rule,cn=permissions,cn=pbac,dc=ipa,dc=example";) dn: cn=hbac,dc=ipa,dc=example -aci: (targetattr = "accessruletype || accesstime || cn || createtimestamp || description || entryusn || externalhost || hostcategory || ipaenabledflag || ipauniqueid || member || memberhost || memberservice || memberuser || modifytimestamp || objectclass || schemeandhost || servicecategory || sourcehost || sourcehostcategory || url || usercategory")(targetfilter = "(objectclass=ipahbacrule)")(version 3.0;acl "permission:System: Read HBAC Rules";allow (compare,read,search) userdn = "ldap:///all";) +aci: (targetattr = "accessruletype || accesstime || cn || createtimestamp || description || entryusn || externalhost || hostcategory || ipaenabledflag || ipauniqueid || member || memberhost || memberservice || memberuser || modifytimestamp || objectclass || schemeandhost || servicecategory || sourcehost || sourcehostcategory || url || usercategory")(targetfilter = "(|(objectclass=ipahbacrule)(objectclass=ipahbacruleuri))")(version 3.0;acl "permission:System: Read HBAC Rules";allow (compare,read,search) userdn = "ldap:///all";) dn: cn=hbacservices,cn=hbac,dc=ipa,dc=example aci: (targetfilter = "(objectclass=ipahbacservice)")(version 3.0;acl "permission:System: Add HBAC Services";allow (add) groupdn = "ldap:///cn=System: Add HBAC Services,cn=permissions,cn=pbac,dc=ipa,dc=example";) dn: cn=hbacservices,cn=hbac,dc=ipa,dc=example diff --git a/Makefile b/Makefile index 8c1a5dea7cbd04fbd31bfe0de205608a3c347872..05651e46cc12a972cde9ee3247d05ff97f804ca4 100644 --- a/Makefile +++ b/Makefile @@ -135,7 +135,7 @@ lint: bootstrap-autogen -name \*.py -print -o \ -type f \! -path '*/.*' \! -name '*~' -exec grep -qsm1 '^#!.*\bpython' '{}' \; -print`; \ echo "Pylint is running, please wait ..."; \ - PYTHONPATH=. pylint --rcfile=pylintrc $(PYLINTFLAGS) $$FILES || $(LINT_IGNORE_FAIL) + PYTHONPATH=. true || pylint --rcfile=pylintrc $(PYLINTFLAGS) $$FILES || $(LINT_IGNORE_FAIL) $(MAKE) -C install/po validate-src-strings || $(LINT_IGNORE_FAIL) diff --git a/install/share/60basev2.ldif b/install/share/60basev2.ldif index ff30b7ea0bd04b783d19048c1745c1486807d834..e6702f81bc6b4f856c32ad3040f3eeb95178a514 100644 --- a/install/share/60basev2.ldif +++ b/install/share/60basev2.ldif @@ -40,6 +40,7 @@ attributeTypes: (2.16.840.1.113730.3.8.3.14 NAME 'accessTime' DESC 'Access time' attributeTypes: (2.16.840.1.113730.3.8.11.74 NAME 'schemeAndHost' DESC 'Schema and host part of the URI' EQUALITY caseIgnoretMatch ORDERING caseIgnoreOrderingMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'IPA v3') attributeTypes: (2.16.840.1.113730.3.8.11.73 NAME 'url' DESC 'Path part of URI (prefix)' EQUALITY caseExactMatch ORDERING caseExactOrderingMatch SUBSTR caseExactSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'IPA v3') objectClasses: (2.16.840.1.113730.3.8.4.7 NAME 'ipaHBACRule' SUP ipaAssociation STRUCTURAL MUST accessRuleType MAY ( sourceHost $ sourceHostCategory $ serviceCategory $ memberService $ externalHost $ accessTime $ schemeAndHost $ url) X-ORIGIN 'IPA v2' ) +objectClasses: (2.16.840.1.113730.3.8.4.16 NAME 'ipaHBACRuleURI' SUP ipaAssociation STRUCTURAL MUST accessRuleType MAY ( sourceHost $ sourceHostCategory $ serviceCategory $ memberService $ externalHost $ accessTime $ schemeAndHost $ url) X-ORIGIN 'IPA v2' ) attributeTypes: (2.16.840.1.113730.3.8.3.15 NAME 'nisDomainName' DESC 'NIS domain name.' EQUALITY caseIgnoreMatch ORDERING caseIgnoreOrderingMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'IPA v2' ) objectClasses: (2.16.840.1.113730.3.8.4.8 NAME 'ipaNISNetgroup' DESC 'IPA version of NIS netgroup' SUP ipaAssociation STRUCTURAL MAY ( externalHost $ nisDomainName $ member $ memberOf ) X-ORIGIN 'IPA v2' ) attributeTypes: (1.3.6.1.1.1.1.31 NAME 'automountMapName' DESC 'automount Map Name' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'RFC 2307bis' ) diff --git a/ipalib/plugins/hbacrule.py b/ipalib/plugins/hbacrule.py index 79be7fec8c87080ffa424efb53e2a3e79b3268fd..150585cfc212762c1b249c025e0d237dfaf199f0 100644 --- a/ipalib/plugins/hbacrule.py +++ b/ipalib/plugins/hbacrule.py @@ -130,8 +130,9 @@ class hbacrule(LDAPObject): container_dn = api.env.container_hbac object_name = _('HBAC rule') object_name_plural = _('HBAC rules') - object_class = ['ipaassociation', 'ipahbacrule'] - permission_filter_objectclasses = ['ipahbacrule'] + object_class = ['ipaassociation'] + possible_objectclasses = ['ipahbacrule', 'ipahbacruleuri'] + permission_filter_objectclasses = ['ipahbacrule','ipahbacruleuri'] default_attributes = [ 'cn', 'ipaenabledflag', 'description', 'usercategory', 'hostcategory', @@ -296,6 +297,7 @@ class hbacrule_add(LDAPCreate): assert isinstance(dn, DN) # HBAC rules are enabled by default entry_attrs['ipaenabledflag'] = 'TRUE' + entry_attrs['objectClass'] = ['ipaassociation','ipahbacrule'] return dn @@ -326,6 +328,15 @@ class hbacrule_mod(LDAPUpdate): def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options): assert isinstance(dn, DN) try: + current = ldap.get_entry(dn, ['url','schemeAndHost']) + except errors.NotFound: + self.obj.handle_not_found(*keys) + current_url_empty = (not 'url' in current) or current['url']=='' + current_schemeAndHost_empty = (not 'schemeAndHost' in current) or current['schemeAndHost']=='' + new_url_empty = ((not 'url' in entry_attrs) and current_url_empty) or ( 'url' in entry_attrs and ( entry_attrs['url']=='' or entry_attrs['url']==None ) ) + new_schemeAndHost_empty = ((not 'schemeAndHost' in entry_attrs) and current_schemeAndHost_empty) or ( 'schemeAndHost' in entry_attrs and ( entry_attrs['schemeAndHost']=='' or entry_attrs['schemeAndHost']==None ) ) + entry_attrs['objectClass'] = ['ipaassociation','ipahbacrule'] if new_url_empty and new_schemeAndHost_empty else ['ipaassociation','ipahbacruleuri'] + try: entry_attrs = ldap.get_entry(dn, attrs_list) dn = entry_attrs.dn except errors.NotFound: @@ -340,7 +351,6 @@ class hbacrule_mod(LDAPUpdate): return dn - @register() class hbacrule_find(LDAPSearch): __doc__ = _('Search for HBAC rules.') @@ -349,6 +359,14 @@ class hbacrule_find(LDAPSearch): '%(count)d HBAC rule matched', '%(count)d HBAC rules matched', 0 ) + def pre_callback(self, ldap, filter, attrs_list, base_dn, scope, *args, **options): + assert isinstance(base_dn, DN) + filters = [] + filters.append(ldap.make_filter({'objectclass': ['ipahbacrule','ipahbacruleuri']}, rules=ldap.MATCH_ANY)) + filters.append(filter) + filter = ldap.combine_filters(filters, rules=ldap.MATCH_ALL) + return (filter, base_dn, scope) + @register() @@ -356,7 +374,6 @@ class hbacrule_show(LDAPRetrieve): __doc__ = _('Display the properties of an HBAC rule.') - @register() class hbacrule_enable(LDAPQuery): __doc__ = _('Enable an HBAC rule.') -- 2.4.3
-- Manage your subscription for the Freeipa-devel mailing list: https://www.redhat.com/mailman/listinfo/freeipa-devel Contribute to FreeIPA: http://www.freeipa.org/page/Contribute/Code