Parsing ldap sid in node - node.js

Im trying to get all the groups of a user including nested groups, to make the query faster I'm trying to use the tokenGroups attribute so to not recursively query the groups of groups.
I got the tokenGroups with contains the sid of all the groups of the user.
The problem is entry.object gives me an array of weird string that I'm unable to use and object.raw gives me an array of jsons with type: "buffer" and data containing an array with numbers that I don't know what to do with.
Given what I have how do I parse the sid or get more info about each group?

tokenGroups is a binary attribute, returned in a base64-encoded string. In order to use it in a query, you would need to decode it and convert to an escaped string, which may be used in a query. To reduce the network load and increase performance, you may query all the groups in a single query and since objectSid is indexed, the result is blazing fast.
Let me give a command line example:
# Preparation
# Domain controller
$ ad_host=w2k8-dc.internal.local
# Get domain context automatically (or set manually)
$ base_dn=$(ldapsearch -LLL -Q -N -o ldif-wrap=no -h $ad_host -s base defaultNamingContext | grep '^defaultNamingContext:' | cut -f2- -d\ )
$ echo $base_dn
DC=internal,DC=local
# User to check
$ user=Administrator
$ user_dn=$(ldapsearch -LLL -Q -N -o ldif-wrap=no -h $ad_host -b "$base_dn" sAMAccountName=$user dn | grep '^dn:' | cut -f2- -d\ )
$ echo $user_dn
CN=Administrator,CN=Users,DC=internal,DC=local
# Actual query
# Get token groups
$ token_groups=$(ldapsearch -LLL -Q -N -o ldif-wrap=no -h $ad_host -b "$user_dn" -s base tokenGroups | grep '^tokenGroups:' | cut -f2- -d\ )
$ echo $token_groups
AQIAAAAAAAUgAAAAIQIAAA== AQIAAAAAAAUgAAAAIAIAAA== AQUAAAAAAAUVAAAAClus3m3pCzBhhoO3PAIAAA== AQUAAAAAAAUVAAAAClus3m3pCzBhhoO3BgIAAA== AQUAAAAAAAUVAAAAClus3m3pCzBhhoO3BwIAAA== AQUAAAAAAAUVAAAAClus3m3pCzBhhoO3AQIAAA== AQUAAAAAAAUVAAAAClus3m3pCzBhhoO3CAIAAA== AQUAAAAAAAUVAAAAClus3m3pCzBhhoO3AAIAAA==
# Decode SIDs and prepare query
$ sid_query=$(for sid in $token_groups; do printf "(objectSid=%s)" $(echo $sid | base64 -d | hexdump -ve '"\\" /1 "%02x"'); done)
$ echo $sid_query
(objectSid=\01\02\00\00\00\00\00\05\20\00\00\00\21\02\00\00)(objectSid=\01\02\00\00\00\00\00\05\20\00\00\00\20\02\00\00)(objectSid=\01\05\00\00\00\00\00\05\15\00\00\00\0a\5b\ac\de\6d\e9\0b\30\61\86\83\b7\3c\02\00\00)(objectSid=\01\05\00\00\00\00\00\05\15\00\00\00\0a\5b\ac\de\6d\e9\0b\30\61\86\83\b7\06\02\00\00)(objectSid=\01\05\00\00\00\00\00\05\15\00\00\00\0a\5b\ac\de\6d\e9\0b\30\61\86\83\b7\07\02\00\00)(objectSid=\01\05\00\00\00\00\00\05\15\00\00\00\0a\5b\ac\de\6d\e9\0b\30\61\86\83\b7\01\02\00\00)(objectSid=\01\05\00\00\00\00\00\05\15\00\00\00\0a\5b\ac\de\6d\e9\0b\30\61\86\83\b7\08\02\00\00)(objectSid=\01\05\00\00\00\00\00\05\15\00\00\00\0a\5b\ac\de\6d\e9\0b\30\61\86\83\b7\00\02\00\00)
# Get group information
$ ldapsearch -LLL -Q -N -o ldif-wrap=no -h $ad_host -b "$base_dn" "(|$sid_query)" dn cn
dn: CN=Schema Admins,CN=Users,DC=internal,DC=local
cn: Schema Admins
dn: CN=Enterprise Admins,CN=Users,DC=internal,DC=local
cn: Enterprise Admins
dn: CN=Administrators,CN=Builtin,DC=internal,DC=local
cn: Administrators
dn: CN=Users,CN=Builtin,DC=internal,DC=local
cn: Users
dn: CN=Domain Admins,CN=Users,DC=internal,DC=local
cn: Domain Admins
dn: CN=Domain Users,CN=Users,DC=internal,DC=local
cn: Domain Users
dn: CN=Group Policy Creator Owners,CN=Users,DC=internal,DC=local
cn: Group Policy Creator Owners
dn: CN=Denied RODC Password Replication Group,CN=Users,DC=internal,DC=local
cn: Denied RODC Password Replication Group
Note that using tokenGroups does not provide information about distribution groups. It includes however user's primary group (most probably Domain Users), which is NOT included in memberOf (nor the user is included in group's member attribute).
That would make a difference in results as the regular recursive member query will not return primary group nor the groups that a user would be a member through their primary group. For example, if user's primary group is Domain Users, and Domain Users is a member of group my-security-group, the latter will not be found through a
member:1.2.840.113556.1.4.1941: query, but will be returned in tokenGroups.
Last but not least, member:1.2.840.113556.1.4.1941: can be very expensive computationally and depending on domain's size, base DN and domain controller's load can take much time to resolve. For my real company's domain it is more or less 3 times longer than the SID query:
$ time ldapsearch -LLL -Q -N -o ldif-wrap=no -h $ad_host -b "$base_dn" "(&(objectClass=group)(member:1.2.840.113556.1.4.1941:=$user_dn))" dn | grep '^dn:' | wc -l
92
real 0m11.038s
user 0m0.017s
sys 0m0.024s
$ time ldapsearch -LLL -Q -N -o ldif-wrap=no -h $ad_host -b "$base_dn" "(|$sid_query)" dn | grep '^dn:' | wc -l
111
real 0m2.851s
user 0m0.014s
sys 0m0.033s
Note the difference in result count; the SID query returns some built-in groups and those groups that a user is member of through Domain Users.

