[Freeipa-devel] [PATCHES] 22-24 Add initial support for ID ranges

Sumit Bose sbose at redhat.com
Sun Jun 17 19:47:20 UTC 2012


On Thu, Jun 14, 2012 at 02:25:01PM +0200, Sumit Bose wrote:
> On Thu, Jun 14, 2012 at 07:54:40AM -0400, Simo Sorce wrote:
> > On Thu, 2012-06-14 at 12:35 +0200, Sumit Bose wrote:
> > > On Wed, Jun 13, 2012 at 08:38:23PM -0400, Simo Sorce wrote:
> > > > On Wed, 2012-06-13 at 21:17 +0200, Sumit Bose wrote:
> > > > > 
> > > > > to keep track of the different ranges we use for UIDs/GIDs for local
> > > > > users/groups and users from trusted domains new range objects are
> > > > > introduced which are stored below cn=range,cn=etc,$SUFFIX.
> > > > > 
> > > > > 0022: LDAP schema update
> > > > 
> > > > ack
> > > > 
> > > > > 0023: Create a range object during installation fir the local ID range
> > > > 
> > > > nack, I think we need to find a way to handle adding at least the base
> > > > range on update. Otherwise an updated server won't be able to have IDs
> > > > for most of its users.
> > > 
> > > I fully agree, but since we said that we concentrate on update issues in
> > > beta2 I wanted to send the version for the fresh install first to allow
> > > testing.
> > 
> > The reason I'd like updates is that this patchset can be installed on
> > top of existing servers for testing w/o having to reinstall from scratch
> > or manually creating the ipaDomainIDRange object :):)
> 
> ok, will do.
> 
> Do you otherwise agree with the patches or is there something I should
> change while adding the updates?
> 
> bye,
> Sumit
> 
> > 
> > > > 
> > > > > 0024: add primary and secondary RID base to the local range object
> > > > >       during ipa-adtrust-install
> > > > 
> > > > Not sure if setting the range belongs in the previous patch or this one.
> > > 
> > > I think it is right here, because a plain IPA server does not need the
> > > RID related attributes.
> > > 
> > > > We might decide to ask questions during ipa-adtrust-install if the range
> > > > is not available, maybe presenting a set of pre-canned choices if we can
> > > > detect them.
> > > 
> > > I agree here, too. But as above I would like to handle update issues
> > > in a second round.
> > > 
> > > > 
> > > > Finally I think we need to do a search with uid/gidNmber < base and
> > > > uid/gidNumber > max and prompt/warn the user if we detect any ID the
> > > > falls outside the configured range (either because we failed to detect
> > > > ranges on upgrade and the user botched the question or because the admin
> > > > added arbitrary IDs.
> > > > If a warning we should warn that missing a range that suitably covers
> > > > these IDs, those users/groups will not be available for the trust.
> > > > 
> > > > Maybe we should also have a simple ipa command that can list all
> > > > users/groups that fall outside the ranges as well.
> > > 
> > > I'm working on the ranges cli plugin to allow 'ipa range-add', 'ipa
> > > range-find' etc. I can add it there.
> > > 

Hi,

this new series of patches add the cli plugin to create the ID ranges
manually. I'm still working on a detection of the locally used id range
of an upgrade domain in ipa-adtrust-install and an plugin which rejects
new ranges which overlaps with existing ones.

bye,
Sumit
-------------- next part --------------
From 6197ddd510ab01ba4de49d1a1c7a66e19e566384 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Mon, 11 Jun 2012 18:31:36 +0200
Subject: [PATCH 1/4] Extend LDAP schema

The objectclass ipaIDobject can be used to reserve local UIDs, GIDs or
SIDs for objects that are no neither users nor groups.

The ipa*IDRange objectclasses will be used to store the used Posix ID
ranges of the local domains (ipaDomainIDRange) or the ranges reserved
for AD domains (ipaTrustedADDomainRange). To be able to map the Posix
IDs to a RID and back the corresponding ranges can be saved here as
well.
---
 install/share/60basev3.ldif |    8 ++++++++
 1 Datei ge?ndert, 8 Zeilen hinzugef?gt(+)

diff --git a/install/share/60basev3.ldif b/install/share/60basev3.ldif
index 2c24137b0dc39f215ed0e4b97079ffce0ec630d3..03561d13f45768006eb22e3dc00f41f35944dc56 100644
--- a/install/share/60basev3.ldif
+++ b/install/share/60basev3.ldif
@@ -29,6 +29,10 @@ attributeTypes: ( 2.16.840.1.113730.3.8.11.21 NAME 'ipaAllowToImpersonate' DESC
 attributeTypes: ( 2.16.840.1.113730.3.8.11.22 NAME 'ipaAllowedTarget' DESC 'Target principals alowed to get a ticket for' SUP distinguishedName X-ORIGIN 'IPA-v3')
 attributeTypes: (2.16.840.1.113730.3.8.11.30 NAME 'ipaSELinuxUser' DESC 'An SELinux user' EQUALITY caseIgnoreMatch ORDERING caseIgnoreOrderingMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE X-ORIGIN 'IPA v3')
 attributeTypes: (2.16.840.1.113730.3.8.11.31 NAME 'ipaSshPubKey' DESC 'SSH public key' EQUALITY octetStringMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 X-ORIGIN 'IPA v3' )
+attributeTypes: (2.16.840.1.113730.3.8.11.33 NAME 'ipaBaseID' DESC 'First value of a Posix ID range' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'IPA v3' )
+attributeTypes: (2.16.840.1.113730.3.8.11.34 NAME 'ipaIDRangeSize' DESC 'Size of a Posix ID range' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'IPA v3' )
+attributeTypes: (2.16.840.1.113730.3.8.11.35 NAME 'ipaBaseRID' DESC 'First value of a RID range' EQUALITY integerMatch ORDERING integerOrderingMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'IPA v3' )
+attributeTypes: (2.16.840.1.113730.3.8.11.36 NAME 'ipaSecondaryBaseRID' DESC 'First value of a secondary RID range' EQUALITY integerMatch ORDERING integerOrderingMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'IPA v3' )
 objectClasses: (2.16.840.1.113730.3.8.12.1 NAME 'ipaExternalGroup' SUP top STRUCTURAL MUST ( cn ) MAY ( ipaExternalMember $ memberOf $ description $ owner) X-ORIGIN 'IPA v3' )
 objectClasses: (2.16.840.1.113730.3.8.12.2 NAME 'ipaNTUserAttrs' SUP top AUXILIARY MUST ( ipaNTSecurityIdentifier ) MAY ( ipaNTHash $ ipaNTLogonScript $ ipaNTProfilePath $ ipaNTHomeDirectory $ ipaNTHomeDirectoryDrive ) X-ORIGIN 'IPA v3' )
 objectClasses: (2.16.840.1.113730.3.8.12.3 NAME 'ipaNTGroupAttrs' SUP top AUXILIARY MUST ( ipaNTSecurityIdentifier ) X-ORIGIN 'IPA v3' )
@@ -40,3 +44,7 @@ objectClasses: (2.16.840.1.113730.3.8.12.10 NAME 'ipaSELinuxUserMap' SUP ipaAsso
 objectClasses: (2.16.840.1.113730.3.8.12.11 NAME 'ipaSshGroupOfPubKeys' ABSTRACT MAY ipaSshPubKey X-ORIGIN 'IPA v3' )
 objectClasses: (2.16.840.1.113730.3.8.12.12 NAME 'ipaSshUser' SUP ipaSshGroupOfPubKeys AUXILIARY X-ORIGIN 'IPA v3' )
 objectClasses: (2.16.840.1.113730.3.8.12.13 NAME 'ipaSshHost' SUP ipaSshGroupOfPubKeys AUXILIARY X-ORIGIN 'IPA v3' )
+objectClasses: (2.16.840.1.113730.3.8.12.14 NAME 'ipaIDobject' SUP top AUXILIARY MAY ( uidNumber $ gidNumber $ ipaNTSecurityIdentifier ) X-ORIGIN 'IPA v3' )
+objectClasses: (2.16.840.1.113730.3.8.12.15 NAME 'ipaIDrange' ABSTRACT MUST ( cn $ ipaBaseID $ ipaIDRangeSize ) X-ORIGIN 'IPA v3' )
+objectClasses: (2.16.840.1.113730.3.8.12.16 NAME 'ipaDomainIDRange' SUP ipaIDrange STRUCTURAL MAY ( ipaBaseRID $ ipaSecondaryBaseRID ) X-ORIGIN 'IPA v3' )
+objectClasses: (2.16.840.1.113730.3.8.12.17 NAME 'ipaTrustedADDomainRange' SUP ipaIDrange STRUCTURAL MUST ( ipaBaseRID $ ipaNTTrustedDomainSID ) X-ORIGIN 'IPA v3' )
-- 
1.7.10.2

-------------- next part --------------
From 32514788013faf7f35171c4addec42998c08ae03 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Tue, 12 Jun 2012 11:58:41 +0200
Subject: [PATCH 2/4] Add objects for initial ID range

---
 install/share/bootstrap-template.ldif |   14 ++++++++++++++
 install/updates/62-ranges.update      |   13 +++++++++++++
 install/updates/Makefile.am           |    1 +
 ipaserver/install/dsinstance.py       |    1 +
 4 Dateien ge?ndert, 29 Zeilen hinzugef?gt(+)
 create mode 100644 install/updates/62-ranges.update

diff --git a/install/share/bootstrap-template.ldif b/install/share/bootstrap-template.ldif
index 149b6c9b29c6fd363eb7baccd9648d49c260ff85..ca74bf6fade5f4e0591ee511f96cc3d58542887d 100644
--- a/install/share/bootstrap-template.ldif
+++ b/install/share/bootstrap-template.ldif
@@ -409,3 +409,17 @@ objectClass: top
 objectClass: nsContainer
 cn: usermap
 
+dn: cn=ranges,cn=etc,$SUFFIX
+changetype: add
+objectClass: top
+objectClass: nsContainer
+cn: ranges
+
+dn: cn=local_id_range,cn=ranges,cn=etc,$SUFFIX
+changetype: add
+objectClass: top
+objectClass: ipaIDrange
+objectClass: ipaDomainIDRange
+cn: local_id_range
+ipaBaseID: $IDSTART
+ipaIDRangeSize: $IDRANGE_SIZE
diff --git a/install/updates/62-ranges.update b/install/updates/62-ranges.update
new file mode 100644
index 0000000000000000000000000000000000000000..42c1e2a98b8b64164ae9ae0292aa7b91beac2b26
--- /dev/null
+++ b/install/updates/62-ranges.update
@@ -0,0 +1,13 @@
+dn: cn=schema
+add:attributeTypes: (2.16.840.1.113730.3.8.11.33 NAME 'ipaBaseID' DESC 'First value of a Posix ID range' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'IPA v3' )
+add:attributeTypes: (2.16.840.1.113730.3.8.11.34 NAME 'ipaIDRangeSize' DESC 'Size of a Posix ID range' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'IPA v3' )
+add:attributeTypes: (2.16.840.1.113730.3.8.11.35 NAME 'ipaBaseRID' DESC 'First value of a RID range' EQUALITY integerMatch ORDERING integerOrderingMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'IPA v3' )
+add:attributeTypes: (2.16.840.1.113730.3.8.11.36 NAME 'ipaSecondaryBaseRID' DESC 'First value of a secondary RID range' EQUALITY integerMatch ORDERING integerOrderingMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'IPA v3' )
+add:objectClasses: (2.16.840.1.113730.3.8.12.15 NAME 'ipaIDrange' ABSTRACT MUST ( cn $$ ipaBaseID $$ ipaIDRangeSize ) X-ORIGIN 'IPA v3' )
+add:objectClasses: (2.16.840.1.113730.3.8.12.16 NAME 'ipaDomainIDRange' SUP ipaIDrange STRUCTURAL MAY ( ipaBaseRID $$ ipaSecondaryBaseRID ) X-ORIGIN 'IPA v3' )
+add:objectClasses: (2.16.840.1.113730.3.8.12.17 NAME 'ipaTrustedADDomainRange' SUP ipaIDrange STRUCTURAL MUST ( ipaBaseRID $$ ipaNTTrustedDomainSID ) X-ORIGIN 'IPA v3' )
+
+dn: cn=ranges,cn=etc,$SUFFIX
+default: obectClass: top
+default: objectClass: nsContainer
+default: cn: ranges
diff --git a/install/updates/Makefile.am b/install/updates/Makefile.am
index 412630e4e6d13167e2c0ae17c54f8ad84a4797fa..e45690f14c41dbd9eb10b5969ee14a257b8c7883 100644
--- a/install/updates/Makefile.am
+++ b/install/updates/Makefile.am
@@ -35,6 +35,7 @@ app_DATA =				\
 	55-pbacmemberof.update		\
 	60-trusts.update		\
 	61-trusts-s4u2proxy.update	\
+	62-ranges.update		\
 	$(NULL)
 
 EXTRA_DIST =				\
diff --git a/ipaserver/install/dsinstance.py b/ipaserver/install/dsinstance.py
index fb620a82e0d432d50e6c40ab8a7053ced153965a..93c6b50c274506949d1cdb81ad952141de10dab1 100644
--- a/ipaserver/install/dsinstance.py
+++ b/ipaserver/install/dsinstance.py
@@ -313,6 +313,7 @@ class DsInstance(service.Service):
                              IDMAX=self.idmax, HOST=self.fqdn,
                              ESCAPED_SUFFIX= escape_dn_chars(self.suffix.lower()),
                              GROUP=DS_GROUP,
+                             IDRANGE_SIZE=self.idmax-self.idstart+1
                          )
 
     def __create_ds_user(self):
-- 
1.7.10.2

-------------- next part --------------
From 7f47d74f825cd7ad05b741cec550deab474e3ddb Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Tue, 12 Jun 2012 17:53:36 +0200
Subject: [PATCH 3/4] Set RID bases for local domain during
 ipa-adtrust-install

---
 install/tools/ipa-adtrust-install    |    9 ++++++-
 ipaserver/install/adtrustinstance.py |   48 +++++++++++++++++++++++++++++++++-
 2 Dateien ge?ndert, 55 Zeilen hinzugef?gt(+), 2 Zeilen entfernt(-)

diff --git a/install/tools/ipa-adtrust-install b/install/tools/ipa-adtrust-install
index c0b477102462e128400436f52d2f78b092f5272d..c104b5113c16acec09d88a665f56bbb10ede4ed1 100755
--- a/install/tools/ipa-adtrust-install
+++ b/install/tools/ipa-adtrust-install
@@ -48,6 +48,12 @@ def parse_options():
     parser.add_option("--no-msdcs", dest="no_msdcs", action="store_true",
                       default=False, help="Do not create DNS service records " \
                                           "for Windows in managed DNS server")
+    parser.add_option("--rid-base", dest="rid_base", type=int, default=1000,
+                      help="Start value for mapping UIDs and GIDs to RIDs")
+    parser.add_option("--secondary-rid-base", dest="secondary_rid_base",
+                      type=int, default=100000000,
+                      help="Start value of the secondary range for mapping " \
+                           "UIDs and GIDs to RIDs")
     parser.add_option("-U", "--unattended", dest="unattended", action="store_true",
                       default=False, help="unattended installation never prompts the user")
 
@@ -207,7 +213,8 @@ def main():
         api.Backend.ldap2.connect(ccache)
 
     smb.setup(api.env.host, ip_address, api.env.realm, api.env.domain,
-              netbios_name, options.no_msdcs)
+              netbios_name, options.rid_base, options.secondary_rid_base,
+              options.no_msdcs)
     smb.create_instance()
 
     print "=============================================================================="
diff --git a/ipaserver/install/adtrustinstance.py b/ipaserver/install/adtrustinstance.py
index 0e9e9ef245a0897dfee9bcb0940d0de35c1bfd61..43a2790831c9e941380c9ce705cc5dc441b4538b 100644
--- a/ipaserver/install/adtrustinstance.py
+++ b/ipaserver/install/adtrustinstance.py
@@ -114,6 +114,8 @@ class ADTRUSTInstance(service.Service):
         self.cifs_principal = None
         self.cifs_agent = None
         self.selinux_booleans = None
+        self.rid_base = None
+        self.secondary_rid_base = None
 
         service.Service.__init__(self, "smb", dm_password=dm_password)
 
@@ -174,6 +176,47 @@ class ADTRUSTInstance(service.Service):
         except:
             print "Failed to modify IPA admin group object"
 
+    def __add_rid_bases(self):
+        """
+        Add RID bases to the range object for the local ID range.
+
+        TODO: handle missing or multiple ranges more gracefully.
+        """
+
+        try:
+            res = self.admin_conn.search_s("cn=ranges,cn=etc,"+self.suffix,
+                                           ldap.SCOPE_ONELEVEL,
+                                           "(objectclass=ipaDomainIDRange)")
+            if len(res) != 1:
+                root_logger.critical("Found more than one ID range for the " \
+                                     "local domain.")
+                raise RuntimeError("Too many ID ranges\n")
+
+            if res[0].getValue('ipaBaseRID') or \
+               res[0].getValue('ipaSecondaryBaseRID'):
+                print "RID bases already set, nothing to do"
+                return
+
+            size = res[0].getValue('ipaIDRangeSize')
+            if abs(self.rid_base - self.secondary_rid_base) > size:
+                print "Primary and secondary RID base are too close. " \
+                      "They have to differ at least by %d." % size
+                raise RuntimeError("RID bases too close.\n")
+
+            try:
+                self.admin_conn.modify_s(res[0].dn,
+                                         [(ldap.MOD_ADD, "ipaBaseRID", \
+                                                 str(self.rid_base)), \
+                                         (ldap.MOD_ADD, "ipaSecondaryBaseRID", \
+                                                 str(self.secondary_rid_base))])
+            except:
+                print "Failed to add RID bases to the local range object"
+
+        except errors.NotFound as e:
+            root_logger.critical("ID range of the local domain not found, " \
+                                 "define it and run again.")
+            raise e
+
     def __create_samba_domain_object(self):
 
         try:
@@ -402,12 +445,14 @@ class ADTRUSTInstance(service.Service):
                              FQDN = self.fqdn)
 
     def setup(self, fqdn, ip_address, realm_name, domain_name, netbios_name,
-              no_msdcs=False, smbd_user="samba"):
+              rid_base, secondary_rid_base, no_msdcs=False, smbd_user="samba"):
         self.fqdn = fqdn
         self.ip_address = ip_address
         self.realm_name = realm_name
         self.domain_name = domain_name
         self.netbios_name = netbios_name
