Archive for June 9, 2006

One Box

I completed my last day at University High School today. All the belongings I needed to take with me took up only one small moving box. Everything else of value was either owned by the school or virtual. The greatest tangible assets I have are the scripts I learned to develop while at UHS.

Next week, I will present at NECC on school web intranets, and then I will join the Catlin Gabel faculty in Portland, Oregon.

The Triumphant Return of DAF

I have succeeded in configuring DAF5 on our new IIS6 web server. DAF is the linchpin of our web intranet, as it permits our web site to authenticate parents without creating network accounts for them. It also provides a standard HTML login form instead of the default Windows popup dialog.

DAF permits a web site to authenticate users against two databases. We authenticate our network users against Active Directory and our parents and guest users against an Access database. DAF checks the Access database first and then forwards unknown users to IIS for Active Directory authentication. I don’t know of another product that does this function, so I was thrilled to be able to configure it correctly. Since DAF5 is in perpetual beta, documentation is scarce.

I found the correct configuration through educated trial-and-error. Here are the key steps.

IIS Manager –> [your web site] –> Properties –> Directory Security –> Authentication and Access Control –> Enable Anonymous Access

You must allow IIS to enable anonymous access in order for DAF to take over authentication for this web site.

Security Handler –> Always use a SSL connection

This is essential to prevent the plain text transmission of user passwords. Windows is no help in this regard, since Windows basic authentication is required in order to authenticate non-Internet Explorer users. Instead, I have purchased a SSL certificate for this web site, which in conjunction with DAF will make login encrypted for all users.

Security Handler –> Login Form Type –> HTML Login form

This points DAF to a HTML form instead of using a standard popup dialog. The form is located in /session in your web site. You can modify the HTML there, as long as you leave the form mechanics and includes intact. Check out our modified login form.

By default, login failure brings up a different web page. I pointed our failure page back to the same login form page, on which the error message appears. Later, it would be preferable to either make the error messages more verbose or to redirect to a different failure page with more information about what the user can do to correct the problem.

Security Handler –> User ID & Session –> HTML Login Form (using Cookies)

I used the defaults for HTML form.

Security Handler –> Advanced –> Default DAFAUTH.INI file

This step is critical to protect all of the directories in your web site at once. By default, a dafauth.ini file must be present in each directory in your web site. Since this is impractical, it is easier and more secure to choose an appropriate ini file here. Mine has the following simple settings:

[PreAuthentication]
Anonymous = disable
Authenticated = enable

Then I set NT folder security as appropriate for the access permissions I want.

Security Handler –> Count as ONE Registered Protected Site

If you don’t register with DAF, then only ten users can connect to your site.

Security Handler –> Logs

Enable Write to log file. DAF keeps different sets of error logs for different purposes. The most useful logs for debugging configuration are site-specific and found in /dafdata just outside the web site directory that you specified during installation. Note that /dafdata has the web site resource id appended to its directory name.

User DB –> Data Store –> Primary Data Store –> ODBC Data Source –> Settings

User your server’s Administrative Tools –> Data Sources (ODBC) to set up an ODBC link to your external database containing non-network user information. I wrote a separate PERL script to populate this database with registered parent login information.

Source & Connection tab: Select the ODBC source for your database and provide login information if necessary.

Table & Columns tab: Match the columns in your ODBC database to DAF standards.

Advanced tab: Use defaults

User DB –> Data Store –> Secondary Data Store –> NT User DB –> Settings

Default NT Domain: Select NT Domain User Database and specify the default NT domain. This step seemed helped in order to successfully authenticate network users without requiring them to specify their domain.

NT Account Mapping: Select Forward credentials to NT/IIS. This step permits IIS to authenticate network users, e.g., those who aren’t in the DAF database.

User DB –> Session

Enable session state. This is required for this approach, but I don’t recall why.

Other settings keep their defaults.

User DB –> NT Accounts

Default mapped NT account: This is an easy way to control privileges for the parent users on our network. As it happens, my parent registration script creates a static mapping in the DAF database, so I leave this setting empty.

Data source Login NT account: A server user that has privileges to read and write the DAF database. If this is improperly set, you will see corresponding error messages in the site error log.

User DB –> Encryption

I would like to use encryption, but it is easier to set this up for a clean install than to migrate existing, unencrypted passwords to this system. I will work on this soon.

User DB –> Logs

Write to log file

Web Script Migration Tips

