5.1.1 Designing the DIT
5.1.2 Select the STRUCTURAL objectClass
5.1.3 slapd.conf File
5.1.4 LDIF File
5.1.5 Loading the LDIF
5.1.6 Adding New Entries using LDIF
5.1.7 Modifying Entries using LDIF
5.1.8 Just Fooling Around
5.2.1 Security Policy
5.2.2 Adding Groups
5.2.3 ACL slapd.conf Access Definitions
5.2.4 Testing the ACL
5.3.1 Requirement
5.3.2 Implementation
5.3.3 LDIF
5.3.4 ACL slapd.conf Access Definitions
5.3.5 Testing the ACL
5.4.1 Requirement
5.4.2 Implementation
5.4.3 Attribute Definitions
5.4.4 objectClass & Schema Definition
5.4.5 ACL slapd.conf Access Definitions
5.4.6 LDIF
5.4.7 Testing the Changes
5.5 Single Sign On
5.6 Referral and Replication
In this section we create a number of attributes, an objectclass and a schema to package them for the future.
As part of the corporate analysis to exploit still further the wildly successful adoption of LDAP our corporate masters have decided that we will add the following capabilities to our currently operational directory:
a dohicky attribute. This attribute is a boolean value. It can only be seen and updated by the owner and any member of the hrpeople group.
an ageAtBirth attribute (note the especially stupid pseudo-Hungarian a.k.a. CamelCase notation - this is the last time you will see it). This attribute is a numeric value. It can only be seen and updated by the owner and any member of the hrpeople group.
a gobbledegook attribute. This attribute is a string value and is publicly visible to all authenticated users. It can be updated only by the owner and any member of the hrpeople group. It will allow searching using <= or >= search filters.
As part of our move to single sign-on (SSO) we will add the standard posixAccount objectclass to each user. The record will be visible only to the itpeople group.
We have striven mightily to see if we can re-use any existing attributes (essentially, use an existing attribute with the right SYNTAX even though its original 'purpose' was designed for another usage) of the inetorgperson objectClass and failed miserably. We will have to roll-our-own objects. Here is what we decided, or in most cases had, to do:
The dohicky attribute. Create our own using the existing boolean syntax OID.
The ageAtBirth attribute. Create our own using the existing integer syntax OID.
The gobbledegook attribute. Create our own using the existing PrintableString syntax OID. But to allow for the use of <= and >= search filters we need to use an ORDERING matchingRule (caseIgnoreOrderingMatch).
We will create a new objectclass for these attributes which we will call ourObject (pretty creative name). Because we already have a STRUCTURAL object in each entry (inetorgperson) we will use an AUXILIARY objectclass.
If we had required a STRUCTURAL object we would have had to make them all children of our current inetorgperson entries just like we did with our private addressbook enhancement. Alternatively, we could have made ourObject STRUCTURAL and used sup inetOrgPerson in the definition thus adding it to the end of the Person ->organizationalPerson ->inetOrgPerson objectClass hierarchy (see objectClass definition .
We are creating both an objectclass and attributes which will require to be globally unique. These examples use a globally unique OID which you can safely use FOR THE PURPOSES OF TESTING THIS EXAMPLE. DO NOT BE TEMPTED TO REUSE EITHER THIS OR ANY OTHER OID. Obtaining your own enterprise number that allows you to define your own attributes and objectclasses is a trivial and zero cost process via IANA. It is a VERY BAD THING™ to re-use existing OIDs.
Since our beloved and esteemed corporate masters are unlikely to stop here we have decided to package these thingies (attributes and objectclass) into a schema which we will call ourco.schema (original or what).
The posixAccount objectclass is - thank goodness - an AUXILIARY class. Since some of the attributes are shared with other objectclasses we will re-interpret the draconic directive to limit access to posixAccount attributes to only itpeople to only the unique attributes of this objectclass - specifically homedirectory, gidnumber, uidnumber, loginshell and gecos.
We create the following attribute definitions:
attributetype ( 1.3.6.1.4.1.6863.2.3.107 NAME 'dohicky' EQUALITY booleanMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )
The attribute's OID uses the suggested numbering convention. We use the standard boolean data type syntax OID. The matchingRules is only EQUALITY. For more information on defining attributes.
attributetype ( 1.3.6.1.4.1.6863.2.3.108 NAME 'ageAtBirth' EQUALITY integerMatch ORDERING integerOrderingMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )
The attribute's OID uses the suggested numbering convention. We use the standard integer data type syntax OID. The matchingRules are both EQUALITY and ORDERING. For more information on defining attributes.
You will occasionally see references to gobbledigook and even gobbledygook - ignore them - this is the real spelling!
attributetype ( 1.3.6.1.4.1.6863.2.3.109 NAME 'gobbledegook' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch ORDERING caseIgnoreOrderingMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.44{200} )
The attribute's OID uses the suggested numbering convention. We use the standard PrintableString data type syntax OID and we define a maximum length of 200 characters (in braces or curly brackets) for the attribute. The matchingRules are EQUALITY, SUBSTR and ORDERING. For more information on defining attributes.
objectclass ( 1.3.6.1.4.1.6863.2.4.57 NAME 'ourObject' DESC 'A very useful object' SUP top AUXILIARY MUST ( dohicky $ gobbledegook ) MAY ageAtBirth )
The objectClass's OID uses the suggested numbering convention.
SUP top terminates the objectclass hierarchy using the convenience objectClass top.
AUXILIARY allows us to associate this objectClass with ANY STRUCTURAL objectClass.
MUST ( dohicky $ gobbledegook ) defines that the attributes dohicky and gobbledegook have to be present when the objectclass is added. Whereas MAY ageAtBirth indicates that this attribute is optional.
For more information on defining objectclases.
Finally we add all the above stuff into a file and save it as ourco.schema in the same directory as the distribution schemas. You can save these schemas anywhere its just easier if they are all in the same place.
Squirrels: The DESC clause of most objects and attributetypes is normally about as meaningful as ours in the above examples. There are many annoying things in this life but one of them is what we call the 'squirrel complex' which is defined as being a unnatural desire to hide things - like meaning and usage. Lord Byron, the poet, was reputedly asked once about the meaning of a line from one of his poems. He replied "When I wrote that, God and I knew what it meant - now only God does". Memory is finite. Why not add a few words of meaningful, descriptive text. Especially when significant limitations or specific usage is envisaged by the designers.
# EXAMPLE.COM SCHEMA FILE # takes values: # true = wears clean socks on monday # false = does not wear clean socks on monday attributetype ( 1.3.6.1.4.1.6863.2.3.107 NAME 'dohicky' EQUALITY booleanMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 ) # if present must take the value = 0 attributetype ( 1.3.6.1.4.1.6863.2.3.108 NAME 'ageAtBirth' EQUALITY integerMatch ORDERING integerOrderingMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 ) # string used to describe the height of the person in either feet/inches or meters # may be expressed as xfyi e.g. 5f7i (5 feet 7 inches) or x.ym e.g. 1.95m (1.95 meters) # the values f, i, m above are case insensitive attributetype ( 1.3.6.1.4.1.6863.2.3.109 NAME 'gobbledegook' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch ORDERING caseIgnoreOrderingMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.44{200} ) # objectclass used with people address book to define required information # for State Law 5.7.3 - data is defined by law to be private - limited access allowed objectclass ( 1.3.6.1.4.1.6863.2.4.57 NAME 'ourObject' DESC 'A very useful object' SUP top AUXILIARY MUST ( dohicky $ gobbledegook ) MAY ageAtBirth )
We need to modify the slapd.conf file first to fix ACL permissions but specifically OpenLDAP knows nothing about our new objectclass and will choke when it sees a dohicky attribute without the include /usr/local/etc/openldap/schema/ourco.schema which contains its definition. The modified slapd.conf file is here:
# ###### SAMPLE 4 - DIRECTORY with home-grown objectclass & attributes ############ # # NOTES: inetorgperson picks up attributes and objectclasses # from all three schemas # devices objectclass is in core.schema # posixAccount is in nis.schema # add ourco.schema # # NB: RH Linux schemas in /etc/openldap # include /usr/local/etc/openldap/schema/core.schema include /usr/local/etc/openldap/schema/cosine.schema include /usr/local/etc/openldap/schema/inetorgperson.schema include /usr/local/etc/openldap/schema/nis.schema include /usr/local/etc/openldap/schema/ourco.schema # NO REFERRALS # DON'T bother with ARGS file # pidfle allows scripts for stopping slapd to work pidfile /var/run/slapd.pid # enable a lot of logging - we might need it loglevel -1 # NO dynamic backend modules # NO TLS-enabled connections ####################################################################### # bdb database definitions # # replace example and com below with a suitable domain # # If you don't have a domain you can leave it since example.com # is reserved for experimentation or change them to My and inc ####################################################################### database bdb suffix "dc=example, dc=com" # ACL1 # only owner and itgroup can see or update access to attrs=userpassword by self write by anonymous auth by group.exact="cn=itpeople,ou=groups,dc=example,dc=com" write by * none # ACL1A # only itgroup can see and update access to attrs=homedirectory,uidnumber,gidnumber,loginshell,gecos by group.exact="cn=itpeople,ou=groups,dc=example,dc=com" write by * none # ACL2 # allow read of addressbook by owner and itpeople; no-one else see it access to dn.regex="^ou=addressbook,cn=([^,]+),ou=people,dc=example,dc=com$" attrs=entry by dn.exact,expand="cn=$1,ou=people,dc=example,dc=com" read by group.exact="cn=itpeople,ou=groups,dc=example,dc=com" write by users none # ACL3 # allows itgroup to create addressbook but not see entries access to dn.regex="cn=[^,]+,ou=people,dc=example,dc=com$" attrs=children by group.exact="cn=itpeople,ou=groups,dc=example,dc=com" write by users none break # ACL4 # allow user to create entries in own addressbook; no-one else can access it # needs write access to the entries ENTRY attribute (ACL5) # and the entries CHILDREN (ACL4) access to dn.regex="ou=addressbook,cn=([^,]+),ou=people,dc=example,dc=com$" attrs=children by dn.regex,expand="cn=$1,ou=people,dc=example,dc=com" write by users none # ACL5 # allow one to create entries in its own addressbook; no-one else can access it # needs write access to the entries ENTRY attribute (ACL5) # and the entries CHILDREN (ACL4) access to dn.regex="ou=addressbook,cn=([^,]+),ou=people,dc=example,dc=com$" attrs=entry by dn.regex,expand="cn=$1,ou=people,dc=example,dc=com" write by users none # ACL6 # allow access to all entries in own addressbook; no-one else can access it access to dn.regex="ou=addressbook,cn=([^,]+),ou=people,dc=example,dc=com$" filter=(objectclass=inetorgperson) by dn.regex,expand="cn=$1,ou=people,dc=example,dc=com" write by users none # LDAP 2.2+ replace ACL5 and ACL6 with #access to dn.regex="ou=addressbook,cn=([^,]+),ou=people,dc=example,dc=com$" # attrs=entry,@inetorgperson # by dn.regex,expand="cn=$1,ou=people,dc=example,dc=com" write # by users none # ACL7 # allows sales to create entries in customers # authenticated user can only read access to dn.one="ou=customers,dc=zytrax,dc=com" attr=children by group.exact="cn=salespeople,ou=groups,dc=example,dc=com" write by users read # ACL8 access to attr=carlicense,homepostaladdress,homephone,dohicky,ageatbirth by self write by group.exact="cn=hrpeople,ou=groups,dc=example,dc=com" write by * none # ACL8A - control access to equipment access to dn.one="ou=equipment,dc=example,dc=com" by group.exact="cn=itpeople,ou=groups,dc=example,dc=com" write by users read by * none # ACL9 access to * by self write by group.exact="cn=hrpeople,ou=groups,dc=example,dc=com" write by users read by * none # root or superuser rootdn "cn=jimbob, dc=example, dc=com" rootpw dirtysecret # The database directory MUST exist prior to running slapd AND # change path as ncessary directory /var/db/openldap/example-com # Indices to maintain for this directory # unique id so equality match only index uid eq # allows general searching on commonname, givenname and email index cn,gn,mail eq,sub # allows multiple variants on surname searching index sn eq,sub # sub above includes subintial,subany,subfinal # optimise department searches index ou eq # if searches will include objectClass uncomment following # index objectClass eq # shows use of default index parameter index default eq,sub # indices missing - uses default eq,sub index telephonenumber # other database parameters # read more in slapd.conf reference section cachesize 10000 checkpoint 128 15
Get sample file as text (use save as in your browser).
Notes:
We added includes for the schemas nis.schema (for posixAccount) and ourco.schema (for ourObject and the various attributes).
We added an access directive (ACL1A) to limit access to the itgroup only of the attributes homedirectory, uidnumber and gidnumber as required by our policy. In OpenLdap 2.2+ we could have used the syntax attr=@posixaccount (all the attributes of the posixAccount objectclass) but in this position it would also have had the minor side effect of limiting access to cd! Not really what we want.
We added dohickey and ageatbirth to the access directive (ACL8) to limit access to the hrgroup and the owner.
We now need to stop OpenLDAP and restart to pick up this new slapd.conf file. Use something like the following commands:
# stop and start OpenLDAP (slapd) # on Linux/Redhat /etc/rc.d/init.d/ldap restart # on BSD [bsd] /usr/local/etc/openldap/slapd.sh stop # then [bsd] /usr/local/etc/rc.d/slapd.sh start # confirm slapd is running ps ax | grep slapd
The LDIF below updates our entries by adding the posixAccount objectclass and its MUST attributes and the ourObject object class and its MUST attributes:
None of the LDAP browsers we used allowed us to add new AUXILIARY objects - LDIF is the only way to do this apparently.
version: 1 dn: cn=john smith,ou=people,dc=example,dc=com changetype: modify objectclass: inetorgperson objectclass: posixaccount uidnumber: 200 gidnumber: 203 homedirectory: /var/mail/example.com/jsmith objectclass: ourObject dohicky: false gobbledegook: john ageatbirth: 0 dn: cn=sheri smith,ou=people,dc=example,dc=com changetype: modify objectclass: inetorgperson objectclass: posixaccount uidnumber: 201 gidnumber: 203 homedirectory: /var/mail/example.com/ssmith objectclass: ourObject dohicky: true gobbledegook: sheri dn: cn=robert smith,ou=people,dc=example,dc=com changetype: modify objectclass: inetorgperson objectclass: posixaccount uidnumber: 202 gidnumber: 203 homedirectory: /var/mail/example.com/rsmith objectclass: ourObject dohicky: false gobbledegook: robert ageatbirth: 17
Notes:
The changetype directive is not strictly necessary when ldapmodify is used since this is assumed to be the default.
The objectclass: inetorgperson is necessary since it tells OpenLDAP which STRUCTURAL objectclass the AUXILIARY objectclasses will use.
The MUST attributes for each objectclass need to be present. The MAY objects are entirely optional.
Assuming we save the above LDIF as modify.ldif in our /tmp directory we load the LDIF file using ldapmodify with a command like this (line below is split for HTML formatting reasons only and should be on a single line):
ldapmodify -H ldap://ldaphost.example.com -x -D "cn=jimbob,dc=example,dc=com" -f /tmp/modify.ldif -w dirtysecret
The ldaphost.example.com should be replaced with whatever hostname your LDAP directory is located on. If the ldap host is the same system as the one from which the command is issued the -H and parameter can be omitted. The -x indicates we do not use SASL security and is required since OpenLDAP 2.x. The -D is the binding and is the rootdn - the superuser gets to do everything. The -w followed by the password is, to say the least, insecure and you could use -W which will prompt for the password.
We now need to test our new update. To test the ACL use your LDAP Browser and:
Configure your LDAP browser to bind or authenticate using dn: cn=Robert Smith, ou=people, dc=example, dc=com with a userpassword of rJsmitH (case sensitive) and because this entry has hrpeople privileges it will see and be able to modify all entries including carlicense, homepostaladdress and homephone but not userpassword (except for his own entry) and can read the customers and equipment entries but cannot write to them. Robert Smith can also see and add to his own addressbook entries but can only guess if anyone else has an addressbook (cannot see addressbook for anyone else). He cannot see the attributes of the posixAccount objectclass homedirectory, guidnumber, gidnumber, loginshell and gecos of his own or any other entry.
Configure your LDAP browser to bind or authenticate using dn: cn=Sheri Smith, ou=people, dc=example, dc=com with a userpassword of sSmitH (case sensitive) and because this entry has itpeople privileges it will see and be able to modify the userpassword,homedirectory, guidnumber, gidnumber, loginshell and gecos attribute of all entries but cannot see carlicense, homepostaladdress and homephone for any entry except her own. This entry can read the customers entries but cannot write to them but can read and write equipment entries . Sheri Smith can also see and add to her own addressbook entries and can see addressbook (but not the entries) for everyone. She can also delete addresbook for each entry (and if you have just tried it - can also add it back again!).
Configure your LDAP browser to bind or authenticate using dn: cn=John Smith, ou=people, dc=example, dc=com with a userpassword of jSmitH (case sensitive) and because this entry has no privileges it cannot see carlicense, homepostaladdress, homephone and userpassword for any entry except his own (which he can also modify). This entry because it is a member of the salespeople group can read and write the customers entries but can only read equipment entries . John Smith can also see and add to his own addressbook entries but can only guess if anyone else has an addressbook (cannot see addressbook for anyone else). He cannot see the attributes of the posixAccount objectclass homedirectory, guidnumber, gidnumber, loginshell and gecos of his own or any other entry.
Configure your LDAP browser for anonymous access and confirm that access is denied.
Authenticate as our rootdn or superuser (defined in the slapd.conf as cn=jimbob,dc=example,dc=com, password dirtysecret) and confirm this overrides all our privileges and can see and modify everything.
It may be useful at this time to export the current state of the directory to an LDIF using either your LDAP browser's export feature or slapcat.
Note:: In all of the above tests you should be able to see with your LDAP Browser the customers, equipment and groups branch and their entries. If you cannot then you may have set your Base DN (or Root DN depending on your browser) fields in the LDAP browser to ou=people,dc=example,dc=com, set this to dc=example,dc=com and you should now be able to see all the entries.
Problems, comments, suggestions, corrections (including broken links) or something to add? Please take the time from a busy life to 'mail us' (at top of screen), the webmaster (below) or info-support at zytrax. You will have a warm inner glow for the rest of the day.
Contents
tech info
guides home
intro
contents
1 objectives
big picture
2 concepts
3 ldap objects
quickstart
4 install ldap
5 samples
6 configuration
7 replica & refer
reference
8 ldif
9 protocol
10 ldap api
operations
11 howtos
12 trouble
13 performance
14 ldap tools
security
15 security
appendices
notes & info
ldap resources
rfc's & x.500
glossary
ldap objects
change log
This work is licensed under a
Creative Commons License.
If you are happy it's OK - but your browser is giving a less than optimal experience on our site. You could, at no charge, upgrade to a W3C STANDARDS COMPLIANT browser such as Firefox
Copyright © 1994 - 2024 ZyTrax, Inc. All rights reserved. Legal and Privacy |
site by zytrax hosted by javapipe.com |
web-master at zytrax Page modified: March 24 2023. |