I was working away updating the usage and examples for AdMod this evening and ran a couple of test commands to figure out which ones I want to document. I like to play against ADAM as it is all local and just because I like playing with ADAM.
Anyway, I fired one of my saved ADAM instances up that has a little over 7000 users in an application partition and went from there… I decided to blog this because to be honest, I am sick of working on usage documentation at the moment. I don’t write these cool tools to document the switches but to actually use them and solve problems. 🙂
First, I added a new attribute to the directory to play with
F:\Dev\CPP\AdMod>admod -h . -add -schema -rb CN=joeware-UAC objectclass::attributeschema attributeid::[secret oid] attributesyntax::2.5.5.9 issinglevalued::TRUE omsyntax::2 ldapdisplayname::joeware-UAC
AdMod V01.07.00cpp_ALPHA Joe Richards (joe@joeware.net) July 2006
DN Count: 1
Using server: 2k38500.joe.com
Adding specified objects…
DN: CN=joeware-UAC,CN=Schema,CN=Configuration,CN={7017763A-D4D1-4EBA-AA7D-B3C8FDA427D3}…The command completed successfully
Then I associated the new attribute with the user class
F:\Dev\CPP\AdMod>admod -h . -schema -rb cn=user maycontain:+:joeware-UAC
AdMod V01.07.00cpp_ALPHA Joe Richards (joe@joeware.net) July 2006
DN Count: 1
Using server: 2k38500.joe.com
Modifying specified objects…
DN: cn=user,CN=Schema,CN=Configuration,CN={7017763A-D4D1-4EBA-AA7D-B3C8FDA427D3}…The command completed successfully
Then I set every user in the application partition to a value of 512
F:\Dev\CPP\AdMod>adfind -h . -b ou=mytestou -f objectclass=user -adcsv | admod joeware-UAC::512 -unsafe -exterr -elapsed
AdMod V01.07.00cpp_ALPHA Joe Richards (joe@joeware.net) July 2006
………………………………………………………………
DN Count: 7269
Using server: 2k38500.joe.com
Modifying specified objects…
DN: CN=$jricha34,CN=Users,OU=import,OU=MyTestOU…
DN: CN=postmaster,OU=MailUsers,OU=joeware2,OU=Exchange,OU=import,OU=MyTestOU…
DN: CN=Guest,CN=Users,OU=import,OU=MyTestOU…
DN: CN=administrator,CN=Users,OU=import,OU=MyTestOU…
DN: CN=krbtgt,CN=Users,OU=import,OU=MyTestOU…
…[SNIP]
…
DN: CN=autouser_21,OU=AutoUsers,OU=import,OU=MyTestOU…
DN: CN=autouser_22,OU=AutoUsers,OU=import,OU=MyTestOU…
DN: CN=autouser_23,OU=AutoUsers,OU=import,OU=MyTestOU…
DN: CN=autouser_24,OU=AutoUsers,OU=import,OU=MyTestOU…Time Elapsed (sec):58.803
The command completed successfully
As you can see, 7000+ objects set with that attribute in under a minute and that is with the DS running on a slow laptop, my old Dell 8500… Oh, you may notice the objectclass=user… normally this isn’t efficient but I tend to index objectclass in my ADAM instances so it is perfectly fine. 🙂
So now… you want to see some new cool power? I want to set bit 5, value 32. In Windows AD this userAccountControl value would be the PWD_NOT_REQD flag. So here we go
F:\Dev\CPP\AdMod>adfind -h . -b ou=mytestou -f objectclass=user joeware-UAC -adcsv | admod joeware-UAC::{{joeware-UAC:SET:32}} -unsafe -exterr -elapsed
AdMod V01.07.00cpp_ALPHA Joe Richards (joe@joeware.net) July 2006
………………………………………………………………
DN Count: 7269
Using server: 2k38500.joe.com
Modifying specified objects…
DN: CN=$jricha34,CN=Users,OU=import,OU=MyTestOU…
DN: CN=postmaster,OU=MailUsers,OU=joeware2,OU=Exchange,OU=import,OU=MyTestOU…
DN: CN=Guest,CN=Users,OU=import,OU=MyTestOU…
DN: CN=administrator,CN=Users,OU=import,OU=MyTestOU…
DN: CN=krbtgt,CN=Users,OU=import,OU=MyTestOU…
…[SNIP]
…
DN: CN=autouser_21,OU=AutoUsers,OU=import,OU=MyTestOU…
DN: CN=autouser_22,OU=AutoUsers,OU=import,OU=MyTestOU…
DN: CN=autouser_23,OU=AutoUsers,OU=import,OU=MyTestOU…
DN: CN=autouser_24,OU=AutoUsers,OU=import,OU=MyTestOU…Time Elapsed (sec):59.370
The command completed successfully
Now maybe you want to clear the same bit for up to 1000 of the users. You can do this either from AdFind with the -MAXE switch or the new -UPTO switch in AdMod. The -UPTO switch is similar to -SAFETY except that instead of ending the program and making no changes if there are more than the specified number of objects to modify, it modifies that many objects and then stops.
F:\Dev\CPP\AdMod>adfind -h . -b ou=mytestou -f objectclass=user joeware-UAC -adcsv | admod joeware-UAC::{{joeware-UAC:CLR:32}} -upto 1000 -exterr -elapsed
AdMod V01.07.00cpp_ALPHA Joe Richards (joe@joeware.net) July 2006
………………………………………………………………
DN Count: 7269
More DNs than -UpTo specified: 1000
Trimming list to specified size.Using server: 2k38500.joe.com
Modifying specified objects…
DN: CN=$jricha34,CN=Users,OU=import,OU=MyTestOU…
DN: CN=postmaster,OU=MailUsers,OU=joeware2,OU=Exchange,OU=import,OU=MyTestOU…
DN: CN=Guest,CN=Users,OU=import,OU=MyTestOU…
DN: CN=administrator,CN=Users,OU=import,OU=MyTestOU…
DN: CN=krbtgt,CN=Users,OU=import,OU=MyTestOU…
…[SNIP]
…
DN: CN=u951,OU=tmptestou,OU=joeware2,OU=Exchange,OU=import,OU=MyTestOU…
DN: CN=u952,OU=tmptestou,OU=joeware2,OU=Exchange,OU=import,OU=MyTestOU…
DN: CN=u953,OU=tmptestou,OU=joeware2,OU=Exchange,OU=import,OU=MyTestOU…
DN: CN=u954,OU=tmptestou,OU=joeware2,OU=Exchange,OU=import,OU=MyTestOU…Time Elapsed (sec): 8.896
The command completed successfully
If you are used to using the DS* tools you will probably think, whoa, that seems a bit faster. Yes… it is. The reason is that the -ADCSV switch in AdFind is a type of CSV output that helps AdMod figure out what to do and makes it so AdMod doesn’t have to look up the current value of joeware-UAC for the objects. This means you go from thousands of queries to a single query to make these changes. The AdMod output looks like
~~~ADCSV~~~~~~ADCSV~~~~~~ADCSV~~~~~~ADCSV~~~~~~ADCSV~~~.~~~ADCSV~~~~~~ADCSV~~~
“dn”,”joeware-UAC”
“CN=$jricha34,CN=Users,OU=import,OU=MyTestOU”,”512″
“CN=postmaster,OU=MailUsers,OU=joeware2,OU=Exchange,OU=import,OU=MyTestOU”,”512″
“CN=Guest,CN=Users,OU=import,OU=MyTestOU”,”512″
“CN=administrator,CN=Users,OU=import,OU=MyTestOU”,”512″
“CN=krbtgt,CN=Users,OU=import,OU=MyTestOU”,”512″
AdMod then takes the joeware-UAC value for the given DN and then manipulates it based on the Op codes specified. This is done here
joeware-UAC::{{joeware-UAC:CLR:32}}
Normally if you would set a static value the command would look something like
joeware-UAC::512
However, as you know, that doesn’t take account to other flags that may be set and so is usually not something you want to do, especially with the userAccountControl attribute.
So here is the special formatting I set up. The first thing you will notice is the double braces around the value. This tells AdMod, hey, this isn’t normal. Don’t worry, if you want to set that as a static value, you can on individual or any non -ADCSV update. When AdMod notices that the info is coming in in -ADCSV format it enables an expansion switch that is normally not enabled. So… anything in {{ }} is handled through a special expansion routing. It has a basic format of
field[:modifiers]
The field can be the name of an attribute or honestly the name of a column in the CSV passed in or it can be one of the following “special” variable values
- *cnt* – enumerator
- *rnd* – random value
- *dn* – object DN
- *rdn* – object RDN
- *parent* – parent DN
- *domain* – domain DN
- *ndc* – DN without domain component
- *name* – object name
- *datetime* – date and time duh!
- *datetimeutc* – ditto UTC
A couple of those special values have their own modifiers, like the random function lets you specify min/max lengths and character sets for example. There are also uppercase and lowercase modifiers as well as logical modifiers for integers that you see in use above such as the SET, CLR (clear), as well as AND, OR, XOR, and NOT and some string modifiers of R and RALL which are Replace and Replace All to do a simple search/replace in the string.
You can combine multiple {{ }} entries per attribute as seen in a previous post
joe
So this new format should help with viewing these kind of posts…
I will try it a day or two…
In the http://blog.joeware.net/2006/06/29/431/ entry when Steve Kelly inquired about clearing that PASSWD_NOTREQD flag I thought I would basically dump a list of objects with the flag set using adfind. Then I would use something like a for command and enumerate each entry, substract 32 and set that new value. Still a little tricky.
This new admod will do just fine me thinks!
Personally, I’d like a shorter switch than joeware-UAC but I aint complaining.
Regards
M@
you need to reconsider the color scheme imho … looks like the UPS blog “what can brown do for you?”
Matheesha:
The joeware-UAC wasn’t a switch, that was an attribute I created in my ADAM instance to show how the new functionality works. 🙂 If you did that in AD you would replace joeware-UAC with userAccountControl. ADAM doesn’t have userAccountControl. Though I guess I could have created it as an attribute, I try to do good schema practices all of the time and when I create something for myself I use proper prefixing and legal OIDs.
Brian:
I completely concur, I have to figure out which CSS files I need to edit for that. It comes in 4 color schemes and this was the easiest on the eyes of the bunch. I will work on a blue or green format.
No wonder you knew [very quickly] what was going on with DSMOD when we were talking yesterday. You’d just finished comparing ADMOD against it and blogged about the improvements! 😀
Great stuff Joe. You know I’ll be using some of these features as soon as you upload the final version based on our recent conversation.
I do wonder though, as you’ve obviously been very busy with all this new stuff, have you remembered about being able to pipe attributes into values (we talked about this a while back and I think you said others had asked for it to), e.g. run adfind and pull a list of users with a certain profilePath attribute and set it with something like \\server\share\usersamaccountname…
Paul: Actually I had looked at dsmod traces previously because someone asked me how good it would be for modifying some 100,000 objects or so. I had a strong feeling it would do what I thought in terms of the extra queries because if there were an easier way (say like a bitwise update in LDAP) I would have implemented it already.
As for your second point, yes, this will allow you to specify attributes piped out of adfind and admod will be able to pick those up and run with them. To do what you asked it would look something like
adfind -base -f filter samaccountname -adcsv | admod profilepath::\\server\share\{{samaccountname}}