Some years ago, a fellow tech director asked me why I would go to the trouble of writing custom scripts if they would all periodically have to be updated to keep up with changing technologies. At the time, I replied that the upgrade paths for commercial web programs were typically not painless, and that I thought that the upgrades would not take very long compared to the time invested the write the scripts in the first place. However, I have never had the chance to put this theory to the test until today. Fortunately, I have been proven right so far.

Last week, I installed the updated framework of IIS6, PHP5, mySQL5, and PERL 5.8.8. Today, it has taken only half a day to restore functionality to about three quarters of the insideUHS web scripts. I have learned a few lessons along the way.

IIS6 has added Web Service Extensions, which must be enabled for each script extension you want to be able to run (e.g., .cgi, .php). This seems obvious in hindsight, but I somehow managed to lose about half a day getting scripts to run on the new server. I was thrown off by the “file not found” error messages that IIS6 returns for the sake of security-by-obfuscation.

D’Arcy Norman provided a quick rundown on upgrading mySQL that I used to move from mySQL4 on the old server to mySQL5 on the new. My transition was a bit tougher than his. I learned that it is important to use the -Q option he specified, as some column names conflicted with mySQL reserved words. I learned to run the mysql_fix_privilege_tables script in order to upgrade the mysql user database to the new version. I somehow barely missed out on a slightly newer version of mySQL that has a mysql_upgrade script included in the distribution.

I was also hung up for a while on mySQL import errors while moving data from the old server to the new. Seems that some students had input dates of 2005-02-30 and 2006-06-31 into date fields, of which mySQL6 is less forgiving. I fixed all these, but then I ran into an “out of range” error that was harder to troubleshoot. Having a hard time fixing all the bad data in our rather large database, I searched the web for a workaround and found that I could temporarily disable strict mode in my.ini for the import. I then restored strict mode and everything worked fine. I suppose the bad data may produce an error again one day, but then it should be a lot easier to localize and fix within the context of a working web app. Lots of last year’s data won’t ever be viewed again. If the problem is a poorly-written open-source script, then a new version should do the trick.

I am still getting used to the new security feature of IIS6 which suppresses PERL compilation errors because they do not include a full content-type header. I still want to search ActiveState for a way to temporarily enable headers on error messages when debugging scripts. However, I have found a couple of other ways to debug these scripts. First off, you can see the compilation errors by running scripts from the command line, e.g. c:\> perl test.cgi. If you need to pass parameters to the script to produce the error, then the format is different from a URL query string, e.g. c:\ perl test.cgi action=submit. This is not going to scale up to a full form, but it resolves most script issues.

Most PERL script issues I have found are related to libraries I used on the old server that I must reinstall on the new server. The command-line error messages are very informative in this case. I love the ActiveState Perl Package Manager (PPM). Just run ‘ppm’ at the command line, search for the module you want, and then install it. For example,

c:\>ppm
ppm>search DBD
ppm>install DBD-mysql

It’s a good idea to search first before installing. I was expecting to use the colon format DBD::mysql but discovered that ppm uses dashes instead, e.g., DBD-mysql. It’s a really fast way to automatically find and install PERL modules into your Windows PERL distribution.

A few scripts have required some easy path edits, since I altered the web directory structure a little bit to better organize static and dynamic content. This was previously motivated by the need to store PHP scripts separately from HTML docs in order to keep database passwords out of directories to which users have read access. I have been good about naming paths to essential data files and templates at the top of each script, so it has been easy to fix those for each script.

This reminds me to mention that Windows has not satisfactorily addressed FTP security problems. Instead of permitting me to set FTP permissions by user account, I only have the option of making users be restricted to their home directories for FTP — and this is not trivial to do. That’s why I had to remove the PHP scripts from the web directories in the first place. Otherwise, users would be able to download PHP source code and look for juicy database passwords contained therein. FTP still relies solely on directory permissions, which are not helpful when you want to give users HTTP read access but no FTP access of any sort. Given the rise of web-based CMS systems, we may completely eliminate FTP this year. the number of FTP users has declined in recent years anyway as Moodle and blogs have taken off.

Onward with the web migration.

Botswana In Hi-Res

Google has dramatically improved its image resolution for Botswana. Here is Maru-a-Pula School in Gaborone (.kmz file).

What a Week!

Having had my head in the servers for the last few days, I only just now caught up on reading blogs from this past week. A lot has happened!

I also harvested some great tips for upcoming personal projects:

  • D’Arcy Norman explains how to migrate mySQL databases for an upgrade. I will be working on this in the upcoming week.

  • Moodlebug describes a new Elgg-Moodle integration module. I am thinking of rolling out such an environment at Catlin Gabel in the fall. (Bill, are they stealing your thunder?)
  • D’Arcy also tries out Adobe Lightroom. I need to create a better web photo gallery for an alum’s Kenya photos.
  • Numerous bloggers are ramping up for NECC. I need to write my presentation!

