Ruby scripting on microsoft active directory plus exchange


#1

Hi All,

Just want to ask anyone in this list doing ruby scripting on active
directory plus exchange server. Basically i want to query all ad users
who have mailboxes and for each mailbox also display all the other users
who may have rights to access it too [*]. Pls pardon my ignorance on
msoft scripting.

Many thanks in advance.
kind regards -botp

[*] it is amazing that to manage a million bucks proprietary system, i’d
have to use a system as so free as ruby. surely ruby must be worth like
“ruby”, a gem indeed.


#2

I would recommend looking at Net::LDAP: gem install ruby-net-ldap

I’ve been using it in Rails Applications to authenticate against AD, as
well
as check group memberships.

On 4/18/07, Peña, Botp removed_email_address@domain.invalid wrote:

kind regards -botp

[*] it is amazing that to manage a million bucks proprietary system, i’d
have to use a system as so free as ruby. surely ruby must be worth like
“ruby”, a gem indeed.


“Hey brother christian with your high and mighty errand, Your actions
speak
so loud, I can’t hear a word you’re saying.”

-Greg Graffin (Bad Religion)


#3

On 4/19/07, Glen H. removed_email_address@domain.invalid wrote:

I would recommend looking at Net::LDAP: gem install ruby-net-ldap

Glen, while I can do nothing other than warmly second your
recommendation
:-), I know for sure that Botp already knows about Net::LDAP. In fact
he’s
already given me feature requests and suggestions.

Since A/D is such a special beast compared to other LDAP servers, and
since
many people use it for authorization as well as authentication, I’d like
to
know the following:

Can we get a small but specific list of commonly-used operations against
A/D
that can be implemented in Net::LDAP and supplied with that library out
of
the box? Botp, your request is quite close, but I don’t exactly
understand
the second half of it (querying memberships associated with a particular
mail address?).


#4

On 4/19/07, Francis C. removed_email_address@domain.invalid wrote:

the second half of it (querying memberships associated with a particular
mail address?).

You can do some bizarre things with Exchange. For example, if I
remember
correctly, you can create mailbox entities that aren’t necessarily tied
to a
particular user account. These can then be treated like any other AD
object/container/whatever Microsoft wants to call them. Hence group
membership would allow multiple user accounts access to the mailbox. I
personally don’t like it at all although I don’t like brussel sprouts
either
but occasionally find I have to eat them. Also my only experience with
Exchange it’s self was recovering a mailbox that had been synced with
empty
data by the head admin. That was no fun and has possibly tainted my
views.

I’m not sure exactly how these appear in the AD structure though. I
never
had to go that low to fix the problem.

Francis, is there a place where you would like to
address/discuss/collect
the commonly-used operations you mentioned? I don’t know that I would
have
much to add as I haven’t done anything too involved with AD but I would
be
happy to provide my input.


“Hey brother christian with your high and mighty errand, Your actions
speak
so loud, I can’t hear a word you’re saying.”

-Greg Graffin (Bad Religion)


#5

I would recommend looking at Net::LDAP: gem install ruby-net-ldap

I’ve been using it in Rails Applications to authenticate
against AD, as well as check group memberships.

I can do the former, but in my almost complete ignorance of LDAP and AD,
have been unable to accomplish the latter. How do you do it?

  • donald

#6

On 4/19/07, Ball, Donald A Jr (Library) removed_email_address@domain.invalid
wrote:

I would recommend looking at Net::LDAP: gem install ruby-net-ldap

I’ve been using it in Rails Applications to authenticate
against AD, as well as check group memberships.

I can do the former, but in my almost complete ignorance of LDAP and AD,
have been unable to accomplish the latter. How do you do it?

I believe that somewhere there is a wiki article (not written by me) on
how
to use Net::LDAP in Rails for authentication. Mr. Google should be able
to
find it for you. If you’re still stuck, feel free to send me a private
email.


#7

On 4/19/07, Glen H. removed_email_address@domain.invalid wrote:

Exchange it’s self was recovering a mailbox that had been synced with
much to add as I haven’t done anything too involved with AD but I would be
happy to provide my input.

Let’s attach it to this thread for the time being. That will give others
the
opportunity to show interest as well. There is no Net::LDAP wiki as far
as I
know but that would be easy enough to fix.

There’s another thing I and some others have been working on for some
years
now: a network-service that would provide fine-grained authorization to
any
application (including Rails of course) through the XACML protocol. The
goal
would be to permit access-control policies to be defined in isolation
from
specific applications, and managed centrally. We’d like to release this
as
an open-source project, probably as part of the Net::XACML project on
Ruyforge. Anyone interested?


#8

There is an attribute called memberof which has a list of all
the groups the user account belongs to. You should be able
to call memberof on your returned LDAP object and get an
array with the groups in it.

That works great, thanks! A quick followup if you don’t mind: if I’m
trying to authenticate a user and see if she belongs to either of two
groups, say, is it better to search twice against two different
treebases and simply see if either returns a match, or search in the
nearest common ancestor and check the memberof attribute?

  • donald

#9

On 4/19/07, Ball, Donald A Jr (Library) removed_email_address@domain.invalid
wrote:

There is an attribute called memberof which has a list of all the groups
the
user account belongs to. You should be able to call memberof on your
returned LDAP object and get an array with the groups in it.


“Hey brother christian with your high and mighty errand, Your actions
speak
so loud, I can’t hear a word you’re saying.”

-Greg Graffin (Bad Religion)


#10

On 4/19/07, Ball, Donald A Jr (Library) removed_email_address@domain.invalid
wrote:

nearest common ancestor and check the memberof attribute?

  • donald

I would guess that the latter would be faster. Although I have no idea
how
your directory is organized or how large it is.