If you need help parsing the tokenGroups, then you'll have to show your code and what output you're actually getting.
But yes, tokenGroups gives you the SID of every security group that the user should be considered a member of (recursively). But there are caveats:
If you want the name of each group, you have to look up the group based on the SID. That's basically one network request per group. If you want "faster", then this is bad. More network requests = slower.
It will not include distribution groups (groups where the Group Type is "Distribution"). That may or may not matter to you.
My first question is always: Why do you want to know this? Do you really need to list every group the user is a member of? Or are you looking for one specific group. If you're looking for one group, then you can find the SID of that group and look for that SID in the tokenGroups.
If you really do want the name of every group, or you need to include distribution groups, then you're better off doing this differently. You can perform a search for all groups that have this user as a member:
(&(objectClass=group)(member:1.2.840.113556.1.4.1941:=userDN))
Where userDN is the distinguishedName of the user. That weird looking number is the object identifier (OID) for LDAP_MATCHING_RULE_IN_CHAIN, which you can read more about on this page. Basically, it tells AD to do a recursive search. So it will return every group that has the user as a direct member, or nested member.
I wrote a couple articles on my website about this, which you might benefit from reading, especially if you have more than one domain in your environment. My code examples are C#, but it's really just LDAP in the background anyway, so the principles can be applied to any language.
Finding all of a user’s groups
Find out if one user is a member of a group

Related

ldapsearch - users in dynamic groups

I need to get all users from a dynamic group with ldapsearch.
I dont know what to look for, I only know how to do basic stuff.
What I got atm:
ldapsearch -LLL -x -D "user#domain" -w "password" -b "OU=org,OU=group,OU=ressources,OU=organisation,DC=domain,DC=local" -H "ldap://dc.domain.local" "CN=groupname" displayName info
This only shows me the groupname and description.
How do I list all the users in this group? I guess I have to check the users for the DN of this group but how?
Did you try:
(memberOfCN=GroupOne,OU=Security Groups,OU=Groups,DC=YOURDOMAIN,DC=NET)

how to import passwords only and update on ldap server?