My last week at UHS is going to be a busy one.

We Have Made It

We got all our users up and running on the new, single-domain servers this morning. For a disaster recovery situation, 24 hours was not too bad. How many tries did this take to get right?

domains

Thank Goodness For Student Techs

While the servers burn, Guru and Eric have completely handled our off-site Summerbridge installation. Each summer, we invite one or two recently graduated seniors to work 100 hours for us, though every year our assistants generally work more than that. Without their assistance, it would be quite difficult to process all of the computers, printers, and network equipment that we turn over each summer. They have installed 15 laptops, six printers, and a Mac lab of 16 computers and a server in the past week. As Summerbridge begins its session tomorrow, they will likely provide a bunch of technical support as well.

Just When I Thought It Couldn’t Get Worse

Days after recovering from our failed network migration, we have had another server blowup. The air conditioning system in our server room failed this weekend, the room heated to 150 degrees F, and our Exchange server drives failed. We did get a good backup of the data store last night before the failure, but now we are left without both an Exchange server and the internal expertise to reinstall Exchange in a multi-domain environment.

At the same time, I have gathered a lot of feedback from other BAISNet tech directors and discovered that we are the only school among the respondents that is running multiple Active Directory domains. So, in this state of emergency, we have decided to immediately rebuild our new servers in a single domain environment, test it this afternoon, and migrate users to it tomorrow.

The simplified approach has reaped dividends within the first hour of adoption. Our systems administrator already worked up the primary domain controller the other day, so all he has to do now is to prep the domain for Exchange and install that. Without the multiple domain issues, we should be able to test the new server environment with user accounts by this afternoon. Our tech department users will spend the night logged into the new servers, and we will migrate others users if all is still well tomorrow morning. We may even recover all mail if we can mount the backed-up data store in an offline Exchange server and spin off the PSTs one final time.

Wish us good luck.

Server Learning Experiences

This feels familiar. We have twice this week unsuccessfully attempted to migrate to new servers. The problems all involve Exchange server communication between parent and child domains. I finally decided to pull in some external expertise and discovered that we are doing things the hard way at a couple of levels. First, our four-domain architecture runs counter to the conventional wisdom for organizations of our size and complexity. Microsoft and our consultant recommend a one domain architecture with organizational unit/group policy management of user privileges. Second, we manually complete a number of steps that the consultant has figured out ways to automate or shortcut. For example, we spend 20 minutes per user unjoining them from the old domain, joining them to the new domain, and then setting up their new profile. Apparently, there is a way to edit the user’s registry to move a user to a new domain without changing their profile. After the third attempt to reinstall and correctly configure our new servers, we rolled back to the old servers and returned to the drawing board.

On another note, I confirmed that my struggles obtaining PERL debugging information in the browser is a new IIS6 security feature. I found a description of the problem that indicates that there is not a good way around this feature. Too bad that I have not yet found error handling options in Activestate PERL similar to those found in PHP. While it was convenient to see error messages when PERL scripts did not compile correctly, this forces me to get a legitimate PERL development enrivonment that can provide debugging information live and write my scripts to capture errors on the fly. These are good things.

Putting WIMP Into Place

Today, I continued work on our new WIMP server configuration. As opposed to LAMP, or even WAMP, WIMP stands for:

Windows
IIS
MySQL
PHP/PERL

Our WIMPy setup is coming along just fine, aside from a few speedbumps. The first occurred when PHP repeatedly failed to load the php_mysql.dll library. It took me three hours to realize that PHP was pointing to \Windows instead of \php to find the php.ini configuration file. This despite the fact that php.ini was only located in \php, and I had added that to the PATH server environment variable! A test script with the phpinfo() command was essential to discover this fault.

I am still working on the second roadblock. PERL is not returning informative error messages. When a script does not compile properly, the browser only returns an “incomplete set of headers” error message. In our old IIS5 setup, this would usually be followed by “the headers it did return are …”, which would provide the substance of the error message. Not this time! I need to determine whether this is a normal consequence of an incomplete set of PERL modules, or whether there is a way to turn on more verbose error messaging. I suspect that my answer lies in some command-line testing.

In other news, Richard Bender has completed most of the new server setup and will begin the migration tomorrow. Ina upgraded Raiser’s Edge to version seven, and we are aiming to join the first admin users to the new domains on Monday.