In Python, there is a built-in string method, “startswith,” that lets you determine whether a line starts with a character. I’ve used it before because I tend to want to use the features of the standard library, despite having awesome features like slicing at my disposal. What I didn’t realize immediately, though, was how to compare the string against two or more sets of characters. All I knew is that entering a list as the prefix — instead of the more common single string — didn’t work.

Luckily, my question was answered right away in the [Bad link]. I found that to perform these comparisons together, you must supply the “startswith” string method with a tuple. It works the same for the “endswith” method. However, this does require Python 2.5.

There are occasionally times in system administration where I feel as if I’m on the bleeding edge. They are not frequent … which probably puts me somewhere much closer to the lunatic fringe. These are also the times when no one else probably cares about the same things — but no matter, I generally have my own pragmatic reasons for them. This is one of those times, and I have waited for this particular feature for a while. I'm happy to have discovered it.

Let’s set up a scenario: you have a Mac OS X Tiger system bound to an Active Directory. All of the thousands of Active Directory users are available on that Tiger system; any one of them could log in to that computer. This isn’t bad if you only allow logins at the login window. However, if you enable any sharing services, the game changes and your exposure widens.

What if you don’t want everyone in your enterprise directory to log in? This gets a little scary to think about. What if you want to limit those who can log in, particularly for services like SSH? How do you let some users in but keep others out — even going to the point of denying access to whole classes of users?

There are a number of things you can do, some at the client and some in the directory. Unfortunately, some kinds of configuration must be done at the client. There isn’t a great way I’m aware of to distinguish between local and network accounts, complicates the situation for the administrator. With Open Directory in Tiger, any user from any directory service was as valid as any other. There will probably be some manual effort — ongoing effort at that — required to restrict access.

Enter Mac OS X Leopard. It now has “computational groups” in its Open Directory client. They are like smart groups in your local node. The memberships of these groups are calculated, rather than static. They are more like query-based groups.

For the scenario above, the two computational groups that provide the most utility are probably “localaccounts” and “netaccounts.” They allow you to distinguish users who are in the DSLocal database from those in Active Directory. This magic gives the glue we need to maintain finer-grained access controls automatically over time; you could use these groups for the sshd server configuration or in the authorization database at /private/etc/authorization, as examples.

Let’s try the groups out with dsmemberutil, with which we can determine whether or not a user is a member of a specific group. What about the first local user, typically created by the Mac OS X Setup Assistant?

$ dsmemberutil checkmembership -u 501 -G localaccounts
user is a member of the group
$ dsmemberutil checkmembership -u 501 -G netaccounts
user is not a member of the group

Digging further, all of the computational groups I’ve found had the same comment. We can search for that to find the rest, to find all of the computational groups that ship with a Leopard client.

Never let it be said that Apple’s Open Directory command lines tools make complete sense. After all, why would you think to use the new dsmemberutil tool in Leopard to find the Universally Unique Identifier (UUID) for a user account?

You would have if you had read the first line of its man page, maybe, where it outlines exactly how miscellaneous — and I say that in the kindest possible way — the command is: “dsmemberutil -- various operations for the membership APIs.”

Enough lead in; the UUID for a user (as well as a group) can be found with this tool:

$ dsmemberutil getuuid -u 501
E4BDC9C9-AD89-4CD6-BE25-16B197669B47

Choose a user with either -u with the userid, or -U with the short username.

One way this can be exceedingly useful is if you want to track down the shadow password file corresponding to a specific user account:

There are times when you need to determine whether a user is a member of a group or not. Knowing the membership of a group can have an impacts on security or operation of system administration scripts. The dsmemberutil tool in Mac OS X Leopard lets you perform checks like this on the command line or in scripts.

You feed it a group and a user, and the tool tells you whether or not the user is a member of the group. This works with group nesting, thanks to the wonder of the memberd functionality first available in Mac OS X Tiger.

$ dsmemberutil checkmembership -u 501 -G admin
user is a member of the group
$ dsmemberutil checkmembership -u 502 -G admin
user is not a member of the group

Unfortunately, you must parse the output, which hinges on whether “not” appears in the text. The exit code for both commands above is “0,” for success.

When I come across software I might need to add into Mac OS X that requires compilation, I typically want to produce one Universal Binary. Make it a four-way UB and you get both 32- and 64-bit support.

A single binary is ideal for a Radmind transcript (or other package, if you wanted to bundle it into an installer) that can be deployed on both PowerPC and Intel Macs on Leopard.

Since [Bad link] 3.0.2 with some patches is apparently working [Bad link] — passing the [Bad link] tests — I thought I'd try my hand at a four-way Universal Binary.

What worked for me, using a Mac Pro 4x2.8 GHz with Mac OS X 10.5.2 and Xcode 3.0, was to start with [Bad link] and modify them with some [Bad link]. The configure and compile were both less than a minute on this system.

