Remove Duplicate Attributes for a (Core) SINGLE-VALUE NO-USER-MODIFICATION Attribute in LDAP - ldap

I recently set up a FreeIPA server (4.9.8) on Centos and a replica. Somehow—I don't even know how this is possible—all of my groups have ended up with two identical sets of core attributes:
dn: cn=<group name>,cn=groups,cn=accounts,dc=<domain>,dc=com
modifiersName: cn=MemberOf Plugin,cn=plugins,cn=config
modifiersName: cn=MemberOf Plugin,cn=plugins,cn=config
I have tried to ldapmodify the attributes deleting or replacing the values; I've tried deleting the groups completely but whatever I try it throws an error complaining that a single-value attribute has multiple values. It might be compounded by the fact that almost all the groups also belong to another group so it's impossible to delete one without trying to make a modification to the membership of that main group and vice versa.
I found the attribute in the core schema for the directory and it is SINGLE-ATTRIBUTE NO-USER-MODIFICATION.
Any thoughts on how to resolve this?

I see, modifiersName is a SINGLE-VALUE with NO-USERMODIFICATION. No chance to modify without delete object.
At least to query similar cases with multi Attributes with different (or same) values can can use the following awk script, if you like.
Firstly: you should export your objects in ad ldif file (REPORT.ldif)
grep '^dn:\|^cn:' REPORT.ldif | awk
'BEGINN {L1="",L2="";TYP="";DN_PREF="dn:";DN=""}
{
if (TYP==$1) {
printf("\n%s %s\n%s %s\n%s %s\n--------",
DN_PREF,DN,
$1,$2,
L1,L2);
}
if (TYP==$1) {
DN=$2;
}
L1=$1;
L2=$2;
}'
Ouput:
dn ...
cn value1
cn value2
Cn ...
--------
dn ...
cn ...
cn ...
--------
...

Related

LDAP Filter Syntax Query

What would be the syntax for LDAP for the below scenario:
Where sAMAccountName = GRA-* without $. I want the records which are highlighted in green.
This is my current LADP Filter for your reference:
(&(objectClass=user)sAMAccountName=GRA-*))
Anyone, Please help with the correct syntax.
Your filter can work, but you're missing a ( in front of sAMAccountName:
(&(objectClass=user)(sAMAccountName=GRA-*))
But you may be able to do better. If those ones that end in $ are computer objects (which always have sAMAccountNames that end in $, but also have an objectClass of user), then you can make sure you only get user objects by including (objectCategory=person):
(&(objectClass=user)(objectCategory=person)(sAMAccountName=GRA-*))
If, for whatever reason, those $ objects are actually user accounts, then you can exclude them with (!sAMAccountName=*$):
(&(objectClass=user)(objectCategory=person)(sAMAccountName=GRA-*)(!sAMAccountName=*$))

TypeORM View Entity synchronization (creation) order problems

