How to get only the most specific objectClass from AD server using openLdap? - active-directory

When using ldap_search to get users from Ad server, I get for each entry several objectClasses.
I'm interested only in the most specific objectClass in the classes hierarchy.
How do I get it?
for example: for the entry
name: user1
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: user
I want to get only the "user" objectClass.
I noticed that in the programmatic ldap_search, the most specific class is returned in the last cell of the values array, that is returned from ldap_get_values(ld, entry, "objectClass") function call. Is that by chance or is that a defined behavior?
(in other words, can I rely on this to always be true?)
Thanks for any help!

For sure you can't count on heritance order. The solution for you is to specify the objectClass attribute in your ldap search filter, and to cross with objectCategory to eliminate computers for example.
(&(objectClass=user)(objectCategory=person))
you'll receive here all the objects of class user and inetOrgPerson (they are also user).
(&(objectClass=inetOrgPerson)(objectCategory=person))
you'll receive here all the objects of class inetOrgPerson (but not those which are uniquely user).

I don't know that you can count on any inheritance order coming back from a directory. As far as I know directory results are never guaranteed to be in a specific order. Most probably return the values in the order they were specified during the add. Objectclass could be a special case and it would be specified in an RFC. Another thing you'll have to watch out for is when an object has an auxillary class that is mixed in with it. Plus that auxillary class could bring in some other parent classes. You could query the directory's schema and work out the inheritance structure from that and store that off if you're doing this all from your own program.

For a generic approach you cannot rely on objectClass values order, because it's not guaranteed by standard and because an objectclass may be derived from two or more direct superclasses (multiple inheritance).
To get the instantiated objetcclass one usually need the schema information and some extra code to analyze the object class chain.
Having said that I should also say that I've seen the code which in case of Active Directory simply relies on objectClass values order. Active Directory does not support multiple inheritance and seems always return objectClass in order or inheritance. This approach is much easier to implement, but not 100% reliable.

Related

Roles instead of inheritance -- are many unused fields okay?

Much exists about a situation where for example you have for example User and Admins in real life. Rather than make Admin its own class inheriting from User, you only have User and Admin is a role. (I think there are better examples.) But my question is, an Admin might have a lot of other fields, like a list of systems it can access. It seems like if you choose to use roles, you would have user objects with many empty fields that would only be non-null if the role was set to Admin. Is this okay or is there a better way to implement than using roles?
EDIT:
An idea that was suggested: Make role not an enum but a class which holds the fields unique to the role. Does this sound reasonable?
Typically, unused fields in an object point to an object decomposition problem. The usual refactoring solution is to push those fields into the objects which use them, the roles in your example, and so make them first class objects rather than just identifiers.

Active Directory custom attribute with lookup values

We need to create a custom attribute in Active Directory that will contains lookup values and the user object will need to choose one or multiple values in this lookup. The lookup values will be defined in this custom attribute. Our application will be able to read this custom attribute.
User is related to a Campus.
Campus 1
Campus 2
Campus 3
And just one campus can be selected. The list of campus is managed in the Active Directory.
How we can acheive this by extending the schema?
You should really NOT do this. Extending the schema to store something like that is like using a nuclear bomb to open a packet of cheezeits.
Active Directory has plenty of attributes that never get used, in this case I suggest the location attribute (l), division or department.
You can add your own attribute changing the Active-Directory Schema, or using an existing attribute that is not exploited in your organization.
Edited
You can create your own class derivated from user, but for me, a Camppus is more an organizationalUnit (OU), and then link user to the nouw object using an attribute of with the unique-name syntax in fact a DN which keep referencial integrity.

How to add user membership using LDIF?