I have seen the use of "-Wl,-syslibroot,/Developer/SDKs/MacOSX10.5.sdk," in the LDFLAGS environment variable when compiling some applications but this did not work for me with rsync; when I removed it, rsync 3.0.2 configured successfully for me.

The result of the above build process appears to be a full four-way UB:

A local transfer on the build system appears to have worked correctly. I did not test with Backup Bouncer, sync with a non-Mac system, or when shuttling data between architectures. So, accept these results with a grain of salt; I’m just happy I got rsync to compile for now.

Microsoft released Service Pack 1 to update Office 2008 for Macintosh on Tuesday, May 13. The update makes a significant number of changes — spread across Entourage, Word, Excel, and PowerPoint — so if you are a system administrator, I would recommend examining the [Bad link] in its release notes.

The update is downloadable via Microsoft AutoUpdate (invoke that helper program with Help > Check for Updates in any of the Office applications, or look inside /Library/Application Support/Microsoft in the file system) as well as the [Bad link] Web site.

It took me a little while to figure out how I could tell what DirectoryService directory nodes are available to a Mac OS X system. I could perform the task interactively, just issuing an “ls” command at the dscl “>” prompt. But for a non-interactive one-liner, I was bedeviled by what I thought was a pretty basic function for the dscl tool.

I wanted to find all of the top-level nodes — because, for example, that could [Bad link].

It turns out that I was missing the use of “localhost” as the datastore parameter, which reliably returns the information I wanted in a parsable form. Rather than “/” (simply doesn’t work) or just a period (only uses the local directory) — or even listing "/Active\ Directory" explicitly — “localhost” specifies all of the directories available to the local host. I was incorrectly assuming “localhost” would tie me to the local directory, as with “localonly,” and I thus avoided trying it until I felt like an utter failure.

$ dscl localhost -list .

This produces the following output on a Leopard-based system which only has local accounts in DSLocal:

$ dscl localhost -list .
BSD
Local
Search
Contact

If your system happens to be bound to a Microsoft Active Directory, you’ll instead see it prepended:

$ dscl localhost -list .
Active Directory
BSD
Local
Search
Contact

Or if you’re on Tiger — again bound to Active Directory — you’ll still see “Bonjour,” “NetInfo,” and “SLP” in the mix:

I used the same drag-and-drop-to-export methodology as in my previous article. The iCalendar .ics file for the existing event that I dropped out of my Entourage calendar contained these unique identifiers:

Both I and the meeting organizer are Entourage users in this case. That may be why both the event and the cancellation had X-ENTOURAGE_UUID properties at all. The UID property has appeared consistently for me in both events and their updates, no matter what their source.

Because of the discrepancy between unique identifiers, Entourage apparently couldn’t determine whether the cancellation was for the event that existed in my calendar. When Entourage “processed” the cancellation, it removed nothing from my calendar.

This seems entirely reasonable, although I would personally like Entourage to do deeper matching if it could: how about “is there an existing event by the same organizer and/or with the same name at the time of the update or cancellation?” Matching UIDs has got to be simpler.

How does this happen? Well, for me, it could have happened any number of ways: There could have been a past error when:

Entourage was trying to synchronize to my Exchange account

my Entourage calendar was synchronizing with Sync Services on Tiger or Leopard

Missing Sync for Palm OS, which I use with my Palm Treo 650, was performing its synchronization with Sync Services on Tiger or Leopard

I was using Microsoft Outlook in cached mode with my Exchange account

I used [Bad link] to remove massive numbers of duplicate calendar entries from my Outlook/Exchange calendar (which could have resulted in the loss of events with their original UIDs).

As far as I can determine, when you have data synchronization problems, you’re going to have one of the following outcomes:

data is added

data is deleted

data is modified

nothing happens.

Not all of these are pleasant, mind you — and that can depend on the circumstances involved. Deleting data is perfectly acceptable in some scenarios where it needed to be removed, but not others where it means it has just been lost. Adding data is great, unless it results in unwanted duplicates.

Anyway, I hope this helps you understand how Microsoft Entourage works a bit better.

Now that I have my dual-monitor Gateway FPD2485W setup, I’ve got a few complaints. Of course!

The two monitors take an awfully long time to wake up from their power-saving mode. Then, when they finally wake up — invariably at different times, the newer one first — I get the on-screen display (OSD) overlay telling me that they’ve chosen to accept the DVI input.

Well, duh, that’s the only video source hooked up to them, so it’s not helpful. This wouldn’t be so bad, but the OSD overlay stays on the screen for what seems like eons. Since the overlays are smack dab in the middle of the screen and are opaque, they block important visual elements like Mac OS X’s login window.

So far, I haven’t been able to find out how to get rid of the OSD overlay. If I could do that, I think I’d tolerate the wake up delay more readily.

Certainly, some of this is Gateway’s fault. I guess I can’t blame them much since they specifically don’t support Macs and that’s what I’ve hooked the flat panels up to. I could have gone with some brand that did advertise Mac support, but I didn’t. This must be my payback. Grin.