Francis, your Net::XACML proposition sounds very interesting. I would
be
happy to provide what help I can. I should forewarn you though, I’m new
to
ruby and haven’t done any serious programming in a while. As for my
ideas
with regards to Net::LDAP and A/D. I will collect them and post
something
later today (work has been a bit hectic).


“Hey brother christian with your high and mighty errand, Your actions
speak
so loud, I can’t hear a word you’re saying.”

-Greg Graffin (Bad Religion)


#11

On 4/19/07, Glen H. removed_email_address@domain.invalid wrote:

Francis, your Net::XACML proposition sounds very interesting. I would
be
happy to provide what help I can. I should forewarn you though, I’m new
to
ruby and haven’t done any serious programming in a while. As for my ideas
with regards to Net::LDAP and A/D. I will collect them and post something
later today (work has been a bit hectic).

With regard to XACML, it would be enough for interested people to
suggest
applications and be wiling to try our code out. We’re getting closer to
a
beta drop of an authorization engine (no more than a few weeks away or
less)
and I’ll announce it here. As I said, it’s the fruit of years of labor,
but
it’s only recently that people are getting interested in the idea of a
centralized authorization service.


#12

Ball, Donald A Jr (Library) wrote:

There is an attribute called memberof which has a list of all
the groups the user account belongs to. You should be able
to call memberof on your returned LDAP object and get an
array with the groups in it.

That works great, thanks! A quick followup if you don’t mind: if I’m
trying to authenticate a user and see if she belongs to either of two
groups, say, is it better to search twice against two different
treebases and simply see if either returns a match, or search in the
nearest common ancestor and check the memberof attribute?

Beware that if you encounter a group that has more than 1000 members,
Microsoft AD has a custom extension to the standard LDAP protocol to
handle paging. Basically you get an attribute returned that has an
extended name, and not all values. IIRC the extension is “;min-max”
where min and max are the index numbers of the first and last value
returned from the members array. You need then to repeat the query,
asking for a similarly-named attribute with larger min and max
numbers, until a query returns fewer than you asked for.

Clifford H…


#13

On 4/19/07, Francis C. removed_email_address@domain.invalid wrote:

something
it’s only recently that people are getting interested in the idea of a
centralized authorization service.

I can actually only think of a couple of things right now.

First, when attempting bind_as with non administrator level credentials
and
the :base set to the root of the tree I get an invalid credentials error
message, It has to be the permissions on the tree. I’m not sure if this
is
the default A/D configuration or not but I have a feeling (after talking
to
the admin) that it is. It would be nice if there were a way for
:bind_as or
maybe a new method :bind_as_ad to automatically change the base to
whatever
normal user accounts try to authenticate against. I’m not sure what
that is
if such a thing exists though.

A few simple wrappers for those not familiar with A/D that want to get
“standard” info out of the directory might be nice too. For example a
groups method so those unfamiliar with A/D don’t have to dig through the
directory structure to find memberof, also things like username to grab
the
cn value.

Some might also find some sort of clean interface for grabbing machine
account info to be useful as well.


“Hey brother christian with your high and mighty errand, Your actions
speak
so loud, I can’t hear a word you’re saying.”

-Greg Graffin (Bad Religion)


#14

On 4/19/07, Francis C. removed_email_address@domain.invalid wrote:

There’s another thing I and some others have been working on for some years
now: a network-service that would provide fine-grained authorization to any
application (including Rails of course) through the XACML protocol. The goal
would be to permit access-control policies to be defined in isolation from
specific applications, and managed centrally. We’d like to release this as
an open-source project, probably as part of the Net::XACML project on
Ruyforge. Anyone interested?

That’s awesome. At work I am just starting on an XACML project. I am
certainly interested in taking your code for a spin when it’s published
:slight_smile:


#15

On 4/30/07, removed_email_address@domain.invalid removed_email_address@domain.invalid wrote:

specific applications, and managed centrally. We’d like to release this
as
an open-source project, probably as part of the Net::XACML project on
Ruyforge. Anyone interested?

That’s awesome. At work I am just starting on an XACML project. I am
certainly interested in taking your code for a spin when it’s published
:slight_smile:

We just swung this project into a higher gear and hope to complete a
release
in the next several weeks. I took the liberty of writing to your address
to
get some idea of your requirements. If anyone else is interested, please
feel free to contact me directly. We’re definitely interested in getting
people to test the code and contribute ideas, particularly as regards
integration with Rails.


#16

On 4/19/07, Clifford H. removed_email_address@domain.invalid wrote:

Beware that if you encounter a group that has more than 1000 members,
Microsoft AD has a custom extension to the standard LDAP protocol to
handle paging. Basically you get an attribute returned that has an
extended name, and not all values. IIRC the extension is “;min-max”
where min and max are the index numbers of the first and last value
returned from the members array. You need then to repeat the query,
asking for a similarly-named attribute with larger min and max
numbers, until a query returns fewer than you asked for.

I’m sorry, I just noticed this, although it’s quite a few days old now.
The
extension you’re talking about is RFC-2696, so although it’s definitely
a
hack invented by Microsoft for their own purposes, it’s probably a
misnomer
to call it a “custom extension” to the standard. They did implement it
as a
V3-standard LDAP “control.” Recent versions of the OpenLDAP server
support
it as well, but it’s not mandatory as it is with A/D. However, paged
searches behave just differently enough on OpenLDAP to keep things
interesting.

If you try a query against A/D that will return more than 1000 rows, you
should find that it “just works” with Net::LDAP. As far as I know, none
of
the other implementations (including ldapsearch) work correctly without
setting extra parameters, but that may have changed since the last time
I
looked.