Getting Started with AMGH

A guide to this new feature available in SRSS 3.1
Last updated Mar 9, 2007 by Bob Doolittle

I was the initial lead engineer [1] for what we wound up calling Automatic Multi-Group Hotdesking, also known as AMGH or Regional Hotdesking (and at one time called Global Session Mobility (GSM) - a terrible name since your session isn't mobile (you are), but this name continues to be used within Sun's internal 'netadmin' tool).  I'll use "AMGH" in this blog since it's easier to type :-)

We haven't yet done as good a job of documentation as we'd like (no slight intended for our excellent doc writer - we just haven't had time to work with him to the extent necessary), and as a result I don't think it's as easy to pick up and customize as it should be yet. In this document I'll describe what it is and how to customize it, as an initial way of getting some facts down that can later be turned into a more formal form of documentation we can distribute with our product. In the meantime hopefully you'll find these notes useful.


AMGH can be used for two purposes, either independently or in combination:
  1. Controlling what Sun Ray Server Groups Sun Rays connect to in very flexible ways.
    Most commonly this is used to extend the basic "Hotdesking" experience available within a single Sun Ray Server Group to encompass multiple Server Groups on your network
  2. Associating a user login name with a smartcard, Sun Ray, or network

Configuring AMGH

To configure AMGH, you must provide some code that implements your site policy for mapping the user environment to your desired behavior. This is not as difficult a task as it may sound to some, for a couple of reasons. The code can be either in the form of a small shell script or other executable, or it can be a dynamic shared library generated from, for example, a small amount of C code. We provide a fair amount of simple reference code (C and shell script) that can actually be used directly if desired (you should probably set the path to your mapping database file at least :-)).

In a nutshell, we've defined a simple API for your code to implement (sorry for the PDF chunk, the man pages of interest are ut_amgh_get_server_list and ut_amgh_script_interface).  For example, a simple script can process ASCII key=value lines on stdin and generate ASCII key=value lines on stdout to implement the API. You use the utamghadm program to specify the location and type (executable/script or library) of your site mapping code.

Why can't AMGH be configured through a GUI?  Why do you have to write code?

AMGH behaviors (Sun Ray "redirection", which causes it to connect to a different server, and the pre-loading of a username into the login dialog) have to be driven by data somewhere that says what to do in different circumstances.  For example, there might be data somewhere that lists smartcard identifiers and the usernames with which they should be associated.  Or there might be data that lists usernames and the servers the Sun Ray should be redirected to for those users, so that they can find their sessions or create new ones if none exist.  This data may already exist for many customers (most commonly the smartcard-to-username data), and might be in a flat file, or in a Directory Service, or in a NIS map.  Where that data resides, and how to use it, will vary from customer to customer.  As a consequence, there's no way to create a GUI to configure these policies because there are no constraints on location, format, or logic defining how to use the data - you can do anything you like with it.

An example - Sun's internal use of AMGH

Let's consider how Sun uses AMGH internally.  Sun's IT department has created a "model" which associates smartcards, users, the buildings users work in, and Sun Ray Server Groups.  All of the data related to their model resides in an Enterprise Directory Service (based on LDAP) which is available throughout Sun's global Wide Area Network (SWAN).  The data is used by a wide variety of internal tools.  The Sun IT AMGH model relies on the following objects and attributes associated with objects:

Objects Person Building Sun Ray Server Group
Attributes username Sun Ray Server Group servers (list)
smartcard CUID
"Preferred" Sun Ray Server Group

The idea is that every employee, upon inserting their smartcard, should have their Sun Ray directed to the Server Group associated with the building they normally work in.  They can override this placement if they like by administering their "Preferred Server Group" and setting it to someplace specific (normally it is not set).

When an employee inserts their smartcard, Sun's AMGH policy module looks up the Person object associated with the smartcard CUID.  If they have a "Preferred" Server Group, its Sun Ray Server Group object is referenced and the list of servers for that object is returned.  Otherwise their Building Object is referenced to determine its Server Group, and then its Sun Ray Server Group object is referenced and the list of servers for that object is returned.  The username for the Person object is also returned, so the employee immediately sees a welcome screen to authenticate themselves.

All of the above lookups and references are made by the means of an ldapsearch command.  Since there are no standard Schemas for most of these objects and attributes, Sun uses a custom Schema for this purpose.