+        self.rid_base = rid_base
+        self.secondary_rid_base = secondary_rid_base
         self.no_msdcs = no_msdcs
         self.smbd_user = smbd_user
         self.suffix = ipautil.realm_to_suffix(self.realm_name)
@@ -440,6 +485,7 @@ class ADTRUSTInstance(service.Service):
         self.step("writing samba config file", self.__write_smb_conf)
         self.step("adding cifs Kerberos principal", self.__setup_principal)
         self.step("adding admin(group) SIDs", self.__add_admin_sids)
+        self.step("adding RID bases", self.__add_rid_bases)
         self.step("activating CLDAP plugin", self.__add_cldap_module)
         self.step("activating extdom plugin", self.__add_extdom_module)
         self.step("configuring smbd to start on boot", self.__enable)
-- 
1.7.10.2

-------------- next part --------------
From 9932893aa3ca94691473e8d8ad30121bc78f982f Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Wed, 13 Jun 2012 20:58:54 +0200
Subject: [PATCH 4/4] Add CLI for ID ranges

---
 API.txt                 |   52 +++++++++++++++++++
 ipalib/constants.py     |    1 +
 ipalib/plugins/range.py |  126 +++++++++++++++++++++++++++++++++++++++++++++++
 3 Dateien ge?ndert, 179 Zeilen hinzugef?gt(+)
 create mode 100644 ipalib/plugins/range.py

