Wednesday, April 29, 2015

Active Directory password changes in Java

I'd been tasked with some changes to support another project.  The changes include making self-service and administrative password changes against MS Active Directory.  I also needed to cause users to change their passwords on next login.

Here are a few comments/notes from the experience.
  • I'm using Java for this
  • I'm currently using Spring-ldap (1.3.x); works "ok sort of".  I'm probably going to have to rip it out and do this manually though.  See note after this list for info on the problem.
  • When using a service account to make administrative password changes; make sure the service account has the correct rights for setting passwords.  The example here is using a service account to make the changes.
  • You can set pwdLastSet to "0" to force a user to set their password on next login.  This requires its own rights in MS AD.
  • You MUST use LDAPS connections to change the password; it will not work otherwise. 
Ok, so I can execute the code below and it works - most of the time.  I keep running into an occasional error on setting pwdLastSet though.  It isn't consistently repeatable though.  I have a thought that it is related to Spring LDAP closing/opening connections per operation and maybe something with AD replication since we have a number of AD servers which replicate - basically a timing/race condition is my thought.  After some research, it looks like a few people have experienced something similar.  Others indicated that using the built-in pooling worked but their use case allowed plain LDAP (not LDAPS).  The built-in pooling per documentation indicates that it won't work for LDAPS.  The idea behind their use of the pooling appeared to be the continued use of a single persistent connection.  I reviewed some options using Spring LDAP but have not found a useful method of making it work reliably in some initial attempts.  I found some recommendation to use the Spring SingleContextSource in place of the LdapContextSource class but lack of a useful constructor pretty much destroyed that idea.  It just seems like the class was poorly designed.  I considered just reimplementing something from the Spring code but that just seems more convoluted.  So doing it manually is likely in my future.  Not a huge problem.

The following is how it is setup right now though - using Spring LdAP..  There are a number of examples like this floating around the internet.

Once you have a Spring LdapTemplate instance, the code for a password change is like this;

final ModificationItem [] mods = new ModificationItem[]
                {
                    new ModificationItem(DirContext.REPLACE_ATTRIBUTE, 

                        new BasicAttribute("unicodePwd", ("\"" + password + "\"").getBytes("UTF-16LE")))
                };
ldapTemplate.modifyAttributes(userDN, mods);


The code to cause a user to require changing their password on next login is;

final ModificationItem[] mods = new ModificationItem[]
                {
                    new ModificationItem(DirContext.REPLACE_ATTRIBUTE, 

                          new BasicAttribute("pwdLastSet", "0"))
                };

ldapTemplate.modifyAttributes(userDN, mods);

There are only 2 values you can set for pwdLastset; 0 and -1.  Using 0 basically forces a user to change their password and a -1 seems to make it seem like it was just set.

Nothing real exciting with this but it does help us move into best practices.


Wednesday, April 22, 2015

Vinyl flooring - the bathroom with all the related stuff

Ok, finally got to the bathroom floors.

