python 3.7 and ldap3 reading group membership - python-3.7

I am using Python 3.7 and ldap3. I can make a connection and retrieve a list of the groups in which I am interested. I am having trouble getting group members though.
server = Server('ldaps.ad.company.com', use_ssl=True, get_info=ALL)
with Connection(server, 'mydomain\\ldapUser', '******', auto_bind=True) as conn:
base = "OU=AccountGroups,OU=UsersAndGroups,OU=WidgetDepartment," \
+ "OU=LocalLocation,DC=ad,DC=company,DC=com"
criteria = """(
&(objectClass=group)
(
|(sAMAccountName=grp-*widgets*)
(sAMAccountName=grp-oldWidgets)
)
)"""
attributes = ['sAMAccountName', 'distinguishedName']
conn.search(base, criteria, attributes=attributes)
groups = conn.entries
At this point groups contains all the groups I want. I want to itterate over the groups to collect the members.
for group in groups:
# print(cn)
criteria = f"""
(&
(objectClass=person)
(memberof:1.2.840.113556.1.4.1941:={group.distinguishedName})
)
"""
# criteria = f"""
# (&
# (objectClass=person)
# (memberof={group.distinguishedName})
# )
# """
attributes = ['displayName', 'sAMAccountName', 'mail']
conn.search(base, criteria, attributes=attributes)
people = conn.entries
I know there are people in the groups but people is always an empty list. It doesn't matter if I do a recirsive search or not.
What am I missing?
Edit
There is a longer backstory to this question that is too long to go into. I have a theory about this particular issue though. I was running out of time and switched to a different python LDAP library -- which is working. I think the issue with this question might be that I "formated" the query over multiple lines. The new ldap lib (python-ldap) complained and I stripped out the newlines and it just worked. I have not had time to go back and test that theory with ldap3.

people is overwritten in each iteration of your loop over groups.
Maybe the search result for the last group entry in groups is just empty.
You should initialise an empty list outside of your loop and extend it with your results:
people = []
for group in groups:
...
conn.search(...)
people.extend(conn.entries)
Another note about your code snippet above. When combining objectClass definitions with attribute definitions in your search filter you may consider using the Reader class which will combine those internally.
Furthermore I would like to point out that I've created an object relational mapper where you can simply define your queries using declarative python syntax, e.g.:
from ldap3_orm import ObjectDef, Reader
from ldap3_orm.config import config
from ldap3_orm.connection import conn
PersonDef = ObjectDef("person", conn)
r = Reader(conn, PersonDef, config.base_dn, PersonDef.memberof == group.distinguishedName)
r.search()
ldap3-orm documentation can be found at http://code.bsm-felder.de/doc/ldap3-orm

Related

Search for MongoDB records containing a certain string

I have a MongoDB database full of tweets that I've gathered using the tweepy API, and I want to be able to search on a web application a hashtag and it shows the tweets containing that hashtag.
Currently, I have created a list with the DB records in, and iterating through that list to display them all, but now I want to refine the search so the user can choose what they see. I have the users search saved into a variable and I have tried the following ideas, but none seem to be working.
My first idea was to just pass in the variable and hope for the best
def display():
input = request.form['input'] # setting variable for user input
# Set up Mongo Client
client = MongoClient("mongo.user/pass")
# Accessing database
db = client.tweets
# acessing a collection
posts = db.posts
data = list(posts.find(input))
return render_template('results.html', posts_info=data)
With this, I get a TypeError, which I somewhat expected as I didn't expect it to be this easy
After some reading online, I tried using a regex.
def display():
input = request.form['input'] # setting variable for user input
# Set up Mongo Client
client = MongoClient("mongo.user/pass")
# Accessing database
db = client.tweets
# acessing a collection
posts = db.posts
data = list(posts.find({Tweet: {$regex: input}}))
return render_template('results.html', posts_info=data)
This also didn't work so I tried to hard code the regex to see if it was the user input variable creating issues
def display():
input = request.form['input'] # setting variable for user input
# Set up Mongo Client
client = MongoClient("mongo.user/pass")
# Accessing database
db = client.tweets
# acessing a collection
posts = db.posts
data = list(posts.find({Tweet: {$regex: "GoT"}}))
return render_template('results.html', posts_info=data)
With both these methods, I get syntax errors at the start of the regex expression, and flags the $ before regex
Error message that I get reads:
File "pathToWebApp/webApp.py", line 71
data = list(posts.find({Tweet: {$regex: input}}))
^
SyntaxError: invalid syntax
I've never worked with MongoDB or used regexs so I'm at a complete loss here. I've scoured the mongo docs but nothing I've tried works so any help from anyone would be greatly appreciated
By the looks of it you might need to wrap the $regex key in quotes as well:
data = list(posts.find({Tweet: {"$regex": input}}))

O365 Powershell | Breaking up a long list into two sets of 100