I am attempting to use an LDIF to add user memberships to existing user groups.
Example:
dn: CN=Domain Users,CN=Users
changeType: Modify
add: member
member: CN=SomeCN1
member: CN=SomeCN2
member: CN=SomeCN3
member: CN=SomeCN4
All works fine, except when one of the memberships already exist. For example, if the SomeCN2 membership already exists, the entire statement fails and no memberships get added. This is a function of the "Modify" changeType... I've tried looking at how to format the LDIF differently, but can't seem to figure it out. I thought of a statement for each membership, but that will lead my file being enormous and difficult to manage and that's not ideal.
How can I structure my membership statements so all memberships get added, regardless if one of the memberships already exist?
Multi-valued attributes in an LDAP object must have unique values, that is, each value of a multi-valued attribute must be different from any other value of the attribute in that object. No structuring of an LDIF input can change that.
I have seen applications remove all values of the multi-valued attribute, then add the desired (in this case, there are no multi-valued attributes). In some cases where the multi-valued attribute is required by the object class of which the group is a member, the entire group can be removed and then added back.
Obviously, #1 is a substandard solution (though it can be made a little more palatable by using LDAP transactions wherein the group is removed and added as part of a single transaction, but this may not be available, the world being full of low-quality servers and APIs that do not support transactions). The LDAP client would do better to retrieve all the members of the group, then, with that knowledge, add only the attribute values that are not already in the group.

Correct way to filter out built in AD SecurityGroups

I have a LDAP searchquery where i am using the following filter
"(&(objectClass=user)(objectCategory=person))"
and running against AD in order to get User-accounts out. One of the attributes being returned ("memberOf") holds a ";" separated string of groups that user is a member of.
i.e.
CN=MyGroup,OU=MyMainOU,DC=masterdom,DC=local;
CN=Administrators,CN=Builtin,DC=masterdom,DC=local
I want to filter out the BuiltIn security groups, when processing the list can I rely on the "built in" groups containing the string "cn=builtin"? Or could it change with local etc. If so what is the correct method?
You if want to utilize the memberOf attribute, you can include it in your filter by using the full container name :
(&(objectClass=user)(objectCategory=person)(memberof=CN=Builtin,DC=masterdom,DC=local))
Something to keep in mind though, is that the memberOf attribute will only show groups native to the domain component (DC) in which the user is derived from - by that I mean, if user A is part of both the Developers and Management groups, but the Developers group doesn't exist within the current domain component you're querying, then the memberOf attribute will only show the Management group for the user when queried.
Plus, the memberOf attribute is a computed back-link attribute or a constructed attribute. It's maintained and calculated by Active Directory, so as you move users and groups around, that value will automatically change for the user.
However, judging by your post, if you're just iterating through a list of users and checking the memberOf attributes for the existence of CN=Builtin (ex. a .Contains check), then yes, you can rely on that string being there, given it's part of the DC you're querying.

Why not always use (objectClass=*) in the LDAP search filter?

I created the following filter for search users in Active Directory:
(&(objectClass=*)(|(sAMAccountName=u)(userPrincipalName=u))
It is possible to create more qualified filter:
(&(objectClass=person)(|(sAMAccountName=u)(userPrincipalName=u))
The question is why?
What benefits of using specified class person?
Is it possible that the same directory contain object where objectClass is not person but the following is true (|(sAMAccountName=u)(userPrincipalName=u))?
Why not always use (objectClass=*) in the LDAP search filter?
(objectClass=*) is a present filter used to filter out objects that have no populated objectClass ... which is none, since all LDAP objects have at least one structural objectClass, hence the filter component in the first filter is unnecessary and may even slow down the search, depending on the server configuration.
The first filter in your question might cause the server to make comparisons using matching rules that are unnecessary. The second filter is a better filter from a performance perspective, assuming that an index for objectClass equality has been created on the server.
It is probably a holdover from generic LDAP services, where in priniciple any object could share the same attribute with the same value, but be of different object classes.
However, Active Directory has a limitation that sAMAccountName must be unique within the domain, across all object classes. And only 4 object classes should have the attribute? (Users, groups, printers, and workstations I think).
So you could most likely just query for
(|(sAMAccountName=u)(userPrincipalName=u))
without the objectclass filter at all.

Resources