As you can see from this example, AMGH mapping policy logic has no constraints, and so does not lend itself to specification by a fixed administrative GUI.  Another site might like to direct Sun Rays on a specific subnet to do something different from the rest, or a specific Sun Ray to have a unique behavior.  Some sites might like all Sun Rays to reconnect to the original server they connected to after bootup when a smartcard is removed (this can be accomplished through another API return parameter: use_firstserver).  All of these policies can be specified and implemented using the AMGH API.

We'll continue to think about ways to make a simple policy-builder GUI that some customers can use but for now releasing the API gives complete power to customers to control their environment as they see fit.

I've gotten permission from our (very supportive) VP Bill Vass to post the source to the AMGH script used by  Sun IT internally.  I've posted that script to my blog.  Hopefully with the above model/object description it should be comprehensible.  Thanks, Bill!

Details of the API - how does it work?

As input we provide a token (which could be a smartcard unique identifier), a terminal ID (based on the SUN Ray MAC address), the Sun Ray IP address, and possibly the username (if the username couldn't be established by AMGH itself, the user is prompted for their username and AMGH is called again with the username).  The API normally returns one or two pieces of information: a list of host and a username.  The Sun Ray will be directed to the first host providing Sun Ray service and preload the username into the login dialog (so the user will not be prompted to enter it).

Tips and tricks

CAM/Kiosk  mode

SRSS supports a mode of use called "CAM" (Controlled Access Mode) or "Kiosk", which can be controlled by setting the Sun Ray policy.  At this time, the product does not support the use of AMGH with Kiosk mode.  We'll try to add that in a future release or possibly a patch.

In the meantime, I've written a simple PAM client that can be used within CAM mode to invoke AMGH.  Binaries are available in my blog, as well as instructions on installing and customizing them.  Use of these binaries is unsupported at this time, but we hope to incorporate them or something like them into our product in a fully supported manner.

API tips

In the API, you generally will find insert_token more useful than token, since the former represents the actual smartcard CUID whereas the latter is a form translated by Sun Ray software in ways that may be hard to predict.  If you run "echo $SUN_SUNRAY_TOKEN" in a Sun Ray session, you will see the value of token.  If you run "utuser -lc" you will see the value of insert_token. Depending on your Sun Ray policy specified by utpolicy or through the administration browser interface these may be the same or different.  You should always use insert_token if you have configured a registered card policy,
because with this policy token is not consistent across different Sun Ray Server Groups, so cannot be used consistently for AMGH redirection.

There's probably not a use for display, since that value is randomly assigned when a session is created.

If you use the 'executable' API, you can use a shell script as we do in all the reference code, but you can also use something like perl or an executable produced from C code.  We used Bourne Shell code in our examples simply because it is widely understood.

Less commonly used features of the AMGH API

There are two other pieces of information that can be returned, which are not as commonly used: use_firstserver and chain_amgh.  Both have boolean values of true or false.

If use_firstserver=true is returned, any host values are ignored, and the Sun Ray will be directed to the first Sun Ray server it contacted after last boot (note this has an Availability issue - if that server is now unavailable, the Sun Ray cannot be directed to other members of its FOG and instead the Sun Ray will remain connected to the current server).  This can be used for example to create a "return to home on smartcard removal" model by matching all "pseudo.*" insert_tokens and returning use_firstserver=true.

chain_amgh is really for expert-use only.  It can be used in situations where there are groups of servers with "partial knowledge" of the policy for AMGH.  If chain_amgh=true is returned, AMGH will perform in the standard way, but after redirecting the Sun Ray the remote server it connects to will apply AMGH policy again, based on its AMGH configuration.  In this way a Sun Ray can be directed to another group of servers with AMGH knowledge which might cause further AMGH redirections to the final desired destination.  Obviously this can result in loops if improperly configured.

Token forms

A Sun Ray with no card inserted will have an insert_token of the form "pseudo.080020010203" where the part after the '.' is the MAC address of the Sun Ray.

Smartcards will have an insert_token of the form "MicroPayflex.5001436200130100", where the part before the '.' is the type of smartcard and the part after it is the unique badge CUID.

utdesktop -l and utuser -l report tokens in insert_token form, which is the same as token form if the tokens are not "registered" (see utuser man page). utwho reports tokens in token form.


For security purposes, you need to lock down permissions on AMGH mapping executables or libraries.  Neither the executables, libraries, nor the directories they reside in should be writable by anybody other than root.  In other words, they should all be owned by root, and writable only by owner.  libraries and executables must be readable by owner (root), and executables must be executable by owner.

Why not write an AMGH script utilizing information in the SRDS token registration database?

Initially this may seem attractive but keep in mind that AMGH is intended to work across FOGs, so you really ought to use a single, consistent database which can be shared across FOGs and is not subject to FOG-local typos or errors.  Such errors can create inconsistent and hard to diagnose behavior.

If you do go this route, do not be tempted to use the "-c" option to utuser.  Although it will restrict the output only to relevant tokens it will have an undesirable performance impact since it involves the Authentication Manager (utauthd) at what can be a critical time (e.g. as a server is first coming up many Sun Rays may be connecting to utauthd simultaneously and creating sessions, all going into the greeter at once so invoking AMGH).  "utuser -l" generates more output but does not involve utauthd so will actually scale better in such scenarios.

A tour of the Reference Source

Upon installing Sun Ray Server Software 3.1, a collection of reference C code and shell scripts will be installed in /opt/SUNWutref/amgh/.  The operative word here is reference.  This code is not secure or robust - that's not its purpose.  It's goal is to give a clear example of how to use the API, so the code is written to be as simple as possible to make it easy to understand and write your own code.  Making the code more "production-ready" would have complicated the code and made the utilization of the actual AMGH API less clear as a result.  I've already explained why we can't write "one size fits all" code that you can just pick up and use.  It's not nearly as flexible as it could be.  For instance it doesn't do any wildcard matching or the like.

A C header file defining the API is installed called /opt/SUNWut/include/utamgh.h.  This can help in understanding the C code, and should be used by any C code you write yourself.  I've mentioned the man pages for the C and executable (e.g. shell script) APIs previously.  Here is a brief description of each of the reference sources currently delivered with the product:

utamghref_token.c Simple C module to map a token to a username and/or hosts Relocatable C library built from utamghref_token.c
utamghref_username.c Simple C module to map a username to hosts    
Relocatable C library built from utamghref_username.c
utamghref_script Simple sh script illustrating how to map a token to a username/hosts, or if no mapping is available (in which case AMGH will prompt the user for their username) map a username to hosts
Flexible sh script which will map any of the AMGH inputs to any of the available AMGH return values

All of the above code uses a flat ASCII file in key=value format, with a single line for every potential mapping.  If a site chooses to use this code they may wish to replicate the file either through an NFS share or a mechanism like 'rdist'.
A reference Makefile is included to illustrate how to build a shared library from this C source.

In future, we may include an example utilizing LDAP, since that is a common customer requirement.  However, the issue here is that, since there are no standard schemas, it is not really possible to write example code that people can understand, without understanding a proprietary schema.  This makes it hard to write clear examples which utilize LDAP.  However, once you understand the API and how you could implement it using a flat file for your data source, changing to using LDAP should be simple, and any complexity there is related to how you store and represent the data that you wish to utilize.  You can just use the 'ldapsearch' command in a shell script, for instance.

Technical details for the interminably curious

Some people have been curious as to where/how AMGH is being activated.  AMGH is invoked from the PAM stack of the Display Manager (either dtlogin or gdm for Linux users).  You'll need to at least read the man page for "pam.conf" to understand the rest of the workings.
If any hosts are returned during either call to your script, pam_sunray_amgh will request the Authentication Manager to redirect the Sun Ray to the first responsive host that you return, and then it will request the DM to tear down the session which was used to invoke AMGH.

An unsupported way to make the "username" non-overridable

Today, the username returned by the API can be overridden by the Display Manager (e.g. dtlogin's "Start Over" button).  Some customers would like this setting to be a sort of "security" feature that cannot be overridden by the user, rather than a "convenience" feature as it exists today.  In future, we may add such a feature to the product.  There is an unsupported way to deal with this today, however, for non-NSCM logins.  You can edit /etc/pam.conf and remove the clearuser option from the module. This is not officially supported because it has not been tested by our Quality Assurance team but it has been known to work for some customers.  There is no similar recourse for NSCM logins today - the "Start Over" button will clear the preset login name returned by AMGH.


This should be enough information for you to get started using AMGH.  If you give me useful feedback I'll roll it into this document.  Eventually I want to see this information distributed officially as part of the Sun Ray product but this document serves as a way to get the information out to users quickly and to start to form what will become the product document.

[1] AMGH was finally led to product by Sangeeta Varma, with the invaluable assistance of Vijay Rajkrishnan who was graciously loaned to our team by Sun IT (an org which has been enormously supportive of Sun Ray from the very beginning).  What a great team - thanks, guys, it was a pleasure!  Also proof that people can collaborate effectively over large distances (CA, TX, and FL).