I'm attempting to find out if a user is an indirect member of a specific AD group. This is done from a Delphi XE5 program but, for clarity, I have written (and tested) my samples in PowerShell.
Unfortunately, I receive completely inconsistent results from my LDAP queries: the same query will sometime work fine and, sometimes, return that the user isn't member of the given group.
Here is a (powershell) sample of what I'm attempting:
get-aduser -LDAPFilter "(memberof:1.2.840.113556.1.4.1941:=CN=egaa_app,OU=Applications,OU=access,OU=groups,OU=xxx,DC=xxx,DC=xxx,DC=xxx)" -SearchBase "CN=usr-sgr,OU=expert1,OU=experts,OU=remoteusers,OU=users,OU=exogit,OU=xxx,DC=xxx,DC=xxx,DC=xxx"
The above command should return the user usr-sgr object if it is directly or indirectly member of the AD groupegaa_app,OU=Applications,OU=access,OU=groups,OU=xxx,DC=xxx,DC=xxx,DC=xxx
Yet, when I run it once, I get an empty result. If I open the user in the AD MMC and update it somehow (in my case, I changed the user's "primary group" and then changed it back), the same query successfully returns the user object.
I have also attempted to use the "reverse" query (which check if a given group contains the user indirectly) and I witnessed the same behavior.
All this was done on a member server (Windows 2008 R2, patched), from within the same login session.
I think I can explain this to you.
First a small recall of the LDAP_MATCHING_RULE_IN_CHAIN :
The LDAP_MATCHING_RULE_IN_CHAIN is a matching rule OID that is designed to provide a method to look up the ancestry of an object. An example of such a query is one designed to check if a user "user1" is a member of group "group1". You would set the base to the user DN (cn=user1, cn=users, dc=x) and the scope to base, and use the following query.
(memberof:1.2.840.113556.1.4.1941:=cn=Group1,OU=groupsOU,DC=x)
Here the attribute memberof is the one that is going to be searched in chain in each group object. Use the attribute editor from the 'user & computer active directory' MMC to follow this attribute :
And then change the primary group, you will see that the new primary group disappear from the memberof attribute list, and the old one appear in the attribute.
Conclusion, the primary group is unsupported by the LDAP_MATCHING_RULE_IN_CHAIN.
In any case be careful to setup the scope -SearchScope in PowerSell.
By the way, for me, the best tool to test this kind of filter is LDIFDE.EXE.
ldifde -f c:\temp\test.ldif -d "CN=Jean-Paul Blanc,OU=Interne,OU=Silogix,DC=silogix,DC=local" -r "(memberof:1.2.840.113556.1.4.1941:=CN=bidon,OU=Interne,OU=Silogix,DC=silogix,DC=local)" -p base
Related
I have to maintain a PowerShell script which transfer the employees informations from our database into our Active Directory.
This script runs every night automatically with elevated rights that I do not posess. In other words, I cannot "test" the script. To run the script, I have to commit my changes and create a PR that will trigger a deployment when accepted and wait until the next morning to see if it worked.
The informations are usually updated without any problems, except for the country. I tried updating the fields countryCode, c and co and it didn't work because we received an error like "value was not in the acceptable range...". Apparently this error happens when you try to update one of these 3 fields separately.
I found how to update them all at once and I was going to make the changes but I was surprised to discover that there is another field called Country.
I have a few questions :
Why does that Country field even exist ? Aren't countryCode, c and co enough ?
Should I update Country or should I update the countryCode, c and co ?
Why are there 4 different fields in the AD just to hold the country ?
I'd like to know more about this because I really want to get this right on the second try (the first one failed, hence why I'm here) Thanks in advance for your help !
Why does that Country field even exist ? Aren't countryCode, c and co enough ?
It doesn't actually exist - the Country property exposed by the ActiveDirectory module maps directly to the c attribute in the AD schema - it's just an alias.
Should I update Country or should I update the countryCode, c and co?
Given the answer above, no, you don't need to set Country when you set c.
Why are there 4 different fields in the AD just to hold the country ?
As we've established, there are only 3:
c is part of LDAPv3 specification (see RFC2256) to ensure compatibility with X500 DITs.
co was (to my best knowledge) included in the original schema for NT domains for the same reason
countryCode was introduced in the AD schema to help administrative tools enforce input validation of country names - unlike co, it's an enumeration type, and tools like "Active Directory Users and Computers" populate the Country dropdown with the possible enumeration values and then sets all three fields based on the chosen values
If you have null values for the users you need to change the country to, it worked for me like this, hope this helps somebody, it gave me some headaches until I figured it out.
$users = get-aduser -SearchBase "ou=RandomOU, Ou=AnotherOU, DC=Domain, Dc=local" -Filter * -Properties c,co,countrycode | Where-Object{$_.co -eq $null}
$users | Set-ADUser -Replace #{c="RO";co="Romania";countrycode=642}
if the user exist in AD.I am trying to add by adding 1 at end and then adding it to AD but it showing this exception
It would be helpful if you show your code so we can see exactly what you are doing. But I suspect I might know.
There are 3 attributes that are enforced unique in AD:
sAMAccountName (commonly called the "username") has to be unique on the domain
userPrincipalName has to be unique in the forest
cn attribute (or the "name") has to be unique in the OU
So I suspect you added a "1" to one of them, but not all.
If you're not sure how to do that properly, then update your question with the code you are using and we can help.
I am creating a script that should check the file server for shares, and should list user's that have any kind of access control type (allow / deny) and their rights on the share. I've successfully managed to create collection of objects that have data that I want, but I have issues formatting them in the way I want.
Current situation, how the collection looks like
Path Identity Access Rights
Share1 User1 Allow Full Control
Share1 Group1 Allow Full Control
Share2 Group1 Deny Full Control
Share2 Group2 Allow Modify
I am fine with having shares appear in multiple objects, with one identity (user or a group) per object, but I would like to expand groups with its members, when the $_.Identity in pipe is a group. But I have issues getting there
My code example is practically non existing, I just tried to check every object in the pipe if it's Identity can be used with Get-ADGroupMember but that's it
$Collection | ForEachObject { if (Get-ADGroupMember $_.Identity) {Get-ADGroupMember $_.Identity }} ...
Desired solution should be like this:
Path Identity Access Rights
Share1 User1 Allow Full Control
Share1 User1,User2 Allow Full Control
Share2 User1,User2 Deny Full Control
Share2 User2,User3 Allow Modify
In this test example, Group1 is consisted of User1 and User2, while Group2 is consisted of User2 and User3.
Any help is appreciated.
I think what I would do is to generate the value on the pipeline like this:
$Collection | Select Path,#{l='Identity';e={ if (Get-ADGroupMember $_.Identity) {(Get-ADGroupMember $_.Identity) -join ", "}else{$_.Identity}}},Access,Rights
I was working on a very similar script. Rather than bore you with my code, here's where I found assistance in sorting out the nested groups.
Sort Nested Groups
Basically, you create a function to get all the group members and then test each item. If it is a group, call the same function and pass it the newly found group name.
Regarding:
$_.identity
I used
$_.objectclass
That will tell you if the get-adgroupmember result is a user or group. It will error on users, but I just suppress the errors at runtime with
$erroractionpreference = "silentlycontinue"
That's probably not best practice, but it works for me.
I tested this with circular nesting and it does not get stuck in an infinite loop. It actually handled it perfectly by returning the individual results only once. Probably has to do with safeguards built into windows for cirucular nesting situations.
Some of the info here might be helpful as well:
Circular Nesting Consequences - ServerFault
We're converting all SP permissions into ActiveDirectory groups (one per uninherited object, per role level). I wanted the group names to reflect where the permissions were/are, so I assigned each group with a name that matched the site structure:
sitecollection|site|list|Full Control
Active Directory had issues with the pipes and the potential length, so I reconfigured everything to use the description of the Active Directory object instead. The actual CN of the group is -someNumber- (-1-,-2-, etc).
I ran across an interesting phenomena while adding the groups into SharePoint under the same role level; I had to start the groups at 1000 else the EnsureUser couldn't find the group no matter what.
$web.EnsureUser('c:0-.f|myprovider|-1-') says it doesn't exist, whereas $web.EnsureUser('c:0-.f|myprovider|-1000-') does just fine.
Is there some sort of limitation to the number of characters a SAM Account Name / Principal Name must be when being searched by SharePoint?
You need to include the Domain name in EnsureUser - Domain\Username
Or you can just add i:0#.f|myprovider| to the username so it looks like i:0#.f|myprovider|myuser and pass the result into EnsureUser. In my case "myprovider" is the name of my custom membership provider.
I'm trying to build a LDAP query that searches for groups that are owned (multivalued attribute) by a particular user and nobody else.
Simple Exp:
Group A: Owners [Bob, Joe, Bill]
Group B: Owners [Bob]
Group C: Owners [Carl]
Only group b should be returned by this query if I was looking for Bob. My current query pulls all groups where a named person is an owner then I'm using Perl to loop through the results and find what I need, but it seems a little inefficient. Any pointers or suggestions would be appreciated.
You can't. There is no LDAP filter syntax that can possibly accomplish that. See RFC 2254. This is a very strange design. It doesn't map not LDAP can do at all.