diff --git a/API.txt b/API.txt
index 8127b90b91415d165590845f0ba1b6d94dab28aa..fef1475c3beaf083cfac50759205de4c425ebd95 100644
--- a/API.txt
+++ b/API.txt
@@ -2340,6 +2340,58 @@ option: Str('version?', exclude='webui')
 output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
 output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None))
 output: Output('value', <type 'unicode'>, None)
+command: range_add
+args: 1,10,3
+arg: Str('cn', attribute=True, cli_name='name', multivalue=False, primary_key=True, required=True)
+option: Int('ipabaseid', attribute=True, cli_name='base_id', multivalue=False, required=True)
+option: Int('ipaidrangesize', attribute=True, cli_name='range_size', multivalue=False, required=True)
+option: Int('ipabaserid', attribute=True, cli_name='rid_base', multivalue=False, required=True)
+option: Int('ipasecondarybaserid', attribute=True, cli_name='secondary_rid_base', multivalue=False, required=False)
+option: Str('ipanttrusteddomainsid', attribute=True, cli_name='dom_sid', multivalue=False, required=False)
+option: Str('setattr*', cli_name='setattr', exclude='webui')
+option: Str('addattr*', cli_name='addattr', exclude='webui')
+option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
+option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui')
+option: Str('version?', exclude='webui')
+output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
+output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None))
+output: Output('value', <type 'unicode'>, None)
+command: range_del
+args: 1,1,3
+arg: Str('cn', attribute=True, cli_name='name', multivalue=True, primary_key=True, query=True, required=True)
+option: Flag('continue', autofill=True, cli_name='continue', default=False)
+output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
+output: Output('result', <type 'dict'>, None)
+output: Output('value', <type 'unicode'>, None)
+command: range_find
+args: 1,12,4
+arg: Str('criteria?', noextrawhitespace=False)
+option: Str('cn', attribute=True, autofill=False, cli_name='name', multivalue=False, primary_key=True, query=True, required=False)
+option: Int('ipabaseid', attribute=True, autofill=False, cli_name='base_id', multivalue=False, query=True, required=False)
+option: Int('ipaidrangesize', attribute=True, autofill=False, cli_name='range_size', multivalue=False, query=True, required=False)
+option: Int('ipabaserid', attribute=True, autofill=False, cli_name='rid_base', multivalue=False, query=True, required=False)
+option: Int('ipasecondarybaserid', attribute=True, autofill=False, cli_name='secondary_rid_base', multivalue=False, query=True, required=False)
+option: Str('ipanttrusteddomainsid', attribute=True, autofill=False, cli_name='dom_sid', multivalue=False, query=True, required=False)
+option: Int('timelimit?', autofill=False, minvalue=0)
+option: Int('sizelimit?', autofill=False, minvalue=0)
+option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
+option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui')
+option: Str('version?', exclude='webui')
+option: Flag('pkey_only?', autofill=True, default=False)
+output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
+output: ListOfEntries('result', (<type 'list'>, <type 'tuple'>), Gettext('A list of LDAP entries', domain='ipa', localedir=None))
+output: Output('count', <type 'int'>, None)
+output: Output('truncated', <type 'bool'>, None)
+command: range_show
+args: 1,4,3
+arg: Str('cn', attribute=True, cli_name='name', multivalue=False, primary_key=True, query=True, required=True)
+option: Flag('rights', autofill=True, default=False)
+option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
+option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui')
+option: Str('version?', exclude='webui')
+output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
+output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None))
+output: Output('value', <type 'unicode'>, None)
 command: role_add
 args: 1,6,3
 arg: Str('cn', attribute=True, cli_name='name', multivalue=False, primary_key=True, required=True)