Using TypeORM, I'm trying to create ViewEntities that depend on each other, for example "View B" select from "View A". No matter what I do I can't get the ViewEntities to get created in the order of dependency. Sometimes "View B" is created first, and the synchronization process fails, because it can't find "View A", since it's not created yet.
The error:
QueryFailedError: relation "public.course_item_view" does not exist
Solutions I have tried:
Renaming the ViewEntity files (to check if the system uses ABC ordering on file names)
Renaming the ViewEntity classes (to check if the system uses ABC ordering on class names)
Renaming the ViewEntity's "name" property (to check if the system uses ABC ordering on the final SQL view names)
Reordering the ViewEntity class references in the "entities: []" array of the connection options
Reordering the ViewEntity class imports in the file where I declare the connection options
Removing/Adding the file again (to check if the system uses Creation Date based ordering)
Modifying the files (to check if the system uses Modification Date based ordering)
All of these failed. I cannot figure out how the system determines the order in which the view's are created.
Any help would be GREATLY appreciated!!
Expected Behavior
The view's should be created in an order that is either specified by a property inside the views, or the order should be resolved automatically from the SELECT statements (dependency array), or it should be based on the order in which I reference the ViewEntities in the "entities: []" array of the connection options, or any other solution would be perfect where one could determine the order in which the ViewEntities are created.
Actual Behavior
The ViewEntites are created in an order that I honestly can't understand. Sometimes a dependent ViewEntity is created before the ViewEntitiy it depends on. This causes the synchronization to fail.
File name: "CourseItemView" which resolves to: "course_item_view"
#ViewEntity({
expression: `
SELECT
"uvcv"."userId",
"uvcv"."courseId",
"uvcv"."videoId",
CAST (null AS integer) AS "examId",
"uvcv"."isComplete" AS "isComplete"
FROM public.video_completed_view AS "uvcv"
UNION ALL
SELECT
"uecv"."userId",
"uecv"."courseId",
CAST (null AS integer) AS "videoId",
"uecv"."examId",
"uecv"."isCompleted" AS "isComplete"
FROM public.user_exam_completed_view AS "uecv"
.
.
File name: "CourseItemStateView" which resolves to: "course_item_state_view"
This DEPENDS on the "course_item_view", as you can see in the SQL
#ViewEntity({
expression: `
SELECT
"course"."id" AS "courseId",
"user"."id" AS "userId",
"civ"."videoId" AS "videoId",
"civ"."isComplete" AS "isVideoCompleted",
"civ"."examId" AS "examId",
"civ"."isComplete" AS "isExamCompleted"
FROM public."course"
LEFT JOIN public."user"
ON 1 = 1
LEFT JOIN public.course_item_view AS "civ" ------------------- HERE
ON "civ"."courseId" = "course"."id"
AND "civ"."userId" = "user"."id"
ORDER BY "civ"."videoId","civ"."examId"
`
})
.
.
My connection options:
const postgresOptions = {
// properties, passwords etc...
entities: [
// entities....
// ...
// ...
// views
VideoCompletedView,
UserExamCompletedView,
UserExamAnswerSessionView,
UserVideoMaxWatchedSecondsView,
CourseItemView, --------------------------------HERE
CourseItemStateView ---------------------------HERE
],
} as ConnectionOptions;
createConnection(postgresOptions )
Steps to Reproduce
Create ViewEntites that depend on each other
You will run into this issue, but is hard to say exactly why and when, this is the main problem.

Trying to filter an AD export script in powershell by user type?

I've been asked to pull a report containing User's name, username, enabled/disabled, and the last login time from our Windows server 2008 domain. I'm using the script below and it's working, but the problem is it's pulling built-in security accounts and some system accounts, and I need just users. Does anyone know if this filtering is possible? The script I'm using is below. Thanks in advance!
$ADUserParams=#{
'Server' = 'servername.domain.local'
'Searchbase' = 'DC=domain,DC=local'
'Searchscope'= 'Subtree'
'Filter' = '*'
'Properties' = '*'
}
$SelectParams=#{
'Property' = 'CN', 'SAMAccountname', 'DisplayName', 'enabled', 'lastlogondate',
}
get-aduser #ADUserParams | select-object #SelectParams | export-csv "c:\temp\users.csv"
At the very least you'll want to modify your filter to something like:
'(&(|(objectclass=person)(objectclass=inetorgperson))(!(objectclass=computer)))'.
That will still leave Administrator, Guest and and domain/realm trusts you've got, but otherwise it's pretty clean.
'(&(sAMAccountType=805306368)(!(isCriticalSystemObject=TRUE)))' is even cleaner, and may be exactly what you need. This uses sAMAccountType, but I pulled from existing AD users rather than build that value from scratch.
Also there is no Enabled attribute. The closest you can get is userAccountControl. lastLogonDate is actually lastLogonTimestamp.
part of your requirements for the report are to show all users in AD, this would include system and built-in accounts. That being said, ff you can exclude the OUs or containers that contain the built-in/system accounts you don't want in the report that would be easiest. It looks like your trying to audit the whole AD DS and should use exclusions otherwise only include the OU that contains the User Accounts as long as it is only possible to not have User accounts anywhere else.
It really depends on what you can use to separate your built-ins and system accounts.
The easiest way would be to add a SearchBase to your $ADUserParams:
$ADUserParams=#{
'Server' = 'servername.domain.local'
...
'SearchBase' = 'OU=Lemmings,DC=contoso,DC=com'
}
If there's one OU that you need to filter out, try adding a Where-Object:
get-aduser #ADUserParams | ?{$_.DistinguishedName -notlike '*ou=Beancounters,*'} | select-object #SelectParams | export-csv c:\temp\users.csv"
The ?{ } bit is an alias for the Where-Object command. $_ represents the objects passed along the pipe.
This is all assuming that these accounts are cleanly separated by OU, however. I know this isn't true in my environment.
You might have to play around for a while before finding something that will separate your users cleanly. It might help to store your initial query as a variable, $users = Get-ADUser #ADUserParams, and see what you can pick apart:
$users | ?{$_.SomeProperty -eq 'SomeValue'}
Try running $users[0] to get an idea of what properties there might be to help you filter through these users. If you need to wrap your head around things like -eq and -like, take a look here.
If all the accounts you're wanting to filter contain a character like $, you could filter the output like so:
$users | ?{$_.SamAccountName -notlike "*$*"}

Is there a way to do an LDAP query to get records where a particular attribute is the same?

I am trying to find an example LDAP query where I can find records where a particular attribute matches one or more other records. For instance, a user object where the userid is different, but the employee ids are the same. Is this even possible?
From a single LDAP query no. Unless you know the emplyeeID value you are looking for.
We created an LDAP tool, Duplicate Attribute Value Locater Tool, that will do this.
-jim
It's not possible to do sub queries within the filter itself. In this case, as long as I understand correctly, you'd like to find users that match :
objectClass of User
match on the value of employeeID
Out of the above subset, find all with a DISTINCT 'userid'
If you knew what userid to look for, or NOT look for, you could expand the inital AND clause to include finding, or not finding, that attribute :
userid not equal to 12345 :
(&(objectClass=person)(employeeID=JSmith)(!(userid=12345)))
userid equal to 12345 :
(&(objectClass=person)(employeeID=JSmith)(userid=12345)
I found this example for 'myattribute'. Needs some polish, and depending on the size of your directory, it could take a while to run. If that's the case, I'd break it up by attribute sections {attr=aa*, attr=ab*, attr=ac*, etc.}.
ldapsearch -x -h ldapserver.domain.com -b ou=myldap,o=mydomain.com "(&(myattribute=aa*))" myattribute | grep '^myattribute:' | sort | uniq -c| sort -n|awk '$1 > 1 { print }'

Modify entry in OpenLDAP directory

I have a large Openldap directory. In the directory the display name property for every is filled but i need to modify these entry and make it like "givenName + + sn". Is there are way i can do it directly in the directory just like sql queries (update query). I have read about the ldapmodify but could not find the way to use it like this.
Any help in this regard will be appreciated.
There is no way to do this with a single LDAP API call. You'll always have to use one LDAP search operation to get givenname and sn attributes, and one LDAP modify operation to modify the displayName attribute.
If you use the command line ldaptools "ldapsearch" and "ldapmodify", you can do this easily with some shell scripting, but you'll have to be careful: sometimes ldapsearch(1) can return LDIF data in base64 format, with UTF-8 strings that contain characters beyond ascii. For instance: 'sn:: Base64data' (note the double ':')
So, if I were you I would use a simple script in my language of choice, that has an LDAP API, instead of using shell commands. This would save me the troubles of base64 decoding that the ldaptools sometimes impose.
For instance, with php-cli, your script would be roughly like this (perhaps some more error checking would be appropriate):
<?php
$ldap = ldap_connect('host');
ldap_bind($ldap, ...);
$sr = ldap_search($ldap, 'ou=people,...', 'objectclass=*');
$entries= ldap_get_entries($ldap, $sr);
for($i=0; $i<$entries['count']; $i++) {
$modify = array('displayname' => $entries[$i]['givenname'] . ' ' . $entries[$i]['sn']);
ldap_modify($ldap, $entries[$i]['dn'], $modify);
}
Addendum: if you want to keep this data up to date without any intervention, you will probably need to use a specialized OpenLDAP module that keeps "virtual" attributes, or even a virtual directory, such as Penrose or Oracle Virtual Directory, on top of OpenLDAP. However this might be overkill for a simple concatenation of attributes.