I want to update passwords [user's already existing in ldap] of the user by importing data from /etc/passwd & /etc/shadow
How to achieve this ?
I will give the overview of my setup.
nodes user id & password managed by management node [xcat], ldap not used for this purpose.
We have imported the user's from management node to ldap server by following the below given steps:-
Copied /etc/passwd, /etc/group & /etc/shadow from management node.
getent passwd > /tmp/passwd.out getent shadow > /tmp/shadow.out
cd /usr/share/migrationtools/ ./migrate_passwd.pl /tmp/passwd.out > /tmp/passwd.ldif
ldapadd -x -W -D "cn=Manager,dc=aadityaldap,dc=com" -f /tmp/passwd.ldif
Now we want to update the passwords frequently and keep the ldap server sync with out management node. please give me idea how to achive this.
I tried the same way i imported users into ldap but it gives me an error.
[root#iitmserver2 migrationtools]# ldapmodify -x -W -D "cn=Manager,dc=aadityaldap,dc=com" -f /tmp/passwd.ldif
Enter LDAP Password:
ldapmodify: modify operation type is missing at line 2, entry "uid=pharthiphan,ou=People,dc=aadityaldap,dc=com"

openam - create a user with ssoadm

I have new goal. Be able to create users of openam with ssoadm.
I have read the documentation of Openam
https://wikis.forgerock.org/confluence/display/openam/ssoadm-identity#ssoadm-identity-create-identity
However, I don't know how to create a user and then assign it a password. For now I just can create users by openam web, but is not desirable, I want to automatize.
Somebody know how can I create a normal user with ssoadm?
./ssoadm create-identity ?
./ssoadm create-agent ?
UPDATE: I have continued with my investigation :) I think I'm closer than before
$ ./ssoadm create-identity -u amadmin -f /tmp/pwd.txt -e / -i Test -t User
Minimum password length is 8.
But where is the parameter for password?
Thanks!
To create a new user in the configured data stores you could execute the following ssoadm command:
$ openam/bin/ssoadm create-identity -e / -i helloworld -t User -u amadmin -f .pass -a givenName=Hello sn=World userPassword=changeit
Here you can see that I've defined the password as the userPassword attribute, which is data store dependent really. For my local OpenDJ this is perfectly legal, but if you are using a database or something else, then you'll have to adjust the command accordingly.
If you don't want to provide the attributes on the command line, then you could put all the values into a properties file, for example:
$ echo "givenName=Hello
sn=World
userPassword=changeit" > hello.txt
$ openam/bin/ssoadm create-identity -e / -i helloworld -t User -u amadmin -f .pass -D hello.txt
But I must say that using OpenAM for identity management is not recommended, you should use your data store's own tools to manage identities (i.e. use an LDAP client within your app, or just simply use the ldap* CLI tools). You may find that OpenAM doesn't handle all the different identity management related tasks as normally people would expect, so to prevent surprises use something else for identity management.

using ldapsearch to return only a value

using an OPENLDAP server i want to retrieve informations from it with ldapsearch. I created a custom class called iduriclass, this class is used to store an id and an uri. in my ldapsearch command i want it to return only the uri for a specified id.
EXAMPLE : the directory contain now two entries id=test uri=server.com/test and id=test2 uri=server.com/test2
Trying it i get an ldif file that contains all uris in the server
I want to have an ldapsearch command that takes test as argument and returns only a value that is : server.com/test
Here's how you query your ldap server.
HOSTNAME=<your ladap hostname>
USERNAME=<your ldap username>
PASSWORD=<your ldap username's password>
SEARCHBASE=<your ldap's search base DN>
QUERYSTRING=test1
PORT=<your ldap port>
ldapsearch -LLL -h ${HOSTNAME} -p $PORT -D cn=${USERNAME} -w ${PASSWORD} -b "${SEARCHBASE}" "(id=${QUERYSTRING})" uri | sed -n 's/^[ \t]*uri:[ \t]*\(.*\)/\1/p'
The option -LLL will not print ldap comments on output. Your ldap may require -x (simple authentication) if it doesn't support SASL.
Adding the parameter -tt writes a file with ONLY the requested attribute(s) value as the OP requested. No preceding field name or anything else. Path is configurable with -T, otherwise is /tmp

user_id and group_id always starts from a unique value

When i used useradd command in linux, the user_id and group_id for the account is automatically chosen as 500. Now if i delete the account and create it again, then also the user_id and group_id is 500. From where is this default value chosen ?
I used this command :
$ useradd ping
password:
and then looked into the following file
$ cat /etc/group /etc/passwd
root::0:root
tty::5:
disk:x:100:
floppy:x:101:
uucp:x:102:
utmp:x:103:
lp:x:104:
kmem:x:105:
vcsa:x:106:
sshd:x:74:
ping:x:500:
root:x:0:0:root:/root:/bin/bash
nobody:x:99:99:Nobody:/:/sbin/nologin
vcsa:x:106:106:vcsa privsep:/var/empty:/sbin/false
sshd:x:74:74:sshd privsep:/var/empty:/sbin/false
ping:x:500:500::/home/ping:/bin/bash
The defaults are dependent upon the linux distribution you're running.
My debian box has UID_MIN 1000 set in the /etc/login.defs file.
If your goal is to use a different UID, then you need to use the -u | --uid option for useradd.

Resources