HAAGE&PARTNER Computer GmbH  HAAGE&PARTNER

Sawmill Analytics

Analyse und Reporting
für Web | Netzwerk | Sicherheit

Zugriffs- und Datenanalyse von Server-Logs (Proxy, Mailserver, Firewall, Webserver) und Überwachung der Sicherheit & Performance, Schwachstellenanalyse.

Sawmill Analytics 8 | Loganalyse

Sawmill-Tutorial

Adding Users Automatically With Salang Scripting


Sawmill's "Create Many Profiles" feature makes it easy to add new profiles automatically, by embedding Sawmill in a larger environment, and calling the "create many profiles" Salang script to generate or regenerate many similar profiles from a single template. See the November 15, 2007 Sawmill Newsletter for a discussion of Create Many Profiles.

But what if you want to have a separate user for each profile, and want that to be created automatically too? This might be useful in a web hosting environment, where you want each user to be able to log into Sawmill to see only the reports for their own domains; so for each customer, you would create a Sawmill user, and then give it permission to access its own domains (profiles), and finally give the customer a direct link to the Sawmill web interface (or, including Sawmill as a "tab" in a larger interface).

This can be done using Salang scripting. This newsletter includes an example script, and how to use it.

The Add User Script

Here is a script which adds a user (or modifies an existing user):


  # This script adds a non-administrative user with access to one profile.
  #
  # Usage: sawmill -dp miscellaneous.add_user v.username <username> v.password <password> v.profile <profile>

  {=
 
  # Create the user node for v.username (in the "users" node, i.e., the users.cfg file in LogAnalysisInfo),
  # if it doesn't already exist
  set_subnode_value('users', v.username, '');

  # Set the username to v.username
  set_subnode_value('users.' . v.username, 'username', v.username);

  # Set the password.  This computes the MD5 checksum of v.password, and puts it in the password_checksum of the user node
  set_subnode_value('users.' . v.username, 'password_checksum', md5_digest(v.password) );

  # Make this a non-administrative user
  set_subnode_value('users.' . v.username, 'administrator', false);

  # Add a "profiles" subnode in the user record, where we can list the profile accessible to this user.
  set_subnode_value('users.' . v.username, 'profiles', '');

  # Give the user access to one profile: the one specified by v.profile
  set_subnode_value('users.' . v.username . '.profiles', v.profile, true);

  # Save the users node (users.cfg)
  save_node('users');

  # Display the new (or modified) users node
  echo(node_as_string('users.' . v.username));
 
  =}



LogAnalysisInfo/miscellaneous/add_user.cfv

To use this script, put it in the miscellaneous folder, which is in the LogAnalysisInfo folder of your Sawmill installation. Then, from the command line, run this on Windows (assuming Sawmill is installed at C:\Program Files\Sawmill 7):

  C:
  cd Program Files\Sawmill 7
  SawmillCL -dp miscellaneous.add_user v.username username v.password password v.profile profile

Or on other operating systems, run this command line:

  cd sawmill-install-dir
  ./sawmill -dp miscellaneous.add_user v.username username v.password password v.profile profile

(./sawmill may need to be qualified with the version number, e.g., ./sawmill7.2.15).

That will create a new user whose username is username, whose password is password, who is a non-administrator, and who has access to one profile, called profile. The profile parameter must be the internal name of the profile, i.e., the name of the file as it appears in LogAnalysisInfo\profiles, without the .cfg extension. So, if your have a profile CFG file in LogAnalysisInfo\profiles\jennys_site.cfg, you would use "v.profile jennys_side" in the command line.

By embedding a call to this script in a larger environment, you can automatically create a username every time you add a new customer. By calling it again with the same username, you can change their password, or add access to new profiles.


Advanced Topic: Understanding The Script

You don't need to understand the script to use it, but if you want to modify it, or do some Salang scripting of your own, you'll need to know how it works, and why. This section dissects the script in detail, to explain what each piece does. This section assumes familiarity with computer programming. The Salang section of the Sawmill Technical Manual (click Help in the upper right of any Sawmill installation) provides a more technical and complete description of Salang.
1. The {= and =} tags.

The {= before the script and =} after the scripts are used in a CFV ("configuration value") file to indicate a section of Salang code. Without these tags, the entire CFV file is treated as a literal string. When {= and =} are present, the section between them is compiled and executed, and its result is inserted in the resulting string. In this case, we're not using the result string at all--we just want to have an effect when we run the script--so the entire script is embedded in {= =}.

2. Comments start with #

All lines beginning with # are comments, and are ignored by Salang. These are for documentation purposes only, and have no effect on the code.

3.  set_subnode_value('users', v.username, '');

The set_subnode_value() function in Salang sets a value within a node. A node is a general Salang data structure, which is similar to a perl hash (or, to a lesser degree, a C structure). Unlike perl hashes or C structures, however, Salang nodes can reside in memory, or on disk, or both. Referring to a node by the name 'users' indicates that it is a top-level node called 'users'; and because there is a file called "users.cfg" in LogAnalysisInfo, Sawmill automatically equates the two, and this function operates on the node whose content is described by the file users.cfg. Because that is the file which contains Sawmill User information, this line operates directly on the user information file. The contents of the file is loaded into memory automatically, when the node is referenced, and the modifications are made to the in-memory copy. The changes are not saved to disk until save_node() is called, below.

So, this operates on the "users" node, and in this case it is setting the value of a subnode. The name of the subnode is the value of v.username, which is a variable specified by the v.username command-line parameter. v.username is also a node: it is the "username" subnode of the top-level "v" node, which does not have an on-disk counterpart, so remains in memory. The "v" node is often used for temporary variables, but has no particular significance to Salang--it could have been called x.username, as long as both the command line and the script called it that.