I am looking to create a rule in Office 365 applied to all of the members in our org.
I would like this rule to append a warning on all incoming email from outside the organization with the same Display Names as our users.
When I attempt to apply it to all of the users in our org I get an error stating that the rule is too long.
In order to solve that I pulled a group, but I am still about 1000 characters over the limit.
I would like to make two variables, that each hold one half of the list, created by this command:
(Get-DistibutionGroupMember -Identity email#contoso.com -ResultSize Unlimited).DisplayName
I have attempted to modify the ResultSize parameter, but what I would need is result 1-100 and then 100-200 from the same list.
Another caveat to this problem is that the list cannot be static. It is something that the script will have to update every time it is run.
There is a sub-string command that you can use on a particular username that I have utilized when I made something for AD, but I am not aware of any way to break up a list like this.
If anyone has any other ways to solve this issue I would be more than open to any suggestion.
Thanks for taking the time to read this!
There are many ways of doing it. I found it very readable.
My favorite one is this one:
$ObjectList = 1..1000
$Step = 100
$counter = [pscustomobject] #{ Value = 0 }
$ObjectListSplitted = $ObjectList | Group-Object -Property { math]::Floor($counter.Value++ / $step) }
Then if you want to show the third subset just use this format :
$ObjectListSplitted[3].Group
Have a look to this solution already explained.
As a note other languages are capable of slicing an array of object with a start, stop and a step, have a look here if you're curious.

Tastypie relationship fields on obj_get_list

I have a very standard user/group many to many relationship with the following simplified definition:
class GroupResource(ModelResource):
users = fields.ToManyField(UserResource, 'group_set')
class Meta:
cache = SimpleCache()
queryset = Group.objects.all()
resource_name = "hr/group"
When I get a list groups it returns the group along with the list of uris of users connected to the group. However, our production system is starting to get quite large and a group can have hundreds of users in it. It is becoming painstakingly slow to return a list of groups, since each group also returns with it a list of users connected to that group.
Is there a way to exclude the linked users only for obj_get_list, but include the users when viewing the group instance? Or is there another solution to this problem that will fit better?
You need to specify a callable as use_in argument to fields.ToManyField which returns False if current request corresponds to get_list end point.
Example code
def is_not_group_get_list_end_point(bundle):
# TODO: use dynamically generated path here.
if bundle.request.get_full_path() == '/api/v1/hr/group/':
return False
return True
class GroupResource(ModelResource):
users = fields.ToManyField(UserResource, 'group_set',
use_in=is_not_group_get_list_end_point)
class Meta:
cache = SimpleCache()
queryset = Group.objects.all()
resource_name = "hr/group"

exporting MongoDB to CSV using pymongo

I would like write a script to generate a CSV file from my mongoDB database and I would like to know the most convenient version !
first let me begin with the structure of collections.
MyDataBase -> setting
users
fruits
in setting I have something like
setting -> _id
data
_tenant
and the thing I am after, is making a CSV file out of profiles in data
which they have some fields/properties like "name", "address", "postalcode", "email", age and etc. and not neccessary all of these profile have all files/properties and even some of them look like collection (have sub-branches) which I am not interested in at all !
so, my code is python so far is look like these
myquery = db.settings.find() # I am getting everything !
output = csv.writer(open('some.csv', 'wt')) # writng in this file
for items in myquery[0:10]: # first 11 entries
a = list(items['data']['Profile'].values()) # collections are importent as dictionary and I am making them as list
tt = list()
for chiz in a:
if chiz is not None:
tt.append(chiz.encode('ascii', 'ignore')) #encoding
else:
tt.append("none")
output.writerow(tt)
these fields/properties dont have neccessary all fields, and also even some of them are collection(with sub-branch) and will be imported as dictionary ! so, I have to convert them to list and all and all, there are quite few things to take care in such a process and in all doesn't look that straightforward !
My question might be sounds very general but is it a typical way to make such report ?! if not, can you someone make it clear ?!
Yes, I am using the same way.
It is clear and fast, also it works without of any additional libraries.

How to query Organizational Units from a given DN in Perl

I need to retrieve all Organizational Units from a given DN stringh, I am using Net::LDAP module and this little script:
my $msg = $ldap->search(
base=>'DC=sample1,DC=sample2',
filter=>'(objectclass=User)',
);
foreach $entry ($msg->entries) {
$dn = $entry->dn;
#how can i retrieve OUs?
}
For example if dn returns that string:
CN=Sample Sample,OU=One,OU=Two,DC=sample1,DC=sample2
I want to retrieve One and Two.
Issue a one level search request using the base object dc=example1,dc=sample2 and a presence filter of (ou=*). Given those results, issue a one level search using each returned ou with a presence filter of (ou=*). For each of these searches, specify a size limit and a time limit. For more information on search requests, see "LDAP: Using ldapsearch" and "LDAP: programming practices".
Most detailed "(&(ou=*)(objectClass=organizationalunit))"