diff --git a/ipalib/constants.py b/ipalib/constants.py
index 8f87a18eef80e9824203aedf50e29e9819ae7c18..c4ba32007f74f0b8ccc6c8c518587dbf76530217 100644
--- a/ipalib/constants.py
+++ b/ipalib/constants.py
@@ -104,6 +104,7 @@ DEFAULT_CONFIG = (
     ('container_cifsdomains', 'cn=ad,cn=etc'),
     ('container_trusts', 'cn=trusts'),
     ('container_adtrusts', 'cn=ad,cn=trusts'),
+    ('container_ranges', 'cn=ranges,cn=etc'),
  
     # Ports, hosts, and URIs:
     # FIXME: let's renamed xmlrpc_uri to rpc_xml_uri
diff --git a/ipalib/plugins/range.py b/ipalib/plugins/range.py
new file mode 100644
index 0000000000000000000000000000000000000000..37482b09a6517e3b129249c9937621da17232c8c
--- /dev/null
+++ b/ipalib/plugins/range.py
@@ -0,0 +1,126 @@
+# Authors:
+#     Sumit Bose <sbose at redhat.com>
+#
+# Copyright (C) 2012  Red Hat
+# see file 'COPYING' for use and warranty information
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+from ipalib.plugins.baseldap import *
+from ipalib import api, Str, Password, DefaultFrom, _, ngettext, Object
+from ipalib.parameters import Enum
+from ipalib import Command
+from ipalib import errors
+from ipapython import ipautil
+from ipalib import util
+
+
+__doc__ = _("""
+Manage ID ranges
+""")
+
+class range(LDAPObject):
+    """
+    Range object.
+    """
+
+    range_time = ('domain', 'ad', 'ipa')
+    container_dn = api.env.container_ranges
+    object_name = ('range')
+    object_name_plural = ('ranges')
+    object_class = ['ipaIDrange']
+    possible_objectclasses = ['ipadomainidrange', 'ipatrustedaddomainrange']
+    default_attributes = ['cn', 'ipabaseid', 'ipaidrangesize', 'ipabaserid',
+                          'ipasecondarybaserid', 'ipanttrusteddomainsid']
+
+    label = _('Ranges')
+    label_singular = _('Range')
+
+    takes_params = (
+        Str('cn',
+            cli_name='name',
+            label=_('Range name'),
+            primary_key=True,
+        ),
+        Int('ipabaseid',
+            cli_name='base_id',
+            label=_("First Posix ID of the range"),
+        ),
+        Int('ipaidrangesize',
+            cli_name='range_size',
+            label=_("Number of IDs in the range"),
+        ),
+        Int('ipabaserid',
+            cli_name='rid_base',
+            label=_('First RID of the corresponding RID range'),
+        ),
+        Int('ipasecondarybaserid?',
+            cli_name='secondary_rid_base',
+            label=_('First RID of the secondary RID range'),
+        ),
+        Str('ipanttrusteddomainsid?',
+            cli_name='dom_sid',
+            label=_('Domain SID of the trusted domain'),
+        ),
+    )
+
+class range_add(LDAPCreate):
+    __doc__ = _('Add new ID range.')
+
+    msg_summary = _('Added ID range "%(value)s"')
+
+    def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
+        if 'ipanttrusteddomainsid' not in options and \
+           'ipasecondarybaserid' not in options:
+            raise errors.ValidationError(name=_('Range setup'),
+                reason=_('Ranges for local domain ' \
+                         'must have a secondary RID base'))
+
+        if 'ipanttrusteddomainsid' in options:
+            entry_attrs['objectclass'].append('ipatrustedaddomainrange')
+        else:
+            entry_attrs['objectclass'].append('ipadomainidrange')
+
+        return dn
+
+class range_del(LDAPDelete):
+    __doc__ = _('Delete an ID range.')
+
+    msg_summary = _('Deleted ID range "%(value)s"')
+
+class range_find(LDAPSearch):
+    __doc__ = _('Search for ranges.')
+
+    msg_summary = ngettext(
+        '%(count)d range matched', '%(count)d rangess matched', 0
+    )
+
+    # Since all range types are stored within separate containers under
+    # 'cn=ranges,cn=etc' search can be done on a one-level scope
+    def pre_callback(self, ldap, filters, attrs_list, base_dn, scope, *args, **options):
+        return (filters, base_dn, ldap.SCOPE_ONELEVEL)
+
+class range_show(LDAPRetrieve):
+    __doc__ = _('Display information about a range.')
+
+    def pre_callback(self, ldap, dn, entry_attrs, *keys, **options):
+        return dn
+
+api.register(range)
+api.register(range_add)
+#api.register(range_mod)
+api.register(range_del)
+api.register(range_find)
+api.register(range_show)
+
-- 
1.7.10.2



More information about the Freeipa-devel mailing list