A main few details summarized:
  1. vinyl flooring; no seams
  2. underlayment (~ 1/4")
  3. screw down underlayment
  4. #6 & #8 zinc coated screws - 3/4-1" 
  5.  Roll on adhesive at the recommendation of the flooring store (Flex-Tech); 1 quart just covered both bathrooms
  6. 3/8" nap roller
Then the miscellaneous things - expected and unexpected:
  1. waxless toilet seals; needed to use 2 stacked in master bathroom and one high in spare bathroom.  I saw these in Lowes and decided to give them a try.  I like them but I do have a little concern that if a hard plunge is ever needed they might blow out - wax could as well I suppose.  Time will tell.
  2. New compression style toilet supply valves.  I went for the 1/4" ball valves instead of the multi-turn gate(?) valve that was there.
  3. New supply valve cover/flanges
  4. 4-in-1 plumbers tool; worked nicer than the random piece of sandpaper I would have used.
  5. Some decent type of solid straight edge.  I had a 4' x 3"x 1/4" aluminum bar which helped me at times.
  6. A decent number of clamps in a few styles (C, F style mainly) and sizes.
  7. hammer / punch to remove door pins
  8. Oscillatting tool (saw) to undercut the door jamb
  9. pry bars to remove base molding and/or shoe molding
  10. screw drivers to remove things like tower bars / toilet paper holders to get them out of the way
  11. caulk and caulk gun
  12. paper towels (used quite a few cleaning up caulk as I went along)
  13. shoe/base molding; multiple stains (having to mix different ones to match the existing molding around the doors).
 I decided on vinyl flooring because the kids tend to track water like crazy and I was able to do it without seams.  I did both bathrooms in the same vinyl mainly because it was more cost effective since the material came in a 12 foot wide sheet which reduced my waste a bit because of the dimensions I needed.

I had decided to use underlayment because I didn't feel the existing surface was smooth enough; and there are many nails that refuse to sink further even with a punch and large hammer.  I screwed it down to prevent heads from raising.  This took more than I expected - I ended up using over a box of 100 in each bathroom.  The master bath was worse since I was covering up new and old plywood where subfloor had been replaced due to a water leak. 

The process I used for this project was to create a paper template of the floor with all obstacles removed.  I used a roll of brown garden paper (same stuff is probably available at paint stores or construction supply places) - around 30" wide in a 300 foot plus roll.  I made cutouts for the toilet and vent.  I taped multiple runs of it together to produce the entire floor plan.  I then taped the template to sheets of underlayment and marked/cutout the matching shape.  I used a jigsaw which worked fine - relatively fast and low physical effort but I probably would have been more accurate doing repeated deep scribes with a utility knife but it would have been a lot slower.  The took one and a partial sheet of underlayment per bathroom.  I tried to keep the new seams from laying on the old seams.  I ended up taking a coarse rasp I got from my dad to remove many of the splinters from the jigsaw cuts - the cuts were pretty rough looking.

Once I had the underlayment cut to match; I tested the layout to verify I got it right and tweaked it as needed.  I then laid the vinyl in the driveway (carefully) and put the underlayment over it.  I was then able to cut the vinyl to the desired size/shape.  I had made a few notes on the plywood to follow as well; like leaving a little extra length for the door jambs where I undercut the jamb so extra vinyl would go under it for a proper clean/finished look.

The roll-on adhesive was totally new to me.  We did the master bath first and it was interesting. You have to let the adhesive dry to the point of just being tacky before laying the vinyl.  It stays tacky for 24 hours or so though.  I made the choice (mistake?) to do the master bath in one go - went in rolled the glue, waited for 60-90 minutes and then awkwardly laid the vinyl in with the wife's help.  My son wandered in as she was trying to go from a step stool in the doorway to the window sill to standing/sitting on the sink where she could hold the far end of the vinyl for me.  He shook his head and wandered back out - apparently we were site that was too scary to watch.  When we did the spare bathroom, I did it in 3 separate stages starting from the far end (thanks to the prompt by my sweetie pie wife :)  ).  This was much easier.

Below is a pic of the spare bathroom in progress.  The first 2 sections had been laid; here I think the the adhesive was at the tacky point and ready for the vinyl.  I did have to get from the doorway to the bathtub to do this section but it wasn't too bad. 


Below is the fully laid vinyl with the toilet in place.  I still have to stain/cut some new base/shoe molding the bathrooms.  I only salvaged the base molding in the spare bath - left it in place.  In the master I remove base/shoe before doing any work.
  

Overall, this wasn't too hard and turned out pretty well so far.  I am still reserving judgement on the adhesive.  It was really nice that I was able to lift and move the vinyl a bit to adjust it as I worked but I am not sure how it will hold over time.  The glue indicated that no large roller should be used (like 75 lbs+) which I was a little surprised by.  We mainly worked out little bubbles by hand and foot. Hopefully I wont end up dragging out the molding work.

[Update 2015/04/22] Sigh, just got around to caulking the spare bathroom.  Realize I didn't trim along the bathtub very well - ended up with a pretty large caulk bead to take care of it.  Take lots of care on that and don't hurry if you try it.  I have some spare vinyl - I may ponder slicing in a bit someday to allow me to shrink the caulk bead.  It isn't terrible but I am somewhat overly perfectionistic at times.  Did I mention that I wish someone would write a book - "Caulking for dummies".


Friday, April 17, 2015

ServiceMix - first prod integration deployed

I have been pushing to replace WebMethods within our organization for a few years now and this is finally the first step - getting ServiceMix into production.  Unfortunately, this initial integration isn't  replacing any WebMethods integration but it got ServiceMix into production though.

Some minor details on the integration.

Tech used:
  • Linux
  • Java 8 
  • ServiceMix 5.4.x
  • Camel
    • SQL Component
  • PeopleSoft psjoa.jar and the associated jar of generated component interface definitions
The biggest challenge was getting the PeopleSoft aspects usable in a real OSGI context.  It isn't perfect but it is functional. 


Here is a simple diagram of the OSGI related dependencies.
Since PeopleSoft integrations using psjoa.jar require using the jar that exactly matches the version of PeopleTools in use; I used the PeopleTools version for the OSGI version of the exported packages.  I used the maven bndtools plugin to convert the jar into an OSGI bundle.  The only painful part of this is that I ran into a need to utilized the dynamic-import to pick of some internal references which were causing problems otherwise.  The interesting aspect is that what was picked up appears to be things like JMS items and similar things.  I am guessing that psjoa.jar does some stuff with Class.forName() with regard to some optional functionality it provides and it still causes OSGI issues for some unknown reason.
 
 The PeopleSoft component interface definitions were a much larger headache.  The code is generated and you have no control of the code/package naming - all CI files are produced into the package: PeopleSoft\Generated\CompIntfc. 

 The CI files are not necessarily tied to a particular PeopleTools version - the file can be used for later PeopleTools versions as long as nothing is structurally different between CIs defs and the PeopleSoft server side definition that you use.  The main issue here is that if you have multiple PeopleSoft ERP systems (i.e. HR, Financials, etc) then the set of  CI definitions is different but the Java side package must be the same.  This made it harder to support multiple PeopleSoft systems (with different PeopleTools versions) concurrently in one ServiceMix instance.  I am not  trying to run multiple integrations like this at the moment but I need to.  I think I worked about the problem but it required the use of "required-bundle" - so Finance CI definitions go into a jar like finance-ci-<version>.jar and HR definitions go into a jar like hr-ci-<version>.jar.  They both contain the same java packages so in dependent integrations I import the package and I must also be sure to do a require-bundle on the jar for the system I am interested in.  I think I have it working but need to do some further validation.  Without doing this, I would likely have to do some sort of version scheme which distinguishes the various ERP systems of interest - that seemed awkward as well so for now I am doing it this way.

Back to the overall integration.  Nothing fancy, some database triggers generate records into a table which acts as input to the ServiceMix integration.  ServiceMix (Camel SQL) has a route which runs a regular SQL against the table and selects the data into the route.  The route takes the data and does some work with the PeopleSoft instance and if no error/exception resulted then the route marks the originating data as processed.  If something goes wrong, the route marks the failed row as failed processing. 

One thing that isn't working for  me right now is that I intended to have the route delete the source rows on success but that is not working at the moment - not sure why.  I am wondering if it is a bug in Camel.  I did check the Camel unit tests and there is a test matching basically what I am doing but the test is done via Java code versus using Blueprint - it seems like it shouldn't matter but for lack of a better answer.  Or it could be differences in database/drivers (maybe far fetched - not doing anything wild here).  I did note in documentation that it looks like there are so limitations on the number of parms to the queries specified to the SQL/DML.  I just don't have time to debug it for now.  I will probably write a quick batch job to run every so often and cleanup the completed data and  generate a report on failures, counts, timings, etc.

 There are still a number of setup changes which will likely occur to the environment as we implement more complex integrations but at least we started the process - I am very thankful for that.

Thanks for checking this out; hope it was interesting and maybe even helpful in some way.

God bless!

Scott