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

Reply via email to