The last parameter to set_subnode_value(), which specifies the value to assign to the subnode, is empty. So this line sets the subnode whose name is in the variable v.username to "". If the value v.username is "jenny", then a subnode "jenny" will be created in "users" (users.cfg), and set to empty. This creates a new user record, called "jenny."

By the way, this code uses single-quotes ('), but double-quotes (") and backticks (`) are all treated identically by Salang. So the script would work the same if all single quotes were double quotes, or if they were all backticks.

Assuming there were no users before this line ran, the "users" node would look like this after this line:


  users = {
    jenny = ""
  } # users


So, the user record has been created, but has no values in it yet. Note that the file users.cfg has not yet been modified, and won't be until save_node() is called, below.

4.  set_subnode_value('users.' . v.username, 'username', v.username);

This is similar to #2, above. But the first parameter uses the concatenation operator (.) to concatentate the value of the v.username variable to the literal string "users.". If the value of v.username was "jenny", the concatenation would be "users.jenny", so that is the node we are operating on. In node names (like "users.jenny"), a dot is a hierarchy divider, so "users.jenny" refers to the subnode "jenny" of the node "users". So this line sets the subnode "username" of the node "users.jenny" to the value of v.username. This adds a "username" parameter, with value "jenny", to the user record for "jenny".

The "users" node would look like this after this line:


  users = {
    jenny = {
      username = "jenny"
    } # jenny
  } # users


5.  set_subnode_value('users.' . v.username, 'password_checksum', md5_digest(v.password) );

As with #3, this sets a subnode of the user node (users.jenny). In this case, it's setting the password_checksum node. For security, the password is not stored plain-text in the users node, so it is first encoded using the built-in function md5_digest(), before being written to the password_checksum node.

The "users" node would look like this after this line:


  users = {
    jenny = {
      username = "jenny"
      password_checksum = "4ed9407630eb1000c0f6b63842defa7d"
    } # jenny
  } # users


6.  set_subnode_value('users.' . v.username, 'administrator', false);

As with #3 and #4, this sets a subnode of the user node (users.jenny). Here, it sets the "administrator" node to false, indicating that this user is not an administrator.

The "users" node would look like this after this line:


  users = {
    jenny = {
      username = "jenny"
      password_checksum = "4ed9407630eb1000c0f6b63842defa7d"
      administrator = false
    } # jenny
  } # users


7.  set_subnode_value('users.' . v.username, 'profiles', '');

As with #3, #4, and #5 this sets a subnode of the user node. Here, it creates a "profiles" subnode of the users node. This node is empty at first, but can be filled with one or more profile names, indicating which profiles the user may access.

The "users" node would look like this after this line:


  users = {
    jenny = {
      username = "jenny"
      password_checksum = "4ed9407630eb1000c0f6b63842defa7d"
      administrator = false
      profiles = ""
    } # jenny
  } # users


8.  set_subnode_value('users.' . v.username . '.profiles', v.profile, true);

This sets a subnode of the "profiles" node created in step 6. It uses the concatenation operator to concatenate "users.", the value of v.username, and ".profiles"; if v.profile is "jenny" (as above), this string is "users.jenny.profiles", which points to the "profiles" subnode of the "jenny" subnode of the "users" node (which is users.cfg in LogAnalysisInfo). This operates on the subnode specified by the value of v.profile. The v.profile value is specified on the command line, so for this example, we'll assume it is "jennys_site". This subnode does not exist, so it is created, and its value is set to true (the third parameter above).

The "users" node would look like this after this line:


  users = {
    jenny = {
      username = "jenny"
      password_checksum = "4ed9407630eb1000c0f6b63842defa7d"
      administrator = false
      profiles = {
        jennys_site = true
      } # profiles
    } # jenny
  } # users


9.  save_node('users');

This saves the node 'users' to its natural position on disk, which is the users.cfg file in LogAnalysisInfo. The content of users.cfg is replaced by the "users" node shown in the box above. After this line, the user modification is complete, and Sawmill will immediately allow logins by the new user and there is no need to restart the service.

10.  echo(node_as_string('users.' . v.username));

This displays to console (standard output) the contents of the subnode specified by v.username, in the "users" node. In the example above, it would display this to console:


  jenny = {
    username = "jenny"
    password_checksum = "4ed9407630eb1000c0f6b63842defa7d"
    administrator = false
    profiles = {
      jennys_site = true
    } # profiles
  } # jenny
 


This provides some feedback of what the script did, allowing you to verify the new or modified user record.

Conclusion

This newsletter presented a simple Salang script, which performs a useful operation. Salang is a fully general programming language, which can be used to do any type of scripting. Sawmill's entire web interface is written in Salang, as are log filters, parsing filters, and many other major components. If you are a programmer, or have a programmer available, you can use Salang to greatly extend the functionality of Sawmill, and to implement your own features in Sawmill.


[Article revision v1.2]


Professionelle Dienstleistungen

Sollten Sie die Anpassung von Sawmill Analytics nicht selbst vornehmen wollen, können wir Ihnen dies als Dienstleisung anbieten. Unsere Experten setzen sich gerne mit Ihnen in Verbindung, um die Reports oder sonstige Aspekte von Sawmill Analytics an Ihre Gegebenheiten und Wünsche anzupassen. Kontakt

Zur Tutorial-Übersicht

Weitere Informationen

      Live-Demonstrationen »    
© 1995-2011 HAAGE & PARTNER Computer GmbH · Impressum · Datenschutz · www.haage-partner.de